mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-17 03:53:29 +01:00
Merge branch 'master' into indev-prism
This commit is contained in:
@@ -1,12 +1,13 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
node_js:
|
node_js:
|
||||||
- "6"
|
- "6"
|
||||||
|
- "7"
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- node_modules
|
- node_modules
|
||||||
install: npm install
|
install: npm install
|
||||||
script:
|
script:
|
||||||
- npm run test
|
- npm run lint
|
||||||
- bash ./deploy/deploy.sh
|
- bash ./deploy/deploy.sh
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
|
|||||||
@@ -3,36 +3,40 @@
|
|||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
function build {
|
function tests {
|
||||||
# Build docs
|
npm run test-docs
|
||||||
npm run docs
|
VERSIONED=false npm run web-dist
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
# Build the webpack
|
function build {
|
||||||
|
npm run docs
|
||||||
VERSIONED=false npm run web-dist
|
VERSIONED=false npm run web-dist
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ignore Travis checking PRs
|
# Only run tests for PRs
|
||||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||||
echo "deploy.sh: Ignoring PR build"
|
echo -e "\e[36m\e[1mBuild triggered for PR #$TRAVIS_PULL_REQUEST to branch $TRAVIS_BRANCH - only running tests."
|
||||||
build
|
tests
|
||||||
exit 0
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ignore travis checking other branches irrelevant to users
|
# Figure out the source of the build
|
||||||
if [ "$TRAVIS_BRANCH" == "gh-pages" -o "$TRAVIS_BRANCH" == "gh-pages-dev" -o "$TRAVIS_BRANCH" == "docs" -o "$TRAVIS_BRANCH" == "webpack" -o "$TRAVIS_BRANCH" == "v8" ]; then
|
|
||||||
echo "deploy.sh: Ignoring push to blacklisted branch"
|
|
||||||
build
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
SOURCE=$TRAVIS_BRANCH
|
|
||||||
|
|
||||||
# Make sure tag pushes are handled
|
|
||||||
if [ -n "$TRAVIS_TAG" ]; then
|
if [ -n "$TRAVIS_TAG" ]; then
|
||||||
echo "deploy.sh: This is a tag build, proceeding accordingly"
|
echo -e "\e[36m\e[1mBuild triggered for tag \"$TRAVIS_TAG\"."
|
||||||
SOURCE=$TRAVIS_TAG
|
SOURCE=$TRAVIS_TAG
|
||||||
|
else
|
||||||
|
echo -e "\e[36m\e[1mBuild triggered for branch \"$TRAVIS_BRANCH\"."
|
||||||
|
SOURCE=$TRAVIS_BRANCH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Only run tests for Node versions other than 6
|
||||||
|
if [ "$TRAVIS_NODE_VERSION" != "6" ]; then
|
||||||
|
echo -e "\e[36m\e[1mBuild triggered with Node v$TRAVIS_NODE_VERSION - only running tests."
|
||||||
|
tests
|
||||||
|
fi
|
||||||
|
|
||||||
|
build
|
||||||
|
|
||||||
# Initialise some useful variables
|
# Initialise some useful variables
|
||||||
REPO=`git config remote.origin.url`
|
REPO=`git config remote.origin.url`
|
||||||
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
|
SSH_REPO=${REPO/https:\/\/github.com\//git@github.com:}
|
||||||
@@ -48,15 +52,11 @@ chmod 600 deploy_key
|
|||||||
eval `ssh-agent -s`
|
eval `ssh-agent -s`
|
||||||
ssh-add deploy_key
|
ssh-add deploy_key
|
||||||
|
|
||||||
# Build everything
|
|
||||||
build
|
|
||||||
|
|
||||||
# Checkout the repo in the target branch so we can build docs and push to it
|
# Checkout the repo in the target branch so we can build docs and push to it
|
||||||
TARGET_BRANCH="docs"
|
TARGET_BRANCH="docs"
|
||||||
git clone $REPO out -b $TARGET_BRANCH
|
git clone $REPO out -b $TARGET_BRANCH
|
||||||
|
|
||||||
# Move the generated JSON file to the newly-checked-out repo, to be committed
|
# Move the generated JSON file to the newly-checked-out repo, to be committed and pushed
|
||||||
# and pushed
|
|
||||||
mv docs/docs.json out/$SOURCE.json
|
mv docs/docs.json out/$SOURCE.json
|
||||||
|
|
||||||
# Commit and push
|
# Commit and push
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "eslint src && docgen --source src --custom docs/index.yml",
|
"test": "eslint src && docgen --source src --custom docs/index.yml",
|
||||||
"docs": "docgen --source src --custom docs/index.yml --output docs/docs.json",
|
"docs": "docgen --source src --custom docs/index.yml --output docs/docs.json",
|
||||||
"test-docs": "docgen --source src --custom docs",
|
"test-docs": "docgen --source src --custom docs/index.yml",
|
||||||
"lint": "eslint src",
|
"lint": "eslint src",
|
||||||
"web-dist": "node ./node_modules/parallel-webpack/bin/run.js"
|
"web-dist": "node ./node_modules/parallel-webpack/bin/run.js"
|
||||||
},
|
},
|
||||||
@@ -32,6 +32,7 @@
|
|||||||
"runkitExampleFilename": "./docs/examples/ping.js",
|
"runkitExampleFilename": "./docs/examples/ping.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^6.0.0",
|
"@types/node": "^6.0.0",
|
||||||
|
"long": "^3.2.0",
|
||||||
"pako": "^1.0.0",
|
"pako": "^1.0.0",
|
||||||
"prism-media": "hydrabolt/prism-media#master",
|
"prism-media": "hydrabolt/prism-media#master",
|
||||||
"superagent": "^3.3.0",
|
"superagent": "^3.3.0",
|
||||||
|
|||||||
@@ -123,6 +123,19 @@ class ClientDataResolver {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a ChannelResolvable to a Channel object
|
||||||
|
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||||
|
* @returns {?string}
|
||||||
|
*/
|
||||||
|
resolveChannelID(channel) {
|
||||||
|
if (channel instanceof Channel) return channel.id;
|
||||||
|
if (typeof channel === 'string') return channel;
|
||||||
|
if (channel instanceof Message) return channel.channel.id;
|
||||||
|
if (channel instanceof Guild) return channel.defaultChannel.id;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data that can be resolved to give an invite code. This can be:
|
* Data that can be resolved to give an invite code. This can be:
|
||||||
* * An invite code
|
* * An invite code
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ const Collection = require('../../util/Collection');
|
|||||||
const splitMessage = require('../../util/SplitMessage');
|
const splitMessage = require('../../util/SplitMessage');
|
||||||
const parseEmoji = require('../../util/ParseEmoji');
|
const parseEmoji = require('../../util/ParseEmoji');
|
||||||
const escapeMarkdown = require('../../util/EscapeMarkdown');
|
const escapeMarkdown = require('../../util/EscapeMarkdown');
|
||||||
|
const transformSearchOptions = require('../../util/TransformSearchOptions');
|
||||||
|
|
||||||
const User = require('../../structures/User');
|
const User = require('../../structures/User');
|
||||||
const GuildMember = require('../../structures/GuildMember');
|
const GuildMember = require('../../structures/GuildMember');
|
||||||
@@ -12,6 +13,8 @@ const Invite = require('../../structures/Invite');
|
|||||||
const Webhook = require('../../structures/Webhook');
|
const Webhook = require('../../structures/Webhook');
|
||||||
const UserProfile = require('../../structures/UserProfile');
|
const UserProfile = require('../../structures/UserProfile');
|
||||||
const ClientOAuth2Application = require('../../structures/ClientOAuth2Application');
|
const ClientOAuth2Application = require('../../structures/ClientOAuth2Application');
|
||||||
|
const Channel = require('../../structures/Channel');
|
||||||
|
const Guild = require('../../structures/Guild');
|
||||||
|
|
||||||
class RESTMethods {
|
class RESTMethods {
|
||||||
constructor(restManager) {
|
constructor(restManager) {
|
||||||
@@ -117,6 +120,30 @@ class RESTMethods {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
search(target, options) {
|
||||||
|
options = transformSearchOptions(options, this.client);
|
||||||
|
|
||||||
|
const queryString = Object.keys(options)
|
||||||
|
.filter(k => options[k])
|
||||||
|
.map(k => [k, options[k]])
|
||||||
|
.map(x => x.join('='))
|
||||||
|
.join('&');
|
||||||
|
|
||||||
|
let type;
|
||||||
|
if (target instanceof Channel) {
|
||||||
|
type = 'channel';
|
||||||
|
} else if (target instanceof Guild) {
|
||||||
|
type = 'guild';
|
||||||
|
} else {
|
||||||
|
throw new TypeError('Target must be a TextChannel, DMChannel, GroupDMChannel, or Guild.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${Constants.Endpoints[`${type}Search`](target.id)}?${queryString}`;
|
||||||
|
return this.rest.makeRequest('get', url, true).then(body =>
|
||||||
|
body.messages.map(x => x.map(m => new Message(this.client.channels.get(m.channel_id), m, this.client)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
createChannel(guild, channelName, channelType, overwrites) {
|
createChannel(guild, channelName, channelType, overwrites) {
|
||||||
if (overwrites instanceof Collection) overwrites = overwrites.array();
|
if (overwrites instanceof Collection) overwrites = overwrites.array();
|
||||||
return this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, {
|
return this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, {
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class ClientUser extends User {
|
|||||||
* .catch(console.error);
|
* .catch(console.error);
|
||||||
*/
|
*/
|
||||||
setAvatar(avatar) {
|
setAvatar(avatar) {
|
||||||
if (avatar.startsWith('data:')) {
|
if (typeof avatar === 'string' && avatar.startsWith('data:')) {
|
||||||
return this.client.rest.methods.updateCurrentUser({ avatar });
|
return this.client.rest.methods.updateCurrentUser({ avatar });
|
||||||
} else {
|
} else {
|
||||||
return this.client.resolver.resolveBuffer(avatar).then(data =>
|
return this.client.resolver.resolveBuffer(avatar).then(data =>
|
||||||
|
|||||||
@@ -703,6 +703,27 @@ class Guild {
|
|||||||
return this.client.rest.methods.setRolePositions(this.id, updatedRoles);
|
return this.client.rest.methods.setRolePositions(this.id, updatedRoles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a search
|
||||||
|
* @param {MessageSearchOptions} [options={}] Options to pass to the search
|
||||||
|
* @returns {Promise<Array<Message[]>>}
|
||||||
|
* An array containing arrays of messages. Each inner array is a search context cluster.
|
||||||
|
* The message which has triggered the result will have the `hit` property set to `true`.
|
||||||
|
* @example
|
||||||
|
* guild.search({
|
||||||
|
* content: 'discord.js',
|
||||||
|
* before: '2016-11-17'
|
||||||
|
* })
|
||||||
|
* .then(res => {
|
||||||
|
* const hit = res[0].find(m => m.hit).content;
|
||||||
|
* console.log(`I found: **${hit}**`);
|
||||||
|
* })
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
search(options) {
|
||||||
|
return this.client.rest.methods.search(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this Guild equals another Guild. It compares all properties, so for most operations
|
* Whether this Guild equals another Guild. It compares all properties, so for most operations
|
||||||
* it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
|
* it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
|
||||||
|
|||||||
@@ -172,6 +172,12 @@ class Message {
|
|||||||
* @type {?string}
|
* @type {?string}
|
||||||
*/
|
*/
|
||||||
this.webhookID = data.webhook_id || null;
|
this.webhookID = data.webhook_id || null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this message is a hit in a search
|
||||||
|
* @type {?boolean}
|
||||||
|
*/
|
||||||
|
this.hit = typeof data.hit === 'boolean' ? data.hit : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
patch(data) { // eslint-disable-line complexity
|
patch(data) { // eslint-disable-line complexity
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ class User {
|
|||||||
* @readonly
|
* @readonly
|
||||||
*/
|
*/
|
||||||
get defaultAvatarURL() {
|
get defaultAvatarURL() {
|
||||||
let defaultAvatars = Object.values(Constants.DefaultAvatars);
|
const avatars = Object.keys(Constants.DefaultAvatars);
|
||||||
let defaultAvatar = this.discriminator % defaultAvatars.length;
|
const avatar = avatars[this.discriminator % avatars.length];
|
||||||
return Constants.Endpoints.assets(`${defaultAvatars[defaultAvatar]}.png`);
|
return Constants.Endpoints.assets(`${Constants.DefaultAvatars[avatar]}.png`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ const Message = require('../Message');
|
|||||||
const MessageCollector = require('../MessageCollector');
|
const MessageCollector = require('../MessageCollector');
|
||||||
const Collection = require('../../util/Collection');
|
const Collection = require('../../util/Collection');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for classes that have text-channel-like features
|
* Interface for classes that have text-channel-like features
|
||||||
* @interface
|
* @interface
|
||||||
@@ -214,6 +213,27 @@ class TextBasedChannel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs a search
|
||||||
|
* @param {MessageSearchOptions} [options={}] Options to pass to the search
|
||||||
|
* @returns {Promise<Array<Message[]>>}
|
||||||
|
* An array containing arrays of messages. Each inner array is a search context cluster.
|
||||||
|
* The message which has triggered the result will have the `hit` property set to `true`.
|
||||||
|
* @example
|
||||||
|
* channel.search({
|
||||||
|
* content: 'discord.js',
|
||||||
|
* before: '2016-11-17'
|
||||||
|
* })
|
||||||
|
* .then(res => {
|
||||||
|
* const hit = res[0].find(m => m.hit).content;
|
||||||
|
* console.log(`I found: **${hit}**`);
|
||||||
|
* })
|
||||||
|
* .catch(console.error);
|
||||||
|
*/
|
||||||
|
search(options) {
|
||||||
|
return this.client.rest.methods.search(this, options);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a typing indicator in the channel.
|
* Starts a typing indicator in the channel.
|
||||||
* @param {number} [count] The number of times startTyping should be considered to have been called
|
* @param {number} [count] The number of times startTyping should be considered to have been called
|
||||||
@@ -361,6 +381,7 @@ exports.applyToClass = (structure, full = false) => {
|
|||||||
'_cacheMessage',
|
'_cacheMessage',
|
||||||
'fetchMessages',
|
'fetchMessages',
|
||||||
'fetchMessage',
|
'fetchMessage',
|
||||||
|
'search',
|
||||||
'bulkDelete',
|
'bulkDelete',
|
||||||
'startTyping',
|
'startTyping',
|
||||||
'stopTyping',
|
'stopTyping',
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ const Endpoints = exports.Endpoints = {
|
|||||||
guildMemberNickname: (guildID) => `${Endpoints.guildMember(guildID, '@me')}/nick`,
|
guildMemberNickname: (guildID) => `${Endpoints.guildMember(guildID, '@me')}/nick`,
|
||||||
guildChannels: (guildID) => `${Endpoints.guild(guildID)}/channels`,
|
guildChannels: (guildID) => `${Endpoints.guild(guildID)}/channels`,
|
||||||
guildEmojis: (guildID) => `${Endpoints.guild(guildID)}/emojis`,
|
guildEmojis: (guildID) => `${Endpoints.guild(guildID)}/emojis`,
|
||||||
|
guildSearch: (guildID) => `${Endpoints.guild(guildID)}/messages/search`,
|
||||||
|
|
||||||
// channels
|
// channels
|
||||||
channels: `${API}/channels`,
|
channels: `${API}/channels`,
|
||||||
@@ -132,6 +133,7 @@ const Endpoints = exports.Endpoints = {
|
|||||||
channelPermissions: (channelID) => `${Endpoints.channel(channelID)}/permissions`,
|
channelPermissions: (channelID) => `${Endpoints.channel(channelID)}/permissions`,
|
||||||
channelMessage: (channelID, messageID) => `${Endpoints.channelMessages(channelID)}/${messageID}`,
|
channelMessage: (channelID, messageID) => `${Endpoints.channelMessages(channelID)}/${messageID}`,
|
||||||
channelWebhooks: (channelID) => `${Endpoints.channel(channelID)}/webhooks`,
|
channelWebhooks: (channelID) => `${Endpoints.channel(channelID)}/webhooks`,
|
||||||
|
channelSearch: (channelID) => `${Endpoints.channelMessages(channelID)}/search`,
|
||||||
|
|
||||||
// message reactions
|
// message reactions
|
||||||
messageReactions: (channelID, messageID) => `${Endpoints.channelMessage(channelID, messageID)}/reactions`,
|
messageReactions: (channelID, messageID) => `${Endpoints.channelMessage(channelID, messageID)}/reactions`,
|
||||||
|
|||||||
75
src/util/TransformSearchOptions.js
Normal file
75
src/util/TransformSearchOptions.js
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
const long = require('long');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} MessageSearchOptions
|
||||||
|
* @property {string} [content] Message content
|
||||||
|
* @property {string} [maxID] Maximum ID for the filter
|
||||||
|
* @property {string} [minID] Minimum ID for the filter
|
||||||
|
* @property {string} [has] One of `link`, `embed`, `file`, `video`, `image`, or `sound`,
|
||||||
|
* or add `-` to negate (e.g. `-file`)
|
||||||
|
* @property {ChannelResolvable} [channel] Channel to limit search to (only for guild search endpoint)
|
||||||
|
* @property {UserResolvable} [author] Author to limit search
|
||||||
|
* @property {string} [authorType] One of `user`, `bot`, `webhook`, or add `-` to negate (e.g. `-webhook`)
|
||||||
|
* @property {string} [sortBy='recent'] `recent` or `relevant`
|
||||||
|
* @property {string} [sortOrder='desc'] `asc` or `desc`
|
||||||
|
* @property {number} [contextSize=2] How many messages to get around the matched message (0 to 2)
|
||||||
|
* @property {number} [limit=25] Maximum number of results to get (1 to 25)
|
||||||
|
* @property {number} [offset=0] Offset the "pages" of results (since you can only see 25 at a time)
|
||||||
|
* @property {UserResolvable} [mentions] Mentioned user filter
|
||||||
|
* @property {boolean} [mentionsEveryone] If everyone is mentioned
|
||||||
|
* @property {string} [linkHostname] Filter links by hostname
|
||||||
|
* @property {string} [embedProvider] The name of an embed provider
|
||||||
|
* @property {string} [embedType] one of `image`, `video`, `url`, `rich`
|
||||||
|
* @property {string} [attachmentFilename] The name of an attachment
|
||||||
|
* @property {string} [attachmentExtention] The extension of an attachment
|
||||||
|
* @property {Date} [before] Date to find messages before
|
||||||
|
* @property {Date} [after] Date to find messages before
|
||||||
|
* @property {Date} [during] Date to find messages during (range of date to date + 24 hours)
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = function TransformSearchOptions(options, client) {
|
||||||
|
if (options.before) {
|
||||||
|
if (!(options.before instanceof Date)) options.before = new Date(options.before);
|
||||||
|
options.maxID = long.fromNumber(options.before.getTime() - 14200704e5).shiftLeft(22).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.after) {
|
||||||
|
if (!(options.after instanceof Date)) options.after = new Date(options.after);
|
||||||
|
options.minID = long.fromNumber(options.after.getTime() - 14200704e5).shiftLeft(22).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.during) {
|
||||||
|
if (!(options.during instanceof Date)) options.during = new Date(options.during);
|
||||||
|
const t = options.during.getTime() - 14200704e5;
|
||||||
|
options.minID = long.fromNumber(t).shiftLeft(22).toString();
|
||||||
|
options.maxID = long.fromNumber(t + 86400000).shift(222).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.channel) options.channel = client.resolver.resolveChannelID(options.channel);
|
||||||
|
|
||||||
|
if (options.author) options.author = client.resolver.resolveUserID(options.author);
|
||||||
|
|
||||||
|
if (options.mentions) options.mentions = client.resolver.resolveUserID(options.options.mentions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
content: options.content,
|
||||||
|
max_id: options.maxID,
|
||||||
|
min_id: options.minID,
|
||||||
|
has: options.has,
|
||||||
|
channel_id: options.channel,
|
||||||
|
author_id: options.author,
|
||||||
|
author_type: options.authorType,
|
||||||
|
context_size: options.contextSize,
|
||||||
|
sort_by: options.sortBy,
|
||||||
|
sort_order: options.sortOrder,
|
||||||
|
limit: options.limit,
|
||||||
|
offset: options.offset,
|
||||||
|
mentions: options.mentions,
|
||||||
|
mentions_everyone: options.mentionsEveryone,
|
||||||
|
link_hostname: options.linkHostname,
|
||||||
|
embed_provider: options.embedProvider,
|
||||||
|
embed_type: options.embedType,
|
||||||
|
attachment_filename: options.attachmentFilename,
|
||||||
|
attachment_extension: options.attachmentExtension,
|
||||||
|
};
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user