/******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ // Flag the module as loaded /******/ module.l = true; /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ // identity function for calling harmory imports with the correct context /******/ __webpack_require__.i = function(value) { return value; }; /******/ // define getter function for harmory exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ }; /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = 138); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process) {exports.Package = __webpack_require__(25); /** * Options for a Client. * @typedef {Object} ClientOptions * @property {string} [apiRequestMethod='sequential'] 'sequential' or 'burst'. Sequential executes all requests in * the order they are triggered, whereas burst runs multiple at a time, and doesn't guarantee a particular order. * @property {number} [shardId=0] The ID of this shard * @property {number} [shardCount=0] The number of shards * @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel * (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb * indefinitely) * @property {number} [messageCacheLifetime=0] How long until a message should be uncached by the message sweeping * (in seconds, 0 for forever) * @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than * the message cache lifetime (in seconds, 0 for never) * @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as * upon joining a guild * @property {boolean} [disableEveryone=false] Default value for MessageOptions.disableEveryone * @property {boolean} [sync=false] Whether to periodically sync guilds (for userbots) * @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their * corresponding websocket events * @property {string[]} [disabledEvents] An array of disabled websocket events. Events in this array will not be * processed. Disabling useless events such as 'TYPING_START' can result in significant performance increases on * large-scale bots. * @property {WebsocketOptions} [ws] Options for the websocket */ exports.DefaultOptions = { apiRequestMethod: 'sequential', shardId: 0, shardCount: 0, messageCacheMaxSize: 200, messageCacheLifetime: 0, messageSweepInterval: 0, fetchAllMembers: false, disableEveryone: false, sync: false, restWsBridgeTimeout: 5000, disabledEvents: [], /** * Websocket options. These are left as snake_case to match the API. * @typedef {Object} WebsocketOptions * @property {number} [large_threshold=250] Number of members in a guild to be considered large * @property {boolean} [compress=true] Whether to compress data sent on the connection. * Defaults to `false` for browsers. */ ws: { large_threshold: 250, compress: typeof window === 'undefined', properties: { $os: process ? process.platform : 'discord.js', $browser: 'discord.js', $device: 'discord.js', $referrer: '', $referring_domain: '', }, }, }; exports.Errors = { NO_TOKEN: 'Request to use token, but token was unavailable to the client.', NO_BOT_ACCOUNT: 'Only bot accounts are able to make use of this feature.', NO_USER_ACCOUNT: 'Only user accounts are able to make use of this feature.', BAD_WS_MESSAGE: 'A bad message was received from the websocket; either bad compression, or not JSON.', TOOK_TOO_LONG: 'Something took too long to do.', NOT_A_PERMISSION: 'Invalid permission string or number.', INVALID_RATE_LIMIT_METHOD: 'Unknown rate limiting method.', BAD_LOGIN: 'Incorrect login details were provided.', INVALID_SHARD: 'Invalid shard settings were provided.', }; const PROTOCOL_VERSION = exports.PROTOCOL_VERSION = 6; const API = exports.API = `https://discordapp.com/api/v${PROTOCOL_VERSION}`; const Endpoints = exports.Endpoints = { // general login: `${API}/auth/login`, logout: `${API}/auth/logout`, gateway: `${API}/gateway`, botGateway: `${API}/gateway/bot`, invite: (id) => `${API}/invite/${id}`, inviteLink: (id) => `https://discord.gg/${id}`, CDN: 'https://cdn.discordapp.com', // users user: (userID) => `${API}/users/${userID}`, userChannels: (userID) => `${Endpoints.user(userID)}/channels`, userProfile: (userID) => `${Endpoints.user(userID)}/profile`, avatar: (userID, avatar) => userID === '1' ? avatar : `${Endpoints.user(userID)}/avatars/${avatar}.jpg`, me: `${API}/users/@me`, meGuild: (guildID) => `${Endpoints.me}/guilds/${guildID}`, relationships: (userID) => `${Endpoints.user(userID)}/relationships`, note: (userID) => `${Endpoints.me}/notes/${userID}`, // guilds guilds: `${API}/guilds`, guild: (guildID) => `${Endpoints.guilds}/${guildID}`, guildIcon: (guildID, hash) => `${Endpoints.guild(guildID)}/icons/${hash}.jpg`, guildPrune: (guildID) => `${Endpoints.guild(guildID)}/prune`, guildEmbed: (guildID) => `${Endpoints.guild(guildID)}/embed`, guildInvites: (guildID) => `${Endpoints.guild(guildID)}/invites`, guildRoles: (guildID) => `${Endpoints.guild(guildID)}/roles`, guildRole: (guildID, roleID) => `${Endpoints.guildRoles(guildID)}/${roleID}`, guildBans: (guildID) => `${Endpoints.guild(guildID)}/bans`, guildIntegrations: (guildID) => `${Endpoints.guild(guildID)}/integrations`, guildMembers: (guildID) => `${Endpoints.guild(guildID)}/members`, guildMember: (guildID, memberID) => `${Endpoints.guildMembers(guildID)}/${memberID}`, stupidInconsistentGuildEndpoint: (guildID) => `${Endpoints.guildMember(guildID, '@me')}/nick`, guildChannels: (guildID) => `${Endpoints.guild(guildID)}/channels`, guildEmojis: (guildID) => `${Endpoints.guild(guildID)}/emojis`, // channels channels: `${API}/channels`, channel: (channelID) => `${Endpoints.channels}/${channelID}`, channelMessages: (channelID) => `${Endpoints.channel(channelID)}/messages`, channelInvites: (channelID) => `${Endpoints.channel(channelID)}/invites`, channelTyping: (channelID) => `${Endpoints.channel(channelID)}/typing`, channelPermissions: (channelID) => `${Endpoints.channel(channelID)}/permissions`, channelMessage: (channelID, messageID) => `${Endpoints.channelMessages(channelID)}/${messageID}`, channelWebhooks: (channelID) => `${Endpoints.channel(channelID)}/webhooks`, // message reactions messageReactions: (channelID, messageID) => `${Endpoints.channelMessage(channelID, messageID)}/reactions`, messageReaction: (channel, msg, emoji, limit) => `${Endpoints.messageReactions(channel, msg)}/${emoji}` + `${limit ? `?limit=${limit}` : ''}`, selfMessageReaction: (channel, msg, emoji, limit) => `${Endpoints.messageReaction(channel, msg, emoji, limit)}/@me`, userMessageReaction: (channel, msg, emoji, limit, id) => `${Endpoints.messageReaction(channel, msg, emoji, limit)}/${id}`, // webhooks webhook: (webhookID, token) => `${API}/webhooks/${webhookID}${token ? `/${token}` : ''}`, // oauth myApplication: `${API}/oauth2/applications/@me`, getApp: (id) => `${API}/oauth2/authorize?client_id=${id}`, }; exports.Status = { READY: 0, CONNECTING: 1, RECONNECTING: 2, IDLE: 3, NEARLY: 4, }; exports.ChannelTypes = { text: 0, DM: 1, voice: 2, groupDM: 3, }; exports.OPCodes = { DISPATCH: 0, HEARTBEAT: 1, IDENTIFY: 2, STATUS_UPDATE: 3, VOICE_STATE_UPDATE: 4, VOICE_GUILD_PING: 5, RESUME: 6, RECONNECT: 7, REQUEST_GUILD_MEMBERS: 8, INVALID_SESSION: 9, HELLO: 10, HEARTBEAT_ACK: 11, }; exports.VoiceOPCodes = { IDENTIFY: 0, SELECT_PROTOCOL: 1, READY: 2, HEARTBEAT: 3, SESSION_DESCRIPTION: 4, SPEAKING: 5, }; exports.Events = { READY: 'ready', GUILD_CREATE: 'guildCreate', GUILD_DELETE: 'guildDelete', GUILD_UPDATE: 'guildUpdate', GUILD_UNAVAILABLE: 'guildUnavailable', GUILD_AVAILABLE: 'guildAvailable', GUILD_MEMBER_ADD: 'guildMemberAdd', GUILD_MEMBER_REMOVE: 'guildMemberRemove', GUILD_MEMBER_UPDATE: 'guildMemberUpdate', GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable', GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking', GUILD_MEMBERS_CHUNK: 'guildMembersChunk', GUILD_ROLE_CREATE: 'roleCreate', GUILD_ROLE_DELETE: 'roleDelete', GUILD_ROLE_UPDATE: 'roleUpdate', GUILD_EMOJI_CREATE: 'guildEmojiCreate', GUILD_EMOJI_DELETE: 'guildEmojiDelete', GUILD_EMOJI_UPDATE: 'guildEmojiUpdate', GUILD_BAN_ADD: 'guildBanAdd', GUILD_BAN_REMOVE: 'guildBanRemove', CHANNEL_CREATE: 'channelCreate', CHANNEL_DELETE: 'channelDelete', CHANNEL_UPDATE: 'channelUpdate', CHANNEL_PINS_UPDATE: 'channelPinsUpdate', MESSAGE_CREATE: 'message', MESSAGE_DELETE: 'messageDelete', MESSAGE_UPDATE: 'messageUpdate', MESSAGE_BULK_DELETE: 'messageDeleteBulk', MESSAGE_REACTION_ADD: 'messageReactionAdd', MESSAGE_REACTION_REMOVE: 'messageReactionRemove', MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll', USER_UPDATE: 'userUpdate', USER_NOTE_UPDATE: 'userNoteUpdate', PRESENCE_UPDATE: 'presenceUpdate', VOICE_STATE_UPDATE: 'voiceStateUpdate', TYPING_START: 'typingStart', TYPING_STOP: 'typingStop', DISCONNECT: 'disconnect', RECONNECTING: 'reconnecting', ERROR: 'error', WARN: 'warn', DEBUG: 'debug', }; exports.WSEvents = { READY: 'READY', GUILD_SYNC: 'GUILD_SYNC', GUILD_CREATE: 'GUILD_CREATE', GUILD_DELETE: 'GUILD_DELETE', GUILD_UPDATE: 'GUILD_UPDATE', GUILD_MEMBER_ADD: 'GUILD_MEMBER_ADD', GUILD_MEMBER_REMOVE: 'GUILD_MEMBER_REMOVE', GUILD_MEMBER_UPDATE: 'GUILD_MEMBER_UPDATE', GUILD_MEMBERS_CHUNK: 'GUILD_MEMBERS_CHUNK', GUILD_ROLE_CREATE: 'GUILD_ROLE_CREATE', GUILD_ROLE_DELETE: 'GUILD_ROLE_DELETE', GUILD_ROLE_UPDATE: 'GUILD_ROLE_UPDATE', GUILD_BAN_ADD: 'GUILD_BAN_ADD', GUILD_BAN_REMOVE: 'GUILD_BAN_REMOVE', CHANNEL_CREATE: 'CHANNEL_CREATE', CHANNEL_DELETE: 'CHANNEL_DELETE', CHANNEL_UPDATE: 'CHANNEL_UPDATE', CHANNEL_PINS_UPDATE: 'CHANNEL_PINS_UPDATE', MESSAGE_CREATE: 'MESSAGE_CREATE', MESSAGE_DELETE: 'MESSAGE_DELETE', MESSAGE_UPDATE: 'MESSAGE_UPDATE', MESSAGE_DELETE_BULK: 'MESSAGE_DELETE_BULK', MESSAGE_REACTION_ADD: 'MESSAGE_REACTION_ADD', MESSAGE_REACTION_REMOVE: 'MESSAGE_REACTION_REMOVE', MESSAGE_REACTION_REMOVE_ALL: 'MESSAGE_REACTION_REMOVE_ALL', USER_UPDATE: 'USER_UPDATE', USER_NOTE_UPDATE: 'USER_NOTE_UPDATE', PRESENCE_UPDATE: 'PRESENCE_UPDATE', VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE', TYPING_START: 'TYPING_START', FRIEND_ADD: 'RELATIONSHIP_ADD', FRIEND_REMOVE: 'RELATIONSHIP_REMOVE', VOICE_SERVER_UPDATE: 'VOICE_SERVER_UPDATE', RELATIONSHIP_ADD: 'RELATIONSHIP_ADD', RELATIONSHIP_REMOVE: 'RELATIONSHIP_REMOVE', }; exports.MessageTypes = { 0: 'DEFAULT', 1: 'RECIPIENT_ADD', 2: 'RECIPIENT_REMOVE', 3: 'CALL', 4: 'CHANNEL_NAME_CHANGE', 5: 'CHANNEL_ICON_CHANGE', 6: 'PINS_ADD', }; const PermissionFlags = exports.PermissionFlags = { CREATE_INSTANT_INVITE: 1 << 0, KICK_MEMBERS: 1 << 1, BAN_MEMBERS: 1 << 2, ADMINISTRATOR: 1 << 3, MANAGE_CHANNELS: 1 << 4, MANAGE_GUILD: 1 << 5, ADD_REACTIONS: 1 << 6, READ_MESSAGES: 1 << 10, SEND_MESSAGES: 1 << 11, SEND_TTS_MESSAGES: 1 << 12, MANAGE_MESSAGES: 1 << 13, EMBED_LINKS: 1 << 14, ATTACH_FILES: 1 << 15, READ_MESSAGE_HISTORY: 1 << 16, MENTION_EVERYONE: 1 << 17, EXTERNAL_EMOJIS: 1 << 18, CONNECT: 1 << 20, SPEAK: 1 << 21, MUTE_MEMBERS: 1 << 22, DEAFEN_MEMBERS: 1 << 23, MOVE_MEMBERS: 1 << 24, USE_VAD: 1 << 25, CHANGE_NICKNAME: 1 << 26, MANAGE_NICKNAMES: 1 << 27, MANAGE_ROLES_OR_PERMISSIONS: 1 << 28, MANAGE_WEBHOOKS: 1 << 29, MANAGE_EMOJIS: 1 << 30, }; let _ALL_PERMISSIONS = 0; for (const key in PermissionFlags) _ALL_PERMISSIONS |= PermissionFlags[key]; exports.ALL_PERMISSIONS = _ALL_PERMISSIONS; exports.DEFAULT_PERMISSIONS = 104324097; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(16))) /***/ }, /* 1 */ /***/ function(module, exports) { class AbstractHandler { constructor(packetManager) { this.packetManager = packetManager; } handle(packet) { return packet; } } module.exports = AbstractHandler; /***/ }, /* 2 */ /***/ function(module, exports) { /* ABOUT ACTIONS Actions are similar to WebSocket Packet Handlers, but since introducing the REST API methods, in order to prevent rewriting code to handle data, "actions" have been introduced. They're basically what Packet Handlers used to be but they're strictly for manipulating data and making sure that WebSocket events don't clash with REST methods. */ class GenericAction { constructor(client) { this.client = client; } handle(data) { return data; } } module.exports = GenericAction; /***/ }, /* 3 */ /***/ function(module, exports) { /** * A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has * an ID, for significantly improved performance and ease-of-use. * @extends {Map} */ class Collection extends Map { constructor(iterable) { super(iterable); /** * Cached array for the `array()` method - will be reset to `null` whenever `set()` or `delete()` are called. * @type {?Array} * @private */ this._array = null; /** * Cached array for the `keyArray()` method - will be reset to `null` whenever `set()` or `delete()` are called. * @type {?Array} * @private */ this._keyArray = null; } set(key, val) { super.set(key, val); this._array = null; this._keyArray = null; } delete(key) { super.delete(key); this._array = null; this._keyArray = null; } /** * Creates an ordered array of the values of this collection, and caches it internally. The array will only be * reconstructed if an item is added to or removed from the collection, or if you change the length of the array * itself. If you don't want this caching behaviour, use `Array.from(collection.values())` instead. * @returns {Array} */ array() { if (!this._array || this._array.length !== this.size) this._array = Array.from(this.values()); return this._array; } /** * Creates an ordered array of the keys of this collection, and caches it internally. The array will only be * reconstructed if an item is added to or removed from the collection, or if you change the length of the array * itself. If you don't want this caching behaviour, use `Array.from(collection.keys())` instead. * @returns {Array} */ keyArray() { if (!this._keyArray || this._keyArray.length !== this.size) this._keyArray = Array.from(this.keys()); return this._keyArray; } /** * Obtains the first item in this collection. * @returns {*} */ first() { return this.values().next().value; } /** * Obtains the first key in this collection. * @returns {*} */ firstKey() { return this.keys().next().value; } /** * Obtains the last item in this collection. This relies on the `array()` method, and thus the caching mechanism * applies here as well. * @returns {*} */ last() { const arr = this.array(); return arr[arr.length - 1]; } /** * Obtains the last key in this collection. This relies on the `keyArray()` method, and thus the caching mechanism * applies here as well. * @returns {*} */ lastKey() { const arr = this.keyArray(); return arr[arr.length - 1]; } /** * Obtains a random item from this collection. This relies on the `array()` method, and thus the caching mechanism * applies here as well. * @returns {*} */ random() { const arr = this.array(); return arr[Math.floor(Math.random() * arr.length)]; } /** * Obtains a random key from this collection. This relies on the `keyArray()` method, and thus the caching mechanism * applies here as well. * @returns {*} */ randomKey() { const arr = this.keyArray(); return arr[Math.floor(Math.random() * arr.length)]; } /** * Searches for all items where their specified property's value is identical to the given value * (`item[prop] === value`). * @param {string} prop The property to test against * @param {*} value The expected value * @returns {Array} * @example * collection.findAll('username', 'Bob'); */ findAll(prop, value) { if (typeof prop !== 'string') throw new TypeError('Key must be a string.'); if (typeof value === 'undefined') throw new Error('Value must be specified.'); const results = []; for (const item of this.values()) { if (item[prop] === value) results.push(item); } return results; } /** * Searches for a single item where its specified property's value is identical to the given value * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to * [Array.find()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find). * Do not use this to obtain an item by its ID. Instead, use `collection.get(id)`. See * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get) for details. * @param {string|Function} propOrFn The property to test against, or the function to test with * @param {*} [value] The expected value - only applicable and required if using a property for the first argument * @returns {*} * @example * collection.find('username', 'Bob'); * @example * collection.find(val => val.username === 'Bob'); */ find(propOrFn, value) { if (typeof propOrFn === 'string') { if (typeof value === 'undefined') throw new Error('Value must be specified.'); if (propOrFn === 'id') throw new RangeError('Don\'t use .find() with IDs. Instead, use .get(id).'); for (const item of this.values()) { if (item[propOrFn] === value) return item; } return null; } else if (typeof propOrFn === 'function') { for (const [key, val] of this) { if (propOrFn(val, key, this)) return val; } return null; } else { throw new Error('First argument must be a property string or a function.'); } } /* eslint-disable max-len */ /** * Searches for the key of a single item where its specified property's value is identical to the given value * (`item[prop] === value`), or the given function returns a truthy value. In the latter case, this is identical to * [Array.findIndex()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex). * @param {string|Function} propOrFn The property to test against, or the function to test with * @param {*} [value] The expected value - only applicable and required if using a property for the first argument * @returns {*} * @example * collection.findKey('username', 'Bob'); * @example * collection.findKey(val => val.username === 'Bob'); */ /* eslint-enable max-len */ findKey(propOrFn, value) { if (typeof propOrFn === 'string') { if (typeof value === 'undefined') throw new Error('Value must be specified.'); for (const [key, val] of this) { if (val[propOrFn] === value) return key; } return null; } else if (typeof propOrFn === 'function') { for (const [key, val] of this) { if (propOrFn(val, key, this)) return key; } return null; } else { throw new Error('First argument must be a property string or a function.'); } } /** * Searches for the existence of a single item where its specified property's value is identical to the given value * (`item[prop] === value`). * Do not use this to check for an item by its ID. Instead, use `collection.has(id)`. See * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has) for details. * @param {string} prop The property to test against * @param {*} value The expected value * @returns {boolean} * @example * if (collection.exists('username', 'Bob')) { * console.log('user here!'); * } */ exists(prop, value) { if (prop === 'id') throw new RangeError('Don\'t use .exists() with IDs. Instead, use .has(id).'); return Boolean(this.find(prop, value)); } /** * Identical to * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter), * but returns a Collection instead of an Array. * @param {Function} fn Function used to test (should return a boolean) * @param {Object} [thisArg] Value to use as `this` when executing function * @returns {Collection} */ filter(fn, thisArg) { if (thisArg) fn = fn.bind(thisArg); const results = new Collection(); for (const [key, val] of this) { if (fn(val, key, this)) results.set(key, val); } return results; } /** * Identical to * [Array.filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter). * @param {Function} fn Function used to test (should return a boolean) * @param {Object} [thisArg] Value to use as `this` when executing function * @returns {Array} */ filterArray(fn, thisArg) { if (thisArg) fn = fn.bind(thisArg); const results = []; for (const [key, val] of this) { if (fn(val, key, this)) results.push(val); } return results; } /** * Identical to * [Array.map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map). * @param {Function} fn Function that produces an element of the new array, taking three arguments * @param {*} [thisArg] Value to use as `this` when executing function * @returns {Array} */ map(fn, thisArg) { if (thisArg) fn = fn.bind(thisArg); const arr = new Array(this.size); let i = 0; for (const [key, val] of this) arr[i++] = fn(val, key, this); return arr; } /** * Identical to * [Array.some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some). * @param {Function} fn Function used to test (should return a boolean) * @param {Object} [thisArg] Value to use as `this` when executing function * @returns {boolean} */ some(fn, thisArg) { if (thisArg) fn = fn.bind(thisArg); for (const [key, val] of this) { if (fn(val, key, this)) return true; } return false; } /** * Identical to * [Array.every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every). * @param {Function} fn Function used to test (should return a boolean) * @param {Object} [thisArg] Value to use as `this` when executing function * @returns {boolean} */ every(fn, thisArg) { if (thisArg) fn = fn.bind(thisArg); for (const [key, val] of this) { if (!fn(val, key, this)) return false; } return true; } /** * Identical to * [Array.reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce). * @param {Function} fn Function used to reduce * @param {*} [startVal] The starting value * @returns {*} */ reduce(fn, startVal) { let currentVal = startVal; for (const [key, val] of this) currentVal = fn(currentVal, val, key, this); return currentVal; } /** * Combines this collection with others into a new collection. None of the source collections are modified. * @param {Collection} collections Collections to merge (infinite/rest argument, not an array) * @returns {Collection} * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); */ concat(...collections) { const newColl = new this.constructor(); for (const [key, val] of this) newColl.set(key, val); for (const coll of collections) { for (const [key, val] of coll) newColl.set(key, val); } return newColl; } /** * Calls the `delete()` method on all items that have it. * @returns {Promise[]} */ deleteAll() { const returns = []; for (const item of this.values()) { if (item.delete) returns.push(item.delete()); } return returns; } } module.exports = Collection; /***/ }, /* 4 */ /***/ function(module, exports) { module.exports = function cloneObject(obj) { const cloned = Object.create(obj); Object.assign(cloned, obj); return cloned; }; /***/ }, /* 5 */ /***/ function(module, exports, __webpack_require__) { const TextBasedChannel = __webpack_require__(10); const Constants = __webpack_require__(0); const Presence = __webpack_require__(6).Presence; /** * Represents a user on Discord. * @implements {TextBasedChannel} */ class User { constructor(client, data) { /** * The Client that created the instance of the the User. * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); if (data) this.setup(data); } setup(data) { /** * The ID of the user * @type {string} */ this.id = data.id; /** * The username of the user * @type {string} */ this.username = data.username; /** * A discriminator based on username for the user * @type {string} */ this.discriminator = data.discriminator; /** * The ID of the user's avatar * @type {string} */ this.avatar = data.avatar; /** * Whether or not the user is a bot. * @type {boolean} */ this.bot = Boolean(data.bot); } patch(data) { for (const prop of ['id', 'username', 'discriminator', 'avatar', 'bot']) { if (typeof data[prop] !== 'undefined') this[prop] = data[prop]; } } /** * The timestamp the user was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the user was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * The presence of this user * @type {Presence} * @readonly */ get presence() { if (this.client.presences.has(this.id)) return this.client.presences.get(this.id); for (const guild of this.client.guilds.values()) { if (guild.presences.has(this.id)) return guild.presences.get(this.id); } return new Presence(); } /** * A link to the user's avatar (if they have one, otherwise null) * @type {?string} * @readonly */ get avatarURL() { if (!this.avatar) return null; return Constants.Endpoints.avatar(this.id, this.avatar); } /** * The note that is set for the user * This is only available when using a user account. * @type {?string} * @readonly */ get note() { return this.client.user.notes.get(this.id) || null; } /** * Check whether the user is typing in a channel. * @param {ChannelResolvable} channel The channel to check in * @returns {boolean} */ typingIn(channel) { channel = this.client.resolver.resolveChannel(channel); return channel._typing.has(this.id); } /** * Get the time that the user started typing. * @param {ChannelResolvable} channel The channel to get the time in * @returns {?Date} */ typingSinceIn(channel) { channel = this.client.resolver.resolveChannel(channel); return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null; } /** * Get the amount of time the user has been typing in a channel for (in milliseconds), or -1 if they're not typing. * @param {ChannelResolvable} channel The channel to get the time in * @returns {number} */ typingDurationIn(channel) { channel = this.client.resolver.resolveChannel(channel); return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1; } /** * Deletes a DM channel (if one exists) between the client and the user. Resolves with the channel if successful. * @returns {Promise} */ deleteDM() { return this.client.rest.methods.deleteChannel(this); } /** * Sends a friend request to the user * This is only available when using a user account. * @returns {Promise} */ addFriend() { return this.client.rest.methods.addFriend(this); } /** * Removes the user from your friends * This is only available when using a user account. * @returns {Promise} */ removeFriend() { return this.client.rest.methods.removeFriend(this); } /** * Blocks the user * This is only available when using a user account. * @returns {Promise} */ block() { return this.client.rest.methods.blockUser(this); } /** * Unblocks the user * This is only available when using a user account. * @returns {Promise} */ unblock() { return this.client.rest.methods.unblockUser(this); } /** * Get the profile of the user * This is only available when using a user account. * @returns {Promise} */ fetchProfile() { return this.client.rest.methods.fetchUserProfile(this); } /** * Sets a note for the user * This is only available when using a user account. * @param {string} note The note to set for the user * @returns {Promise} */ setNote(note) { return this.client.rest.methods.setNote(this, note); } /** * Checks if the user is equal to another. It compares username, ID, discriminator, status and the game being played. * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. * @param {User} user The user to compare * @returns {boolean} */ equals(user) { let equal = user && this.id === user.id && this.username === user.username && this.discriminator === user.discriminator && this.avatar === user.avatar && this.bot === Boolean(user.bot); return equal; } /** * When concatenated with a string, this automatically concatenates the user's mention instead of the User object. * @returns {string} * @example * // logs: Hello from <@123456789>! * console.log(`Hello from ${user}!`); */ toString() { return `<@${this.id}>`; } // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } sendFile() { return; } sendCode() { return; } } TextBasedChannel.applyToClass(User); module.exports = User; /***/ }, /* 6 */ /***/ function(module, exports) { /** * Represents a user's presence */ class Presence { constructor(data = {}) { /** * The status of the presence: * * * **`online`** - user is online * * **`offline`** - user is offline or invisible * * **`idle`** - user is AFK * * **`dnd`** - user is in Do not Disturb * @type {string} */ this.status = data.status || 'offline'; /** * The game that the user is playing, `null` if they aren't playing a game. * @type {?Game} */ this.game = data.game ? new Game(data.game) : null; } update(data) { this.status = data.status || this.status; this.game = data.game ? new Game(data.game) : null; } /** * Whether this presence is equal to another * @param {Presence} other the presence to compare * @returns {boolean} */ equals(other) { return ( other && this.status === other.status && this.game ? this.game.equals(other.game) : !other.game ); } } /** * Represents a game that is part of a user's presence. */ class Game { constructor(data) { /** * The name of the game being played * @type {string} */ this.name = data.name; /** * The type of the game status * @type {number} */ this.type = data.type; /** * If the game is being streamed, a link to the stream * @type {?string} */ this.url = data.url || null; } /** * Whether or not the game is being streamed * @type {boolean} * @readonly */ get streaming() { return this.type === 1; } /** * Whether this game is equal to another game * @param {Game} other the other game to compare * @returns {boolean} */ equals(other) { return ( other && this.name === other.name && this.type === other.type && this.url === other.url ); } } exports.Presence = Presence; exports.Game = Game; /***/ }, /* 7 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); /** * Represents a role on Discord */ class Role { constructor(guild, data) { /** * The client that instantiated the role * @type {Client} */ this.client = guild.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The guild that the role belongs to * @type {Guild} */ this.guild = guild; if (data) this.setup(data); } setup(data) { /** * The ID of the role (unique to the guild it is part of) * @type {string} */ this.id = data.id; /** * The name of the role * @type {string} */ this.name = data.name; /** * The base 10 color of the role * @type {number} */ this.color = data.color; /** * If true, users that are part of this role will appear in a separate category in the users list * @type {boolean} */ this.hoist = data.hoist; /** * The position of the role in the role manager * @type {number} */ this.position = data.position; /** * The evaluated permissions number * @type {number} */ this.permissions = data.permissions; /** * Whether or not the role is managed by an external service * @type {boolean} */ this.managed = data.managed; /** * Whether or not the role can be mentioned by anyone * @type {boolean} */ this.mentionable = data.mentionable; } /** * The timestamp the role was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the role was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * The hexadecimal version of the role color, with a leading hashtag. * @type {string} * @readonly */ get hexColor() { let col = this.color.toString(16); while (col.length < 6) col = `0${col}`; return `#${col}`; } /** * The cached guild members that have this role. * @type {Collection} * @readonly */ get members() { return this.guild.members.filter(m => m.roles.has(this.id)); } /** * Get an object mapping permission names to whether or not the role enables that permission * @returns {Object} * @example * // print the serialized role * console.log(role.serialize()); */ serialize() { const serializedPermissions = {}; for (const permissionName in Constants.PermissionFlags) { serializedPermissions[permissionName] = this.hasPermission(permissionName); } return serializedPermissions; } /** * Checks if the role has a permission. * @param {PermissionResolvable} permission The permission to check for * @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permission * @returns {boolean} * @example * // see if a role can ban a member * if (role.hasPermission('BAN_MEMBERS')) { * console.log('This role can ban members'); * } else { * console.log('This role can\'t ban members'); * } */ hasPermission(permission, explicit = false) { permission = this.client.resolver.resolvePermission(permission); if (!explicit && (this.permissions & Constants.PermissionFlags.ADMINISTRATOR) > 0) return true; return (this.permissions & permission) > 0; } /** * Checks if the role has all specified permissions. * @param {PermissionResolvable[]} permissions The permissions to check for * @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permissions * @returns {boolean} */ hasPermissions(permissions, explicit = false) { return permissions.every(p => this.hasPermission(p, explicit)); } /** * Compares this role's position to another role's. * @param {Role} role Role to compare to this one * @returns {number} Negative number if the this role's position is lower (other role's is higher), * positive number if the this one is higher (other's is lower), 0 if equal */ comparePositionTo(role) { return this.constructor.comparePositions(this, role); } /** * The data for a role * @typedef {Object} RoleData * @property {string} [name] The name of the role * @property {number|string} [color] The color of the role, either a hex string or a base 10 number * @property {boolean} [hoist] Whether or not the role should be hoisted * @property {number} [position] The position of the role * @property {string[]} [permissions] The permissions of the role * @property {boolean} [mentionable] Whether or not the role should be mentionable */ /** * Edits the role * @param {RoleData} data The new data for the role * @returns {Promise} * @example * // edit a role * role.edit({name: 'new role'}) * .then(r => console.log(`Edited role ${r}`)) * .catch(console.error); */ edit(data) { return this.client.rest.methods.updateGuildRole(this, data); } /** * Set a new name for the role * @param {string} name The new name of the role * @returns {Promise} * @example * // set the name of the role * role.setName('new role') * .then(r => console.log(`Edited name of role ${r}`)) * .catch(console.error); */ setName(name) { return this.edit({ name }); } /** * Set a new color for the role * @param {number|string} color The new color for the role, either a hex string or a base 10 number * @returns {Promise} * @example * // set the color of a role * role.setColor('#FF0000') * .then(r => console.log(`Set color of role ${r}`)) * .catch(console.error); */ setColor(color) { return this.edit({ color }); } /** * Set whether or not the role should be hoisted * @param {boolean} hoist Whether or not to hoist the role * @returns {Promise} * @example * // set the hoist of the role * role.setHoist(true) * .then(r => console.log(`Role hoisted: ${r.hoist}`)) * .catch(console.error); */ setHoist(hoist) { return this.edit({ hoist }); } /** * Set the position of the role * @param {number} position The position of the role * @returns {Promise} * @example * // set the position of the role * role.setPosition(1) * .then(r => console.log(`Role position: ${r.position}`)) * .catch(console.error); */ setPosition(position) { return this.guild.setRolePosition(this, position); } /** * Set the permissions of the role * @param {string[]} permissions The permissions of the role * @returns {Promise} * @example * // set the permissions of the role * role.setPermissions(['KICK_MEMBERS', 'BAN_MEMBERS']) * .then(r => console.log(`Role updated ${r}`)) * .catch(console.error); */ setPermissions(permissions) { return this.edit({ permissions }); } /** * Set whether this role is mentionable * @param {boolean} mentionable Whether this role should be mentionable * @returns {Promise} * @example * // make the role mentionable * role.setMentionable(true) * .then(r => console.log(`Role updated ${r}`)) * .catch(console.error); */ setMentionable(mentionable) { return this.edit({ mentionable }); } /** * Deletes the role * @returns {Promise} * @example * // delete a role * role.delete() * .then(r => console.log(`Deleted role ${r}`)) * .catch(console.error); */ delete() { return this.client.rest.methods.deleteGuildRole(this); } /** * Whether the role is managable by the client user. * @type {boolean} * @readonly */ get editable() { if (this.managed) return false; const clientMember = this.guild.member(this.client.user); if (!clientMember.hasPermission(Constants.PermissionFlags.MANAGE_ROLES_OR_PERMISSIONS)) return false; return clientMember.highestRole.comparePositionTo(this) > 0; } /** * Whether this role equals another role. It compares all properties, so for most operations * it is advisable to just compare `role.id === role2.id` as it is much faster and is often * what most users need. * @param {Role} role The role to compare to * @returns {boolean} */ equals(role) { return role && this.id === role.id && this.name === role.name && this.color === role.color && this.hoist === role.hoist && this.position === role.position && this.permissions === role.permissions && this.managed === role.managed; } /** * When concatenated with a string, this automatically concatenates the role mention rather than the Role object. * @returns {string} */ toString() { return `<@&${this.id}>`; } /** * Compares the positions of two roles. * @param {Role} role1 First role to compare * @param {Role} role2 Second role to compare * @returns {number} Negative number if the first role's position is lower (second role's is higher), * positive number if the first's is higher (second's is lower), 0 if equal */ static comparePositions(role1, role2) { if (role1.position === role2.position) return role2.id - role1.id; return role1.position - role2.position; } } module.exports = Role; /***/ }, /* 8 */ /***/ function(module, exports) { /** * Represents any channel on Discord */ class Channel { constructor(client, data) { /** * The client that instantiated the Channel * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The type of the channel, either: * * `dm` - a DM channel * * `group` - a Group DM channel * * `text` - a guild text channel * * `voice` - a guild voice channel * @type {string} */ this.type = null; if (data) this.setup(data); } setup(data) { /** * The unique ID of the channel * @type {string} */ this.id = data.id; } /** * The timestamp the channel was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the channel was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * Deletes the channel * @returns {Promise} * @example * // delete the channel * channel.delete() * .then() // success * .catch(console.error); // log error */ delete() { return this.client.rest.methods.deleteChannel(this); } } module.exports = Channel; /***/ }, /* 9 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); const Collection = __webpack_require__(3); /** * Represents a custom emoji */ class Emoji { constructor(guild, data) { /** * The Client that instantiated this object * @type {Client} */ this.client = guild.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The guild this emoji is part of * @type {Guild} */ this.guild = guild; this.setup(data); } setup(data) { /** * The ID of the emoji * @type {string} */ this.id = data.id; /** * The name of the emoji * @type {string} */ this.name = data.name; /** * Whether or not this emoji requires colons surrounding it * @type {boolean} */ this.requiresColons = data.require_colons; /** * Whether this emoji is managed by an external service * @type {boolean} */ this.managed = data.managed; this._roles = data.roles; } /** * The timestamp the emoji was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the emoji was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * A collection of roles this emoji is active for (empty if all), mapped by role ID. * @type {Collection} * @readonly */ get roles() { const roles = new Collection(); for (const role of this._roles) { if (this.guild.roles.has(role)) roles.set(role, this.guild.roles.get(role)); } return roles; } /** * The URL to the emoji file * @type {string} * @readonly */ get url() { return `${Constants.Endpoints.CDN}/emojis/${this.id}.png`; } /** * When concatenated with a string, this automatically returns the emoji mention rather than the object. * @returns {string} * @example * // send an emoji: * const emoji = guild.emojis.first(); * msg.reply(`Hello! ${emoji}`); */ toString() { return this.requiresColons ? `<:${this.name}:${this.id}>` : this.name; } /** * The identifier of this emoji, used for message reactions * @readonly * @type {string} */ get identifier() { if (this.id) { return `${this.name}:${this.id}`; } return encodeURIComponent(this.name); } } module.exports = Emoji; /***/ }, /* 10 */ /***/ function(module, exports, __webpack_require__) { const path = __webpack_require__(22); const Message = __webpack_require__(13); const MessageCollector = __webpack_require__(32); const Collection = __webpack_require__(3); const escapeMarkdown = __webpack_require__(14); /** * Interface for classes that have text-channel-like features * @interface */ class TextBasedChannel { constructor() { /** * A collection containing the messages sent to this channel. * @type {Collection} */ this.messages = new Collection(); /** * The ID of the last message in the channel, if one was sent. * @type {?string} */ this.lastMessageID = null; } /** * Options that can be passed into sendMessage, sendTTSMessage, sendFile, sendCode, or Message.reply * @typedef {Object} MessageOptions * @property {boolean} [tts=false] Whether or not the message should be spoken aloud * @property {string} [nonce=''] The nonce for the message * @property {Object} [embed] An embed for the message * (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details) * @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here * should be replaced with plain-text * @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if * it exceeds the character limit. If an object is provided, these are the options for splitting the message. */ /** * Options for splitting a message * @typedef {Object} SplitOptions * @property {number} [maxLength=1950] Maximum character length per message piece * @property {string} [char='\n'] Character to split the message with * @property {string} [prepend=''] Text to prepend to every piece except the first * @property {string} [append=''] Text to append to every piece except the last */ /** * Send a message to this channel * @param {StringResolvable} content The content to send * @param {MessageOptions} [options={}] The options to provide * @returns {Promise} * @example * // send a message * channel.sendMessage('hello!') * .then(message => console.log(`Sent message: ${message.content}`)) * .catch(console.error); */ sendMessage(content, options = {}) { return this.client.rest.methods.sendMessage(this, content, options); } /** * Send a text-to-speech message to this channel * @param {StringResolvable} content The content to send * @param {MessageOptions} [options={}] The options to provide * @returns {Promise} * @example * // send a TTS message * channel.sendTTSMessage('hello!') * .then(message => console.log(`Sent tts message: ${message.content}`)) * .catch(console.error); */ sendTTSMessage(content, options = {}) { Object.assign(options, { tts: true }); return this.client.rest.methods.sendMessage(this, content, options); } /** * Send a file to this channel * @param {BufferResolvable} attachment The file to send * @param {string} [fileName="file.jpg"] The name and extension of the file * @param {StringResolvable} [content] Text message to send with the attachment * @param {MessageOptions} [options] The options to provide * @returns {Promise} */ sendFile(attachment, fileName, content, options = {}) { if (!fileName) { if (typeof attachment === 'string') { fileName = path.basename(attachment); } else if (attachment && attachment.path) { fileName = path.basename(attachment.path); } else { fileName = 'file.jpg'; } } return this.client.resolver.resolveBuffer(attachment).then(file => this.client.rest.methods.sendMessage(this, content, options, { file, name: fileName, }) ); } /** * Send a code block to this channel * @param {string} lang Language for the code block * @param {StringResolvable} content Content of the code block * @param {MessageOptions} options The options to provide * @returns {Promise} */ sendCode(lang, content, options = {}) { if (options.split) { if (typeof options.split !== 'object') options.split = {}; if (!options.split.prepend) options.split.prepend = `\`\`\`${lang || ''}\n`; if (!options.split.append) options.split.append = '\n```'; } content = escapeMarkdown(this.client.resolver.resolveString(content), true); return this.sendMessage(`\`\`\`${lang || ''}\n${content}\n\`\`\``, options); } /** * Gets a single message from this channel, regardless of it being cached or not. * This is only available when using a bot account. * @param {string} messageID The ID of the message to get * @returns {Promise} * @example * // get message * channel.fetchMessage('99539446449315840') * .then(message => console.log(message.content)) * .catch(console.error); */ fetchMessage(messageID) { return this.client.rest.methods.getChannelMessage(this, messageID).then(data => { const msg = data instanceof Message ? data : new Message(this, data, this.client); this._cacheMessage(msg); return msg; }); } /** * The parameters to pass in when requesting previous messages from a channel. `around`, `before` and * `after` are mutually exclusive. All the parameters are optional. * @typedef {Object} ChannelLogsQueryOptions * @property {number} [limit=50] Number of messages to acquire * @property {string} [before] ID of a message to get the messages that were posted before it * @property {string} [after] ID of a message to get the messages that were posted after it * @property {string} [around] ID of a message to get the messages that were posted around it */ /** * Gets the past messages sent in this channel. Resolves with a collection mapping message ID's to Message objects. * @param {ChannelLogsQueryOptions} [options={}] The query parameters to pass in * @returns {Promise>} * @example * // get messages * channel.fetchMessages({limit: 10}) * .then(messages => console.log(`Received ${messages.size} messages`)) * .catch(console.error); */ fetchMessages(options = {}) { return this.client.rest.methods.getChannelMessages(this, options).then(data => { const messages = new Collection(); for (const message of data) { const msg = new Message(this, message, this.client); messages.set(message.id, msg); this._cacheMessage(msg); } return messages; }); } /** * Fetches the pinned messages of this channel and returns a collection of them. * @returns {Promise>} */ fetchPinnedMessages() { return this.client.rest.methods.getChannelPinnedMessages(this).then(data => { const messages = new Collection(); for (const message of data) { const msg = new Message(this, message, this.client); messages.set(message.id, msg); this._cacheMessage(msg); } return messages; }); } /** * Starts a typing indicator in the channel. * @param {number} [count] The number of times startTyping should be considered to have been called * @example * // start typing in a channel * channel.startTyping(); */ startTyping(count) { if (typeof count !== 'undefined' && count < 1) throw new RangeError('Count must be at least 1.'); if (!this.client.user._typing.has(this.id)) { this.client.user._typing.set(this.id, { count: count || 1, interval: this.client.setInterval(() => { this.client.rest.methods.sendTyping(this.id); }, 4000), }); this.client.rest.methods.sendTyping(this.id); } else { const entry = this.client.user._typing.get(this.id); entry.count = count || entry.count + 1; } } /** * Stops the typing indicator in the channel. * The indicator will only stop if this is called as many times as startTyping(). * It can take a few seconds for the client user to stop typing. * @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop * @example * // stop typing in a channel * channel.stopTyping(); * @example * // force typing to fully stop in a channel * channel.stopTyping(true); */ stopTyping(force = false) { if (this.client.user._typing.has(this.id)) { const entry = this.client.user._typing.get(this.id); entry.count--; if (entry.count <= 0 || force) { this.client.clearInterval(entry.interval); this.client.user._typing.delete(this.id); } } } /** * Whether or not the typing indicator is being shown in the channel. * @type {boolean} * @readonly */ get typing() { return this.client.user._typing.has(this.id); } /** * Number of times `startTyping` has been called. * @type {number} * @readonly */ get typingCount() { if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; return 0; } /** * Creates a Message Collector * @param {CollectorFilterFunction} filter The filter to create the collector with * @param {CollectorOptions} [options={}] The options to pass to the collector * @returns {MessageCollector} * @example * // create a message collector * const collector = channel.createCollector( * m => m.content.includes('discord'), * { time: 15000 } * ); * collector.on('message', m => console.log(`Collected ${m.content}`)); * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); */ createCollector(filter, options = {}) { return new MessageCollector(this, filter, options); } /** * An object containing the same properties as CollectorOptions, but a few more: * @typedef {CollectorOptions} AwaitMessagesOptions * @property {string[]} [errors] Stop/end reasons that cause the promise to reject */ /** * Similar to createCollector but in promise form. Resolves with a collection of messages that pass the specified * filter. * @param {CollectorFilterFunction} filter The filter function to use * @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector * @returns {Promise>} * @example * // await !vote messages * const filter = m => m.content.startsWith('!vote'); * // errors: ['time'] treats ending because of the time limit as an error * channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] }) * .then(collected => console.log(collected.size)) * .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`)); */ awaitMessages(filter, options = {}) { return new Promise((resolve, reject) => { const collector = this.createCollector(filter, options); collector.on('end', (collection, reason) => { if (options.errors && options.errors.includes(reason)) { reject(collection); } else { resolve(collection); } }); }); } /** * Bulk delete given messages. * This is only available when using a bot account. * @param {Collection|Message[]|number} messages Messages to delete, or number of messages to delete * @returns {Promise>} Deleted messages */ bulkDelete(messages) { if (!isNaN(messages)) return this.fetchMessages({ limit: messages }).then(msgs => this.bulkDelete(msgs)); if (messages instanceof Array || messages instanceof Collection) { const messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id); return this.client.rest.methods.bulkDeleteMessages(this, messageIDs); } throw new TypeError('The messages must be an Array, Collection, or number.'); } _cacheMessage(message) { const maxSize = this.client.options.messageCacheMaxSize; if (maxSize === 0) return null; if (this.messages.size >= maxSize && maxSize > 0) this.messages.delete(this.messages.firstKey()); this.messages.set(message.id, message); return message; } } exports.applyToClass = (structure, full = false) => { const props = ['sendMessage', 'sendTTSMessage', 'sendFile', 'sendCode']; if (full) { props.push('_cacheMessage'); props.push('fetchMessages'); props.push('fetchMessage'); props.push('bulkDelete'); props.push('startTyping'); props.push('stopTyping'); props.push('typing'); props.push('typingCount'); props.push('fetchPinnedMessages'); props.push('createCollector'); props.push('awaitMessages'); } for (const prop of props) applyProp(structure, prop); }; function applyProp(structure, prop) { Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop)); } /***/ }, /* 11 */ /***/ function(module, exports, __webpack_require__) { const Channel = __webpack_require__(8); const Role = __webpack_require__(7); const PermissionOverwrites = __webpack_require__(38); const EvaluatedPermissions = __webpack_require__(17); const Constants = __webpack_require__(0); const Collection = __webpack_require__(3); const arraysEqual = __webpack_require__(24); /** * Represents a guild channel (i.e. text channels and voice channels) * @extends {Channel} */ class GuildChannel extends Channel { constructor(guild, data) { super(guild.client, data); /** * The guild the channel is in * @type {Guild} */ this.guild = guild; } setup(data) { super.setup(data); /** * The name of the guild channel * @type {string} */ this.name = data.name; /** * The position of the channel in the list. * @type {number} */ this.position = data.position; /** * A map of permission overwrites in this channel for roles and users. * @type {Collection} */ this.permissionOverwrites = new Collection(); if (data.permission_overwrites) { for (const overwrite of data.permission_overwrites) { this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite)); } } } /** * Gets the overall set of permissions for a user in this channel, taking into account roles and permission * overwrites. * @param {GuildMemberResolvable} member The user that you want to obtain the overall permissions for * @returns {?EvaluatedPermissions} */ permissionsFor(member) { member = this.client.resolver.resolveGuildMember(this.guild, member); if (!member) return null; if (member.id === this.guild.ownerID) return new EvaluatedPermissions(member, Constants.ALL_PERMISSIONS); let permissions = 0; const roles = member.roles; for (const role of roles.values()) permissions |= role.permissions; const overwrites = this.overwritesFor(member, true, roles); for (const overwrite of overwrites.role.concat(overwrites.member)) { permissions &= ~overwrite.denyData; permissions |= overwrite.allowData; } const admin = Boolean(permissions & Constants.PermissionFlags.ADMINISTRATOR); if (admin) permissions = Constants.ALL_PERMISSIONS; return new EvaluatedPermissions(member, permissions); } overwritesFor(member, verified = false, roles = null) { if (!verified) member = this.client.resolver.resolveGuildMember(this.guild, member); if (!member) return []; roles = roles || member.roles; const roleOverwrites = []; const memberOverwrites = []; for (const overwrite of this.permissionOverwrites.values()) { if (overwrite.id === member.id) { memberOverwrites.push(overwrite); } else if (roles.has(overwrite.id)) { roleOverwrites.push(overwrite); } } return { role: roleOverwrites, member: memberOverwrites, }; } /** * An object mapping permission flags to `true` (enabled) or `false` (disabled) * ```js * { * 'SEND_MESSAGES': true, * 'ATTACH_FILES': false, * } * ``` * @typedef {Object} PermissionOverwriteOptions */ /** * Overwrites the permissions for a user or role in this channel. * @param {RoleResolvable|UserResolvable} userOrRole The user or role to update * @param {PermissionOverwriteOptions} options The configuration for the update * @returns {Promise} * @example * // overwrite permissions for a message author * message.channel.overwritePermissions(message.author, { * SEND_MESSAGES: false * }) * .then(() => console.log('Done!')) * .catch(console.error); */ overwritePermissions(userOrRole, options) { const payload = { allow: 0, deny: 0, }; if (userOrRole instanceof Role) { payload.type = 'role'; } else if (this.guild.roles.has(userOrRole)) { userOrRole = this.guild.roles.get(userOrRole); payload.type = 'role'; } else { userOrRole = this.client.resolver.resolveUser(userOrRole); payload.type = 'member'; if (!userOrRole) return Promise.reject(new TypeError('Supplied parameter was neither a User nor a Role.')); } payload.id = userOrRole.id; const prevOverwrite = this.permissionOverwrites.get(userOrRole.id); if (prevOverwrite) { payload.allow = prevOverwrite.allowData; payload.deny = prevOverwrite.denyData; } for (const perm in options) { if (options[perm] === true) { payload.allow |= Constants.PermissionFlags[perm] || 0; payload.deny &= ~(Constants.PermissionFlags[perm] || 0); } else if (options[perm] === false) { payload.allow &= ~(Constants.PermissionFlags[perm] || 0); payload.deny |= Constants.PermissionFlags[perm] || 0; } else if (options[perm] === null) { payload.allow &= ~(Constants.PermissionFlags[perm] || 0); payload.deny &= ~(Constants.PermissionFlags[perm] || 0); } } return this.client.rest.methods.setChannelOverwrite(this, payload); } /** * The data for a guild channel * @typedef {Object} ChannelData * @property {string} [name] The name of the channel * @property {number} [position] The position of the channel * @property {string} [topic] The topic of the text channel * @property {number} [bitrate] The bitrate of the voice channel * @property {number} [userLimit] The user limit of the channel */ /** * Edits the channel * @param {ChannelData} data The new data for the channel * @returns {Promise} * @example * // edit a channel * channel.edit({name: 'new-channel'}) * .then(c => console.log(`Edited channel ${c}`)) * .catch(console.error); */ edit(data) { return this.client.rest.methods.updateChannel(this, data); } /** * Set a new name for the guild channel * @param {string} name The new name for the guild channel * @returns {Promise} * @example * // set a new channel name * channel.setName('not_general') * .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`)) * .catch(console.error); */ setName(name) { return this.edit({ name }); } /** * Set a new position for the guild channel * @param {number} position The new position for the guild channel * @returns {Promise} * @example * // set a new channel position * channel.setPosition(2) * .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`)) * .catch(console.error); */ setPosition(position) { return this.client.rest.methods.updateChannel(this, { position }); } /** * Set a new topic for the guild channel * @param {string} topic The new topic for the guild channel * @returns {Promise} * @example * // set a new channel topic * channel.setTopic('needs more rate limiting') * .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`)) * .catch(console.error); */ setTopic(topic) { return this.client.rest.methods.updateChannel(this, { topic }); } /** * Options given when creating a guild channel invite * @typedef {Object} InviteOptions * @property {boolean} [temporary=false] Whether the invite should kick users after 24hrs if they are not given a role * @property {number} [maxAge=0] Time in seconds the invite expires in * @property {number} [maxUses=0] Maximum amount of uses for this invite */ /** * Create an invite to this guild channel * @param {InviteOptions} [options={}] The options for the invite * @returns {Promise} */ createInvite(options = {}) { return this.client.rest.methods.createChannelInvite(this, options); } /** * Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel. * In most cases, a simple `channel.id === channel2.id` will do, and is much faster too. * @param {GuildChannel} channel The channel to compare this channel to * @returns {boolean} */ equals(channel) { let equal = channel && this.id === channel.id && this.type === channel.type && this.topic === channel.topic && this.position === channel.position && this.name === channel.name; if (equal) { if (this.permissionOverwrites && channel.permissionOverwrites) { const thisIDSet = this.permissionOverwrites.keyArray(); const otherIDSet = channel.permissionOverwrites.keyArray(); equal = arraysEqual(thisIDSet, otherIDSet); } else { equal = !this.permissionOverwrites && !channel.permissionOverwrites; } } return equal; } /** * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. * @returns {string} * @example * // Outputs: Hello from #general * console.log(`Hello from ${channel}`); * @example * // Outputs: Hello from #general * console.log('Hello from ' + channel); */ toString() { return `<#${this.id}>`; } } module.exports = GuildChannel; /***/ }, /* 12 */ /***/ function(module, exports, __webpack_require__) { const TextBasedChannel = __webpack_require__(10); const Role = __webpack_require__(7); const EvaluatedPermissions = __webpack_require__(17); const Constants = __webpack_require__(0); const Collection = __webpack_require__(3); const Presence = __webpack_require__(6).Presence; /** * Represents a member of a guild on Discord * @implements {TextBasedChannel} */ class GuildMember { constructor(guild, data) { /** * The Client that instantiated this GuildMember * @type {Client} */ this.client = guild.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The guild that this member is part of * @type {Guild} */ this.guild = guild; /** * The user that this guild member instance Represents * @type {User} */ this.user = {}; this._roles = []; if (data) this.setup(data); } setup(data) { /** * Whether this member is deafened server-wide * @type {boolean} */ this.serverDeaf = data.deaf; /** * Whether this member is muted server-wide * @type {boolean} */ this.serverMute = data.mute; /** * Whether this member is self-muted * @type {boolean} */ this.selfMute = data.self_mute; /** * Whether this member is self-deafened * @type {boolean} */ this.selfDeaf = data.self_deaf; /** * The voice session ID of this member, if any * @type {?string} */ this.voiceSessionID = data.session_id; /** * The voice channel ID of this member, if any * @type {?string} */ this.voiceChannelID = data.channel_id; /** * Whether this member is speaking * @type {boolean} */ this.speaking = false; /** * The nickname of this guild member, if they have one * @type {?string} */ this.nickname = data.nick || null; /** * The timestamp the member joined the guild at * @type {number} */ this.joinedTimestamp = new Date(data.joined_at).getTime(); this.user = data.user; this._roles = data.roles; } /** * The time the member joined the guild * @type {Date} * @readonly */ get joinedAt() { return new Date(this.joinedTimestamp); } /** * The presence of this guild member * @type {Presence} * @readonly */ get presence() { return this.frozenPresence || this.guild.presences.get(this.id) || new Presence(); } /** * A list of roles that are applied to this GuildMember, mapped by the role ID. * @type {Collection} * @readonly */ get roles() { const list = new Collection(); const everyoneRole = this.guild.roles.get(this.guild.id); if (everyoneRole) list.set(everyoneRole.id, everyoneRole); for (const roleID of this._roles) { const role = this.guild.roles.get(roleID); if (role) list.set(role.id, role); } return list; } /** * The role of the member with the highest position. * @type {Role} * @readonly */ get highestRole() { return this.roles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev); } /** * Whether this member is muted in any way * @type {boolean} * @readonly */ get mute() { return this.selfMute || this.serverMute; } /** * Whether this member is deafened in any way * @type {boolean} * @readonly */ get deaf() { return this.selfDeaf || this.serverDeaf; } /** * The voice channel this member is in, if any * @type {?VoiceChannel} * @readonly */ get voiceChannel() { return this.guild.channels.get(this.voiceChannelID); } /** * The ID of this user * @type {string} * @readonly */ get id() { return this.user.id; } /** * The overall set of permissions for the guild member, taking only roles into account * @type {EvaluatedPermissions} * @readonly */ get permissions() { if (this.user.id === this.guild.ownerID) return new EvaluatedPermissions(this, Constants.ALL_PERMISSIONS); let permissions = 0; const roles = this.roles; for (const role of roles.values()) permissions |= role.permissions; const admin = Boolean(permissions & Constants.PermissionFlags.ADMINISTRATOR); if (admin) permissions = Constants.ALL_PERMISSIONS; return new EvaluatedPermissions(this, permissions); } /** * Whether the member is kickable by the client user. * @type {boolean} * @readonly */ get kickable() { if (this.user.id === this.guild.ownerID) return false; if (this.user.id === this.client.user.id) return false; const clientMember = this.guild.member(this.client.user); if (!clientMember.hasPermission(Constants.PermissionFlags.KICK_MEMBERS)) return false; return clientMember.highestRole.comparePositionTo(this.highestRole) > 0; } /** * Whether the member is bannable by the client user. * @type {boolean} * @readonly */ get bannable() { if (this.user.id === this.guild.ownerID) return false; if (this.user.id === this.client.user.id) return false; const clientMember = this.guild.member(this.client.user); if (!clientMember.hasPermission(Constants.PermissionFlags.BAN_MEMBERS)) return false; return clientMember.highestRole.comparePositionTo(this.highestRole) > 0; } /** * Returns `channel.permissionsFor(guildMember)`. Returns evaluated permissions for a member in a guild channel. * @param {ChannelResolvable} channel Guild channel to use as context * @returns {?EvaluatedPermissions} */ permissionsIn(channel) { channel = this.client.resolver.resolveChannel(channel); if (!channel || !channel.guild) throw new Error('Could not resolve channel to a guild channel.'); return channel.permissionsFor(this); } /** * Checks if any of the member's roles have a permission. * @param {PermissionResolvable} permission The permission to check for * @param {boolean} [explicit=false] Whether to require the roles to explicitly have the exact permission * @returns {boolean} */ hasPermission(permission, explicit = false) { if (!explicit && this.user.id === this.guild.ownerID) return true; return this.roles.some(r => r.hasPermission(permission, explicit)); } /** * Checks whether the roles of the member allows them to perform specific actions. * @param {PermissionResolvable[]} permissions The permissions to check for * @param {boolean} [explicit=false] Whether to require the member to explicitly have the exact permissions * @returns {boolean} */ hasPermissions(permissions, explicit = false) { if (!explicit && this.user.id === this.guild.ownerID) return true; return permissions.every(p => this.hasPermission(p, explicit)); } /** * Checks whether the roles of the member allows them to perform specific actions, and lists any missing permissions. * @param {PermissionResolvable[]} permissions The permissions to check for * @param {boolean} [explicit=false] Whether to require the member to explicitly have the exact permissions * @returns {PermissionResolvable[]} */ missingPermissions(permissions, explicit = false) { return permissions.filter(p => !this.hasPermission(p, explicit)); } /** * Edit a guild member * @param {GuildmemberEditData} data The data to edit the member with * @returns {Promise} */ edit(data) { return this.client.rest.methods.updateGuildMember(this, data); } /** * Mute/unmute a user * @param {boolean} mute Whether or not the member should be muted * @returns {Promise} */ setMute(mute) { return this.edit({ mute }); } /** * Deafen/undeafen a user * @param {boolean} deaf Whether or not the member should be deafened * @returns {Promise} */ setDeaf(deaf) { return this.edit({ deaf }); } /** * Moves the guild member to the given channel. * @param {ChannelResolvable} channel The channel to move the member to * @returns {Promise} */ setVoiceChannel(channel) { return this.edit({ channel }); } /** * Sets the roles applied to the member. * @param {Collection|Role[]|string[]} roles The roles or role IDs to apply * @returns {Promise} */ setRoles(roles) { return this.edit({ roles }); } /** * Adds a single role to the member. * @param {Role|string} role The role or ID of the role to add * @returns {Promise} */ addRole(role) { return this.addRoles([role]); } /** * Adds multiple roles to the member. * @param {Collection|Role[]|string[]} roles The roles or role IDs to add * @returns {Promise} */ addRoles(roles) { let allRoles; if (roles instanceof Collection) { allRoles = this._roles.slice(); for (const role of roles.values()) allRoles.push(role.id); } else { allRoles = this._roles.concat(roles); } return this.edit({ roles: allRoles }); } /** * Removes a single role from the member. * @param {Role|string} role The role or ID of the role to remove * @returns {Promise} */ removeRole(role) { return this.removeRoles([role]); } /** * Removes multiple roles from the member. * @param {Collection|Role[]|string[]} roles The roles or role IDs to remove * @returns {Promise} */ removeRoles(roles) { const allRoles = this._roles.slice(); if (roles instanceof Collection) { for (const role of roles.values()) { const index = allRoles.indexOf(role.id); if (index >= 0) allRoles.splice(index, 1); } } else { for (const role of roles) { const index = allRoles.indexOf(role instanceof Role ? role.id : role); if (index >= 0) allRoles.splice(index, 1); } } return this.edit({ roles: allRoles }); } /** * Set the nickname for the guild member * @param {string} nick The nickname for the guild member * @returns {Promise} */ setNickname(nick) { return this.edit({ nick }); } /** * Deletes any DMs with this guild member * @returns {Promise} */ deleteDM() { return this.client.rest.methods.deleteChannel(this); } /** * Kick this member from the guild * @returns {Promise} */ kick() { return this.client.rest.methods.kickGuildMember(this.guild, this); } /** * Ban this guild member * @param {number} [deleteDays=0] The amount of days worth of messages from this member that should * also be deleted. Between `0` and `7`. * @returns {Promise} * @example * // ban a guild member * guildMember.ban(7); */ ban(deleteDays = 0) { return this.client.rest.methods.banGuildMember(this.guild, this, deleteDays); } /** * When concatenated with a string, this automatically concatenates the user's mention instead of the Member object. * @returns {string} * @example * // logs: Hello from <@123456789>! * console.log(`Hello from ${member}!`); */ toString() { return `<@${this.nickname ? '!' : ''}${this.user.id}>`; } // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } sendFile() { return; } sendCode() { return; } } TextBasedChannel.applyToClass(GuildMember); module.exports = GuildMember; /***/ }, /* 13 */ /***/ function(module, exports, __webpack_require__) { const Attachment = __webpack_require__(31); const Embed = __webpack_require__(33); const Collection = __webpack_require__(3); const Constants = __webpack_require__(0); const escapeMarkdown = __webpack_require__(14); const MessageReaction = __webpack_require__(34); /** * Represents a message on Discord */ class Message { constructor(channel, data, client) { /** * The Client that instantiated the Message * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The channel that the message was sent in * @type {TextChannel|DMChannel|GroupDMChannel} */ this.channel = channel; if (data) this.setup(data); } setup(data) { // eslint-disable-line complexity /** * The ID of the message (unique in the channel it was sent) * @type {string} */ this.id = data.id; /** * The type of the message * @type {string} */ this.type = Constants.MessageTypes[data.type]; /** * The content of the message * @type {string} */ this.content = data.content; /** * The author of the message * @type {User} */ this.author = this.client.dataManager.newUser(data.author); /** * Represents the author of the message as a guild member. Only available if the message comes from a guild * where the author is still a member. * @type {GuildMember} */ this.member = this.guild ? this.guild.member(this.author) || null : null; /** * Whether or not this message is pinned * @type {boolean} */ this.pinned = data.pinned; /** * Whether or not the message was Text-To-Speech * @type {boolean} */ this.tts = data.tts; /** * A random number used for checking message delivery * @type {string} */ this.nonce = data.nonce; /** * Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications) * @type {boolean} */ this.system = data.type === 6; /** * A list of embeds in the message - e.g. YouTube Player * @type {MessageEmbed[]} */ this.embeds = data.embeds.map(e => new Embed(this, e)); /** * A collection of attachments in the message - e.g. Pictures - mapped by their ID. * @type {Collection} */ this.attachments = new Collection(); for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment)); /** * The timestamp the message was sent at * @type {number} */ this.createdTimestamp = new Date(data.timestamp).getTime(); /** * The timestamp the message was last edited at (if applicable) * @type {?number} */ this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null; /** * An object containing a further users, roles or channels collections * @type {Object} * @property {Collection} mentions.users Mentioned users, maps their ID to the user object. * @property {Collection} mentions.roles Mentioned roles, maps their ID to the role object. * @property {Collection} mentions.channels Mentioned channels, * maps their ID to the channel object. * @property {boolean} mentions.everyone Whether or not @everyone was mentioned. */ this.mentions = { users: new Collection(), roles: new Collection(), channels: new Collection(), everyone: data.mention_everyone, }; for (const mention of data.mentions) { let user = this.client.users.get(mention.id); if (user) { this.mentions.users.set(user.id, user); } else { user = this.client.dataManager.newUser(mention); this.mentions.users.set(user.id, user); } } if (data.mention_roles) { for (const mention of data.mention_roles) { const role = this.channel.guild.roles.get(mention); if (role) this.mentions.roles.set(role.id, role); } } if (this.channel.guild) { const channMentionsRaw = data.content.match(/<#([0-9]{14,20})>/g) || []; for (const raw of channMentionsRaw) { const chan = this.channel.guild.channels.get(raw.match(/([0-9]{14,20})/g)[0]); if (chan) this.mentions.channels.set(chan.id, chan); } } this._edits = []; /** * A collection of reactions to this message, mapped by the reaction "id". * @type {Collection} */ this.reactions = new Collection(); if (data.reactions && data.reactions.length > 0) { for (const reaction of data.reactions) { const id = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name; this.reactions.set(id, new MessageReaction(this, reaction.emoji, reaction.count, reaction.me)); } } } patch(data) { // eslint-disable-line complexity if (data.author) { this.author = this.client.users.get(data.author.id); if (this.guild) this.member = this.guild.member(this.author); } if (data.content) this.content = data.content; if (data.timestamp) this.createdTimestamp = new Date(data.timestamp).getTime(); if (data.edited_timestamp) { this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null; } if ('tts' in data) this.tts = data.tts; if ('mention_everyone' in data) this.mentions.everyone = data.mention_everyone; if (data.nonce) this.nonce = data.nonce; if (data.embeds) this.embeds = data.embeds.map(e => new Embed(this, e)); if (data.type > -1) { this.system = false; if (data.type === 6) this.system = true; } if (data.attachments) { this.attachments = new Collection(); for (const attachment of data.attachments) { this.attachments.set(attachment.id, new Attachment(this, attachment)); } } if (data.mentions) { for (const mention of data.mentions) { let user = this.client.users.get(mention.id); if (user) { this.mentions.users.set(user.id, user); } else { user = this.client.dataManager.newUser(mention); this.mentions.users.set(user.id, user); } } } if (data.mention_roles) { for (const mention of data.mention_roles) { const role = this.channel.guild.roles.get(mention); if (role) this.mentions.roles.set(role.id, role); } } if (data.id) this.id = data.id; if (this.channel.guild && data.content) { const channMentionsRaw = data.content.match(/<#([0-9]{14,20})>/g) || []; for (const raw of channMentionsRaw) { const chan = this.channel.guild.channels.get(raw.match(/([0-9]{14,20})/g)[0]); if (chan) this.mentions.channels.set(chan.id, chan); } } if (data.reactions) { this.reactions = new Collection(); if (data.reactions.length > 0) { for (const reaction of data.reactions) { const id = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name; this.reactions.set(id, new MessageReaction(this, data.emoji, data.count, data.me)); } } } } /** * The time the message was sent * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * The time the message was last edited at (if applicable) * @type {?Date} * @readonly */ get editedAt() { return this.editedTimestamp ? new Date(this.editedTimestamp) : null; } /** * The guild the message was sent in (if in a guild channel) * @type {?Guild} * @readonly */ get guild() { return this.channel.guild || null; } /** * The message contents with all mentions replaced by the equivalent text. If mentions cannot be resolved to a name, * the relevant mention in the message content will not be converted. * @type {string} * @readonly */ get cleanContent() { return this.content .replace(/@(everyone|here)/g, '@\u200b$1') .replace(/<@!?[0-9]+>/g, (input) => { const id = input.replace(/<|!|>|@/g, ''); if (this.channel.type === 'dm' || this.channel.type === 'group') { return this.client.users.has(id) ? `@${this.client.users.get(id).username}` : input; } const member = this.channel.guild.members.get(id); if (member) { if (member.nickname) return `@${member.nickname}`; return `@${member.user.username}`; } else { const user = this.client.users.get(id); if (user) return `@${user.username}`; return input; } }) .replace(/<#[0-9]+>/g, (input) => { const channel = this.client.channels.get(input.replace(/<|#|>/g, '')); if (channel) return `#${channel.name}`; return input; }) .replace(/<@&[0-9]+>/g, (input) => { if (this.channel.type === 'dm' || this.channel.type === 'group') return input; const role = this.guild.roles.get(input.replace(/<|@|>|&/g, '')); if (role) return `@${role.name}`; return input; }); } /** * An array of cached versions of the message, including the current version. * Sorted from latest (first) to oldest (last). * @type {Message[]} * @readonly */ get edits() { return this._edits.slice().unshift(this); } /** * Whether the message is editable by the client user. * @type {boolean} * @readonly */ get editable() { return this.author.id === this.client.user.id; } /** * Whether the message is deletable by the client user. * @type {boolean} * @readonly */ get deletable() { return this.author.id === this.client.user.id || (this.guild && this.channel.permissionsFor(this.client.user).hasPermission(Constants.PermissionFlags.MANAGE_MESSAGES) ); } /** * Whether the message is pinnable by the client user. * @type {boolean} * @readonly */ get pinnable() { return !this.guild || this.channel.permissionsFor(this.client.user).hasPermission(Constants.PermissionFlags.MANAGE_MESSAGES); } /** * Whether or not a user, channel or role is mentioned in this message. * @param {GuildChannel|User|Role|string} data either a guild channel, user or a role object, or a string representing * the ID of any of these. * @returns {boolean} */ isMentioned(data) { data = data && data.id ? data.id : data; return this.mentions.users.has(data) || this.mentions.channels.has(data) || this.mentions.roles.has(data); } /** * Options that can be passed into editMessage * @typedef {Object} MessageEditOptions * @property {Object} [embed] An embed to be added/edited */ /** * Edit the content of the message * @param {StringResolvable} content The new content for the message * @param {MessageEditOptions} [options={}] The options to provide * @returns {Promise} * @example * // update the content of a message * message.edit('This is my new content!') * .then(msg => console.log(`Updated the content of a message from ${msg.author}`)) * .catch(console.error); */ edit(content, options = {}) { return this.client.rest.methods.updateMessage(this, content, options); } /** * Edit the content of the message, with a code block * @param {string} lang Language for the code block * @param {StringResolvable} content The new content for the message * @returns {Promise} */ editCode(lang, content) { content = escapeMarkdown(this.client.resolver.resolveString(content), true); return this.edit(`\`\`\`${lang || ''}\n${content}\n\`\`\``); } /** * Pins this message to the channel's pinned messages * @returns {Promise} */ pin() { return this.client.rest.methods.pinMessage(this); } /** * Unpins this message from the channel's pinned messages * @returns {Promise} */ unpin() { return this.client.rest.methods.unpinMessage(this); } /** * Add a reaction to the message * @param {string|Emoji|ReactionEmoji} emoji Emoji to react with * @returns {Promise} */ react(emoji) { emoji = this.client.resolver.resolveEmojiIdentifier(emoji); if (!emoji) throw new TypeError('Emoji must be a string or Emoji/ReactionEmoji'); return this.client.rest.methods.addMessageReaction(this, emoji); } /** * Remove all reactions from a message * @returns {Promise} */ clearReactions() { return this.client.rest.methods.removeMessageReactions(this); } /** * Deletes the message * @param {number} [timeout=0] How long to wait to delete the message in milliseconds * @returns {Promise} * @example * // delete a message * message.delete() * .then(msg => console.log(`Deleted message from ${msg.author}`)) * .catch(console.error); */ delete(timeout = 0) { if (timeout <= 0) { return this.client.rest.methods.deleteMessage(this); } else { return new Promise(resolve => { this.client.setTimeout(() => { resolve(this.delete()); }, timeout); }); } } /** * Reply to the message * @param {StringResolvable} content The content for the message * @param {MessageOptions} [options = {}] The options to provide * @returns {Promise} * @example * // reply to a message * message.reply('Hey, I\'m a reply!') * .then(msg => console.log(`Sent a reply to ${msg.author}`)) * .catch(console.error); */ reply(content, options = {}) { content = this.client.resolver.resolveString(content); const prepend = this.guild ? `${this.author}, ` : ''; content = `${prepend}${content}`; if (options.split) { if (typeof options.split !== 'object') options.split = {}; if (!options.split.prepend) options.split.prepend = prepend; } return this.client.rest.methods.sendMessage(this.channel, content, options); } /** * Used mainly internally. Whether two messages are identical in properties. If you want to compare messages * without checking all the properties, use `message.id === message2.id`, which is much more efficient. This * method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties. * @param {Message} message The message to compare it to * @param {Object} rawData Raw data passed through the WebSocket about this message * @returns {boolean} */ equals(message, rawData) { if (!message) return false; const embedUpdate = !message.author && !message.attachments; if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length; let equal = this.id === message.id && this.author.id === message.author.id && this.content === message.content && this.tts === message.tts && this.nonce === message.nonce && this.embeds.length === message.embeds.length && this.attachments.length === message.attachments.length; if (equal && rawData) { equal = this.mentions.everyone === message.mentions.everyone && this.createdTimestamp === new Date(rawData.timestamp).getTime() && this.editedTimestamp === new Date(rawData.edited_timestamp).getTime(); } return equal; } /** * When concatenated with a string, this automatically concatenates the message's content instead of the object. * @returns {string} * @example * // logs: Message: This is a message! * console.log(`Message: ${message}`); */ toString() { return this.content; } _addReaction(emoji, user) { const emojiID = emoji.id ? `${emoji.name}:${emoji.id}` : emoji.name; let reaction; if (this.reactions.has(emojiID)) { reaction = this.reactions.get(emojiID); if (!reaction.me) reaction.me = user.id === this.client.user.id; } else { reaction = new MessageReaction(this, emoji, 0, user.id === this.client.user.id); this.reactions.set(emojiID, reaction); } if (!reaction.users.has(user.id)) { reaction.users.set(user.id, user); reaction.count++; return reaction; } return null; } _removeReaction(emoji, user) { const emojiID = emoji.id || emoji; if (this.reactions.has(emojiID)) { const reaction = this.reactions.get(emojiID); if (reaction.users.has(user.id)) { reaction.users.delete(user.id); reaction.count--; if (user.id === this.client.user.id) reaction.me = false; return reaction; } } return null; } _clearReactions() { this.reactions.clear(); } } module.exports = Message; /***/ }, /* 14 */ /***/ function(module, exports) { module.exports = function escapeMarkdown(text, onlyCodeBlock = false, onlyInlineCode = false) { if (onlyCodeBlock) return text.replace(/```/g, '`\u200b``'); if (onlyInlineCode) return text.replace(/\\(`|\\)/g, '$1').replace(/(`|\\)/g, '\\$1'); return text.replace(/\\(\*|_|`|~|\\)/g, '$1').replace(/(\*|_|`|~|\\)/g, '\\$1'); }; /***/ }, /* 15 */ /***/ function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(Buffer, global) {/*! * The buffer module from node.js, for the browser. * * @author Feross Aboukhadijeh * @license MIT */ /* eslint-disable no-proto */ 'use strict' var base64 = __webpack_require__(55) var ieee754 = __webpack_require__(57) var isArray = __webpack_require__(58) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer exports.INSPECT_MAX_BYTES = 50 /** * If `Buffer.TYPED_ARRAY_SUPPORT`: * === true Use Uint8Array implementation (fastest) * === false Use Object implementation (most compatible, even IE6) * * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, * Opera 11.6+, iOS 4.2+. * * Due to various browser bugs, sometimes the Object implementation will be used even * when the browser supports typed arrays. * * Note: * * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. * * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. * * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of * incorrect length in some situations. * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they * get the Object implementation, which is slower but behaves correctly. */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT : typedArraySupport() /* * Export kMaxLength after typed array support is determined. */ exports.kMaxLength = kMaxLength() function typedArraySupport () { try { var arr = new Uint8Array(1) arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` } catch (e) { return false } } function kMaxLength () { return Buffer.TYPED_ARRAY_SUPPORT ? 0x7fffffff : 0x3fffffff } function createBuffer (that, length) { if (kMaxLength() < length) { throw new RangeError('Invalid typed array length') } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = new Uint8Array(length) that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class if (that === null) { that = new Buffer(length) } that.length = length } return that } /** * The Buffer constructor returns instances of `Uint8Array` that have their * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of * `Uint8Array`, so the returned instances will have all the node `Buffer` methods * and the `Uint8Array` methods. Square bracket notation works as expected -- it * returns a single octet. * * The `Uint8Array` prototype remains unmodified. */ function Buffer (arg, encodingOrOffset, length) { if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { return new Buffer(arg, encodingOrOffset, length) } // Common case. if (typeof arg === 'number') { if (typeof encodingOrOffset === 'string') { throw new Error( 'If encoding is specified then the first argument must be a string' ) } return allocUnsafe(this, arg) } return from(this, arg, encodingOrOffset, length) } Buffer.poolSize = 8192 // not used by this implementation // TODO: Legacy, not needed anymore. Remove in next major version. Buffer._augment = function (arr) { arr.__proto__ = Buffer.prototype return arr } function from (that, value, encodingOrOffset, length) { if (typeof value === 'number') { throw new TypeError('"value" argument must not be a number') } if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { return fromArrayBuffer(that, value, encodingOrOffset, length) } if (typeof value === 'string') { return fromString(that, value, encodingOrOffset) } return fromObject(that, value) } /** * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError * if value is a number. * Buffer.from(str[, encoding]) * Buffer.from(array) * Buffer.from(buffer) * Buffer.from(arrayBuffer[, byteOffset[, length]]) **/ Buffer.from = function (value, encodingOrOffset, length) { return from(null, value, encodingOrOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { Buffer.prototype.__proto__ = Uint8Array.prototype Buffer.__proto__ = Uint8Array if (typeof Symbol !== 'undefined' && Symbol.species && Buffer[Symbol.species] === Buffer) { // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 Object.defineProperty(Buffer, Symbol.species, { value: null, configurable: true }) } } function assertSize (size) { if (typeof size !== 'number') { throw new TypeError('"size" argument must be a number') } else if (size < 0) { throw new RangeError('"size" argument must not be negative') } } function alloc (that, size, fill, encoding) { assertSize(size) if (size <= 0) { return createBuffer(that, size) } if (fill !== undefined) { // Only pay attention to encoding if it's a string. This // prevents accidentally sending in a number that would // be interpretted as a start offset. return typeof encoding === 'string' ? createBuffer(that, size).fill(fill, encoding) : createBuffer(that, size).fill(fill) } return createBuffer(that, size) } /** * Creates a new filled Buffer instance. * alloc(size[, fill[, encoding]]) **/ Buffer.alloc = function (size, fill, encoding) { return alloc(null, size, fill, encoding) } function allocUnsafe (that, size) { assertSize(size) that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < size; ++i) { that[i] = 0 } } return that } /** * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(null, size) } /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(null, size) } function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') { encoding = 'utf8' } if (!Buffer.isEncoding(encoding)) { throw new TypeError('"encoding" must be a valid string encoding') } var length = byteLength(string, encoding) | 0 that = createBuffer(that, length) var actual = that.write(string, encoding) if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will // cause everything after the first invalid character to be ignored. (e.g. // 'abxxcd' will be treated as 'ab') that = that.slice(0, actual) } return that } function fromArrayLike (that, array) { var length = array.length < 0 ? 0 : checked(array.length) | 0 that = createBuffer(that, length) for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } return that } function fromArrayBuffer (that, array, byteOffset, length) { array.byteLength // this throws if `array` is not a valid ArrayBuffer if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('\'offset\' is out of bounds') } if (array.byteLength < byteOffset + (length || 0)) { throw new RangeError('\'length\' is out of bounds') } if (byteOffset === undefined && length === undefined) { array = new Uint8Array(array) } else if (length === undefined) { array = new Uint8Array(array, byteOffset) } else { array = new Uint8Array(array, byteOffset, length) } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance that = array that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class that = fromArrayLike(that, array) } return that } function fromObject (that, obj) { if (Buffer.isBuffer(obj)) { var len = checked(obj.length) | 0 that = createBuffer(that, len) if (that.length === 0) { return that } obj.copy(that, 0, 0, len) return that } if (obj) { if ((typeof ArrayBuffer !== 'undefined' && obj.buffer instanceof ArrayBuffer) || 'length' in obj) { if (typeof obj.length !== 'number' || isnan(obj.length)) { return createBuffer(that, 0) } return fromArrayLike(that, obj) } if (obj.type === 'Buffer' && isArray(obj.data)) { return fromArrayLike(that, obj.data) } } throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') } function checked (length) { // Note: cannot use `length < kMaxLength()` here because that fails when // length is NaN (which is otherwise coerced to zero.) if (length >= kMaxLength()) { throw new RangeError('Attempt to allocate Buffer larger than maximum ' + 'size: 0x' + kMaxLength().toString(16) + ' bytes') } return length | 0 } function SlowBuffer (length) { if (+length != length) { // eslint-disable-line eqeqeq length = 0 } return Buffer.alloc(+length) } Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) } Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } if (a === b) return 0 var x = a.length var y = b.length for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { x = a[i] y = b[i] break } } if (x < y) return -1 if (y < x) return 1 return 0 } Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'latin1': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return true default: return false } } Buffer.concat = function concat (list, length) { if (!isArray(list)) { throw new TypeError('"list" argument must be an Array of Buffers') } if (list.length === 0) { return Buffer.alloc(0) } var i if (length === undefined) { length = 0 for (i = 0; i < list.length; ++i) { length += list[i].length } } var buffer = Buffer.allocUnsafe(length) var pos = 0 for (i = 0; i < list.length; ++i) { var buf = list[i] if (!Buffer.isBuffer(buf)) { throw new TypeError('"list" argument must be an Array of Buffers') } buf.copy(buffer, pos) pos += buf.length } return buffer } function byteLength (string, encoding) { if (Buffer.isBuffer(string)) { return string.length } if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { return string.byteLength } if (typeof string !== 'string') { string = '' + string } var len = string.length if (len === 0) return 0 // Use a for loop to avoid recursion var loweredCase = false for (;;) { switch (encoding) { case 'ascii': case 'latin1': case 'binary': return len case 'utf8': case 'utf-8': case undefined: return utf8ToBytes(string).length case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return len * 2 case 'hex': return len >>> 1 case 'base64': return base64ToBytes(string).length default: if (loweredCase) return utf8ToBytes(string).length // assume utf8 encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.byteLength = byteLength function slowToString (encoding, start, end) { var loweredCase = false // No need to verify that "this.length <= MAX_UINT32" since it's a read-only // property of a typed array. // This behaves neither like String nor Uint8Array in that we set start/end // to their upper/lower bounds if the value passed is out of range. // undefined is handled specially as per ECMA-262 6th Edition, // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. if (start === undefined || start < 0) { start = 0 } // Return early if start > this.length. Done here to prevent potential uint32 // coercion fail below. if (start > this.length) { return '' } if (end === undefined || end > this.length) { end = this.length } if (end <= 0) { return '' } // Force coersion to uint32. This will also coerce falsey/NaN values to 0. end >>>= 0 start >>>= 0 if (end <= start) { return '' } if (!encoding) encoding = 'utf8' while (true) { switch (encoding) { case 'hex': return hexSlice(this, start, end) case 'utf8': case 'utf-8': return utf8Slice(this, start, end) case 'ascii': return asciiSlice(this, start, end) case 'latin1': case 'binary': return latin1Slice(this, start, end) case 'base64': return base64Slice(this, start, end) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return utf16leSlice(this, start, end) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = (encoding + '').toLowerCase() loweredCase = true } } } // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect // Buffer instances. Buffer.prototype._isBuffer = true function swap (b, n, m) { var i = b[n] b[n] = b[m] b[m] = i } Buffer.prototype.swap16 = function swap16 () { var len = this.length if (len % 2 !== 0) { throw new RangeError('Buffer size must be a multiple of 16-bits') } for (var i = 0; i < len; i += 2) { swap(this, i, i + 1) } return this } Buffer.prototype.swap32 = function swap32 () { var len = this.length if (len % 4 !== 0) { throw new RangeError('Buffer size must be a multiple of 32-bits') } for (var i = 0; i < len; i += 4) { swap(this, i, i + 3) swap(this, i + 1, i + 2) } return this } Buffer.prototype.swap64 = function swap64 () { var len = this.length if (len % 8 !== 0) { throw new RangeError('Buffer size must be a multiple of 64-bits') } for (var i = 0; i < len; i += 8) { swap(this, i, i + 7) swap(this, i + 1, i + 6) swap(this, i + 2, i + 5) swap(this, i + 3, i + 4) } return this } Buffer.prototype.toString = function toString () { var length = this.length | 0 if (length === 0) return '' if (arguments.length === 0) return utf8Slice(this, 0, length) return slowToString.apply(this, arguments) } Buffer.prototype.equals = function equals (b) { if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') if (this === b) return true return Buffer.compare(this, b) === 0 } Buffer.prototype.inspect = function inspect () { var str = '' var max = exports.INSPECT_MAX_BYTES if (this.length > 0) { str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') if (this.length > max) str += ' ... ' } return '' } Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { if (!Buffer.isBuffer(target)) { throw new TypeError('Argument must be a Buffer') } if (start === undefined) { start = 0 } if (end === undefined) { end = target ? target.length : 0 } if (thisStart === undefined) { thisStart = 0 } if (thisEnd === undefined) { thisEnd = this.length } if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { throw new RangeError('out of range index') } if (thisStart >= thisEnd && start >= end) { return 0 } if (thisStart >= thisEnd) { return -1 } if (start >= end) { return 1 } start >>>= 0 end >>>= 0 thisStart >>>= 0 thisEnd >>>= 0 if (this === target) return 0 var x = thisEnd - thisStart var y = end - start var len = Math.min(x, y) var thisCopy = this.slice(thisStart, thisEnd) var targetCopy = target.slice(start, end) for (var i = 0; i < len; ++i) { if (thisCopy[i] !== targetCopy[i]) { x = thisCopy[i] y = targetCopy[i] break } } if (x < y) return -1 if (y < x) return 1 return 0 } // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, // OR the last index of `val` in `buffer` at offset <= `byteOffset`. // // Arguments: // - buffer - a Buffer to search // - val - a string, Buffer, or number // - byteOffset - an index into `buffer`; will be clamped to an int32 // - encoding - an optional encoding, relevant is val is a string // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { // Empty buffer means no match if (buffer.length === 0) return -1 // Normalize byteOffset if (typeof byteOffset === 'string') { encoding = byteOffset byteOffset = 0 } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff } else if (byteOffset < -0x80000000) { byteOffset = -0x80000000 } byteOffset = +byteOffset // Coerce to Number. if (isNaN(byteOffset)) { // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer byteOffset = dir ? 0 : (buffer.length - 1) } // Normalize byteOffset: negative offsets start from the end of the buffer if (byteOffset < 0) byteOffset = buffer.length + byteOffset if (byteOffset >= buffer.length) { if (dir) return -1 else byteOffset = buffer.length - 1 } else if (byteOffset < 0) { if (dir) byteOffset = 0 else return -1 } // Normalize val if (typeof val === 'string') { val = Buffer.from(val, encoding) } // Finally, search either indexOf (if dir is true) or lastIndexOf if (Buffer.isBuffer(val)) { // Special case: looking for empty string/buffer always fails if (val.length === 0) { return -1 } return arrayIndexOf(buffer, val, byteOffset, encoding, dir) } else if (typeof val === 'number') { val = val & 0xFF // Search for a byte value [0-255] if (Buffer.TYPED_ARRAY_SUPPORT && typeof Uint8Array.prototype.indexOf === 'function') { if (dir) { return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) } else { return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) } } return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) } throw new TypeError('val must be string, number or Buffer') } function arrayIndexOf (arr, val, byteOffset, encoding, dir) { var indexSize = 1 var arrLength = arr.length var valLength = val.length if (encoding !== undefined) { encoding = String(encoding).toLowerCase() if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { if (arr.length < 2 || val.length < 2) { return -1 } indexSize = 2 arrLength /= 2 valLength /= 2 byteOffset /= 2 } } function read (buf, i) { if (indexSize === 1) { return buf[i] } else { return buf.readUInt16BE(i * indexSize) } } var i if (dir) { var foundIndex = -1 for (i = byteOffset; i < arrLength; i++) { if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { if (foundIndex === -1) foundIndex = i if (i - foundIndex + 1 === valLength) return foundIndex * indexSize } else { if (foundIndex !== -1) i -= i - foundIndex foundIndex = -1 } } } else { if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength for (i = byteOffset; i >= 0; i--) { var found = true for (var j = 0; j < valLength; j++) { if (read(arr, i + j) !== read(val, j)) { found = false break } } if (found) return i } } return -1 } Buffer.prototype.includes = function includes (val, byteOffset, encoding) { return this.indexOf(val, byteOffset, encoding) !== -1 } Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, true) } Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, false) } function hexWrite (buf, string, offset, length) { offset = Number(offset) || 0 var remaining = buf.length - offset if (!length) { length = remaining } else { length = Number(length) if (length > remaining) { length = remaining } } // must be an even number of digits var strLen = string.length if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; ++i) { var parsed = parseInt(string.substr(i * 2, 2), 16) if (isNaN(parsed)) return i buf[offset + i] = parsed } return i } function utf8Write (buf, string, offset, length) { return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) } function asciiWrite (buf, string, offset, length) { return blitBuffer(asciiToBytes(string), buf, offset, length) } function latin1Write (buf, string, offset, length) { return asciiWrite(buf, string, offset, length) } function base64Write (buf, string, offset, length) { return blitBuffer(base64ToBytes(string), buf, offset, length) } function ucs2Write (buf, string, offset, length) { return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) } Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { encoding = 'utf8' length = this.length offset = 0 // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { encoding = offset length = this.length offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { offset = offset | 0 if (isFinite(length)) { length = length | 0 if (encoding === undefined) encoding = 'utf8' } else { encoding = length length = undefined } // legacy write(string, encoding, offset, length) - remove in v0.13 } else { throw new Error( 'Buffer.write(string, encoding, offset[, length]) is no longer supported' ) } var remaining = this.length - offset if (length === undefined || length > remaining) length = remaining if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('Attempt to write outside buffer bounds') } if (!encoding) encoding = 'utf8' var loweredCase = false for (;;) { switch (encoding) { case 'hex': return hexWrite(this, string, offset, length) case 'utf8': case 'utf-8': return utf8Write(this, string, offset, length) case 'ascii': return asciiWrite(this, string, offset, length) case 'latin1': case 'binary': return latin1Write(this, string, offset, length) case 'base64': // Warning: maxLength not taken into account in base64Write return base64Write(this, string, offset, length) case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': return ucs2Write(this, string, offset, length) default: if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) encoding = ('' + encoding).toLowerCase() loweredCase = true } } } Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } } function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { return base64.fromByteArray(buf) } else { return base64.fromByteArray(buf.slice(start, end)) } } function utf8Slice (buf, start, end) { end = Math.min(buf.length, end) var res = [] var i = start while (i < end) { var firstByte = buf[i] var codePoint = null var bytesPerSequence = (firstByte > 0xEF) ? 4 : (firstByte > 0xDF) ? 3 : (firstByte > 0xBF) ? 2 : 1 if (i + bytesPerSequence <= end) { var secondByte, thirdByte, fourthByte, tempCodePoint switch (bytesPerSequence) { case 1: if (firstByte < 0x80) { codePoint = firstByte } break case 2: secondByte = buf[i + 1] if ((secondByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) if (tempCodePoint > 0x7F) { codePoint = tempCodePoint } } break case 3: secondByte = buf[i + 1] thirdByte = buf[i + 2] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { codePoint = tempCodePoint } } break case 4: secondByte = buf[i + 1] thirdByte = buf[i + 2] fourthByte = buf[i + 3] if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { codePoint = tempCodePoint } } } } if (codePoint === null) { // we did not generate a valid codePoint so insert a // replacement char (U+FFFD) and advance only 1 byte codePoint = 0xFFFD bytesPerSequence = 1 } else if (codePoint > 0xFFFF) { // encode to utf16 (surrogate pair dance) codePoint -= 0x10000 res.push(codePoint >>> 10 & 0x3FF | 0xD800) codePoint = 0xDC00 | codePoint & 0x3FF } res.push(codePoint) i += bytesPerSequence } return decodeCodePointsArray(res) } // Based on http://stackoverflow.com/a/22747272/680742, the browser with // the lowest limit is Chrome, with 0x10000 args. // We go 1 magnitude less, for safety var MAX_ARGUMENTS_LENGTH = 0x1000 function decodeCodePointsArray (codePoints) { var len = codePoints.length if (len <= MAX_ARGUMENTS_LENGTH) { return String.fromCharCode.apply(String, codePoints) // avoid extra slice() } // Decode in chunks to avoid "call stack size exceeded". var res = '' var i = 0 while (i < len) { res += String.fromCharCode.apply( String, codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) ) } return res } function asciiSlice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i] & 0x7F) } return ret } function latin1Slice (buf, start, end) { var ret = '' end = Math.min(buf.length, end) for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i]) } return ret } function hexSlice (buf, start, end) { var len = buf.length if (!start || start < 0) start = 0 if (!end || end < 0 || end > len) end = len var out = '' for (var i = start; i < end; ++i) { out += toHex(buf[i]) } return out } function utf16leSlice (buf, start, end) { var bytes = buf.slice(start, end) var res = '' for (var i = 0; i < bytes.length; i += 2) { res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) } return res } Buffer.prototype.slice = function slice (start, end) { var len = this.length start = ~~start end = end === undefined ? len : ~~end if (start < 0) { start += len if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { end += len if (end < 0) end = 0 } else if (end > len) { end = len } if (end < start) end = start var newBuf if (Buffer.TYPED_ARRAY_SUPPORT) { newBuf = this.subarray(start, end) newBuf.__proto__ = Buffer.prototype } else { var sliceLen = end - start newBuf = new Buffer(sliceLen, undefined) for (var i = 0; i < sliceLen; ++i) { newBuf[i] = this[i + start] } } return newBuf } /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } return val } Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { checkOffset(offset, byteLength, this.length) } var val = this[offset + --byteLength] var mul = 1 while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul } return val } Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) return this[offset] } Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return this[offset] | (this[offset + 1] << 8) } Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) return (this[offset] << 8) | this[offset + 1] } Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) } Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) } Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var val = this[offset] var mul = 1 var i = 0 while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) checkOffset(offset, byteLength, this.length) var i = byteLength var mul = 1 var val = this[offset + --i] while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul } mul *= 0x80 if (val >= mul) val -= Math.pow(2, 8 * byteLength) return val } Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { if (!noAssert) checkOffset(offset, 1, this.length) if (!(this[offset] & 0x80)) return (this[offset]) return ((0xff - this[offset] + 1) * -1) } Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset] | (this[offset + 1] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 2, this.length) var val = this[offset + 1] | (this[offset] << 8) return (val & 0x8000) ? val | 0xFFFF0000 : val } Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) } Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) } Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, true, 23, 4) } Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 4, this.length) return ieee754.read(this, offset, false, 23, 4) } Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, true, 52, 8) } Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { if (!noAssert) checkOffset(offset, 8, this.length) return ieee754.read(this, offset, false, 52, 8) } function checkInt (buf, value, offset, ext, max, min) { if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') if (offset + ext > buf.length) throw new RangeError('Index out of range') } Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) } var mul = 1 var i = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 byteLength = byteLength | 0 if (!noAssert) { var maxBytes = Math.pow(2, 8 * byteLength) - 1 checkInt(this, value, offset, byteLength, maxBytes, 0) } var i = byteLength - 1 var mul = 1 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength } Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) this[offset] = (value & 0xff) return offset + 1 } function objectWriteUInt16 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 } } Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } function objectWriteUInt32 (buf, value, offset, littleEndian) { if (value < 0) value = 0xffffffff + value + 1 for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset + 3] = (value >>> 24) this[offset + 2] = (value >>> 16) this[offset + 1] = (value >>> 8) this[offset] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = 0 var mul = 1 var sub = 0 this[offset] = value & 0xFF while (++i < byteLength && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { sub = 1 } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { value = +value offset = offset | 0 if (!noAssert) { var limit = Math.pow(2, 8 * byteLength - 1) checkInt(this, value, offset, byteLength, limit - 1, -limit) } var i = byteLength - 1 var mul = 1 var sub = 0 this[offset + i] = value & 0xFF while (--i >= 0 && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { sub = 1 } this[offset + i] = ((value / mul) >> 0) - sub & 0xFF } return offset + byteLength } Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) if (value < 0) value = 0xff + value + 1 this[offset] = (value & 0xff) return offset + 1 } Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 } Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 8) this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 } Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value & 0xff) this[offset + 1] = (value >>> 8) this[offset + 2] = (value >>> 16) this[offset + 3] = (value >>> 24) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 } Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { value = +value offset = offset | 0 if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) if (value < 0) value = 0xffffffff + value + 1 if (Buffer.TYPED_ARRAY_SUPPORT) { this[offset] = (value >>> 24) this[offset + 1] = (value >>> 16) this[offset + 2] = (value >>> 8) this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 } function checkIEEE754 (buf, value, offset, ext, max, min) { if (offset + ext > buf.length) throw new RangeError('Index out of range') if (offset < 0) throw new RangeError('Index out of range') } function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } ieee754.write(buf, value, offset, littleEndian, 23, 4) return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) } Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) } function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } ieee754.write(buf, value, offset, littleEndian, 52, 8) return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) } Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) } // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { if (!start) start = 0 if (!end && end !== 0) end = this.length if (targetStart >= target.length) targetStart = target.length if (!targetStart) targetStart = 0 if (end > 0 && end < start) end = start // Copy 0 bytes; we're done if (end === start) return 0 if (target.length === 0 || this.length === 0) return 0 // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') if (end < 0) throw new RangeError('sourceEnd out of bounds') // Are we oob? if (end > this.length) end = this.length if (target.length - targetStart < end - start) { end = target.length - targetStart + start } var len = end - start var i if (this === target && start < targetStart && targetStart < end) { // descending copy from end for (i = len - 1; i >= 0; --i) { target[i + targetStart] = this[i + start] } } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { // ascending copy from start for (i = 0; i < len; ++i) { target[i + targetStart] = this[i + start] } } else { Uint8Array.prototype.set.call( target, this.subarray(start, start + len), targetStart ) } return len } // Usage: // buffer.fill(number[, offset[, end]]) // buffer.fill(buffer[, offset[, end]]) // buffer.fill(string[, offset[, end]][, encoding]) Buffer.prototype.fill = function fill (val, start, end, encoding) { // Handle string cases: if (typeof val === 'string') { if (typeof start === 'string') { encoding = start start = 0 end = this.length } else if (typeof end === 'string') { encoding = end end = this.length } if (val.length === 1) { var code = val.charCodeAt(0) if (code < 256) { val = code } } if (encoding !== undefined && typeof encoding !== 'string') { throw new TypeError('encoding must be a string') } if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { throw new TypeError('Unknown encoding: ' + encoding) } } else if (typeof val === 'number') { val = val & 255 } // Invalid ranges are not set to a default, so can range check early. if (start < 0 || this.length < start || this.length < end) { throw new RangeError('Out of range index') } if (end <= start) { return this } start = start >>> 0 end = end === undefined ? this.length : end >>> 0 if (!val) val = 0 var i if (typeof val === 'number') { for (i = start; i < end; ++i) { this[i] = val } } else { var bytes = Buffer.isBuffer(val) ? val : utf8ToBytes(new Buffer(val, encoding).toString()) var len = bytes.length for (i = 0; i < end - start; ++i) { this[i + start] = bytes[i % len] } } return this } // HELPER FUNCTIONS // ================ var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not str = stringtrim(str).replace(INVALID_BASE64_RE, '') // Node converts strings with length < 2 to '' if (str.length < 2) return '' // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' } return str } function stringtrim (str) { if (str.trim) return str.trim() return str.replace(/^\s+|\s+$/g, '') } function toHex (n) { if (n < 16) return '0' + n.toString(16) return n.toString(16) } function utf8ToBytes (string, units) { units = units || Infinity var codePoint var length = string.length var leadSurrogate = null var bytes = [] for (var i = 0; i < length; ++i) { codePoint = string.charCodeAt(i) // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { // last char was a lead if (!leadSurrogate) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } else if (i + 1 === length) { // unpaired lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) continue } // valid lead leadSurrogate = codePoint continue } // 2 leads in a row if (codePoint < 0xDC00) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) leadSurrogate = codePoint continue } // valid surrogate pair codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 } else if (leadSurrogate) { // valid bmp char, but last char was a lead if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) } leadSurrogate = null // encode utf8 if (codePoint < 0x80) { if ((units -= 1) < 0) break bytes.push(codePoint) } else if (codePoint < 0x800) { if ((units -= 2) < 0) break bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x10000) { if ((units -= 3) < 0) break bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x110000) { if ((units -= 4) < 0) break bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else { throw new Error('Invalid code point') } } return bytes } function asciiToBytes (str) { var byteArray = [] for (var i = 0; i < str.length; ++i) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) } return byteArray } function utf16leToBytes (str, units) { var c, hi, lo var byteArray = [] for (var i = 0; i < str.length; ++i) { if ((units -= 2) < 0) break c = str.charCodeAt(i) hi = c >> 8 lo = c % 256 byteArray.push(lo) byteArray.push(hi) } return byteArray } function base64ToBytes (str) { return base64.toByteArray(base64clean(str)) } function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; ++i) { if ((i + offset >= dst.length) || (i >= src.length)) break dst[i + offset] = src[i] } return i } function isnan (val) { return val !== val // eslint-disable-line no-self-compare } /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15).Buffer, __webpack_require__(61))) /***/ }, /* 16 */ /***/ function(module, exports) { // shim for using process in browser var process = module.exports = {}; // cached from whatever global is present so that test runners that stub it // don't break things. But we need to wrap it in a try catch in case it is // wrapped in strict mode code which doesn't define any globals. It's inside a // function because try/catches deoptimize in certain engines. var cachedSetTimeout; var cachedClearTimeout; function defaultSetTimout() { throw new Error('setTimeout has not been defined'); } function defaultClearTimeout () { throw new Error('clearTimeout has not been defined'); } (function () { try { if (typeof setTimeout === 'function') { cachedSetTimeout = setTimeout; } else { cachedSetTimeout = defaultSetTimout; } } catch (e) { cachedSetTimeout = defaultSetTimout; } try { if (typeof clearTimeout === 'function') { cachedClearTimeout = clearTimeout; } else { cachedClearTimeout = defaultClearTimeout; } } catch (e) { cachedClearTimeout = defaultClearTimeout; } } ()) function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations return setTimeout(fun, 0); } // if setTimeout wasn't available but was latter defined if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { cachedSetTimeout = setTimeout; return setTimeout(fun, 0); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedSetTimeout(fun, 0); } catch(e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedSetTimeout.call(null, fun, 0); } catch(e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error return cachedSetTimeout.call(this, fun, 0); } } } function runClearTimeout(marker) { if (cachedClearTimeout === clearTimeout) { //normal enviroments in sane situations return clearTimeout(marker); } // if clearTimeout wasn't available but was latter defined if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { cachedClearTimeout = clearTimeout; return clearTimeout(marker); } try { // when when somebody has screwed with setTimeout but no I.E. maddness return cachedClearTimeout(marker); } catch (e){ try { // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally return cachedClearTimeout.call(null, marker); } catch (e){ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. // Some versions of I.E. have different rules for clearTimeout vs setTimeout return cachedClearTimeout.call(this, marker); } } } var queue = []; var draining = false; var currentQueue; var queueIndex = -1; function cleanUpNextTick() { if (!draining || !currentQueue) { return; } draining = false; if (currentQueue.length) { queue = currentQueue.concat(queue); } else { queueIndex = -1; } if (queue.length) { drainQueue(); } } function drainQueue() { if (draining) { return; } var timeout = runTimeout(cleanUpNextTick); draining = true; var len = queue.length; while(len) { currentQueue = queue; queue = []; while (++queueIndex < len) { if (currentQueue) { currentQueue[queueIndex].run(); } } queueIndex = -1; len = queue.length; } currentQueue = null; draining = false; runClearTimeout(timeout); } process.nextTick = function (fun) { var args = new Array(arguments.length - 1); if (arguments.length > 1) { for (var i = 1; i < arguments.length; i++) { args[i - 1] = arguments[i]; } } queue.push(new Item(fun, args)); if (queue.length === 1 && !draining) { runTimeout(drainQueue); } }; // v8 likes predictible objects function Item(fun, array) { this.fun = fun; this.array = array; } Item.prototype.run = function () { this.fun.apply(null, this.array); }; process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; process.version = ''; // empty string to avoid regexp issues process.versions = {}; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); }; process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; process.umask = function() { return 0; }; /***/ }, /* 17 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); /** * The final evaluated permissions for a member in a channel */ class EvaluatedPermissions { constructor(member, raw) { /** * The member this permissions refer to * @type {GuildMember} */ this.member = member; /** * A number representing the packed permissions * @type {number} */ this.raw = raw; } /** * Get an object mapping permission name, e.g. `READ_MESSAGES` to a boolean - whether the user * can perform this or not. * @returns {Object} */ serialize() { const serializedPermissions = {}; for (const permissionName in Constants.PermissionFlags) { serializedPermissions[permissionName] = this.hasPermission(permissionName); } return serializedPermissions; } /** * Checks whether the user has a certain permission, e.g. `READ_MESSAGES`. * @param {PermissionResolvable} permission The permission to check for * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permission * @returns {boolean} */ hasPermission(permission, explicit = false) { permission = this.member.client.resolver.resolvePermission(permission); if (!explicit && (this.raw & Constants.PermissionFlags.ADMINISTRATOR) > 0) return true; return (this.raw & permission) > 0; } /** * Checks whether the user has all specified permissions. * @param {PermissionResolvable[]} permissions The permissions to check for * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions * @returns {boolean} */ hasPermissions(permissions, explicit = false) { return permissions.every(p => this.hasPermission(p, explicit)); } /** * Checks whether the user has all specified permissions, and lists any missing permissions. * @param {PermissionResolvable[]} permissions The permissions to check for * @param {boolean} [explicit=false] Whether to require the user to explicitly have the exact permissions * @returns {PermissionResolvable[]} */ missingPermissions(permissions, explicit = false) { return permissions.filter(p => !this.hasPermission(p, explicit)); } } module.exports = EvaluatedPermissions; /***/ }, /* 18 */ /***/ function(module, exports, __webpack_require__) { const User = __webpack_require__(5); const Role = __webpack_require__(7); const Emoji = __webpack_require__(9); const Presence = __webpack_require__(6).Presence; const GuildMember = __webpack_require__(12); const Constants = __webpack_require__(0); const Collection = __webpack_require__(3); const cloneObject = __webpack_require__(4); const arraysEqual = __webpack_require__(24); /** * Represents a guild (or a server) on Discord. * It's recommended to see if a guild is available before performing operations or reading data from it. You can * check this with `guild.available`. */ class Guild { constructor(client, data) { /** * The Client that created the instance of the the Guild. * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * A collection of members that are in this guild. The key is the member's ID, the value is the member. * @type {Collection} */ this.members = new Collection(); /** * A collection of channels that are in this guild. The key is the channel's ID, the value is the channel. * @type {Collection} */ this.channels = new Collection(); /** * A collection of roles that are in this guild. The key is the role's ID, the value is the role. * @type {Collection} */ this.roles = new Collection(); if (!data) return; if (data.unavailable) { /** * Whether the guild is available to access. If it is not available, it indicates a server outage. * @type {boolean} */ this.available = false; /** * The Unique ID of the Guild, useful for comparisons. * @type {string} */ this.id = data.id; } else { this.available = true; this.setup(data); } } /** * Sets up the Guild * @param {*} data The raw data of the guild * @private */ setup(data) { /** * The name of the guild * @type {string} */ this.name = data.name; /** * The hash of the guild icon, or null if there is no icon. * @type {?string} */ this.icon = data.icon; /** * The hash of the guild splash image, or null if no splash (VIP only) * @type {?string} */ this.splash = data.splash; /** * The region the guild is located in * @type {string} */ this.region = data.region; /** * The full amount of members in this guild as of `READY` * @type {number} */ this.memberCount = data.member_count || this.memberCount; /** * Whether the guild is "large" (has more than 250 members) * @type {boolean} */ this.large = data.large || this.large; /** * A collection of presences in this guild * @type {Collection} */ this.presences = new Collection(); /** * An array of guild features. * @type {Object[]} */ this.features = data.features; /** * A collection of emojis that are in this guild. The key is the emoji's ID, the value is the emoji. * @type {Collection} */ this.emojis = new Collection(); for (const emoji of data.emojis) this.emojis.set(emoji.id, new Emoji(this, emoji)); /** * The time in seconds before a user is counted as "away from keyboard". * @type {?number} */ this.afkTimeout = data.afk_timeout; /** * The ID of the voice channel where AFK members are moved. * @type {?string} */ this.afkChannelID = data.afk_channel_id; /** * Whether embedded images are enabled on this guild. * @type {boolean} */ this.embedEnabled = data.embed_enabled; /** * The verification level of the guild. * @type {number} */ this.verificationLevel = data.verification_level; /** * The timestamp the client user joined the guild at * @type {number} */ this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp; this.id = data.id; this.available = !data.unavailable; this.features = data.features || this.features || []; if (data.members) { this.members.clear(); for (const guildUser of data.members) this._addMember(guildUser, false); } if (data.owner_id) { /** * The user ID of this guild's owner. * @type {string} */ this.ownerID = data.owner_id; } if (data.channels) { this.channels.clear(); for (const channel of data.channels) this.client.dataManager.newChannel(channel, this); } if (data.roles) { this.roles.clear(); for (const role of data.roles) { const newRole = new Role(this, role); this.roles.set(newRole.id, newRole); } } if (data.presences) { for (const presence of data.presences) { this._setPresence(presence.user.id, presence); } } this._rawVoiceStates = new Collection(); if (data.voice_states) { for (const voiceState of data.voice_states) { this._rawVoiceStates.set(voiceState.user_id, voiceState); const member = this.members.get(voiceState.user_id); if (member) { member.serverMute = voiceState.mute; member.serverDeaf = voiceState.deaf; member.selfMute = voiceState.self_mute; member.selfDeaf = voiceState.self_deaf; member.voiceSessionID = voiceState.session_id; member.voiceChannelID = voiceState.channel_id; this.channels.get(voiceState.channel_id).members.set(member.user.id, member); } } } } /** * The timestamp the guild was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the guild was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * The time the client user joined the guild * @type {Date} * @readonly */ get joinedAt() { return new Date(this.joinedTimestamp); } /** * Gets the URL to this guild's icon (if it has one, otherwise it returns null) * @type {?string} * @readonly */ get iconURL() { if (!this.icon) return null; return Constants.Endpoints.guildIcon(this.id, this.icon); } /** * The owner of the guild * @type {GuildMember} * @readonly */ get owner() { return this.members.get(this.ownerID); } /** * If the client is connected to any voice channel in this guild, this will be the relevant VoiceConnection. * @type {?VoiceConnection} * @readonly */ get voiceConnection() { if (this.client.browser) return null; return this.client.voice.connections.get(this.id) || null; } /** * The `#general` GuildChannel of the server. * @type {GuildChannel} * @readonly */ get defaultChannel() { return this.channels.get(this.id); } /** * Returns the GuildMember form of a User object, if the user is present in the guild. * @param {UserResolvable} user The user that you want to obtain the GuildMember of * @returns {?GuildMember} * @example * // get the guild member of a user * const member = guild.member(message.author); */ member(user) { return this.client.resolver.resolveGuildMember(this, user); } /** * Fetch a collection of banned users in this guild. * @returns {Promise>} */ fetchBans() { return this.client.rest.methods.getGuildBans(this); } /** * Fetch a collection of invites to this guild. Resolves with a collection mapping invites by their codes. * @returns {Promise>} */ fetchInvites() { return this.client.rest.methods.getGuildInvites(this); } /** * Fetch all webhooks for the guild. * @returns {Collection} */ fetchWebhooks() { return this.client.rest.methods.getGuildWebhooks(this); } /** * Fetch a single guild member from a user. * @param {UserResolvable} user The user to fetch the member for * @returns {Promise} */ fetchMember(user) { if (this._fetchWaiter) return Promise.reject(new Error('Already fetching guild members.')); user = this.client.resolver.resolveUser(user); if (!user) return Promise.reject(new Error('User is not cached. Use Client.fetchUser first.')); if (this.members.has(user.id)) return Promise.resolve(this.members.get(user.id)); return this.client.rest.methods.getGuildMember(this, user); } /** * Fetches all the members in the guild, even if they are offline. If the guild has less than 250 members, * this should not be necessary. * @param {string} [query=''] An optional query to provide when fetching members * @returns {Promise} */ fetchMembers(query = '') { return new Promise((resolve, reject) => { if (this._fetchWaiter) throw new Error('Already fetching guild members in ${this.id}.'); if (this.memberCount === this.members.size) { resolve(this); return; } this._fetchWaiter = resolve; this.client.ws.send({ op: Constants.OPCodes.REQUEST_GUILD_MEMBERS, d: { guild_id: this.id, query, limit: 0, }, }); this._checkChunks(); this.client.setTimeout(() => reject(new Error('Members didn\'t arrive in time.')), 120 * 1000); }); } /** * The data for editing a guild * @typedef {Object} GuildEditData * @property {string} [name] The name of the guild * @property {string} [region] The region of the guild * @property {number} [verificationLevel] The verification level of the guild * @property {ChannelResolvable} [afkChannel] The AFK channel of the guild * @property {number} [afkTimeout] The AFK timeout of the guild * @property {Base64Resolvable} [icon] The icon of the guild * @property {GuildMemberResolvable} [owner] The owner of the guild * @property {Base64Resolvable} [splash] The splash screen of the guild */ /** * Updates the Guild with new information - e.g. a new name. * @param {GuildEditData} data The data to update the guild with * @returns {Promise} * @example * // set the guild name and region * guild.edit({ * name: 'Discord Guild', * region: 'london', * }) * .then(updated => console.log(`New guild name ${updated.name} in region ${updated.region}`)) * .catch(console.error); */ edit(data) { return this.client.rest.methods.updateGuild(this, data); } /** * Edit the name of the guild. * @param {string} name The new name of the guild * @returns {Promise} * @example * // edit the guild name * guild.setName('Discord Guild') * .then(updated => console.log(`Updated guild name to ${guild.name}`)) * .catch(console.error); */ setName(name) { return this.edit({ name }); } /** * Edit the region of the guild. * @param {string} region The new region of the guild. * @returns {Promise} * @example * // edit the guild region * guild.setRegion('london') * .then(updated => console.log(`Updated guild region to ${guild.region}`)) * .catch(console.error); */ setRegion(region) { return this.edit({ region }); } /** * Edit the verification level of the guild. * @param {number} verificationLevel The new verification level of the guild * @returns {Promise} * @example * // edit the guild verification level * guild.setVerificationLevel(1) * .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`)) * .catch(console.error); */ setVerificationLevel(verificationLevel) { return this.edit({ verificationLevel }); } /** * Edit the AFK channel of the guild. * @param {ChannelResolvable} afkChannel The new AFK channel * @returns {Promise} * @example * // edit the guild AFK channel * guild.setAFKChannel(channel) * .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel}`)) * .catch(console.error); */ setAFKChannel(afkChannel) { return this.edit({ afkChannel }); } /** * Edit the AFK timeout of the guild. * @param {number} afkTimeout The time in seconds that a user must be idle to be considered AFK * @returns {Promise} * @example * // edit the guild AFK channel * guild.setAFKTimeout(60) * .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`)) * .catch(console.error); */ setAFKTimeout(afkTimeout) { return this.edit({ afkTimeout }); } /** * Set a new guild icon. * @param {Base64Resolvable} icon The new icon of the guild * @returns {Promise} * @example * // edit the guild icon * guild.setIcon(fs.readFileSync('./icon.png')) * .then(updated => console.log('Updated the guild icon')) * .catch(console.error); */ setIcon(icon) { return this.edit({ icon }); } /** * Sets a new owner of the guild. * @param {GuildMemberResolvable} owner The new owner of the guild * @returns {Promise} * @example * // edit the guild owner * guild.setOwner(guilds.members[0]) * .then(updated => console.log(`Updated the guild owner to ${updated.owner.username}`)) * .catch(console.error); */ setOwner(owner) { return this.edit({ owner }); } /** * Set a new guild splash screen. * @param {Base64Resolvable} splash The new splash screen of the guild * @returns {Promise} * @example * // edit the guild splash * guild.setIcon(fs.readFileSync('./splash.png')) * .then(updated => console.log('Updated the guild splash')) * .catch(console.error); */ setSplash(splash) { return this.edit({ splash }); } /** * Bans a user from the guild. * @param {UserResolvable} user The user to ban * @param {number} [deleteDays=0] The amount of days worth of messages from this user that should * also be deleted. Between `0` and `7`. * @returns {Promise} Result object will be resolved as specifically as possible. * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot * be resolved, the user ID will be the result. * @example * // ban a user * guild.ban('123123123123'); */ ban(user, deleteDays = 0) { return this.client.rest.methods.banGuildMember(this, user, deleteDays); } /** * Unbans a user from the guild. * @param {UserResolvable} user The user to unban * @returns {Promise} * @example * // unban a user * guild.unban('123123123123') * .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`)) * .catch(reject); */ unban(user) { return this.client.rest.methods.unbanGuildMember(this, user); } /** * Prunes members from the guild based on how long they have been inactive. * @param {number} days Number of days of inactivity required to kick * @param {boolean} [dry=false] If true, will return number of users that will be kicked, without actually doing it * @returns {Promise} The number of members that were/will be kicked * @example * // see how many members will be pruned * guild.pruneMembers(12, true) * .then(pruned => console.log(`This will prune ${pruned} people!`); * .catch(console.error); * @example * // actually prune the members * guild.pruneMembers(12) * .then(pruned => console.log(`I just pruned ${pruned} people!`); * .catch(console.error); */ pruneMembers(days, dry = false) { if (typeof days !== 'number') throw new TypeError('Days must be a number.'); return this.client.rest.methods.pruneGuildMembers(this, days, dry); } /** * Syncs this guild (already done automatically every 30 seconds). * This is only available when using a user account. */ sync() { if (!this.client.user.bot) this.client.syncGuilds([this]); } /** * Creates a new channel in the guild. * @param {string} name The name of the new channel * @param {string} type The type of the new channel, either `text` or `voice` * @returns {Promise} * @example * // create a new text channel * guild.createChannel('new-general', 'text') * .then(channel => console.log(`Created new channel ${channel}`)) * .catch(console.error); */ createChannel(name, type) { return this.client.rest.methods.createChannel(this, name, type); } /** * Creates a new role in the guild, and optionally updates it with the given information. * @param {RoleData} [data] The data to update the role with * @returns {Promise} * @example * // create a new role * guild.createRole() * .then(role => console.log(`Created role ${role}`)) * .catch(console.error); * @example * // create a new role with data * guild.createRole({ name: 'Super Cool People' }) * .then(role => console.log(`Created role ${role}`)) * .catch(console.error) */ createRole(data) { const create = this.client.rest.methods.createGuildRole(this); if (!data) return create; return create.then(role => role.edit(data)); } /** * Creates a new custom emoji in the guild. * @param {BufferResolvable} attachment The image for the emoji. * @param {string} name The name for the emoji. * @returns {Promise} The created emoji. * @example * // create a new emoji from a url * guild.createEmoji('https://i.imgur.com/w3duR07.png', 'rip') * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`)) * .catch(console.error); * @example * // create a new emoji from a file on your computer * guild.createEmoji('./memes/banana.png', 'banana') * .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`)) * .catch(console.error); */ createEmoji(attachment, name) { return new Promise(resolve => { if (attachment.startsWith('data:')) { resolve(this.client.rest.methods.createEmoji(this, attachment, name)); } else { this.client.resolver.resolveBuffer(attachment).then(data => resolve(this.client.rest.methods.createEmoji(this, data, name)) ); } }); } /** * Delete an emoji. * @param {Emoji|string} emoji The emoji to delete. * @returns {Promise} */ deleteEmoji(emoji) { if (!(emoji instanceof Emoji)) emoji = this.emojis.get(emoji); return this.client.rest.methods.deleteEmoji(emoji); } /** * Causes the Client to leave the guild. * @returns {Promise} * @example * // leave a guild * guild.leave() * .then(g => console.log(`Left the guild ${g}`)) * .catch(console.error); */ leave() { return this.client.rest.methods.leaveGuild(this); } /** * Causes the Client to delete the guild. * @returns {Promise} * @example * // delete a guild * guild.delete() * .then(g => console.log(`Deleted the guild ${g}`)) * .catch(console.error); */ delete() { return this.client.rest.methods.deleteGuild(this); } /** * Set the position of a role in this guild * @param {string|Role} role the role to edit, can be a role object or a role ID. * @param {number} position the new position of the role * @returns {Promise} */ setRolePosition(role, position) { if (role instanceof Role) { role = role.id; } else if (typeof role !== 'string') { return Promise.reject(new Error('Supplied role is not a role or string')); } position = Number(position); if (isNaN(position)) { return Promise.reject(new Error('Supplied position is not a number')); } const updatedRoles = this.roles.array().map(r => ({ id: r.id, position: r.id === role ? position : r.position < position ? r.position : r.position + 1, })); return this.client.rest.methods.setRolePositions(this.id, updatedRoles); } /** * 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 * what most users need. * @param {Guild} guild The guild to compare * @returns {boolean} */ equals(guild) { let equal = guild && this.id === guild.id && this.available === !guild.unavailable && this.splash === guild.splash && this.region === guild.region && this.name === guild.name && this.memberCount === guild.member_count && this.large === guild.large && this.icon === guild.icon && arraysEqual(this.features, guild.features) && this.ownerID === guild.owner_id && this.verificationLevel === guild.verification_level && this.embedEnabled === guild.embed_enabled; if (equal) { if (this.embedChannel) { if (this.embedChannel.id !== guild.embed_channel_id) equal = false; } else if (guild.embed_channel_id) { equal = false; } } return equal; } /** * When concatenated with a string, this automatically concatenates the guild's name instead of the Guild object. * @returns {string} * @example * // logs: Hello from My Guild! * console.log(`Hello from ${guild}!`); * @example * // logs: Hello from My Guild! * console.log(`Hello from ' + guild + '!'); */ toString() { return this.name; } _addMember(guildUser, emitEvent = true) { const existing = this.members.has(guildUser.user.id); if (!(guildUser.user instanceof User)) guildUser.user = this.client.dataManager.newUser(guildUser.user); guildUser.joined_at = guildUser.joined_at || 0; const member = new GuildMember(this, guildUser); this.members.set(member.id, member); if (this._rawVoiceStates && this._rawVoiceStates.get(member.user.id)) { const voiceState = this._rawVoiceStates.get(member.user.id); member.serverMute = voiceState.mute; member.serverDeaf = voiceState.deaf; member.selfMute = voiceState.self_mute; member.selfDeaf = voiceState.self_deaf; member.voiceSessionID = voiceState.session_id; member.voiceChannelID = voiceState.channel_id; this.channels.get(voiceState.channel_id).members.set(member.user.id, member); } /** * Emitted whenever a user joins a guild. * @event Client#guildMemberAdd * @param {GuildMember} member The member that has joined a guild */ if (this.client.ws.status === Constants.Status.READY && emitEvent && !existing) { this.client.emit(Constants.Events.GUILD_MEMBER_ADD, member); } this._checkChunks(); return member; } _updateMember(member, data) { const oldMember = cloneObject(member); if (data.roles) member._roles = data.roles; if (typeof data.nick !== 'undefined') member.nickname = data.nick; const notSame = member.nickname !== oldMember.nickname || !arraysEqual(member._roles, oldMember._roles); if (this.client.ws.status === Constants.Status.READY && notSame) { /** * Emitted whenever a guild member changes - i.e. new role, removed role, nickname * @event Client#guildMemberUpdate * @param {GuildMember} oldMember The member before the update * @param {GuildMember} newMember The member after the update */ this.client.emit(Constants.Events.GUILD_MEMBER_UPDATE, oldMember, member); } return { old: oldMember, mem: member, }; } _removeMember(guildMember) { this.members.delete(guildMember.id); this._checkChunks(); } _memberSpeakUpdate(user, speaking) { const member = this.members.get(user); if (member && member.speaking !== speaking) { member.speaking = speaking; /** * Emitted once a guild member starts/stops speaking * @event Client#guildMemberSpeaking * @param {GuildMember} member The member that started/stopped speaking * @param {boolean} speaking Whether or not the member is speaking */ this.client.emit(Constants.Events.GUILD_MEMBER_SPEAKING, member, speaking); } } _setPresence(id, presence) { if (this.presences.get(id)) { this.presences.get(id).update(presence); return; } this.presences.set(id, new Presence(presence)); } _checkChunks() { if (this._fetchWaiter) { if (this.members.size === this.memberCount) { this._fetchWaiter(this); this._fetchWaiter = null; } } } } module.exports = Guild; /***/ }, /* 19 */ /***/ function(module, exports) { /** * Represents a limited emoji set used for both custom and unicode emojis. Custom emojis * will use this class opposed to the Emoji class when the client doesn't know enough * information about them. */ class ReactionEmoji { constructor(reaction, name, id) { /** * The message reaction this emoji refers to * @type {MessageReaction} */ this.reaction = reaction; /** * The name of this reaction emoji. * @type {string} */ this.name = name; /** * The ID of this reaction emoji. * @type {string} */ this.id = id; } /** * The identifier of this emoji, used for message reactions * @readonly * @type {string} */ get identifier() { if (this.id) return `${this.name}:${this.id}`; return encodeURIComponent(this.name); } /** * Creates the text required to form a graphical emoji on Discord. * @example * // send the emoji used in a reaction to the channel the reaction is part of * reaction.message.channel.sendMessage(`The emoji used is ${reaction.emoji}`); * @returns {string} */ toString() { return this.id ? `<:${this.name}:${this.id}>` : this.name; } } module.exports = ReactionEmoji; /***/ }, /* 20 */ /***/ function(module, exports, __webpack_require__) { const path = __webpack_require__(22); const escapeMarkdown = __webpack_require__(14); /** * Represents a webhook */ class Webhook { constructor(client, dataOrID, token) { if (client) { /** * The Client that instantiated the Webhook * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); if (dataOrID) this.setup(dataOrID); } else { this.id = dataOrID; this.token = token; this.client = this; } } setup(data) { /** * The name of the webhook * @type {string} */ this.name = data.name; /** * The token for the webhook * @type {string} */ this.token = data.token; /** * The avatar for the webhook * @type {string} */ this.avatar = data.avatar; /** * The ID of the webhook * @type {string} */ this.id = data.id; /** * The guild the webhook belongs to * @type {string} */ this.guildID = data.guild_id; /** * The channel the webhook belongs to * @type {string} */ this.channelID = data.channel_id; /** * The owner of the webhook * @type {User} */ if (data.user) this.owner = data.user; } /** * Options that can be passed into sendMessage, sendTTSMessage, sendFile, sendCode * @typedef {Object} WebhookMessageOptions * @property {boolean} [tts=false] Whether or not the message should be spoken aloud * @property {boolean} [disableEveryone=this.options.disableEveryone] Whether or not @everyone and @here * should be replaced with plain-text */ /** * Send a message with this webhook * @param {StringResolvable} content The content to send. * @param {WebhookMessageOptions} [options={}] The options to provide. * @returns {Promise} * @example * // send a message * webhook.sendMessage('hello!') * .then(message => console.log(`Sent message: ${message.content}`)) * .catch(console.error); */ sendMessage(content, options = {}) { return this.client.rest.methods.sendWebhookMessage(this, content, options); } /** * Send a raw slack message with this webhook * @param {Object} body The raw body to send. * @returns {Promise} * @example * // send a slack message * webhook.sendSlackMessage({ * 'username': 'Wumpus', * 'attachments': [{ * 'pretext': 'this looks pretty cool', * 'color': '#F0F', * 'footer_icon': 'http://snek.s3.amazonaws.com/topSnek.png', * 'footer': 'Powered by sneks', * 'ts': new Date().getTime() / 1000 * }] * }).catch(console.error); */ sendSlackMessage(body) { return this.client.rest.methods.sendSlackWebhookMessage(this, body); } /** * Send a text-to-speech message with this webhook * @param {StringResolvable} content The content to send * @param {WebhookMessageOptions} [options={}] The options to provide * @returns {Promise} * @example * // send a TTS message * webhook.sendTTSMessage('hello!') * .then(message => console.log(`Sent tts message: ${message.content}`)) * .catch(console.error); */ sendTTSMessage(content, options = {}) { Object.assign(options, { tts: true }); return this.client.rest.methods.sendWebhookMessage(this, content, options); } /** * Send a file with this webhook * @param {BufferResolvable} attachment The file to send * @param {string} [fileName="file.jpg"] The name and extension of the file * @param {StringResolvable} [content] Text message to send with the attachment * @param {WebhookMessageOptions} [options] The options to provide * @returns {Promise} */ sendFile(attachment, fileName, content, options = {}) { if (!fileName) { if (typeof attachment === 'string') { fileName = path.basename(attachment); } else if (attachment && attachment.path) { fileName = path.basename(attachment.path); } else { fileName = 'file.jpg'; } } return this.client.resolver.resolveBuffer(attachment).then(file => this.client.rest.methods.sendWebhookMessage(this, content, options, { file, name: fileName, }) ); } /** * Send a code block with this webhook * @param {string} lang Language for the code block * @param {StringResolvable} content Content of the code block * @param {WebhookMessageOptions} options The options to provide * @returns {Promise} */ sendCode(lang, content, options = {}) { if (options.split) { if (typeof options.split !== 'object') options.split = {}; if (!options.split.prepend) options.split.prepend = `\`\`\`${lang || ''}\n`; if (!options.split.append) options.split.append = '\n```'; } content = escapeMarkdown(this.client.resolver.resolveString(content), true); return this.sendMessage(`\`\`\`${lang || ''}\n${content}\n\`\`\``, options); } /** * Edit the webhook. * @param {string} name The new name for the Webhook * @param {BufferResolvable} avatar The new avatar for the Webhook. * @returns {Promise} */ edit(name = this.name, avatar) { if (avatar) { return this.client.resolver.resolveBuffer(avatar).then(file => { const dataURI = this.client.resolver.resolveBase64(file); return this.client.rest.methods.editWebhook(this, name, dataURI); }); } return this.client.rest.methods.editWebhook(this, name).then(data => { this.setup(data); return this; }); } /** * Delete the webhook * @returns {Promise} */ delete() { return this.client.rest.methods.deleteWebhook(this); } } module.exports = Webhook; /***/ }, /* 21 */ /***/ function(module, exports) { // Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. function EventEmitter() { this._events = this._events || {}; this._maxListeners = this._maxListeners || undefined; } module.exports = EventEmitter; // Backwards-compat with node 0.10.x EventEmitter.EventEmitter = EventEmitter; EventEmitter.prototype._events = undefined; EventEmitter.prototype._maxListeners = undefined; // By default EventEmitters will print a warning if more than 10 listeners are // added to it. This is a useful default which helps finding memory leaks. EventEmitter.defaultMaxListeners = 10; // Obviously not all Emitters should be limited to 10. This function allows // that to be increased. Set to zero for unlimited. EventEmitter.prototype.setMaxListeners = function(n) { if (!isNumber(n) || n < 0 || isNaN(n)) throw TypeError('n must be a positive number'); this._maxListeners = n; return this; }; EventEmitter.prototype.emit = function(type) { var er, handler, len, args, i, listeners; if (!this._events) this._events = {}; // If there is no 'error' event listener then throw. if (type === 'error') { if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { er = arguments[1]; if (er instanceof Error) { throw er; // Unhandled 'error' event } else { // At least give some kind of context to the user var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); err.context = er; throw err; } } } handler = this._events[type]; if (isUndefined(handler)) return false; if (isFunction(handler)) { switch (arguments.length) { // fast cases case 1: handler.call(this); break; case 2: handler.call(this, arguments[1]); break; case 3: handler.call(this, arguments[1], arguments[2]); break; // slower default: args = Array.prototype.slice.call(arguments, 1); handler.apply(this, args); } } else if (isObject(handler)) { args = Array.prototype.slice.call(arguments, 1); listeners = handler.slice(); len = listeners.length; for (i = 0; i < len; i++) listeners[i].apply(this, args); } return true; }; EventEmitter.prototype.addListener = function(type, listener) { var m; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events) this._events = {}; // To avoid recursion in the case that type === "newListener"! Before // adding it to the listeners, first emit "newListener". if (this._events.newListener) this.emit('newListener', type, isFunction(listener.listener) ? listener.listener : listener); if (!this._events[type]) // Optimize the case of one listener. Don't need the extra array object. this._events[type] = listener; else if (isObject(this._events[type])) // If we've already got an array, just append. this._events[type].push(listener); else // Adding the second element, need to change to array. this._events[type] = [this._events[type], listener]; // Check for listener leak if (isObject(this._events[type]) && !this._events[type].warned) { if (!isUndefined(this._maxListeners)) { m = this._maxListeners; } else { m = EventEmitter.defaultMaxListeners; } if (m && m > 0 && this._events[type].length > m) { this._events[type].warned = true; console.error('(node) warning: possible EventEmitter memory ' + 'leak detected. %d listeners added. ' + 'Use emitter.setMaxListeners() to increase limit.', this._events[type].length); if (typeof console.trace === 'function') { // not supported in IE 10 console.trace(); } } } return this; }; EventEmitter.prototype.on = EventEmitter.prototype.addListener; EventEmitter.prototype.once = function(type, listener) { if (!isFunction(listener)) throw TypeError('listener must be a function'); var fired = false; function g() { this.removeListener(type, g); if (!fired) { fired = true; listener.apply(this, arguments); } } g.listener = listener; this.on(type, g); return this; }; // emits a 'removeListener' event iff the listener was removed EventEmitter.prototype.removeListener = function(type, listener) { var list, position, length, i; if (!isFunction(listener)) throw TypeError('listener must be a function'); if (!this._events || !this._events[type]) return this; list = this._events[type]; length = list.length; position = -1; if (list === listener || (isFunction(list.listener) && list.listener === listener)) { delete this._events[type]; if (this._events.removeListener) this.emit('removeListener', type, listener); } else if (isObject(list)) { for (i = length; i-- > 0;) { if (list[i] === listener || (list[i].listener && list[i].listener === listener)) { position = i; break; } } if (position < 0) return this; if (list.length === 1) { list.length = 0; delete this._events[type]; } else { list.splice(position, 1); } if (this._events.removeListener) this.emit('removeListener', type, listener); } return this; }; EventEmitter.prototype.removeAllListeners = function(type) { var key, listeners; if (!this._events) return this; // not listening for removeListener, no need to emit if (!this._events.removeListener) { if (arguments.length === 0) this._events = {}; else if (this._events[type]) delete this._events[type]; return this; } // emit removeListener for all listeners on all events if (arguments.length === 0) { for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); this._events = {}; return this; } listeners = this._events[type]; if (isFunction(listeners)) { this.removeListener(type, listeners); } else if (listeners) { // LIFO order while (listeners.length) this.removeListener(type, listeners[listeners.length - 1]); } delete this._events[type]; return this; }; EventEmitter.prototype.listeners = function(type) { var ret; if (!this._events || !this._events[type]) ret = []; else if (isFunction(this._events[type])) ret = [this._events[type]]; else ret = this._events[type].slice(); return ret; }; EventEmitter.prototype.listenerCount = function(type) { if (this._events) { var evlistener = this._events[type]; if (isFunction(evlistener)) return 1; else if (evlistener) return evlistener.length; } return 0; }; EventEmitter.listenerCount = function(emitter, type) { return emitter.listenerCount(type); }; function isFunction(arg) { return typeof arg === 'function'; } function isNumber(arg) { return typeof arg === 'number'; } function isObject(arg) { return typeof arg === 'object' && arg !== null; } function isUndefined(arg) { return arg === void 0; } /***/ }, /* 22 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. // resolves . and .. elements in a path array with directory names there // must be no slashes, empty elements, or device names (c:\) in the array // (so also no leading and trailing slashes - it does not distinguish // relative and absolute paths) function normalizeArray(parts, allowAboveRoot) { // if the path tries to go above the root, `up` ends up > 0 var up = 0; for (var i = parts.length - 1; i >= 0; i--) { var last = parts[i]; if (last === '.') { parts.splice(i, 1); } else if (last === '..') { parts.splice(i, 1); up++; } else if (up) { parts.splice(i, 1); up--; } } // if the path is allowed to go above the root, restore leading ..s if (allowAboveRoot) { for (; up--; up) { parts.unshift('..'); } } return parts; } // Split a filename into [root, dir, basename, ext], unix version // 'root' is just a slash, or nothing. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; var splitPath = function(filename) { return splitPathRe.exec(filename).slice(1); }; // path.resolve([from ...], to) // posix version exports.resolve = function() { var resolvedPath = '', resolvedAbsolute = false; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path = (i >= 0) ? arguments[i] : process.cwd(); // Skip empty and invalid entries if (typeof path !== 'string') { throw new TypeError('Arguments to path.resolve must be strings'); } else if (!path) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charAt(0) === '/'; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { return !!p; }), !resolvedAbsolute).join('/'); return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; }; // path.normalize(path) // posix version exports.normalize = function(path) { var isAbsolute = exports.isAbsolute(path), trailingSlash = substr(path, -1) === '/'; // Normalize the path path = normalizeArray(filter(path.split('/'), function(p) { return !!p; }), !isAbsolute).join('/'); if (!path && !isAbsolute) { path = '.'; } if (path && trailingSlash) { path += '/'; } return (isAbsolute ? '/' : '') + path; }; // posix version exports.isAbsolute = function(path) { return path.charAt(0) === '/'; }; // posix version exports.join = function() { var paths = Array.prototype.slice.call(arguments, 0); return exports.normalize(filter(paths, function(p, index) { if (typeof p !== 'string') { throw new TypeError('Arguments to path.join must be strings'); } return p; }).join('/')); }; // path.relative(from, to) // posix version exports.relative = function(from, to) { from = exports.resolve(from).substr(1); to = exports.resolve(to).substr(1); function trim(arr) { var start = 0; for (; start < arr.length; start++) { if (arr[start] !== '') break; } var end = arr.length - 1; for (; end >= 0; end--) { if (arr[end] !== '') break; } if (start > end) return []; return arr.slice(start, end - start + 1); } var fromParts = trim(from.split('/')); var toParts = trim(to.split('/')); var length = Math.min(fromParts.length, toParts.length); var samePartsLength = length; for (var i = 0; i < length; i++) { if (fromParts[i] !== toParts[i]) { samePartsLength = i; break; } } var outputParts = []; for (var i = samePartsLength; i < fromParts.length; i++) { outputParts.push('..'); } outputParts = outputParts.concat(toParts.slice(samePartsLength)); return outputParts.join('/'); }; exports.sep = '/'; exports.delimiter = ':'; exports.dirname = function(path) { var result = splitPath(path), root = result[0], dir = result[1]; if (!root && !dir) { // No dirname whatsoever return '.'; } if (dir) { // It has a dirname, strip trailing slash dir = dir.substr(0, dir.length - 1); } return root + dir; }; exports.basename = function(path, ext) { var f = splitPath(path)[2]; // TODO: make this comparison case-insensitive on windows? if (ext && f.substr(-1 * ext.length) === ext) { f = f.substr(0, f.length - ext.length); } return f; }; exports.extname = function(path) { return splitPath(path)[3]; }; function filter (xs, f) { if (xs.filter) return xs.filter(f); var res = []; for (var i = 0; i < xs.length; i++) { if (f(xs[i], i, xs)) res.push(xs[i]); } return res; } // String.prototype.substr - negative index don't work in IE8 var substr = 'ab'.substr(-1) === 'b' ? function (str, start, len) { return str.substr(start, len) } : function (str, start, len) { if (start < 0) start = str.length + start; return str.substr(start, len); } ; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(16))) /***/ }, /* 23 */ /***/ function(module, exports, __webpack_require__) { /** * Root reference for iframes. */ var root; if (typeof window !== 'undefined') { // Browser window root = window; } else if (typeof self !== 'undefined') { // Web Worker root = self; } else { // Other environments console.warn("Using browser-only version of superagent in non-browser environment"); root = this; } var Emitter = __webpack_require__(56); var RequestBase = __webpack_require__(59); var isObject = __webpack_require__(42); /** * Noop. */ function noop(){}; /** * Expose `request`. */ var request = module.exports = __webpack_require__(60).bind(null, Request); /** * Determine XHR. */ request.getXHR = function () { if (root.XMLHttpRequest && (!root.location || 'file:' != root.location.protocol || !root.ActiveXObject)) { return new XMLHttpRequest; } else { try { return new ActiveXObject('Microsoft.XMLHTTP'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP.6.0'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP.3.0'); } catch(e) {} try { return new ActiveXObject('Msxml2.XMLHTTP'); } catch(e) {} } throw Error("Browser-only verison of superagent could not find XHR"); }; /** * Removes leading and trailing whitespace, added to support IE. * * @param {String} s * @return {String} * @api private */ var trim = ''.trim ? function(s) { return s.trim(); } : function(s) { return s.replace(/(^\s*|\s*$)/g, ''); }; /** * Serialize the given `obj`. * * @param {Object} obj * @return {String} * @api private */ function serialize(obj) { if (!isObject(obj)) return obj; var pairs = []; for (var key in obj) { pushEncodedKeyValuePair(pairs, key, obj[key]); } return pairs.join('&'); } /** * Helps 'serialize' with serializing arrays. * Mutates the pairs array. * * @param {Array} pairs * @param {String} key * @param {Mixed} val */ function pushEncodedKeyValuePair(pairs, key, val) { if (val != null) { if (Array.isArray(val)) { val.forEach(function(v) { pushEncodedKeyValuePair(pairs, key, v); }); } else if (isObject(val)) { for(var subkey in val) { pushEncodedKeyValuePair(pairs, key + '[' + subkey + ']', val[subkey]); } } else { pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(val)); } } else if (val === null) { pairs.push(encodeURIComponent(key)); } } /** * Expose serialization method. */ request.serializeObject = serialize; /** * Parse the given x-www-form-urlencoded `str`. * * @param {String} str * @return {Object} * @api private */ function parseString(str) { var obj = {}; var pairs = str.split('&'); var pair; var pos; for (var i = 0, len = pairs.length; i < len; ++i) { pair = pairs[i]; pos = pair.indexOf('='); if (pos == -1) { obj[decodeURIComponent(pair)] = ''; } else { obj[decodeURIComponent(pair.slice(0, pos))] = decodeURIComponent(pair.slice(pos + 1)); } } return obj; } /** * Expose parser. */ request.parseString = parseString; /** * Default MIME type map. * * superagent.types.xml = 'application/xml'; * */ request.types = { html: 'text/html', json: 'application/json', xml: 'application/xml', urlencoded: 'application/x-www-form-urlencoded', 'form': 'application/x-www-form-urlencoded', 'form-data': 'application/x-www-form-urlencoded' }; /** * Default serialization map. * * superagent.serialize['application/xml'] = function(obj){ * return 'generated xml here'; * }; * */ request.serialize = { 'application/x-www-form-urlencoded': serialize, 'application/json': JSON.stringify }; /** * Default parsers. * * superagent.parse['application/xml'] = function(str){ * return { object parsed from str }; * }; * */ request.parse = { 'application/x-www-form-urlencoded': parseString, 'application/json': JSON.parse }; /** * Parse the given header `str` into * an object containing the mapped fields. * * @param {String} str * @return {Object} * @api private */ function parseHeader(str) { var lines = str.split(/\r?\n/); var fields = {}; var index; var line; var field; var val; lines.pop(); // trailing CRLF for (var i = 0, len = lines.length; i < len; ++i) { line = lines[i]; index = line.indexOf(':'); field = line.slice(0, index).toLowerCase(); val = trim(line.slice(index + 1)); fields[field] = val; } return fields; } /** * Check if `mime` is json or has +json structured syntax suffix. * * @param {String} mime * @return {Boolean} * @api private */ function isJSON(mime) { return /[\/+]json\b/.test(mime); } /** * Return the mime type for the given `str`. * * @param {String} str * @return {String} * @api private */ function type(str){ return str.split(/ *; */).shift(); }; /** * Return header field parameters. * * @param {String} str * @return {Object} * @api private */ function params(str){ return str.split(/ *; */).reduce(function(obj, str){ var parts = str.split(/ *= */), key = parts.shift(), val = parts.shift(); if (key && val) obj[key] = val; return obj; }, {}); }; /** * Initialize a new `Response` with the given `xhr`. * * - set flags (.ok, .error, etc) * - parse header * * Examples: * * Aliasing `superagent` as `request` is nice: * * request = superagent; * * We can use the promise-like API, or pass callbacks: * * request.get('/').end(function(res){}); * request.get('/', function(res){}); * * Sending data can be chained: * * request * .post('/user') * .send({ name: 'tj' }) * .end(function(res){}); * * Or passed to `.send()`: * * request * .post('/user') * .send({ name: 'tj' }, function(res){}); * * Or passed to `.post()`: * * request * .post('/user', { name: 'tj' }) * .end(function(res){}); * * Or further reduced to a single call for simple cases: * * request * .post('/user', { name: 'tj' }, function(res){}); * * @param {XMLHTTPRequest} xhr * @param {Object} options * @api private */ function Response(req, options) { options = options || {}; this.req = req; this.xhr = this.req.xhr; // responseText is accessible only if responseType is '' or 'text' and on older browsers this.text = ((this.req.method !='HEAD' && (this.xhr.responseType === '' || this.xhr.responseType === 'text')) || typeof this.xhr.responseType === 'undefined') ? this.xhr.responseText : null; this.statusText = this.req.xhr.statusText; this._setStatusProperties(this.xhr.status); this.header = this.headers = parseHeader(this.xhr.getAllResponseHeaders()); // getAllResponseHeaders sometimes falsely returns "" for CORS requests, but // getResponseHeader still works. so we get content-type even if getting // other headers fails. this.header['content-type'] = this.xhr.getResponseHeader('content-type'); this._setHeaderProperties(this.header); this.body = this.req.method != 'HEAD' ? this._parseBody(this.text ? this.text : this.xhr.response) : null; } /** * Get case-insensitive `field` value. * * @param {String} field * @return {String} * @api public */ Response.prototype.get = function(field){ return this.header[field.toLowerCase()]; }; /** * Set header related properties: * * - `.type` the content type without params * * A response of "Content-Type: text/plain; charset=utf-8" * will provide you with a `.type` of "text/plain". * * @param {Object} header * @api private */ Response.prototype._setHeaderProperties = function(header){ // content-type var ct = this.header['content-type'] || ''; this.type = type(ct); // params var obj = params(ct); for (var key in obj) this[key] = obj[key]; }; /** * Parse the given body `str`. * * Used for auto-parsing of bodies. Parsers * are defined on the `superagent.parse` object. * * @param {String} str * @return {Mixed} * @api private */ Response.prototype._parseBody = function(str){ var parse = request.parse[this.type]; if (!parse && isJSON(this.type)) { parse = request.parse['application/json']; } return parse && str && (str.length || str instanceof Object) ? parse(str) : null; }; /** * Set flags such as `.ok` based on `status`. * * For example a 2xx response will give you a `.ok` of __true__ * whereas 5xx will be __false__ and `.error` will be __true__. The * `.clientError` and `.serverError` are also available to be more * specific, and `.statusType` is the class of error ranging from 1..5 * sometimes useful for mapping respond colors etc. * * "sugar" properties are also defined for common cases. Currently providing: * * - .noContent * - .badRequest * - .unauthorized * - .notAcceptable * - .notFound * * @param {Number} status * @api private */ Response.prototype._setStatusProperties = function(status){ // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request if (status === 1223) { status = 204; } var type = status / 100 | 0; // status / class this.status = this.statusCode = status; this.statusType = type; // basics this.info = 1 == type; this.ok = 2 == type; this.clientError = 4 == type; this.serverError = 5 == type; this.error = (4 == type || 5 == type) ? this.toError() : false; // sugar this.accepted = 202 == status; this.noContent = 204 == status; this.badRequest = 400 == status; this.unauthorized = 401 == status; this.notAcceptable = 406 == status; this.notFound = 404 == status; this.forbidden = 403 == status; }; /** * Return an `Error` representative of this response. * * @return {Error} * @api public */ Response.prototype.toError = function(){ var req = this.req; var method = req.method; var url = req.url; var msg = 'cannot ' + method + ' ' + url + ' (' + this.status + ')'; var err = new Error(msg); err.status = this.status; err.method = method; err.url = url; return err; }; /** * Expose `Response`. */ request.Response = Response; /** * Initialize a new `Request` with the given `method` and `url`. * * @param {String} method * @param {String} url * @api public */ function Request(method, url) { var self = this; this._query = this._query || []; this.method = method; this.url = url; this.header = {}; // preserves header name case this._header = {}; // coerces header names to lowercase this.on('end', function(){ var err = null; var res = null; try { res = new Response(self); } catch(e) { err = new Error('Parser is unable to parse the response'); err.parse = true; err.original = e; // issue #675: return the raw response if the response parsing fails if (self.xhr) { // ie9 doesn't have 'response' property err.rawResponse = typeof self.xhr.responseType == 'undefined' ? self.xhr.responseText : self.xhr.response; // issue #876: return the http status code if the response parsing fails err.statusCode = self.xhr.status ? self.xhr.status : null; } else { err.rawResponse = null; err.statusCode = null; } return self.callback(err); } self.emit('response', res); var new_err; try { if (res.status < 200 || res.status >= 300) { new_err = new Error(res.statusText || 'Unsuccessful HTTP response'); new_err.original = err; new_err.response = res; new_err.status = res.status; } } catch(e) { new_err = e; // #985 touching res may cause INVALID_STATE_ERR on old Android } // #1000 don't catch errors from the callback to avoid double calling it if (new_err) { self.callback(new_err, res); } else { self.callback(null, res); } }); } /** * Mixin `Emitter` and `RequestBase`. */ Emitter(Request.prototype); RequestBase(Request.prototype); /** * Set Content-Type to `type`, mapping values from `request.types`. * * Examples: * * superagent.types.xml = 'application/xml'; * * request.post('/') * .type('xml') * .send(xmlstring) * .end(callback); * * request.post('/') * .type('application/xml') * .send(xmlstring) * .end(callback); * * @param {String} type * @return {Request} for chaining * @api public */ Request.prototype.type = function(type){ this.set('Content-Type', request.types[type] || type); return this; }; /** * Set responseType to `val`. Presently valid responseTypes are 'blob' and * 'arraybuffer'. * * Examples: * * req.get('/') * .responseType('blob') * .end(callback); * * @param {String} val * @return {Request} for chaining * @api public */ Request.prototype.responseType = function(val){ this._responseType = val; return this; }; /** * Set Accept to `type`, mapping values from `request.types`. * * Examples: * * superagent.types.json = 'application/json'; * * request.get('/agent') * .accept('json') * .end(callback); * * request.get('/agent') * .accept('application/json') * .end(callback); * * @param {String} accept * @return {Request} for chaining * @api public */ Request.prototype.accept = function(type){ this.set('Accept', request.types[type] || type); return this; }; /** * Set Authorization field value with `user` and `pass`. * * @param {String} user * @param {String} pass * @param {Object} options with 'type' property 'auto' or 'basic' (default 'basic') * @return {Request} for chaining * @api public */ Request.prototype.auth = function(user, pass, options){ if (!options) { options = { type: 'basic' } } switch (options.type) { case 'basic': var str = btoa(user + ':' + pass); this.set('Authorization', 'Basic ' + str); break; case 'auto': this.username = user; this.password = pass; break; } return this; }; /** * Add query-string `val`. * * Examples: * * request.get('/shoes') * .query('size=10') * .query({ color: 'blue' }) * * @param {Object|String} val * @return {Request} for chaining * @api public */ Request.prototype.query = function(val){ if ('string' != typeof val) val = serialize(val); if (val) this._query.push(val); return this; }; /** * Queue the given `file` as an attachment to the specified `field`, * with optional `options` (or filename). * * ``` js * request.post('/upload') * .attach('content', new Blob(['hey!'], { type: "text/html"})) * .end(callback); * ``` * * @param {String} field * @param {Blob|File} file * @param {String|Object} options * @return {Request} for chaining * @api public */ Request.prototype.attach = function(field, file, options){ if (this._data) { throw Error("superagent can't mix .send() and .attach()"); } this._getFormData().append(field, file, options || file.name); return this; }; Request.prototype._getFormData = function(){ if (!this._formData) { this._formData = new root.FormData(); } return this._formData; }; /** * Invoke the callback with `err` and `res` * and handle arity check. * * @param {Error} err * @param {Response} res * @api private */ Request.prototype.callback = function(err, res){ var fn = this._callback; this.clearTimeout(); if (err) { this.emit('error', err); } fn(err, res); }; /** * Invoke callback with x-domain error. * * @api private */ Request.prototype.crossDomainError = function(){ var err = new Error('Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.'); err.crossDomain = true; err.status = this.status; err.method = this.method; err.url = this.url; this.callback(err); }; // This only warns, because the request is still likely to work Request.prototype.buffer = Request.prototype.ca = Request.prototype.agent = function(){ console.warn("This is not supported in browser version of superagent"); return this; }; // This throws, because it can't send/receive data as expected Request.prototype.pipe = Request.prototype.write = function(){ throw Error("Streaming is not supported in browser version of superagent"); }; /** * Invoke callback with timeout error. * * @api private */ Request.prototype._timeoutError = function(){ var timeout = this._timeout; var err = new Error('timeout of ' + timeout + 'ms exceeded'); err.timeout = timeout; this.callback(err); }; /** * Compose querystring to append to req.url * * @api private */ Request.prototype._appendQueryString = function(){ var query = this._query.join('&'); if (query) { this.url += ~this.url.indexOf('?') ? '&' + query : '?' + query; } }; /** * Check if `obj` is a host object, * we don't want to serialize these :) * * @param {Object} obj * @return {Boolean} * @api private */ Request.prototype._isHost = function _isHost(obj) { // Native objects stringify to [object File], [object Blob], [object FormData], etc. return obj && 'object' === typeof obj && !Array.isArray(obj) && Object.prototype.toString.call(obj) !== '[object Object]'; } /** * Initiate request, invoking callback `fn(res)` * with an instanceof `Response`. * * @param {Function} fn * @return {Request} for chaining * @api public */ Request.prototype.end = function(fn){ var self = this; var xhr = this.xhr = request.getXHR(); var timeout = this._timeout; var data = this._formData || this._data; // store callback this._callback = fn || noop; // state change xhr.onreadystatechange = function(){ if (4 != xhr.readyState) return; // In IE9, reads to any property (e.g. status) off of an aborted XHR will // result in the error "Could not complete the operation due to error c00c023f" var status; try { status = xhr.status } catch(e) { status = 0; } if (0 == status) { if (self.timedout) return self._timeoutError(); if (self._aborted) return; return self.crossDomainError(); } self.emit('end'); }; // progress var handleProgress = function(direction, e) { if (e.total > 0) { e.percent = e.loaded / e.total * 100; } e.direction = direction; self.emit('progress', e); } if (this.hasListeners('progress')) { try { xhr.onprogress = handleProgress.bind(null, 'download'); if (xhr.upload) { xhr.upload.onprogress = handleProgress.bind(null, 'upload'); } } catch(e) { // Accessing xhr.upload fails in IE from a web worker, so just pretend it doesn't exist. // Reported here: // https://connect.microsoft.com/IE/feedback/details/837245/xmlhttprequest-upload-throws-invalid-argument-when-used-from-web-worker-context } } // timeout if (timeout && !this._timer) { this._timer = setTimeout(function(){ self.timedout = true; self.abort(); }, timeout); } // querystring this._appendQueryString(); // initiate request if (this.username && this.password) { xhr.open(this.method, this.url, true, this.username, this.password); } else { xhr.open(this.method, this.url, true); } // CORS if (this._withCredentials) xhr.withCredentials = true; // body if ('GET' != this.method && 'HEAD' != this.method && 'string' != typeof data && !this._isHost(data)) { // serialize stuff var contentType = this._header['content-type']; var serialize = this._serializer || request.serialize[contentType ? contentType.split(';')[0] : '']; if (!serialize && isJSON(contentType)) serialize = request.serialize['application/json']; if (serialize) data = serialize(data); } // set header fields for (var field in this.header) { if (null == this.header[field]) continue; xhr.setRequestHeader(field, this.header[field]); } if (this._responseType) { xhr.responseType = this._responseType; } // send stuff this.emit('request', this); // IE11 xhr.send(undefined) sends 'undefined' string as POST payload (instead of nothing) // We need null here if data is undefined xhr.send(typeof data !== 'undefined' ? data : null); return this; }; /** * Expose `Request`. */ request.Request = Request; /** * GET `url` with optional callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} [data] or fn * @param {Function} [fn] * @return {Request} * @api public */ request.get = function(url, data, fn){ var req = request('GET', url); if ('function' == typeof data) fn = data, data = null; if (data) req.query(data); if (fn) req.end(fn); return req; }; /** * HEAD `url` with optional callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} [data] or fn * @param {Function} [fn] * @return {Request} * @api public */ request.head = function(url, data, fn){ var req = request('HEAD', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * OPTIONS query to `url` with optional callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} [data] or fn * @param {Function} [fn] * @return {Request} * @api public */ request.options = function(url, data, fn){ var req = request('OPTIONS', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * DELETE `url` with optional callback `fn(res)`. * * @param {String} url * @param {Function} [fn] * @return {Request} * @api public */ function del(url, fn){ var req = request('DELETE', url); if (fn) req.end(fn); return req; }; request['del'] = del; request['delete'] = del; /** * PATCH `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed} [data] * @param {Function} [fn] * @return {Request} * @api public */ request.patch = function(url, data, fn){ var req = request('PATCH', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * POST `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed} [data] * @param {Function} [fn] * @return {Request} * @api public */ request.post = function(url, data, fn){ var req = request('POST', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /** * PUT `url` with optional `data` and callback `fn(res)`. * * @param {String} url * @param {Mixed|Function} [data] or fn * @param {Function} [fn] * @return {Request} * @api public */ request.put = function(url, data, fn){ var req = request('PUT', url); if ('function' == typeof data) fn = data, data = null; if (data) req.send(data); if (fn) req.end(fn); return req; }; /***/ }, /* 24 */ /***/ function(module, exports) { module.exports = function arraysEqual(a, b) { if (a === b) return true; if (a.length !== b.length) return false; for (const itemInd in a) { const item = a[itemInd]; const ind = b.indexOf(item); if (ind) { b.splice(ind, 1); } } return b.length === 0; }; /***/ }, /* 25 */ /***/ function(module, exports) { module.exports = { "name": "discord.js", "version": "10.0.1", "description": "A powerful library for interacting with the Discord API", "main": "./src/index", "scripts": { "test": "eslint src && docgen --source src --custom docs", "docs": "docgen --source src --custom docs --output docs/docs.json", "test-docs": "docgen --source src --custom docs", "lint": "eslint src", "web-dist": "node ./node_modules/parallel-webpack/bin/run.js" }, "repository": { "type": "git", "url": "git+https://github.com/hydrabolt/discord.js.git" }, "keywords": [ "discord", "api", "bot", "client", "node", "discordapp" ], "author": "Amish Shah ", "license": "Apache-2.0", "bugs": { "url": "https://github.com/hydrabolt/discord.js/issues" }, "homepage": "https://github.com/hydrabolt/discord.js#readme", "dependencies": { "superagent": "^3.0.0", "tweetnacl": "^0.14.3", "ws": "^1.1.1" }, "peerDependencies": { "node-opus": "^0.2.0", "opusscript": "^0.0.1" }, "devDependencies": { "bufferutil": "^1.2.1", "discord.js-docgen": "github:Gawdl3y/discord.js-docgen", "eslint": "^3.10.0", "jsdoc-to-markdown": "^2.0.0", "json-loader": "^0.5.4", "parallel-webpack": "^1.5.0", "uglify-js": "github:mishoo/UglifyJS2#harmony", "utf-8-validate": "^1.2.1", "webpack": "2.1.0-beta.27", "zlibjs": "^0.2.0" }, "engines": { "node": ">=6.0.0" }, "browser": { "ws": false, "opusscript": false, "node-opus": false, "tweet-nacl": false, "src/sharding/Shard.js": false, "src/sharding/ShardClientUtil.js": false, "src/sharding/ShardingManager.js": false, "src/client/voice/dispatcher/StreamDispatcher.js": false, "src/client/voice/opus/BaseOpusEngine.js": false, "src/client/voice/opus/NodeOpusEngine.js": false, "src/client/voice/opus/OpusEngineList.js": false, "src/client/voice/opus/OpusScriptEngine.js": false, "src/client/voice/pcm/ConverterEngine.js": false, "src/client/voice/pcm/ConverterEngineList.js": false, "src/client/voice/pcm/FfmpegConverterEngine.js": false, "src/client/voice/player/AudioPlayer.js": false, "src/client/voice/player/BasePlayer.js": false, "src/client/voice/player/DefaultPlayer.js": false, "src/client/voice/receiver/VoiceReadable.js": false, "src/client/voice/receiver/VoiceReceiver.js": false, "src/client/voice/util/SecretKey.js": false, "src/client/voice/ClientVoiceManager.js": false, "src/client/voice/VoiceConnection.js": false, "src/client/voice/VoiceUDPClient.js": false, "src/client/voice/VoiceWebSocket.js": false } }; /***/ }, /* 26 */ /***/ function(module, exports, __webpack_require__) { const User = __webpack_require__(5); const OAuth2Application = __webpack_require__(35); /** * Represents the client's OAuth2 Application * @extends {OAuth2Application} */ class ClientOAuth2Application extends OAuth2Application { setup(data) { super.setup(data); /** * The app's flags * @type {number} */ this.flags = data.flags; /** * The app's owner * @type {User} */ this.owner = new User(this.client, data.owner); } } module.exports = ClientOAuth2Application; /***/ }, /* 27 */ /***/ function(module, exports, __webpack_require__) { const User = __webpack_require__(5); const Collection = __webpack_require__(3); /** * Represents the logged in client's Discord user * @extends {User} */ class ClientUser extends User { setup(data) { super.setup(data); /** * Whether or not this account has been verified * @type {boolean} */ this.verified = data.verified; /** * The email of this account * @type {string} */ this.email = data.email; this.localPresence = {}; this._typing = new Map(); /** * A Collection of friends for the logged in user. * This is only filled when using a user account. * @type {Collection} */ this.friends = new Collection(); /** * A Collection of blocked users for the logged in user. * This is only filled when using a user account. * @type {Collection} */ this.blocked = new Collection(); /** * A Collection of notes for the logged in user. * This is only filled when using a user account. * @type {Collection} */ this.notes = new Collection(); } edit(data) { return this.client.rest.methods.updateCurrentUser(data); } /** * Set the username of the logged in Client. * Changing usernames in Discord is heavily rate limited, with only 2 requests * every hour. Use this sparingly! * @param {string} username The new username * @returns {Promise} * @example * // set username * client.user.setUsername('discordjs') * .then(user => console.log(`My new username is ${user.username}`)) * .catch(console.error); */ setUsername(username) { return this.client.rest.methods.updateCurrentUser({ username }); } /** * If this user is a "self bot" or logged in using a normal user's details (which should be avoided), you can set the * email here. * @param {string} email The new email * @returns {Promise} * @example * // set email * client.user.setEmail('bob@gmail.com') * .then(user => console.log(`My new email is ${user.email}`)) * .catch(console.error); */ setEmail(email) { return this.client.rest.methods.updateCurrentUser({ email }); } /** * If this user is a "self bot" or logged in using a normal user's details (which should be avoided), you can set the * password here. * @param {string} password The new password * @returns {Promise} * @example * // set password * client.user.setPassword('password123') * .then(user => console.log('New password set!')) * .catch(console.error); */ setPassword(password) { return this.client.rest.methods.updateCurrentUser({ password }); } /** * Set the avatar of the logged in Client. * @param {BufferResolvable|Base64Resolvable} avatar The new avatar * @returns {Promise} * @example * // set avatar * client.user.setAvatar('./avatar.png') * .then(user => console.log(`New avatar set!`)) * .catch(console.error); */ setAvatar(avatar) { if (avatar.startsWith('data:')) { return this.client.rest.methods.updateCurrentUser({ avatar }); } else { return this.client.resolver.resolveBuffer(avatar).then(data => this.client.rest.methods.updateCurrentUser({ avatar: data }) ); } } /** * Set the status of the logged in user. * @param {string} status can be `online`, `idle`, `invisible` or `dnd` (do not disturb) * @returns {Promise} */ setStatus(status) { return this.setPresence({ status }); } /** * Set the current game of the logged in user. * @param {string} game the game being played * @param {string} [streamingURL] an optional URL to a twitch stream, if one is available. * @returns {Promise} */ setGame(game, streamingURL) { return this.setPresence({ game: { name: game, url: streamingURL, } }); } /** * Set/remove the AFK flag for the current user. * @param {boolean} afk whether or not the user is AFK. * @returns {Promise} */ setAFK(afk) { return this.setPresence({ afk }); } /** * Send a friend request * This is only available when using a user account. * @param {UserResolvable} user The user to send the friend request to. * @returns {Promise} The user the friend request was sent to. */ addFriend(user) { user = this.client.resolver.resolveUser(user); return this.client.rest.methods.addFriend(user); } /** * Remove a friend * This is only available when using a user account. * @param {UserResolvable} user The user to remove from your friends * @returns {Promise} The user that was removed */ removeFriend(user) { user = this.client.resolver.resolveUser(user); return this.client.rest.methods.removeFriend(user); } /** * Creates a guild * This is only available when using a user account. * @param {string} name The name of the guild * @param {string} region The region for the server * @param {BufferResolvable|Base64Resolvable} [icon=null] The icon for the guild * @returns {Promise} The guild that was created */ createGuild(name, region, icon = null) { if (!icon) return this.client.rest.methods.createGuild({ name, icon, region }); if (icon.startsWith('data:')) { return this.client.rest.methods.createGuild({ name, icon, region }); } else { return this.client.resolver.resolveBuffer(icon).then(data => this.client.rest.methods.createGuild({ name, icon: data, region }) ); } } /** * Set the full presence of the current user. * @param {Object} data the data to provide * @returns {Promise} */ setPresence(data) { // {"op":3,"d":{"status":"dnd","since":0,"game":null,"afk":false}} return new Promise(resolve => { let status = this.localPresence.status || this.presence.status; let game = this.localPresence.game; let afk = this.localPresence.afk || this.presence.afk; if (!game && this.presence.game) { game = { name: this.presence.game.name, type: this.presence.game.type, url: this.presence.game.url, }; } if (data.status) { if (typeof data.status !== 'string') throw new TypeError('Status must be a string'); status = data.status; } if (data.game) { game = data.game; if (game.url) game.type = 1; } if (typeof data.afk !== 'undefined') afk = data.afk; afk = Boolean(afk); this.localPresence = { status, game, afk }; this.localPresence.since = 0; this.localPresence.game = this.localPresence.game || null; this.client.ws.send({ op: 3, d: this.localPresence, }); this.client._setPresence(this.id, this.localPresence); resolve(this); }); } } module.exports = ClientUser; /***/ }, /* 28 */ /***/ function(module, exports, __webpack_require__) { const Channel = __webpack_require__(8); const TextBasedChannel = __webpack_require__(10); const Collection = __webpack_require__(3); /** * Represents a direct message channel between two users. * @extends {Channel} * @implements {TextBasedChannel} */ class DMChannel extends Channel { constructor(client, data) { super(client, data); this.type = 'dm'; this.messages = new Collection(); this._typing = new Map(); } setup(data) { super.setup(data); /** * The recipient on the other end of the DM * @type {User} */ this.recipient = this.client.dataManager.newUser(data.recipients[0]); this.lastMessageID = data.last_message_id; } /** * When concatenated with a string, this automatically concatenates the recipient's mention instead of the * DM channel object. * @returns {string} */ toString() { return this.recipient.toString(); } // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } fetchMessages() { return; } fetchPinnedMessages() { return; } startTyping() { return; } stopTyping() { return; } get typing() { return; } get typingCount() { return; } createCollector() { return; } awaitMessages() { return; } bulkDelete() { return; } _cacheMessage() { return; } } TextBasedChannel.applyToClass(DMChannel, true); module.exports = DMChannel; /***/ }, /* 29 */ /***/ function(module, exports, __webpack_require__) { const Channel = __webpack_require__(8); const TextBasedChannel = __webpack_require__(10); const Collection = __webpack_require__(3); const arraysEqual = __webpack_require__(24); /* { type: 3, recipients: [ { username: 'Charlie', id: '123', discriminator: '6631', avatar: '123' }, { username: 'Ben', id: '123', discriminator: '2055', avatar: '123' }, { username: 'Adam', id: '123', discriminator: '2406', avatar: '123' } ], owner_id: '123', name: null, last_message_id: '123', id: '123', icon: null } */ /** * Represents a Group DM on Discord * @extends {Channel} * @implements {TextBasedChannel} */ class GroupDMChannel extends Channel { constructor(client, data) { super(client, data); this.type = 'group'; this.messages = new Collection(); this._typing = new Map(); } setup(data) { super.setup(data); /** * The name of this Group DM, can be null if one isn't set. * @type {string} */ this.name = data.name; /** * A hash of the Group DM icon. * @type {string} */ this.icon = data.icon; /** * The user ID of this Group DM's owner. * @type {string} */ this.ownerID = data.owner_id; if (!this.recipients) { /** * A collection of the recipients of this DM, mapped by their ID. * @type {Collection} */ this.recipients = new Collection(); } if (data.recipients) { for (const recipient of data.recipients) { const user = this.client.dataManager.newUser(recipient); this.recipients.set(user.id, user); } } this.lastMessageID = data.last_message_id; } /** * The owner of this Group DM. * @type {User} * @readonly */ get owner() { return this.client.users.get(this.ownerID); } /** * Whether this channel equals another channel. It compares all properties, so for most operations * it is advisable to just compare `channel.id === channel2.id` as it is much faster and is often * what most users need. * @param {GroupDMChannel} channel The channel to compare to * @returns {boolean} */ equals(channel) { const equal = channel && this.id === channel.id && this.name === channel.name && this.icon === channel.icon && this.ownerID === channel.ownerID; if (equal) { const thisIDs = this.recipients.keyArray(); const otherIDs = channel.recipients.keyArray(); return arraysEqual(thisIDs, otherIDs); } return equal; } /** * When concatenated with a string, this automatically concatenates the channel's name instead of the Channel object. * @returns {string} * @example * // logs: Hello from My Group DM! * console.log(`Hello from ${channel}!`); * @example * // logs: Hello from My Group DM! * console.log(`Hello from ' + channel + '!'); */ toString() { return this.name; } // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } fetchMessages() { return; } fetchPinnedMessages() { return; } startTyping() { return; } stopTyping() { return; } get typing() { return; } get typingCount() { return; } createCollector() { return; } awaitMessages() { return; } bulkDelete() { return; } _cacheMessage() { return; } } TextBasedChannel.applyToClass(GroupDMChannel, true); module.exports = GroupDMChannel; /***/ }, /* 30 */ /***/ function(module, exports, __webpack_require__) { const PartialGuild = __webpack_require__(36); const PartialGuildChannel = __webpack_require__(37); const Constants = __webpack_require__(0); /* { max_age: 86400, code: 'CG9A5', guild: { splash: null, id: '123123123', icon: '123123123', name: 'name' }, created_at: '2016-08-28T19:07:04.763368+00:00', temporary: false, uses: 0, max_uses: 0, inviter: { username: '123', discriminator: '4204', bot: true, id: '123123123', avatar: '123123123' }, channel: { type: 0, id: '123123', name: 'heavy-testing' } } */ /** * Represents an invitation to a guild channel. * The only guaranteed properties are `code`, `guild` and `channel`. Other properties can be missing. */ class Invite { constructor(client, data) { /** * The client that instantiated the invite * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); this.setup(data); } setup(data) { /** * The guild the invite is for. If this guild is already known, this will be a Guild object. If the guild is * unknown, this will be a PartialGuild object. * @type {Guild|PartialGuild} */ this.guild = this.client.guilds.get(data.guild.id) || new PartialGuild(this.client, data.guild); /** * The code for this invite * @type {string} */ this.code = data.code; /** * Whether or not this invite is temporary * @type {boolean} */ this.temporary = data.temporary; /** * The maximum age of the invite, in seconds * @type {?number} */ this.maxAge = data.max_age; /** * How many times this invite has been used * @type {number} */ this.uses = data.uses; /** * The maximum uses of this invite * @type {number} */ this.maxUses = data.max_uses; if (data.inviter) { /** * The user who created this invite * @type {User} */ this.inviter = this.client.dataManager.newUser(data.inviter); } /** * The channel the invite is for. If this channel is already known, this will be a GuildChannel object. * If the channel is unknown, this will be a PartialGuildChannel object. * @type {GuildChannel|PartialGuildChannel} */ this.channel = this.client.channels.get(data.channel.id) || new PartialGuildChannel(this.client, data.channel); /** * The timestamp the invite was created at * @type {number} */ this.createdTimestamp = new Date(data.created_at).getTime(); } /** * The time the invite was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * The timestamp the invite will expire at * @type {number} * @readonly */ get expiresTimestamp() { return this.createdTimestamp + (this.maxAge * 1000); } /** * The time the invite will expire * @type {Date} * @readonly */ get expiresAt() { return new Date(this.expiresTimestamp); } /** * The URL to the invite * @type {string} * @readonly */ get url() { return Constants.Endpoints.inviteLink(this.code); } /** * Deletes this invite * @returns {Promise} */ delete() { return this.client.rest.methods.deleteInvite(this); } /** * When concatenated with a string, this automatically concatenates the invite's URL instead of the object. * @returns {string} * @example * // logs: Invite: https://discord.gg/A1b2C3 * console.log(`Invite: ${invite}`); */ toString() { return this.url; } } module.exports = Invite; /***/ }, /* 31 */ /***/ function(module, exports) { /** * Represents an attachment in a message */ class MessageAttachment { constructor(message, data) { /** * The Client that instantiated this MessageAttachment. * @type {Client} */ this.client = message.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The message this attachment is part of. * @type {Message} */ this.message = message; this.setup(data); } setup(data) { /** * The ID of this attachment * @type {string} */ this.id = data.id; /** * The file name of this attachment * @type {string} */ this.filename = data.filename; /** * The size of this attachment in bytes * @type {number} */ this.filesize = data.size; /** * The URL to this attachment * @type {string} */ this.url = data.url; /** * The Proxy URL to this attachment * @type {string} */ this.proxyURL = data.proxy_url; /** * The height of this attachment (if an image) * @type {?number} */ this.height = data.height; /** * The width of this attachment (if an image) * @type {?number} */ this.width = data.width; } } module.exports = MessageAttachment; /***/ }, /* 32 */ /***/ function(module, exports, __webpack_require__) { const EventEmitter = __webpack_require__(21).EventEmitter; const Collection = __webpack_require__(3); /** * Collects messages based on a specified filter, then emits them. * @extends {EventEmitter} */ class MessageCollector extends EventEmitter { /** * A function that takes a Message object and a MessageCollector and returns a boolean. * ```js * function(message, collector) { * if (message.content.includes('discord')) { * return true; // passed the filter test * } * return false; // failed the filter test * } * ``` * @typedef {function} CollectorFilterFunction */ /** * An object containing options used to configure a MessageCollector. All properties are optional. * @typedef {Object} CollectorOptions * @property {number} [time] Duration for the collector in milliseconds * @property {number} [max] Maximum number of messages to handle * @property {number} [maxMatches] Maximum number of successfully filtered messages to obtain */ /** * @param {Channel} channel The channel to collect messages in * @param {CollectorFilterFunction} filter The filter function * @param {CollectorOptions} [options] Options for the collector */ constructor(channel, filter, options = {}) { super(); /** * The channel this collector is operating on * @type {Channel} */ this.channel = channel; /** * A function used to filter messages that the collector collects. * @type {CollectorFilterFunction} */ this.filter = filter; /** * Options for the collecor. * @type {CollectorOptions} */ this.options = options; /** * Whether this collector has stopped collecting messages. * @type {boolean} */ this.ended = false; /** * A collection of collected messages, mapped by message ID. * @type {Collection} */ this.collected = new Collection(); this.listener = message => this.verify(message); this.channel.client.on('message', this.listener); if (options.time) this.channel.client.setTimeout(() => this.stop('time'), options.time); } /** * Verifies a message against the filter and options * @private * @param {Message} message The message * @returns {boolean} */ verify(message) { if (this.channel ? this.channel.id !== message.channel.id : false) return false; if (this.filter(message, this)) { this.collected.set(message.id, message); /** * Emitted whenever the collector receives a message that passes the filter test. * @param {Message} message The received message * @param {MessageCollector} collector The collector the message passed through * @event MessageCollector#message */ this.emit('message', message, this); if (this.collected.size >= this.options.maxMatches) this.stop('matchesLimit'); else if (this.options.max && this.collected.size === this.options.max) this.stop('limit'); return true; } return false; } /** * Returns a promise that resolves when a valid message is sent. Rejects * with collected messages if the Collector ends before receiving a message. * @type {Promise} * @readonly */ get next() { return new Promise((resolve, reject) => { if (this.ended) { reject(this.collected); return; } const cleanup = () => { this.removeListener('message', onMessage); this.removeListener('end', onEnd); }; const onMessage = (...args) => { cleanup(); resolve(...args); }; const onEnd = (...args) => { cleanup(); reject(...args); }; this.once('message', onMessage); this.once('end', onEnd); }); } /** * Stops the collector and emits `end`. * @param {string} [reason='user'] An optional reason for stopping the collector */ stop(reason = 'user') { if (this.ended) return; this.ended = true; this.channel.client.removeListener('message', this.listener); /** * Emitted when the Collector stops collecting. * @param {Collection} collection A collection of messages collected * during the lifetime of the collector, mapped by the ID of the messages. * @param {string} reason The reason for the end of the collector. If it ended because it reached the specified time * limit, this would be `time`. If you invoke `.stop()` without specifying a reason, this would be `user`. If it * ended because it reached its message limit, it will be `limit`. * @event MessageCollector#end */ this.emit('end', this.collected, reason); } } module.exports = MessageCollector; /***/ }, /* 33 */ /***/ function(module, exports) { /** * Represents an embed in a message (image/video preview, rich embed, etc.) */ class MessageEmbed { constructor(message, data) { /** * The client that instantiated this embed * @type {Client} */ this.client = message.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * The message this embed is part of * @type {Message} */ this.message = message; this.setup(data); } setup(data) { /** * The title of this embed, if there is one * @type {?string} */ this.title = data.title; /** * The type of this embed * @type {string} */ this.type = data.type; /** * The description of this embed, if there is one * @type {?string} */ this.description = data.description; /** * The URL of this embed * @type {string} */ this.url = data.url; /** * The fields of this embed * @type {MessageEmbedField[]} */ this.fields = []; if (data.fields) for (const field of data.fields) this.fields.push(new MessageEmbedField(this, field)); /** * The timestamp of this embed * @type {number} */ this.createdTimestamp = data.timestamp; /** * The thumbnail of this embed, if there is one * @type {MessageEmbedThumbnail} */ this.thumbnail = data.thumbnail ? new MessageEmbedThumbnail(this, data.thumbnail) : null; /** * The author of this embed, if there is one * @type {MessageEmbedAuthor} */ this.author = data.author ? new MessageEmbedAuthor(this, data.author) : null; /** * The provider of this embed, if there is one * @type {MessageEmbedProvider} */ this.provider = data.provider ? new MessageEmbedProvider(this, data.provider) : null; /** * The footer of this embed * @type {MessageEmbedFooter} */ this.footer = data.footer ? new MessageEmbedFooter(this, data.footer) : null; } /** * The date this embed was created * @type {Date} */ get createdAt() { return new Date(this.createdTimestamp); } } /** * Represents a thumbnail for a message embed */ class MessageEmbedThumbnail { constructor(embed, data) { /** * The embed this thumbnail is part of * @type {MessageEmbed} */ this.embed = embed; this.setup(data); } setup(data) { /** * The URL for this thumbnail * @type {string} */ this.url = data.url; /** * The Proxy URL for this thumbnail * @type {string} */ this.proxyURL = data.proxy_url; /** * The height of the thumbnail * @type {number} */ this.height = data.height; /** * The width of the thumbnail * @type {number} */ this.width = data.width; } } /** * Represents a provider for a message embed */ class MessageEmbedProvider { constructor(embed, data) { /** * The embed this provider is part of * @type {MessageEmbed} */ this.embed = embed; this.setup(data); } setup(data) { /** * The name of this provider * @type {string} */ this.name = data.name; /** * The URL of this provider * @type {string} */ this.url = data.url; } } /** * Represents an author for a message embed */ class MessageEmbedAuthor { constructor(embed, data) { /** * The embed this author is part of * @type {MessageEmbed} */ this.embed = embed; this.setup(data); } setup(data) { /** * The name of this author * @type {string} */ this.name = data.name; /** * The URL of this author * @type {string} */ this.url = data.url; } } /** * Represents a field for a message embed */ class MessageEmbedField { constructor(embed, data) { /** * The embed this footer is part of * @type {MessageEmbed} */ this.embed = embed; this.setup(data); } setup(data) { /** * The name of this field * @type {string} */ this.name = data.name; /** * The value of this field * @type {string} */ this.value = data.value; /** * If this field is displayed inline * @type {boolean} */ this.inline = data.inline; } } /** * Represents the footer of a message embed */ class MessageEmbedFooter { constructor(embed, data) { /** * The embed this footer is part of * @type {MessageEmbed} */ this.embed = embed; this.setup(data); } setup(data) { /** * The text in this footer * @type {string} */ this.text = data.text; /** * The icon URL of this footer * @type {string} */ this.iconUrl = data.icon_url; /** * The proxy icon URL of this footer * @type {string} */ this.proxyIconUrl = data.proxy_icon_url; } } MessageEmbed.Thumbnail = MessageEmbedThumbnail; MessageEmbed.Provider = MessageEmbedProvider; MessageEmbed.Author = MessageEmbedAuthor; MessageEmbed.Field = MessageEmbedField; MessageEmbed.Footer = MessageEmbedFooter; module.exports = MessageEmbed; /***/ }, /* 34 */ /***/ function(module, exports, __webpack_require__) { const Collection = __webpack_require__(3); const Emoji = __webpack_require__(9); const ReactionEmoji = __webpack_require__(19); /** * Represents a reaction to a message */ class MessageReaction { constructor(message, emoji, count, me) { /** * The message that this reaction refers to * @type {Message} */ this.message = message; /** * Whether the client has given this reaction * @type {boolean} */ this.me = me; /** * The number of people that have given the same reaction. * @type {number} */ this.count = count || 0; /** * The users that have given this reaction, mapped by their ID. * @type {Collection} */ this.users = new Collection(); this._emoji = new ReactionEmoji(this, emoji.name, emoji.id); } /** * The emoji of this reaction, either an Emoji object for known custom emojis, or a ReactionEmoji * object which has fewer properties. Whatever the prototype of the emoji, it will still have * `name`, `id`, `identifier` and `toString()` * @type {Emoji|ReactionEmoji} */ get emoji() { if (this._emoji instanceof Emoji) return this._emoji; // check to see if the emoji has become known to the client if (this._emoji.id) { const emojis = this.message.client.emojis; if (emojis.has(this._emoji.id)) { const emoji = emojis.get(this._emoji.id); this._emoji = emoji; return emoji; } } return this._emoji; } /** * Removes a user from this reaction. * @param {UserResolvable} [user] the user that you want to remove the reaction, defaults to the client. * @returns {Promise} */ remove(user = this.message.client.user) { const message = this.message; user = this.message.client.resolver.resolveUserID(user); if (!user) return Promise.reject('Couldn\'t resolve the user ID to remove from the reaction.'); return message.client.rest.methods.removeMessageReaction( message, this.emoji.identifier, user ); } /** * Fetch all the users that gave this reaction. Resolves with a collection of users, * mapped by their IDs. * @param {number} [limit=100] the maximum amount of users to fetch, defaults to 100 * @returns {Promise>} */ fetchUsers(limit = 100) { const message = this.message; return message.client.rest.methods.getMessageReactionUsers( message, this.emoji.identifier, limit ).then(users => { this.users = new Collection(); for (const rawUser of users) { const user = this.message.client.dataManager.newUser(rawUser); this.users.set(user.id, user); } this.count = this.users.size; return users; }); } } module.exports = MessageReaction; /***/ }, /* 35 */ /***/ function(module, exports) { /** * Represents an OAuth2 Application */ class OAuth2Application { constructor(client, data) { /** * The client that instantiated the application * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); this.setup(data); } setup(data) { /** * The ID of the app * @type {string} */ this.id = data.id; /** * The name of the app * @type {string} */ this.name = data.name; /** * The app's description * @type {string} */ this.description = data.description; /** * The app's icon hash * @type {string} */ this.icon = data.icon; /** * The app's icon URL * @type {string} */ this.iconURL = `https://cdn.discordapp.com/app-icons/${this.id}/${this.icon}.jpg`; /** * The app's RPC origins * @type {Array} */ this.rpcOrigins = data.rpc_origins; } /** * The timestamp the app was created at * @type {number} * @readonly */ get createdTimestamp() { return (this.id / 4194304) + 1420070400000; } /** * The time the app was created * @type {Date} * @readonly */ get createdAt() { return new Date(this.createdTimestamp); } /** * When concatenated with a string, this automatically concatenates the app name rather than the app object. * @returns {string} */ toString() { return this.name; } } module.exports = OAuth2Application; /***/ }, /* 36 */ /***/ function(module, exports) { /* { splash: null, id: '123123123', icon: '123123123', name: 'name' } */ /** * Represents a guild that the client only has limited information for - e.g. from invites. */ class PartialGuild { constructor(client, data) { /** * The Client that instantiated this PartialGuild * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); this.setup(data); } setup(data) { /** * The ID of this guild * @type {string} */ this.id = data.id; /** * The name of this guild * @type {string} */ this.name = data.name; /** * The hash of this guild's icon, or null if there is none. * @type {?string} */ this.icon = data.icon; /** * The hash of the guild splash image, or null if no splash (VIP only) * @type {?string} */ this.splash = data.splash; } } module.exports = PartialGuild; /***/ }, /* 37 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); /* { type: 0, id: '123123', name: 'heavy-testing' } } */ /** * Represents a guild channel that the client only has limited information for - e.g. from invites. */ class PartialGuildChannel { constructor(client, data) { /** * The Client that instantiated this PartialGuildChannel * @type {Client} */ this.client = client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); this.setup(data); } setup(data) { /** * The ID of this guild channel * @type {string} */ this.id = data.id; /** * The name of this guild channel * @type {string} */ this.name = data.name; /** * The type of this guild channel - `text` or `voice` * @type {string} */ this.type = Constants.ChannelTypes.text === data.type ? 'text' : 'voice'; } } module.exports = PartialGuildChannel; /***/ }, /* 38 */ /***/ function(module, exports) { /** * Represents a permission overwrite for a role or member in a guild channel. */ class PermissionOverwrites { constructor(guildChannel, data) { /** * The GuildChannel this overwrite is for * @type {GuildChannel} */ this.channel = guildChannel; if (data) this.setup(data); } setup(data) { /** * The ID of this overwrite, either a user ID or a role ID * @type {string} */ this.id = data.id; /** * The type of this overwrite * @type {string} */ this.type = data.type; this.denyData = data.deny; this.allowData = data.allow; } /** * Delete this Permission Overwrite. * @returns {Promise} */ delete() { return this.channel.client.rest.methods.deletePermissionOverwrites(this); } } module.exports = PermissionOverwrites; /***/ }, /* 39 */ /***/ function(module, exports, __webpack_require__) { const GuildChannel = __webpack_require__(11); const TextBasedChannel = __webpack_require__(10); const Collection = __webpack_require__(3); /** * Represents a guild text channel on Discord. * @extends {GuildChannel} * @implements {TextBasedChannel} */ class TextChannel extends GuildChannel { constructor(guild, data) { super(guild, data); this.type = 'text'; this.messages = new Collection(); this._typing = new Map(); } setup(data) { super.setup(data); /** * The topic of the text channel, if there is one. * @type {?string} */ this.topic = data.topic; this.lastMessageID = data.last_message_id; } /** * A collection of members that can see this channel, mapped by their ID. * @type {Collection} * @readonly */ get members() { const members = new Collection(); for (const member of this.guild.members.values()) { if (this.permissionsFor(member).hasPermission('READ_MESSAGES')) { members.set(member.id, member); } } return members; } /** * Fetch all webhooks for the channel. * @returns {Promise>} */ fetchWebhooks() { return this.client.rest.methods.getChannelWebhooks(this); } /** * Create a webhook for the channel. * @param {string} name The name of the webhook. * @param {BufferResolvable} avatar The avatar for the webhook. * @returns {Promise} webhook The created webhook. * @example * channel.createWebhook('Snek', 'http://snek.s3.amazonaws.com/topSnek.png') * .then(webhook => console.log(`Created Webhook ${webhook}`)) * .catch(console.error) */ createWebhook(name, avatar) { return new Promise(resolve => { if (avatar.startsWith('data:')) { resolve(this.client.rest.methods.createWebhook(this, name, avatar)); } else { this.client.resolver.resolveBuffer(avatar).then(data => resolve(this.client.rest.methods.createWebhook(this, name, data)) ); } }); } // These are here only for documentation purposes - they are implemented by TextBasedChannel sendMessage() { return; } sendTTSMessage() { return; } sendFile() { return; } sendCode() { return; } fetchMessage() { return; } fetchMessages() { return; } fetchPinnedMessages() { return; } startTyping() { return; } stopTyping() { return; } get typing() { return; } get typingCount() { return; } createCollector() { return; } awaitMessages() { return; } bulkDelete() { return; } _cacheMessage() { return; } } TextBasedChannel.applyToClass(TextChannel, true); module.exports = TextChannel; /***/ }, /* 40 */ /***/ function(module, exports, __webpack_require__) { const GuildChannel = __webpack_require__(11); const Collection = __webpack_require__(3); /** * Represents a guild voice channel on Discord. * @extends {GuildChannel} */ class VoiceChannel extends GuildChannel { constructor(guild, data) { super(guild, data); /** * The members in this voice channel. * @type {Collection} */ this.members = new Collection(); this.type = 'voice'; } setup(data) { super.setup(data); /** * The bitrate of this voice channel * @type {number} */ this.bitrate = data.bitrate; /** * The maximum amount of users allowed in this channel - 0 means unlimited. * @type {number} */ this.userLimit = data.user_limit; } /** * The voice connection for this voice channel, if the client is connected * @type {?VoiceConnection} * @readonly */ get connection() { const connection = this.guild.voiceConnection; if (connection && connection.channel.id === this.id) return connection; return null; } /** * Checks if the client has permission join the voice channel * @type {boolean} */ get joinable() { if (this.client.browser) return false; return this.permissionsFor(this.client.user).hasPermission('CONNECT'); } /** * Checks if the client has permission to send audio to the voice channel * @type {boolean} */ get speakable() { return this.permissionsFor(this.client.user).hasPermission('SPEAK'); } /** * Sets the bitrate of the channel * @param {number} bitrate The new bitrate * @returns {Promise} * @example * // set the bitrate of a voice channel * voiceChannel.setBitrate(48000) * .then(vc => console.log(`Set bitrate to ${vc.bitrate} for ${vc.name}`)) * .catch(console.error); */ setBitrate(bitrate) { return this.edit({ bitrate }); } /** * Sets the user limit of the channel * @param {number} userLimit The new user limit * @returns {Promise} * @example * // set the user limit of a voice channel * voiceChannel.setUserLimit(42) * .then(vc => console.log(`Set user limit to ${vc.userLimit} for ${vc.name}`)) * .catch(console.error); */ setUserLimit(userLimit) { return this.edit({ userLimit }); } /** * Attempts to join this voice channel * @returns {Promise} * @example * // join a voice channel * voiceChannel.join() * .then(connection => console.log('Connected!')) * .catch(console.error); */ join() { if (this.client.browser) return Promise.reject(new Error('Voice connections are not available in browsers.')); return this.client.voice.joinChannel(this); } /** * Leaves this voice channel * @example * // leave a voice channel * voiceChannel.leave(); */ leave() { if (this.client.browser) return; const connection = this.client.voice.connections.get(this.guild.id); if (connection && connection.channel.id === this.id) connection.disconnect(); } } module.exports = VoiceChannel; /***/ }, /* 41 */ /***/ function(module, exports) { module.exports = function splitMessage(text, { maxLength = 1950, char = '\n', prepend = '', append = '' } = {}) { if (text.length <= maxLength) return text; const splitText = text.split(char); if (splitText.length === 1) throw new Error('Message exceeds the max length and contains no split characters.'); const messages = ['']; let msg = 0; for (let i = 0; i < splitText.length; i++) { if (messages[msg].length + splitText[i].length + 1 > maxLength) { messages[msg] += append; messages.push(prepend); msg++; } messages[msg] += (messages[msg].length > 0 && messages[msg] !== prepend ? char : '') + splitText[i]; } return messages; }; /***/ }, /* 42 */ /***/ function(module, exports) { /** * Check if `obj` is an object. * * @param {Object} obj * @return {Boolean} * @api private */ function isObject(obj) { return null !== obj && 'object' === typeof obj; } module.exports = isObject; /***/ }, /* 43 */ /***/ function(module, exports) { /***/ }, /* 44 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer) {const path = __webpack_require__(22); const fs = __webpack_require__(43); const request = __webpack_require__(23); const Constants = __webpack_require__(0); const convertArrayBuffer = __webpack_require__(47); const User = __webpack_require__(5); const Message = __webpack_require__(13); const Guild = __webpack_require__(18); const Channel = __webpack_require__(8); const GuildMember = __webpack_require__(12); const Emoji = __webpack_require__(9); const ReactionEmoji = __webpack_require__(19); /** * The DataResolver identifies different objects and tries to resolve a specific piece of information from them, e.g. * extracting a User from a Message object. * @private */ class ClientDataResolver { /** * @param {Client} client The client the resolver is for */ constructor(client) { this.client = client; } /** * Data that resolves to give a User object. This can be: * * A User object * * A user ID * * A Message object (resolves to the message author) * * A Guild object (owner of the guild) * * A GuildMember object * @typedef {User|string|Message|Guild|GuildMember} UserResolvable */ /** * Resolves a UserResolvable to a User object * @param {UserResolvable} user The UserResolvable to identify * @returns {?User} */ resolveUser(user) { if (user instanceof User) return user; if (typeof user === 'string') return this.client.users.get(user) || null; if (user instanceof GuildMember) return user.user; if (user instanceof Message) return user.author; if (user instanceof Guild) return user.owner; return null; } /** * Resolves a UserResolvable to a user ID string * @param {UserResolvable} user The UserResolvable to identify * @returns {?string} */ resolveUserID(user) { if (user instanceof User || user instanceof GuildMember) return user.id; if (typeof user === 'string') return user || null; if (user instanceof Message) return user.author.id; if (user instanceof Guild) return user.ownerID; return null; } /** * Data that resolves to give a Guild object. This can be: * * A Guild object * @typedef {Guild} GuildResolvable */ /** * Resolves a GuildResolvable to a Guild object * @param {GuildResolvable} guild The GuildResolvable to identify * @returns {?Guild} */ resolveGuild(guild) { if (guild instanceof Guild) return guild; if (typeof guild === 'string') return this.client.guilds.get(guild) || null; return null; } /** * Data that resolves to give a GuildMember object. This can be: * * A GuildMember object * * A User object * @typedef {Guild} GuildMemberResolvable */ /** * Resolves a GuildMemberResolvable to a GuildMember object * @param {GuildResolvable} guild The guild that the member is part of * @param {UserResolvable} user The user that is part of the guild * @returns {?GuildMember} */ resolveGuildMember(guild, user) { if (user instanceof GuildMember) return user; guild = this.resolveGuild(guild); user = this.resolveUser(user); if (!guild || !user) return null; return guild.members.get(user.id) || null; } /** * Data that can be resolved to give a Channel. This can be: * * A Channel object * * A Message object (the channel the message was sent in) * * A Guild object (the #general channel) * * A channel ID * @typedef {Channel|Guild|Message|string} ChannelResolvable */ /** * Resolves a ChannelResolvable to a Channel object * @param {ChannelResolvable} channel The channel resolvable to resolve * @returns {?Channel} */ resolveChannel(channel) { if (channel instanceof Channel) return channel; if (channel instanceof Message) return channel.channel; if (channel instanceof Guild) return channel.channels.get(channel.id) || null; if (typeof channel === 'string') return this.client.channels.get(channel) || null; return null; } /** * Data that can be resolved to give an invite code. This can be: * * An invite code * * An invite URL * @typedef {string} InviteResolvable */ /** * Resolves InviteResolvable to an invite code * @param {InviteResolvable} data The invite resolvable to resolve * @returns {string} */ resolveInviteCode(data) { const inviteRegex = /discord(?:app)?\.(?:gg|com\/invite)\/([a-z0-9]{5})/i; const match = inviteRegex.exec(data); if (match && match[1]) return match[1]; return data; } /** * Data that can be resolved to give a permission number. This can be: * * A string * * A permission number * * Possible strings: * ```js * [ * "CREATE_INSTANT_INVITE", * "KICK_MEMBERS", * "BAN_MEMBERS", * "ADMINISTRATOR", * "MANAGE_CHANNELS", * "MANAGE_GUILD", * "ADD_REACTIONS", // add reactions to messages * "READ_MESSAGES", * "SEND_MESSAGES", * "SEND_TTS_MESSAGES", * "MANAGE_MESSAGES", * "EMBED_LINKS", * "ATTACH_FILES", * "READ_MESSAGE_HISTORY", * "MENTION_EVERYONE", * "EXTERNAL_EMOJIS", // use external emojis * "CONNECT", // connect to voice * "SPEAK", // speak on voice * "MUTE_MEMBERS", // globally mute members on voice * "DEAFEN_MEMBERS", // globally deafen members on voice * "MOVE_MEMBERS", // move member's voice channels * "USE_VAD", // use voice activity detection * "CHANGE_NICKNAME", * "MANAGE_NICKNAMES", // change nicknames of others * "MANAGE_ROLES_OR_PERMISSIONS" * ] * ``` * @typedef {string|number} PermissionResolvable */ /** * Resolves a PermissionResolvable to a permission number * @param {PermissionResolvable} permission The permission resolvable to resolve * @returns {number} */ resolvePermission(permission) { if (typeof permission === 'string') permission = Constants.PermissionFlags[permission]; if (typeof permission !== 'number' || permission < 1) throw new Error(Constants.Errors.NOT_A_PERMISSION); return permission; } /** * Data that can be resolved to give a string. This can be: * * A string * * An array (joined with a new line delimiter to give a string) * * Any value * @typedef {string|Array|*} StringResolvable */ /** * Resolves a StringResolvable to a string * @param {StringResolvable} data The string resolvable to resolve * @returns {string} */ resolveString(data) { if (typeof data === 'string') return data; if (data instanceof Array) return data.join('\n'); return String(data); } /** * Data that resolves to give a Base64 string, typically for image uploading. This can be: * * A Buffer * * A base64 string * @typedef {Buffer|string} Base64Resolvable */ /** * Resolves a Base64Resolvable to a Base 64 image * @param {Base64Resolvable} data The base 64 resolvable you want to resolve * @returns {?string} */ resolveBase64(data) { if (data instanceof Buffer) return `data:image/jpg;base64,${data.toString('base64')}`; return data; } /** * Data that can be resolved to give a Buffer. This can be: * * A Buffer * * The path to a local file * * A URL * @typedef {string|Buffer} BufferResolvable */ /** * Resolves a BufferResolvable to a Buffer * @param {BufferResolvable} resource The buffer resolvable to resolve * @returns {Promise} */ resolveBuffer(resource) { if (resource instanceof Buffer) return Promise.resolve(resource); if (this.client.browser && resource instanceof ArrayBuffer) return Promise.resolve(convertArrayBuffer(resource)); if (typeof resource === 'string') { return new Promise((resolve, reject) => { if (/^https?:\/\//.test(resource)) { const req = request.get(resource).set('Content-Type', 'blob'); if (this.client.browser) req.responseType('arraybuffer'); req.end((err, res) => { if (err) return reject(err); if (this.client.browser) return resolve(convertArrayBuffer(res.xhr.response)); if (!(res.body instanceof Buffer)) return reject(new TypeError('Body is not a Buffer')); return resolve(res.body); }); } else { const file = path.resolve(resource); fs.stat(file, (err, stats) => { if (err) reject(err); if (!stats || !stats.isFile()) throw new Error(`The file could not be found: ${file}`); fs.readFile(file, (err2, data) => { if (err2) reject(err2); else resolve(data); }); }); } }); } return Promise.reject(new TypeError('The resource must be a string or Buffer.')); } /** * Data that can be resolved to give an emoji identifier. This can be: * * A string * * An Emoji * * A ReactionEmoji * @typedef {string|Emoji|ReactionEmoji} EmojiIdentifierResolvable */ /** * Resolves an EmojiResolvable to an emoji identifier * @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve * @returns {string} */ resolveEmojiIdentifier(emoji) { if (emoji instanceof Emoji || emoji instanceof ReactionEmoji) return emoji.identifier; if (typeof emoji === 'string') { if (!emoji.includes('%')) return encodeURIComponent(emoji); } return null; } } module.exports = ClientDataResolver; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15).Buffer)) /***/ }, /* 45 */ /***/ function(module, exports, __webpack_require__) { const UserAgentManager = __webpack_require__(96); const RESTMethods = __webpack_require__(93); const SequentialRequestHandler = __webpack_require__(95); const BurstRequestHandler = __webpack_require__(94); const APIRequest = __webpack_require__(92); const Constants = __webpack_require__(0); class RESTManager { constructor(client) { this.client = client; this.handlers = {}; this.userAgentManager = new UserAgentManager(this); this.methods = new RESTMethods(this); this.rateLimitedEndpoints = {}; this.globallyRateLimited = false; } push(handler, apiRequest) { return new Promise((resolve, reject) => { handler.push({ request: apiRequest, resolve, reject, }); }); } getRequestHandler() { switch (this.client.options.apiRequestMethod) { case 'sequential': return SequentialRequestHandler; case 'burst': return BurstRequestHandler; default: throw new Error(Constants.Errors.INVALID_RATE_LIMIT_METHOD); } } makeRequest(method, url, auth, data, file) { const apiRequest = new APIRequest(this, method, url, auth, data, file); if (!this.handlers[apiRequest.route]) { const RequestHandlerType = this.getRequestHandler(); this.handlers[apiRequest.route] = new RequestHandlerType(this, apiRequest.route); } return this.push(this.handlers[apiRequest.route], apiRequest); } } module.exports = RESTManager; /***/ }, /* 46 */ /***/ function(module, exports) { /** * A base class for different types of rate limiting handlers for the REST API. * @private */ class RequestHandler { /** * @param {RESTManager} restManager The REST manager to use */ constructor(restManager) { /** * The RESTManager that instantiated this RequestHandler * @type {RESTManager} */ this.restManager = restManager; /** * A list of requests that have yet to be processed. * @type {APIRequest[]} */ this.queue = []; } /** * Whether or not the client is being rate limited on every endpoint. * @type {boolean} */ get globalLimit() { return this.restManager.globallyRateLimited; } set globalLimit(value) { this.restManager.globallyRateLimited = value; } /** * Push a new API request into this bucket * @param {APIRequest} request The new request to push into the queue */ push(request) { this.queue.push(request); } /** * Attempts to get this RequestHandler to process its current queue */ handle() { return; } } module.exports = RequestHandler; /***/ }, /* 47 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(Buffer) {function arrayBufferToBuffer(ab) { const buffer = new Buffer(ab.byteLength); const view = new Uint8Array(ab); for (var i = 0; i < buffer.length; ++i) buffer[i] = view[i]; return buffer; } function str2ab(str) { const buffer = new ArrayBuffer(str.length * 2); const view = new Uint16Array(buffer); for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i); return buffer; } module.exports = function convertArrayBuffer(x) { if (typeof x === 'string') x = str2ab(x); return arrayBufferToBuffer(x); }; /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(15).Buffer)) /***/ }, /* 48 */ /***/ function(module, exports) { module.exports = function merge(def, given) { if (!given) return def; for (const key in def) { if (!{}.hasOwnProperty.call(given, key)) { given[key] = def[key]; } else if (given[key] === Object(given[key])) { given[key] = merge(def[key], given[key]); } } return given; }; /***/ }, /* 49 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process) {const EventEmitter = __webpack_require__(21).EventEmitter; const mergeDefault = __webpack_require__(48); const Constants = __webpack_require__(0); const RESTManager = __webpack_require__(45); const ClientDataManager = __webpack_require__(63); const ClientManager = __webpack_require__(64); const ClientDataResolver = __webpack_require__(44); const ClientVoiceManager = __webpack_require__(136); const WebSocketManager = __webpack_require__(97); const ActionsManager = __webpack_require__(65); const Collection = __webpack_require__(3); const Presence = __webpack_require__(6).Presence; const ShardClientUtil = __webpack_require__(135); /** * The starting point for making a Discord Bot. * @extends {EventEmitter} */ class Client extends EventEmitter { /** * @param {ClientOptions} [options] Options for the client */ constructor(options = {}) { super(); // Obtain shard details from environment if (!options.shardId && 'SHARD_ID' in process.env) options.shardId = Number(process.env.SHARD_ID); if (!options.shardCount && 'SHARD_COUNT' in process.env) options.shardCount = Number(process.env.SHARD_COUNT); /** * The options the client was instantiated with * @type {ClientOptions} */ this.options = mergeDefault(Constants.DefaultOptions, options); this._validateOptions(); /** * The REST manager of the client * @type {RESTManager} * @private */ this.rest = new RESTManager(this); /** * The data manager of the Client * @type {ClientDataManager} * @private */ this.dataManager = new ClientDataManager(this); /** * The manager of the Client * @type {ClientManager} * @private */ this.manager = new ClientManager(this); /** * The WebSocket Manager of the Client * @type {WebSocketManager} * @private */ this.ws = new WebSocketManager(this); /** * The Data Resolver of the Client * @type {ClientDataResolver} * @private */ this.resolver = new ClientDataResolver(this); /** * The Action Manager of the Client * @type {ActionsManager} * @private */ this.actions = new ActionsManager(this); /** * The Voice Manager of the Client (`null` in browsers) * @type {?ClientVoiceManager} * @private */ this.voice = !this.browser ? new ClientVoiceManager(this) : null; /** * The shard helpers for the client (only if the process was spawned as a child, such as from a ShardingManager) * @type {?ShardClientUtil} */ this.shard = process.send ? ShardClientUtil.singleton(this) : null; /** * A collection of the Client's stored users * @type {Collection} */ this.users = new Collection(); /** * A collection of the Client's stored guilds * @type {Collection} */ this.guilds = new Collection(); /** * A collection of the Client's stored channels * @type {Collection} */ this.channels = new Collection(); /** * A collection of presences for friends of the logged in user. * This is only filled when using a user account. * @type {Collection} */ this.presences = new Collection(); if (!this.token && 'CLIENT_TOKEN' in process.env) { /** * The authorization token for the logged in user/bot. * @type {?string} */ this.token = process.env.CLIENT_TOKEN; } else { this.token = null; } /** * The email, if there is one, for the logged in Client * @type {?string} */ this.email = null; /** * The password, if there is one, for the logged in Client * @type {?string} */ this.password = null; /** * The ClientUser representing the logged in Client * @type {?ClientUser} */ this.user = null; /** * The date at which the Client was regarded as being in the `READY` state. * @type {?Date} */ this.readyAt = null; this._timeouts = new Set(); this._intervals = new Set(); if (this.options.messageSweepInterval > 0) { this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000); } } /** * The status for the logged in Client. * @type {?number} * @readonly */ get status() { return this.ws.status; } /** * The uptime for the logged in Client. * @type {?number} * @readonly */ get uptime() { return this.readyAt ? Date.now() - this.readyAt : null; } /** * Returns a collection, mapping guild ID to voice connections. * @type {Collection} * @readonly */ get voiceConnections() { if (this.browser) return new Collection(); return this.voice.connections; } /** * The emojis that the client can use. Mapped by emoji ID. * @type {Collection} * @readonly */ get emojis() { const emojis = new Collection(); for (const guild of this.guilds.values()) { for (const emoji of guild.emojis.values()) emojis.set(emoji.id, emoji); } return emojis; } /** * The timestamp that the client was last ready at * @type {?number} * @readonly */ get readyTimestamp() { return this.readyAt ? this.readyAt.getTime() : null; } /** * Whether the client is in a browser environment * @type {boolean} * @readonly */ get browser() { return typeof window !== 'undefined'; } /** * Logs the client in. If successful, resolves with the account's token. If you're making a bot, it's * much better to use a bot account rather than a user account. * Bot accounts have higher rate limits and have access to some features user accounts don't have. User bots * that are making a lot of API requests can even be banned. * @param {string} tokenOrEmail The token or email used for the account. If it is an email, a password _must_ be * provided. * @param {string} [password] The password for the account, only needed if an email was provided. * @returns {Promise} * @example * // log the client in using a token * const token = 'my token'; * client.login(token); * @example * // log the client in using email and password * const email = 'user@email.com'; * const password = 'supersecret123'; * client.login(email, password); */ login(tokenOrEmail, password = null) { if (password) return this.rest.methods.loginEmailPassword(tokenOrEmail, password); return this.rest.methods.loginToken(tokenOrEmail); } /** * Destroys the client and logs out. * @returns {Promise} */ destroy() { for (const t of this._timeouts) clearTimeout(t); for (const i of this._intervals) clearInterval(i); this._timeouts.clear(); this._intervals.clear(); this.token = null; this.email = null; this.password = null; return this.manager.destroy(); } /** * This shouldn't really be necessary to most developers as it is automatically invoked every 30 seconds, however * if you wish to force a sync of guild data, you can use this. * This is only available when using a user account. * @param {Guild[]|Collection} [guilds=this.guilds] An array or collection of guilds to sync */ syncGuilds(guilds = this.guilds) { if (this.user.bot) return; this.ws.send({ op: 12, d: guilds instanceof Collection ? guilds.keyArray() : guilds.map(g => g.id), }); } /** * Caches a user, or obtains it from the cache if it's already cached. * This is only available when using a bot account. * @param {string} id The ID of the user to obtain * @returns {Promise} */ fetchUser(id) { if (this.users.has(id)) return Promise.resolve(this.users.get(id)); return this.rest.methods.getUser(id); } /** * Fetches an invite object from an invite code. * @param {InviteResolvable} invite An invite code or URL * @returns {Promise} */ fetchInvite(invite) { const code = this.resolver.resolveInviteCode(invite); return this.rest.methods.getInvite(code); } /** * Fetch a webhook by ID. * @param {string} id ID of the webhook * @param {string} [token] Token for the webhook * @returns {Promise} */ fetchWebhook(id, token) { return this.rest.methods.getWebhook(id, token); } /** * Sweeps all channels' messages and removes the ones older than the max message lifetime. * If the message has been edited, the time of the edit is used rather than the time of the original message. * @param {number} [lifetime=this.options.messageCacheLifetime] Messages that are older than this (in seconds) * will be removed from the caches. The default is based on the client's `messageCacheLifetime` option. * @returns {number} Amount of messages that were removed from the caches, * or -1 if the message cache lifetime is unlimited */ sweepMessages(lifetime = this.options.messageCacheLifetime) { if (typeof lifetime !== 'number' || isNaN(lifetime)) throw new TypeError('The lifetime must be a number.'); if (lifetime <= 0) { this.emit('debug', 'Didn\'t sweep messages - lifetime is unlimited'); return -1; } const lifetimeMs = lifetime * 1000; const now = Date.now(); let channels = 0; let messages = 0; for (const channel of this.channels.values()) { if (!channel.messages) continue; channels++; for (const message of channel.messages.values()) { if (now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs) { channel.messages.delete(message.id); messages++; } } } this.emit('debug', `Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`); return messages; } /** * Gets the bot's OAuth2 application. * This is only available when using a bot account. * @returns {Promise} */ fetchApplication() { if (!this.user.bot) throw new Error(Constants.Errors.NO_BOT_ACCOUNT); return this.rest.methods.getMyApplication(); } /** * Sets a timeout that will be automatically cancelled if the client is destroyed. * @param {Function} fn Function to execute * @param {number} delay Time to wait before executing (in milliseconds) * @param {args} args Arguments for the function (infinite/rest argument, not an array) * @returns {Timeout} */ setTimeout(fn, delay, ...args) { const timeout = setTimeout(() => { fn(); this._timeouts.delete(timeout); }, delay, ...args); this._timeouts.add(timeout); return timeout; } /** * Clears a timeout * @param {Timeout} timeout Timeout to cancel */ clearTimeout(timeout) { clearTimeout(timeout); this._timeouts.delete(timeout); } /** * Sets an interval that will be automatically cancelled if the client is destroyed. * @param {Function} fn Function to execute * @param {number} delay Time to wait before executing (in milliseconds) * @param {args} args Arguments for the function (infinite/rest argument, not an array) * @returns {Timeout} */ setInterval(fn, delay, ...args) { const interval = setInterval(fn, delay, ...args); this._intervals.add(interval); return interval; } /** * Clears an interval * @param {Timeout} interval Interval to cancel */ clearInterval(interval) { clearInterval(interval); this._intervals.delete(interval); } _setPresence(id, presence) { if (this.presences.get(id)) { this.presences.get(id).update(presence); return; } this.presences.set(id, new Presence(presence)); } _eval(script) { return eval(script); } _validateOptions(options = this.options) { if (typeof options.shardCount !== 'number' || isNaN(options.shardCount)) { throw new TypeError('The shardCount option must be a number.'); } if (typeof options.shardId !== 'number' || isNaN(options.shardId)) { throw new TypeError('The shardId option must be a number.'); } if (options.shardCount < 0) throw new RangeError('The shardCount option must be at least 0.'); if (options.shardId < 0) throw new RangeError('The shardId option must be at least 0.'); if (options.shardId !== 0 && options.shardId >= options.shardCount) { throw new RangeError('The shardId option must be less than shardCount.'); } if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) { throw new TypeError('The messageCacheMaxSize option must be a number.'); } if (typeof options.messageCacheLifetime !== 'number' || isNaN(options.messageCacheLifetime)) { throw new TypeError('The messageCacheLifetime option must be a number.'); } if (typeof options.messageSweepInterval !== 'number' || isNaN(options.messageSweepInterval)) { throw new TypeError('The messageSweepInterval option must be a number.'); } if (typeof options.fetchAllMembers !== 'boolean') { throw new TypeError('The fetchAllMembers option must be a boolean.'); } if (typeof options.disableEveryone !== 'boolean') { throw new TypeError('The disableEveryone option must be a boolean.'); } if (typeof options.restWsBridgeTimeout !== 'number' || isNaN(options.restWsBridgeTimeout)) { throw new TypeError('The restWsBridgeTimeout option must be a number.'); } if (!(options.disabledEvents instanceof Array)) throw new TypeError('The disabledEvents option must be an Array.'); } } module.exports = Client; /** * Emitted for general warnings * @event Client#warn * @param {string} The warning */ /** * Emitted for general debugging information * @event Client#debug * @param {string} The debug information */ /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(16))) /***/ }, /* 50 */ /***/ function(module, exports, __webpack_require__) { const Webhook = __webpack_require__(20); const RESTManager = __webpack_require__(45); const ClientDataResolver = __webpack_require__(44); const mergeDefault = __webpack_require__(48); const Constants = __webpack_require__(0); /** * The Webhook Client * @extends {Webhook} */ class WebhookClient extends Webhook { /** * @param {string} id The id of the webhook. * @param {string} token the token of the webhook. * @param {ClientOptions} [options] Options for the client * @example * // create a new webhook and send a message * let hook = new Discord.WebhookClient('1234', 'abcdef') * hook.sendMessage('This will send a message').catch(console.error) */ constructor(id, token, options) { super(null, id, token); /** * The options the client was instantiated with * @type {ClientOptions} */ this.options = mergeDefault(Constants.DefaultOptions, options); /** * The REST manager of the client * @type {RESTManager} * @private */ this.rest = new RESTManager(this); /** * The Data Resolver of the Client * @type {ClientDataResolver} * @private */ this.resolver = new ClientDataResolver(this); } } module.exports = WebhookClient; /***/ }, /* 51 */ /***/ function(module, exports, __webpack_require__) { const superagent = __webpack_require__(23); const botGateway = __webpack_require__(0).Endpoints.botGateway; /** * Gets the recommended shard count from Discord * @param {number} token Discord auth token * @returns {Promise} the recommended number of shards */ module.exports = function fetchRecommendedShards(token) { return new Promise((resolve, reject) => { if (!token) throw new Error('A token must be provided.'); superagent.get(botGateway) .set('Authorization', `Bot ${token.replace(/^Bot\s*/i, '')}`) .end((err, res) => { if (err) reject(err); resolve(res.body.shards); }); }); }; /***/ }, /* 52 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 53 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 54 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 55 */ /***/ function(module, exports) { "use strict"; 'use strict' exports.byteLength = byteLength exports.toByteArray = toByteArray exports.fromByteArray = fromByteArray var lookup = [] var revLookup = [] var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' for (var i = 0, len = code.length; i < len; ++i) { lookup[i] = code[i] revLookup[code.charCodeAt(i)] = i } revLookup['-'.charCodeAt(0)] = 62 revLookup['_'.charCodeAt(0)] = 63 function placeHoldersCount (b64) { var len = b64.length if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } // the number of equal signs (place holders) // if there are two placeholders, than the two characters before it // represent one byte // if there is only one, then the three characters before it represent 2 bytes // this is just a cheap hack to not do indexOf twice return b64[len - 2] === '=' ? 2 : b64[len - 1] === '=' ? 1 : 0 } function byteLength (b64) { // base64 is 4/3 + up to two characters of the original data return b64.length * 3 / 4 - placeHoldersCount(b64) } function toByteArray (b64) { var i, j, l, tmp, placeHolders, arr var len = b64.length placeHolders = placeHoldersCount(b64) arr = new Arr(len * 3 / 4 - placeHolders) // if there are placeholders, only get up to the last complete 4 chars l = placeHolders > 0 ? len - 4 : len var L = 0 for (i = 0, j = 0; i < l; i += 4, j += 3) { tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] arr[L++] = (tmp >> 16) & 0xFF arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } if (placeHolders === 2) { tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) arr[L++] = tmp & 0xFF } else if (placeHolders === 1) { tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) arr[L++] = (tmp >> 8) & 0xFF arr[L++] = tmp & 0xFF } return arr } function tripletToBase64 (num) { return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F] } function encodeChunk (uint8, start, end) { var tmp var output = [] for (var i = start; i < end; i += 3) { tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray (uint8) { var tmp var len = uint8.length var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes var output = '' var parts = [] var maxChunkLength = 16383 // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { parts.push(encodeChunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength))) } // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { tmp = uint8[len - 1] output += lookup[tmp >> 2] output += lookup[(tmp << 4) & 0x3F] output += '==' } else if (extraBytes === 2) { tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) output += lookup[tmp >> 10] output += lookup[(tmp >> 4) & 0x3F] output += lookup[(tmp << 2) & 0x3F] output += '=' } parts.push(output) return parts.join('') } /***/ }, /* 56 */ /***/ function(module, exports, __webpack_require__) { /** * Expose `Emitter`. */ if (true) { module.exports = Emitter; } /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; (this._callbacks['$' + event] = this._callbacks['$' + event] || []) .push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function(event, fn){ function on() { this.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function(event, fn){ this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks['$' + event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks['$' + event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function(event){ this._callbacks = this._callbacks || {}; var args = [].slice.call(arguments, 1) , callbacks = this._callbacks['$' + event]; if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function(event){ this._callbacks = this._callbacks || {}; return this._callbacks['$' + event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function(event){ return !! this.listeners(event).length; }; /***/ }, /* 57 */ /***/ function(module, exports) { exports.read = function (buffer, offset, isLE, mLen, nBytes) { var e, m var eLen = nBytes * 8 - mLen - 1 var eMax = (1 << eLen) - 1 var eBias = eMax >> 1 var nBits = -7 var i = isLE ? (nBytes - 1) : 0 var d = isLE ? -1 : 1 var s = buffer[offset + i] i += d e = s & ((1 << (-nBits)) - 1) s >>= (-nBits) nBits += eLen for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} m = e & ((1 << (-nBits)) - 1) e >>= (-nBits) nBits += mLen for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { e = 1 - eBias } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { m = m + Math.pow(2, mLen) e = e - eBias } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) } exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { var e, m, c var eLen = nBytes * 8 - mLen - 1 var eMax = (1 << eLen) - 1 var eBias = eMax >> 1 var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) var i = isLE ? 0 : (nBytes - 1) var d = isLE ? 1 : -1 var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 value = Math.abs(value) if (isNaN(value) || value === Infinity) { m = isNaN(value) ? 1 : 0 e = eMax } else { e = Math.floor(Math.log(value) / Math.LN2) if (value * (c = Math.pow(2, -e)) < 1) { e-- c *= 2 } if (e + eBias >= 1) { value += rt / c } else { value += rt * Math.pow(2, 1 - eBias) } if (value * c >= 2) { e++ c /= 2 } if (e + eBias >= eMax) { m = 0 e = eMax } else if (e + eBias >= 1) { m = (value * c - 1) * Math.pow(2, mLen) e = e + eBias } else { m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) e = 0 } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} e = (e << mLen) | m eLen += mLen for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128 } /***/ }, /* 58 */ /***/ function(module, exports) { var toString = {}.toString; module.exports = Array.isArray || function (arr) { return toString.call(arr) == '[object Array]'; }; /***/ }, /* 59 */ /***/ function(module, exports, __webpack_require__) { /** * Module of mixed-in functions shared between node and client code */ var isObject = __webpack_require__(42); /** * Expose `RequestBase`. */ module.exports = RequestBase; /** * Initialize a new `RequestBase`. * * @api public */ function RequestBase(obj) { if (obj) return mixin(obj); } /** * Mixin the prototype properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in RequestBase.prototype) { obj[key] = RequestBase.prototype[key]; } return obj; } /** * Clear previous timeout. * * @return {Request} for chaining * @api public */ RequestBase.prototype.clearTimeout = function _clearTimeout(){ this._timeout = 0; clearTimeout(this._timer); return this; }; /** * Override default response body parser * * This function will be called to convert incoming data into request.body * * @param {Function} * @api public */ RequestBase.prototype.parse = function parse(fn){ this._parser = fn; return this; }; /** * Override default request body serializer * * This function will be called to convert data set via .send or .attach into payload to send * * @param {Function} * @api public */ RequestBase.prototype.serialize = function serialize(fn){ this._serializer = fn; return this; }; /** * Set timeout to `ms`. * * @param {Number} ms * @return {Request} for chaining * @api public */ RequestBase.prototype.timeout = function timeout(ms){ this._timeout = ms; return this; }; /** * Promise support * * @param {Function} resolve * @param {Function} reject * @return {Request} */ RequestBase.prototype.then = function then(resolve, reject) { if (!this._fullfilledPromise) { var self = this; this._fullfilledPromise = new Promise(function(innerResolve, innerReject){ self.end(function(err, res){ if (err) innerReject(err); else innerResolve(res); }); }); } return this._fullfilledPromise.then(resolve, reject); } RequestBase.prototype.catch = function(cb) { return this.then(undefined, cb); }; /** * Allow for extension */ RequestBase.prototype.use = function use(fn) { fn(this); return this; } /** * Get request header `field`. * Case-insensitive. * * @param {String} field * @return {String} * @api public */ RequestBase.prototype.get = function(field){ return this._header[field.toLowerCase()]; }; /** * Get case-insensitive header `field` value. * This is a deprecated internal API. Use `.get(field)` instead. * * (getHeader is no longer used internally by the superagent code base) * * @param {String} field * @return {String} * @api private * @deprecated */ RequestBase.prototype.getHeader = RequestBase.prototype.get; /** * Set header `field` to `val`, or multiple fields with one object. * Case-insensitive. * * Examples: * * req.get('/') * .set('Accept', 'application/json') * .set('X-API-Key', 'foobar') * .end(callback); * * req.get('/') * .set({ Accept: 'application/json', 'X-API-Key': 'foobar' }) * .end(callback); * * @param {String|Object} field * @param {String} val * @return {Request} for chaining * @api public */ RequestBase.prototype.set = function(field, val){ if (isObject(field)) { for (var key in field) { this.set(key, field[key]); } return this; } this._header[field.toLowerCase()] = val; this.header[field] = val; return this; }; /** * Remove header `field`. * Case-insensitive. * * Example: * * req.get('/') * .unset('User-Agent') * .end(callback); * * @param {String} field */ RequestBase.prototype.unset = function(field){ delete this._header[field.toLowerCase()]; delete this.header[field]; return this; }; /** * Write the field `name` and `val`, or multiple fields with one object * for "multipart/form-data" request bodies. * * ``` js * request.post('/upload') * .field('foo', 'bar') * .end(callback); * * request.post('/upload') * .field({ foo: 'bar', baz: 'qux' }) * .end(callback); * ``` * * @param {String|Object} name * @param {String|Blob|File|Buffer|fs.ReadStream} val * @return {Request} for chaining * @api public */ RequestBase.prototype.field = function(name, val) { // name should be either a string or an object. if (null === name || undefined === name) { throw new Error('.field(name, val) name can not be empty'); } if (isObject(name)) { for (var key in name) { this.field(key, name[key]); } return this; } // val should be defined now if (null === val || undefined === val) { throw new Error('.field(name, val) val can not be empty'); } this._getFormData().append(name, val); return this; }; /** * Abort the request, and clear potential timeout. * * @return {Request} * @api public */ RequestBase.prototype.abort = function(){ if (this._aborted) { return this; } this._aborted = true; this.xhr && this.xhr.abort(); // browser this.req && this.req.abort(); // node this.clearTimeout(); this.emit('abort'); return this; }; /** * Enable transmission of cookies with x-domain requests. * * Note that for this to work the origin must not be * using "Access-Control-Allow-Origin" with a wildcard, * and also must set "Access-Control-Allow-Credentials" * to "true". * * @api public */ RequestBase.prototype.withCredentials = function(){ // This is browser-only functionality. Node side is no-op. this._withCredentials = true; return this; }; /** * Set the max redirects to `n`. Does noting in browser XHR implementation. * * @param {Number} n * @return {Request} for chaining * @api public */ RequestBase.prototype.redirects = function(n){ this._maxRedirects = n; return this; }; /** * Convert to a plain javascript object (not JSON string) of scalar properties. * Note as this method is designed to return a useful non-this value, * it cannot be chained. * * @return {Object} describing method, url, and data of this request * @api public */ RequestBase.prototype.toJSON = function(){ return { method: this.method, url: this.url, data: this._data, headers: this._header }; }; /** * Send `data` as the request body, defaulting the `.type()` to "json" when * an object is given. * * Examples: * * // manual json * request.post('/user') * .type('json') * .send('{"name":"tj"}') * .end(callback) * * // auto json * request.post('/user') * .send({ name: 'tj' }) * .end(callback) * * // manual x-www-form-urlencoded * request.post('/user') * .type('form') * .send('name=tj') * .end(callback) * * // auto x-www-form-urlencoded * request.post('/user') * .type('form') * .send({ name: 'tj' }) * .end(callback) * * // defaults to x-www-form-urlencoded * request.post('/user') * .send('name=tobi') * .send('species=ferret') * .end(callback) * * @param {String|Object} data * @return {Request} for chaining * @api public */ RequestBase.prototype.send = function(data){ var isObj = isObject(data); var type = this._header['content-type']; if (isObj && !this._data) { if (Array.isArray(data)) { this._data = []; } else if (!this._isHost(data)) { this._data = {}; } } else if (data && this._data && this._isHost(this._data)) { throw Error("Can't merge these send calls"); } // merge if (isObj && isObject(this._data)) { for (var key in data) { this._data[key] = data[key]; } } else if ('string' == typeof data) { // default to x-www-form-urlencoded if (!type) this.type('form'); type = this._header['content-type']; if ('application/x-www-form-urlencoded' == type) { this._data = this._data ? this._data + '&' + data : data; } else { this._data = (this._data || '') + data; } } else { this._data = data; } if (!isObj || this._isHost(data)) return this; // default to json if (!type) this.type('json'); return this; }; /***/ }, /* 60 */ /***/ function(module, exports) { // The node and browser modules expose versions of this with the // appropriate constructor function bound as first argument /** * Issue a request: * * Examples: * * request('GET', '/users').end(callback) * request('/users').end(callback) * request('/users', callback) * * @param {String} method * @param {String|Function} url or callback * @return {Request} * @api public */ function request(RequestConstructor, method, url) { // callback if ('function' == typeof url) { return new RequestConstructor('GET', method).end(url); } // url first if (2 == arguments.length) { return new RequestConstructor('GET', method); } return new RequestConstructor(method, url); } module.exports = request; /***/ }, /* 61 */ /***/ function(module, exports) { var g; // This works in non-strict mode g = (function() { return this; })(); try { // This works if eval is allowed (see CSP) g = g || Function("return this")() || (1,eval)("this"); } catch(e) { // This works if the window reference is available if(typeof window === "object") g = window; } // g can still be undefined, but nothing to do about it... // We return undefined, instead of nothing here, so it's // easier to handle this case. if(!global) { ...} module.exports = g; /***/ }, /* 62 */ /***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process, Buffer) {/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function q(b){throw b;}var t=void 0,v=!0;var A="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function E(b,a){this.index="number"===typeof a?a:0;this.m=0;this.buffer=b instanceof(A?Uint8Array:Array)?b:new (A?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&q(Error("invalid index"));this.buffer.length<=this.index&&this.f()}E.prototype.f=function(){var b=this.buffer,a,c=b.length,d=new (A?Uint8Array:Array)(c<<1);if(A)d.set(b);else for(a=0;a>>8&255]<<16|G[b>>>16&255]<<8|G[b>>>24&255])>>32-a:G[b]>>8-a);if(8>a+f)g=g<>a-k-1&1,8===++f&&(f=0,d[e++]=G[g],g=0,e===d.length&&(d=this.f()));d[e]=g;this.buffer=d;this.m=f;this.index=e};E.prototype.finish=function(){var b=this.buffer,a=this.index,c;0J;++J){for(var N=J,Q=N,ba=7,N=N>>>1;N;N>>>=1)Q<<=1,Q|=N&1,--ba;aa[J]=(Q<>>0}var G=aa;function R(b,a,c){var d,e="number"===typeof a?a:a=0,f="number"===typeof c?c:b.length;d=-1;for(e=f&7;e--;++a)d=d>>>8^S[(d^b[a])&255];for(e=f>>3;e--;a+=8)d=d>>>8^S[(d^b[a])&255],d=d>>>8^S[(d^b[a+1])&255],d=d>>>8^S[(d^b[a+2])&255],d=d>>>8^S[(d^b[a+3])&255],d=d>>>8^S[(d^b[a+4])&255],d=d>>>8^S[(d^b[a+5])&255],d=d>>>8^S[(d^b[a+6])&255],d=d>>>8^S[(d^b[a+7])&255];return(d^4294967295)>>>0} var ga=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759, 2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977, 2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755, 2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956, 3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270, 936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],S=A?new Uint32Array(ga):ga;function ha(){};function ia(b){this.buffer=new (A?Uint16Array:Array)(2*b);this.length=0}ia.prototype.getParent=function(b){return 2*((b-2)/4|0)};ia.prototype.push=function(b,a){var c,d,e=this.buffer,f;c=this.length;e[this.length++]=a;for(e[this.length++]=b;0e[d])f=e[c],e[c]=e[d],e[d]=f,f=e[c+1],e[c+1]=e[d+1],e[d+1]=f,c=d;else break;return this.length}; ia.prototype.pop=function(){var b,a,c=this.buffer,d,e,f;a=c[0];b=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(f=0;;){e=2*f+2;if(e>=this.length)break;e+2c[e]&&(e+=2);if(c[e]>c[f])d=c[f],c[f]=c[e],c[e]=d,d=c[f+1],c[f+1]=c[e+1],c[e+1]=d;else break;f=e}return{index:b,value:a,length:this.length}};function ja(b){var a=b.length,c=0,d=Number.POSITIVE_INFINITY,e,f,g,k,h,l,s,p,m,n;for(p=0;pc&&(c=b[p]),b[p]>=1;n=g<<16|p;for(m=l;mT;T++)switch(v){case 143>=T:pa.push([T+48,8]);break;case 255>=T:pa.push([T-144+400,9]);break;case 279>=T:pa.push([T-256+0,7]);break;case 287>=T:pa.push([T-280+192,8]);break;default:q("invalid literal: "+T)} ma.prototype.h=function(){var b,a,c,d,e=this.input;switch(this.k){case 0:c=0;for(d=e.length;c>>8&255;m[n++]=l&255;m[n++]=l>>>8&255;if(A)m.set(f,n),n+=f.length,m=m.subarray(0,n);else{s=0;for(p=f.length;sz)for(;0< z--;)H[F++]=0,L[0]++;else for(;0z?z:138,C>z-3&&C=C?(H[F++]=17,H[F++]=C-3,L[17]++):(H[F++]=18,H[F++]=C-11,L[18]++),z-=C;else if(H[F++]=I[w],L[I[w]]++,z--,3>z)for(;0z?z:6,C>z-3&&CB;B++)sa[B]=ka[qb[B]];for(W=19;4=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272, a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:q("invalid length: "+a)}}var a=[],c,d;for(c=3;258>=c;c++)d=b(c),a[c]=d[2]<<24|d[1]<< 16|d[0];return a}(),xa=A?new Uint32Array(wa):wa; function qa(b,a){function c(a,c){var b=a.O,d=[],f=0,e;e=xa[a.length];d[f++]=e&65535;d[f++]=e>>16&255;d[f++]=e>>24;var g;switch(v){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b- 65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>= b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:q("invalid distance")}e=g;d[f++]=e[0];d[f++]=e[1];d[f++]=e[2];var h,k;h=0;for(k=d.length;h=f;)u[f++]=0;for(f=0;29>=f;)x[f++]=0}u[256]=1;d=0;for(e=a.length;d=e){p&&c(p,-1);f=0;for(g=e-d;fg&&a+gf&&(e=d,f=g);if(258===g)break}return new ua(f,a-e)} function ra(b,a){var c=b.length,d=new ia(572),e=new (A?Uint8Array:Array)(c),f,g,k,h,l;if(!A)for(h=0;h2*e[n-1]+f[n]&&(e[n]=2*e[n-1]+f[n]),k[n]=Array(e[n]),h[n]=Array(e[n]);for(m=0;mb[m]?(k[n][r]=u,h[n][r]=a,x+=2):(k[n][r]=b[m],h[n][r]=m,++m);l[n]=0;1===f[n]&&d(n)}return g} function ta(b){var a=new (A?Uint16Array:Array)(b.length),c=[],d=[],e=0,f,g,k,h;f=0;for(g=b.length;f>>=1}return a};function Aa(b,a){this.input=b;this.b=this.c=0;this.g={};a&&(a.flags&&(this.g=a.flags),"string"===typeof a.filename&&(this.filename=a.filename),"string"===typeof a.comment&&(this.w=a.comment),a.deflateOptions&&(this.l=a.deflateOptions));this.l||(this.l={})} Aa.prototype.h=function(){var b,a,c,d,e,f,g,k,h=new (A?Uint8Array:Array)(32768),l=0,s=this.input,p=this.c,m=this.filename,n=this.w;h[l++]=31;h[l++]=139;h[l++]=8;b=0;this.g.fname&&(b|=Ba);this.g.fcomment&&(b|=Ca);this.g.fhcrc&&(b|=Da);h[l++]=b;a=(Date.now?Date.now():+new Date)/1E3|0;h[l++]=a&255;h[l++]=a>>>8&255;h[l++]=a>>>16&255;h[l++]=a>>>24&255;h[l++]=0;h[l++]=Sa;if(this.g.fname!==t){g=0;for(k=m.length;g>>8&255),h[l++]=f&255;h[l++]=0}if(this.g.comment){g= 0;for(k=n.length;g>>8&255),h[l++]=f&255;h[l++]=0}this.g.fhcrc&&(c=R(h,0,l)&65535,h[l++]=c&255,h[l++]=c>>>8&255);this.l.outputBuffer=h;this.l.outputIndex=l;e=new ma(s,this.l);h=e.h();l=e.b;A&&(l+8>h.buffer.byteLength?(this.a=new Uint8Array(l+8),this.a.set(new Uint8Array(h.buffer)),h=this.a):h=new Uint8Array(h.buffer));d=R(s,t,t);h[l++]=d&255;h[l++]=d>>>8&255;h[l++]=d>>>16&255;h[l++]=d>>>24&255;k=s.length;h[l++]=k&255;h[l++]=k>>>8&255;h[l++]=k>>>16&255;h[l++]= k>>>24&255;this.c=p;A&&l>>=1;switch(b){case 0:var a=this.input,c=this.c,d=this.a,e=this.b,f=a.length,g=t,k=t,h=d.length,l=t;this.e=this.j=0;c+1>=f&&q(Error("invalid uncompressed block header: LEN"));g=a[c++]|a[c++]<<8;c+1>=f&&q(Error("invalid uncompressed block header: NLEN"));k=a[c++]|a[c++]<<8;g===~k&&q(Error("invalid uncompressed block header: length verify"));c+g>a.length&&q(Error("input buffer is broken"));switch(this.q){case Ua:for(;e+g>d.length;){l= h-e;g-=l;if(A)d.set(a.subarray(c,c+l),e),e+=l,c+=l;else for(;l--;)d[e++]=a[c++];this.b=e;d=this.f();e=this.b}break;case Ta:for(;e+g>d.length;)d=this.f({B:2});break;default:q(Error("invalid inflate mode"))}if(A)d.set(a.subarray(c,c+g),e),e+=g,c+=g;else for(;g--;)d[e++]=a[c++];this.c=c;this.b=e;this.a=d;break;case 1:this.r(Va,Wa);break;case 2:Xa(this);break;default:q(Error("unknown BTYPE: "+b))}}return this.z()}; var Ya=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],Za=A?new Uint16Array(Ya):Ya,$a=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],ab=A?new Uint16Array($a):$a,bb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],cb=A?new Uint8Array(bb):bb,db=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],eb=A?new Uint16Array(db):db,fb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10, 10,11,11,12,12,13,13],gb=A?new Uint8Array(fb):fb,hb=new (A?Uint8Array:Array)(288),$,ib;$=0;for(ib=hb.length;$=$?8:255>=$?9:279>=$?7:8;var Va=ja(hb),jb=new (A?Uint8Array:Array)(30),kb,lb;kb=0;for(lb=jb.length;kb=g&&q(Error("input buffer is broken")),c|=e[f++]<>>a;b.e=d-a;b.c=f;return k} function mb(b,a){for(var c=b.j,d=b.e,e=b.input,f=b.c,g=e.length,k=a[0],h=a[1],l,s;d=g);)c|=e[f++]<>>16;b.j=c>>s;b.e=d-s;b.c=f;return l&65535} function Xa(b){function a(a,b,c){var d,e=this.I,f,g;for(g=0;gf)d>=e&&(this.b=d,c=this.f(),d=this.b),c[d++]=f;else{g=f-257;h=ab[g];0=e&&(this.b=d,c=this.f(),d=this.b);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d}; Y.prototype.R=function(b,a){var c=this.a,d=this.b;this.A=b;for(var e=c.length,f,g,k,h;256!==(f=mb(this,b));)if(256>f)d>=e&&(c=this.f(),e=c.length),c[d++]=f;else{g=f-257;h=ab[g];0e&&(c=this.f(),e=c.length);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d}; Y.prototype.f=function(){var b=new (A?Uint8Array:Array)(this.b-32768),a=this.b-32768,c,d,e=this.a;if(A)b.set(e.subarray(32768,b.length));else{c=0;for(d=b.length;cc;++c)e[c]=e[a+c];this.b=32768;return e}; Y.prototype.T=function(b){var a,c=this.input.length/this.c+1|0,d,e,f,g=this.input,k=this.a;b&&("number"===typeof b.B&&(c=b.B),"number"===typeof b.N&&(c+=b.N));2>c?(d=(g.length-this.c)/this.A[2],f=258*(d/2)|0,e=fa&&(this.a.length=a),b=this.a);return this.buffer=b};function nb(b){this.input=b;this.c=0;this.G=[];this.S=!1} nb.prototype.i=function(){for(var b=this.input.length;this.c>>0;R(e,t,t)!==s&&q(Error("invalid CRC-32 checksum: 0x"+R(e,t,t).toString(16)+" / 0x"+ s.toString(16)));a.$=c=(p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24)>>>0;(e.length&4294967295)!==c&&q(Error("invalid input size: "+(e.length&4294967295)+" / "+c));this.G.push(a);this.c=m}this.S=v;var n=this.G,r,u,x=0,O=0,y;r=0;for(u=n.length;r>>0;b=a}for(var e=1,f=0,g=b.length,k,h=0;0>>0};function pb(b,a){var c,d;this.input=b;this.c=0;if(a||!(a={}))a.index&&(this.c=a.index),a.verify&&(this.W=a.verify);c=b[this.c++];d=b[this.c++];switch(c&15){case rb:this.method=rb;break;default:q(Error("unsupported compression method"))}0!==((c<<8)+d)%31&&q(Error("invalid fcheck flag:"+((c<<8)+d)%31));d&32&&q(Error("fdict flag is not supported"));this.K=new Y(b,{index:this.c,bufferSize:a.bufferSize,bufferType:a.bufferType,resize:a.resize})} pb.prototype.i=function(){var b=this.input,a,c;a=this.K.i();this.c=this.K.c;this.W&&(c=(b[this.c++]<<24|b[this.c++]<<16|b[this.c++]<<8|b[this.c++])>>>0,c!==ob(a)&&q(Error("invalid adler-32 checksum")));return a};var rb=8;function sb(b,a){this.input=b;this.a=new (A?Uint8Array:Array)(32768);this.k=tb.t;var c={},d;if((a||!(a={}))&&"number"===typeof a.compressionType)this.k=a.compressionType;for(d in a)c[d]=a[d];c.outputBuffer=this.a;this.J=new ma(this.input,c)}var tb=oa; sb.prototype.h=function(){var b,a,c,d,e,f,g,k=0;g=this.a;b=rb;switch(b){case rb:a=Math.LOG2E*Math.log(32768)-8;break;default:q(Error("invalid compression method"))}c=a<<4|b;g[k++]=c;switch(b){case rb:switch(this.k){case tb.NONE:e=0;break;case tb.M:e=1;break;case tb.t:e=2;break;default:q(Error("unsupported compression type"))}break;default:q(Error("invalid compression method"))}d=e<<6|0;g[k++]=d|31-(256*c+d)%31;f=ob(this.input);this.J.b=k;g=this.J.h();k=g.length;A&&(g=new Uint8Array(g.buffer),g.length<= k+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,k+4));g[k++]=f>>24&255;g[k++]=f>>16&255;g[k++]=f>>8&255;g[k++]=f&255;return g};exports.deflate=ub;exports.deflateSync=vb;exports.inflate=wb;exports.inflateSync=xb;exports.gzip=yb;exports.gzipSync=zb;exports.gunzip=Ab;exports.gunzipSync=Bb;function ub(b,a,c){process.nextTick(function(){var d,e;try{e=vb(b,c)}catch(f){d=f}a(d,e)})}function vb(b,a){var c;c=(new sb(b)).h();a||(a={});return a.H?c:Cb(c)}function wb(b,a,c){process.nextTick(function(){var d,e;try{e=xb(b,c)}catch(f){d=f}a(d,e)})} function xb(b,a){var c;b.subarray=b.slice;c=(new pb(b)).i();a||(a={});return a.noBuffer?c:Cb(c)}function yb(b,a,c){process.nextTick(function(){var d,e;try{e=zb(b,c)}catch(f){d=f}a(d,e)})}function zb(b,a){var c;b.subarray=b.slice;c=(new Aa(b)).h();a||(a={});return a.H?c:Cb(c)}function Ab(b,a,c){process.nextTick(function(){var d,e;try{e=Bb(b,c)}catch(f){d=f}a(d,e)})}function Bb(b,a){var c;b.subarray=b.slice;c=(new nb(b)).i();a||(a={});return a.H?c:Cb(c)} function Cb(b){var a=new Buffer(b.length),c,d;c=0;for(d=b.length;c { this.client.emit(Constants.Events.GUILD_CREATE, guild); }); } else { this.client.emit(Constants.Events.GUILD_CREATE, guild); } } return guild; } newUser(data) { if (this.client.users.has(data.id)) return this.client.users.get(data.id); const user = new User(this.client, data); this.client.users.set(user.id, user); return user; } newChannel(data, guild) { const already = this.client.channels.has(data.id); let channel; if (data.type === Constants.ChannelTypes.DM) { channel = new DMChannel(this.client, data); } else if (data.type === Constants.ChannelTypes.groupDM) { channel = new GroupDMChannel(this.client, data); } else { guild = guild || this.client.guilds.get(data.guild_id); if (guild) { if (data.type === Constants.ChannelTypes.text) { channel = new TextChannel(guild, data); guild.channels.set(channel.id, channel); } else if (data.type === Constants.ChannelTypes.voice) { channel = new VoiceChannel(guild, data); guild.channels.set(channel.id, channel); } } } if (channel) { if (this.pastReady && !already) this.client.emit(Constants.Events.CHANNEL_CREATE, channel); this.client.channels.set(channel.id, channel); return channel; } return null; } newEmoji(data, guild) { const already = guild.emojis.has(data.id); if (data && !already) { let emoji = new Emoji(guild, data); this.client.emit(Constants.Events.EMOJI_CREATE, emoji); guild.emojis.set(emoji.id, emoji); return emoji; } else if (already) { return guild.emojis.get(data.id); } return null; } killEmoji(emoji) { if (!(emoji instanceof Emoji && emoji.guild)) return; this.client.emit(Constants.Events.EMOJI_DELETE, emoji); emoji.guild.emojis.delete(emoji.id); } killGuild(guild) { const already = this.client.guilds.has(guild.id); this.client.guilds.delete(guild.id); if (already && this.pastReady) this.client.emit(Constants.Events.GUILD_DELETE, guild); } killUser(user) { this.client.users.delete(user.id); } killChannel(channel) { this.client.channels.delete(channel.id); if (channel instanceof GuildChannel) channel.guild.channels.delete(channel.id); } updateGuild(currentGuild, newData) { const oldGuild = cloneObject(currentGuild); currentGuild.setup(newData); if (this.pastReady) this.client.emit(Constants.Events.GUILD_UPDATE, oldGuild, currentGuild); } updateChannel(currentChannel, newData) { currentChannel.setup(newData); } updateEmoji(currentEmoji, newData) { const oldEmoji = cloneObject(currentEmoji); currentEmoji.setup(newData); this.client.emit(Constants.Events.GUILD_EMOJI_UPDATE, oldEmoji, currentEmoji); } } module.exports = ClientDataManager; /***/ }, /* 64 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); /** * Manages the State and Background Tasks of the Client * @private */ class ClientManager { constructor(client) { /** * The Client that instantiated this Manager * @type {Client} */ this.client = client; /** * The heartbeat interval, null if not yet set * @type {?number} */ this.heartbeatInterval = null; } /** * Connects the Client to the WebSocket * @param {string} token The authorization token * @param {Function} resolve Function to run when connection is successful * @param {Function} reject Function to run when connection fails */ connectToWebSocket(token, resolve, reject) { this.client.emit(Constants.Events.DEBUG, `Authenticated using token ${token}`); this.client.token = token; const timeout = this.client.setTimeout(() => reject(new Error(Constants.Errors.TOOK_TOO_LONG)), 1000 * 300); this.client.rest.methods.getGateway().then(gateway => { this.client.emit(Constants.Events.DEBUG, `Using gateway ${gateway}`); this.client.ws.connect(gateway); this.client.ws.once('close', event => { if (event.code === 4004) reject(new Error(Constants.Errors.BAD_LOGIN)); if (event.code === 4010) reject(new Error(Constants.Errors.INVALID_SHARD)); }); this.client.once(Constants.Events.READY, () => { resolve(token); this.client.clearTimeout(timeout); }); }, reject); } /** * Sets up a keep-alive interval to keep the Client's connection valid * @param {number} time The interval in milliseconds at which heartbeat packets should be sent */ setupKeepAlive(time) { this.heartbeatInterval = this.client.setInterval(() => { this.client.emit('debug', 'Sending heartbeat'); this.client.ws.send({ op: Constants.OPCodes.HEARTBEAT, d: this.client.ws.sequence, }, true); }, time); } destroy() { return new Promise(resolve => { this.client.ws.destroy(); if (!this.client.user.bot) { resolve(this.client.rest.methods.logout()); } else { resolve(); } }); } } module.exports = ClientManager; /***/ }, /* 65 */ /***/ function(module, exports, __webpack_require__) { class ActionsManager { constructor(client) { this.client = client; this.register(__webpack_require__(82)); this.register(__webpack_require__(83)); this.register(__webpack_require__(84)); this.register(__webpack_require__(88)); this.register(__webpack_require__(85)); this.register(__webpack_require__(86)); this.register(__webpack_require__(87)); this.register(__webpack_require__(66)); this.register(__webpack_require__(67)); this.register(__webpack_require__(68)); this.register(__webpack_require__(70)); this.register(__webpack_require__(81)); this.register(__webpack_require__(74)); this.register(__webpack_require__(75)); this.register(__webpack_require__(69)); this.register(__webpack_require__(76)); this.register(__webpack_require__(77)); this.register(__webpack_require__(78)); this.register(__webpack_require__(89)); this.register(__webpack_require__(91)); this.register(__webpack_require__(90)); this.register(__webpack_require__(80)); this.register(__webpack_require__(71)); this.register(__webpack_require__(72)); this.register(__webpack_require__(73)); this.register(__webpack_require__(79)); } register(Action) { this[Action.name.replace(/Action$/, '')] = new Action(this.client); } } module.exports = ActionsManager; /***/ }, /* 66 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class ChannelCreateAction extends Action { handle(data) { const client = this.client; const channel = client.dataManager.newChannel(data); return { channel, }; } } module.exports = ChannelCreateAction; /***/ }, /* 67 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class ChannelDeleteAction extends Action { constructor(client) { super(client); this.deleted = new Map(); } handle(data) { const client = this.client; let channel = client.channels.get(data.id); if (channel) { client.dataManager.killChannel(channel); this.deleted.set(channel.id, channel); this.scheduleForDeletion(channel.id); } else { channel = this.deleted.get(data.id) || null; } return { channel, }; } scheduleForDeletion(id) { this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout); } } module.exports = ChannelDeleteAction; /***/ }, /* 68 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class ChannelUpdateAction extends Action { handle(data) { const client = this.client; const channel = client.channels.get(data.id); if (channel) { const oldChannel = cloneObject(channel); channel.setup(data); client.emit(Constants.Events.CHANNEL_UPDATE, oldChannel, channel); return { old: oldChannel, updated: channel, }; } return { old: null, updated: null, }; } } /** * Emitted whenever a channel is updated - e.g. name change, topic change. * @event Client#channelUpdate * @param {Channel} oldChannel The channel before the update * @param {Channel} newChannel The channel after the update */ module.exports = ChannelUpdateAction; /***/ }, /* 69 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class GuildBanRemove extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); const user = client.dataManager.newUser(data.user); if (guild && user) client.emit(Constants.Events.GUILD_BAN_REMOVE, guild, user); } } module.exports = GuildBanRemove; /***/ }, /* 70 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class GuildDeleteAction extends Action { constructor(client) { super(client); this.deleted = new Map(); } handle(data) { const client = this.client; let guild = client.guilds.get(data.id); if (guild) { if (guild.available && data.unavailable) { // guild is unavailable guild.available = false; client.emit(Constants.Events.GUILD_UNAVAILABLE, guild); // stops the GuildDelete packet thinking a guild was actually deleted, // handles emitting of event itself return { guild: null, }; } // delete guild client.guilds.delete(guild.id); this.deleted.set(guild.id, guild); this.scheduleForDeletion(guild.id); } else { guild = this.deleted.get(data.id) || null; } return { guild, }; } scheduleForDeletion(id) { this.client.setTimeout(() => this.deleted.delete(id), this.client.options.restWsBridgeTimeout); } } /** * Emitted whenever a guild becomes unavailable, likely due to a server outage. * @event Client#guildUnavailable * @param {Guild} guild The guild that has become unavailable. */ module.exports = GuildDeleteAction; /***/ }, /* 71 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class EmojiCreateAction extends Action { handle(data, guild) { const client = this.client; const emoji = client.dataManager.newEmoji(data, guild); return { emoji, }; } } /** * Emitted whenever an emoji is created * @event Client#guildEmojiCreate * @param {Emoji} emoji The emoji that was created. */ module.exports = EmojiCreateAction; /***/ }, /* 72 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class EmojiDeleteAction extends Action { handle(data) { const client = this.client; client.dataManager.killEmoji(data); return { data, }; } } /** * Emitted whenever an emoji is deleted * @event Client#guildEmojiDelete * @param {Emoji} emoji The emoji that was deleted. */ module.exports = EmojiDeleteAction; /***/ }, /* 73 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class GuildEmojiUpdateAction extends Action { handle(data, guild) { const client = this.client; for (let emoji of data.emojis) { const already = guild.emojis.has(emoji.id); if (already) { client.dataManager.updateEmoji(guild.emojis.get(emoji.id), emoji); } else { emoji = client.dataManager.newEmoji(emoji, guild); } } for (let emoji of guild.emojis) { if (!data.emoijs.has(emoji.id)) client.dataManager.killEmoji(emoji); } return { emojis: data.emojis, }; } } /** * Emitted whenever an emoji is updated * @event Client#guildEmojiUpdate * @param {Emoji} oldEmoji The old emoji * @param {Emoji} newEmoji The new emoji */ module.exports = GuildEmojiUpdateAction; /***/ }, /* 74 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class GuildMemberGetAction extends Action { handle(guild, data) { const member = guild._addMember(data, false); return { member, }; } } module.exports = GuildMemberGetAction; /***/ }, /* 75 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class GuildMemberRemoveAction extends Action { constructor(client) { super(client); this.deleted = new Map(); } handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); if (guild) { let member = guild.members.get(data.user.id); if (member) { guild.memberCount--; guild._removeMember(member); this.deleted.set(guild.id + data.user.id, member); if (client.status === Constants.Status.READY) client.emit(Constants.Events.GUILD_MEMBER_REMOVE, member); this.scheduleForDeletion(guild.id, data.user.id); } else { member = this.deleted.get(guild.id + data.user.id) || null; } return { guild, member, }; } return { guild, member: null, }; } scheduleForDeletion(guildID, userID) { this.client.setTimeout(() => this.deleted.delete(guildID + userID), this.client.options.restWsBridgeTimeout); } } /** * Emitted whenever a member leaves a guild, or is kicked. * @event Client#guildMemberRemove * @param {GuildMember} member The member that has left/been kicked from the guild. */ module.exports = GuildMemberRemoveAction; /***/ }, /* 76 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const Role = __webpack_require__(7); class GuildRoleCreate extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); if (guild) { const already = guild.roles.has(data.role.id); const role = new Role(guild, data.role); guild.roles.set(role.id, role); if (!already) client.emit(Constants.Events.GUILD_ROLE_CREATE, role); return { role, }; } return { role: null, }; } } /** * Emitted whenever a role is created. * @event Client#roleCreate * @param {Role} role The role that was created. */ module.exports = GuildRoleCreate; /***/ }, /* 77 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class GuildRoleDeleteAction extends Action { constructor(client) { super(client); this.deleted = new Map(); } handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); if (guild) { let role = guild.roles.get(data.role_id); if (role) { guild.roles.delete(data.role_id); this.deleted.set(guild.id + data.role_id, role); this.scheduleForDeletion(guild.id, data.role_id); client.emit(Constants.Events.GUILD_ROLE_DELETE, role); } else { role = this.deleted.get(guild.id + data.role_id) || null; } return { role, }; } return { role: null, }; } scheduleForDeletion(guildID, roleID) { this.client.setTimeout(() => this.deleted.delete(guildID + roleID), this.client.options.restWsBridgeTimeout); } } /** * Emitted whenever a guild role is deleted. * @event Client#roleDelete * @param {Role} role The role that was deleted. */ module.exports = GuildRoleDeleteAction; /***/ }, /* 78 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class GuildRoleUpdateAction extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); if (guild) { const roleData = data.role; let oldRole = null; const role = guild.roles.get(roleData.id); if (role) { oldRole = cloneObject(role); role.setup(data.role); client.emit(Constants.Events.GUILD_ROLE_UPDATE, oldRole, role); } return { old: oldRole, updated: role, }; } return { old: null, updated: null, }; } } /** * Emitted whenever a guild role is updated. * @event Client#roleUpdate * @param {Role} oldRole The role before the update. * @param {Role} newRole The role after the update. */ module.exports = GuildRoleUpdateAction; /***/ }, /* 79 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class GuildRolesPositionUpdate extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.guild_id); if (guild) { for (const partialRole of data.roles) { const role = guild.roles.get(partialRole.id); if (role) { role.position = partialRole.position; } } } return { guild, }; } } module.exports = GuildRolesPositionUpdate; /***/ }, /* 80 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class GuildSync extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.id); if (guild) { data.presences = data.presences || []; for (const presence of data.presences) { guild._setPresence(presence.user.id, presence); } data.members = data.members || []; for (const syncMember of data.members) { const member = guild.members.get(syncMember.user.id); if (member) { guild._updateMember(member, syncMember); } else { guild._addMember(syncMember); } } } } } module.exports = GuildSync; /***/ }, /* 81 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class GuildUpdateAction extends Action { handle(data) { const client = this.client; const guild = client.guilds.get(data.id); if (guild) { const oldGuild = cloneObject(guild); guild.setup(data); client.emit(Constants.Events.GUILD_UPDATE, oldGuild, guild); return { old: oldGuild, updated: guild, }; } return { old: null, updated: null, }; } } /** * Emitted whenever a guild is updated - e.g. name change. * @event Client#guildUpdate * @param {Guild} oldGuild The guild before the update. * @param {Guild} newGuild The guild after the update. */ module.exports = GuildUpdateAction; /***/ }, /* 82 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Message = __webpack_require__(13); class MessageCreateAction extends Action { handle(data) { const client = this.client; const channel = client.channels.get((data instanceof Array ? data[0] : data).channel_id); if (channel) { if (data instanceof Array) { const messages = new Array(data.length); for (let i = 0; i < data.length; i++) { messages[i] = channel._cacheMessage(new Message(channel, data[i], client)); } channel.lastMessageID = messages[messages.length - 1].id; return { messages, }; } else { const message = channel._cacheMessage(new Message(channel, data, client)); channel.lastMessageID = data.id; return { message, }; } } return { message: null, }; } } module.exports = MessageCreateAction; /***/ }, /* 83 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class MessageDeleteAction extends Action { constructor(client) { super(client); this.deleted = new Map(); } handle(data) { const client = this.client; const channel = client.channels.get(data.channel_id); if (channel) { let message = channel.messages.get(data.id); if (message) { channel.messages.delete(message.id); this.deleted.set(channel.id + message.id, message); this.scheduleForDeletion(channel.id, message.id); } else { message = this.deleted.get(channel.id + data.id) || null; } return { message, }; } return { message: null, }; } scheduleForDeletion(channelID, messageID) { this.client.setTimeout(() => this.deleted.delete(channelID + messageID), this.client.options.restWsBridgeTimeout); } } module.exports = MessageDeleteAction; /***/ }, /* 84 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Collection = __webpack_require__(3); const Constants = __webpack_require__(0); class MessageDeleteBulkAction extends Action { handle(data) { const client = this.client; const channel = client.channels.get(data.channel_id); const ids = data.ids; const messages = new Collection(); for (const id of ids) { const message = channel.messages.get(id); if (message) messages.set(message.id, message); } if (messages.size > 0) client.emit(Constants.Events.MESSAGE_BULK_DELETE, messages); return { messages, }; } } module.exports = MessageDeleteBulkAction; /***/ }, /* 85 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); /* { user_id: 'id', message_id: 'id', emoji: { name: '�', id: null }, channel_id: 'id' } } */ class MessageReactionAdd extends Action { handle(data) { const user = this.client.users.get(data.user_id); if (!user) return false; const channel = this.client.channels.get(data.channel_id); if (!channel || channel.type === 'voice') return false; const message = channel.messages.get(data.message_id); if (!message) return false; if (!data.emoji) return false; const reaction = message._addReaction(data.emoji, user); if (reaction) { this.client.emit(Constants.Events.MESSAGE_REACTION_ADD, reaction, user); } return { message, reaction, user, }; } } /** * Emitted whenever a reaction is added to a message. * @event Client#messageReactionAdd * @param {MessageReaction} messageReaction The reaction object. * @param {User} user The user that applied the emoji or reaction emoji. */ module.exports = MessageReactionAdd; /***/ }, /* 86 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); /* { user_id: 'id', message_id: 'id', emoji: { name: '�', id: null }, channel_id: 'id' } } */ class MessageReactionRemove extends Action { handle(data) { const user = this.client.users.get(data.user_id); if (!user) return false; const channel = this.client.channels.get(data.channel_id); if (!channel || channel.type === 'voice') return false; const message = channel.messages.get(data.message_id); if (!message) return false; if (!data.emoji) return false; const reaction = message._removeReaction(data.emoji, user); if (reaction) { this.client.emit(Constants.Events.MESSAGE_REACTION_REMOVE, reaction, user); } return { message, reaction, user, }; } } /** * Emitted whenever a reaction is removed from a message. * @event Client#messageReactionRemove * @param {MessageReaction} messageReaction The reaction object. * @param {User} user The user that removed the emoji or reaction emoji. */ module.exports = MessageReactionRemove; /***/ }, /* 87 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class MessageReactionRemoveAll extends Action { handle(data) { const channel = this.client.channels.get(data.channel_id); if (!channel || channel.type === 'voice') return false; const message = channel.messages.get(data.message_id); if (!message) return false; message._clearReactions(); this.client.emit(Constants.Events.MESSAGE_REACTION_REMOVE_ALL, message); return { message, }; } } /** * Emitted whenever all reactions are removed from a message. * @event Client#messageReactionRemoveAll * @param {MessageReaction} messageReaction The reaction object. */ module.exports = MessageReactionRemoveAll; /***/ }, /* 88 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class MessageUpdateAction extends Action { handle(data) { const client = this.client; const channel = client.channels.get(data.channel_id); if (channel) { const message = channel.messages.get(data.id); if (message) { const oldMessage = cloneObject(message); message.patch(data); message._edits.unshift(oldMessage); client.emit(Constants.Events.MESSAGE_UPDATE, oldMessage, message); return { old: oldMessage, updated: message, }; } return { old: message, updated: message, }; } return { old: null, updated: null, }; } } /** * Emitted whenever a message is updated - e.g. embed or content change. * @event Client#messageUpdate * @param {Message} oldMessage The message before the update. * @param {Message} newMessage The message after the update. */ module.exports = MessageUpdateAction; /***/ }, /* 89 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); class UserGetAction extends Action { handle(data) { const client = this.client; const user = client.dataManager.newUser(data); return { user, }; } } module.exports = UserGetAction; /***/ }, /* 90 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); class UserNoteUpdateAction extends Action { handle(data) { const client = this.client; const oldNote = client.user.notes.get(data.id); const note = data.note.length ? data.note : null; client.user.notes.set(data.id, note); client.emit(Constants.Events.USER_NOTE_UPDATE, data.id, oldNote, note); return { old: oldNote, updated: note, }; } } /** * Emitted whenever a note is updated. * @event Client#userNoteUpdate * @param {User} user The user the note belongs to * @param {string} oldNote The note content before the update * @param {string} newNote The note content after the update */ module.exports = UserNoteUpdateAction; /***/ }, /* 91 */ /***/ function(module, exports, __webpack_require__) { const Action = __webpack_require__(2); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class UserUpdateAction extends Action { handle(data) { const client = this.client; if (client.user) { if (client.user.equals(data)) { return { old: client.user, updated: client.user, }; } const oldUser = cloneObject(client.user); client.user.patch(data); client.emit(Constants.Events.USER_UPDATE, oldUser, client.user); return { old: oldUser, updated: client.user, }; } return { old: null, updated: null, }; } } module.exports = UserUpdateAction; /***/ }, /* 92 */ /***/ function(module, exports, __webpack_require__) { const request = __webpack_require__(23); const Constants = __webpack_require__(0); function getRoute(url) { let route = url.split('?')[0]; if (route.includes('/channels/') || route.includes('/guilds/')) { const startInd = ~route.indexOf('/channels/') ? route.indexOf('/channels/') : route.indexOf('/guilds/'); const majorID = route.substring(startInd).split('/')[2]; route = route.replace(/(\d{8,})/g, ':id').replace(':id', majorID); } return route; } class APIRequest { constructor(rest, method, url, auth, data, file) { this.rest = rest; this.method = method; this.url = url; this.auth = auth; this.data = data; this.file = file; this.route = getRoute(this.url); } getAuth() { if (this.rest.client.token && this.rest.client.user && this.rest.client.user.bot) { return `Bot ${this.rest.client.token}`; } else if (this.rest.client.token) { return this.rest.client.token; } throw new Error(Constants.Errors.NO_TOKEN); } gen() { const apiRequest = request[this.method](this.url); if (this.auth) apiRequest.set('authorization', this.getAuth()); if (this.file && this.file.file) { apiRequest.attach('file', this.file.file, this.file.name); this.data = this.data || {}; for (const key in this.data) { if (this.data[key]) { apiRequest.field(key, this.data[key]); } } } else if (this.data) { apiRequest.send(this.data); } apiRequest.set('User-Agent', this.rest.userAgentManager.userAgent); return apiRequest; } } module.exports = APIRequest; /***/ }, /* 93 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); const Collection = __webpack_require__(3); const splitMessage = __webpack_require__(41); const parseEmoji = __webpack_require__(134); const User = __webpack_require__(5); const GuildMember = __webpack_require__(12); const Role = __webpack_require__(7); const Invite = __webpack_require__(30); const Webhook = __webpack_require__(20); const UserProfile = __webpack_require__(133); const ClientOAuth2Application = __webpack_require__(26); class RESTMethods { constructor(restManager) { this.rest = restManager; } loginToken(token = this.rest.client.token) { return new Promise((resolve, reject) => { token = token.replace(/^Bot\s*/i, ''); this.rest.client.manager.connectToWebSocket(token, resolve, reject); }); } loginEmailPassword(email, password) { this.rest.client.emit('warn', 'Client launched using email and password - should use token instead'); this.rest.client.email = email; this.rest.client.password = password; return this.rest.makeRequest('post', Constants.Endpoints.login, false, { email, password }).then(data => this.loginToken(data.token) ); } logout() { return this.rest.makeRequest('post', Constants.Endpoints.logout, true, {}); } getGateway() { return this.rest.makeRequest('get', Constants.Endpoints.gateway, true).then(res => { this.rest.client.ws.gateway = `${res.url}/?encoding=json&v=${Constants.PROTOCOL_VERSION}`; return this.rest.client.ws.gateway; }); } getBotGateway() { return this.rest.makeRequest('get', Constants.Endpoints.botGateway, true); } sendMessage(channel, content, { tts, nonce, embed, disableEveryone, split } = {}, file = null) { return new Promise((resolve, reject) => { if (typeof content !== 'undefined') content = this.rest.client.resolver.resolveString(content); if (content) { if (disableEveryone || (typeof disableEveryone === 'undefined' && this.rest.client.options.disableEveryone)) { content = content.replace(/@(everyone|here)/g, '@\u200b$1'); } if (split) content = splitMessage(content, typeof split === 'object' ? split : {}); } if (channel instanceof User || channel instanceof GuildMember) { this.createDM(channel).then(chan => { this._sendMessageRequest(chan, content, file, tts, nonce, embed, resolve, reject); }, reject); } else { this._sendMessageRequest(channel, content, file, tts, nonce, embed, resolve, reject); } }); } _sendMessageRequest(channel, content, file, tts, nonce, embed, resolve, reject) { if (content instanceof Array) { const datas = []; let promise = this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, { content: content[0], tts, nonce, }, file).catch(reject); for (let i = 1; i <= content.length; i++) { if (i < content.length) { const i2 = i; promise = promise.then(data => { datas.push(data); return this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, { content: content[i2], tts, nonce, embed, }, file); }, reject); } else { promise.then(data => { datas.push(data); resolve(this.rest.client.actions.MessageCreate.handle(datas).messages); }, reject); } } } else { this.rest.makeRequest('post', Constants.Endpoints.channelMessages(channel.id), true, { content, tts, nonce, embed, }, file) .then(data => resolve(this.rest.client.actions.MessageCreate.handle(data).message), reject); } } deleteMessage(message) { return this.rest.makeRequest('del', Constants.Endpoints.channelMessage(message.channel.id, message.id), true) .then(() => this.rest.client.actions.MessageDelete.handle({ id: message.id, channel_id: message.channel.id, }).message ); } bulkDeleteMessages(channel, messages) { return this.rest.makeRequest('post', `${Constants.Endpoints.channelMessages(channel.id)}/bulk_delete`, true, { messages, }).then(() => this.rest.client.actions.MessageDeleteBulk.handle({ channel_id: channel.id, ids: messages, }).messages ); } updateMessage(message, content, { embed } = {}) { content = this.rest.client.resolver.resolveString(content); return this.rest.makeRequest('patch', Constants.Endpoints.channelMessage(message.channel.id, message.id), true, { content, embed, }).then(data => this.rest.client.actions.MessageUpdate.handle(data).updated); } createChannel(guild, channelName, channelType) { return this.rest.makeRequest('post', Constants.Endpoints.guildChannels(guild.id), true, { name: channelName, type: channelType, }).then(data => this.rest.client.actions.ChannelCreate.handle(data).channel); } createDM(recipient) { const dmChannel = this.getExistingDM(recipient); if (dmChannel) return Promise.resolve(dmChannel); return this.rest.makeRequest('post', Constants.Endpoints.userChannels(this.rest.client.user.id), true, { recipient_id: recipient.id, }).then(data => this.rest.client.actions.ChannelCreate.handle(data).channel); } getExistingDM(recipient) { return this.rest.client.channels.find(channel => channel.recipient && channel.recipient.id === recipient.id ); } deleteChannel(channel) { if (channel instanceof User || channel instanceof GuildMember) channel = this.getExistingDM(channel); if (!channel) return Promise.reject(new Error('No channel to delete.')); return this.rest.makeRequest('del', Constants.Endpoints.channel(channel.id), true).then(data => { data.id = channel.id; return this.rest.client.actions.ChannelDelete.handle(data).channel; }); } updateChannel(channel, _data) { const data = {}; data.name = (_data.name || channel.name).trim(); data.topic = _data.topic || channel.topic; data.position = _data.position || channel.position; data.bitrate = _data.bitrate || channel.bitrate; data.user_limit = _data.userLimit || channel.userLimit; return this.rest.makeRequest('patch', Constants.Endpoints.channel(channel.id), true, data).then(newData => this.rest.client.actions.ChannelUpdate.handle(newData).updated ); } leaveGuild(guild) { if (guild.ownerID === this.rest.client.user.id) return Promise.reject(new Error('Guild is owned by the client.')); return this.rest.makeRequest('del', Constants.Endpoints.meGuild(guild.id), true).then(() => this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild ); } createGuild(options) { options.icon = this.rest.client.resolver.resolveBase64(options.icon) || null; options.region = options.region || 'us-central'; return new Promise((resolve, reject) => { this.rest.makeRequest('post', Constants.Endpoints.guilds, true, options).then(data => { if (this.rest.client.guilds.has(data.id)) { resolve(this.rest.client.guilds.get(data.id)); return; } const handleGuild = guild => { if (guild.id === data.id) { this.rest.client.removeListener('guildCreate', handleGuild); this.rest.client.clearTimeout(timeout); resolve(guild); } }; this.rest.client.on('guildCreate', handleGuild); const timeout = this.rest.client.setTimeout(() => { this.rest.client.removeListener('guildCreate', handleGuild); reject(new Error('Took too long to receive guild data.')); }, 10000); }, reject); }); } // untested but probably will work deleteGuild(guild) { return this.rest.makeRequest('del', Constants.Endpoints.guild(guild.id), true).then(() => this.rest.client.actions.GuildDelete.handle({ id: guild.id }).guild ); } getUser(userID) { return this.rest.makeRequest('get', Constants.Endpoints.user(userID), true).then(data => this.rest.client.actions.UserGet.handle(data).user ); } updateCurrentUser(_data) { const user = this.rest.client.user; const data = {}; data.username = _data.username || user.username; data.avatar = this.rest.client.resolver.resolveBase64(_data.avatar) || user.avatar; if (!user.bot) { data.email = _data.email || user.email; data.password = this.rest.client.password; if (_data.new_password) data.new_password = _data.newPassword; } return this.rest.makeRequest('patch', Constants.Endpoints.me, true, data).then(newData => this.rest.client.actions.UserUpdate.handle(newData).updated ); } updateGuild(guild, _data) { const data = {}; if (_data.name) data.name = _data.name; if (_data.region) data.region = _data.region; if (_data.verificationLevel) data.verification_level = Number(_data.verificationLevel); if (_data.afkChannel) data.afk_channel_id = this.rest.client.resolver.resolveChannel(_data.afkChannel).id; if (_data.afkTimeout) data.afk_timeout = Number(_data.afkTimeout); if (_data.icon) data.icon = this.rest.client.resolver.resolveBase64(_data.icon); if (_data.owner) data.owner_id = this.rest.client.resolver.resolveUser(_data.owner).id; if (_data.splash) data.splash = this.rest.client.resolver.resolveBase64(_data.splash); return this.rest.makeRequest('patch', Constants.Endpoints.guild(guild.id), true, data).then(newData => this.rest.client.actions.GuildUpdate.handle(newData).updated ); } kickGuildMember(guild, member) { return this.rest.makeRequest('del', Constants.Endpoints.guildMember(guild.id, member.id), true).then(() => this.rest.client.actions.GuildMemberRemove.handle({ guild_id: guild.id, user: member.user, }).member ); } createGuildRole(guild) { return this.rest.makeRequest('post', Constants.Endpoints.guildRoles(guild.id), true).then(role => this.rest.client.actions.GuildRoleCreate.handle({ guild_id: guild.id, role, }).role ); } deleteGuildRole(role) { return this.rest.makeRequest('del', Constants.Endpoints.guildRole(role.guild.id, role.id), true).then(() => this.rest.client.actions.GuildRoleDelete.handle({ guild_id: role.guild.id, role_id: role.id, }).role ); } setChannelOverwrite(channel, payload) { return this.rest.makeRequest( 'put', `${Constants.Endpoints.channelPermissions(channel.id)}/${payload.id}`, true, payload ); } deletePermissionOverwrites(overwrite) { return this.rest.makeRequest( 'del', `${Constants.Endpoints.channelPermissions(overwrite.channel.id)}/${overwrite.id}`, true ).then(() => overwrite); } getChannelMessages(channel, payload = {}) { const params = []; if (payload.limit) params.push(`limit=${payload.limit}`); if (payload.around) params.push(`around=${payload.around}`); else if (payload.before) params.push(`before=${payload.before}`); else if (payload.after) params.push(`after=${payload.after}`); let endpoint = Constants.Endpoints.channelMessages(channel.id); if (params.length > 0) endpoint += `?${params.join('&')}`; return this.rest.makeRequest('get', endpoint, true); } getChannelMessage(channel, messageID) { const msg = channel.messages.get(messageID); if (msg) return Promise.resolve(msg); return this.rest.makeRequest('get', Constants.Endpoints.channelMessage(channel.id, messageID), true); } getGuildMember(guild, user) { return this.rest.makeRequest('get', Constants.Endpoints.guildMember(guild.id, user.id), true).then(data => this.rest.client.actions.GuildMemberGet.handle(guild, data).member ); } updateGuildMember(member, data) { if (data.channel) data.channel_id = this.rest.client.resolver.resolveChannel(data.channel).id; if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role); let endpoint = Constants.Endpoints.guildMember(member.guild.id, member.id); // fix your endpoints, discord ;-; if (member.id === this.rest.client.user.id) { const keys = Object.keys(data); if (keys.length === 1 && keys[0] === 'nick') { endpoint = Constants.Endpoints.stupidInconsistentGuildEndpoint(member.guild.id); } } return this.rest.makeRequest('patch', endpoint, true, data).then(newData => member.guild._updateMember(member, newData).mem ); } sendTyping(channelID) { return this.rest.makeRequest('post', `${Constants.Endpoints.channel(channelID)}/typing`, true); } banGuildMember(guild, member, deleteDays = 0) { const id = this.rest.client.resolver.resolveUserID(member); if (!id) return Promise.reject(new Error('Couldn\'t resolve the user ID to ban.')); return this.rest.makeRequest( 'put', `${Constants.Endpoints.guildBans(guild.id)}/${id}?delete-message-days=${deleteDays}`, true, { 'delete-message-days': deleteDays, } ).then(() => { if (member instanceof GuildMember) return member; const user = this.rest.client.resolver.resolveUser(id); if (user) { member = this.rest.client.resolver.resolveGuildMember(guild, user); return member || user; } return id; }); } unbanGuildMember(guild, member) { return new Promise((resolve, reject) => { const id = this.rest.client.resolver.resolveUserID(member); if (!id) throw new Error('Couldn\'t resolve the user ID to unban.'); const listener = (eGuild, eUser) => { if (eGuild.id === guild.id && eUser.id === id) { this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener); this.rest.client.clearTimeout(timeout); resolve(eUser); } }; this.rest.client.on(Constants.Events.GUILD_BAN_REMOVE, listener); const timeout = this.rest.client.setTimeout(() => { this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener); reject(new Error('Took too long to receive the ban remove event.')); }, 10000); this.rest.makeRequest('del', `${Constants.Endpoints.guildBans(guild.id)}/${id}`, true).catch(err => { this.rest.client.removeListener(Constants.Events.GUILD_BAN_REMOVE, listener); this.rest.client.clearTimeout(timeout); reject(err); }); }); } getGuildBans(guild) { return this.rest.makeRequest('get', Constants.Endpoints.guildBans(guild.id), true).then(banItems => { const bannedUsers = new Collection(); for (const banItem of banItems) { const user = this.rest.client.dataManager.newUser(banItem.user); bannedUsers.set(user.id, user); } return bannedUsers; }); } updateGuildRole(role, _data) { const data = {}; data.name = _data.name || role.name; data.position = typeof _data.position !== 'undefined' ? _data.position : role.position; data.color = _data.color || role.color; if (typeof data.color === 'string' && data.color.startsWith('#')) { data.color = parseInt(data.color.replace('#', ''), 16); } data.hoist = typeof _data.hoist !== 'undefined' ? _data.hoist : role.hoist; data.mentionable = typeof _data.mentionable !== 'undefined' ? _data.mentionable : role.mentionable; if (_data.permissions) { let perms = 0; for (let perm of _data.permissions) { if (typeof perm === 'string') perm = Constants.PermissionFlags[perm]; perms |= perm; } data.permissions = perms; } else { data.permissions = role.permissions; } return this.rest.makeRequest( 'patch', Constants.Endpoints.guildRole(role.guild.id, role.id), true, data ).then(_role => this.rest.client.actions.GuildRoleUpdate.handle({ role: _role, guild_id: role.guild.id, }).updated ); } pinMessage(message) { return this.rest.makeRequest('put', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true) .then(() => message); } unpinMessage(message) { return this.rest.makeRequest('del', `${Constants.Endpoints.channel(message.channel.id)}/pins/${message.id}`, true) .then(() => message); } getChannelPinnedMessages(channel) { return this.rest.makeRequest('get', `${Constants.Endpoints.channel(channel.id)}/pins`, true); } createChannelInvite(channel, options) { const payload = {}; payload.temporary = options.temporary; payload.max_age = options.maxAge; payload.max_uses = options.maxUses; return this.rest.makeRequest('post', `${Constants.Endpoints.channelInvites(channel.id)}`, true, payload) .then(invite => new Invite(this.rest.client, invite)); } deleteInvite(invite) { return this.rest.makeRequest('del', Constants.Endpoints.invite(invite.code), true).then(() => invite); } getInvite(code) { return this.rest.makeRequest('get', Constants.Endpoints.invite(code), true).then(invite => new Invite(this.rest.client, invite) ); } getGuildInvites(guild) { return this.rest.makeRequest('get', Constants.Endpoints.guildInvites(guild.id), true).then(inviteItems => { const invites = new Collection(); for (const inviteItem of inviteItems) { const invite = new Invite(this.rest.client, inviteItem); invites.set(invite.code, invite); } return invites; }); } pruneGuildMembers(guild, days, dry) { return this.rest.makeRequest(dry ? 'get' : 'post', `${Constants.Endpoints.guildPrune(guild.id)}?days=${days}`, true) .then(data => data.pruned); } createEmoji(guild, image, name) { return this.rest.makeRequest('post', `${Constants.Endpoints.guildEmojis(guild.id)}`, true, { name, image }) .then(data => this.rest.client.actions.EmojiCreate.handle(data, guild).emoji); } deleteEmoji(emoji) { return this.rest.makeRequest('delete', `${Constants.Endpoints.guildEmojis(emoji.guild.id)}/${emoji.id}`, true) .then(() => this.rest.client.actions.EmojiDelete.handle(emoji).data); } getWebhook(id, token) { return this.rest.makeRequest('get', Constants.Endpoints.webhook(id, token), !token).then(data => new Webhook(this.rest.client, data) ); } getGuildWebhooks(guild) { return this.rest.makeRequest('get', Constants.Endpoints.guildWebhooks(guild.id), true).then(data => { const hooks = new Collection(); for (const hook of data) hooks.set(hook.id, new Webhook(this.rest.client, hook)); return hooks; }); } getChannelWebhooks(channel) { return this.rest.makeRequest('get', Constants.Endpoints.channelWebhooks(channel.id), true).then(data => { const hooks = new Collection(); for (const hook of data) hooks.set(hook.id, new Webhook(this.rest.client, hook)); return hooks; }); } createWebhook(channel, name, avatar) { return this.rest.makeRequest('post', Constants.Endpoints.channelWebhooks(channel.id), true, { name, avatar }) .then(data => new Webhook(this.rest.client, data)); } editWebhook(webhook, name, avatar) { return this.rest.makeRequest('patch', Constants.Endpoints.webhook(webhook.id, webhook.token), false, { name, avatar, }).then(data => { webhook.name = data.name; webhook.avatar = data.avatar; return webhook; }); } deleteWebhook(webhook) { return this.rest.makeRequest('delete', Constants.Endpoints.webhook(webhook.id, webhook.token), false); } sendWebhookMessage(webhook, content, { avatarURL, tts, disableEveryone, embeds } = {}, file = null) { if (typeof content !== 'undefined') content = this.rest.client.resolver.resolveString(content); if (content) { if (disableEveryone || (typeof disableEveryone === 'undefined' && this.rest.client.options.disableEveryone)) { content = content.replace(/@(everyone|here)/g, '@\u200b$1'); } } return this.rest.makeRequest('post', `${Constants.Endpoints.webhook(webhook.id, webhook.token)}?wait=true`, false, { username: webhook.name, avatar_url: avatarURL, content, tts, file, embeds, }); } sendSlackWebhookMessage(webhook, body) { return this.rest.makeRequest( 'post', `${Constants.Endpoints.webhook(webhook.id, webhook.token)}/slack?wait=true`, false, body ); } fetchUserProfile(user) { return this.rest.makeRequest('get', Constants.Endpoints.userProfile(user.id), true).then(data => new UserProfile(user, data) ); } addFriend(user) { return this.rest.makeRequest('post', Constants.Endpoints.relationships('@me'), true, { username: user.username, discriminator: user.discriminator, }).then(() => user); } removeFriend(user) { return this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true) .then(() => user); } blockUser(user) { return this.rest.makeRequest('put', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true, { type: 2 }) .then(() => user); } unblockUser(user) { return this.rest.makeRequest('delete', `${Constants.Endpoints.relationships('@me')}/${user.id}`, true) .then(() => user); } setRolePositions(guildID, roles) { return this.rest.makeRequest('patch', Constants.Endpoints.guildRoles(guildID), true, roles).then(() => this.rest.client.actions.GuildRolesPositionUpdate.handle({ guild_id: guildID, roles, }).guild ); } addMessageReaction(message, emoji) { return this.rest.makeRequest( 'put', Constants.Endpoints.selfMessageReaction(message.channel.id, message.id, emoji), true ).then(() => this.rest.client.actions.MessageReactionAdd.handle({ user_id: this.rest.client.user.id, message_id: message.id, emoji: parseEmoji(emoji), channel_id: message.channel.id, }).reaction ); } removeMessageReaction(message, emoji, user) { let endpoint = Constants.Endpoints.selfMessageReaction(message.channel.id, message.id, emoji); if (user.id !== this.rest.client.user.id) { endpoint = Constants.Endpoints.userMessageReaction(message.channel.id, message.id, emoji, null, user.id); } return this.rest.makeRequest('delete', endpoint, true).then(() => this.rest.client.actions.MessageReactionRemove.handle({ user_id: user.id, message_id: message.id, emoji: parseEmoji(emoji), channel_id: message.channel.id, }).reaction ); } removeMessageReactions(message) { this.rest.makeRequest('delete', Constants.Endpoints.messageReactions(message.channel.id, message.id), true) .then(() => message); } getMessageReactionUsers(message, emoji, limit = 100) { return this.rest.makeRequest( 'get', Constants.Endpoints.messageReaction(message.channel.id, message.id, emoji, limit), true ); } getMyApplication() { return this.rest.makeRequest('get', Constants.Endpoints.myApplication, true).then(app => new ClientOAuth2Application(this.rest.client, app) ); } setNote(user, note) { return this.rest.makeRequest('put', Constants.Endpoints.note(user.id), true, { note }).then(() => user); } } module.exports = RESTMethods; /***/ }, /* 94 */ /***/ function(module, exports, __webpack_require__) { const RequestHandler = __webpack_require__(46); class BurstRequestHandler extends RequestHandler { constructor(restManager, endpoint) { super(restManager, endpoint); this.requestRemaining = 1; this.first = true; } push(request) { super.push(request); this.handle(); } handleNext(time) { if (this.waiting) return; this.waiting = true; this.restManager.client.setTimeout(() => { this.requestRemaining = this.requestLimit; this.waiting = false; this.handle(); }, time); } execute(item) { item.request.gen().end((err, res) => { if (res && res.headers) { this.requestLimit = res.headers['x-ratelimit-limit']; this.requestResetTime = Number(res.headers['x-ratelimit-reset']) * 1000; this.requestRemaining = Number(res.headers['x-ratelimit-remaining']); this.timeDifference = Date.now() - new Date(res.headers.date).getTime(); this.handleNext((this.requestResetTime - Date.now()) + this.timeDifference + 1000); } if (err) { if (err.status === 429) { this.requestRemaining = 0; this.queue.unshift(item); this.restManager.client.setTimeout(() => { this.globalLimit = false; this.handle(); }, Number(res.headers['retry-after']) + 500); if (res.headers['x-ratelimit-global']) { this.globalLimit = true; } } else { item.reject(err); } } else { this.globalLimit = false; const data = res && res.body ? res.body : {}; item.resolve(data); if (this.first) { this.first = false; this.handle(); } } }); } handle() { super.handle(); if (this.requestRemaining < 1 || this.queue.length === 0 || this.globalLimit) return; while (this.queue.length > 0 && this.requestRemaining > 0) { this.execute(this.queue.shift()); this.requestRemaining--; } } } module.exports = BurstRequestHandler; /***/ }, /* 95 */ /***/ function(module, exports, __webpack_require__) { const RequestHandler = __webpack_require__(46); /** * Handles API Requests sequentially, i.e. we wait until the current request is finished before moving onto * the next. This plays a _lot_ nicer in terms of avoiding 429's when there is more than one session of the account, * but it can be slower. * @extends {RequestHandler} * @private */ class SequentialRequestHandler extends RequestHandler { /** * @param {RESTManager} restManager The REST manager to use * @param {string} endpoint The endpoint to handle */ constructor(restManager, endpoint) { super(restManager, endpoint); /** * Whether this rate limiter is waiting for a response from a request * @type {boolean} */ this.waiting = false; /** * The endpoint that this handler is handling * @type {string} */ this.endpoint = endpoint; /** * The time difference between Discord's Dates and the local computer's Dates. A positive number means the local * computer's time is ahead of Discord's. * @type {number} */ this.timeDifference = 0; } push(request) { super.push(request); this.handle(); } /** * Performs a request then resolves a promise to indicate its readiness for a new request * @param {APIRequest} item The item to execute * @returns {Promise} */ execute(item) { return new Promise(resolve => { item.request.gen().end((err, res) => { if (res && res.headers) { this.requestLimit = res.headers['x-ratelimit-limit']; this.requestResetTime = Number(res.headers['x-ratelimit-reset']) * 1000; this.requestRemaining = Number(res.headers['x-ratelimit-remaining']); this.timeDifference = Date.now() - new Date(res.headers.date).getTime(); } if (err) { if (err.status === 429) { this.restManager.client.setTimeout(() => { this.waiting = false; this.globalLimit = false; resolve(); }, Number(res.headers['retry-after']) + 500); if (res.headers['x-ratelimit-global']) { this.globalLimit = true; } } else { this.queue.shift(); this.waiting = false; item.reject(err); resolve(err); } } else { this.queue.shift(); this.globalLimit = false; const data = res && res.body ? res.body : {}; item.resolve(data); if (this.requestRemaining === 0) { this.restManager.client.setTimeout(() => { this.waiting = false; resolve(data); }, (this.requestResetTime - Date.now()) + this.timeDifference + 1000); } else { this.waiting = false; resolve(data); } } }); }); } handle() { super.handle(); if (this.waiting || this.queue.length === 0 || this.globalLimit) return; this.waiting = true; const item = this.queue[0]; this.execute(item).then(() => this.handle()); } } module.exports = SequentialRequestHandler; /***/ }, /* 96 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); class UserAgentManager { constructor(restManager) { this.restManager = restManager; this._userAgent = { url: 'https://github.com/hydrabolt/discord.js', version: Constants.Package.version, }; } set(info) { this._userAgent.url = info.url || 'https://github.com/hydrabolt/discord.js'; this._userAgent.version = info.version || Constants.Package.version; } get userAgent() { return `DiscordBot (${this._userAgent.url}, ${this._userAgent.version})`; } } module.exports = UserAgentManager; /***/ }, /* 97 */ /***/ function(module, exports, __webpack_require__) { const browser = typeof window !== 'undefined'; const WebSocket = browser ? window.WebSocket : __webpack_require__(137); // eslint-disable-line no-undef const EventEmitter = __webpack_require__(21).EventEmitter; const Constants = __webpack_require__(0); const inflate = browser ? __webpack_require__(62).inflateSync : __webpack_require__(43).inflateSync; const PacketManager = __webpack_require__(98); const convertArrayBuffer = __webpack_require__(47); /** * The WebSocket Manager of the Client * @private */ class WebSocketManager extends EventEmitter { constructor(client) { super(); /** * The Client that instantiated this WebSocketManager * @type {Client} */ this.client = client; /** * A WebSocket Packet manager, it handles all the messages * @type {PacketManager} */ this.packetManager = new PacketManager(this); /** * The status of the WebSocketManager, a type of Constants.Status. It defaults to IDLE. * @type {number} */ this.status = Constants.Status.IDLE; /** * The session ID of the connection, null if not yet available. * @type {?string} */ this.sessionID = null; /** * The packet count of the client, null if not yet available. * @type {?number} */ this.sequence = -1; /** * The gateway address for this WebSocket connection, null if not yet available. * @type {?string} */ this.gateway = null; /** * Whether READY was emitted normally (all packets received) or not * @type {boolean} */ this.normalReady = false; /** * The WebSocket connection to the gateway * @type {?WebSocket} */ this.ws = null; /** * An object with keys that are websocket event names that should be ignored * @type {Object} */ this.disabledEvents = {}; for (const event in client.options.disabledEvents) this.disabledEvents[event] = true; this.first = true; } /** * Connects the client to a given gateway * @param {string} gateway The gateway to connect to */ _connect(gateway) { this.client.emit('debug', `Connecting to gateway ${gateway}`); this.normalReady = false; if (this.status !== Constants.Status.RECONNECTING) this.status = Constants.Status.CONNECTING; this.ws = new WebSocket(gateway); if (browser) this.ws.binaryType = 'arraybuffer'; this.ws.onopen = () => this.eventOpen(); this.ws.onclose = (d) => this.eventClose(d); this.ws.onmessage = (e) => this.eventMessage(e); this.ws.onerror = (e) => this.eventError(e); this._queue = []; this._remaining = 3; } connect(gateway) { if (this.first) { this._connect(gateway); this.first = false; } else { this.client.setTimeout(() => this._connect(gateway), 5500); } } /** * Sends a packet to the gateway * @param {Object} data An object that can be JSON stringified * @param {boolean} force Whether or not to send the packet immediately */ send(data, force = false) { if (force) { this._send(JSON.stringify(data)); return; } this._queue.push(JSON.stringify(data)); this.doQueue(); } destroy() { this.ws.close(1000); this._queue = []; this.status = Constants.Status.IDLE; } _send(data) { if (this.ws.readyState === WebSocket.OPEN) { this.emit('send', data); this.ws.send(data); } } doQueue() { const item = this._queue[0]; if (this.ws.readyState === WebSocket.OPEN && item) { if (this._remaining === 0) { this.client.setTimeout(this.doQueue.bind(this), 1000); return; } this._remaining--; this._send(item); this._queue.shift(); this.doQueue(); this.client.setTimeout(() => this._remaining++, 1000); } } /** * Run whenever the gateway connections opens up */ eventOpen() { this.client.emit('debug', 'Connection to gateway opened'); if (this.status === Constants.Status.RECONNECTING) this._sendResume(); else this._sendNewIdentify(); } /** * Sends a gateway resume packet, in cases of unexpected disconnections. */ _sendResume() { if (!this.sessionID) { this._sendNewIdentify(); return; } this.client.emit('debug', 'Identifying as resumed session'); const payload = { token: this.client.token, session_id: this.sessionID, seq: this.sequence, }; this.send({ op: Constants.OPCodes.RESUME, d: payload, }); } /** * Sends a new identification packet, in cases of new connections or failed reconnections. */ _sendNewIdentify() { this.reconnecting = false; const payload = this.client.options.ws; payload.token = this.client.token; if (this.client.options.shardCount > 0) { payload.shard = [Number(this.client.options.shardId), Number(this.client.options.shardCount)]; } this.client.emit('debug', 'Identifying as new session'); this.send({ op: Constants.OPCodes.IDENTIFY, d: payload, }); this.sequence = -1; } /** * Run whenever the connection to the gateway is closed, it will try to reconnect the client. * @param {Object} event The received websocket data */ eventClose(event) { this.emit('close', event); this.client.clearInterval(this.client.manager.heartbeatInterval); /** * Emitted whenever the client websocket is disconnected * @event Client#disconnect */ if (!this.reconnecting) this.client.emit(Constants.Events.DISCONNECT); if (event.code === 4004) return; if (event.code === 4010) return; if (!this.reconnecting && event.code !== 1000) this.tryReconnect(); } /** * Run whenever a message is received from the WebSocket. Returns `true` if the message * was handled properly. * @param {Object} event The received websocket data * @returns {boolean} */ eventMessage(event) { const data = this.tryParseEventData(event.data); if (data === null) { this.eventError(new Error(Constants.Errors.BAD_WS_MESSAGE)); return false; } this.client.emit('raw', data); if (data.op === Constants.OPCodes.HELLO) this.client.manager.setupKeepAlive(data.d.heartbeat_interval); return this.packetManager.handle(data); } /** * Parses the raw data from a websocket event, inflating it if necessary * @param {*} data Event data * @returns {Object} */ parseEventData(data) { if (typeof data !== 'string') { if (data instanceof ArrayBuffer) data = convertArrayBuffer(data); data = inflate(data).toString(); } return JSON.parse(data); } /** * Tries to call `parseEventData()` and return its result, or returns `null` upon thrown errors. * @param {*} data Event data * @returns {?Object} */ tryParseEventData(data) { try { return this.parseEventData(data); } catch (err) { return null; } } /** * Run whenever an error occurs with the WebSocket connection. Tries to reconnect * @param {Error} err The encountered error */ eventError(err) { /** * Emitted whenever the Client encounters a serious connection error * @event Client#error * @param {Error} error The encountered error */ if (this.client.listenerCount('error') > 0) this.client.emit('error', err); this.ws.close(); } _emitReady(normal = true) { /** * Emitted when the Client becomes ready to start working * @event Client#ready */ this.status = Constants.Status.READY; this.client.emit(Constants.Events.READY); this.packetManager.handleQueue(); this.normalReady = normal; } /** * Runs on new packets before `READY` to see if the Client is ready yet, if it is prepares * the `READY` event. */ checkIfReady() { if (this.status !== Constants.Status.READY && this.status !== Constants.Status.NEARLY) { let unavailableCount = 0; for (const guildID of this.client.guilds.keys()) { unavailableCount += this.client.guilds.get(guildID).available ? 0 : 1; } if (unavailableCount === 0) { this.status = Constants.Status.NEARLY; if (this.client.options.fetchAllMembers) { const promises = this.client.guilds.map(g => g.fetchMembers()); Promise.all(promises).then(() => this._emitReady(), e => { this.client.emit(Constants.Events.WARN, 'Error in pre-ready guild member fetching'); this.client.emit(Constants.Events.ERROR, e); this._emitReady(); }); return; } this._emitReady(); } } } /** * Tries to reconnect the client, changing the status to Constants.Status.RECONNECTING. */ tryReconnect() { this.status = Constants.Status.RECONNECTING; this.ws.close(); this.packetManager.handleQueue(); /** * Emitted when the Client tries to reconnect after being disconnected * @event Client#reconnecting */ this.client.emit(Constants.Events.RECONNECTING); this.connect(this.client.ws.gateway); } } module.exports = WebSocketManager; /***/ }, /* 98 */ /***/ function(module, exports, __webpack_require__) { const Constants = __webpack_require__(0); const BeforeReadyWhitelist = [ Constants.WSEvents.READY, Constants.WSEvents.GUILD_CREATE, Constants.WSEvents.GUILD_DELETE, Constants.WSEvents.GUILD_MEMBERS_CHUNK, Constants.WSEvents.GUILD_MEMBER_ADD, Constants.WSEvents.GUILD_MEMBER_REMOVE, ]; class WebSocketPacketManager { constructor(websocketManager) { this.ws = websocketManager; this.handlers = {}; this.queue = []; this.register(Constants.WSEvents.READY, __webpack_require__(124)); this.register(Constants.WSEvents.GUILD_CREATE, __webpack_require__(105)); this.register(Constants.WSEvents.GUILD_DELETE, __webpack_require__(106)); this.register(Constants.WSEvents.GUILD_UPDATE, __webpack_require__(115)); this.register(Constants.WSEvents.GUILD_BAN_ADD, __webpack_require__(103)); this.register(Constants.WSEvents.GUILD_BAN_REMOVE, __webpack_require__(104)); this.register(Constants.WSEvents.GUILD_MEMBER_ADD, __webpack_require__(107)); this.register(Constants.WSEvents.GUILD_MEMBER_REMOVE, __webpack_require__(108)); this.register(Constants.WSEvents.GUILD_MEMBER_UPDATE, __webpack_require__(109)); this.register(Constants.WSEvents.GUILD_ROLE_CREATE, __webpack_require__(111)); this.register(Constants.WSEvents.GUILD_ROLE_DELETE, __webpack_require__(112)); this.register(Constants.WSEvents.GUILD_ROLE_UPDATE, __webpack_require__(113)); this.register(Constants.WSEvents.GUILD_MEMBERS_CHUNK, __webpack_require__(110)); this.register(Constants.WSEvents.CHANNEL_CREATE, __webpack_require__(99)); this.register(Constants.WSEvents.CHANNEL_DELETE, __webpack_require__(100)); this.register(Constants.WSEvents.CHANNEL_UPDATE, __webpack_require__(102)); this.register(Constants.WSEvents.CHANNEL_PINS_UPDATE, __webpack_require__(101)); this.register(Constants.WSEvents.PRESENCE_UPDATE, __webpack_require__(123)); this.register(Constants.WSEvents.USER_UPDATE, __webpack_require__(129)); this.register(Constants.WSEvents.USER_NOTE_UPDATE, __webpack_require__(128)); this.register(Constants.WSEvents.VOICE_STATE_UPDATE, __webpack_require__(131)); this.register(Constants.WSEvents.TYPING_START, __webpack_require__(127)); this.register(Constants.WSEvents.MESSAGE_CREATE, __webpack_require__(116)); this.register(Constants.WSEvents.MESSAGE_DELETE, __webpack_require__(117)); this.register(Constants.WSEvents.MESSAGE_UPDATE, __webpack_require__(122)); this.register(Constants.WSEvents.MESSAGE_DELETE_BULK, __webpack_require__(118)); this.register(Constants.WSEvents.VOICE_SERVER_UPDATE, __webpack_require__(130)); this.register(Constants.WSEvents.GUILD_SYNC, __webpack_require__(114)); this.register(Constants.WSEvents.RELATIONSHIP_ADD, __webpack_require__(125)); this.register(Constants.WSEvents.RELATIONSHIP_REMOVE, __webpack_require__(126)); this.register(Constants.WSEvents.MESSAGE_REACTION_ADD, __webpack_require__(119)); this.register(Constants.WSEvents.MESSAGE_REACTION_REMOVE, __webpack_require__(120)); this.register(Constants.WSEvents.MESSAGE_REACTION_REMOVE_ALL, __webpack_require__(121)); } get client() { return this.ws.client; } register(event, Handler) { this.handlers[event] = new Handler(this); } handleQueue() { this.queue.forEach((element, index) => { this.handle(this.queue[index]); this.queue.splice(index, 1); }); } setSequence(s) { if (s && s > this.ws.sequence) this.ws.sequence = s; } handle(packet) { if (packet.op === Constants.OPCodes.RECONNECT) { this.setSequence(packet.s); this.ws.tryReconnect(); return false; } if (packet.op === Constants.OPCodes.INVALID_SESSION) { this.ws.sessionID = null; this.ws._sendNewIdentify(); return false; } if (packet.op === Constants.OPCodes.HEARTBEAT_ACK) this.ws.client.emit('debug', 'Heartbeat acknowledged'); if (this.ws.status === Constants.Status.RECONNECTING) { this.ws.reconnecting = false; this.ws.checkIfReady(); } this.setSequence(packet.s); if (this.ws.disabledEvents[packet.t] !== undefined) return false; if (this.ws.status !== Constants.Status.READY) { if (BeforeReadyWhitelist.indexOf(packet.t) === -1) { this.queue.push(packet); return false; } } if (this.handlers[packet.t]) return this.handlers[packet.t].handle(packet); return false; } } module.exports = WebSocketPacketManager; /***/ }, /* 99 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class ChannelCreateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.ChannelCreate.handle(data); } } /** * Emitted whenever a channel is created. * @event Client#channelCreate * @param {Channel} channel The channel that was created */ module.exports = ChannelCreateHandler; /***/ }, /* 100 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class ChannelDeleteHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const response = client.actions.ChannelDelete.handle(data); if (response.channel) client.emit(Constants.Events.CHANNEL_DELETE, response.channel); } } /** * Emitted whenever a channel is deleted. * @event Client#channelDelete * @param {Channel} channel The channel that was deleted */ module.exports = ChannelDeleteHandler; /***/ }, /* 101 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); /* { t: 'CHANNEL_PINS_UPDATE', s: 666, op: 0, d: { last_pin_timestamp: '2016-08-28T17:37:13.171774+00:00', channel_id: '314866471639044027' } } */ class ChannelPinsUpdate extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const channel = client.channels.get(data.channel_id); const time = new Date(data.last_pin_timestamp); if (channel && time) client.emit(Constants.Events.CHANNEL_PINS_UPDATE, channel, time); } } /** * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event, not much information * can be provided easily here - you need to manually check the pins yourself. * @event Client#channelPinsUpdate * @param {Channel} channel The channel that the pins update occured in * @param {Date} time The time of the pins update */ module.exports = ChannelPinsUpdate; /***/ }, /* 102 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class ChannelUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.ChannelUpdate.handle(data); } } module.exports = ChannelUpdateHandler; /***/ }, /* 103 */ /***/ function(module, exports, __webpack_require__) { // ##untested handler## const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class GuildBanAddHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.guild_id); const user = client.users.get(data.user.id); if (guild && user) client.emit(Constants.Events.GUILD_BAN_ADD, guild, user); } } /** * Emitted whenever a member is banned from a guild. * @event Client#guildBanAdd * @param {Guild} guild The guild that the ban occurred in * @param {User} user The user that was banned */ module.exports = GuildBanAddHandler; /***/ }, /* 104 */ /***/ function(module, exports, __webpack_require__) { // ##untested handler## const AbstractHandler = __webpack_require__(1); class GuildBanRemoveHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildBanRemove.handle(data); } } /** * Emitted whenever a member is unbanned from a guild. * @event Client#guildBanRemove * @param {Guild} guild The guild that the unban occurred in * @param {User} user The user that was unbanned */ module.exports = GuildBanRemoveHandler; /***/ }, /* 105 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildCreateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.id); if (guild) { if (!guild.available && !data.unavailable) { // a newly available guild guild.setup(data); this.packetManager.ws.checkIfReady(); } } else { // a new guild client.dataManager.newGuild(data); } } } module.exports = GuildCreateHandler; /***/ }, /* 106 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class GuildDeleteHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const response = client.actions.GuildDelete.handle(data); if (response.guild) client.emit(Constants.Events.GUILD_DELETE, response.guild); } } /** * Emitted whenever a guild is deleted/left. * @event Client#guildDelete * @param {Guild} guild The guild that was deleted */ module.exports = GuildDeleteHandler; /***/ }, /* 107 */ /***/ function(module, exports, __webpack_require__) { // ##untested handler## const AbstractHandler = __webpack_require__(1); class GuildMemberAddHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.guild_id); if (guild) { guild.memberCount++; guild._addMember(data); } } } module.exports = GuildMemberAddHandler; /***/ }, /* 108 */ /***/ function(module, exports, __webpack_require__) { // ##untested handler## const AbstractHandler = __webpack_require__(1); class GuildMemberRemoveHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildMemberRemove.handle(data); } } module.exports = GuildMemberRemoveHandler; /***/ }, /* 109 */ /***/ function(module, exports, __webpack_require__) { // ##untested handler## const AbstractHandler = __webpack_require__(1); class GuildMemberUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.guild_id); if (guild) { const member = guild.members.get(data.user.id); if (member) guild._updateMember(member, data); } } } module.exports = GuildMemberUpdateHandler; /***/ }, /* 110 */ /***/ function(module, exports, __webpack_require__) { // ##untested## const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class GuildMembersChunkHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.guild_id); const members = []; if (guild) { for (const member of data.members) members.push(guild._addMember(member, false)); } guild._checkChunks(); client.emit(Constants.Events.GUILD_MEMBERS_CHUNK, members); } } /** * Emitted whenever a chunk of guild members is received (all members come from the same guild) * @event Client#guildMembersChunk * @param {GuildMember[]} members The members in the chunk */ module.exports = GuildMembersChunkHandler; /***/ }, /* 111 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildRoleCreateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildRoleCreate.handle(data); } } module.exports = GuildRoleCreateHandler; /***/ }, /* 112 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildRoleDeleteHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildRoleDelete.handle(data); } } module.exports = GuildRoleDeleteHandler; /***/ }, /* 113 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildRoleUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildRoleUpdate.handle(data); } } module.exports = GuildRoleUpdateHandler; /***/ }, /* 114 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildSyncHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildSync.handle(data); } } module.exports = GuildSyncHandler; /***/ }, /* 115 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class GuildUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.GuildUpdate.handle(data); } } module.exports = GuildUpdateHandler; /***/ }, /* 116 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class MessageCreateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const response = client.actions.MessageCreate.handle(data); if (response.message) client.emit(Constants.Events.MESSAGE_CREATE, response.message); } } /** * Emitted whenever a message is created * @event Client#message * @param {Message} message The created message */ module.exports = MessageCreateHandler; /***/ }, /* 117 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class MessageDeleteHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const response = client.actions.MessageDelete.handle(data); if (response.message) client.emit(Constants.Events.MESSAGE_DELETE, response.message); } } /** * Emitted whenever a message is deleted * @event Client#messageDelete * @param {Message} message The deleted message */ module.exports = MessageDeleteHandler; /***/ }, /* 118 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class MessageDeleteBulkHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.MessageDeleteBulk.handle(data); } } /** * Emitted whenever messages are deleted in bulk * @event Client#messageDeleteBulk * @param {Collection} messages The deleted messages, mapped by their ID */ module.exports = MessageDeleteBulkHandler; /***/ }, /* 119 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class MessageReactionAddHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.MessageReactionAdd.handle(data); } } module.exports = MessageReactionAddHandler; /***/ }, /* 120 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class MessageReactionRemove extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.MessageReactionRemove.handle(data); } } module.exports = MessageReactionRemove; /***/ }, /* 121 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class MessageReactionRemoveAll extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.MessageReactionRemoveAll.handle(data); } } module.exports = MessageReactionRemoveAll; /***/ }, /* 122 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class MessageUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.MessageUpdate.handle(data); } } module.exports = MessageUpdateHandler; /***/ }, /* 123 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class PresenceUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; let user = client.users.get(data.user.id); const guild = client.guilds.get(data.guild_id); // step 1 if (!user) { if (data.user.username) { user = client.dataManager.newUser(data.user); } else { return; } } const oldUser = cloneObject(user); user.patch(data.user); if (!user.equals(oldUser)) { client.emit(Constants.Events.USER_UPDATE, oldUser, user); } if (guild) { let member = guild.members.get(user.id); if (!member && data.status !== 'offline') { member = guild._addMember({ user, roles: data.roles, deaf: false, mute: false, }, false); client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, member); } if (member) { const oldMember = cloneObject(member); if (member.presence) { oldMember.frozenPresence = cloneObject(member.presence); } guild._setPresence(user.id, data); client.emit(Constants.Events.PRESENCE_UPDATE, oldMember, member); } else { guild._setPresence(user.id, data); } } } } /** * Emitted whenever a guild member's presence changes, or they change one of their details. * @event Client#presenceUpdate * @param {GuildMember} oldMember The member before the presence update * @param {GuildMember} newMember The member after the presence update */ /** * Emitted whenever a user's details (e.g. username) are changed. * @event Client#userUpdate * @param {User} oldUser The user before the update * @param {User} newUser The user after the update */ /** * Emitted whenever a member becomes available in a large guild * @event Client#guildMemberAvailable * @param {GuildMember} member The member that became available */ module.exports = PresenceUpdateHandler; /***/ }, /* 124 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const ClientUser = __webpack_require__(27); class ReadyHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const clientUser = new ClientUser(client, data.user); client.user = clientUser; client.readyAt = new Date(); client.users.set(clientUser.id, clientUser); for (const guild of data.guilds) client.dataManager.newGuild(guild); for (const privateDM of data.private_channels) client.dataManager.newChannel(privateDM); for (const relation of data.relationships) { const user = client.dataManager.newUser(relation.user); if (relation.type === 1) { client.user.friends.set(user.id, user); } else if (relation.type === 2) { client.user.blocked.set(user.id, user); } } data.presences = data.presences || []; for (const presence of data.presences) { client.dataManager.newUser(presence.user); client._setPresence(presence.user.id, presence); } if (data.notes) { for (const user in data.notes) { let note = data.notes[user]; if (!note.length) note = null; client.user.notes.set(user, note); } } if (!client.user.bot && client.options.sync) client.setInterval(client.syncGuilds.bind(client), 30000); client.once('ready', client.syncGuilds.bind(client)); if (!client.users.has('1')) { client.dataManager.newUser({ id: '1', username: 'Clyde', discriminator: '0000', avatar: 'https://discordapp.com/assets/f78426a064bc9dd24847519259bc42af.png', bot: true, status: 'online', game: null, verified: true, }); } client.setTimeout(() => { if (!client.ws.normalReady) client.ws._emitReady(false); }, 1200 * data.guilds.length); this.packetManager.ws.sessionID = data.session_id; this.packetManager.ws.checkIfReady(); } } module.exports = ReadyHandler; /***/ }, /* 125 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class RelationshipAddHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; if (data.type === 1) { client.fetchUser(data.id).then(user => { client.user.friends.set(user.id, user); }); } else if (data.type === 2) { client.fetchUser(data.id).then(user => { client.user.blocked.set(user.id, user); }); } } } module.exports = RelationshipAddHandler; /***/ }, /* 126 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class RelationshipRemoveHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; if (data.type === 2) { if (client.user.blocked.has(data.id)) { client.user.blocked.delete(data.id); } } else if (data.type === 1) { if (client.user.friends.has(data.id)) { client.user.friends.delete(data.id); } } } } module.exports = RelationshipRemoveHandler; /***/ }, /* 127 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); class TypingStartHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const channel = client.channels.get(data.channel_id); const user = client.users.get(data.user_id); const timestamp = new Date(data.timestamp * 1000); if (channel && user) { if (channel.type === 'voice') { client.emit(Constants.Events.WARN, `Discord sent a typing packet to voice channel ${channel.id}`); return; } if (channel._typing.has(user.id)) { const typing = channel._typing.get(user.id); typing.lastTimestamp = timestamp; typing.resetTimeout(tooLate(channel, user)); } else { channel._typing.set(user.id, new TypingData(client, timestamp, timestamp, tooLate(channel, user))); client.emit(Constants.Events.TYPING_START, channel, user); } } } } class TypingData { constructor(client, since, lastTimestamp, _timeout) { this.client = client; this.since = since; this.lastTimestamp = lastTimestamp; this._timeout = _timeout; } resetTimeout(_timeout) { this.client.clearTimeout(this._timeout); this._timeout = _timeout; } get elapsedTime() { return Date.now() - this.since; } } function tooLate(channel, user) { return channel.client.setTimeout(() => { channel.client.emit(Constants.Events.TYPING_STOP, channel, user, channel._typing.get(user.id)); channel._typing.delete(user.id); }, 6000); } /** * Emitted whenever a user starts typing in a channel * @event Client#typingStart * @param {Channel} channel The channel the user started typing in * @param {User} user The user that started typing */ /** * Emitted whenever a user stops typing in a channel * @event Client#typingStop * @param {Channel} channel The channel the user stopped typing in * @param {User} user The user that stopped typing */ module.exports = TypingStartHandler; /***/ }, /* 128 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class UserNoteUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.UserNoteUpdate.handle(data); } } module.exports = UserNoteUpdateHandler; /***/ }, /* 129 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); class UserUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.actions.UserUpdate.handle(data); } } module.exports = UserUpdateHandler; /***/ }, /* 130 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); /* { "token": "my_token", "guild_id": "41771983423143937", "endpoint": "smart.loyal.discord.gg" } */ class VoiceServerUpdate extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; client.emit('self.voiceServer', data); } } module.exports = VoiceServerUpdate; /***/ }, /* 131 */ /***/ function(module, exports, __webpack_require__) { const AbstractHandler = __webpack_require__(1); const Constants = __webpack_require__(0); const cloneObject = __webpack_require__(4); class VoiceStateUpdateHandler extends AbstractHandler { handle(packet) { const client = this.packetManager.client; const data = packet.d; const guild = client.guilds.get(data.guild_id); if (guild) { const member = guild.members.get(data.user_id); if (member) { const oldVoiceChannelMember = cloneObject(member); if (member.voiceChannel && member.voiceChannel.id !== data.channel_id) { member.voiceChannel.members.delete(oldVoiceChannelMember.id); } // if the member left the voice channel, unset their speaking property if (!data.channel_id) member.speaking = null; if (member.user.id === client.user.id && data.channel_id) { client.emit('self.voiceStateUpdate', data); } const newChannel = client.channels.get(data.channel_id); if (newChannel) newChannel.members.set(member.user.id, member); member.serverMute = data.mute; member.serverDeaf = data.deaf; member.selfMute = data.self_mute; member.selfDeaf = data.self_deaf; member.voiceSessionID = data.session_id; member.voiceChannelID = data.channel_id; client.emit(Constants.Events.VOICE_STATE_UPDATE, oldVoiceChannelMember, member); } } } } /** * Emitted whenever a user changes voice state - e.g. joins/leaves a channel, mutes/unmutes. * @event Client#voiceStateUpdate * @param {GuildMember} oldMember The member before the voice state update * @param {GuildMember} newMember The member after the voice state update */ module.exports = VoiceStateUpdateHandler; /***/ }, /* 132 */ /***/ function(module, exports) { /** * Represents a user connection (or "platform identity") */ class UserConnection { constructor(user, data) { /** * The user that owns the Connection * @type {User} */ this.user = user; this.setup(data); } setup(data) { /** * The type of the Connection * @type {string} */ this.type = data.type; /** * The username of the connection account * @type {string} */ this.name = data.name; /** * The id of the connection account * @type {string} */ this.id = data.id; /** * Whether the connection is revoked * @type {Boolean} */ this.revoked = data.revoked; /** * an array of partial server integrations (not yet implemented in this lib) * @type {Object[]} */ this.integrations = data.integrations; } } module.exports = UserConnection; /***/ }, /* 133 */ /***/ function(module, exports, __webpack_require__) { const Collection = __webpack_require__(3); const UserConnection = __webpack_require__(132); /** * Represents a user's profile on Discord. */ class UserProfile { constructor(user, data) { /** * The owner of the profile * @type {User} */ this.user = user; /** * The Client that created the instance of the the UserProfile. * @type {Client} */ this.client = this.user.client; Object.defineProperty(this, 'client', { enumerable: false, configurable: false }); /** * Guilds that the client user and the user share * @type {Collection} */ this.mutualGuilds = new Collection(); /** * The user's connections * @type {Collection} */ this.connections = new Collection(); this.setup(data); } setup(data) { for (const guild of data.mutual_guilds) { if (this.client.guilds.has(guild.id)) { this.mutualGuilds.set(guild.id, this.client.guilds.get(guild.id)); } } for (const connection of data.connected_accounts) { this.connections.set(connection.id, new UserConnection(this.user, connection)); } } } module.exports = UserProfile; /***/ }, /* 134 */ /***/ function(module, exports) { module.exports = function parseEmoji(text) { if (text.includes('%')) { text = decodeURIComponent(text); } if (text.includes(':')) { const [name, id] = text.split(':'); return { name, id }; } else { return { name: text, id: null, }; } }; /***/ }, /* 135 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 136 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 137 */ /***/ function(module, exports) { /* (ignored) */ /***/ }, /* 138 */ /***/ function(module, exports, __webpack_require__) { module.exports = { Client: __webpack_require__(49), WebhookClient: __webpack_require__(50), Shard: __webpack_require__(52), ShardClientUtil: __webpack_require__(53), ShardingManager: __webpack_require__(54), Collection: __webpack_require__(3), splitMessage: __webpack_require__(41), escapeMarkdown: __webpack_require__(14), fetchRecommendedShards: __webpack_require__(51), Channel: __webpack_require__(8), ClientOAuth2Application: __webpack_require__(26), ClientUser: __webpack_require__(27), DMChannel: __webpack_require__(28), Emoji: __webpack_require__(9), EvaluatedPermissions: __webpack_require__(17), Game: __webpack_require__(6).Game, GroupDMChannel: __webpack_require__(29), Guild: __webpack_require__(18), GuildChannel: __webpack_require__(11), GuildMember: __webpack_require__(12), Invite: __webpack_require__(30), Message: __webpack_require__(13), MessageAttachment: __webpack_require__(31), MessageCollector: __webpack_require__(32), MessageEmbed: __webpack_require__(33), MessageReaction: __webpack_require__(34), OAuth2Application: __webpack_require__(35), PartialGuild: __webpack_require__(36), PartialGuildChannel: __webpack_require__(37), PermissionOverwrites: __webpack_require__(38), Presence: __webpack_require__(6).Presence, ReactionEmoji: __webpack_require__(19), Role: __webpack_require__(7), TextChannel: __webpack_require__(39), User: __webpack_require__(5), VoiceChannel: __webpack_require__(40), Webhook: __webpack_require__(20), version: __webpack_require__(25).version, }; if (typeof window !== 'undefined') window.Discord = module.exports; // eslint-disable-line no-undef /***/ } /******/ ]);