From 354e07d8c00907e73b28f7572dd5c66697aede18 Mon Sep 17 00:00:00 2001 From: Travis CI Date: Sat, 29 Apr 2017 18:20:32 +0000 Subject: [PATCH] Webpack build: 260b09e91c102a9a3e77e98d3cd627d84d442eb9 --- discord.master.js | 36160 +++++++++++++++++++--------------------- discord.master.min.js | 28 +- 2 files changed, 17345 insertions(+), 18843 deletions(-) diff --git a/discord.master.js b/discord.master.js index a2ccf5ac..47aade73 100644 --- a/discord.master.js +++ b/discord.master.js @@ -6,9 +6,9 @@ /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { +/******/ if(installedModules[moduleId]) /******/ return installedModules[moduleId].exports; -/******/ } +/******/ /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, @@ -63,38 +63,36 @@ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 179); +/******/ return __webpack_require__(__webpack_require__.s = 57); /******/ }) /************************************************************************/ /******/ ([ /* 0 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { -/* WEBPACK VAR INJECTION */(function(process) {exports.Package = __webpack_require__(39); +/* WEBPACK VAR INJECTION */(function(process) {exports.Package = __webpack_require__(27); /** * Options for a Client. * @typedef {Object} ClientOptions - * @property {string} [apiRequestMethod='sequential'] One of `sequential` or `burst`. The sequential handler executes - * all requests in the order they are triggered, whereas the burst handler runs multiple in parallel, and doesn't - * provide the guarantee of any particular order. Burst mode is more likely to hit a 429 ratelimit error by its nature, - * and is therefore slightly riskier to use. - * @property {number} [shardId=0] ID of the shard to run - * @property {number} [shardCount=0] Total number of shards + * @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 a message should stay in the cache until it is considered - * sweepable (in seconds, 0 for forever) + * @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 (should be avoided whenever possible) - * @property {boolean} [disableEveryone=false] Default value for {@link MessageOptions#disableEveryone} - * @property {boolean} [sync=false] Whether to periodically sync guilds (for user accounts) + * 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 {number} [restTimeOffset=500] Extra time in millseconds to wait before continuing to make REST + * @property {number} [restTimeOffset=500] The extra time in millseconds to wait before continuing to make REST * requests (higher values will reduce rate-limiting errors on bad connections) * @property {WSEventType[]} [disabledEvents] An array of disabled websocket events. Events in this array will not be * processed, potentially resulting in performance improvements for larger bots. Only disable events you are @@ -117,15 +115,15 @@ exports.DefaultOptions = { restTimeOffset: 500, /** - * Websocket options (these are left as snake_case to match the API) + * 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) + * @property {boolean} [compress=true] Whether to compress data sent on the connection. + * Defaults to `false` for browsers. */ ws: { large_threshold: 250, - compress: __webpack_require__(23).platform() !== 'browser', + compress: typeof window === 'undefined', properties: { $os: process ? process.platform : 'discord.js', $browser: 'discord.js', @@ -133,20 +131,7 @@ exports.DefaultOptions = { $referrer: '', $referring_domain: '', }, - version: 6, }, - http: { - version: 6, - host: 'https://discordapp.com', - cdn: 'https://cdn.discordapp.com', - }, -}; - -exports.WSCodes = { - 1000: 'Connection gracefully closed', - 4004: 'Tried to identify with an invalid token', - 4010: 'Sharding data provided was invalid', - 4011: 'Shard would be on too many guilds if connected', }; exports.Errors = { @@ -159,146 +144,91 @@ exports.Errors = { INVALID_RATE_LIMIT_METHOD: 'Unknown rate limiting method.', BAD_LOGIN: 'Incorrect login details were provided.', INVALID_SHARD: 'Invalid shard settings were provided.', - SHARDING_REQUIRED: 'This session would have handled too many guilds - Sharding is required.', INVALID_TOKEN: 'An invalid token was provided.', }; +const PROTOCOL_VERSION = exports.PROTOCOL_VERSION = 6; +const HOST = exports.HOST = `https://discordapp.com`; +const API = exports.API = `${HOST}/api/v${PROTOCOL_VERSION}`; const Endpoints = exports.Endpoints = { - User: userID => { - if (userID.id) userID = userID.id; - const base = `/users/${userID}`; - return { - toString: () => base, - channels: `${base}/channels`, - profile: `${base}/profile`, - relationships: `${base}/relationships`, - settings: `${base}/settings`, - Relationship: uID => `${base}/relationships/${uID}`, - Guild: guildID => `${base}/guilds/${guildID}`, - Note: id => `${base}/notes/${id}`, - Mentions: (limit, roles, everyone, guildID) => - `${base}/mentions?limit=${limit}&roles=${roles}&everyone=${everyone}${guildID ? `&guild_id=${guildID}` : ''}`, - Avatar: (root, hash) => { - if (userID === '1') return hash; - return Endpoints.CDN(root).Avatar(userID, hash); - }, - }; + // 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}`, + assets: (asset) => `${HOST}/assets/${asset}`, + 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) => { + if (userID === '1') return avatar; + return `${Endpoints.CDN}/avatars/${userID}/${avatar}.${avatar.startsWith('a_') ? 'gif' : 'jpg'}?size=1024`; }, - guilds: '/guilds', - Guild: guildID => { - if (guildID.id) guildID = guildID.id; - const base = `/guilds/${guildID}`; - return { - toString: () => base, - prune: `${base}/prune`, - embed: `${base}/embed`, - bans: `${base}/bans`, - integrations: `${base}/integrations`, - members: `${base}/members`, - channels: `${base}/channels`, - invites: `${base}/invites`, - roles: `${base}/roles`, - emojis: `${base}/emojis`, - search: `${base}/messages/search`, - voiceRegions: `${base}/regions`, - webhooks: `${base}/webhooks`, - ack: `${base}/ack`, - settings: `${base}/settings`, - Emoji: emojiID => Endpoints.CDN(root).Emoji(emojiID), - Icon: (root, hash) => Endpoints.CDN(root).Icon(guildID, hash), - Splash: (root, hash) => Endpoints.CDN(root).Splash(guildID, hash), - Role: roleID => `${base}/roles/${roleID}`, - Member: memberID => { - if (memberID.id) memberID = memberID.id; - const mbase = `${base}/members/${memberID}`; - return { - toString: () => mbase, - Role: roleID => `${mbase}/roles/${roleID}`, - nickname: `${base}/members/@me/nick`, - }; - }, - }; - }, - channels: '/channels', - Channel: channelID => { - if (channelID.id) channelID = channelID.id; - const base = `/channels/${channelID}`; - return { - toString: () => base, - messages: { - toString: () => `${base}/messages`, - bulkDelete: `${base}/messages/bulk-delete`, - }, - invites: `${base}/invites`, - typing: `${base}/typing`, - permissions: `${base}/permissions`, - webhooks: `${base}/webhooks`, - search: `${base}/messages/search`, - pins: `${base}/pins`, - Pin: messageID => `${base}/pins/${messageID}`, - Recipient: recipientID => `${base}/recipients/${recipientID}`, - Message: messageID => { - if (messageID.id) messageID = messageID.id; - const mbase = `${base}/messages/${messageID}`; - return { - toString: () => mbase, - reactions: `${mbase}/reactions`, - ack: `${mbase}/ack`, - Reaction: (emoji, limit) => { - const rbase = `${mbase}/reactions/${emoji}${limit ? `?limit=${limit}` : ''}`; - return { - toString: () => rbase, - User: userID => `${rbase}/${userID}`, - }; - }, - }; - }, - }; - }, - Message: m => exports.Endpoints.Channel(m.channel).Message(m), - Member: m => exports.Endpoints.Guild(m.guild).Member(m), - CDN(root) { - return { - Emoji: emojiID => `${root}/emojis/${emojiID}.png`, - Asset: name => `${root}/assets/${name}`, - Avatar: (userID, hash) => `${root}/avatars/${userID}/${hash}.${hash.startsWith('a_') ? 'gif' : 'png'}?size=2048`, - Icon: (guildID, hash) => `${root}/icons/${guildID}/${hash}.jpg`, - Splash: (guildID, hash) => `${root}/splashes/${guildID}/${hash}.jpg`, - }; - }, - OAUTH2: { - Application: appID => { - const base = `/oauth2/applications/${appID}`; - return { - toString: () => base, - reset: `${base}/reset`, - }; - }, - App: appID => `/oauth2/authorize?client_id=${appID}`, - }, - login: '/auth/login', - logout: '/auth/logout', - voiceRegions: '/voice/regions', - gateway: { - toString: () => '/gateway', - bot: '/gateway/bot', - }, - Invite: inviteID => `/invite/${inviteID}`, - inviteLink: id => `https://discord.gg/${id}`, - Webhook: (webhookID, token) => `/webhooks/${webhookID}${token ? `/${token}` : ''}`, + me: `${API}/users/@me`, + meGuild: (guildID) => `${Endpoints.me}/guilds/${guildID}`, + meMentions: (limit, roles, everyone, guildID) => + `users/@me/mentions?limit=${limit}&roles=${roles}&everyone=${everyone}${guildID ? `&guild_id=${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.CDN}/icons/${guildID}/${hash}.jpg`, + guildSplash: (guildID, hash) => `${Endpoints.CDN}/splashes/${guildID}/${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}`, + guildMemberRole: (guildID, memberID, roleID) => `${Endpoints.guildMember(guildID, memberID)}/roles/${roleID}`, + guildMemberNickname: (guildID) => `${Endpoints.guildMember(guildID, '@me')}/nick`, + guildChannels: (guildID) => `${Endpoints.guild(guildID)}/channels`, + guildEmojis: (guildID) => `${Endpoints.guild(guildID)}/emojis`, + guildSearch: (guildID) => `${Endpoints.guild(guildID)}/messages/search`, + + // 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`, + channelSearch: (channelID) => `${Endpoints.channelMessages(channelID)}/search`, + + // 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}`, + + // emoji + emoji: (emojiID) => `${Endpoints.CDN}/emojis/${emojiID}.png`, }; - -/** - * The current status of the client. Here are the available statuses: - * - READY - * - CONNECTING - * - RECONNECTING - * - IDLE - * - NEARLY - * - DISCONNECTED - * @typedef {number} Status - */ exports.Status = { READY: 0, CONNECTING: 1, @@ -308,28 +238,11 @@ exports.Status = { DISCONNECTED: 5, }; -/** - * The current status of a voice connection. Here are the available statuses: - * - CONNECTED - * - CONNECTING - * - AUTHENTICATING - * - RECONNECTING - * - DISCONNECTED - * @typedef {number} VoiceStatus - */ -exports.VoiceStatus = { - CONNECTED: 0, - CONNECTING: 1, - AUTHENTICATING: 2, - RECONNECTING: 3, - DISCONNECTED: 4, -}; - exports.ChannelTypes = { - TEXT: 0, + text: 0, DM: 1, - VOICE: 2, - GROUP_DM: 3, + voice: 2, + groupDM: 3, }; exports.OPCodes = { @@ -390,7 +303,6 @@ exports.Events = { MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll', USER_UPDATE: 'userUpdate', USER_NOTE_UPDATE: 'userNoteUpdate', - USER_SETTINGS_UPDATE: 'clientUserSettingsUpdate', PRESENCE_UPDATE: 'presenceUpdate', VOICE_STATE_UPDATE: 'voiceStateUpdate', TYPING_START: 'typingStart', @@ -405,7 +317,6 @@ exports.Events = { /** * The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events: * - READY - * - RESUMED * - GUILD_SYNC * - GUILD_CREATE * - GUILD_DELETE @@ -432,7 +343,6 @@ exports.Events = { * - MESSAGE_REACTION_REMOVE_ALL * - USER_UPDATE * - USER_NOTE_UPDATE - * - USER_SETTINGS_UPDATE * - PRESENCE_UPDATE * - VOICE_STATE_UPDATE * - TYPING_START @@ -443,7 +353,6 @@ exports.Events = { */ exports.WSEvents = { READY: 'READY', - RESUMED: 'RESUMED', GUILD_SYNC: 'GUILD_SYNC', GUILD_CREATE: 'GUILD_CREATE', GUILD_DELETE: 'GUILD_DELETE', @@ -471,7 +380,6 @@ exports.WSEvents = { MESSAGE_REACTION_REMOVE_ALL: 'MESSAGE_REACTION_REMOVE_ALL', USER_UPDATE: 'USER_UPDATE', USER_NOTE_UPDATE: 'USER_NOTE_UPDATE', - USER_SETTINGS_UPDATE: 'USER_SETTINGS_UPDATE', PRESENCE_UPDATE: 'PRESENCE_UPDATE', VOICE_STATE_UPDATE: 'VOICE_STATE_UPDATE', TYPING_START: 'TYPING_START', @@ -480,16 +388,15 @@ exports.WSEvents = { RELATIONSHIP_REMOVE: 'RELATIONSHIP_REMOVE', }; -exports.MessageTypes = [ - 'DEFAULT', - 'RECIPIENT_ADD', - 'RECIPIENT_REMOVE', - 'CALL', - 'CHANNEL_NAME_CHANGE', - 'CHANNEL_ICON_CHANGE', - 'PINS_ADD', - 'GUILD_MEMBER_JOIN', -]; +exports.MessageTypes = { + 0: 'DEFAULT', + 1: 'RECIPIENT_ADD', + 2: 'RECIPIENT_REMOVE', + 3: 'CALL', + 4: 'CHANNEL_NAME_CHANGE', + 5: 'CHANNEL_ICON_CHANGE', + 6: 'PINS_ADD', +}; exports.DefaultAvatars = { BLURPLE: '6debd47ed13483642cf09e832ed0bc1b', @@ -499,178 +406,49 @@ exports.DefaultAvatars = { RED: '1cbd08c76f8af6dddce02c5138971129', }; -exports.ExplicitContentFilterTypes = [ - 'DISABLED', - 'NON_FRIENDS', - 'FRIENDS_AND_NON_FRIENDS', -]; +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, -exports.UserSettingsMap = { - /** - * Automatically convert emoticons in your messages to emoji. - * For example, when you type `:-)` Discord will convert it to 😃 - * @name ClientUserSettings#convertEmoticons - * @type {boolean} - */ - convert_emoticons: 'convertEmoticons', + 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, - /** - * If new guilds should automatically disable DMs between you and its members - * @name ClientUserSettings#defaultGuildsRestricted - * @type {boolean} - */ - default_guilds_restricted: 'defaultGuildsRestricted', + CONNECT: 1 << 20, + SPEAK: 1 << 21, + MUTE_MEMBERS: 1 << 22, + DEAFEN_MEMBERS: 1 << 23, + MOVE_MEMBERS: 1 << 24, + USE_VAD: 1 << 25, - /** - * Automatically detect accounts from services like Steam and Blizzard when you open the Discord client - * @name ClientUserSettings#detectPlatformAccounts - * @type {boolean} - */ - detect_platform_accounts: 'detectPlatformAccounts', - - /** - * Developer Mode exposes context menu items helpful for people writing bots using the Discord API - * @name ClientUserSettings#developerMode - * @type {boolean} - */ - developer_mode: 'developerMode', - - /** - * Allow playback and usage of the `/tts` command - * @name ClientUserSettings#enableTTSCommand - * @type {boolean} - */ - enable_tts_command: 'enableTTSCommand', - - /** - * The theme of the client. Either `light` or `dark` - * @name ClientUserSettings#theme - * @type {string} - */ - theme: 'theme', - - /** - * Last status set in the client - * @name ClientUserSettings#status - * @type {PresenceStatus} - */ - status: 'status', - - /** - * Display currently running game as status message - * @name ClientUserSettings#showCurrentGame - * @type {boolean} - */ - show_current_game: 'showCurrentGame', - - /** - * Display images, videos, and lolcats when uploaded directly to Discord - * @name ClientUserSettings#inlineAttachmentMedia - * @type {boolean} - */ - inline_attachment_media: 'inlineAttachmentMedia', - - /** - * Display images, videos, and lolcats when uploaded posted as links in chat - * @name ClientUserSettings#inlineEmbedMedia - * @type {boolean} - */ - inline_embed_media: 'inlineEmbedMedia', - - /** - * Language the Discord client will use, as an RFC 3066 language identifier - * @name ClientUserSettings#locale - * @type {string} - */ - locale: 'locale', - - /** - * Display messages in compact mode - * @name ClientUserSettings#messageDisplayCompact - * @type {boolean} - */ - message_display_compact: 'messageDisplayCompact', - - /** - * Show emoji reactions on messages - * @name ClientUserSettings#renderReactions - * @type {boolean} - */ - render_reactions: 'renderReactions', - - /** - * Array of snowflake IDs for guilds, in the order they appear in the Discord client - * @name ClientUserSettings#guildPositions - * @type {Snowflake[]} - */ - guild_positions: 'guildPositions', - - /** - * Array of snowflake IDs for guilds which you will not recieve DMs from - * @name ClientUserSettings#restrictedGuilds - * @type {Snowflake[]} - */ - restricted_guilds: 'restrictedGuilds', - - explicit_content_filter: function explicitContentFilter(type) { // eslint-disable-line func-name-matching - /** - * Safe direct messaging; force people's messages with images to be scanned before they are sent to you - * one of `DISABLED`, `NON_FRIENDS`, `FRIENDS_AND_NON_FRIENDS` - * @name ClientUserSettings#explicitContentFilter - * @type {string} - */ - return exports.ExplicitContentFilterTypes[type]; - }, - friend_source_flags: function friendSources(flags) { // eslint-disable-line func-name-matching - /** - * Who can add you as a friend - * @name ClientUserSettings#friendSources - * @type {Object} - * @property {boolean} all Mutual friends and mutual guilds - * @property {boolean} mutualGuilds Only mutual guilds - * @property {boolean} mutualFriends Only mutual friends - */ - return { - all: flags.all || false, - mutualGuilds: flags.all ? true : flags.mutual_guilds || false, - mutualFriends: flags.all ? true : flags.mutualFriends || false, - }; - }, + CHANGE_NICKNAME: 1 << 26, + MANAGE_NICKNAMES: 1 << 27, + MANAGE_ROLES_OR_PERMISSIONS: 1 << 28, + MANAGE_WEBHOOKS: 1 << 29, + MANAGE_EMOJIS: 1 << 30, }; -exports.Colors = { - DEFAULT: 0x000000, - AQUA: 0x1ABC9C, - GREEN: 0x2ECC71, - BLUE: 0x3498DB, - PURPLE: 0x9B59B6, - GOLD: 0xF1C40F, - ORANGE: 0xE67E22, - RED: 0xE74C3C, - GREY: 0x95A5A6, - NAVY: 0x34495E, - DARK_AQUA: 0x11806A, - DARK_GREEN: 0x1F8B4C, - DARK_BLUE: 0x206694, - DARK_PURPLE: 0x71368A, - DARK_GOLD: 0xC27C0E, - DARK_ORANGE: 0xA84300, - DARK_RED: 0x992D22, - DARK_GREY: 0x979C9F, - DARKER_GREY: 0x7F8C8D, - LIGHT_GREY: 0xBCC0C0, - DARK_NAVY: 0x2C3E50, - BLURPLE: 0x7289DA, - GREYPLE: 0x99AAB5, - DARK_BUT_NOT_BLACK: 0x2C2F33, - NOT_QUITE_BLACK: 0x23272A, -}; +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__(6))) +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24))) -/***/ }), +/***/ }, /* 1 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { class AbstractHandler { constructor(packetManager) { @@ -685,9 +463,9 @@ class AbstractHandler { module.exports = AbstractHandler; -/***/ }), +/***/ }, /* 2 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { /* @@ -714,9 +492,9 @@ class GenericAction { module.exports = GenericAction; -/***/ }), +/***/ }, /* 3 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { /** * A Map with additional utility methods. This is used throughout discord.js rather than Arrays for anything that has @@ -729,19 +507,17 @@ class Collection extends Map { /** * Cached array for the `array()` method - will be reset to `null` whenever `set()` or `delete()` are called. - * @name Collection#_array * @type {?Array} * @private */ - Object.defineProperty(this, '_array', { value: null, writable: true, configurable: true }); + this._array = null; /** * Cached array for the `keyArray()` method - will be reset to `null` whenever `set()` or `delete()` are called. - * @name Collection#_keyArray * @type {?Array} * @private */ - Object.defineProperty(this, '_keyArray', { value: null, writable: true, configurable: true }); + this._keyArray = null; } set(key, val) { @@ -857,8 +633,7 @@ class Collection extends Map { * 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). - * All collections used in Discord.js are mapped using their `id` property, and if you want to find by id you - * should use the `get` method. See + * 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 @@ -871,6 +646,7 @@ class Collection extends Map { 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; } @@ -930,6 +706,7 @@ class Collection extends Map { * } */ 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)); } @@ -1038,15 +815,6 @@ class Collection extends Map { return accumulator; } - /** - * Creates an identical shallow copy of this collection. - * @returns {Collection} - * @example const newColl = someColl.clone(); - */ - clone() { - return new this.constructor(this); - } - /** * Combines this collection with others into a new collection. None of the source collections are modified. * @param {...Collection} collections Collections to merge @@ -1054,7 +822,8 @@ class Collection extends Map { * @example const newColl = someColl.concat(someOtherColl, anotherColl, ohBoyAColl); */ concat(...collections) { - const newColl = this.clone(); + 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); } @@ -1089,245 +858,4037 @@ class Collection extends Map { return testVal !== value || (testVal === undefined && !collection.has(key)); }); } - - /** - * The sort() method sorts the elements of a collection in place and returns the collection. - * The sort is not necessarily stable. The default sort order is according to string Unicode code points. - * @param {Function} [compareFunction] Specifies a function that defines the sort order. - * if omitted, the collection is sorted according to each character's Unicode code point value, - * according to the string conversion of each element. - * @returns {Collection} - */ - sort(compareFunction = (x, y) => +(x > y) || +(x === y) - 1) { - return new Collection(Array.from(this.entries()).sort((a, b) => compareFunction(a[1], b[1], a[0], b[0]))); - } } module.exports = Collection; -/***/ }), +/***/ }, /* 4 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports) { -/* WEBPACK VAR INJECTION */(function(Buffer) {const snekfetch = __webpack_require__(37); +module.exports = function cloneObject(obj) { + const cloned = Object.create(obj); + Object.assign(cloned, obj); + return cloned; +}; + + +/***/ }, +/* 5 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + + +var TYPED_OK = (typeof Uint8Array !== 'undefined') && + (typeof Uint16Array !== 'undefined') && + (typeof Int32Array !== 'undefined'); + + +exports.assign = function (obj /*from1, from2, from3, ...*/) { + var sources = Array.prototype.slice.call(arguments, 1); + while (sources.length) { + var source = sources.shift(); + if (!source) { continue; } + + if (typeof source !== 'object') { + throw new TypeError(source + 'must be non-object'); + } + + for (var p in source) { + if (source.hasOwnProperty(p)) { + obj[p] = source[p]; + } + } + } + + return obj; +}; + + +// reduce buffer size, avoiding mem copy +exports.shrinkBuf = function (buf, size) { + if (buf.length === size) { return buf; } + if (buf.subarray) { return buf.subarray(0, size); } + buf.length = size; + return buf; +}; + + +var fnTyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + if (src.subarray && dest.subarray) { + dest.set(src.subarray(src_offs, src_offs + len), dest_offs); + return; + } + // Fallback to ordinary array + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + var i, l, len, pos, chunk, result; + + // calculate data length + len = 0; + for (i = 0, l = chunks.length; i < l; i++) { + len += chunks[i].length; + } + + // join chunks + result = new Uint8Array(len); + pos = 0; + for (i = 0, l = chunks.length; i < l; i++) { + chunk = chunks[i]; + result.set(chunk, pos); + pos += chunk.length; + } + + return result; + } +}; + +var fnUntyped = { + arraySet: function (dest, src, src_offs, len, dest_offs) { + for (var i = 0; i < len; i++) { + dest[dest_offs + i] = src[src_offs + i]; + } + }, + // Join array of chunks to single array. + flattenChunks: function (chunks) { + return [].concat.apply([], chunks); + } +}; + + +// Enable/Disable typed arrays use, for testing +// +exports.setTyped = function (on) { + if (on) { + exports.Buf8 = Uint8Array; + exports.Buf16 = Uint16Array; + exports.Buf32 = Int32Array; + exports.assign(exports, fnTyped); + } else { + exports.Buf8 = Array; + exports.Buf16 = Array; + exports.Buf32 = Array; + exports.assign(exports, fnUntyped); + } +}; + +exports.setTyped(TYPED_OK); + + +/***/ }, +/* 6 */ +/***/ function(module, exports, __webpack_require__) { + +const TextBasedChannel = __webpack_require__(12); const Constants = __webpack_require__(0); -const ConstantsHttp = Constants.DefaultOptions.http; +const Presence = __webpack_require__(7).Presence; /** - * Contains various general-purpose utility methods. These functions are also available on the base `Discord` object. + * Represents a user on Discord. + * @implements {TextBasedChannel} */ -class Util { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); +class User { + constructor(client, data) { + /** + * The Client that created the instance of the the User. + * @name User#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + if (data) this.setup(data); } - /** - * Splits a string into multiple chunks at a designated character that do not exceed a specific length. - * @param {string} text Content to split - * @param {SplitOptions} [options] Options controlling the behaviour of the split - * @returns {string|string[]} - */ - static 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]; + 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); + + /** + * The ID of the last message sent by the user, if one was sent. + * @type {?string} + */ + this.lastMessageID = null; + } + + patch(data) { + for (const prop of ['id', 'username', 'discriminator', 'avatar', 'bot']) { + if (typeof data[prop] !== 'undefined') this[prop] = data[prop]; } - return messages; + if (data.token) this.client.token = data.token; } /** - * Escapes any Discord-flavour markdown in a string. - * @param {string} text Content to escape - * @param {boolean} [onlyCodeBlock=false] Whether to only escape codeblocks (takes priority) - * @param {boolean} [onlyInlineCode=false] Whether to only escape inline code + * 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); + } + + /** + * A link to the user's default avatar + * @type {string} + * @readonly + */ + get defaultAvatarURL() { + const avatars = Object.keys(Constants.DefaultAvatars); + const avatar = avatars[this.discriminator % avatars.length]; + return Constants.Endpoints.assets(`${Constants.DefaultAvatars[avatar]}.png`); + } + + /** + * A link to the user's avatar if they have one. Otherwise a link to their default avatar will be returned + * @type {string} + * @readonly + */ + get displayAvatarURL() { + return this.avatarURL || this.defaultAvatarURL; + } + + /** + * 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; + } + + /** + * The DM between the client's user and this user + * @type {?DMChannel} + */ + get dmChannel() { + return this.client.channels.filter(c => c.type === 'dm').find(c => c.recipient.id === this.id); + } + + /** + * 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 ID, username, discriminator, avatar, and bot flags. + * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. + * @param {User} user User to compare with + * @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 + send() { return; } + sendMessage() { return; } + sendEmbed() { return; } + sendFile() { return; } + sendCode() { return; } +} + +TextBasedChannel.applyToClass(User); + +module.exports = User; + + +/***/ }, +/* 7 */ +/***/ 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} presence Presence to compare with + * @returns {boolean} + */ + equals(presence) { + return this === presence || ( + presence && + this.status === presence.status && + this.game ? this.game.equals(presence.game) : !presence.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} game Game to compare with + * @returns {boolean} + */ + equals(game) { + return this === game || ( + game && + this.name === game.name && + this.type === game.type && + this.url === game.url + ); + } +} + +exports.Presence = Presence; +exports.Game = Game; + + +/***/ }, +/* 8 */ +/***/ function(module, exports) { + +/** + * Represents any channel on Discord + */ +class Channel { + constructor(client, data) { + /** + * The client that instantiated the Channel + * @name Channel#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * 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); + +/** + * Represents a role on Discord + */ +class Role { + constructor(guild, data) { + /** + * The client that instantiated the role + * @name Role#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: guild.client }); + + /** + * 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)); + } + + /** + * Whether the role is editable 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; + } + + /** + * 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).then(() => this); + } + + /** + * 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 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 Role to compare with + * @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} */ - static 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'); + toString() { + if (this.id === this.guild.id) return '@everyone'; + return `<@&${this.id}>`; } /** - * Gets the recommended shard count from Discord. - * @param {string} token Discord auth token - * @param {number} [guildsPerShard=1000] Number of guilds per shard - * @returns {Promise} the recommended number of shards + * 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 fetchRecommendedShards(token, guildsPerShard = 1000) { - return new Promise((resolve, reject) => { - if (!token) throw new Error('A token must be provided.'); - snekfetch.get(`${ConstantsHttp.host}/api/v${ConstantsHttp.version}${Constants.Endpoints.gateway.bot}`) - .set('Authorization', `Bot ${token.replace(/^Bot\s*/i, '')}`) - .end((err, res) => { - if (err) reject(err); - resolve(res.body.shards * (1000 / guildsPerShard)); - }); + static comparePositions(role1, role2) { + if (role1.position === role2.position) return role2.id - role1.id; + return role1.position - role2.position; + } +} + +module.exports = Role; + + +/***/ }, +/* 10 */ +/***/ 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 + * @name Emoji#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: guild.client }); + + /** + * 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.emoji(this.id); + } + + /** + * 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; + } + + /** + * Whether this emoji is the same as another one + * @param {Emoji|Object} other the emoji to compare it to + * @returns {boolean} whether the emoji is equal to the given emoji or not + */ + equals(other) { + if (other instanceof Emoji) { + return ( + other.id === this.id && + other.name === this.name && + other.managed === this.managed && + other.requiresColons === this.requiresColons + ); + } else { + return ( + other.id === this.id && + other.name === 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; + + +/***/ }, +/* 11 */ +/***/ function(module, exports, __webpack_require__) { + +const Attachment = __webpack_require__(33); +const Embed = __webpack_require__(35); +const MessageReaction = __webpack_require__(36); +const Collection = __webpack_require__(3); +const Constants = __webpack_require__(0); +const escapeMarkdown = __webpack_require__(16); + +// Done purely for GuildMember, which would cause a bad circular dependency +const Discord = __webpack_require__(57); + +/** + * Represents a message on Discord + */ +class Message { + constructor(channel, data, client) { + /** + * The Client that instantiated the Message + * @name Message#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * 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)); + } + } + + /** + * ID of the webhook that sent the message, if applicable + * @type {?string} + */ + this.webhookID = data.webhook_id || null; + + /** + * Whether this message is a hit in a search + * @type {?boolean} + */ + this.hit = typeof data.hit === 'boolean' ? data.hit : null; + } + + patch(data) { // eslint-disable-line complexity + 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() { + const copy = this._edits.slice(); + copy.unshift(this); + return copy; + } + + /** + * 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); + } + + /** + * Whether or not a guild member is mentioned in this message. Takes into account + * user mentions, role mentions, and @everyone/@here mentions. + * @param {GuildMember|User} member Member/user to check for a mention of + * @returns {boolean} + */ + isMemberMentioned(member) { + if (this.mentions.everyone) return true; + if (this.mentions.users.has(member.id)) return true; + if (member instanceof Discord.GuildMember && member.roles.some(r => this.mentions.roles.has(r.id))) return true; + return false; + } + + /** + * Options that can be passed into editMessage + * @typedef {Object} MessageEditOptions + * @property {Object} [embed] An embed to be added/edited + * @property {string|boolean} [code] Language for optional codeblock formatting to apply + */ + + /** + * 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) { + if (!options && typeof content === 'object') { + options = content; + content = ''; + } else if (!options) { + 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.guild || this.channel.type === 'group' ? `${this.author}, ` : ''}${content}`; + return this.channel.send(content, options); + } + + /** + * Fetches the webhook used to create this message. + * @returns {Promise} + */ + fetchWebhook() { + if (!this.webhookID) return Promise.reject(new Error('The message was not sent by a webhook.')); + return this.client.fetchWebhook(this.webhookID); + } + + /** + * 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; + + +/***/ }, +/* 12 */ +/***/ function(module, exports, __webpack_require__) { + +const path = __webpack_require__(23); +const Message = __webpack_require__(11); +const MessageCollector = __webpack_require__(34); +const Collection = __webpack_require__(3); + +/** + * 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 send, sendMessage, sendFile, sendEmbed, sendCode, and 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 {FileOptions|string} [file] A file to send with the message + * @property {string|boolean} [code] Language for optional codeblock formatting to apply + * @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. + */ + + /** + * @typedef {Object} FileOptions + * @property {BufferResolvable} attachment + * @property {string} [name='file.jpg'] + */ + + /** + * 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] Text for the message + * @param {MessageOptions} [options={}] Options for the message + * @returns {Promise} + * @example + * // send a message + * channel.send('hello!') + * .then(message => console.log(`Sent message: ${message.content}`)) + * .catch(console.error); + */ + send(content, options) { + if (!options && typeof content === 'object' && !(content instanceof Array)) { + options = content; + content = ''; + } else if (!options) { + options = {}; + } + if (options.file) { + if (typeof options.file === 'string') options.file = { attachment: options.file }; + if (!options.file.name) { + if (typeof options.file.attachment === 'string') { + options.file.name = path.basename(options.file.attachment); + } else if (options.file.attachment && options.file.attachment.path) { + options.file.name = path.basename(options.file.attachment.path); + } else { + options.file.name = 'file.jpg'; + } + } + return this.client.resolver.resolveBuffer(options.file.attachment).then(file => + this.client.rest.methods.sendMessage(this, content, options, { + file, + name: options.file.name, + }) + ); + } + return this.client.rest.methods.sendMessage(this, content, options); + } + + /** + * Send a message to this channel + * @param {StringResolvable} content Text for the message + * @param {MessageOptions} [options={}] Options for the message + * @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.send(content, options); + } + + /** + * Send an embed to this channel + * @param {RichEmbed|Object} embed Embed for the message + * @param {string} [content] Text for the message + * @param {MessageOptions} [options] Options for the message + * @returns {Promise} + */ + sendEmbed(embed, content, options) { + if (!options && typeof content === 'object') { + options = content; + content = ''; + } else if (!options) { + options = {}; + } + return this.send(content, Object.assign(options, { embed })); + } + + /** + * Send a file to this channel + * @param {BufferResolvable} attachment File to send + * @param {string} [name='file.jpg'] Name and extension of the file + * @param {StringResolvable} [content] Text for the message + * @param {MessageOptions} [options] Options for the message + * @returns {Promise} + */ + sendFile(attachment, name, content, options = {}) { + return this.send(content, Object.assign(options, { file: { attachment, name } })); + } + + /** + * 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] Options for the message + * @returns {Promise} + */ + sendCode(lang, content, options = {}) { + return this.send(content, Object.assign(options, { code: lang })); + } + + /** + * 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 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; }); } /** - * Parses emoji info out of a string. The string must be one of: - * - A UTF-8 emoji (no ID) - * - A URL-encoded UTF-8 emoji (no ID) - * - A Discord custom emoji (`<:name:id>`) - * @param {string} text Emoji string to parse - * @returns {Object} Object with `name` and `id` properties - * @private + * 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 */ - static parseEmoji(text) { - if (text.includes('%')) text = decodeURIComponent(text); - if (text.includes(':')) { - const [name, id] = text.split(':'); - return { name, id }; + + /** + * Gets the past messages sent in this channel. Resolves with a collection mapping message ID's to Message objects. + * @param {ChannelLogsQueryOptions} [options={}] 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; + }); + } + + /** + * Performs a search within the channel. + * @param {MessageSearchOptions} [options={}] Options to pass to the search + * @returns {Promise>} + * An array containing arrays of messages. Each inner array is a search context cluster. + * The message which has triggered the result will have the `hit` property set to `true`. + * @example + * channel.search({ + * content: 'discord.js', + * before: '2016-11-17' + * }).then(res => { + * const hit = res[0].find(m => m.hit).content; + * console.log(`I found: **${hit}**`); + * }).catch(console.error); + */ + search(options) { + return this.client.rest.methods.search(this, options); + } + + /** + * Starts a typing indicator in the channel. + * @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 { - return { - name: text, - id: null, - }; + const entry = this.client.user._typing.get(this.id); + entry.count = count || entry.count + 1; } } /** - * Checks whether the arrays are equal, also removes duplicated entries from b. - * @param {Array<*>} a Array which will not be modified. - * @param {Array<*>} b Array to remove duplicated entries from. - * @returns {boolean} boolean Whether the arrays are equal. - * @private + * 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); */ - static arraysEqual(a, b) { - if (a === b) return true; - if (a.length !== b.length) return false; - - for (const item of a) { - const ind = b.indexOf(item); - if (ind !== -1) b.splice(ind, 1); - } - - return b.length === 0; - } - - /** - * Shallow-copies an object with its class/prototype intact. - * @param {Object} obj Object to clone - * @returns {Object} - * @private - */ - static cloneObject(obj) { - return Object.assign(Object.create(obj), obj); - } - - /** - * Sets default properties on an object that aren't already specified. - * @param {Object} def Default properties - * @param {Object} given Object to assign defaults to - * @returns {Object} - * @private - */ - static mergeDefault(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] = this.mergeDefault(def[key], given[key]); + 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); } } - - return given; } /** - * Converts an ArrayBuffer or string to a Buffer. - * @param {ArrayBuffer|string} ab ArrayBuffer to convert - * @returns {Buffer} - * @private + * Whether or not the typing indicator is being shown in the channel. + * @type {boolean} + * @readonly */ - static convertToBuffer(ab) { - if (typeof ab === 'string') ab = this.str2ab(ab); - return Buffer.from(ab); + get typing() { + return this.client.user._typing.has(this.id); } /** - * Converts a string to an ArrayBuffer. - * @param {string} str String to convert - * @returns {ArrayBuffer} - * @private + * Number of times `startTyping` has been called. + * @type {number} + * @readonly */ - static 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; + get typingCount() { + if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; + return 0; } /** - * Makes an Error from a plain info object - * @param {Object} obj Error info - * @param {string} obj.name Error type - * @param {string} obj.message Message for the error - * @param {string} obj.stack Stack for the error - * @returns {Error} - * @private + * 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`)); */ - static makeError(obj) { - const err = new Error(obj.message); - err.name = obj.name; - err.stack = obj.stack; - return err; + createCollector(filter, options = {}) { + return new MessageCollector(this, filter, options); } /** - * Makes a plain error info object from an Error - * @param {Error} err Error to get info from - * @returns {Object} - * @private + * 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 */ - static makePlainError(err) { - const obj = {}; - obj.name = err.name; - obj.message = err.message; - obj.stack = err.stack; - return obj; + + /** + * 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); + } + }); + }); } /** - * Moves an element in an array *in place* - * @param {Array<*>} array Array to modify - * @param {*} element Element to move - * @param {number} newIndex Index or offset to move the element to - * @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index - * @returns {number} - * @private + * 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 */ - static moveElementInArray(array, element, newIndex, offset = false) { - const index = array.indexOf(element); - newIndex = (offset ? index : 0) + newIndex; - if (newIndex > -1 && newIndex < array.length) { - const removedElement = array.splice(index, 1)[0]; - array.splice(newIndex, 0, removedElement); + 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); } - return array.indexOf(element); + 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; } } -module.exports = Util; +exports.applyToClass = (structure, full = false) => { + const props = ['send', 'sendMessage', 'sendEmbed', 'sendFile', 'sendCode']; + if (full) { + props.push( + '_cacheMessage', + 'fetchMessages', + 'fetchMessage', + 'search', + 'bulkDelete', + 'startTyping', + 'stopTyping', + 'typing', + 'typingCount', + 'fetchPinnedMessages', + 'createCollector', + 'awaitMessages' + ); + } + for (const prop of props) { + Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop)); + } +}; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5).Buffer)) -/***/ }), -/* 5 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 13 */ +/***/ function(module, exports, __webpack_require__) { + +const User = __webpack_require__(6); +const Role = __webpack_require__(9); +const Emoji = __webpack_require__(10); +const Presence = __webpack_require__(7).Presence; +const GuildMember = __webpack_require__(15); +const Constants = __webpack_require__(0); +const Collection = __webpack_require__(3); +const cloneObject = __webpack_require__(4); +const arraysEqual = __webpack_require__(155); + +/** + * 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. + * @name Guild#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + /** + * 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(); + + /** + * A collection of presences in this guild + * @type {Collection} + */ + this.presences = 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; + + /** + * An array of guild features. + * @type {Object[]} + */ + this.features = data.features; + + /** + * The ID of the application that created this guild (if applicable) + * @type {?string} + */ + this.applicationID = data.application_id; + + /** + * 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); + } + + /** + * Gets the URL to this guild's splash (if it has one, otherwise it returns null) + * @type {?string} + * @readonly + */ + get splashURL() { + if (!this.splash) return null; + return Constants.Endpoints.guildSplash(this.id, this.splash); + } + + /** + * 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); + }); + } + + /** + * Performs a search within the entire guild. + * @param {MessageSearchOptions} [options={}] Options to pass to the search + * @returns {Promise>} + * An array containing arrays of messages. Each inner array is a search context cluster. + * The message which has triggered the result will have the `hit` property set to `true`. + * @example + * guild.search({ + * content: 'discord.js', + * before: '2016-11-17' + * }).then(res => { + * const hit = res[0].find(m => m.hit).content; + * console.log(`I found: **${hit}**`); + * }).catch(console.error); + */ + search(options) { + return this.client.rest.methods.search(this, options); + } + + /** + * 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` + * @param {Array} overwrites Permission overwrites to apply to the new channel + * @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, overwrites) { + return this.client.rest.methods.createChannel(this, name, type, overwrites); + } + + /** + * 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)); + } + + /** + * 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 (typeof role === 'string') { + role = this.roles.get(role); + if (!role) 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 lowestAffected = Math.min(role.position, position); + const highestAffected = Math.max(role.position, position); + + const rolesToUpdate = this.roles.filter(r => r.position >= lowestAffected && r.position <= highestAffected); + + // stop role positions getting stupidly inflated + if (position > role.position) { + position = rolesToUpdate.first().position; + } else { + position = rolesToUpdate.last().position; + } + + const updatedRoles = []; + + for (const uRole of rolesToUpdate.values()) { + updatedRoles.push({ + id: uRole.id, + position: uRole.id === role.id ? position : uRole.position + (position < role.position ? 1 : -1), + }); + } + + return this.client.rest.methods.setRolePositions(this.id, updatedRoles); + } + + /** + * Creates a new custom emoji in the guild. + * @param {BufferResolvable|Base64Resolvable} 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 (typeof attachment === 'string' && 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); + } + + /** + * 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 Guild to compare with + * @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.has(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; + if (this.client.channels.has(voiceState.channel_id)) { + this.client.channels.get(voiceState.channel_id).members.set(member.user.id, member); + } else { + this.client.emit('warn', `Member ${member.id} added in guild ${this.id} with an uncached voice channel`); + } + } + + /** + * 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; + + +/***/ }, +/* 14 */ +/***/ function(module, exports, __webpack_require__) { + +const Channel = __webpack_require__(8); +const Role = __webpack_require__(9); +const PermissionOverwrites = __webpack_require__(40); +const EvaluatedPermissions = __webpack_require__(17); +const Constants = __webpack_require__(0); +const Collection = __webpack_require__(3); + +/** + * 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.deny; + permissions |= overwrite.allow; + } + + 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.allow; + payload.deny = prevOverwrite.deny; + } + + 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); + } + + /** + * Clone this channel + * @param {string} [name=this.name] Optional name for the new channel, otherwise it has the name of this channel + * @param {boolean} [withPermissions=true] Whether to clone the channel with this channel's permission overwrites + * @returns {Promise} + */ + clone(name = this.name, withPermissions = true) { + return this.guild.createChannel(name, this.type, withPermissions ? this.permissionOverwrites : []); + } + + /** + * 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 Channel to compare with + * @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) { + equal = this.permissionOverwrites.equals(channel.permissionOverwrites); + } 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; + + +/***/ }, +/* 15 */ +/***/ function(module, exports, __webpack_require__) { + +const TextBasedChannel = __webpack_require__(12); +const Role = __webpack_require__(9); +const EvaluatedPermissions = __webpack_require__(17); +const Constants = __webpack_require__(0); +const Collection = __webpack_require__(3); +const Presence = __webpack_require__(7).Presence; + +/** + * Represents a member of a guild on Discord + * @implements {TextBasedChannel} + */ +class GuildMember { + constructor(guild, data) { + /** + * The Client that instantiated this GuildMember + * @name GuildMember#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: guild.client }); + + /** + * 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); + + /** + * The ID of the last message sent by the member in their guild, if one was sent. + * @type {?string} + */ + this.lastMessageID = null; + } + + 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 nickname of the member, or their username if they don't have one + * @type {string} + * @readonly + */ + get displayName() { + return this.nickname || this.user.username; + } + + /** + * 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) { + if (!(role instanceof Role)) role = this.guild.roles.get(role); + return this.client.rest.methods.addMemberRole(this, 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) { + if (!(role instanceof Role)) role = this.guild.roles.get(role); + return this.client.rest.methods.removeMemberRole(this, 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 + send() { return; } + sendMessage() { return; } + sendEmbed() { return; } + sendFile() { return; } + sendCode() { return; } +} + +TextBasedChannel.applyToClass(GuildMember); + +module.exports = GuildMember; + + +/***/ }, +/* 16 */ +/***/ 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'); +}; + + +/***/ }, +/* 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) { + +/** + * 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; + + +/***/ }, +/* 19 */ +/***/ function(module, exports, __webpack_require__) { + +const path = __webpack_require__(23); +const escapeMarkdown = __webpack_require__(16); + +/** + * Represents a webhook + */ +class Webhook { + constructor(client, dataOrID, token) { + if (client) { + /** + * The Client that instantiated the Webhook + * @name Webhook#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + if (dataOrID) this.setup(dataOrID); + } else { + this.id = dataOrID; + this.token = token; + Object.defineProperty(this, 'client', { value: 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': Date.now() / 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; + + +/***/ }, +/* 20 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; /* WEBPACK VAR INJECTION */(function(global) {/*! @@ -1340,9 +4901,9 @@ module.exports = Util; -var base64 = __webpack_require__(74) -var ieee754 = __webpack_require__(77) -var isArray = __webpack_require__(56) +var base64 = __webpack_require__(63) +var ieee754 = __webpack_require__(65) +var isArray = __webpack_require__(66) exports.Buffer = Buffer exports.SlowBuffer = SlowBuffer @@ -3120,690 +6681,11 @@ function isnan (val) { return val !== val // eslint-disable-line no-self-compare } -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8))) +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(82))) -/***/ }), -/* 6 */ -/***/ (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; }; - - -/***/ }), -/* 7 */ -/***/ (function(module, exports, __webpack_require__) { - -const Long = __webpack_require__(33); - -// Discord epoch (2015-01-01T00:00:00.000Z) -const EPOCH = 1420070400000; -let INCREMENT = 0; - -/** - * A container for useful snowflake-related methods - */ -class SnowflakeUtil { - constructor() { - throw new Error(`The ${this.constructor.name} class may not be instantiated.`); - } - - /** - * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z - * ``` - * If we have a snowflake '266241948824764416' we can represent it as binary: - * - * 64 22 17 12 0 - * 000000111011000111100001101001000101000000 00001 00000 000000000000 - * number of ms since discord epoch worker pid increment - * ``` - * @typedef {string} Snowflake - */ - - /** - * Generates a Discord snowflake - * This hardcodes the worker ID as 1 and the process ID as 0. - * @returns {Snowflake} The generated snowflake - */ - static generate() { - if (INCREMENT >= 4095) INCREMENT = 0; - const BINARY = `${pad((Date.now() - EPOCH).toString(2), 42)}0000100000${pad((INCREMENT++).toString(2), 12)}`; - return Long.fromString(BINARY, 2).toString(); - } - - /** - * A deconstructed snowflake - * @typedef {Object} DeconstructedSnowflake - * @property {number} timestamp Timestamp the snowflake was created - * @property {Date} date Date the snowflake was created - * @property {number} workerID Worker ID in the snowflake - * @property {number} processID Process ID in the snowflake - * @property {number} increment Increment in the snowflake - * @property {string} binary Binary representation of the snowflake - */ - - /** - * Deconstructs a Discord snowflake - * @param {Snowflake} snowflake Snowflake to deconstruct - * @returns {DeconstructedSnowflake} Deconstructed snowflake - */ - static deconstruct(snowflake) { - const BINARY = pad(Long.fromString(snowflake).toString(2), 64); - const res = { - timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH, - workerID: parseInt(BINARY.substring(42, 47), 2), - processID: parseInt(BINARY.substring(47, 52), 2), - increment: parseInt(BINARY.substring(52, 64), 2), - binary: BINARY, - }; - Object.defineProperty(res, 'date', { - get: function get() { return new Date(this.timestamp); }, - enumerable: true, - }); - return res; - } -} - -function pad(v, n, c = '0') { - return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n); -} - -module.exports = SnowflakeUtil; - - -/***/ }), -/* 8 */ -/***/ (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; - - -/***/ }), -/* 9 */ -/***/ (function(module, exports, __webpack_require__) { - -const Constants = __webpack_require__(0); - -/** - * Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of - * permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member - * that override their default permissions. - */ -class Permissions { - /** - * @param {GuildMember} [member] Member the permissions are for **(deprecated)** - * @param {number|PermissionResolvable[]} permissions Permissions or bitfield to read from - */ - constructor(member, permissions) { - permissions = typeof member === 'object' && !(member instanceof Array) ? permissions : member; - - /** - * Member the permissions are for - * @type {GuildMember} - * @deprecated - */ - this.member = typeof member === 'object' ? member : null; - - /** - * Bitfield of the packed permissions - * @type {number} - */ - this.bitfield = typeof permissions === 'number' ? permissions : this.constructor.resolve(permissions); - } - - /** - * Bitfield of the packed permissions - * @type {number} - * @see {@link Permissions#bitfield} - * @deprecated - * @readonly - */ - get raw() { - return this.bitfield; - } - - set raw(raw) { - this.bitfield = raw; - } - - /** - * Checks whether the bitfield has a permission, or multiple permissions. - * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for - * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override - * @returns {boolean} - */ - has(permission, checkAdmin = true) { - if (permission instanceof Array) return permission.every(p => this.has(p, checkAdmin)); - permission = this.constructor.resolve(permission); - if (checkAdmin && (this.bitfield & this.constructor.FLAGS.ADMINISTRATOR) > 0) return true; - return (this.bitfield & permission) === permission; - } - - /** - * Gets all given permissions that are missing from the bitfield. - * @param {PermissionResolvable[]} permissions Permissions to check for - * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override - * @returns {PermissionResolvable[]} - */ - missing(permissions, checkAdmin = true) { - return permissions.filter(p => !this.has(p, checkAdmin)); - } - - /** - * Adds permissions to this one, creating a new instance to represent the new bitfield. - * @param {...PermissionResolvable} permissions Permissions to add - * @returns {Permissions} - */ - add(...permissions) { - let total = 0; - for (let p = 0; p < permissions.length; p++) { - const perm = this.constructor.resolve(permissions[p]); - if ((this.bitfield & perm) !== perm) total |= perm; - } - return new this.constructor(this.member, this.bitfield | total); - } - - /** - * Removes permissions to this one, creating a new instance to represent the new bitfield. - * @param {...PermissionResolvable} permissions Permissions to remove - * @returns {Permissions} - */ - remove(...permissions) { - let total = 0; - for (let p = 0; p < permissions.length; p++) { - const perm = this.constructor.resolve(permissions[p]); - if ((this.bitfield & perm) === perm) total |= perm; - } - return new this.constructor(this.member, this.bitfield & ~total); - } - - /** - * Gets an object mapping permission name (like `READ_MESSAGES`) to a {@link boolean} indicating whether the - * permission is available. - * @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override - * @returns {Object} - */ - serialize(checkAdmin = true) { - const serialized = {}; - for (const perm in this.constructor.FLAGS) serialized[perm] = this.has(perm, checkAdmin); - return serialized; - } - - /** - * 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} - * @see {@link Permissions#has} - * @deprecated - */ - hasPermission(permission, explicit = false) { - return this.has(permission, !explicit); - } - - /** - * 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} - * @see {@link Permissions#has} - * @deprecated - */ - hasPermissions(permissions, explicit = false) { - return this.has(permissions, !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[]} - * @see {@link Permissions#missing} - * @deprecated - */ - missingPermissions(permissions, explicit = false) { - return this.missing(permissions, !explicit); - } - - /** - * Data that can be resolved to give a permission number. This can be: - * - A string (see {@link Permissions.flags}) - * - A permission number - * @typedef {string|number} PermissionResolvable - */ - - /** - * Resolves permissions to their numeric form. - * @param {PermissionResolvable|PermissionResolvable[]} permission - Permission(s) to resolve - * @returns {number} - */ - static resolve(permission) { - if (permission instanceof Array) return permission.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0); - if (typeof permission === 'string') permission = this.FLAGS[permission]; - if (typeof permission !== 'number' || permission < 1) throw new RangeError(Constants.Errors.NOT_A_PERMISSION); - return permission; - } -} - -/** - * Numeric permission flags. All available properties: - * - `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites) - * - `CREATE_INSTANT_INVITE` (create invitations to the guild) - * - `KICK_MEMBERS` - * - `BAN_MEMBERS` - * - `MANAGE_CHANNELS` (edit and reorder channels) - * - `MANAGE_GUILD` (edit the guild information, region, etc.) - * - `ADD_REACTIONS` (add new reactions to messages) - * - `READ_MESSAGES` - * - `SEND_MESSAGES` - * - `SEND_TTS_MESSAGES` - * - `MANAGE_MESSAGES` (delete messages and reactions) - * - `EMBED_LINKS` (links posted will have a preview embedded) - * - `ATTACH_FILES` - * - `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord) - * - `MENTION_EVERYONE` - * - `USE_EXTERNAL_EMOJIS` (use emojis from different guilds) - * - `EXTERNAL_EMOJIS` **(deprecated)** - * - `CONNECT` (connect to a voice channel) - * - `SPEAK` (speak in a voice channel) - * - `MUTE_MEMBERS` (mute members across all voice channels) - * - `DEAFEN_MEMBERS` (deafen members across all voice channels) - * - `MOVE_MEMBERS` (move members between voice channels) - * - `USE_VAD` (use voice activity detection) - * - `CHANGE_NICKNAME` - * - `MANAGE_NICKNAMES` (change other members' nicknames) - * - `MANAGE_ROLES` - * - `MANAGE_ROLES_OR_PERMISSIONS` **(deprecated)** - * - `MANAGE_WEBHOOKS` - * - `MANAGE_EMOJIS` - * @type {Object} - * @see {@link https://discordapp.com/developers/docs/topics/permissions} - */ -Permissions.FLAGS = { - 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, - USE_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: 1 << 28, - MANAGE_ROLES_OR_PERMISSIONS: 1 << 28, - MANAGE_WEBHOOKS: 1 << 29, - MANAGE_EMOJIS: 1 << 30, -}; - -/** - * Bitfield representing every permission combined - * @type {number} - */ -Permissions.ALL = Object.keys(Permissions.FLAGS).reduce((all, p) => all | Permissions.FLAGS[p], 0); - -/** - * Bitfield representing the default permissions for users - * @type {number} - */ -Permissions.DEFAULT = 104324097; - -/** - * @class EvaluatedPermissions - * @classdesc The final evaluated permissions for a member in a channel - * @see {@link Permissions} - * @deprecated - */ - -module.exports = Permissions; - - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - - -/***/ }), -/* 11 */ -/***/ (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} presence Presence to compare with - * @returns {boolean} - */ - equals(presence) { - return this === presence || ( - presence && - this.status === presence.status && - this.game ? this.game.equals(presence.game) : !presence.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} game Game to compare with - * @returns {boolean} - */ - equals(game) { - return this === game || ( - game && - this.name === game.name && - this.type === game.type && - this.url === game.url - ); - } -} - -exports.Presence = Presence; -exports.Game = Game; - - -/***/ }), -/* 12 */ -/***/ (function(module, exports) { +/***/ }, +/* 21 */ +/***/ function(module, exports) { // Copyright Joyent, Inc. and other Node contributors. // @@ -4109,4171 +6991,48 @@ function isUndefined(arg) { } -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 22 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -// a duplex stream is just a stream that is both readable and writable. -// Since JS doesn't have multiple prototypal inheritance, this class -// prototypally inherits from Readable, and then parasitically from -// Writable. - -/**/ - -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - keys.push(key); - }return keys; -}; -/**/ - -module.exports = Duplex; - -/**/ -var processNextTick = __webpack_require__(34); -/**/ - -/**/ -var util = __webpack_require__(20); -util.inherits = __webpack_require__(10); -/**/ - -var Readable = __webpack_require__(57); -var Writable = __webpack_require__(36); - -util.inherits(Duplex, Readable); - -var keys = objectKeys(Writable.prototype); -for (var v = 0; v < keys.length; v++) { - var method = keys[v]; - if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; -} - -function Duplex(options) { - if (!(this instanceof Duplex)) return new Duplex(options); - - Readable.call(this, options); - Writable.call(this, options); - - if (options && options.readable === false) this.readable = false; - - if (options && options.writable === false) this.writable = false; - - this.allowHalfOpen = true; - if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; - - this.once('end', onend); -} - -// the no-half-open enforcer -function onend() { - // if we allow half-open state, or if the writable side ended, - // then we're ok. - if (this.allowHalfOpen || this._writableState.ended) return; - - // no more data can be written. - // But allow more writes to happen in this tick. - processNextTick(onEndNT, this); -} - -function onEndNT(self) { - self.end(); -} - -function forEach(xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -const Snowflake = __webpack_require__(7); - -/** - * Represents any channel on Discord - */ -class Channel { - constructor(client, data) { - /** - * The client that instantiated the Channel - * @name Channel#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * 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 {Snowflake} - */ - this.id = data.id; - } - - /** - * The timestamp the channel was created at - * @type {number} - * @readonly - */ - get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; - } - - /** - * 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; - - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -const Snowflake = __webpack_require__(7); -const Permissions = __webpack_require__(9); - -/** - * Represents a role on Discord - */ -class Role { - constructor(guild, data) { - /** - * The client that instantiated the role - * @name Role#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: guild.client }); - - /** - * 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 {Snowflake} - */ - 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 from the API - * @type {number} - */ - this.position = data.position; - - /** - * The permissions bitfield of the role - * @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 Snowflake.deconstruct(this.id).timestamp; - } - - /** - * 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)); - } - - /** - * Whether the role is editable 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(Permissions.FLAGS.MANAGE_ROLES_OR_PERMISSIONS)) return false; - return clientMember.highestRole.comparePositionTo(this) > 0; - } - - /** - * The position of the role in the role manager - * @type {number} - * @readonly - */ - get calculatedPosition() { - const sorted = this.guild._sortedRoles; - return sorted.array().indexOf(sorted.get(this.id)); - } - - /** - * Get an object mapping permission names to whether or not the role enables that permission - * @returns {Object} - * @example - * // print the serialized role permissions - * console.log(role.serialize()); - */ - serialize() { - return new Permissions(this.permissions).serialize(); - } - - /** - * Checks if the role has a permission. - * @param {PermissionResolvable|PermissionResolvable[]} permission Permission(s) to check for - * @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permission - * **(deprecated)** - * @param {boolean} [checkAdmin] Whether to allow the administrator permission to override - * (takes priority over `explicit`) - * @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, checkAdmin) { - return new Permissions(this.permissions).has( - permission, typeof checkAdmin !== 'undefined' ? checkAdmin : !explicit - ); - } - - /** - * 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} - * @deprecated - */ - hasPermissions(permissions, explicit = false) { - return new Permissions(this.permissions).has(permissions, !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 {ColorResolvable} [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 {ColorResolvable} color The color of the role - * @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 - * @param {boolean} [relative=false] Move the position relative to its current value - * @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, relative) { - return this.guild.setRolePosition(this, position, relative).then(() => this); - } - - /** - * 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 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 Role to compare with - * @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() { - if (this.id === this.guild.id) return '@everyone'; - 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; - - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - -const TextBasedChannel = __webpack_require__(22); -const Constants = __webpack_require__(0); -const Presence = __webpack_require__(11).Presence; -const Snowflake = __webpack_require__(7); - -/** - * Represents a user on Discord. - * @implements {TextBasedChannel} - */ -class User { - constructor(client, data) { - /** - * The Client that created the instance of the the User. - * @name User#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - if (data) this.setup(data); - } - - setup(data) { - /** - * The ID of the user - * @type {Snowflake} - */ - 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); - - /** - * The ID of the last message sent by the user, if one was sent. - * @type {?Snowflake} - */ - this.lastMessageID = null; - - /** - * The Message object of the last message sent by the user, if one was sent. - * @type {?Message} - */ - this.lastMessage = null; - } - - patch(data) { - for (const prop of ['id', 'username', 'discriminator', 'avatar', 'bot']) { - if (typeof data[prop] !== 'undefined') this[prop] = data[prop]; - } - if (data.token) this.client.token = data.token; - } - - /** - * The timestamp the user was created at - * @type {number} - * @readonly - */ - get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; - } - - /** - * 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.User(this).Avatar(this.client.options.http.cdn, this.avatar); - } - - /** - * A link to the user's default avatar - * @type {string} - * @readonly - */ - get defaultAvatarURL() { - const avatars = Object.keys(Constants.DefaultAvatars); - const avatar = avatars[this.discriminator % avatars.length]; - return Constants.Endpoints.CDN(this.client.options.http.host).Asset(`${Constants.DefaultAvatars[avatar]}.png`); - } - - /** - * A link to the user's avatar if they have one. Otherwise a link to their default avatar will be returned - * @type {string} - * @readonly - */ - get displayAvatarURL() { - return this.avatarURL || this.defaultAvatarURL; - } - - /** - * The discord "tag" for this user - * @type {string} - * @readonly - */ - get tag() { - return `${this.username}#${this.discriminator}`; - } - - /** - * 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; - } - - /** - * The DM between the client's user and this user - * @type {?DMChannel} - * @readonly - */ - get dmChannel() { - return this.client.channels.filter(c => c.type === 'dm').find(c => c.recipient.id === this.id); - } - - /** - * Creates a DM channel between the client and the user - * @returns {Promise} - */ - createDM() { - return this.client.rest.methods.createDM(this); - } - - /** - * 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 ID, username, discriminator, avatar, and bot flags. - * It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties. - * @param {User} user User to compare with - * @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 - /* eslint-disable no-empty-function */ - send() {} - sendMessage() {} - sendEmbed() {} - sendFile() {} - sendCode() {} -} - -TextBasedChannel.applyToClass(User); - -module.exports = User; - - -/***/ }), -/* 17 */ -/***/ (function(module, exports, __webpack_require__) { - -const Constants = __webpack_require__(0); -const Collection = __webpack_require__(3); -const Snowflake = __webpack_require__(7); - -/** - * Represents a custom emoji - */ -class Emoji { - constructor(guild, data) { - /** - * The Client that instantiated this object - * @name Emoji#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: guild.client }); - - /** - * The guild this emoji is part of - * @type {Guild} - */ - this.guild = guild; - - this.setup(data); - } - - setup(data) { - /** - * The ID of the emoji - * @type {Snowflake} - */ - 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 Snowflake.deconstruct(this.id).timestamp; - } - - /** - * 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(this.client.options.http.cdn).Emoji(this.id); - } - - /** - * The identifier of this emoji, used for message reactions - * @type {string} - * @readonly - */ - get identifier() { - if (this.id) return `${this.name}:${this.id}`; - return encodeURIComponent(this.name); - } - - /** - * Data for editing an emoji - * @typedef {Object} EmojiEditData - * @property {string} [name] The name of the emoji - * @property {Collection|Array} [roles] Roles to restrict emoji to - */ - - /** - * Edits the emoji - * @param {EmojiEditData} data The new data for the emoji - * @returns {Promise} - * @example - * // edit a emoji - * emoji.edit({name: 'newemoji'}) - * .then(e => console.log(`Edited emoji ${e}`)) - * .catch(console.error); - */ - edit(data) { - return this.client.rest.methods.updateEmoji(this, data); - } - - /** - * 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; - } - - /** - * Whether this emoji is the same as another one - * @param {Emoji|Object} other the emoji to compare it to - * @returns {boolean} whether the emoji is equal to the given emoji or not - */ - equals(other) { - if (other instanceof Emoji) { - return ( - other.id === this.id && - other.name === this.name && - other.managed === this.managed && - other.requiresColons === this.requiresColons - ); - } else { - return ( - other.id === this.id && - other.name === this.name - ); - } - } -} - -module.exports = Emoji; - - -/***/ }), -/* 18 */ -/***/ (function(module, exports, __webpack_require__) { - -const TextBasedChannel = __webpack_require__(22); -const Role = __webpack_require__(15); -const Permissions = __webpack_require__(9); -const Collection = __webpack_require__(3); -const Presence = __webpack_require__(11).Presence; - -/** - * Represents a member of a guild on Discord - * @implements {TextBasedChannel} - */ -class GuildMember { - constructor(guild, data) { - /** - * The Client that instantiated this GuildMember - * @name GuildMember#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: guild.client }); - - /** - * 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); - - /** - * The ID of the last message sent by the member in their guild, if one was sent. - * @type {?Snowflake} - */ - this.lastMessageID = null; - - /** - * The Message object of the last message sent by the member in their guild, if one was sent. - * @type {?Message} - */ - this.lastMessage = null; - } - - 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 {?Snowflake} - */ - this.voiceSessionID = data.session_id; - - /** - * The voice channel ID of this member, if any - * @type {?Snowflake} - */ - 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); - } - - /** - * The role of the member used to set their color. - * @type {?Role} - * @readonly - */ - get colorRole() { - const coloredRoles = this.roles.filter(role => role.color); - if (!coloredRoles.size) return null; - return coloredRoles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev); - } - - /** - * The displayed color of the member in base 10. - * @type {number} - * @readonly - */ - get displayColor() { - const role = this.colorRole; - return (role && role.color) || 0; - } - - /** - * The displayed color of the member in hexadecimal. - * @type {string} - * @readonly - */ - get displayHexColor() { - const role = this.colorRole; - return (role && role.hexColor) || '#000000'; - } - - /** - * The role of the member used to hoist them in a separate category in the users list. - * @type {?Role} - * @readonly - */ - get hoistRole() { - const hoistedRoles = this.roles.filter(role => role.hoist); - if (!hoistedRoles.size) return null; - return hoistedRoles.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 {Snowflake} - * @readonly - */ - get id() { - return this.user.id; - } - - /** - * The nickname of the member, or their username if they don't have one - * @type {string} - * @readonly - */ - get displayName() { - return this.nickname || this.user.username; - } - - /** - * The overall set of permissions for the guild member, taking only roles into account - * @type {Permissions} - * @readonly - */ - get permissions() { - if (this.user.id === this.guild.ownerID) return new Permissions(this, Permissions.ALL); - - let permissions = 0; - const roles = this.roles; - for (const role of roles.values()) permissions |= role.permissions; - - return new Permissions(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(Permissions.FLAGS.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(Permissions.FLAGS.BAN_MEMBERS)) return false; - return clientMember.highestRole.comparePositionTo(this.highestRole) > 0; - } - - /** - * Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel, - * taking into account roles and permission overwrites. - * @param {ChannelResolvable} channel Guild channel to use as context - * @returns {?Permissions} - */ - 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|PermissionResolvable[]} permission Permission(s) to check for - * @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permission - * **(deprecated)** - * @param {boolean} [checkAdmin] Whether to allow the administrator permission to override - * (takes priority over `explicit`) - * @param {boolean} [checkOwner] Whether to allow being the guild's owner to override - * (takes priority over `explicit`) - * @returns {boolean} - */ - hasPermission(permission, explicit = false, checkAdmin, checkOwner) { - if (typeof checkAdmin === 'undefined') checkAdmin = !explicit; - if (typeof checkOwner === 'undefined') checkOwner = !explicit; - if (checkOwner && this.user.id === this.guild.ownerID) return true; - return this.roles.some(r => r.hasPermission(permission, undefined, checkAdmin)); - } - - /** - * 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} - * @deprecated - */ - 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)); - } - - /** - * The data for editing a guild member - * @typedef {Object} GuildMemberEditData - * @property {string} [nick] The nickname to set for the member - * @property {Collection|Role[]|Snowflake[]} [roles] The roles or role IDs to apply - * @property {boolean} [mute] Whether or not the member should be muted - * @property {boolean} [deaf] Whether or not the member should be deafened - * @property {ChannelResolvable} [channel] Channel to move member to (if they are connected to voice) - */ - - /** - * 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[]|Snowflake[]} 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|Snowflake} role The role or ID of the role to add - * @returns {Promise} - */ - addRole(role) { - if (!(role instanceof Role)) role = this.guild.roles.get(role); - if (!role) throw new TypeError('Supplied parameter was neither a Role nor a Snowflake.'); - return this.client.rest.methods.addMemberRole(this, role); - } - - /** - * Adds multiple roles to the member. - * @param {Collection|Role[]|Snowflake[]} 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|Snowflake} role The role or ID of the role to remove - * @returns {Promise} - */ - removeRole(role) { - if (!(role instanceof Role)) role = this.guild.roles.get(role); - if (!role) throw new TypeError('Supplied parameter was neither a Role nor a Snowflake.'); - return this.client.rest.methods.removeMemberRole(this, role); - } - - /** - * Removes multiple roles from the member. - * @param {Collection|Role[]|Snowflake[]} 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 }); - } - - /** - * Creates a DM channel between the client and the member - * @returns {Promise} - */ - createDM() { - return this.user.createDM(); - } - - /** - * Deletes any DMs with this guild member - * @returns {Promise} - */ - deleteDM() { - return this.user.deleteDM(); - } - - /** - * 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 - /* eslint-disable no-empty-function */ - send() {} - sendMessage() {} - sendEmbed() {} - sendFile() {} - sendCode() {} -} - -TextBasedChannel.applyToClass(GuildMember); - -module.exports = GuildMember; - - -/***/ }), -/* 19 */ -/***/ (function(module, exports, __webpack_require__) { - -const Mentions = __webpack_require__(47); -const Attachment = __webpack_require__(44); -const Embed = __webpack_require__(46); -const MessageReaction = __webpack_require__(48); -const ReactionCollector = __webpack_require__(53); -const Util = __webpack_require__(4); -const Collection = __webpack_require__(3); -const Constants = __webpack_require__(0); -const Permissions = __webpack_require__(9); -let GuildMember; - -/** - * Represents a message on Discord - */ -class Message { - constructor(channel, data, client) { - /** - * The Client that instantiated the Message - * @name Message#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * 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 {Snowflake} - */ - 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 or string 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; - - /** - * 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)); - } - } - - /** - * All valid mentions that the message contains - * @type {MessageMentions} - */ - this.mentions = new Mentions(this, data.mentions, data.mention_roles, data.mention_everyone); - - /** - * ID of the webhook that sent the message, if applicable - * @type {?Snowflake} - */ - this.webhookID = data.webhook_id || null; - - /** - * Whether this message is a hit in a search - * @type {?boolean} - */ - this.hit = typeof data.hit === 'boolean' ? data.hit : null; - - /** - * The previous versions of the message, sorted with the most recent first - * @type {Message[]} - * @private - */ - this._edits = []; - } - - /** - * Updates the message - * @param {Object} data Raw Discord message update data - * @private - */ - patch(data) { - const clone = Util.cloneObject(this); - this._edits.unshift(clone); - - this.editedTimestamp = new Date(data.edited_timestamp).getTime(); - if ('content' in data) this.content = data.content; - if ('pinned' in data) this.pinned = data.pinned; - if ('tts' in data) this.tts = data.tts; - if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(this, e)); - else this.embeds = this.embeds.slice(); - - if ('attachments' in data) { - this.attachments = new Collection(); - for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment)); - } else { - this.attachments = new Collection(this.attachments); - } - - this.mentions = new Mentions( - this, - 'mentions' in data ? data.mentions : this.mentions.users, - 'mentions_roles' in data ? data.mentions_roles : this.mentions.roles, - 'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone - ); - } - - /** - * 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; - }); - } - - /** - * Creates a reaction collector. - * @param {CollectorFilter} filter The filter to apply. - * @param {ReactionCollectorOptions} [options={}] Options to send to the collector. - * @returns {ReactionCollector} - * @example - * // create a reaction collector - * const collector = message.createReactionCollector( - * (reaction, user) => reaction.emoji.id === '👌' && user.id === 'someID', - * { time: 15000 } - * ); - * collector.on('collect', r => console.log(`Collected ${r.emoji.name}`)); - * collector.on('end', collected => console.log(`Collected ${collected.size} items`)); - */ - createReactionCollector(filter, options = {}) { - return new ReactionCollector(this, filter, options); - } - - /** - * An object containing the same properties as CollectorOptions, but a few more: - * @typedef {ReactionCollectorOptions} AwaitReactionsOptions - * @property {string[]} [errors] Stop/end reasons that cause the promise to reject - */ - - /** - * Similar to createCollector but in promise form. Resolves with a collection of reactions that pass the specified - * filter. - * @param {CollectorFilter} filter The filter function to use - * @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector - * @returns {Promise>} - */ - awaitReactions(filter, options = {}) { - return new Promise((resolve, reject) => { - const collector = this.createReactionCollector(filter, options); - collector.once('end', (reactions, reason) => { - if (options.errors && options.errors.includes(reason)) reject(reactions); - else resolve(reactions); - }); - }); - } - - /** - * An array of cached versions of the message, including the current version. - * Sorted from latest (first) to oldest (last). - * @type {Message[]} - * @readonly - */ - get edits() { - const copy = this._edits.slice(); - copy.unshift(this); - return copy; - } - - /** - * 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(Permissions.FLAGS.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(Permissions.FLAGS.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); - } - - /** - * Whether or not a guild member is mentioned in this message. Takes into account - * user mentions, role mentions, and @everyone/@here mentions. - * @param {GuildMember|User} member Member/user to check for a mention of - * @returns {boolean} - */ - isMemberMentioned(member) { - // Lazy-loading is used here to get around a circular dependency that breaks things - if (!GuildMember) GuildMember = __webpack_require__(18); - if (this.mentions.everyone) return true; - if (this.mentions.users.has(member.id)) return true; - if (member instanceof GuildMember && member.roles.some(r => this.mentions.roles.has(r.id))) return true; - return false; - } - - /** - * Options that can be passed into editMessage - * @typedef {Object} MessageEditOptions - * @property {Object} [embed] An embed to be added/edited - * @property {string|boolean} [code] Language for optional codeblock formatting to apply - */ - - /** - * 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) { - if (!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } else if (!options) { - 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 = Util.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) { - if (!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } else if (!options) { - options = {}; - } - return this.channel.send(content, Object.assign(options, { reply: this.member || this.author })); - } - - /** - * Marks the message as read - * This is only available when using a user account. - * @returns {Promise} - */ - acknowledge() { - return this.client.rest.methods.ackMessage(this); - } - - /** - * Fetches the webhook used to create this message. - * @returns {Promise} - */ - fetchWebhook() { - if (!this.webhookID) return Promise.reject(new Error('The message was not sent by a webhook.')); - return this.client.fetchWebhook(this.webhookID); - } - - /** - * 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}` : encodeURIComponent(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; - } - - _removeReaction(emoji, user) { - const emojiID = emoji.id ? `${emoji.name}:${emoji.id}` : encodeURIComponent(emoji.name); - 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; - if (reaction.count <= 0) this.reactions.delete(emojiID); - return reaction; - } - } - return null; - } - - _clearReactions() { - this.reactions.clear(); - } -} - -module.exports = Message; - - -/***/ }), -/* 20 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(Buffer) {// Copyright Joyent, Inc. and other Node contributors. +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // -// 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: +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. // -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: // -// 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. +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. - -function isArray(arg) { - if (Array.isArray) { - return Array.isArray(arg); - } - return objectToString(arg) === '[object Array]'; -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = Buffer.isBuffer; - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5).Buffer)) - -/***/ }), -/* 21 */ -/***/ (function(module, exports, __webpack_require__) { - -exports = module.exports = __webpack_require__(57); -exports.Stream = exports; -exports.Readable = exports; -exports.Writable = __webpack_require__(36); -exports.Duplex = __webpack_require__(13); -exports.Transform = __webpack_require__(58); -exports.PassThrough = __webpack_require__(82); - - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -const path = __webpack_require__(26); -const Message = __webpack_require__(19); -const MessageCollector = __webpack_require__(45); -const Collection = __webpack_require__(3); -const util = __webpack_require__(102); - -/** - * 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 {?Snowflake} - */ - this.lastMessageID = null; - - /** - * The Message object of the last message in the channel, if one was sent. - * @type {?Message} - */ - this.lastMessage = null; - } - - /** - * Options provided when sending or editing a message - * @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 {RichEmbed|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 {FileOptions|string} [file] A file to send with the message **(deprecated)** - * @property {FileOptions[]|string[]} [files] Files to send with the message - * @property {string|boolean} [code] Language for optional codeblock formatting to apply - * @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. - * @property {UserResolvable} [reply] User to reply to (prefixes the message with a mention, except in DMs) - */ - - /** - * @typedef {Object} FileOptions - * @property {BufferResolvable} attachment File to attach - * @property {string} [name='file.jpg'] Filename of the attachment - */ - - /** - * 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] Text for the message - * @param {MessageOptions} [options={}] Options for the message - * @returns {Promise} - * @example - * // send a message - * channel.send('hello!') - * .then(message => console.log(`Sent message: ${message.content}`)) - * .catch(console.error); - */ - send(content, options) { - if (!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } else if (!options) { - options = {}; - } - - if (options.embed && options.embed.file) options.file = options.embed.file; - - if (options.file) { - if (options.files) options.files.push(options.file); - else options.files = [options.file]; - } - - if (options.files) { - for (const i in options.files) { - let file = options.files[i]; - if (typeof file === 'string') file = { attachment: file }; - if (!file.name) { - if (typeof file.attachment === 'string') { - file.name = path.basename(file.attachment); - } else if (file.attachment && file.attachment.path) { - file.name = path.basename(file.attachment.path); - } else { - file.name = 'file.jpg'; - } - } - options.files[i] = file; - } - - return Promise.all(options.files.map(file => - this.client.resolver.resolveBuffer(file.attachment).then(buffer => { - file.file = buffer; - return file; - }) - )).then(files => this.client.rest.methods.sendMessage(this, content, options, files)); - } - - return this.client.rest.methods.sendMessage(this, content, options); - } - - /** - * Gets a single message from this channel, regardless of it being cached or not. Since the single message fetching - * endpoint is reserved for bot accounts, this abstracts the `fetchMessages` method to obtain the single message when - * using a user account. - * @param {Snowflake} messageID 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) { - if (!this.client.user.bot) { - return this.fetchMessages({ limit: 1, around: messageID }).then(messages => { - const msg = messages.get(messageID); - if (!msg) throw new Error('Message not found.'); - return msg; - }); - } - 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 {Snowflake} [before] ID of a message to get the messages that were posted before it - * @property {Snowflake} [after] ID of a message to get the messages that were posted after it - * @property {Snowflake} [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={}] 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; - }); - } - - /** - * @typedef {Object} MessageSearchOptions - * @property {string} [content] Message content - * @property {Snowflake} [maxID] Maximum ID for the filter - * @property {Snowflake} [minID] Minimum ID for the filter - * @property {string} [has] One of `link`, `embed`, `file`, `video`, `image`, or `sound`, - * or add `-` to negate (e.g. `-file`) - * @property {ChannelResolvable} [channel] Channel to limit search to (only for guild search endpoint) - * @property {UserResolvable} [author] Author to limit search - * @property {string} [authorType] One of `user`, `bot`, `webhook`, or add `-` to negate (e.g. `-webhook`) - * @property {string} [sortBy='recent'] `recent` or `relevant` - * @property {string} [sortOrder='desc'] `asc` or `desc` - * @property {number} [contextSize=2] How many messages to get around the matched message (0 to 2) - * @property {number} [limit=25] Maximum number of results to get (1 to 25) - * @property {number} [offset=0] Offset the "pages" of results (since you can only see 25 at a time) - * @property {UserResolvable} [mentions] Mentioned user filter - * @property {boolean} [mentionsEveryone] If everyone is mentioned - * @property {string} [linkHostname] Filter links by hostname - * @property {string} [embedProvider] The name of an embed provider - * @property {string} [embedType] one of `image`, `video`, `url`, `rich` - * @property {string} [attachmentFilename] The name of an attachment - * @property {string} [attachmentExtension] The extension of an attachment - * @property {Date} [before] Date to find messages before - * @property {Date} [after] Date to find messages before - * @property {Date} [during] Date to find messages during (range of date to date + 24 hours) - */ - - /** - * Performs a search within the channel. - * This is only available when using a user account. - * @param {MessageSearchOptions} [options={}] Options to pass to the search - * @returns {Promise>} - * An array containing arrays of messages. Each inner array is a search context cluster. - * The message which has triggered the result will have the `hit` property set to `true`. - * @example - * channel.search({ - * content: 'discord.js', - * before: '2016-11-17' - * }).then(res => { - * const hit = res.messages[0].find(m => m.hit).content; - * console.log(`I found: **${hit}**, total results: ${res.totalResults}`); - * }).catch(console.error); - */ - search(options = {}) { - return this.client.rest.methods.search(this, options); - } - - /** - * 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); - }, 9000), - }); - 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 {CollectorFilter} filter The filter to create the collector with - * @param {MessageCollectorOptions} [options={}] The options to pass to the collector - * @returns {MessageCollector} - * @deprecated - */ - createCollector(filter, options) { - return this.createMessageCollector(filter, options); - } - - /** - * Creates a Message Collector - * @param {CollectorFilter} filter The filter to create the collector with - * @param {MessageCollectorOptions} [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`)); - */ - createMessageCollector(filter, options = {}) { - return new MessageCollector(this, filter, options); - } - - /** - * An object containing the same properties as CollectorOptions, but a few more: - * @typedef {MessageCollectorOptions} 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 {CollectorFilter} 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.once('end', (collection, reason) => { - if (options.errors && options.errors.includes(reason)) { - reject(collection); - } else { - resolve(collection); - } - }); - }); - } - - /** - * Bulk delete given messages that are newer than two weeks - * This is only available when using a bot account. - * @param {Collection|Message[]|number} messages Messages or number of messages to delete - * @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically - * @returns {Promise>} Deleted messages - */ - bulkDelete(messages, filterOld = false) { - if (!isNaN(messages)) return this.fetchMessages({ limit: messages }).then(msgs => this.bulkDelete(msgs, filterOld)); - 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, filterOld); - } - throw new TypeError('The messages must be an Array, Collection, or number.'); - } - - /** - * Marks all messages in this channel as read - * This is only available when using a user account. - * @returns {Promise} - */ - acknowledge() { - if (!this.lastMessageID) return Promise.resolve(this); - return this.client.rest.methods.ackTextChannel(this); - } - - _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; - } -} - -/** @lends TextBasedChannel.prototype */ -const Deprecated = { - /** - * Send a message to this channel - * @param {StringResolvable} [content] Text for the message - * @param {MessageOptions} [options={}] Options for the message - * @returns {Promise} - * @deprecated - * @example - * // send a message - * channel.sendMessage('hello!') - * .then(message => console.log(`Sent message: ${message.content}`)) - * .catch(console.error); - */ - sendMessage(content, options) { - return this.send(content, options); - }, - - /** - * Send an embed to this channel - * @param {RichEmbed|Object} embed Embed for the message - * @param {string} [content] Text for the message - * @param {MessageOptions} [options] Options for the message - * @returns {Promise} - * @deprecated - */ - sendEmbed(embed, content, options) { - if (!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } else if (!options) { - options = {}; - } - return this.send(content, Object.assign(options, { embed })); - }, - - /** - * Send files to this channel - * @param {FileOptions[]|string[]} files Files to send with the message - * @param {StringResolvable} [content] Text for the message - * @param {MessageOptions} [options] Options for the message - * @returns {Promise} - * @deprecated - */ - sendFiles(files, content, options = {}) { - return this.send(content, Object.assign(options, { files })); - }, - - /** - * Send a file to this channel - * @param {BufferResolvable} attachment File to send - * @param {string} [name='file.jpg'] Name and extension of the file - * @param {StringResolvable} [content] Text for the message - * @param {MessageOptions} [options] Options for the message - * @returns {Promise} - * @deprecated - */ - sendFile(attachment, name, content, options = {}) { - return this.sendFiles([{ attachment, name }], content, options); - }, - - /** - * 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] Options for the message - * @returns {Promise} - * @deprecated - */ - sendCode(lang, content, options = {}) { - return this.send(content, Object.assign(options, { code: lang })); - }, -}; - -for (const key of Object.keys(Deprecated)) { - TextBasedChannel.prototype[key] = util.deprecate(Deprecated[key], `TextChannel#${key}: use TextChannel#send instead`); -} - -exports.applyToClass = (structure, full = false, ignore = []) => { - const props = ['send', 'sendMessage', 'sendEmbed', 'sendFile', 'sendFiles', 'sendCode']; - if (full) { - props.push( - '_cacheMessage', - 'acknowledge', - 'fetchMessages', - 'fetchMessage', - 'search', - 'bulkDelete', - 'startTyping', - 'stopTyping', - 'typing', - 'typingCount', - 'fetchPinnedMessages', - 'createCollector', - 'createMessageCollector', - 'awaitMessages' - ); - } - for (const prop of props) { - if (ignore.includes(prop)) continue; - Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop)); - } +module.exports = { + 2: 'need dictionary', /* Z_NEED_DICT 2 */ + 1: 'stream end', /* Z_STREAM_END 1 */ + 0: '', /* Z_OK 0 */ + '-1': 'file error', /* Z_ERRNO (-1) */ + '-2': 'stream error', /* Z_STREAM_ERROR (-2) */ + '-3': 'data error', /* Z_DATA_ERROR (-3) */ + '-4': 'insufficient memory', /* Z_MEM_ERROR (-4) */ + '-5': 'buffer error', /* Z_BUF_ERROR (-5) */ + '-6': 'incompatible version' /* Z_VERSION_ERROR (-6) */ }; -/***/ }), +/***/ }, /* 23 */ -/***/ (function(module, exports) { - -exports.endianness = function () { return 'LE' }; - -exports.hostname = function () { - if (typeof location !== 'undefined') { - return location.hostname - } - else return ''; -}; - -exports.loadavg = function () { return [] }; - -exports.uptime = function () { return 0 }; - -exports.freemem = function () { - return Number.MAX_VALUE; -}; - -exports.totalmem = function () { - return Number.MAX_VALUE; -}; - -exports.cpus = function () { return [] }; - -exports.type = function () { return 'Browser' }; - -exports.release = function () { - if (typeof navigator !== 'undefined') { - return navigator.appVersion; - } - return ''; -}; - -exports.networkInterfaces -= exports.getNetworkInterfaces -= function () { return {} }; - -exports.arch = function () { return 'javascript' }; - -exports.platform = function () { return 'browser' }; - -exports.tmpdir = exports.tmpDir = function () { - return '/tmp'; -}; - -exports.EOL = '\n'; - - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -const Long = __webpack_require__(33); -const User = __webpack_require__(16); -const Role = __webpack_require__(15); -const Emoji = __webpack_require__(17); -const Presence = __webpack_require__(11).Presence; -const GuildMember = __webpack_require__(18); -const Constants = __webpack_require__(0); -const Collection = __webpack_require__(3); -const Util = __webpack_require__(4); -const Snowflake = __webpack_require__(7); - -/** - * 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. - * @name Guild#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - /** - * 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(); - - /** - * A collection of presences in this guild - * @type {Collection} - */ - this.presences = 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 {Snowflake} - */ - 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 = Boolean('large' in data ? data.large : this.large); - - /** - * An array of guild features. - * @type {Object[]} - */ - this.features = data.features; - - /** - * The ID of the application that created this guild (if applicable) - * @type {?Snowflake} - */ - this.applicationID = data.application_id; - - /** - * 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 explicit content filter level of the guild. - * @type {number} - */ - this.explicitContentFilter = data.explicit_content_filter; - - /** - * 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 {Snowflake} - */ - 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); - } - } - } - - if (!this.emojis) { - /** - * 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)); - } else { - this.client.actions.GuildEmojisUpdate.handle({ - guild_id: this.id, - emojis: data.emojis, - }); - } - } - - /** - * The timestamp the guild was created at - * @type {number} - * @readonly - */ - get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; - } - - /** - * 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.Guild(this).Icon(this.client.options.http.cdn, this.icon); - } - - /** - * Gets the URL to this guild's splash (if it has one, otherwise it returns null) - * @type {?string} - * @readonly - */ - get splashURL() { - if (!this.splash) return null; - return Constants.Endpoints.Guild(this).Splash(this.client.options.http.cdn, this.splash); - } - - /** - * 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` TextChannel of the guild. - * @type {TextChannel} - * @readonly - */ - get defaultChannel() { - return this.channels.get(this.id); - } - - /** - * Get the position of this guild - * This is only available when using a user account. - * @type {?number} - */ - get position() { - if (this.client.user.bot) return null; - if (!this.client.user.settings.guildPositions) return null; - return this.client.user.settings.guildPositions.indexOf(this.id); - } - - /** - * The `@everyone` Role of the guild. - * @type {Role} - * @readonly - */ - get defaultRole() { - return this.roles.get(this.id); - } - - /** - * Fetches a collection of roles in the current guild sorted by position. - * @type {Collection} - * @readonly - * @private - */ - get _sortedRoles() { - return this._sortPositionWithID(this.roles); - } - - /** - * 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 available voice regions - * @returns {Collection} - */ - fetchVoiceRegions() { - return this.client.rest.methods.fetchVoiceRegions(this.id); - } - - /** - * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission. - * @param {UserResolvable} user User to add to the guild - * @param {Object} options Options for the addition - * @param {string} options.accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the - * bot's application - * @param {string} [options.nick] Nickname to give the member (requires `MANAGE_NICKNAMES`) - * @param {Collection|Role[]|Snowflake[]} [options.roles] Roles to add to the member - * (requires `MANAGE_ROLES`) - * @param {boolean} [options.mute] Whether the member should be muted (requires `MUTE_MEMBERS`) - * @param {boolean} [options.deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`) - * @returns {Promise} - */ - addMember(user, options) { - if (this.members.has(user.id)) return Promise.resolve(this.members.get(user.id)); - return this.client.rest.methods.putGuildMember(this, user, options); - } - - /** - * Fetch a single guild member from a user. - * @param {UserResolvable} user The user to fetch the member for - * @param {boolean} [cache=true] Insert the user into the users cache - * @returns {Promise} - */ - fetchMember(user, cache = true) { - 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, cache); - } - - /** - * 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=''] Limit fetch to members with similar usernames - * @param {number} [limit=0] Maximum number of members to request - * @returns {Promise} - */ - fetchMembers(query = '', limit = 0) { - return new Promise((resolve, reject) => { - if (this.memberCount === this.members.size) { - // Uncomment in v12 - // resolve(this.members) - resolve(this); - return; - } - this.client.ws.send({ - op: Constants.OPCodes.REQUEST_GUILD_MEMBERS, - d: { - guild_id: this.id, - query, - limit, - }, - }); - const handler = (members, guild) => { - if (guild.id !== this.id) return; - if (this.memberCount === this.members.size || members.length < 1000) { - this.client.removeListener(Constants.Events.GUILD_MEMBERS_CHUNK, handler); - // Uncomment in v12 - // resolve(this.members) - resolve(this); - } - }; - this.client.on(Constants.Events.GUILD_MEMBERS_CHUNK, handler); - this.client.setTimeout(() => reject(new Error('Members didn\'t arrive in time.')), 120 * 1000); - }); - } - - /** - * Performs a search within the entire guild. - * This is only available when using a user account. - * @param {MessageSearchOptions} [options={}] Options to pass to the search - * @returns {Promise>} - * An array containing arrays of messages. Each inner array is a search context cluster. - * The message which has triggered the result will have the `hit` property set to `true`. - * @example - * guild.search({ - * content: 'discord.js', - * before: '2016-11-17' - * }).then(res => { - * const hit = res.messages[0].find(m => m.hit).content; - * console.log(`I found: **${hit}**, total results: ${res.totalResults}`); - * }).catch(console.error); - */ - search(options = {}) { - return this.client.rest.methods.search(this, options); - } - - /** - * 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(guild.members.first()) - * .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 by ID (or with a user/guild member object) - * guild.ban('some user ID') - * .then(user => console.log(`Banned ${user.username || user.id || user} from ${guild.name}`)) - * .catch(console.error); - */ - 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 by ID (or with a user/guild member object) - * guild.unban('some user ID') - * .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`)) - * .catch(console.error); - */ - 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` - * @param {Array} overwrites Permission overwrites to apply to the new channel - * @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, overwrites) { - return this.client.rest.methods.createChannel(this, name, type, overwrites); - } - - /** - * The data needed for updating a channel's position. - * @typedef {Object} ChannelPosition - * @property {ChannelResolvable} channel Channel to update - * @property {number} position New position for the channel - */ - - /** - * Batch-updates the guild's channels' positions. - * @param {ChannelPosition[]} channelPositions Channel positions to update - * @returns {Promise} - * @example - * guild.updateChannels([{ channel: channelID, position: newChannelIndex }]) - * .then(guild => console.log(`Updated channel positions for ${guild.id}`)) - * .catch(console.error); - */ - setChannelPositions(channelPositions) { - return this.client.rest.methods.updateChannelPositions(this.id, channelPositions); - } - - /** - * Creates a new role in the guild with 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', - * color: 'BLUE', - * }) - * .then(role => console.log(`Created role ${role}`)) - * .catch(console.error) - */ - createRole(data = {}) { - return this.client.rest.methods.createGuildRole(this, data); - } - - /** - * Creates a new custom emoji in the guild. - * @param {BufferResolvable|Base64Resolvable} attachment The image for the emoji. - * @param {string} name The name for the emoji. - * @param {Collection|Role[]} [roles] Roles to limit the emoji to - * @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, roles) { - return new Promise(resolve => { - if (typeof attachment === 'string' && attachment.startsWith('data:')) { - resolve(this.client.rest.methods.createEmoji(this, attachment, name, roles)); - } else { - this.client.resolver.resolveBuffer(attachment).then(data => { - const dataURI = this.client.resolver.resolveBase64(data); - resolve(this.client.rest.methods.createEmoji(this, dataURI, name, roles)); - }); - } - }); - } - - /** - * 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); - } - - /** - * Marks all messages in this guild as read - * This is only available when using a user account. - * @returns {Promise} this guild - */ - acknowledge() { - return this.client.rest.methods.ackGuild(this); - } - - /** - * @param {number} position Absolute or relative position - * @param {boolean} [relative=false] Whether to position relatively or absolutely - * @returns {Promise} - */ - setPosition(position, relative) { - if (this.client.user.bot) { - return Promise.reject(new Error('Setting guild position is only available for user accounts')); - } - return this.client.user.settings.setGuildPosition(this, position, relative); - } - - /** - * Allow direct messages from guild members - * @param {boolean} allow Whether to allow direct messages - * @returns {Promise} - */ - allowDMs(allow) { - const settings = this.client.user.settings; - if (allow) return settings.removeRestrictedGuild(this); - else return settings.addRestrictedGuild(this); - } - - /** - * 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 Guild to compare with - * @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 && - Util.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.has(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; - if (this.client.channels.has(voiceState.channel_id)) { - this.client.channels.get(voiceState.channel_id).members.set(member.user.id, member); - } else { - this.client.emit('warn', `Member ${member.id} added in guild ${this.id} with an uncached voice channel`); - } - } - - /** - * Emitted whenever a user joins a guild. - * @event Client#guildMemberAdd - * @param {GuildMember} member The member that has joined a guild - */ - if (this.client.ws.connection.status === Constants.Status.READY && emitEvent && !existing) { - this.client.emit(Constants.Events.GUILD_MEMBER_ADD, member); - } - - return member; - } - - _updateMember(member, data) { - const oldMember = Util.cloneObject(member); - - if (data.roles) member._roles = data.roles; - if (typeof data.nick !== 'undefined') member.nickname = data.nick; - - const notSame = member.nickname !== oldMember.nickname || !Util.arraysEqual(member._roles, oldMember._roles); - - if (this.client.ws.connection.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); - } - - _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)); - } - - /** - * 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 - * @param {boolean} [relative=false] Position Moves the role relative to its current position - * @returns {Promise} - */ - setRolePosition(role, position, relative = false) { - if (typeof role === 'string') { - role = this.roles.get(role); - if (!role) return Promise.reject(new Error('Supplied role is not a role or snowflake.')); - } - - position = Number(position); - if (isNaN(position)) return Promise.reject(new Error('Supplied position is not a number.')); - - let updatedRoles = this._sortedRoles.array(); - - Util.moveElementInArray(updatedRoles, role, position, relative); - - updatedRoles = updatedRoles.map((r, i) => ({ id: r.id, position: i })); - return this.client.rest.methods.setRolePositions(this.id, updatedRoles); - } - - /** - * Set the position of a channel in this guild - * @param {string|GuildChannel} channel The channel to edit, can be a channel object or a channel ID. - * @param {number} position The new position of the channel - * @param {boolean} [relative=false] Position Moves the channel relative to its current position - * @returns {Promise} - */ - setChannelPosition(channel, position, relative = false) { - if (typeof channel === 'string') { - channel = this.channels.get(channel); - if (!channel) return Promise.reject(new Error('Supplied channel is not a channel or snowflake.')); - } - - position = Number(position); - if (isNaN(position)) return Promise.reject(new Error('Supplied position is not a number.')); - - let updatedChannels = this._sortedChannels(channel.type).array(); - - Util.moveElementInArray(updatedChannels, channel, position, relative); - - updatedChannels = updatedChannels.map((r, i) => ({ id: r.id, position: i })); - return this.client.rest.methods.setChannelPositions(this.id, updatedChannels); - } - - /** - * Fetches a collection of channels in the current guild sorted by position. - * @param {string} type Channel type - * @returns {Collection} - * @private - */ - _sortedChannels(type) { - return this._sortPositionWithID(this.channels.filter(c => { - if (type === 'voice' && c.type === 'voice') return true; - else if (type !== 'voice' && c.type !== 'voice') return true; - else return type === c.type; - })); - } - - /** - * Sorts a collection by object position or ID if the positions are equivalent. - * Intended to be identical to Discord's sorting method. - * @param {Collection} collection The collection to sort - * @returns {Collection} - * @private - */ - _sortPositionWithID(collection) { - return collection.sort((a, b) => - a.position !== b.position ? - a.position - b.position : - Long.fromString(a.id).sub(Long.fromString(b.id)).toNumber() - ); - } -} - -module.exports = Guild; - - -/***/ }), -/* 25 */ -/***/ (function(module, exports, __webpack_require__) { - -const Channel = __webpack_require__(14); -const Role = __webpack_require__(15); -const PermissionOverwrites = __webpack_require__(52); -const Permissions = __webpack_require__(9); -const Collection = __webpack_require__(3); - -/** - * 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)); - } - } - } - - /** - * The position of the channel - * @type {number} - * @readonly - */ - get calculatedPosition() { - const sorted = this.guild._sortedChannels(this.type); - return sorted.array().indexOf(sorted.get(this.id)); - } - - /** - * 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 {?Permissions} - */ - permissionsFor(member) { - member = this.client.resolver.resolveGuildMember(this.guild, member); - if (!member) return null; - if (member.id === this.guild.ownerID) return new Permissions(member, Permissions.ALL); - - let permissions = 0; - - const roles = member.roles; - for (const role of roles.values()) permissions |= role.permissions; - - const overwrites = this.overwritesFor(member, true, roles); - - if (overwrites.everyone) { - permissions &= ~overwrites.everyone.deny; - permissions |= overwrites.everyone.allow; - } - - let allow = 0; - for (const overwrite of overwrites.roles) { - permissions &= ~overwrite.deny; - allow |= overwrite.allow; - } - permissions |= allow; - - if (overwrites.member) { - permissions &= ~overwrites.member.deny; - permissions |= overwrites.member.allow; - } - - const admin = Boolean(permissions & Permissions.FLAGS.ADMINISTRATOR); - if (admin) permissions = Permissions.ALL; - - return new Permissions(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 = []; - let memberOverwrites; - let everyoneOverwrites; - - for (const overwrite of this.permissionOverwrites.values()) { - if (overwrite.id === this.guild.id) { - everyoneOverwrites = overwrite; - } else if (roles.has(overwrite.id)) { - roleOverwrites.push(overwrite); - } else if (overwrite.id === member.id) { - memberOverwrites = overwrite; - } - } - - return { - everyone: everyoneOverwrites, - roles: 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.allow; - payload.deny = prevOverwrite.deny; - } - - for (const perm in options) { - if (options[perm] === true) { - payload.allow |= Permissions.FLAGS[perm] || 0; - payload.deny &= ~(Permissions.FLAGS[perm] || 0); - } else if (options[perm] === false) { - payload.allow &= ~(Permissions.FLAGS[perm] || 0); - payload.deny |= Permissions.FLAGS[perm] || 0; - } else if (options[perm] === null) { - payload.allow &= ~(Permissions.FLAGS[perm] || 0); - payload.deny &= ~(Permissions.FLAGS[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 - * @param {boolean} [relative=false] Move the position relative to its current value - * @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, relative) { - return this.guild.setChannelPosition(this, position, relative).then(() => this); - } - - /** - * 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 - - */ - - /** - * Create an invite to this guild channel - * @param {InviteOptions} [options={}] Options for the invite - * @param {boolean} [options.temporary=false] Whether members that joined via the invite should be automatically - * kicked after 24 hours if they have not yet received a role - * @param {number} [options.maxAge=86400] How long the invite should last (in seconds, 0 for forever) - * @param {number} [options.maxUses=0] Maximum number of uses - * @returns {Promise} - */ - createInvite(options = {}) { - return this.client.rest.methods.createChannelInvite(this, options); - } - - /** - * Clone this channel - * @param {string} [name=this.name] Optional name for the new channel, otherwise it has the name of this channel - * @param {boolean} [withPermissions=true] Whether to clone the channel with this channel's permission overwrites - * @param {boolean} [withTopic=true] Whether to clone the channel with this channel's topic - * @returns {Promise} - */ - clone(name = this.name, withPermissions = true, withTopic = true) { - return this.guild.createChannel(name, this.type, withPermissions ? this.permissionOverwrites : []) - .then(channel => withTopic ? channel.setTopic(this.topic) : channel); - } - - /** - * 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 Channel to compare with - * @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) { - equal = this.permissionOverwrites.equals(channel.permissionOverwrites); - } else { - equal = !this.permissionOverwrites && !channel.permissionOverwrites; - } - } - - return equal; - } - - /** - * Whether the channel is deletable by the client user. - * @type {boolean} - * @readonly - */ - get deletable() { - return this.id !== this.guild.id && - this.permissionsFor(this.client.user).hasPermission(Permissions.FLAGS.MANAGE_CHANNELS); - } - - /** - * 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; - - -/***/ }), -/* 26 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { /* WEBPACK VAR INJECTION */(function(process) {// Copyright Joyent, Inc. and other Node contributors. // @@ -8500,20 +7259,1635 @@ var substr = 'ab'.substr(-1) === 'b' } ; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6))) +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24))) -/***/ }), +/***/ }, +/* 24 */ +/***/ 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; }; + + +/***/ }, +/* 25 */ +/***/ 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__(64); +var RequestBase = __webpack_require__(78); +var isObject = __webpack_require__(26); +var isFunction = __webpack_require__(77); +var ResponseBase = __webpack_require__(79); +var shouldRetry = __webpack_require__(80); + +/** + * Noop. + */ + +function noop(){}; + +/** + * Expose `request`. + */ + +var request = exports = module.exports = function(method, url) { + // callback + if ('function' == typeof url) { + return new exports.Request('GET', method).end(url); + } + + // url first + if (1 == arguments.length) { + return new exports.Request('GET', method); + } + + return new exports.Request(method, url); +} + +exports.Request = 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); +} + +/** + * 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) { + 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; + var status = this.xhr.status; + // handle IE9 bug: http://stackoverflow.com/questions/10046972/msie-returns-status-code-of-1223-for-ajax-request + if (status === 1223) { + status = 204; + } + this._setStatusProperties(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); + + if (null === this.text && req._responseType) { + this.body = this.xhr.response; + } else { + this.body = this.req.method != 'HEAD' + ? this._parseBody(this.text ? this.text : this.xhr.response) + : null; + } +} + +ResponseBase(Response.prototype); + +/** + * 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(this.req._parser) { + return this.req._parser(this, str); + } + if (!parse && isJSON(this.type)) { + parse = request.parse['application/json']; + } + return parse && str && (str.length || str instanceof Object) + ? parse(str) + : null; +}; + +/** + * 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.status = self.xhr.status ? self.xhr.status : null; + err.statusCode = err.status; // backwards-compat only + } else { + err.rawResponse = null; + err.status = null; + } + + return self.callback(err); + } + + self.emit('response', res); + + var new_err; + try { + if (!self._isResponseOK(res)) { + 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 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] optional in case of using 'bearer' as type + * @param {Object} options with 'type' property 'auto', 'basic' or 'bearer' (default 'basic') + * @return {Request} for chaining + * @api public + */ + +Request.prototype.auth = function(user, pass, options){ + if (typeof pass === 'object' && pass !== null) { // pass is optional and can substitute for options + options = pass; + } + if (!options) { + options = { + type: 'function' === typeof btoa ? 'basic' : 'auto', + } + } + + switch (options.type) { + case 'basic': + this.set('Authorization', 'Basic ' + btoa(user + ':' + pass)); + break; + + case 'auto': + this.username = user; + this.password = pass; + break; + + case 'bearer': // usage would be .auth(accessToken, { type: 'bearer' }) + this.set('Authorization', 'Bearer ' + user); + 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 (file) { + 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){ + // console.log(this._retries, this._maxRetries) + if (this._maxRetries && this._retries++ < this._maxRetries && shouldRetry(err, res)) { + return this._retry(); + } + + var fn = this._callback; + this.clearTimeout(); + + if (err) { + if (this._maxRetries) err.retries = this._retries - 1; + 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"); +}; + +/** + * 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('?') >= 0 ? '&' : '?') + query; + } + + if (this._sort) { + var index = this.url.indexOf('?'); + if (index >= 0) { + var queryArr = this.url.substring(index + 1).split('&'); + if (isFunction(this._sort)) { + queryArr.sort(this._sort); + } else { + queryArr.sort(); + } + this.url = this.url.substring(0, index) + '?' + queryArr.join('&'); + } + } +}; + +/** + * 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){ + if (this._endCalled) { + console.warn("Warning: .end() was called twice. This is not supported in superagent"); + } + this._endCalled = true; + + // store callback + this._callback = fn || noop; + + // querystring + this._appendQueryString(); + + return this._end(); +}; + +Request.prototype._end = function() { + var self = this; + var xhr = this.xhr = request.getXHR(); + var data = this._formData || this._data; + + this._setTimeouts(); + + // state change + xhr.onreadystatechange = function(){ + var readyState = xhr.readyState; + if (readyState >= 2 && self._responseTimeoutTimer) { + clearTimeout(self._responseTimeoutTimer); + } + if (4 != 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 (!status) { + if (self.timedout || 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 + } + } + + // initiate request + try { + if (this.username && this.password) { + xhr.open(this.method, this.url, true, this.username, this.password); + } else { + xhr.open(this.method, this.url, true); + } + } catch (err) { + // see #1149 + return this.callback(err); + } + + // CORS + if (this._withCredentials) xhr.withCredentials = true; + + // body + if (!this._formData && '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; + + if (this.header.hasOwnProperty(field)) + 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; +}; + +/** + * 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 `data` and callback `fn(res)`. + * + * @param {String} url + * @param {Mixed} [data] + * @param {Function} [fn] + * @return {Request} + * @api public + */ + +function del(url, data, fn){ + var req = request('DELETE', url); + if ('function' == typeof data) fn = data, data = null; + if (data) req.send(data); + 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; +}; + + +/***/ }, +/* 26 */ +/***/ 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; + + +/***/ }, /* 27 */ -/***/ (function(module, exports) { +/***/ function(module, exports) { +module.exports = { + "name": "discord.js", + "version": "11.0.0", + "description": "A powerful library for interacting with the Discord API", + "main": "./src/index", + "types": "./typings/index.d.ts", + "scripts": { + "test": "eslint src && docgen --source src --custom docs/index.yml", + "docs": "docgen --source src --custom docs/index.yml --output docs/docs.json", + "test-docs": "docgen --source src --custom docs/index.yml", + "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", + "runkitExampleFilename": "./docs/examples/ping.js", + "dependencies": { + "@types/node": "^6.0.0", + "long": "^3.2.0", + "pako": "^1.0.0", + "superagent": "^3.3.0", + "tweetnacl": "^0.14.0", + "ws": "^1.1.1" + }, + "peerDependencies": { + "erlpack": "hammerandchisel/erlpack", + "node-opus": "^0.2.0", + "opusscript": "^0.0.1", + "uws": "^0.12.0" + }, + "devDependencies": { + "discord.js-docgen": "hydrabolt/discord.js-docgen", + "eslint": "^3.12.0", + "parallel-webpack": "^1.6.0", + "uglify-js": "mishoo/UglifyJS2#harmony", + "webpack": "2.2.0-rc.3" + }, + "engines": { + "node": ">=6.0.0" + }, + "browser": { + "ws": false, + "uws": false, + "erlpack": 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 + } +}; - -/***/ }), +/***/ }, /* 28 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ function(module, exports, __webpack_require__) { -const Channel = __webpack_require__(14); -const TextBasedChannel = __webpack_require__(22); +const User = __webpack_require__(6); +const OAuth2Application = __webpack_require__(37); + +/** + * 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; + + +/***/ }, +/* 29 */ +/***/ function(module, exports, __webpack_require__) { + +const User = __webpack_require__(6); +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(); + + /** + * Discord client settings, such as guild positions + * This is only filled when using a user account. + * @type {Object} + */ + this.settings = {}; + } + + 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 + * @param {string} [password] Current password (only for user accounts) + * @returns {Promise} + * @example + * // set username + * client.user.setUsername('discordjs') + * .then(user => console.log(`My new username is ${user.username}`)) + * .catch(console.error); + */ + setUsername(username, password) { + return this.client.rest.methods.updateCurrentUser({ username }, password); + } + + /** + * Changes the email for the client user's account. + * This is only available when using a user account. + * @param {string} email New email to change to + * @param {string} password Current password + * @returns {Promise} + * @example + * // set email + * client.user.setEmail('bob@gmail.com', 'some amazing password 123') + * .then(user => console.log(`My new email is ${user.email}`)) + * .catch(console.error); + */ + setEmail(email, password) { + return this.client.rest.methods.updateCurrentUser({ email }, password); + } + + /** + * Changes the password for the client user's account. + * This is only available when using a user account. + * @param {string} newPassword New password to change to + * @param {string} oldPassword Current password + * @returns {Promise} + * @example + * // set password + * client.user.setPassword('some new amazing password 456', 'some amazing password 123') + * .then(user => console.log('New password set!')) + * .catch(console.error); + */ + setPassword(newPassword, oldPassword) { + return this.client.rest.methods.updateCurrentUser({ password: newPassword }, oldPassword); + } + + /** + * 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 (typeof avatar === 'string' && 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 }) + ); + } + } + + /** + * Data resembling a raw Discord presence + * @typedef {Object} PresenceData + * @property {PresenceStatus} [status] Status of the user + * @property {boolean} [afk] Whether the user is AFK + * @property {Object} [game] Game the user is playing + * @property {string} [game.name] Name of the game + * @property {string} [game.url] Twitch stream URL + */ + + /** + * Sets the full presence of the client user. + * @param {PresenceData} data Data for the presence + * @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); + }); + } + + /** + * A user's status. Must be one of: + * - `online` + * - `idle` + * - `invisible` + * - `dnd` (do not disturb) + * @typedef {string} PresenceStatus + */ + + /** + * Sets the status of the client user. + * @param {PresenceStatus} status Status to change to + * @returns {Promise} + */ + setStatus(status) { + return this.setPresence({ status }); + } + + /** + * Sets the game the client user is playing. + * @param {string} game Game being played + * @param {string} [streamingURL] Twitch stream URL + * @returns {Promise} + */ + setGame(game, streamingURL) { + return this.setPresence({ game: { + name: game, + url: streamingURL, + } }); + } + + /** + * Sets/removes the AFK flag for the client user. + * @param {boolean} afk Whether or not the user is AFK + * @returns {Promise} + */ + setAFK(afk) { + return this.setPresence({ afk }); + } + + /** + * Fetches messages that mentioned the client's user + * @param {Object} [options] Options for the fetch + * @param {number} [options.limit=25] Maximum number of mentions to retrieve + * @param {boolean} [options.roles=true] Whether to include role mentions + * @param {boolean} [options.everyone=true] Whether to include everyone/here mentions + * @param {Guild|string} [options.guild] Limit the search to a specific guild + * @returns {Promise} + */ + fetchMentions(options = { limit: 25, roles: true, everyone: true, guild: null }) { + return this.client.rest.methods.fetchMentions(options); + } + + /** + * 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 (typeof icon === 'string' && 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 }) + ); + } + } +} + +module.exports = ClientUser; + + +/***/ }, +/* 30 */ +/***/ function(module, exports, __webpack_require__) { + +const Channel = __webpack_require__(8); +const TextBasedChannel = __webpack_require__(12); +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 + send() { return; } + sendMessage() { return; } + sendEmbed() { return; } + sendFile() { return; } + sendCode() { return; } + fetchMessage() { return; } + fetchMessages() { return; } + fetchPinnedMessages() { return; } + search() { 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; + + +/***/ }, +/* 31 */ +/***/ function(module, exports, __webpack_require__) { + +const Channel = __webpack_require__(8); +const TextBasedChannel = __webpack_require__(12); const Collection = __webpack_require__(3); /* @@ -8572,28 +8946,10 @@ class GroupDMChannel extends Channel { */ this.ownerID = data.owner_id; - /** - * If the dm is managed by an application - * @type {boolean} - */ - this.managed = data.managed; - - /** - * Application ID of the application that made this group dm, if applicable - * @type {?string} - */ - this.applicationID = data.application_id; - - /** - * Nicknames for group members - * @type {?Collection} - */ - if (data.nicks) this.nicks = new Collection(data.nicks.map(n => [n.id, n.nick])); - if (!this.recipients) { /** * A collection of the recipients of this DM, mapped by their ID. - * @type {Collection} + * @type {Collection} */ this.recipients = new Collection(); } @@ -8638,20 +8994,6 @@ class GroupDMChannel extends Channel { return equal; } - /** - * Add a user to the dm - * @param {UserResolvable|string} accessTokenOrID Access token or user resolvable - * @param {string} [nick] Permanent nickname to give the user (only available if a bot is creating the dm) - */ - - addUser(accessTokenOrID, nick) { - return this.client.rest.methods.addUserToGroupDM(this, { - nick, - id: this.client.resolver.resolveUserID(accessTokenOrID), - accessToken: accessTokenOrID, - }); - } - /** * When concatenated with a string, this automatically concatenates the channel's name instead of the Channel object. * @returns {string} @@ -8667,413 +9009,373 @@ class GroupDMChannel extends Channel { } // These are here only for documentation purposes - they are implemented by TextBasedChannel - /* eslint-disable no-empty-function */ - send() {} - sendMessage() {} - sendEmbed() {} - sendFile() {} - sendFiles() {} - sendCode() {} - fetchMessage() {} - fetchMessages() {} - fetchPinnedMessages() {} - search() {} - startTyping() {} - stopTyping() {} - get typing() {} - get typingCount() {} - createCollector() {} - awaitMessages() {} - // Doesn't work on group DMs; bulkDelete() {} - acknowledge() {} - _cacheMessage() {} + send() { return; } + sendMessage() { return; } + sendEmbed() { return; } + sendFile() { return; } + sendCode() { return; } + fetchMessage() { return; } + fetchMessages() { return; } + fetchPinnedMessages() { return; } + search() { return; } + startTyping() { return; } + stopTyping() { return; } + get typing() { return; } + get typingCount() { return; } + createCollector() { return; } + awaitMessages() { return; } + bulkDelete() { return; } + _cacheMessage() { return; } } -TextBasedChannel.applyToClass(GroupDMChannel, true, ['bulkDelete']); +TextBasedChannel.applyToClass(GroupDMChannel, true); module.exports = GroupDMChannel; -/***/ }), -/* 29 */ -/***/ (function(module, exports) { +/***/ }, +/* 32 */ +/***/ function(module, exports, __webpack_require__) { + +const PartialGuild = __webpack_require__(38); +const PartialGuildChannel = __webpack_require__(39); +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 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. + * Represents an invitation to a guild channel. + * The only guaranteed properties are `code`, `guild` and `channel`. Other properties can be missing. */ -class ReactionEmoji { - constructor(reaction, name, id) { +class Invite { + constructor(client, data) { /** - * 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 {?Snowflake} - */ - this.id = id; - } - - /** - * The identifier of this emoji, used for message reactions - * @type {string} - * @readonly - */ - 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; - - -/***/ }), -/* 30 */ -/***/ (function(module, exports, __webpack_require__) { - -const path = __webpack_require__(26); - -/** - * Represents a webhook - */ -class Webhook { - constructor(client, dataOrID, token) { - if (client) { - /** - * The Client that instantiated the Webhook - * @name Webhook#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - if (dataOrID) this.setup(dataOrID); - } else { - this.id = dataOrID; - this.token = token; - Object.defineProperty(this, 'client', { value: 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 {Snowflake} - */ - this.id = data.id; - - /** - * The guild the webhook belongs to - * @type {Snowflake} - */ - this.guildID = data.guild_id; - - /** - * The channel the webhook belongs to - * @type {Snowflake} - */ - this.channelID = data.channel_id; - - if (data.user) { - /** - * The owner of the webhook - * @type {?User|Object} - */ - this.owner = this.client.users ? this.client.users.get(data.user.id) : data.user; - } else { - this.owner = null; - } - } - - /** - * Options that can be passed into send, sendMessage, sendFile, sendEmbed, and sendCode - * @typedef {Object} WebhookMessageOptions - * @property {string} [username=this.name] Username override for the message - * @property {string} [avatarURL] Avatar URL override for the message - * @property {boolean} [tts=false] Whether or not the message should be spoken aloud - * @property {string} [nonce=''] The nonce for the message - * @property {Object[]} [embeds] An array of embeds 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 {FileOptions|string} [file] A file to send with the message - * @property {string|boolean} [code] Language for optional codeblock formatting to apply - * @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. - */ - - /** - * 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.send('hello!') - * .then(message => console.log(`Sent message: ${message.content}`)) - * .catch(console.error); - */ - send(content, options) { - if (!options && typeof content === 'object' && !(content instanceof Array)) { - options = content; - content = ''; - } else if (!options) { - options = {}; - } - if (options.file) { - if (typeof options.file === 'string') options.file = { attachment: options.file }; - if (!options.file.name) { - if (typeof options.file.attachment === 'string') { - options.file.name = path.basename(options.file.attachment); - } else if (options.file.attachment && options.file.attachment.path) { - options.file.name = path.basename(options.file.attachment.path); - } else { - options.file.name = 'file.jpg'; - } - } - return this.client.resolver.resolveBuffer(options.file.attachment).then(file => - this.client.rest.methods.sendWebhookMessage(this, content, options, { - file, - name: options.file.name, - }) - ); - } - return this.client.rest.methods.sendWebhookMessage(this, content, options); - } - - /** - * 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.send(content, options); - } - - /** - * Send a file with this webhook - * @param {BufferResolvable} attachment The file to send - * @param {string} [name='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, name, content, options = {}) { - return this.send(content, Object.assign(options, { file: { attachment, name } })); - } - - /** - * 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 = {}) { - return this.send(content, Object.assign(options, { code: lang })); - } - - /** - * 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': Date.now() / 1000 - * }] - * }).catch(console.error); - */ - sendSlackMessage(body) { - return this.client.rest.methods.sendSlackWebhookMessage(this, body); - } - - /** - * 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; - - -/***/ }), -/* 31 */ -/***/ (function(module, exports, __webpack_require__) { - -const Collection = __webpack_require__(3); -const EventEmitter = __webpack_require__(12).EventEmitter; - -/** - * Filter to be applied to the collector. - * @typedef {Function} CollectorFilter - * @param {...*} args Any arguments received by the listener. - * @returns {boolean} To collect or not collect. - */ - -/** - * Options to be applied to the collector. - * @typedef {Object} CollectorOptions - * @property {number} [time] How long to run the collector for. - */ - -/** - * Abstract class for defining a new Collector. - * @abstract - */ -class Collector extends EventEmitter { - constructor(client, filter, options = {}) { - super(); - - /** - * The client. - * @name Collector#client + * The client that instantiated the invite + * @name Invite#client * @type {Client} * @readonly */ Object.defineProperty(this, 'client', { value: client }); + this.setup(data); + } + + setup(data) { /** - * The filter applied to this collector. - * @type {CollectorFilter} + * 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; + + +/***/ }, +/* 33 */ +/***/ function(module, exports) { + +/** + * Represents an attachment in a message + */ +class MessageAttachment { + constructor(message, data) { + /** + * The Client that instantiated this MessageAttachment. + * @name MessageAttachment#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: message.client }); + + /** + * 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; + + +/***/ }, +/* 34 */ +/***/ 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; /** - * The options of this collector. + * Options for the collecor. * @type {CollectorOptions} */ this.options = options; /** - * The items collected by this collector. - * @type {Collection} - */ - this.collected = new Collection(); - - /** - * Whether this collector has finished collecting. + * Whether this collector has stopped collecting messages. * @type {boolean} */ this.ended = false; /** - * Timeout for cleanup. - * @type {?Timeout} - * @private + * A collection of collected messages, mapped by message ID. + * @type {Collection} */ - this._timeout = null; + this.collected = new Collection(); - /** - * Call this to handle an event as a collectable element. - * Accepts any event data as parameters. - * @type {Function} - * @private - */ - this.listener = this._handle.bind(this); - if (options.time) this._timeout = this.client.setTimeout(() => this.stop('time'), options.time); + 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); } /** - * @param {...*} args The arguments emitted by the listener. - * @emits Collector#collect + * Verifies a message against the filter and options * @private + * @param {Message} message The message + * @returns {boolean} */ - _handle(...args) { - const collect = this.handle(...args); - if (!collect || !this.filter(...args)) return; - - this.collected.set(collect.key, collect.value); - - /** - * Emitted whenever an element is collected. - * @event Collector#collect - * @param {*} element The element that got collected. - * @param {Collector} collector The collector. - */ - this.emit('collect', collect.value, this); - - const post = this.postCheck(...args); - if (post) this.stop(post); + 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; } /** - * Return a promise that resolves with the next collected element; - * rejects with collected elements if the collector finishes without receving a next element. - * @type {Promise} + * 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() { @@ -9084,195 +9386,3116 @@ class Collector extends EventEmitter { } const cleanup = () => { - this.removeListener('collect', onCollect); + this.removeListener('message', onMessage); this.removeListener('end', onEnd); }; - const onCollect = item => { + const onMessage = (...args) => { cleanup(); - resolve(item); + resolve(...args); }; - const onEnd = () => { + const onEnd = (...args) => { cleanup(); - reject(this.collected); // eslint-disable-line prefer-promise-reject-errors + reject(...args); }; - this.on('collect', onCollect); - this.on('end', onEnd); + this.once('message', onMessage); + this.once('end', onEnd); }); } /** - * Stop this collector and emit the `end` event. - * @param {string} [reason='user'] The reason this collector is ending. - * @emits Collector#end + * Stops the collector and emits `end`. + * @param {string} [reason='user'] An optional reason for stopping the collector */ stop(reason = 'user') { if (this.ended) return; - - if (this._timeout) this.client.clearTimeout(this._timeout); this.ended = true; - this.cleanup(); - + this.channel.client.removeListener('message', this.listener); /** - * Emitted when the collector is finished collecting. - * @event Collector#end - * @param {Collection} collected The elements collected by the collector. - * @param {string} reason The reason the collector ended. + * 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); } - - /* eslint-disable no-empty-function, valid-jsdoc */ - /** - * Handles incoming events from the `listener` function. Returns null if the - * event should not be collected, or returns an object describing the data that should be stored. - * @see Collector#listener - * @param {...*} args Any args the event listener emits. - * @returns {?{key: string, value}} Data to insert into collection, if any. - * @abstract - */ - handle() {} - - /** - * This method runs after collection to see if the collector should finish. - * @param {...*} args Any args the event listener emits. - * @returns {?string} Reason to end the collector, if any. - * @abstract - */ - postCheck() {} - - /** - * Called when the collector is ending. - * @abstract - */ - cleanup() {} - /* eslint-enable no-empty-function, valid-jsdoc */ } -module.exports = Collector; +module.exports = MessageCollector; -/***/ }), -/* 32 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 35 */ +/***/ 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 + * @name MessageEmbed#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: message.client }); + + /** + * The message this embed is part of + * @type {Message} + */ + this.message = message; + + this.setup(data); + } + + setup(data) { + /** + * The type of this embed + * @type {string} + */ + this.type = data.type; + + /** + * The title of this embed, if there is one + * @type {?string} + */ + this.title = data.title; + + /** + * 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 color of the embed + * @type {number} + */ + this.color = data.color; + + /** + * 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); + } + + /** + * The hexadecimal version of the embed color, with a leading hash. + * @type {string} + * @readonly + */ + get hexColor() { + let col = this.color.toString(16); + while (col.length < 6) col = `0${col}`; + return `#${col}`; + } +} + +/** + * 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; + + /** + * The icon URL of this author + * @type {string} + */ + this.iconURL = data.icon_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; + + +/***/ }, +/* 36 */ +/***/ function(module, exports, __webpack_require__) { + +const Collection = __webpack_require__(3); +const Emoji = __webpack_require__(10); +const ReactionEmoji = __webpack_require__(18); + +/** + * 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=this.message.client.user] User to remove the reaction of + * @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; + + +/***/ }, +/* 37 */ +/***/ function(module, exports) { + +/** + * Represents an OAuth2 Application + */ +class OAuth2Application { + constructor(client, data) { + /** + * The client that instantiated the application + * @name OAuth2Application#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + 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; + + +/***/ }, +/* 38 */ +/***/ 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 + * @name PartialGuild#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + 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; + + +/***/ }, +/* 39 */ +/***/ 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 + * @name PartialGuildChannel#client + * @type {Client} + * @readonly + */ + Object.defineProperty(this, 'client', { value: client }); + + 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; + + +/***/ }, +/* 40 */ +/***/ 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 + * @name PermissionOverwrites#channel + * @type {GuildChannel} + * @readonly + */ + Object.defineProperty(this, 'channel', { value: 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.deny = data.deny; + this.allow = data.allow; + } + + /** + * Delete this Permission Overwrite. + * @returns {Promise} + */ + delete() { + return this.channel.client.rest.methods.deletePermissionOverwrites(this); + } +} + +module.exports = PermissionOverwrites; + + +/***/ }, +/* 41 */ +/***/ function(module, exports, __webpack_require__) { + +const GuildChannel = __webpack_require__(14); +const TextBasedChannel = __webpack_require__(12); +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|Base64Resolvable} 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 (typeof avatar === 'string' && 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 + send() { return; } + sendMessage() { return; } + sendEmbed() { return; } + sendFile() { return; } + sendCode() { return; } + fetchMessage() { return; } + fetchMessages() { return; } + fetchPinnedMessages() { return; } + search() { 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; + + +/***/ }, +/* 42 */ +/***/ function(module, exports, __webpack_require__) { + +const GuildChannel = __webpack_require__(14); +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; + + +/***/ }, +/* 43 */ +/***/ 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; +}; + + +/***/ }, +/* 44 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -/* WEBPACK VAR INJECTION */(function(global) { +// String encode/decode helpers -var buffer = __webpack_require__(5); -var Buffer = buffer.Buffer; -var SlowBuffer = buffer.SlowBuffer; -var MAX_LEN = buffer.kMaxLength || 2147483647; -exports.alloc = function alloc(size, fill, encoding) { - if (typeof Buffer.alloc === 'function') { - return Buffer.alloc(size, fill, encoding); - } - if (typeof encoding === 'number') { - throw new TypeError('encoding must not be number'); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - var enc = encoding; - var _fill = fill; - if (_fill === undefined) { - enc = undefined; - _fill = 0; - } - var buf = new Buffer(size); - if (typeof _fill === 'string') { - var fillBuf = new Buffer(_fill, enc); - var flen = fillBuf.length; - var i = -1; - while (++i < size) { - buf[i] = fillBuf[i % flen]; + + +var utils = __webpack_require__(5); + + +// Quick check if we can use fast array to bin string conversion +// +// - apply(Array) can fail on Android 2.2 +// - apply(Uint8Array) can fail on iOS 5.1 Safary +// +var STR_APPLY_OK = true; +var STR_APPLY_UIA_OK = true; + +try { String.fromCharCode.apply(null, [ 0 ]); } catch (__) { STR_APPLY_OK = false; } +try { String.fromCharCode.apply(null, new Uint8Array(1)); } catch (__) { STR_APPLY_UIA_OK = false; } + + +// Table with utf8 lengths (calculated by first byte of sequence) +// Note, that 5 & 6-byte values and some 4-byte values can not be represented in JS, +// because max possible codepoint is 0x10ffff +var _utf8len = new utils.Buf8(256); +for (var q = 0; q < 256; q++) { + _utf8len[q] = (q >= 252 ? 6 : q >= 248 ? 5 : q >= 240 ? 4 : q >= 224 ? 3 : q >= 192 ? 2 : 1); +} +_utf8len[254] = _utf8len[254] = 1; // Invalid sequence start + + +// convert string to array (typed, when possible) +exports.string2buf = function (str) { + var buf, c, c2, m_pos, i, str_len = str.length, buf_len = 0; + + // count binary size + for (m_pos = 0; m_pos < str_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } } - } else { - buf.fill(_fill); + buf_len += c < 0x80 ? 1 : c < 0x800 ? 2 : c < 0x10000 ? 3 : 4; + } + + // allocate buffer + buf = new utils.Buf8(buf_len); + + // convert + for (i = 0, m_pos = 0; i < buf_len; m_pos++) { + c = str.charCodeAt(m_pos); + if ((c & 0xfc00) === 0xd800 && (m_pos + 1 < str_len)) { + c2 = str.charCodeAt(m_pos + 1); + if ((c2 & 0xfc00) === 0xdc00) { + c = 0x10000 + ((c - 0xd800) << 10) + (c2 - 0xdc00); + m_pos++; + } + } + if (c < 0x80) { + /* one byte */ + buf[i++] = c; + } else if (c < 0x800) { + /* two bytes */ + buf[i++] = 0xC0 | (c >>> 6); + buf[i++] = 0x80 | (c & 0x3f); + } else if (c < 0x10000) { + /* three bytes */ + buf[i++] = 0xE0 | (c >>> 12); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } else { + /* four bytes */ + buf[i++] = 0xf0 | (c >>> 18); + buf[i++] = 0x80 | (c >>> 12 & 0x3f); + buf[i++] = 0x80 | (c >>> 6 & 0x3f); + buf[i++] = 0x80 | (c & 0x3f); + } + } + + return buf; +}; + +// Helper (used in 2 places) +function buf2binstring(buf, len) { + // use fallback for big arrays to avoid stack overflow + if (len < 65537) { + if ((buf.subarray && STR_APPLY_UIA_OK) || (!buf.subarray && STR_APPLY_OK)) { + return String.fromCharCode.apply(null, utils.shrinkBuf(buf, len)); + } + } + + var result = ''; + for (var i = 0; i < len; i++) { + result += String.fromCharCode(buf[i]); + } + return result; +} + + +// Convert byte array to binary string +exports.buf2binstring = function (buf) { + return buf2binstring(buf, buf.length); +}; + + +// Convert binary string (typed, when possible) +exports.binstring2buf = function (str) { + var buf = new utils.Buf8(str.length); + for (var i = 0, len = buf.length; i < len; i++) { + buf[i] = str.charCodeAt(i); } return buf; -} -exports.allocUnsafe = function allocUnsafe(size) { - if (typeof Buffer.allocUnsafe === 'function') { - return Buffer.allocUnsafe(size); - } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size > MAX_LEN) { - throw new RangeError('size is too large'); - } - return new Buffer(size); -} -exports.from = function from(value, encodingOrOffset, length) { - if (typeof Buffer.from === 'function' && (!global.Uint8Array || Uint8Array.from !== Buffer.from)) { - return Buffer.from(value, encodingOrOffset, length); - } - if (typeof value === 'number') { - throw new TypeError('"value" argument must not be a number'); - } - if (typeof value === 'string') { - return new Buffer(value, encodingOrOffset); - } - if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { - var offset = encodingOrOffset; - if (arguments.length === 1) { - return new Buffer(value); +}; + + +// convert array to string +exports.buf2string = function (buf, max) { + var i, out, c, c_len; + var len = max || buf.length; + + // Reserve max possible length (2 words per char) + // NB: by unknown reasons, Array is significantly faster for + // String.fromCharCode.apply than Uint16Array. + var utf16buf = new Array(len * 2); + + for (out = 0, i = 0; i < len;) { + c = buf[i++]; + // quick process ascii + if (c < 0x80) { utf16buf[out++] = c; continue; } + + c_len = _utf8len[c]; + // skip 5 & 6 byte codes + if (c_len > 4) { utf16buf[out++] = 0xfffd; i += c_len - 1; continue; } + + // apply mask on first byte + c &= c_len === 2 ? 0x1f : c_len === 3 ? 0x0f : 0x07; + // join the rest + while (c_len > 1 && i < len) { + c = (c << 6) | (buf[i++] & 0x3f); + c_len--; } - if (typeof offset === 'undefined') { - offset = 0; - } - var len = length; - if (typeof len === 'undefined') { - len = value.byteLength - offset; - } - if (offset >= value.byteLength) { - throw new RangeError('\'offset\' is out of bounds'); - } - if (len > value.byteLength - offset) { - throw new RangeError('\'length\' is out of bounds'); - } - return new Buffer(value.slice(offset, offset + len)); - } - if (Buffer.isBuffer(value)) { - var out = new Buffer(value.length); - value.copy(out, 0, 0, value.length); - return out; - } - if (value) { - if (Array.isArray(value) || (typeof ArrayBuffer !== 'undefined' && value.buffer instanceof ArrayBuffer) || 'length' in value) { - return new Buffer(value); - } - if (value.type === 'Buffer' && Array.isArray(value.data)) { - return new Buffer(value.data); + + // terminated by end of string? + if (c_len > 1) { utf16buf[out++] = 0xfffd; continue; } + + if (c < 0x10000) { + utf16buf[out++] = c; + } else { + c -= 0x10000; + utf16buf[out++] = 0xd800 | ((c >> 10) & 0x3ff); + utf16buf[out++] = 0xdc00 | (c & 0x3ff); } } - throw new TypeError('First argument must be a string, Buffer, ' + 'ArrayBuffer, Array, or array-like object.'); -} -exports.allocUnsafeSlow = function allocUnsafeSlow(size) { - if (typeof Buffer.allocUnsafeSlow === 'function') { - return Buffer.allocUnsafeSlow(size); + return buf2binstring(utf16buf, out); +}; + + +// Calculate max possible position in utf8 buffer, +// that will not break sequence. If that's not possible +// - (very small limits) return max size as is. +// +// buf[] - utf8 bytes array +// max - length limit (mandatory); +exports.utf8border = function (buf, max) { + var pos; + + max = max || buf.length; + if (max > buf.length) { max = buf.length; } + + // go back from last position, until start of sequence found + pos = max - 1; + while (pos >= 0 && (buf[pos] & 0xC0) === 0x80) { pos--; } + + // Fuckup - very small and broken sequence, + // return max, because we should return something anyway. + if (pos < 0) { return max; } + + // If we came to start of buffer - that means vuffer is too small, + // return max too. + if (pos === 0) { return max; } + + return (pos + _utf8len[buf[pos]] > max) ? pos : max; +}; + + +/***/ }, +/* 45 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// Note: adler32 takes 12% for level 0 and 2% for level 6. +// It doesn't worth to make additional optimizationa as in original. +// Small size is preferable. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function adler32(adler, buf, len, pos) { + var s1 = (adler & 0xffff) |0, + s2 = ((adler >>> 16) & 0xffff) |0, + n = 0; + + while (len !== 0) { + // Set limit ~ twice less than 5552, to keep + // s2 in 31-bits, because we force signed ints. + // in other case %= will fail. + n = len > 2000 ? 2000 : len; + len -= n; + + do { + s1 = (s1 + buf[pos++]) |0; + s2 = (s2 + s1) |0; + } while (--n); + + s1 %= 65521; + s2 %= 65521; } - if (typeof size !== 'number') { - throw new TypeError('size must be a number'); - } - if (size >= MAX_LEN) { - throw new RangeError('size is too large'); - } - return new SlowBuffer(size); + + return (s1 | (s2 << 16)) |0; } -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8))) -/***/ }), -/* 33 */ -/***/ (function(module, exports, __webpack_require__) { +module.exports = adler32; + + +/***/ }, +/* 46 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +module.exports = { + + /* Allowed flush values; see deflate() and inflate() below for details */ + Z_NO_FLUSH: 0, + Z_PARTIAL_FLUSH: 1, + Z_SYNC_FLUSH: 2, + Z_FULL_FLUSH: 3, + Z_FINISH: 4, + Z_BLOCK: 5, + Z_TREES: 6, + + /* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + Z_OK: 0, + Z_STREAM_END: 1, + Z_NEED_DICT: 2, + Z_ERRNO: -1, + Z_STREAM_ERROR: -2, + Z_DATA_ERROR: -3, + //Z_MEM_ERROR: -4, + Z_BUF_ERROR: -5, + //Z_VERSION_ERROR: -6, + + /* compression levels */ + Z_NO_COMPRESSION: 0, + Z_BEST_SPEED: 1, + Z_BEST_COMPRESSION: 9, + Z_DEFAULT_COMPRESSION: -1, + + + Z_FILTERED: 1, + Z_HUFFMAN_ONLY: 2, + Z_RLE: 3, + Z_FIXED: 4, + Z_DEFAULT_STRATEGY: 0, + + /* Possible values of the data_type field (though see inflate()) */ + Z_BINARY: 0, + Z_TEXT: 1, + //Z_ASCII: 1, // = Z_TEXT (deprecated) + Z_UNKNOWN: 2, + + /* The deflate compression method */ + Z_DEFLATED: 8 + //Z_NULL: null // Use -1 or null inline, depending on var type +}; + + +/***/ }, +/* 47 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// Note: we can't get significant speed boost here. +// So write code to minimize size - no pregenerated tables +// and array tools dependencies. + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// Use ordinary array, since untyped makes no boost here +function makeTable() { + var c, table = []; + + for (var n = 0; n < 256; n++) { + c = n; + for (var k = 0; k < 8; k++) { + c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); + } + table[n] = c; + } + + return table; +} + +// Create table on load. Just 255 signed longs. Not a problem. +var crcTable = makeTable(); + + +function crc32(crc, buf, len, pos) { + var t = crcTable, + end = pos + len; + + crc ^= -1; + + for (var i = pos; i < end; i++) { + crc = (crc >>> 8) ^ t[(crc ^ buf[i]) & 0xFF]; + } + + return (crc ^ (-1)); // >>> 0; +} + + +module.exports = crc32; + + +/***/ }, +/* 48 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function ZStream() { + /* next input byte */ + this.input = null; // JS specific, because we have no pointers + this.next_in = 0; + /* number of bytes available at input */ + this.avail_in = 0; + /* total number of input bytes read so far */ + this.total_in = 0; + /* next output byte should be put there */ + this.output = null; // JS specific, because we have no pointers + this.next_out = 0; + /* remaining free space at output */ + this.avail_out = 0; + /* total number of bytes output so far */ + this.total_out = 0; + /* last error message, NULL if no error */ + this.msg = ''/*Z_NULL*/; + /* not visible by applications */ + this.state = null; + /* best guess about the data type: binary or text */ + this.data_type = 2/*Z_UNKNOWN*/; + /* adler32 value of the uncompressed data */ + this.adler = 0; +} + +module.exports = ZStream; + + +/***/ }, +/* 49 */ +/***/ function(module, exports) { + + + +/***/ }, +/* 50 */ +/***/ function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(Buffer) {const path = __webpack_require__(23); +const fs = __webpack_require__(49); +const request = __webpack_require__(25); + +const Constants = __webpack_require__(0); +const convertArrayBuffer = __webpack_require__(53); +const User = __webpack_require__(6); +const Message = __webpack_require__(11); +const Guild = __webpack_require__(13); +const Channel = __webpack_require__(8); +const GuildMember = __webpack_require__(15); +const Emoji = __webpack_require__(10); +const ReactionEmoji = __webpack_require__(18); + +/** + * 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 + * * A Guild ID + * @typedef {Guild|string} 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; + } + + /** + * Resolves a ChannelResolvable to a Channel object + * @param {ChannelResolvable} channel The channel resolvable to resolve + * @returns {?string} + */ + resolveChannelID(channel) { + if (channel instanceof Channel) return channel.id; + if (typeof channel === 'string') return channel; + if (channel instanceof Message) return channel.channel.id; + if (channel instanceof Guild) return channel.defaultChannel.id; + return null; + } + + /** + * Data that can be resolved to give an invite code. This can be: + * * 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", + * "MANAGE_WEBHOOKS", + * "MANAGE_EMOJIS" + * ] + * ``` + * @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; + } + + /** + * Turn an array of permissions into a valid Discord permission bitfield + * @param {PermissionResolvable[]} permissions Permissions to resolve together + * @returns {number} + */ + resolvePermissions(permissions) { + let bitfield = 0; + for (const permission of permissions) bitfield |= this.resolvePermission(permission); + return bitfield; + } + + /** + * 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('The response body isn\'t 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__(20).Buffer)) + +/***/ }, +/* 51 */ +/***/ function(module, exports, __webpack_require__) { + +const UserAgentManager = __webpack_require__(116); +const RESTMethods = __webpack_require__(113); +const SequentialRequestHandler = __webpack_require__(115); +const BurstRequestHandler = __webpack_require__(114); +const APIRequest = __webpack_require__(112); +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; + + +/***/ }, +/* 52 */ +/***/ 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; + + +/***/ }, +/* 53 */ +/***/ 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__(20).Buffer)) + +/***/ }, +/* 54 */ +/***/ 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; +}; + + +/***/ }, +/* 55 */ +/***/ function(module, exports, __webpack_require__) { + +/* WEBPACK VAR INJECTION */(function(process) {const EventEmitter = __webpack_require__(21).EventEmitter; +const mergeDefault = __webpack_require__(54); +const Constants = __webpack_require__(0); +const RESTManager = __webpack_require__(51); +const ClientDataManager = __webpack_require__(83); +const ClientManager = __webpack_require__(84); +const ClientDataResolver = __webpack_require__(50); +const ClientVoiceManager = __webpack_require__(159); +const WebSocketManager = __webpack_require__(117); +const ActionsManager = __webpack_require__(85); +const Collection = __webpack_require__(3); +const Presence = __webpack_require__(7).Presence; +const ShardClientUtil = __webpack_require__(158); + +/** + * 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 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; + + /** + * The previous heartbeat pings of the websocket (most recent first, limited to three elements) + * @type {number[]} + */ + this.pings = []; + + this._pingTimestamp = 0; + 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; + } + + /** + * The average heartbeat ping of the websocket + * @type {number} + * @readonly + */ + get ping() { + return this.pings.reduce((prev, p) => prev + p, 0) / this.pings.length; + } + + /** + * 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} token The token used for the account. + * @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(token) { + return this.rest.methods.login(token); + } + + /** + * 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(); + 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(); + } + + /** + * Generate an invite link for your bot + * @param {PermissionResolvable[]|number} [permissions] An array of permissions to request + * @returns {Promise} The invite link + * @example + * client.generateInvite(['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE']) + * .then(link => { + * console.log(`Generated bot invite link: ${link}`); + * }); + */ + generateInvite(permissions) { + if (permissions) { + if (permissions instanceof Array) permissions = this.resolver.resolvePermissions(permissions); + } else { + permissions = 0; + } + return this.fetchApplication().then(application => + `https://discordapp.com/oauth2/authorize?client_id=${application.id}&permissions=${permissions}&scope=bot` + ); + } + + /** + * 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 Arguments for the function + * @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 Arguments for the function + * @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); + } + + _pong(startTime) { + this.pings.unshift(Date.now() - startTime); + if (this.pings.length > 3) this.pings.length = 3; + this.ws.lastHeartbeatAck = true; + } + + _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} info The warning + */ + +/** + * Emitted for general debugging information + * @event Client#debug + * @param {string} info The debug information + */ + +/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(24))) + +/***/ }, +/* 56 */ +/***/ function(module, exports, __webpack_require__) { + +const Webhook = __webpack_require__(19); +const RESTManager = __webpack_require__(51); +const ClientDataResolver = __webpack_require__(50); +const mergeDefault = __webpack_require__(54); +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; + + +/***/ }, +/* 57 */ +/***/ function(module, exports, __webpack_require__) { + +module.exports = { + Client: __webpack_require__(55), + WebhookClient: __webpack_require__(56), + Shard: __webpack_require__(60), + ShardClientUtil: __webpack_require__(61), + ShardingManager: __webpack_require__(62), + + Collection: __webpack_require__(3), + splitMessage: __webpack_require__(43), + escapeMarkdown: __webpack_require__(16), + fetchRecommendedShards: __webpack_require__(59), + + Channel: __webpack_require__(8), + ClientOAuth2Application: __webpack_require__(28), + ClientUser: __webpack_require__(29), + DMChannel: __webpack_require__(30), + Emoji: __webpack_require__(10), + EvaluatedPermissions: __webpack_require__(17), + Game: __webpack_require__(7).Game, + GroupDMChannel: __webpack_require__(31), + Guild: __webpack_require__(13), + GuildChannel: __webpack_require__(14), + GuildMember: __webpack_require__(15), + Invite: __webpack_require__(32), + Message: __webpack_require__(11), + MessageAttachment: __webpack_require__(33), + MessageCollector: __webpack_require__(34), + MessageEmbed: __webpack_require__(35), + MessageReaction: __webpack_require__(36), + OAuth2Application: __webpack_require__(37), + PartialGuild: __webpack_require__(38), + PartialGuildChannel: __webpack_require__(39), + PermissionOverwrites: __webpack_require__(40), + Presence: __webpack_require__(7).Presence, + ReactionEmoji: __webpack_require__(18), + RichEmbed: __webpack_require__(58), + Role: __webpack_require__(9), + TextChannel: __webpack_require__(41), + User: __webpack_require__(6), + VoiceChannel: __webpack_require__(42), + Webhook: __webpack_require__(19), + + version: __webpack_require__(27).version, + Constants: __webpack_require__(0), +}; + +if (typeof window !== 'undefined') window.Discord = module.exports; // eslint-disable-line no-undef + + +/***/ }, +/* 58 */ +/***/ function(module, exports) { + +/** + * A rich embed to be sent with a message + * @param {Object} [data] Data to set in the rich embed + */ +class RichEmbed { + constructor(data = {}) { + /** + * Title for this Embed + * @type {string} + */ + this.title = data.title; + + /** + * Description for this Embed + * @type {string} + */ + this.description = data.description; + + /** + * URL for this Embed + * @type {string} + */ + this.url = data.url; + + /** + * Color for this Embed + * @type {number} + */ + this.color = data.color; + + /** + * Author for this Embed + * @type {Object} + */ + this.author = data.author; + + /** + * Timestamp for this Embed + * @type {Date} + */ + this.timestamp = data.timestamp; + + /** + * Fields for this Embed + * @type {Object[]} + */ + this.fields = data.fields || []; + + /** + * Thumbnail for this Embed + * @type {Object} + */ + this.thumbnail = data.thumbnail; + + /** + * Image for this Embed + * @type {Object} + */ + this.image = data.image; + + /** + * Footer for this Embed + * @type {Object} + */ + this.footer = data.footer; + } + + /** + * Sets the title of this embed + * @param {StringResolvable} title The title + * @returns {RichEmbed} This embed + */ + setTitle(title) { + title = resolveString(title); + if (title.length > 256) throw new RangeError('RichEmbed titles may not exceed 256 characters.'); + this.title = title; + return this; + } + + /** + * Sets the description of this embed + * @param {StringResolvable} description The description + * @returns {RichEmbed} This embed + */ + setDescription(description) { + description = resolveString(description); + if (description.length > 2048) throw new RangeError('RichEmbed descriptions may not exceed 2048 characters.'); + this.description = description; + return this; + } + + /** + * Sets the URL of this embed + * @param {string} url The URL + * @returns {RichEmbed} This embed + */ + setURL(url) { + this.url = url; + return this; + } + + /** + * Sets the color of this embed + * @param {string|number|number[]} color The color to set + * @returns {RichEmbed} This embed + */ + setColor(color) { + let radix = 10; + if (color instanceof Array) { + color = (color[0] << 16) + (color[1] << 8) + color[2]; + } else if (typeof color === 'string' && color.startsWith('#')) { + radix = 16; + color = color.replace('#', ''); + } + color = parseInt(color, radix); + if (color < 0 || color > 0xFFFFFF) { + throw new RangeError('RichEmbed color must be within the range 0 - 16777215 (0xFFFFFF).'); + } else if (color && isNaN(color)) { + throw new TypeError('Unable to convert RichEmbed color to a number.'); + } + this.color = color; + return this; + } + + /** + * Sets the author of this embed + * @param {StringResolvable} name The name of the author + * @param {string} [icon] The icon URL of the author + * @param {string} [url] The URL of the author + * @returns {RichEmbed} This embed + */ + setAuthor(name, icon, url) { + this.author = { name: resolveString(name), icon_url: icon, url }; + return this; + } + + /** + * Sets the timestamp of this embed + * @param {Date} [timestamp=current date] The timestamp + * @returns {RichEmbed} This embed + */ + setTimestamp(timestamp = new Date()) { + this.timestamp = timestamp; + return this; + } + + /** + * Adds a field to the embed (max 25) + * @param {StringResolvable} name The name of the field + * @param {StringResolvable} value The value of the field + * @param {boolean} [inline=false] Set the field to display inline + * @returns {RichEmbed} This embed + */ + addField(name, value, inline = false) { + if (this.fields.length >= 25) throw new RangeError('RichEmbeds may not exceed 25 fields.'); + name = resolveString(name); + if (name.length > 256) throw new RangeError('RichEmbed field names may not exceed 256 characters.'); + value = resolveString(value); + if (value.length > 1024) throw new RangeError('RichEmbed field values may not exceed 1024 characters.'); + this.fields.push({ name: String(name), value: value, inline }); + return this; + } + + /** + * Set the thumbnail of this embed + * @param {string} url The URL of the thumbnail + * @returns {RichEmbed} This embed + */ + setThumbnail(url) { + this.thumbnail = { url }; + return this; + } + + /** + * Set the image of this embed + * @param {string} url The URL of the thumbnail + * @returns {RichEmbed} This embed + */ + setImage(url) { + this.image = { url }; + return this; + } + + /** + * Sets the footer of this embed + * @param {StringResolvable} text The text of the footer + * @param {string} [icon] The icon URL of the footer + * @returns {RichEmbed} This embed + */ + setFooter(text, icon) { + text = resolveString(text); + if (text.length > 2048) throw new RangeError('RichEmbed footer text may not exceed 2048 characters.'); + this.footer = { text, icon_url: icon }; + return this; + } +} + +module.exports = RichEmbed; + +function resolveString(data) { + if (typeof data === 'string') return data; + if (data instanceof Array) return data.join('\n'); + return String(data); +} + + +/***/ }, +/* 59 */ +/***/ function(module, exports, __webpack_require__) { + +const superagent = __webpack_require__(25); +const botGateway = __webpack_require__(0).Endpoints.botGateway; + +/** + * Gets the recommended shard count from Discord + * @param {string} token Discord auth token + * @param {number} [guildsPerShard=1000] Number of guilds per shard + * @returns {Promise} the recommended number of shards + */ +module.exports = function fetchRecommendedShards(token, guildsPerShard = 1000) { + 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 * (1000 / guildsPerShard)); + }); + }); +}; + + +/***/ }, +/* 60 */ +/***/ function(module, exports) { + +/* (ignored) */ + +/***/ }, +/* 61 */ +/***/ function(module, exports) { + +/* (ignored) */ + +/***/ }, +/* 62 */ +/***/ function(module, exports) { + +/* (ignored) */ + +/***/ }, +/* 63 */ +/***/ function(module, exports, __webpack_require__) { + +"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('') +} + + +/***/ }, +/* 64 */ +/***/ 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; +}; + + +/***/ }, +/* 65 */ +/***/ 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 +} + + +/***/ }, +/* 66 */ +/***/ function(module, exports) { + +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + + +/***/ }, +/* 67 */ +/***/ function(module, exports, __webpack_require__) { var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/* Copyright 2013 Daniel Wirtz @@ -9299,10 +12522,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ (function(global, factory) { /* AMD */ if (true) - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), - __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? - (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) module["exports"] = factory(); /* Global */ else @@ -10488,11902 +13708,7195 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ }); -/***/ }), -/* 34 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 68 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -/* WEBPACK VAR INJECTION */(function(process) { +// Top level file is just a mixin of submodules & constants -if (!process.version || - process.version.indexOf('v0.') === 0 || - process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { - module.exports = nextTick; -} else { - module.exports = process.nextTick; -} -function nextTick(fn, arg1, arg2, arg3) { - if (typeof fn !== 'function') { - throw new TypeError('"callback" argument must be a function'); - } - var len = arguments.length; - var args, i; - switch (len) { - case 0: - case 1: - return process.nextTick(fn); - case 2: - return process.nextTick(function afterTickOne() { - fn.call(null, arg1); - }); - case 3: - return process.nextTick(function afterTickTwo() { - fn.call(null, arg1, arg2); - }); - case 4: - return process.nextTick(function afterTickThree() { - fn.call(null, arg1, arg2, arg3); - }); - default: - args = new Array(len - 1); - i = 0; - while (i < args.length) { - args[i++] = arguments[i]; - } - return process.nextTick(function afterTick() { - fn.apply(null, args); - }); - } -} +var assign = __webpack_require__(5).assign; -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6))) +var deflate = __webpack_require__(69); +var inflate = __webpack_require__(70); +var constants = __webpack_require__(46); -/***/ }), -/* 35 */ -/***/ (function(module, exports, __webpack_require__) { +var pako = {}; + +assign(pako, deflate, inflate, constants); + +module.exports = pako; + + +/***/ }, +/* 69 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -exports.decode = exports.parse = __webpack_require__(79); -exports.encode = exports.stringify = __webpack_require__(80); + +var zlib_deflate = __webpack_require__(71); +var utils = __webpack_require__(5); +var strings = __webpack_require__(44); +var msg = __webpack_require__(22); +var ZStream = __webpack_require__(48); + +var toString = Object.prototype.toString; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + +var Z_NO_FLUSH = 0; +var Z_FINISH = 4; + +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_SYNC_FLUSH = 2; + +var Z_DEFAULT_COMPRESSION = -1; + +var Z_DEFAULT_STRATEGY = 0; + +var Z_DEFLATED = 8; + +/* ===========================================================================*/ -/***/ }), -/* 36 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * class Deflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[deflate]], + * [[deflateRaw]] and [[gzip]]. + **/ -"use strict"; -/* WEBPACK VAR INJECTION */(function(process, setImmediate) {// A bit simpler than readable streams. -// Implement an async ._write(chunk, encoding, cb), and it'll handle all -// the drain event emission and buffering. +/* internal + * Deflate.chunks -> Array + * + * Chunks of output data, if [[Deflate#onData]] not overriden. + **/ + +/** + * Deflate.result -> Uint8Array|Array + * + * Compressed result, generated by default [[Deflate#onData]] + * and [[Deflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Deflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Deflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ + +/** + * Deflate.err -> Number + * + * Error code after deflate finished. 0 (Z_OK) on success. + * You will not need it in real life, because deflate errors + * are possible only on wrong options or bad `onData` / `onEnd` + * custom handlers. + **/ + +/** + * Deflate.msg -> String + * + * Error message, if [[Deflate.err]] != 0 + **/ +/** + * new Deflate(options) + * - options (Object): zlib deflate options. + * + * Creates new deflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `level` + * - `windowBits` + * - `memLevel` + * - `strategy` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw deflate + * - `gzip` (Boolean) - create gzip wrapper + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * - `header` (Object) - custom header for gzip + * - `text` (Boolean) - true if compressed data believed to be text + * - `time` (Number) - modification time, unix timestamp + * - `os` (Number) - operation system code + * - `extra` (Array) - array of bytes with extra data (max 65536) + * - `name` (String) - file name (binary string) + * - `comment` (String) - comment (binary string) + * - `hcrc` (Boolean) - true if header crc should be added + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var deflate = new pako.Deflate({ level: 3}); + * + * deflate.push(chunk1, false); + * deflate.push(chunk2, true); // true -> last chunk + * + * if (deflate.err) { throw new Error(deflate.err); } + * + * console.log(deflate.result); + * ``` + **/ +function Deflate(options) { + if (!(this instanceof Deflate)) return new Deflate(options); -module.exports = Writable; + this.options = utils.assign({ + level: Z_DEFAULT_COMPRESSION, + method: Z_DEFLATED, + chunkSize: 16384, + windowBits: 15, + memLevel: 8, + strategy: Z_DEFAULT_STRATEGY, + to: '' + }, options || {}); -/**/ -var processNextTick = __webpack_require__(34); -/**/ + var opt = this.options; -/**/ -var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : processNextTick; -/**/ - -/**/ -var Duplex; -/**/ - -Writable.WritableState = WritableState; - -/**/ -var util = __webpack_require__(20); -util.inherits = __webpack_require__(10); -/**/ - -/**/ -var internalUtil = { - deprecate: __webpack_require__(99) -}; -/**/ - -/**/ -var Stream = __webpack_require__(59); -/**/ - -var Buffer = __webpack_require__(5).Buffer; -/**/ -var bufferShim = __webpack_require__(32); -/**/ - -util.inherits(Writable, Stream); - -function nop() {} - -function WriteReq(chunk, encoding, cb) { - this.chunk = chunk; - this.encoding = encoding; - this.callback = cb; - this.next = null; -} - -function WritableState(options, stream) { - Duplex = Duplex || __webpack_require__(13); - - options = options || {}; - - // object stream flag to indicate whether or not this stream - // contains buffers or objects. - this.objectMode = !!options.objectMode; - - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.writableObjectMode; - - // the point at which write() starts returning false - // Note: 0 is a valid value, means that we always return false if - // the entire buffer is not flushed immediately on write() - var hwm = options.highWaterMark; - var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - // drain event flag. - this.needDrain = false; - // at the start of calling end() - this.ending = false; - // when end() has been called, and returned - this.ended = false; - // when 'finish' is emitted - this.finished = false; - - // should we decode strings into buffers before passing to _write? - // this is here so that some node-core streams can optimize string - // handling at a lower level. - var noDecode = options.decodeStrings === false; - this.decodeStrings = !noDecode; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // not an actual buffer we keep track of, but a measurement - // of how much we're waiting to get pushed to some underlying - // socket or file. - this.length = 0; - - // a flag to see when we're in the middle of a write. - this.writing = false; - - // when true all writes will be buffered until .uncork() call - this.corked = 0; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // a flag to know if we're processing previously buffered items, which - // may call the _write() callback in the same tick, so that we don't - // end up in an overlapped onwrite situation. - this.bufferProcessing = false; - - // the callback that's passed to _write(chunk,cb) - this.onwrite = function (er) { - onwrite(stream, er); - }; - - // the callback that the user supplies to write(chunk,encoding,cb) - this.writecb = null; - - // the amount that is being written when _write is called. - this.writelen = 0; - - this.bufferedRequest = null; - this.lastBufferedRequest = null; - - // number of pending user-supplied write callbacks - // this must be 0 before 'finish' can be emitted - this.pendingcb = 0; - - // emit prefinish if the only thing we're waiting for is _write cbs - // This is relevant for synchronous Transform streams - this.prefinished = false; - - // True if the error was already emitted and should not be thrown again - this.errorEmitted = false; - - // count buffered requests - this.bufferedRequestCount = 0; - - // allocate the first CorkedRequest, there is always - // one allocated and free to use, and we maintain at most two - this.corkedRequestsFree = new CorkedRequest(this); -} - -WritableState.prototype.getBuffer = function getBuffer() { - var current = this.bufferedRequest; - var out = []; - while (current) { - out.push(current); - current = current.next; - } - return out; -}; - -(function () { - try { - Object.defineProperty(WritableState.prototype, 'buffer', { - get: internalUtil.deprecate(function () { - return this.getBuffer(); - }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.') - }); - } catch (_) {} -})(); - -// Test _writableState for inheritance to account for Duplex streams, -// whose prototype chain only points to Readable. -var realHasInstance; -if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { - realHasInstance = Function.prototype[Symbol.hasInstance]; - Object.defineProperty(Writable, Symbol.hasInstance, { - value: function (object) { - if (realHasInstance.call(this, object)) return true; - - return object && object._writableState instanceof WritableState; - } - }); -} else { - realHasInstance = function (object) { - return object instanceof this; - }; -} - -function Writable(options) { - Duplex = Duplex || __webpack_require__(13); - - // Writable ctor is applied to Duplexes, too. - // `realHasInstance` is necessary because using plain `instanceof` - // would return false, as no `_writableState` property is attached. - - // Trying to use the custom `instanceof` for Writable here will also break the - // Node.js LazyTransform implementation, which has a non-trivial getter for - // `_writableState` that would lead to infinite recursion. - if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { - return new Writable(options); + if (opt.raw && (opt.windowBits > 0)) { + opt.windowBits = -opt.windowBits; } - this._writableState = new WritableState(options, this); - - // legacy. - this.writable = true; - - if (options) { - if (typeof options.write === 'function') this._write = options.write; - - if (typeof options.writev === 'function') this._writev = options.writev; + else if (opt.gzip && (opt.windowBits > 0) && (opt.windowBits < 16)) { + opt.windowBits += 16; } - Stream.call(this); -} + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data -// Otherwise people can pipe Writable streams, which is just wrong. -Writable.prototype.pipe = function () { - this.emit('error', new Error('Cannot pipe, not readable')); -}; + this.strm = new ZStream(); + this.strm.avail_out = 0; -function writeAfterEnd(stream, cb) { - var er = new Error('write after end'); - // TODO: defer error events consistently everywhere, not just the cb - stream.emit('error', er); - processNextTick(cb, er); -} + var status = zlib_deflate.deflateInit2( + this.strm, + opt.level, + opt.method, + opt.windowBits, + opt.memLevel, + opt.strategy + ); -// Checks that a user-supplied chunk is valid, especially for the particular -// mode the stream is in. Currently this means that `null` is never accepted -// and undefined/non-string values are only allowed in object mode. -function validChunk(stream, state, chunk, cb) { - var valid = true; - var er = false; - - if (chunk === null) { - er = new TypeError('May not write null values to stream'); - } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - if (er) { - stream.emit('error', er); - processNextTick(cb, er); - valid = false; - } - return valid; -} - -Writable.prototype.write = function (chunk, encoding, cb) { - var state = this._writableState; - var ret = false; - var isBuf = Buffer.isBuffer(chunk); - - if (typeof encoding === 'function') { - cb = encoding; - encoding = null; + if (status !== Z_OK) { + throw new Error(msg[status]); } - if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; - - if (typeof cb !== 'function') cb = nop; - - if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { - state.pendingcb++; - ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + if (opt.header) { + zlib_deflate.deflateSetHeader(this.strm, opt.header); } - return ret; -}; - -Writable.prototype.cork = function () { - var state = this._writableState; - - state.corked++; -}; - -Writable.prototype.uncork = function () { - var state = this._writableState; - - if (state.corked) { - state.corked--; - - if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); - } -}; - -Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { - // node::ParseEncoding() requires lower case. - if (typeof encoding === 'string') encoding = encoding.toLowerCase(); - if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); - this._writableState.defaultEncoding = encoding; - return this; -}; - -function decodeChunk(state, chunk, encoding) { - if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { - chunk = bufferShim.from(chunk, encoding); - } - return chunk; -} - -// if we're already writing something, then just put this -// in the queue, and wait our turn. Otherwise, call _write -// If we return false, then we need a drain event, so set that flag. -function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { - if (!isBuf) { - chunk = decodeChunk(state, chunk, encoding); - if (Buffer.isBuffer(chunk)) encoding = 'buffer'; - } - var len = state.objectMode ? 1 : chunk.length; - - state.length += len; - - var ret = state.length < state.highWaterMark; - // we must ensure that previous needDrain will not be reset to false. - if (!ret) state.needDrain = true; - - if (state.writing || state.corked) { - var last = state.lastBufferedRequest; - state.lastBufferedRequest = new WriteReq(chunk, encoding, cb); - if (last) { - last.next = state.lastBufferedRequest; + if (opt.dictionary) { + var dict; + // Convert data if needed + if (typeof opt.dictionary === 'string') { + // If we need to compress text, change encoding to utf8. + dict = strings.string2buf(opt.dictionary); + } else if (toString.call(opt.dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(opt.dictionary); } else { - state.bufferedRequest = state.lastBufferedRequest; + dict = opt.dictionary; } - state.bufferedRequestCount += 1; + + status = zlib_deflate.deflateSetDictionary(this.strm, dict); + + if (status !== Z_OK) { + throw new Error(msg[status]); + } + + this._dict_set = true; + } +} + +/** + * Deflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data. Strings will be + * converted to utf8 byte sequence. + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. + * + * Sends input data to deflate pipe, generating [[Deflate#onData]] calls with + * new compressed chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Deflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the compression context. + * + * On fail call [[Deflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * array format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Deflate.prototype.push = function (data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var status, _mode; + + if (this.ended) { return false; } + + _mode = (mode === ~~mode) ? mode : ((mode === true) ? Z_FINISH : Z_NO_FLUSH); + + // Convert data if needed + if (typeof data === 'string') { + // If we need to compress text, change encoding to utf8. + strm.input = strings.string2buf(data); + } else if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); } else { - doWrite(stream, state, false, len, chunk, encoding, cb); + strm.input = data; } - return ret; -} + strm.next_in = 0; + strm.avail_in = strm.input.length; -function doWrite(stream, state, writev, len, chunk, encoding, cb) { - state.writelen = len; - state.writecb = cb; - state.writing = true; - state.sync = true; - if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); - state.sync = false; -} - -function onwriteError(stream, state, sync, er, cb) { - --state.pendingcb; - if (sync) processNextTick(cb, er);else cb(er); - - stream._writableState.errorEmitted = true; - stream.emit('error', er); -} - -function onwriteStateUpdate(state) { - state.writing = false; - state.writecb = null; - state.length -= state.writelen; - state.writelen = 0; -} - -function onwrite(stream, er) { - var state = stream._writableState; - var sync = state.sync; - var cb = state.writecb; - - onwriteStateUpdate(state); - - if (er) onwriteError(stream, state, sync, er, cb);else { - // Check if we're actually ready to finish, but don't emit yet - var finished = needFinish(state); - - if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { - clearBuffer(stream, state); + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; } + status = zlib_deflate.deflate(strm, _mode); /* no bad return value */ - if (sync) { - /**/ - asyncWrite(afterWrite, stream, state, finished, cb); - /**/ - } else { - afterWrite(stream, state, finished, cb); + if (status !== Z_STREAM_END && status !== Z_OK) { + this.onEnd(status); + this.ended = true; + return false; } - } -} - -function afterWrite(stream, state, finished, cb) { - if (!finished) onwriteDrain(stream, state); - state.pendingcb--; - cb(); - finishMaybe(stream, state); -} - -// Must force callback to be called on nextTick, so that we don't -// emit 'drain' before the write() consumer gets the 'false' return -// value, and has a chance to attach a 'drain' listener. -function onwriteDrain(stream, state) { - if (state.length === 0 && state.needDrain) { - state.needDrain = false; - stream.emit('drain'); - } -} - -// if there's something in the buffer waiting, then process it -function clearBuffer(stream, state) { - state.bufferProcessing = true; - var entry = state.bufferedRequest; - - if (stream._writev && entry && entry.next) { - // Fast case, write everything using _writev() - var l = state.bufferedRequestCount; - var buffer = new Array(l); - var holder = state.corkedRequestsFree; - holder.entry = entry; - - var count = 0; - while (entry) { - buffer[count] = entry; - entry = entry.next; - count += 1; - } - - doWrite(stream, state, true, state.length, buffer, '', holder.finish); - - // doWrite is almost always async, defer these to save a bit of time - // as the hot path ends with doWrite - state.pendingcb++; - state.lastBufferedRequest = null; - if (holder.next) { - state.corkedRequestsFree = holder.next; - holder.next = null; - } else { - state.corkedRequestsFree = new CorkedRequest(state); - } - } else { - // Slow case, write chunks one-by-one - while (entry) { - var chunk = entry.chunk; - var encoding = entry.encoding; - var cb = entry.callback; - var len = state.objectMode ? 1 : chunk.length; - - doWrite(stream, state, false, len, chunk, encoding, cb); - entry = entry.next; - // if we didn't call the onwrite immediately, then - // it means that we need to wait until it does. - // also, that means that the chunk and cb are currently - // being processed, so move the buffer counter past them. - if (state.writing) { - break; - } - } - - if (entry === null) state.lastBufferedRequest = null; - } - - state.bufferedRequestCount = 0; - state.bufferedRequest = entry; - state.bufferProcessing = false; -} - -Writable.prototype._write = function (chunk, encoding, cb) { - cb(new Error('_write() is not implemented')); -}; - -Writable.prototype._writev = null; - -Writable.prototype.end = function (chunk, encoding, cb) { - var state = this._writableState; - - if (typeof chunk === 'function') { - cb = chunk; - chunk = null; - encoding = null; - } else if (typeof encoding === 'function') { - cb = encoding; - encoding = null; - } - - if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); - - // .end() fully uncorks - if (state.corked) { - state.corked = 1; - this.uncork(); - } - - // ignore unnecessary end() calls. - if (!state.ending && !state.finished) endWritable(this, state, cb); -}; - -function needFinish(state) { - return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; -} - -function prefinish(stream, state) { - if (!state.prefinished) { - state.prefinished = true; - stream.emit('prefinish'); - } -} - -function finishMaybe(stream, state) { - var need = needFinish(state); - if (need) { - if (state.pendingcb === 0) { - prefinish(stream, state); - state.finished = true; - stream.emit('finish'); - } else { - prefinish(stream, state); - } - } - return need; -} - -function endWritable(stream, state, cb) { - state.ending = true; - finishMaybe(stream, state); - if (cb) { - if (state.finished) processNextTick(cb);else stream.once('finish', cb); - } - state.ended = true; - stream.writable = false; -} - -// It seems a linked list but it is not -// there will be only 2 of these for each stream -function CorkedRequest(state) { - var _this = this; - - this.next = null; - this.entry = null; - this.finish = function (err) { - var entry = _this.entry; - _this.entry = null; - while (entry) { - var cb = entry.callback; - state.pendingcb--; - cb(err); - entry = entry.next; - } - if (state.corkedRequestsFree) { - state.corkedRequestsFree.next = _this; - } else { - state.corkedRequestsFree = _this; - } - }; -} -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6), __webpack_require__(96).setImmediate)) - -/***/ }), -/* 37 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(__dirname, Buffer, process) {const Snekfetch = __webpack_require__(90); - -const ENV_VAR = '__SNEKFETCH_SYNC_REQUEST'; -let first = true; - -for (let method of Snekfetch.METHODS) { - method = method === 'M-SEARCH' ? 'msearch' : method.toLowerCase(); - Snekfetch[`${method}Sync`] = (url, options = {}) => { - if (first) { - first = false; - console.error( - 'Performing sync requests is a really stupid thing to do. ' + - 'https://www.google.com/search?q=why+sync+requests+are+bad+nodejs' - ); - } - options.url = url; - options.method = method; - const cp = __webpack_require__(27); - const result = JSON.parse( - cp.execSync(`node ${__dirname}/index.js`, { - env: { [ENV_VAR]: JSON.stringify(options) }, - }).toString(), - (k, v) => { - if (v === null) return v; - if (v.type === 'Buffer' && Array.isArray(v.data)) return new Buffer(v.data); - if (v.__CONVERT_TO_ERROR) { - const e = new Error(); - for (const key of Object.keys(v)) { - if (key === '__CONVERT_TO_ERROR') continue; - e[key] = v[key]; - } - return e; - } - return v; - } - ); - if (result.error) throw result.error; - return result; - }; -} - -if (process.env[ENV_VAR]) { - const options = JSON.parse(process.env[ENV_VAR]); - const request = Snekfetch[options.method](options.url); - if (options.headers) request.set(options.headers); - if (options.body) request.send(options.body); - request.end((err, res = {}) => { - if (err) { - const alt = {}; - for (const name of Object.getOwnPropertyNames(err)) alt[name] = err[name]; - res.error = alt; - res.error.__CONVERT_TO_ERROR = true; - } - // circulars - res.request = null; - process.stdout.write(JSON.stringify(res)); - }); -} - -module.exports = Snekfetch; - -/* WEBPACK VAR INJECTION */}.call(exports, "node_modules/snekfetch", __webpack_require__(5).Buffer, __webpack_require__(6))) - -/***/ }), -/* 38 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(Buffer) {const path = __webpack_require__(26); -const fs = __webpack_require__(27); -const snekfetch = __webpack_require__(37); - -const Constants = __webpack_require__(0); -const convertToBuffer = __webpack_require__(4).convertToBuffer; -const User = __webpack_require__(16); -const Message = __webpack_require__(19); -const Guild = __webpack_require__(24); -const Channel = __webpack_require__(14); -const GuildMember = __webpack_require__(18); -const Emoji = __webpack_require__(17); -const ReactionEmoji = __webpack_require__(29); - -/** - * 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|Snowflake|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 {?Snowflake} - */ - 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 - * * A Guild ID - * @typedef {Guild|Snowflake} 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 object. 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|Snowflake} 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 (typeof channel === 'string') return this.client.channels.get(channel) || null; - if (channel instanceof Message) return channel.channel; - if (channel instanceof Guild) return channel.channels.get(channel.id) || null; - return null; - } - - /** - * Resolves a ChannelResolvable to a channel ID - * @param {ChannelResolvable} channel The channel resolvable to resolve - * @returns {?Snowflake} - */ - resolveChannelID(channel) { - if (channel instanceof Channel) return channel.id; - if (typeof channel === 'string') return channel; - if (channel instanceof Message) return channel.channel.id; - if (channel instanceof Guild) return channel.defaultChannel.id; - return null; - } - - /** - * Data that can be resolved to give an invite code. This can be: - * * 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\.com\/invite|\.gg)\/([\w-]{2,255})/i; - const match = inviteRegex.exec(data); - if (match && match[1]) return match[1]; - return data; - } - - /** - * 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(convertToBuffer(resource)); - - if (typeof resource === 'string') { - return new Promise((resolve, reject) => { - if (/^https?:\/\//.test(resource)) { - snekfetch.get(resource) - .end((err, res) => { - if (err) return reject(err); - if (!(res.body instanceof Buffer)) return reject(new TypeError('The response body isn\'t a Buffer.')); - return resolve(res.body); - }); - } else { - const file = path.resolve(resource); - fs.stat(file, (err, stats) => { - if (err) return reject(err); - if (!stats || !stats.isFile()) return reject(new Error(`The file could not be found: ${file}`)); - fs.readFile(file, (err2, data) => { - if (err2) reject(err2); else resolve(data); - }); - return null; - }); - } - }); - } - - 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: - * * The unicode representation of an emoji - * * A custom emoji ID - * * An Emoji object - * * A ReactionEmoji object - * @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 (this.client.emojis.has(emoji)) return this.client.emojis.get(emoji).identifier; - else if (!emoji.includes('%')) return encodeURIComponent(emoji); - else return emoji; - } - return null; - } - - /** - * Can be a Hex Literal, Hex String, Number, RGB Array, or one of the following - * ``` - * [ - * 'DEFAULT', - * 'AQUA', - * 'GREEN', - * 'BLUE', - * 'PURPLE', - * 'GOLD', - * 'ORANGE', - * 'RED', - * 'GREY', - * 'DARKER_GREY', - * 'NAVY', - * 'DARK_AQUA', - * 'DARK_GREEN', - * 'DARK_BLUE', - * 'DARK_PURPLE', - * 'DARK_GOLD', - * 'DARK_ORANGE', - * 'DARK_RED', - * 'DARK_GREY', - * 'LIGHT_GREY', - * 'DARK_NAVY', - * 'RANDOM', - * ] - * ``` - * or something like - * ``` - * [255, 0, 255] - * ``` - * for purple - * @typedef {string|number|Array} ColorResolvable - */ - - /** - * Resolves a ColorResolvable into a color number - * @param {ColorResolvable} color Color to resolve - * @returns {number} A color - */ - static resolveColor(color) { - if (typeof color === 'string') { - if (color === 'RANDOM') return Math.floor(Math.random() * (0xFFFFFF + 1)); - color = Constants.Colors[color] || parseInt(color.replace('#', ''), 16); - } else if (color instanceof Array) { - color = (color[0] << 16) + (color[1] << 8) + color[2]; - } - - if (color < 0 || color > 0xFFFFFF) { - throw new RangeError('Color must be within the range 0 - 16777215 (0xFFFFFF).'); - } else if (color && isNaN(color)) { - throw new TypeError('Unable to convert color to a number.'); - } - - return color; - } - - /** - * @param {ColorResolvable} color Color to resolve - * @returns {number} A color - */ - resolveColor(color) { - return this.constructor.resolveColor(color); - } -} - -module.exports = ClientDataResolver; - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5).Buffer)) - -/***/ }), -/* 39 */ -/***/ (function(module, exports) { - -module.exports = { - "name": "discord.js", - "version": "11.1.0", - "description": "A powerful library for interacting with the Discord API", - "main": "./src/index", - "types": "./typings/index.d.ts", - "scripts": { - "test": "npm run lint && npm run docs:test", - "docs": "docgen --source src --custom docs/index.yml --output docs/docs.json", - "docs:test": "docgen --source src --custom docs/index.yml", - "lint": "eslint src", - "lint:fix": "eslint --fix src", - "webpack": "parallel-webpack" - }, - "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", - "runkitExampleFilename": "./docs/examples/ping.js", - "dependencies": { - "long": "^3.2.0", - "prism-media": "^0.0.1", - "snekfetch": "^3.1.0", - "tweetnacl": "^0.14.0", - "ws": "^2.0.0" - }, - "peerDependencies": { - "bufferutil": "^2.0.0", - "erlpack": "hammerandchisel/erlpack", - "node-opus": "^0.2.5", - "opusscript": "^0.0.3", - "sodium": "^2.0.1", - "libsodium-wrappers": "^0.5.1" - }, - "devDependencies": { - "@types/node": "^7.0.0", - "discord.js-docgen": "hydrabolt/discord.js-docgen", - "eslint": "^3.19.0", - "parallel-webpack": "^1.6.0", - "uglify-js": "mishoo/UglifyJS2#harmony", - "webpack": "^2.2.0" - }, - "engines": { - "node": ">=6.0.0" - }, - "browser": { - "ws": false, - "uws": false, - "erlpack": false, - "prism-media": false, - "opusscript": false, - "node-opus": false, - "tweetnacl": false, - "sodium": 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/receiver/VoiceReadable.js": false, - "src/client/voice/receiver/VoiceReceiver.js": false, - "src/client/voice/util/Secretbox.js": false, - "src/client/voice/util/SecretKey.js": false, - "src/client/voice/util/VolumeInterface.js": false, - "src/client/voice/ClientVoiceManager.js": false, - "src/client/voice/VoiceBroadcast.js": false, - "src/client/voice/VoiceConnection.js": false, - "src/client/voice/VoiceUDPClient.js": false, - "src/client/voice/VoiceWebSocket.js": false - } -}; - -/***/ }), -/* 40 */ -/***/ (function(module, exports, __webpack_require__) { - -const User = __webpack_require__(16); -const Collection = __webpack_require__(3); -const ClientUserSettings = __webpack_require__(41); -const Constants = __webpack_require__(0); - -/** - * 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(); - - /** - * If the user has discord premium (nitro) - * This is only filled when using a user account. - * @type {?boolean} - */ - this.premium = typeof data.premium === 'boolean' ? data.premium : null; - - /** - * If the user has MFA enabled on their account - * This is only filled when using a user account. - * @type {?boolean} - */ - this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null; - - /** - * If the user has ever used a mobile device on discord - * This is only filled when using a user account. - * @type {?boolean} - */ - this.mobile = typeof data.mobile === 'boolean' ? data.mobile : null; - - /** - * Various settings for this user - * This is only filled when using a user account - * @type {?ClientUserSettings} - */ - if (data.user_settings) this.settings = new ClientUserSettings(this, data.user_settings); - } - - 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 - * @param {string} [password] Current password (only for user accounts) - * @returns {Promise} - * @example - * // set username - * client.user.setUsername('discordjs') - * .then(user => console.log(`My new username is ${user.username}`)) - * .catch(console.error); - */ - setUsername(username, password) { - return this.client.rest.methods.updateCurrentUser({ username }, password); - } - - /** - * Changes the email for the client user's account. - * This is only available when using a user account. - * @param {string} email New email to change to - * @param {string} password Current password - * @returns {Promise} - * @example - * // set email - * client.user.setEmail('bob@gmail.com', 'some amazing password 123') - * .then(user => console.log(`My new email is ${user.email}`)) - * .catch(console.error); - */ - setEmail(email, password) { - return this.client.rest.methods.updateCurrentUser({ email }, password); - } - - /** - * Changes the password for the client user's account. - * This is only available when using a user account. - * @param {string} newPassword New password to change to - * @param {string} oldPassword Current password - * @returns {Promise} - * @example - * // set password - * client.user.setPassword('some new amazing password 456', 'some amazing password 123') - * .then(user => console.log('New password set!')) - * .catch(console.error); - */ - setPassword(newPassword, oldPassword) { - return this.client.rest.methods.updateCurrentUser({ password: newPassword }, oldPassword); - } - - /** - * 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 (typeof avatar === 'string' && 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 }) - ); - } - } - - /** - * Data resembling a raw Discord presence - * @typedef {Object} PresenceData - * @property {PresenceStatus} [status] Status of the user - * @property {boolean} [afk] Whether the user is AFK - * @property {Object} [game] Game the user is playing - * @property {string} [game.name] Name of the game - * @property {string} [game.url] Twitch stream URL - */ - - /** - * Sets the full presence of the client user. - * @param {PresenceData} data Data for the presence - * @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'); - if (this.bot) { - status = data.status; - } else { - this.settings.update(Constants.UserSettingsMap.status, data.status); - status = 'invisible'; - } - } - - if (data.game) { - game = data.game; - if (game.url) game.type = 1; - } else if (typeof data.game !== 'undefined') { - game = null; - } - - 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); - }); - } - - /** - * A user's status. Must be one of: - * - `online` - * - `idle` - * - `invisible` - * - `dnd` (do not disturb) - * @typedef {string} PresenceStatus - */ - - /** - * Sets the status of the client user. - * @param {PresenceStatus} status Status to change to - * @returns {Promise} - */ - setStatus(status) { - return this.setPresence({ status }); - } - - /** - * Sets the game the client user is playing. - * @param {?string} game Game being played - * @param {string} [streamingURL] Twitch stream URL - * @returns {Promise} - */ - setGame(game, streamingURL) { - if (!game) return this.setPresence({ game: null }); - return this.setPresence({ - game: { - name: game, - url: streamingURL, - }, - }); - } - - /** - * Sets/removes the AFK flag for the client user. - * @param {boolean} afk Whether or not the user is AFK - * @returns {Promise} - */ - setAFK(afk) { - return this.setPresence({ afk }); - } - - /** - * Fetches messages that mentioned the client's user - * @param {Object} [options] Options for the fetch - * @param {number} [options.limit=25] Maximum number of mentions to retrieve - * @param {boolean} [options.roles=true] Whether to include role mentions - * @param {boolean} [options.everyone=true] Whether to include everyone/here mentions - * @param {Guild|Snowflake} [options.guild] Limit the search to a specific guild - * @returns {Promise} - */ - fetchMentions(options = { limit: 25, roles: true, everyone: true, guild: null }) { - return this.client.rest.methods.fetchMentions(options); - } - - /** - * 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 (typeof icon === 'string' && 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 }) - ); - } - } - - /** - * An object containing either a user or access token, and an optional nickname - * @typedef {Object} GroupDMRecipientOptions - * @property {UserResolvable|Snowflake} [user] User to add to the group DM - * (only available if a user is creating the DM) - * @property {string} [accessToken] Access token to use to add a user to the group DM - * (only available if a bot is creating the DM) - * @property {string} [nick] Permanent nickname (only available if a bot is creating the DM) - */ - - /** - * Creates a group DM - * @param {GroupDMRecipientOptions[]} recipients The recipients - * @returns {Promise} - */ - createGroupDM(recipients) { - return this.client.rest.methods.createGroupDM({ - recipients: recipients.map(u => this.client.resolver.resolveUserID(u.user)), - accessTokens: recipients.map(u => u.accessToken), - nicks: recipients.map(u => u.nick), - }); - } - - /** - * Accepts an invite to join a guild - * This is only available when using a user account. - * @param {Invite|string} invite Invite or code to accept - * @returns {Promise} Joined guild - */ - acceptInvite(invite) { - return this.client.rest.methods.acceptInvite(invite); - } -} - -module.exports = ClientUser; - - -/***/ }), -/* 41 */ -/***/ (function(module, exports, __webpack_require__) { - -const Constants = __webpack_require__(0); -const Util = __webpack_require__(4); - -/** - * A wrapper around the ClientUser's settings - */ -class ClientUserSettings { - constructor(user, data) { - this.user = user; - this.patch(data); - } - - /** - * Patch the data contained in this class with new partial data - * @param {Object} data Data to patch this with - */ - patch(data) { - for (const key of Object.keys(Constants.UserSettingsMap)) { - const value = Constants.UserSettingsMap[key]; - if (!data.hasOwnProperty(key)) continue; - if (typeof value === 'function') { - this[value.name] = value(data[key]); + if (strm.avail_out === 0 || (strm.avail_in === 0 && (_mode === Z_FINISH || _mode === Z_SYNC_FLUSH))) { + if (this.options.to === 'string') { + this.onData(strings.buf2binstring(utils.shrinkBuf(strm.output, strm.next_out))); } else { - this[value] = data[key]; + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); } } - } - - /** - * Update a specific property of of user settings - * @param {string} name Name of property - * @param {value} value Value to patch - * @returns {Promise} - */ - update(name, value) { - return this.user.client.rest.methods.patchUserSettings({ [name]: value }); - } - - /** - * @param {Guild} guild Guild to move - * @param {number} position Absolute or relative position - * @param {boolean} [relative=false] Whether to position relatively or absolutely - * @returns {Promise} - */ - setGuildPosition(guild, position, relative) { - const temp = Object.assign([], this.guildPositions); - Util.moveElementInArray(temp, guild.id, position, relative); - return this.update('guild_positions', temp).then(() => guild); - } - - /** - * Add a guild to the list of restricted guilds - * @param {Guild} guild Guild to add - * @returns {Promise} - */ - addRestrictedGuild(guild) { - const temp = Object.assign([], this.restrictedGuilds); - if (temp.includes(guild.id)) return Promise.reject(new Error('Guild is already restricted')); - temp.push(guild.id); - return this.update('restricted_guilds', temp).then(() => guild); - } - - /** - * Remove a guild from the list of restricted guilds - * @param {Guild} guild Guild to remove - * @returns {Promise} - */ - removeRestrictedGuild(guild) { - const temp = Object.assign([], this.restrictedGuilds); - const index = temp.indexOf(guild.id); - if (index < 0) return Promise.reject(new Error('Guild is not restricted')); - temp.splice(index, 1); - return this.update('restricted_guilds', temp).then(() => guild); - } -} - -module.exports = ClientUserSettings; - - -/***/ }), -/* 42 */ -/***/ (function(module, exports, __webpack_require__) { - -const Channel = __webpack_require__(14); -const TextBasedChannel = __webpack_require__(22); -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 - /* eslint-disable no-empty-function */ - send() {} - sendMessage() {} - sendEmbed() {} - sendFile() {} - sendFiles() {} - sendCode() {} - fetchMessage() {} - fetchMessages() {} - fetchPinnedMessages() {} - search() {} - startTyping() {} - stopTyping() {} - get typing() {} - get typingCount() {} - createCollector() {} - awaitMessages() {} - // Doesn't work on DM channels; bulkDelete() {} - acknowledge() {} - _cacheMessage() {} -} - -TextBasedChannel.applyToClass(DMChannel, true, ['bulkDelete']); - -module.exports = DMChannel; - - -/***/ }), -/* 43 */ -/***/ (function(module, exports, __webpack_require__) { - -const PartialGuild = __webpack_require__(50); -const PartialGuildChannel = __webpack_require__(51); -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 - * @name Invite#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - 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; - - -/***/ }), -/* 44 */ -/***/ (function(module, exports) { - -/** - * Represents an attachment in a message - */ -class MessageAttachment { - constructor(message, data) { - /** - * The Client that instantiated this MessageAttachment. - * @name MessageAttachment#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: message.client }); - - /** - * The message this attachment is part of. - * @type {Message} - */ - this.message = message; - - this.setup(data); - } - - setup(data) { - /** - * The ID of this attachment - * @type {Snowflake} - */ - 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; - - -/***/ }), -/* 45 */ -/***/ (function(module, exports, __webpack_require__) { - -const Collector = __webpack_require__(31); - -/** - * @typedef {CollectorOptions} MessageCollectorOptions - * @property {number} max The maximum amount of messages to process. - * @property {number} maxMatches The maximum amount of messages to collect. - */ - -/** - * Collects messages on a channel. - * @extends {Collector} - */ -class MessageCollector extends Collector { - - /** - * @param {TextChannel|DMChannel|GroupDMChannel} channel The channel. - * @param {CollectorFilter} filter The filter to be applied to this collector. - * @param {MessageCollectorOptions} options The options to be applied to this collector. - * @emits MessageCollector#message - */ - constructor(channel, filter, options = {}) { - super(channel.client, filter, options); - - /** - * @type {TextBasedChannel} channel The channel. - */ - this.channel = channel; - - /** - * Total number of messages that were received in the - * channel during message collection. - * @type {number} - */ - this.received = 0; - - this.client.on('message', this.listener); - - // For backwards compatibility (remove in v12). - if (this.options.max) this.options.maxProcessed = this.options.max; - if (this.options.maxMatches) this.options.max = this.options.maxMatches; - this._reEmitter = message => { - /** - * Emitted when the collector receives a message. - * @event MessageCollector#message - * @param {Message} message The message. - * @deprecated - */ - this.emit('message', message); - }; - this.on('collect', this._reEmitter); - } - - /** - * Handle an incoming message for possible collection. - * @param {Message} message The message that could be collected. - * @returns {?{key: Snowflake, value: Message}} Message data to collect. - * @private - */ - handle(message) { - if (message.channel.id !== this.channel.id) return null; - this.received++; - return { - key: message.id, - value: message, - }; - } - - /** - * Check after collection to see if the collector is done. - * @returns {?string} Reason to end the collector, if any. - * @private - */ - postCheck() { - // Consider changing the end reasons for v12 - if (this.options.maxMatches && this.collected.size >= this.options.max) return 'matchesLimit'; - if (this.options.max && this.received >= this.options.maxProcessed) return 'limit'; - return null; - } - - /** - * Removes event listeners. - * @private - */ - cleanup() { - this.removeListener('collect', this._reEmitter); - this.client.removeListener('message', this.listener); - } -} - -module.exports = MessageCollector; - - -/***/ }), -/* 46 */ -/***/ (function(module, exports) { - -/** - * Represents an embed in a message (image/video preview, rich embed, etc.) - * This class is only used for *recieved* embeds. If you wish to send one, use the {@link RichEmbed} class. - */ -class MessageEmbed { - constructor(message, data) { - /** - * The client that instantiated this embed - * @name MessageEmbed#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: message.client }); - - /** - * The message this embed is part of - * @type {Message} - */ - this.message = message; - - this.setup(data); - } - - setup(data) { - /** - * The type of this embed - * @type {string} - */ - this.type = data.type; - - /** - * The title of this embed, if there is one - * @type {?string} - */ - this.title = data.title; - - /** - * 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 color of the embed - * @type {number} - */ - this.color = data.color; - - /** - * 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 image of this embed, if there is one - * @type {?MessageEmbedImage} - */ - this.image = data.image ? new MessageEmbedImage(this, data.image) : null; - - /** - * The video of this embed, if there is one - * @type {?MessageEmbedVideo} - */ - this.video = data.video ? new MessageEmbedVideo(this, data.video) : 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} - * @readonly - */ - get createdAt() { - return new Date(this.createdTimestamp); - } - - /** - * The hexadecimal version of the embed color, with a leading hash. - * @type {string} - * @readonly - */ - get hexColor() { - let col = this.color.toString(16); - while (col.length < 6) col = `0${col}`; - return `#${col}`; - } -} - -/** - * 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 an image for a message embed - */ -class MessageEmbedImage { - constructor(embed, data) { - /** - * The embed this image is part of - * @type {MessageEmbed} - */ - this.embed = embed; - - this.setup(data); - } - - setup(data) { - /** - * The URL for this image - * @type {string} - */ - this.url = data.url; - - /** - * The Proxy URL for this image - * @type {string} - */ - this.proxyURL = data.proxy_url; - - /** - * The height of the image - * @type {number} - */ - this.height = data.height; - - /** - * The width of the image - * @type {number} - */ - this.width = data.width; - } -} - -/** - * Represents a video for a message embed - */ -class MessageEmbedVideo { - constructor(embed, data) { - /** - * The embed this video is part of - * @type {MessageEmbed} - */ - this.embed = embed; - - this.setup(data); - } - - setup(data) { - /** - * The source URL for this video - * @type {string} - */ - this.url = data.url; - - /** - * The height of the video - * @type {number} - */ - this.height = data.height; - - /** - * The width of the video - * @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; - - /** - * The icon URL of this author - * @type {string} - */ - this.iconURL = data.icon_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.Image = MessageEmbedImage; -MessageEmbed.Video = MessageEmbedVideo; -MessageEmbed.Provider = MessageEmbedProvider; -MessageEmbed.Author = MessageEmbedAuthor; -MessageEmbed.Field = MessageEmbedField; -MessageEmbed.Footer = MessageEmbedFooter; - -module.exports = MessageEmbed; - - -/***/ }), -/* 47 */ -/***/ (function(module, exports, __webpack_require__) { - -const Collection = __webpack_require__(3); - -/** - * Keeps track of mentions in a {@link Message} - */ -class MessageMentions { - constructor(message, users, roles, everyone) { - /** - * Whether `@everyone` or `@here` were mentioned - * @type {boolean} - */ - this.everyone = Boolean(everyone); - - if (users) { - if (users instanceof Collection) { - /** - * Any users that were mentioned - * @type {Collection} - */ - this.users = new Collection(users); - } else { - this.users = new Collection(); - for (const mention of users) { - let user = message.client.users.get(mention.id); - if (!user) user = message.client.dataManager.newUser(mention); - this.users.set(user.id, user); - } - } - } else { - this.users = new Collection(); - } - - if (roles) { - if (roles instanceof Collection) { - /** - * Any roles that were mentioned - * @type {Collection} - */ - this.roles = new Collection(roles); - } else { - this.roles = new Collection(); - for (const mention of roles) { - const role = message.channel.guild.roles.get(mention); - if (role) this.roles.set(role.id, role); - } - } - } else { - this.roles = new Collection(); - } - - /** - * Content of the message - * @type {Message} - * @private - */ - this._content = message.content; - - /** - * Guild the message is in - * @type {?Guild} - * @private - */ - this._guild = message.channel.guild; - - /** - * Cached members for {@MessageMention#members} - * @type {?Collection} - * @private - */ - this._members = null; - - /** - * Cached channels for {@MessageMention#channels} - * @type {?Collection} - * @private - */ - this._channels = null; - } - - /** - * Any members that were mentioned (only in {@link TextChannel}s) - * @type {?Collection} - * @readonly - */ - get members() { - if (this._members) return this._members; - if (!this._guild) return null; - this._members = new Collection(); - this.users.forEach(user => { - const member = this._guild.member(user); - if (member) this._members.set(member.user.id, member); - }); - return this._members; - } - - /** - * Any channels that were mentioned (only populated in {@link TextChannel}s) - * @type {Collection} - * @readonly - */ - get channels() { - if (this._channels) return this._channels; - this._channels = new Collection(); - if (!this._guild) return this._channels; - let matches; - while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) { - const chan = this._guild.channels.get(matches[1]); - if (chan) this._channels.set(chan.id, chan); - } - return this._channels; - } -} - -/** - * Regular expression that globally matches `@everyone` and `@here` - * @type {RegExp} - */ -MessageMentions.EVERYONE_PATTERN = /@(everyone|here)/g; - -/** - * Regular expression that globally matches user mentions like `<#81440962496172032>` - * @type {RegExp} - */ -MessageMentions.USERS_PATTERN = /<@!?[0-9]+>/g; - -/** - * Regular expression that globally matches role mentions like `<@&297577916114403338>` - * @type {RegExp} - */ -MessageMentions.ROLES_PATTERN = /<@&[0-9]+>/g; - -/** - * Regular expression that globally matches channel mentions like `<#222079895583457280>` - * @type {RegExp} - */ -MessageMentions.CHANNELS_PATTERN = /<#([0-9]+)>/g; - -module.exports = MessageMentions; - - -/***/ }), -/* 48 */ -/***/ (function(module, exports, __webpack_require__) { - -const Collection = __webpack_require__(3); -const Emoji = __webpack_require__(17); -const ReactionEmoji = __webpack_require__(29); - -/** - * 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} - * @readonly - */ - 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=this.message.client.user] User to remove the reaction of - * @returns {Promise} - */ - remove(user = this.message.client.user) { - const message = this.message; - const userID = this.message.client.resolver.resolveUserID(user); - if (!userID) return Promise.reject(new Error('Couldn\'t resolve the user ID to remove from the reaction.')); - return message.client.rest.methods.removeMessageReaction( - message, this.emoji.identifier, userID - ); - } - - /** - * 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 this.users; - }); - } -} - -module.exports = MessageReaction; - - -/***/ }), -/* 49 */ -/***/ (function(module, exports, __webpack_require__) { - -const Snowflake = __webpack_require__(7); - -/** - * Represents an OAuth2 Application - */ -class OAuth2Application { - constructor(client, data) { - /** - * The client that instantiated the application - * @name OAuth2Application#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - this.setup(data); - } - - setup(data) { - /** - * The ID of the app - * @type {Snowflake} - */ - 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 {?string[]} - */ - this.rpcOrigins = data.rpc_origins; - - /** - * The app's redirect URIs - * @type {string[]} - */ - this.redirectURIs = data.redirect_uris; - - /** - * If this app's bot requires a code grant when using the oauth2 flow - * @type {boolean} - */ - this.botRequireCodeGrant = data.bot_require_code_grant; - - /** - * If this app's bot is public - * @type {boolean} - */ - this.botPublic = data.bot_public; - - /** - * If this app can use rpc - * @type {boolean} - */ - this.rpcApplicationState = data.rpc_application_state; - - /** - * Object containing basic info about this app's bot - * @type {Object} - */ - this.bot = data.bot; - - /** - * Flags for the app - * @type {number} - */ - this.flags = data.flags; - - /** - * OAuth2 secret for the application - * @type {boolean} - */ - this.secret = data.secret; - } - - /** - * The timestamp the app was created at - * @type {number} - * @readonly - */ - get createdTimestamp() { - return Snowflake.deconstruct(this.id).timestamp; - } - - /** - * The time the app was created - * @type {Date} - * @readonly - */ - get createdAt() { - return new Date(this.createdTimestamp); - } - - /** - * Reset the app's secret and bot token - * @returns {OAuth2Application} - */ - reset() { - return this.client.rest.methods.resetApplication(this.id); - } - - /** - * 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; - - -/***/ }), -/* 50 */ -/***/ (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 - * @name PartialGuild#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - this.setup(data); - } - - setup(data) { - /** - * The ID of this guild - * @type {Snowflake} - */ - 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; - - -/***/ }), -/* 51 */ -/***/ (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 - * @name PartialGuildChannel#client - * @type {Client} - * @readonly - */ - Object.defineProperty(this, 'client', { value: client }); - - this.setup(data); - } - - setup(data) { - /** - * The ID of this guild channel - * @type {Snowflake} - */ - 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; - - -/***/ }), -/* 52 */ -/***/ (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 - * @name PermissionOverwrites#channel - * @type {GuildChannel} - * @readonly - */ - Object.defineProperty(this, 'channel', { value: guildChannel }); - - if (data) this.setup(data); - } - - setup(data) { - /** - * The ID of this overwrite, either a user ID or a role ID - * @type {Snowflake} - */ - this.id = data.id; - - /** - * The type of this overwrite - * @type {string} - */ - this.type = data.type; - - this.deny = data.deny; - this.allow = data.allow; - } - - /** - * Delete this Permission Overwrite. - * @returns {Promise} - */ - delete() { - return this.channel.client.rest.methods.deletePermissionOverwrites(this); - } -} - -module.exports = PermissionOverwrites; - - -/***/ }), -/* 53 */ -/***/ (function(module, exports, __webpack_require__) { - -const Collector = __webpack_require__(31); -const Collection = __webpack_require__(3); - -/** - * @typedef {CollectorOptions} ReactionCollectorOptions - * @property {number} max The maximum total amount of reactions to collect. - * @property {number} maxEmojis The maximum number of emojis to collect. - * @property {number} maxUsers The maximum number of users to react. - */ - -/** - * Collects reactions on messages. - * @extends {Collector} - */ -class ReactionCollector extends Collector { - - /** - * @param {Message} message The message upon which to collect reactions. - * @param {CollectorFilter} filter The filter to apply to this collector. - * @param {ReactionCollectorOptions} [options={}] The options to apply to this collector. - */ - constructor(message, filter, options = {}) { - super(message.client, filter, options); - - /** - * The message. - * @type {Message} - */ - this.message = message; - - /** - * Users which have reacted. - * @type {Collection} - */ - this.users = new Collection(); - - /** - * Total number of reactions collected. - * @type {number} - */ - this.total = 0; - - this.client.on('messageReactionAdd', this.listener); - } - - /** - * Handle an incoming reaction for possible collection. - * @param {MessageReaction} reaction The reaction to possibly collect. - * @returns {?{key: Snowflake, value: MessageReaction}} Reaction data to collect. - * @private - */ - handle(reaction) { - if (reaction.message.id !== this.message.id) return null; - return { - key: reaction.emoji.id || reaction.emoji.name, - value: reaction, - }; - } - - /** - * Check after collection to see if the collector is done. - * @param {MessageReaction} reaction The reaction that was collected. - * @param {User} user The user that reacted. - * @returns {?string} Reason to end the collector, if any. - * @private - */ - postCheck(reaction, user) { - this.users.set(user.id, user); - if (this.options.max && ++this.total >= this.options.max) return 'limit'; - if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit'; - if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit'; - return null; - } - - /** - * Remove event listeners. - * @private - */ - cleanup() { - this.client.removeListener('messageReactionAdd', this.listener); - } -} - -module.exports = ReactionCollector; - - -/***/ }), -/* 54 */ -/***/ (function(module, exports, __webpack_require__) { - -const GuildChannel = __webpack_require__(25); -const TextBasedChannel = __webpack_require__(22); -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|Base64Resolvable} 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 (typeof avatar === 'string' && 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)) - ); - } - }); - } - - /** - * If the Discord Client considers this channel NSFW - * @type {boolean} - * @readonly - */ - get nsfw() { - return /^nsfw(-|$)/.test(this.name); - } - - // These are here only for documentation purposes - they are implemented by TextBasedChannel - /* eslint-disable no-empty-function */ - send() {} - sendMessage() {} - sendEmbed() {} - sendFile() {} - sendFiles() {} - sendCode() {} - fetchMessage() {} - fetchMessages() {} - fetchPinnedMessages() {} - search() {} - startTyping() {} - stopTyping() {} - get typing() {} - get typingCount() {} - createCollector() {} - createMessageCollector() {} - awaitMessages() {} - bulkDelete() {} - acknowledge() {} - _cacheMessage() {} -} - -TextBasedChannel.applyToClass(TextChannel, true); - -module.exports = TextChannel; - - -/***/ }), -/* 55 */ -/***/ (function(module, exports, __webpack_require__) { - -const GuildChannel = __webpack_require__(25); -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; - } + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== Z_STREAM_END); - /** - * Checks if the voice channel is full - * @type {boolean} - * @readonly - */ - get full() { - return this.userLimit > 0 && this.members.size >= this.userLimit; + // Finalize on the last chunk. + if (_mode === Z_FINISH) { + status = zlib_deflate.deflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === Z_OK; } - /** - * Checks if the client has permission join the voice channel - * @type {boolean} - * @readonly - */ - get joinable() { - if (this.client.browser) return false; - if (!this.permissionsFor(this.client.user).hasPermission('CONNECT')) return false; - if (this.full && !this.permissionsFor(this.client.user).hasPermission('MOVE_MEMBERS')) return false; + // callback interim results if Z_SYNC_FLUSH. + if (_mode === Z_SYNC_FLUSH) { + this.onEnd(Z_OK); + strm.avail_out = 0; return true; } - /** - * Checks if the client has permission to send audio to the voice channel - * @type {boolean} - * @readonly - */ - 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; - - -/***/ }), -/* 56 */ -/***/ (function(module, exports) { - -var toString = {}.toString; - -module.exports = Array.isArray || function (arr) { - return toString.call(arr) == '[object Array]'; + return true; }; -/***/ }), -/* 57 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/* WEBPACK VAR INJECTION */(function(process) { - -module.exports = Readable; - -/**/ -var processNextTick = __webpack_require__(34); -/**/ - -/**/ -var isArray = __webpack_require__(56); -/**/ - -/**/ -var Duplex; -/**/ - -Readable.ReadableState = ReadableState; - -/**/ -var EE = __webpack_require__(12).EventEmitter; - -var EElistenerCount = function (emitter, type) { - return emitter.listeners(type).length; +/** + * Deflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): ouput data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Deflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); }; -/**/ -/**/ -var Stream = __webpack_require__(59); -/**/ -var Buffer = __webpack_require__(5).Buffer; -/**/ -var bufferShim = __webpack_require__(32); -/**/ - -/**/ -var util = __webpack_require__(20); -util.inherits = __webpack_require__(10); -/**/ - -/**/ -var debugUtil = __webpack_require__(183); -var debug = void 0; -if (debugUtil && debugUtil.debuglog) { - debug = debugUtil.debuglog('stream'); -} else { - debug = function () {}; -} -/**/ - -var BufferList = __webpack_require__(83); -var StringDecoder; - -util.inherits(Readable, Stream); - -var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; - -function prependListener(emitter, event, fn) { - // Sadly this is not cacheable as some libraries bundle their own - // event emitter implementation with them. - if (typeof emitter.prependListener === 'function') { - return emitter.prependListener(event, fn); - } else { - // This is a hack to make sure that our error handler is attached before any - // userland ones. NEVER DO THIS. This is here only because this code needs - // to continue to work with older versions of Node.js that do not include - // the prependListener() method. The goal is to eventually remove this hack. - if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +/** + * Deflate#onEnd(status) -> Void + * - status (Number): deflate status. 0 (Z_OK) on success, + * other if not. + * + * Called once after you tell deflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Deflate.prototype.onEnd = function (status) { + // On success - join + if (status === Z_OK) { + if (this.options.to === 'string') { + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; + + +/** + * deflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * Compress `data` with deflate algorithm and `options`. + * + * Supported options are: + * + * - level + * - windowBits + * - memLevel + * - strategy + * - dictionary + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be "binary string" + * (each char code [0..255]) + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , data = Uint8Array([1,2,3,4,5,6,7,8,9]); + * + * console.log(pako.deflate(data)); + * ``` + **/ +function deflate(input, options) { + var deflator = new Deflate(options); + + deflator.push(input, true); + + // That will never happens, if you don't cheat with options :) + if (deflator.err) { throw deflator.msg || msg[deflator.err]; } + + return deflator.result; } -function ReadableState(options, stream) { - Duplex = Duplex || __webpack_require__(13); +/** + * deflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function deflateRaw(input, options) { options = options || {}; - - // object stream flag. Used to make read(n) ignore n and to - // make all the buffer merging and length checks go away - this.objectMode = !!options.objectMode; - - if (stream instanceof Duplex) this.objectMode = this.objectMode || !!options.readableObjectMode; - - // the point at which it stops calling _read() to fill the buffer - // Note: 0 is a valid value, means "don't call _read preemptively ever" - var hwm = options.highWaterMark; - var defaultHwm = this.objectMode ? 16 : 16 * 1024; - this.highWaterMark = hwm || hwm === 0 ? hwm : defaultHwm; - - // cast to ints. - this.highWaterMark = ~~this.highWaterMark; - - // A linked list is used to store data chunks instead of an array because the - // linked list can remove elements from the beginning faster than - // array.shift() - this.buffer = new BufferList(); - this.length = 0; - this.pipes = null; - this.pipesCount = 0; - this.flowing = null; - this.ended = false; - this.endEmitted = false; - this.reading = false; - - // a flag to be able to tell if the onwrite cb is called immediately, - // or on a later tick. We set this to true at first, because any - // actions that shouldn't happen until "later" should generally also - // not happen before the first write call. - this.sync = true; - - // whenever we return null, then we set a flag to say - // that we're awaiting a 'readable' event emission. - this.needReadable = false; - this.emittedReadable = false; - this.readableListening = false; - this.resumeScheduled = false; - - // Crypto is kind of old and crusty. Historically, its default string - // encoding is 'binary' so we have to make this configurable. - // Everything else in the universe uses 'utf8', though. - this.defaultEncoding = options.defaultEncoding || 'utf8'; - - // when piping, we only care about 'readable' events that happen - // after read()ing all the bytes and not getting any pushback. - this.ranOut = false; - - // the number of writers that are awaiting a drain event in .pipe()s - this.awaitDrain = 0; - - // if true, a maybeReadMore has been scheduled - this.readingMore = false; - - this.decoder = null; - this.encoding = null; - if (options.encoding) { - if (!StringDecoder) StringDecoder = __webpack_require__(64).StringDecoder; - this.decoder = new StringDecoder(options.encoding); - this.encoding = options.encoding; - } + options.raw = true; + return deflate(input, options); } -function Readable(options) { - Duplex = Duplex || __webpack_require__(13); - if (!(this instanceof Readable)) return new Readable(options); - - this._readableState = new ReadableState(options, this); - - // legacy - this.readable = true; - - if (options && typeof options.read === 'function') this._read = options.read; - - Stream.call(this); +/** + * gzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to compress. + * - options (Object): zlib deflate options. + * + * The same as [[deflate]], but create gzip wrapper instead of + * deflate one. + **/ +function gzip(input, options) { + options = options || {}; + options.gzip = true; + return deflate(input, options); } -// Manually shove something into the read() buffer. -// This returns true if the highWaterMark has not been hit yet, -// similar to how Writable.write() returns true if you should -// write() some more. -Readable.prototype.push = function (chunk, encoding) { - var state = this._readableState; - if (!state.objectMode && typeof chunk === 'string') { - encoding = encoding || state.defaultEncoding; - if (encoding !== state.encoding) { - chunk = bufferShim.from(chunk, encoding); - encoding = ''; - } - } +exports.Deflate = Deflate; +exports.deflate = deflate; +exports.deflateRaw = deflateRaw; +exports.gzip = gzip; - return readableAddChunk(this, state, chunk, encoding, false); -}; -// Unshift should *always* be something directly out of read() -Readable.prototype.unshift = function (chunk) { - var state = this._readableState; - return readableAddChunk(this, state, chunk, '', true); -}; - -Readable.prototype.isPaused = function () { - return this._readableState.flowing === false; -}; - -function readableAddChunk(stream, state, chunk, encoding, addToFront) { - var er = chunkInvalid(state, chunk); - if (er) { - stream.emit('error', er); - } else if (chunk === null) { - state.reading = false; - onEofChunk(stream, state); - } else if (state.objectMode || chunk && chunk.length > 0) { - if (state.ended && !addToFront) { - var e = new Error('stream.push() after EOF'); - stream.emit('error', e); - } else if (state.endEmitted && addToFront) { - var _e = new Error('stream.unshift() after end event'); - stream.emit('error', _e); - } else { - var skipAdd; - if (state.decoder && !addToFront && !encoding) { - chunk = state.decoder.write(chunk); - skipAdd = !state.objectMode && chunk.length === 0; - } - - if (!addToFront) state.reading = false; - - // Don't add to the buffer if we've decoded to an empty string chunk and - // we're not in object mode - if (!skipAdd) { - // if we want the data now, just emit it. - if (state.flowing && state.length === 0 && !state.sync) { - stream.emit('data', chunk); - stream.read(0); - } else { - // update the buffer info. - state.length += state.objectMode ? 1 : chunk.length; - if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); - - if (state.needReadable) emitReadable(stream); - } - } - - maybeReadMore(stream, state); - } - } else if (!addToFront) { - state.reading = false; - } - - return needMoreData(state); -} - -// if it's past the high water mark, we can push in some more. -// Also, if we have no data yet, we can stand some -// more bytes. This is to work around cases where hwm=0, -// such as the repl. Also, if the push() triggered a -// readable event, and the user called read(largeNumber) such that -// needReadable was set, then we ought to push more, so that another -// 'readable' event will be triggered. -function needMoreData(state) { - return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); -} - -// backwards compatibility. -Readable.prototype.setEncoding = function (enc) { - if (!StringDecoder) StringDecoder = __webpack_require__(64).StringDecoder; - this._readableState.decoder = new StringDecoder(enc); - this._readableState.encoding = enc; - return this; -}; - -// Don't raise the hwm > 8MB -var MAX_HWM = 0x800000; -function computeNewHighWaterMark(n) { - if (n >= MAX_HWM) { - n = MAX_HWM; - } else { - // Get the next highest power of 2 to prevent increasing hwm excessively in - // tiny amounts - n--; - n |= n >>> 1; - n |= n >>> 2; - n |= n >>> 4; - n |= n >>> 8; - n |= n >>> 16; - n++; - } - return n; -} - -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function howMuchToRead(n, state) { - if (n <= 0 || state.length === 0 && state.ended) return 0; - if (state.objectMode) return 1; - if (n !== n) { - // Only flow one buffer at a time - if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; - } - // If we're asking for more than the current hwm, then raise the hwm. - if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); - if (n <= state.length) return n; - // Don't have enough - if (!state.ended) { - state.needReadable = true; - return 0; - } - return state.length; -} - -// you can override either this method, or the async _read(n) below. -Readable.prototype.read = function (n) { - debug('read', n); - n = parseInt(n, 10); - var state = this._readableState; - var nOrig = n; - - if (n !== 0) state.emittedReadable = false; - - // if we're doing read(0) to trigger a readable event, but we - // already have a bunch of data in the buffer, then just trigger - // the 'readable' event and move on. - if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { - debug('read: emitReadable', state.length, state.ended); - if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); - return null; - } - - n = howMuchToRead(n, state); - - // if we've ended, and we're now clear, then finish it up. - if (n === 0 && state.ended) { - if (state.length === 0) endReadable(this); - return null; - } - - // All the actual chunk generation logic needs to be - // *below* the call to _read. The reason is that in certain - // synthetic stream cases, such as passthrough streams, _read - // may be a completely synchronous operation which may change - // the state of the read buffer, providing enough data when - // before there was *not* enough. - // - // So, the steps are: - // 1. Figure out what the state of things will be after we do - // a read from the buffer. - // - // 2. If that resulting state will trigger a _read, then call _read. - // Note that this may be asynchronous, or synchronous. Yes, it is - // deeply ugly to write APIs this way, but that still doesn't mean - // that the Readable class should behave improperly, as streams are - // designed to be sync/async agnostic. - // Take note if the _read call is sync or async (ie, if the read call - // has returned yet), so that we know whether or not it's safe to emit - // 'readable' etc. - // - // 3. Actually pull the requested chunks out of the buffer and return. - - // if we need a readable event, then we need to do some reading. - var doRead = state.needReadable; - debug('need readable', doRead); - - // if we currently have less than the highWaterMark, then also read some - if (state.length === 0 || state.length - n < state.highWaterMark) { - doRead = true; - debug('length less than watermark', doRead); - } - - // however, if we've ended, then there's no point, and if we're already - // reading, then it's unnecessary. - if (state.ended || state.reading) { - doRead = false; - debug('reading or ended', doRead); - } else if (doRead) { - debug('do read'); - state.reading = true; - state.sync = true; - // if the length is currently zero, then we *need* a readable event. - if (state.length === 0) state.needReadable = true; - // call internal read method - this._read(state.highWaterMark); - state.sync = false; - // If _read pushed data synchronously, then `reading` will be false, - // and we need to re-evaluate how much data we can return to the user. - if (!state.reading) n = howMuchToRead(nOrig, state); - } - - var ret; - if (n > 0) ret = fromList(n, state);else ret = null; - - if (ret === null) { - state.needReadable = true; - n = 0; - } else { - state.length -= n; - } - - if (state.length === 0) { - // If we have nothing in the buffer, then we want to know - // as soon as we *do* get something into the buffer. - if (!state.ended) state.needReadable = true; - - // If we tried to read() past the EOF, then emit end on the next tick. - if (nOrig !== n && state.ended) endReadable(this); - } - - if (ret !== null) this.emit('data', ret); - - return ret; -}; - -function chunkInvalid(state, chunk) { - var er = null; - if (!Buffer.isBuffer(chunk) && typeof chunk !== 'string' && chunk !== null && chunk !== undefined && !state.objectMode) { - er = new TypeError('Invalid non-string/buffer chunk'); - } - return er; -} - -function onEofChunk(stream, state) { - if (state.ended) return; - if (state.decoder) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) { - state.buffer.push(chunk); - state.length += state.objectMode ? 1 : chunk.length; - } - } - state.ended = true; - - // emit 'readable' now to make sure it gets picked up. - emitReadable(stream); -} - -// Don't emit readable right away in sync mode, because this can trigger -// another read() call => stack overflow. This way, it might trigger -// a nextTick recursion warning, but that's not so bad. -function emitReadable(stream) { - var state = stream._readableState; - state.needReadable = false; - if (!state.emittedReadable) { - debug('emitReadable', state.flowing); - state.emittedReadable = true; - if (state.sync) processNextTick(emitReadable_, stream);else emitReadable_(stream); - } -} - -function emitReadable_(stream) { - debug('emit readable'); - stream.emit('readable'); - flow(stream); -} - -// at this point, the user has presumably seen the 'readable' event, -// and called read() to consume some data. that may have triggered -// in turn another _read(n) call, in which case reading = true if -// it's in progress. -// However, if we're not ended, or reading, and the length < hwm, -// then go ahead and try to read some more preemptively. -function maybeReadMore(stream, state) { - if (!state.readingMore) { - state.readingMore = true; - processNextTick(maybeReadMore_, stream, state); - } -} - -function maybeReadMore_(stream, state) { - var len = state.length; - while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { - debug('maybeReadMore read 0'); - stream.read(0); - if (len === state.length) - // didn't get any data, stop spinning. - break;else len = state.length; - } - state.readingMore = false; -} - -// abstract method. to be overridden in specific implementation classes. -// call cb(er, data) where data is <= n in length. -// for virtual (non-string, non-buffer) streams, "length" is somewhat -// arbitrary, and perhaps not very meaningful. -Readable.prototype._read = function (n) { - this.emit('error', new Error('_read() is not implemented')); -}; - -Readable.prototype.pipe = function (dest, pipeOpts) { - var src = this; - var state = this._readableState; - - switch (state.pipesCount) { - case 0: - state.pipes = dest; - break; - case 1: - state.pipes = [state.pipes, dest]; - break; - default: - state.pipes.push(dest); - break; - } - state.pipesCount += 1; - debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); - - var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; - - var endFn = doEnd ? onend : cleanup; - if (state.endEmitted) processNextTick(endFn);else src.once('end', endFn); - - dest.on('unpipe', onunpipe); - function onunpipe(readable) { - debug('onunpipe'); - if (readable === src) { - cleanup(); - } - } - - function onend() { - debug('onend'); - dest.end(); - } - - // when the dest drains, it reduces the awaitDrain counter - // on the source. This would be more elegant with a .once() - // handler in flow(), but adding and removing repeatedly is - // too slow. - var ondrain = pipeOnDrain(src); - dest.on('drain', ondrain); - - var cleanedUp = false; - function cleanup() { - debug('cleanup'); - // cleanup event handlers once the pipe is broken - dest.removeListener('close', onclose); - dest.removeListener('finish', onfinish); - dest.removeListener('drain', ondrain); - dest.removeListener('error', onerror); - dest.removeListener('unpipe', onunpipe); - src.removeListener('end', onend); - src.removeListener('end', cleanup); - src.removeListener('data', ondata); - - cleanedUp = true; - - // if the reader is waiting for a drain event from this - // specific writer, then it would cause it to never start - // flowing again. - // So, if this is awaiting a drain, then we just call it now. - // If we don't know, then assume that we are waiting for one. - if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); - } - - // If the user pushes more data while we're writing to dest then we'll end up - // in ondata again. However, we only want to increase awaitDrain once because - // dest will only emit one 'drain' event for the multiple writes. - // => Introduce a guard on increasing awaitDrain. - var increasedAwaitDrain = false; - src.on('data', ondata); - function ondata(chunk) { - debug('ondata'); - increasedAwaitDrain = false; - var ret = dest.write(chunk); - if (false === ret && !increasedAwaitDrain) { - // If the user unpiped during `dest.write()`, it is possible - // to get stuck in a permanently paused state if that write - // also returned false. - // => Check whether `dest` is still a piping destination. - if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { - debug('false write response, pause', src._readableState.awaitDrain); - src._readableState.awaitDrain++; - increasedAwaitDrain = true; - } - src.pause(); - } - } - - // if the dest has an error, then stop piping into it. - // however, don't suppress the throwing behavior for this. - function onerror(er) { - debug('onerror', er); - unpipe(); - dest.removeListener('error', onerror); - if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); - } - - // Make sure our error handler is attached before userland ones. - prependListener(dest, 'error', onerror); - - // Both close and finish should trigger unpipe, but only once. - function onclose() { - dest.removeListener('finish', onfinish); - unpipe(); - } - dest.once('close', onclose); - function onfinish() { - debug('onfinish'); - dest.removeListener('close', onclose); - unpipe(); - } - dest.once('finish', onfinish); - - function unpipe() { - debug('unpipe'); - src.unpipe(dest); - } - - // tell the dest that it's being piped to - dest.emit('pipe', src); - - // start the flow if it hasn't been started already. - if (!state.flowing) { - debug('pipe resume'); - src.resume(); - } - - return dest; -}; - -function pipeOnDrain(src) { - return function () { - var state = src._readableState; - debug('pipeOnDrain', state.awaitDrain); - if (state.awaitDrain) state.awaitDrain--; - if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { - state.flowing = true; - flow(src); - } - }; -} - -Readable.prototype.unpipe = function (dest) { - var state = this._readableState; - - // if we're not piping anywhere, then do nothing. - if (state.pipesCount === 0) return this; - - // just one destination. most common case. - if (state.pipesCount === 1) { - // passed in one, but it's not the right one. - if (dest && dest !== state.pipes) return this; - - if (!dest) dest = state.pipes; - - // got a match. - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - if (dest) dest.emit('unpipe', this); - return this; - } - - // slow case. multiple pipe destinations. - - if (!dest) { - // remove all. - var dests = state.pipes; - var len = state.pipesCount; - state.pipes = null; - state.pipesCount = 0; - state.flowing = false; - - for (var i = 0; i < len; i++) { - dests[i].emit('unpipe', this); - }return this; - } - - // try to find the right one. - var index = indexOf(state.pipes, dest); - if (index === -1) return this; - - state.pipes.splice(index, 1); - state.pipesCount -= 1; - if (state.pipesCount === 1) state.pipes = state.pipes[0]; - - dest.emit('unpipe', this); - - return this; -}; - -// set up data events if they are asked for -// Ensure readable listeners eventually get something -Readable.prototype.on = function (ev, fn) { - var res = Stream.prototype.on.call(this, ev, fn); - - if (ev === 'data') { - // Start flowing on next tick if stream isn't explicitly paused - if (this._readableState.flowing !== false) this.resume(); - } else if (ev === 'readable') { - var state = this._readableState; - if (!state.endEmitted && !state.readableListening) { - state.readableListening = state.needReadable = true; - state.emittedReadable = false; - if (!state.reading) { - processNextTick(nReadingNextTick, this); - } else if (state.length) { - emitReadable(this, state); - } - } - } - - return res; -}; -Readable.prototype.addListener = Readable.prototype.on; - -function nReadingNextTick(self) { - debug('readable nexttick read 0'); - self.read(0); -} - -// pause() and resume() are remnants of the legacy readable stream API -// If the user uses them, then switch into old mode. -Readable.prototype.resume = function () { - var state = this._readableState; - if (!state.flowing) { - debug('resume'); - state.flowing = true; - resume(this, state); - } - return this; -}; - -function resume(stream, state) { - if (!state.resumeScheduled) { - state.resumeScheduled = true; - processNextTick(resume_, stream, state); - } -} - -function resume_(stream, state) { - if (!state.reading) { - debug('resume read 0'); - stream.read(0); - } - - state.resumeScheduled = false; - state.awaitDrain = 0; - stream.emit('resume'); - flow(stream); - if (state.flowing && !state.reading) stream.read(0); -} - -Readable.prototype.pause = function () { - debug('call pause flowing=%j', this._readableState.flowing); - if (false !== this._readableState.flowing) { - debug('pause'); - this._readableState.flowing = false; - this.emit('pause'); - } - return this; -}; - -function flow(stream) { - var state = stream._readableState; - debug('flow', state.flowing); - while (state.flowing && stream.read() !== null) {} -} - -// wrap an old-style stream as the async data source. -// This is *not* part of the readable stream interface. -// It is an ugly unfortunate mess of history. -Readable.prototype.wrap = function (stream) { - var state = this._readableState; - var paused = false; - - var self = this; - stream.on('end', function () { - debug('wrapped end'); - if (state.decoder && !state.ended) { - var chunk = state.decoder.end(); - if (chunk && chunk.length) self.push(chunk); - } - - self.push(null); - }); - - stream.on('data', function (chunk) { - debug('wrapped data'); - if (state.decoder) chunk = state.decoder.write(chunk); - - // don't skip over falsy values in objectMode - if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; - - var ret = self.push(chunk); - if (!ret) { - paused = true; - stream.pause(); - } - }); - - // proxy all the other methods. - // important when wrapping filters and duplexes. - for (var i in stream) { - if (this[i] === undefined && typeof stream[i] === 'function') { - this[i] = function (method) { - return function () { - return stream[method].apply(stream, arguments); - }; - }(i); - } - } - - // proxy certain important events. - for (var n = 0; n < kProxyEvents.length; n++) { - stream.on(kProxyEvents[n], self.emit.bind(self, kProxyEvents[n])); - } - - // when we try to consume some more bytes, simply unpause the - // underlying stream. - self._read = function (n) { - debug('wrapped _read', n); - if (paused) { - paused = false; - stream.resume(); - } - }; - - return self; -}; - -// exposed for testing purposes only. -Readable._fromList = fromList; - -// Pluck off n bytes from an array of buffers. -// Length is the combined lengths of all the buffers in the list. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function fromList(n, state) { - // nothing buffered - if (state.length === 0) return null; - - var ret; - if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { - // read it all, truncate the list - if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); - state.buffer.clear(); - } else { - // read part of list - ret = fromListPartial(n, state.buffer, state.decoder); - } - - return ret; -} - -// Extracts only enough buffered data to satisfy the amount requested. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function fromListPartial(n, list, hasStrings) { - var ret; - if (n < list.head.data.length) { - // slice is the same for buffers and strings - ret = list.head.data.slice(0, n); - list.head.data = list.head.data.slice(n); - } else if (n === list.head.data.length) { - // first chunk is a perfect match - ret = list.shift(); - } else { - // result spans more than one buffer - ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); - } - return ret; -} - -// Copies a specified amount of characters from the list of buffered data -// chunks. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function copyFromBufferString(n, list) { - var p = list.head; - var c = 1; - var ret = p.data; - n -= ret.length; - while (p = p.next) { - var str = p.data; - var nb = n > str.length ? str.length : n; - if (nb === str.length) ret += str;else ret += str.slice(0, n); - n -= nb; - if (n === 0) { - if (nb === str.length) { - ++c; - if (p.next) list.head = p.next;else list.head = list.tail = null; - } else { - list.head = p; - p.data = str.slice(nb); - } - break; - } - ++c; - } - list.length -= c; - return ret; -} - -// Copies a specified amount of bytes from the list of buffered data chunks. -// This function is designed to be inlinable, so please take care when making -// changes to the function body. -function copyFromBuffer(n, list) { - var ret = bufferShim.allocUnsafe(n); - var p = list.head; - var c = 1; - p.data.copy(ret); - n -= p.data.length; - while (p = p.next) { - var buf = p.data; - var nb = n > buf.length ? buf.length : n; - buf.copy(ret, ret.length - n, 0, nb); - n -= nb; - if (n === 0) { - if (nb === buf.length) { - ++c; - if (p.next) list.head = p.next;else list.head = list.tail = null; - } else { - list.head = p; - p.data = buf.slice(nb); - } - break; - } - ++c; - } - list.length -= c; - return ret; -} - -function endReadable(stream) { - var state = stream._readableState; - - // If we get here before consuming all the bytes, then that is a - // bug in node. Should never happen. - if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); - - if (!state.endEmitted) { - state.ended = true; - processNextTick(endReadableNT, state, stream); - } -} - -function endReadableNT(state, stream) { - // Check that we didn't get one last unshift. - if (!state.endEmitted && state.length === 0) { - state.endEmitted = true; - stream.readable = false; - stream.emit('end'); - } -} - -function forEach(xs, f) { - for (var i = 0, l = xs.length; i < l; i++) { - f(xs[i], i); - } -} - -function indexOf(xs, x) { - for (var i = 0, l = xs.length; i < l; i++) { - if (xs[i] === x) return i; - } - return -1; -} -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6))) - -/***/ }), -/* 58 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 70 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -// a transform stream is a readable/writable stream where you do -// something with the data. Sometimes it's called a "filter", -// but that's not a great name for it, since that implies a thing where -// some bits pass through, and others are simply ignored. (That would -// be a valid example of a transform, of course.) -// -// While the output is causally related to the input, it's not a -// necessarily symmetric or synchronous transformation. For example, -// a zlib stream might take multiple plain-text writes(), and then -// emit a single compressed chunk some time in the future. -// -// Here's how this works: -// -// The Transform stream has all the aspects of the readable and writable -// stream classes. When you write(chunk), that calls _write(chunk,cb) -// internally, and returns false if there's a lot of pending writes -// buffered up. When you call read(), that calls _read(n) until -// there's enough pending readable data buffered up. -// -// In a transform stream, the written data is placed in a buffer. When -// _read(n) is called, it transforms the queued up data, calling the -// buffered _write cb's as it consumes chunks. If consuming a single -// written chunk would result in multiple output chunks, then the first -// outputted bit calls the readcb, and subsequent chunks just go into -// the read buffer, and will cause it to emit 'readable' if necessary. -// -// This way, back-pressure is actually determined by the reading side, -// since _read has to be called to start processing a new chunk. However, -// a pathological inflate type of transform can cause excessive buffering -// here. For example, imagine a stream where every byte of input is -// interpreted as an integer from 0-255, and then results in that many -// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in -// 1kb of data being output. In this case, you could write a very small -// amount of input, and end up with a very large amount of output. In -// such a pathological inflating mechanism, there'd be no way to tell -// the system to stop doing the transform. A single 4MB write could -// cause the system to run out of memory. -// -// However, even in such a pathological case, only a single written chunk -// would be consumed, and then the rest would wait (un-transformed) until -// the results of the previous transformed chunk were consumed. -module.exports = Transform; +var zlib_inflate = __webpack_require__(74); +var utils = __webpack_require__(5); +var strings = __webpack_require__(44); +var c = __webpack_require__(46); +var msg = __webpack_require__(22); +var ZStream = __webpack_require__(48); +var GZheader = __webpack_require__(72); -var Duplex = __webpack_require__(13); +var toString = Object.prototype.toString; -/**/ -var util = __webpack_require__(20); -util.inherits = __webpack_require__(10); -/**/ +/** + * class Inflate + * + * Generic JS-style wrapper for zlib calls. If you don't need + * streaming behaviour - use more simple functions: [[inflate]] + * and [[inflateRaw]]. + **/ -util.inherits(Transform, Duplex); +/* internal + * inflate.chunks -> Array + * + * Chunks of output data, if [[Inflate#onData]] not overriden. + **/ -function TransformState(stream) { - this.afterTransform = function (er, data) { - return afterTransform(stream, er, data); - }; +/** + * Inflate.result -> Uint8Array|Array|String + * + * Uncompressed result, generated by default [[Inflate#onData]] + * and [[Inflate#onEnd]] handlers. Filled after you push last chunk + * (call [[Inflate#push]] with `Z_FINISH` / `true` param) or if you + * push a chunk with explicit flush (call [[Inflate#push]] with + * `Z_SYNC_FLUSH` param). + **/ - this.needTransform = false; - this.transforming = false; - this.writecb = null; - this.writechunk = null; - this.writeencoding = null; -} +/** + * Inflate.err -> Number + * + * Error code after inflate finished. 0 (Z_OK) on success. + * Should be checked if broken data possible. + **/ -function afterTransform(stream, er, data) { - var ts = stream._transformState; - ts.transforming = false; +/** + * Inflate.msg -> String + * + * Error message, if [[Inflate.err]] != 0 + **/ - var cb = ts.writecb; - if (!cb) return stream.emit('error', new Error('no writecb in Transform class')); +/** + * new Inflate(options) + * - options (Object): zlib inflate options. + * + * Creates new inflator instance with specified params. Throws exception + * on bad params. Supported options: + * + * - `windowBits` + * - `dictionary` + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information on these. + * + * Additional options, for internal needs: + * + * - `chunkSize` - size of generated data chunks (16K by default) + * - `raw` (Boolean) - do raw inflate + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * By default, when no options set, autodetect deflate/gzip data format via + * wrapper header. + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , chunk1 = Uint8Array([1,2,3,4,5,6,7,8,9]) + * , chunk2 = Uint8Array([10,11,12,13,14,15,16,17,18,19]); + * + * var inflate = new pako.Inflate({ level: 3}); + * + * inflate.push(chunk1, false); + * inflate.push(chunk2, true); // true -> last chunk + * + * if (inflate.err) { throw new Error(inflate.err); } + * + * console.log(inflate.result); + * ``` + **/ +function Inflate(options) { + if (!(this instanceof Inflate)) return new Inflate(options); - ts.writechunk = null; - ts.writecb = null; + this.options = utils.assign({ + chunkSize: 16384, + windowBits: 0, + to: '' + }, options || {}); - if (data !== null && data !== undefined) stream.push(data); + var opt = this.options; - cb(er); - - var rs = stream._readableState; - rs.reading = false; - if (rs.needReadable || rs.length < rs.highWaterMark) { - stream._read(rs.highWaterMark); - } -} - -function Transform(options) { - if (!(this instanceof Transform)) return new Transform(options); - - Duplex.call(this, options); - - this._transformState = new TransformState(this); - - var stream = this; - - // start out asking for a readable event once data is transformed. - this._readableState.needReadable = true; - - // we have implemented the _read method, and done the other things - // that Readable wants before the first _read call, so unset the - // sync guard flag. - this._readableState.sync = false; - - if (options) { - if (typeof options.transform === 'function') this._transform = options.transform; - - if (typeof options.flush === 'function') this._flush = options.flush; + // Force window size for `raw` data, if not set directly, + // because we have no header for autodetect. + if (opt.raw && (opt.windowBits >= 0) && (opt.windowBits < 16)) { + opt.windowBits = -opt.windowBits; + if (opt.windowBits === 0) { opt.windowBits = -15; } } - // When the writable side finishes, then flush out anything remaining. - this.once('prefinish', function () { - if (typeof this._flush === 'function') this._flush(function (er, data) { - done(stream, er, data); - });else done(stream); - }); + // If `windowBits` not defined (and mode not raw) - set autodetect flag for gzip/deflate + if ((opt.windowBits >= 0) && (opt.windowBits < 16) && + !(options && options.windowBits)) { + opt.windowBits += 32; + } + + // Gzip header has no info about windows size, we can do autodetect only + // for deflate. So, if window size not set, force it to max when gzip possible + if ((opt.windowBits > 15) && (opt.windowBits < 48)) { + // bit 3 (16) -> gzipped data + // bit 4 (32) -> autodetect gzip/deflate + if ((opt.windowBits & 15) === 0) { + opt.windowBits |= 15; + } + } + + this.err = 0; // error code, if happens (0 = Z_OK) + this.msg = ''; // error message + this.ended = false; // used to avoid multiple onEnd() calls + this.chunks = []; // chunks of compressed data + + this.strm = new ZStream(); + this.strm.avail_out = 0; + + var status = zlib_inflate.inflateInit2( + this.strm, + opt.windowBits + ); + + if (status !== c.Z_OK) { + throw new Error(msg[status]); + } + + this.header = new GZheader(); + + zlib_inflate.inflateGetHeader(this.strm, this.header); } -Transform.prototype.push = function (chunk, encoding) { - this._transformState.needTransform = false; - return Duplex.prototype.push.call(this, chunk, encoding); -}; +/** + * Inflate#push(data[, mode]) -> Boolean + * - data (Uint8Array|Array|ArrayBuffer|String): input data + * - mode (Number|Boolean): 0..6 for corresponding Z_NO_FLUSH..Z_TREE modes. + * See constants. Skipped or `false` means Z_NO_FLUSH, `true` meansh Z_FINISH. + * + * Sends input data to inflate pipe, generating [[Inflate#onData]] calls with + * new output chunks. Returns `true` on success. The last data block must have + * mode Z_FINISH (or `true`). That will flush internal pending buffers and call + * [[Inflate#onEnd]]. For interim explicit flushes (without ending the stream) you + * can use mode Z_SYNC_FLUSH, keeping the decompression context. + * + * On fail call [[Inflate#onEnd]] with error code and return false. + * + * We strongly recommend to use `Uint8Array` on input for best speed (output + * format is detected automatically). Also, don't skip last param and always + * use the same type in your code (boolean or number). That will improve JS speed. + * + * For regular `Array`-s make sure all elements are [0..255]. + * + * ##### Example + * + * ```javascript + * push(chunk, false); // push one of data chunks + * ... + * push(chunk, true); // push last chunk + * ``` + **/ +Inflate.prototype.push = function (data, mode) { + var strm = this.strm; + var chunkSize = this.options.chunkSize; + var dictionary = this.options.dictionary; + var status, _mode; + var next_out_utf8, tail, utf8str; + var dict; -// This is the part where you do stuff! -// override this function in implementation classes. -// 'chunk' is an input chunk. -// -// Call `push(newChunk)` to pass along transformed output -// to the readable side. You may call 'push' zero or more times. -// -// Call `cb(err)` when you are done with this chunk. If you pass -// an error, then that'll put the hurt on the whole operation. If you -// never call cb(), then you'll never get another chunk. -Transform.prototype._transform = function (chunk, encoding, cb) { - throw new Error('_transform() is not implemented'); -}; + // Flag to properly process Z_BUF_ERROR on testing inflate call + // when we check that all output data was flushed. + var allowBufError = false; -Transform.prototype._write = function (chunk, encoding, cb) { - var ts = this._transformState; - ts.writecb = cb; - ts.writechunk = chunk; - ts.writeencoding = encoding; - if (!ts.transforming) { - var rs = this._readableState; - if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); - } -}; + if (this.ended) { return false; } + _mode = (mode === ~~mode) ? mode : ((mode === true) ? c.Z_FINISH : c.Z_NO_FLUSH); -// Doesn't matter what the args are here. -// _transform does all the work. -// That we got here means that the readable side wants more data. -Transform.prototype._read = function (n) { - var ts = this._transformState; - - if (ts.writechunk !== null && ts.writecb && !ts.transforming) { - ts.transforming = true; - this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + // Convert data if needed + if (typeof data === 'string') { + // Only binary strings can be decompressed on practice + strm.input = strings.binstring2buf(data); + } else if (toString.call(data) === '[object ArrayBuffer]') { + strm.input = new Uint8Array(data); } else { - // mark that we need a transform, so that any data that comes in - // will get processed, now that we've asked for it. - ts.needTransform = true; + strm.input = data; } -}; -function done(stream, er, data) { - if (er) return stream.emit('error', er); + strm.next_in = 0; + strm.avail_in = strm.input.length; - if (data !== null && data !== undefined) stream.push(data); + do { + if (strm.avail_out === 0) { + strm.output = new utils.Buf8(chunkSize); + strm.next_out = 0; + strm.avail_out = chunkSize; + } - // if there's nothing in the write buffer, then that means - // that nothing more will ever be provided - var ws = stream._writableState; - var ts = stream._transformState; + status = zlib_inflate.inflate(strm, c.Z_NO_FLUSH); /* no bad return value */ - if (ws.length) throw new Error('Calling transform done when ws.length != 0'); + if (status === c.Z_NEED_DICT && dictionary) { + // Convert data if needed + if (typeof dictionary === 'string') { + dict = strings.string2buf(dictionary); + } else if (toString.call(dictionary) === '[object ArrayBuffer]') { + dict = new Uint8Array(dictionary); + } else { + dict = dictionary; + } - if (ts.transforming) throw new Error('Calling transform done when still transforming'); + status = zlib_inflate.inflateSetDictionary(this.strm, dict); - return stream.push(null); -} + } -/***/ }), -/* 59 */ -/***/ (function(module, exports, __webpack_require__) { + if (status === c.Z_BUF_ERROR && allowBufError === true) { + status = c.Z_OK; + allowBufError = false; + } -module.exports = __webpack_require__(12).EventEmitter; + if (status !== c.Z_STREAM_END && status !== c.Z_OK) { + this.onEnd(status); + this.ended = true; + return false; + } + if (strm.next_out) { + if (strm.avail_out === 0 || status === c.Z_STREAM_END || (strm.avail_in === 0 && (_mode === c.Z_FINISH || _mode === c.Z_SYNC_FLUSH))) { -/***/ }), -/* 60 */ -/***/ (function(module, exports, __webpack_require__) { + if (this.options.to === 'string') { -// 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. + next_out_utf8 = strings.utf8border(strm.output, strm.next_out); -module.exports = Stream; + tail = strm.next_out - next_out_utf8; + utf8str = strings.buf2string(strm.output, next_out_utf8); -var EE = __webpack_require__(12).EventEmitter; -var inherits = __webpack_require__(10); + // move tail + strm.next_out = tail; + strm.avail_out = chunkSize - tail; + if (tail) { utils.arraySet(strm.output, strm.output, next_out_utf8, tail, 0); } -inherits(Stream, EE); -Stream.Readable = __webpack_require__(21); -Stream.Writable = __webpack_require__(86); -Stream.Duplex = __webpack_require__(81); -Stream.Transform = __webpack_require__(85); -Stream.PassThrough = __webpack_require__(84); + this.onData(utf8str); -// Backwards-compat with node 0.4.x -Stream.Stream = Stream; - - - -// old-style streams. Note that the pipe method (the only relevant -// part of this class) is overridden in the Readable class. - -function Stream() { - EE.call(this); -} - -Stream.prototype.pipe = function(dest, options) { - var source = this; - - function ondata(chunk) { - if (dest.writable) { - if (false === dest.write(chunk) && source.pause) { - source.pause(); + } else { + this.onData(utils.shrinkBuf(strm.output, strm.next_out)); + } } } - } - source.on('data', ondata); - - function ondrain() { - if (source.readable && source.resume) { - source.resume(); + // When no more input data, we should check that internal inflate buffers + // are flushed. The only way to do it when avail_out = 0 - run one more + // inflate pass. But if output data not exists, inflate return Z_BUF_ERROR. + // Here we set flag to process this error properly. + // + // NOTE. Deflate does not return error in this case and does not needs such + // logic. + if (strm.avail_in === 0 && strm.avail_out === 0) { + allowBufError = true; } + + } while ((strm.avail_in > 0 || strm.avail_out === 0) && status !== c.Z_STREAM_END); + + if (status === c.Z_STREAM_END) { + _mode = c.Z_FINISH; } - dest.on('drain', ondrain); - - // If the 'end' option is not supplied, dest.end() will be called when - // source gets the 'end' or 'close' events. Only dest.end() once. - if (!dest._isStdio && (!options || options.end !== false)) { - source.on('end', onend); - source.on('close', onclose); + // Finalize on the last chunk. + if (_mode === c.Z_FINISH) { + status = zlib_inflate.inflateEnd(this.strm); + this.onEnd(status); + this.ended = true; + return status === c.Z_OK; } - var didOnEnd = false; - function onend() { - if (didOnEnd) return; - didOnEnd = true; - - dest.end(); + // callback interim results if Z_SYNC_FLUSH. + if (_mode === c.Z_SYNC_FLUSH) { + this.onEnd(c.Z_OK); + strm.avail_out = 0; + return true; } - - function onclose() { - if (didOnEnd) return; - didOnEnd = true; - - if (typeof dest.destroy === 'function') dest.destroy(); - } - - // don't leave dangling pipes when there are errors. - function onerror(er) { - cleanup(); - if (EE.listenerCount(this, 'error') === 0) { - throw er; // Unhandled stream error in pipe. - } - } - - source.on('error', onerror); - dest.on('error', onerror); - - // remove all the event listeners that were added. - function cleanup() { - source.removeListener('data', ondata); - dest.removeListener('drain', ondrain); - - source.removeListener('end', onend); - source.removeListener('close', onclose); - - source.removeListener('error', onerror); - dest.removeListener('error', onerror); - - source.removeListener('end', cleanup); - source.removeListener('close', cleanup); - - dest.removeListener('close', cleanup); - } - - source.on('end', cleanup); - source.on('close', cleanup); - - dest.on('close', cleanup); - - dest.emit('pipe', source); - - // Allow for unix-like usage: A.pipe(B).pipe(C) - return dest; + return true; }; -/***/ }), -/* 61 */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Inflate#onData(chunk) -> Void + * - chunk (Uint8Array|Array|String): ouput data. Type of array depends + * on js engine support. When string output requested, each chunk + * will be string. + * + * By default, stores data blocks in `chunks[]` property and glue + * those in `onEnd`. Override this handler, if you need another behaviour. + **/ +Inflate.prototype.onData = function (chunk) { + this.chunks.push(chunk); +}; -/* WEBPACK VAR INJECTION */(function(global) {var ClientRequest = __webpack_require__(94) -var extend = __webpack_require__(104) -var statusCodes = __webpack_require__(75) -var url = __webpack_require__(63) -var http = exports +/** + * Inflate#onEnd(status) -> Void + * - status (Number): inflate status. 0 (Z_OK) on success, + * other if not. + * + * Called either after you tell inflate that the input stream is + * complete (Z_FINISH) or should be flushed (Z_SYNC_FLUSH) + * or if an error happened. By default - join collected chunks, + * free memory and fill `results` / `err` properties. + **/ +Inflate.prototype.onEnd = function (status) { + // On success - join + if (status === c.Z_OK) { + if (this.options.to === 'string') { + // Glue & convert here, until we teach pako to send + // utf8 alligned strings to onData + this.result = this.chunks.join(''); + } else { + this.result = utils.flattenChunks(this.chunks); + } + } + this.chunks = []; + this.err = status; + this.msg = this.strm.msg; +}; -http.request = function (opts, cb) { - if (typeof opts === 'string') - opts = url.parse(opts) - else - opts = extend(opts) - // Normally, the page is loaded from http or https, so not specifying a protocol - // will result in a (valid) protocol-relative url. However, this won't work if - // the protocol is something else, like 'file:' - var defaultProtocol = global.location.protocol.search(/^https?:$/) === -1 ? 'http:' : '' +/** + * inflate(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Decompress `data` with inflate/ungzip and `options`. Autodetect + * format via wrapper header by default. That's why we don't provide + * separate `ungzip` method. + * + * Supported options are: + * + * - windowBits + * + * [http://zlib.net/manual.html#Advanced](http://zlib.net/manual.html#Advanced) + * for more information. + * + * Sugar (options): + * + * - `raw` (Boolean) - say that we work with raw stream, if you don't wish to specify + * negative windowBits implicitly. + * - `to` (String) - if equal to 'string', then result will be converted + * from utf8 to utf16 (javascript) string. When string output requested, + * chunk length can differ from `chunkSize`, depending on content. + * + * + * ##### Example: + * + * ```javascript + * var pako = require('pako') + * , input = pako.deflate([1,2,3,4,5,6,7,8,9]) + * , output; + * + * try { + * output = pako.inflate(input); + * } catch (err) + * console.log(err); + * } + * ``` + **/ +function inflate(input, options) { + var inflator = new Inflate(options); - var protocol = opts.protocol || defaultProtocol - var host = opts.hostname || opts.host - var port = opts.port - var path = opts.path || '/' + inflator.push(input, true); - // Necessary for IPv6 addresses - if (host && host.indexOf(':') !== -1) - host = '[' + host + ']' + // That will never happens, if you don't cheat with options :) + if (inflator.err) { throw inflator.msg || msg[inflator.err]; } - // This may be a relative url. The browser should always be able to interpret it correctly. - opts.url = (host ? (protocol + '//' + host) : '') + (port ? ':' + port : '') + path - opts.method = (opts.method || 'GET').toUpperCase() - opts.headers = opts.headers || {} - - // Also valid opts.auth, opts.mode - - var req = new ClientRequest(opts) - if (cb) - req.on('response', cb) - return req + return inflator.result; } -http.get = function get (opts, cb) { - var req = http.request(opts, cb) - req.end() - return req + +/** + * inflateRaw(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * The same as [[inflate]], but creates raw data, without wrapper + * (header and adler32 crc). + **/ +function inflateRaw(input, options) { + options = options || {}; + options.raw = true; + return inflate(input, options); } -http.Agent = function () {} -http.Agent.defaultMaxSockets = 4 -http.STATUS_CODES = statusCodes +/** + * ungzip(data[, options]) -> Uint8Array|Array|String + * - data (Uint8Array|Array|String): input data to decompress. + * - options (Object): zlib inflate options. + * + * Just shortcut to [[inflate]], because it autodetects format + * by header.content. Done for convenience. + **/ -http.METHODS = [ - 'CHECKOUT', - 'CONNECT', - 'COPY', - 'DELETE', - 'GET', - 'HEAD', - 'LOCK', - 'M-SEARCH', - 'MERGE', - 'MKACTIVITY', - 'MKCOL', - 'MOVE', - 'NOTIFY', - 'OPTIONS', - 'PATCH', - 'POST', - 'PROPFIND', - 'PROPPATCH', - 'PURGE', - 'PUT', - 'REPORT', - 'SEARCH', - 'SUBSCRIBE', - 'TRACE', - 'UNLOCK', - 'UNSUBSCRIBE' -] -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8))) -/***/ }), -/* 62 */ -/***/ (function(module, exports, __webpack_require__) { +exports.Inflate = Inflate; +exports.inflate = inflate; +exports.inflateRaw = inflateRaw; +exports.ungzip = inflate; -/* WEBPACK VAR INJECTION */(function(global) {exports.fetch = isFunction(global.fetch) && isFunction(global.ReadableStream) -exports.blobConstructor = false -try { - new Blob([new ArrayBuffer(1)]) - exports.blobConstructor = true -} catch (e) {} - -// The xhr request to example.com may violate some restrictive CSP configurations, -// so if we're running in a browser that supports `fetch`, avoid calling getXHR() -// and assume support for certain features below. -var xhr -function getXHR () { - // Cache the xhr value - if (xhr !== undefined) return xhr - - if (global.XMLHttpRequest) { - xhr = new global.XMLHttpRequest() - // If XDomainRequest is available (ie only, where xhr might not work - // cross domain), use the page location. Otherwise use example.com - // Note: this doesn't actually make an http request. - try { - xhr.open('GET', global.XDomainRequest ? '/' : 'https://example.com') - } catch(e) { - xhr = null - } - } else { - // Service workers don't have XHR - xhr = null - } - return xhr -} - -function checkTypeSupport (type) { - var xhr = getXHR() - if (!xhr) return false - try { - xhr.responseType = type - return xhr.responseType === type - } catch (e) {} - return false -} - -// For some strange reason, Safari 7.0 reports typeof global.ArrayBuffer === 'object'. -// Safari 7.1 appears to have fixed this bug. -var haveArrayBuffer = typeof global.ArrayBuffer !== 'undefined' -var haveSlice = haveArrayBuffer && isFunction(global.ArrayBuffer.prototype.slice) - -// If fetch is supported, then arraybuffer will be supported too. Skip calling -// checkTypeSupport(), since that calls getXHR(). -exports.arraybuffer = exports.fetch || (haveArrayBuffer && checkTypeSupport('arraybuffer')) - -// These next two tests unavoidably show warnings in Chrome. Since fetch will always -// be used if it's available, just return false for these to avoid the warnings. -exports.msstream = !exports.fetch && haveSlice && checkTypeSupport('ms-stream') -exports.mozchunkedarraybuffer = !exports.fetch && haveArrayBuffer && - checkTypeSupport('moz-chunked-arraybuffer') - -// If fetch is supported, then overrideMimeType will be supported too. Skip calling -// getXHR(). -exports.overrideMimeType = exports.fetch || (getXHR() ? isFunction(getXHR().overrideMimeType) : false) - -exports.vbArray = isFunction(global.VBArray) - -function isFunction (value) { - return typeof value === 'function' -} - -xhr = null // Help gc - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(8))) - -/***/ }), -/* 63 */ -/***/ (function(module, exports, __webpack_require__) { +/***/ }, +/* 71 */ +/***/ function(module, exports, __webpack_require__) { "use strict"; -// Copyright Joyent, Inc. and other Node contributors. + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin // -// 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: +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. // -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: // -// 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. +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = __webpack_require__(5); +var trees = __webpack_require__(76); +var adler32 = __webpack_require__(45); +var crc32 = __webpack_require__(47); +var msg = __webpack_require__(22); + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ +/* Allowed flush values; see deflate() and inflate() below for details */ +var Z_NO_FLUSH = 0; +var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +//var Z_TREES = 6; -var punycode = __webpack_require__(78); -var util = __webpack_require__(98); -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +//var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +//var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; -exports.Url = Url; -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; +/* compression levels */ +//var Z_NO_COMPRESSION = 0; +//var Z_BEST_SPEED = 1; +//var Z_BEST_COMPRESSION = 9; +var Z_DEFAULT_COMPRESSION = -1; + + +var Z_FILTERED = 1; +var Z_HUFFMAN_ONLY = 2; +var Z_RLE = 3; +var Z_FIXED = 4; +var Z_DEFAULT_STRATEGY = 0; + +/* Possible values of the data_type field (though see inflate()) */ +//var Z_BINARY = 0; +//var Z_TEXT = 1; +//var Z_ASCII = 1; // = Z_TEXT +var Z_UNKNOWN = 2; + + +/* The deflate compression method */ +var Z_DEFLATED = 8; + +/*============================================================================*/ + + +var MAX_MEM_LEVEL = 9; +/* Maximum value for memLevel in deflateInit2 */ +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_MEM_LEVEL = 8; + + +var LENGTH_CODES = 29; +/* number of length codes, not counting the special END_BLOCK code */ +var LITERALS = 256; +/* number of literal bytes 0..255 */ +var L_CODES = LITERALS + 1 + LENGTH_CODES; +/* number of Literal or Length codes, including the END_BLOCK code */ +var D_CODES = 30; +/* number of distance codes */ +var BL_CODES = 19; +/* number of codes used to transfer the bit lengths */ +var HEAP_SIZE = 2 * L_CODES + 1; +/* maximum heap size */ +var MAX_BITS = 15; +/* All codes must not exceed MAX_BITS bits */ + +var MIN_MATCH = 3; +var MAX_MATCH = 258; +var MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1); + +var PRESET_DICT = 0x20; + +var INIT_STATE = 42; +var EXTRA_STATE = 69; +var NAME_STATE = 73; +var COMMENT_STATE = 91; +var HCRC_STATE = 103; +var BUSY_STATE = 113; +var FINISH_STATE = 666; + +var BS_NEED_MORE = 1; /* block not completed, need more input or more output */ +var BS_BLOCK_DONE = 2; /* block flush performed */ +var BS_FINISH_STARTED = 3; /* finish started, need only more output at next deflate */ +var BS_FINISH_DONE = 4; /* finish done, accept no more input or output */ + +var OS_CODE = 0x03; // Unix :) . Don't detect, use this default. + +function err(strm, errorCode) { + strm.msg = msg[errorCode]; + return errorCode; } -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // Special case for a simple path URL - simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = __webpack_require__(35); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && util.isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; +function rank(f) { + return ((f) << 1) - ((f) > 4 ? 9 : 0); } -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!util.isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); +function zero(buf) { var len = buf.length; while (--len >= 0) { buf[len] = 0; } } + + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->output buffer and copying into it. + * (See also read_buf()). + */ +function flush_pending(strm) { + var s = strm.state; + + //_tr_flush_bits(s); + var len = s.pending; + if (len > strm.avail_out) { + len = strm.avail_out; } - - // Copy chrome, IE, opera backslash-handling behavior. - // Back slashes before the query string get converted to forward slashes - // See: https://code.google.com/p/chromium/issues/detail?id=25916 - var queryIndex = url.indexOf('?'), - splitter = - (queryIndex !== -1 && queryIndex < url.indexOf('#')) ? '?' : '#', - uSplit = url.split(splitter), - slashRegex = /\\/g; - uSplit[0] = uSplit[0].replace(slashRegex, '/'); - url = uSplit.join(splitter); - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - if (!slashesDenoteHost && url.split('#').length === 1) { - // Try fast path regexp - var simplePath = simplePathPattern.exec(rest); - if (simplePath) { - this.path = rest; - this.href = rest; - this.pathname = simplePath[1]; - if (simplePath[2]) { - this.search = simplePath[2]; - if (parseQueryString) { - this.query = querystring.parse(this.search.substr(1)); - } else { - this.query = this.search.substr(1); - } - } else if (parseQueryString) { - this.search = ''; - this.query = {}; - } - return this; - } - } - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a punycoded representation of "domain". - // It only converts parts of the domain name that - // have non-ASCII characters, i.e. it doesn't matter if - // you call it with a domain that already is ASCII-only. - this.hostname = punycode.toASCII(this.hostname); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - if (rest.indexOf(ae) === -1) - continue; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (util.isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - util.isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (util.isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - var tkeys = Object.keys(this); - for (var tk = 0; tk < tkeys.length; tk++) { - var tkey = tkeys[tk]; - result[tkey] = this[tkey]; - } - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - var rkeys = Object.keys(relative); - for (var rk = 0; rk < rkeys.length; rk++) { - var rkey = rkeys[rk]; - if (rkey !== 'protocol') - result[rkey] = relative[rkey]; - } - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - var keys = Object.keys(relative); - for (var v = 0; v < keys.length; v++) { - var k = keys[v]; - result[k] = relative[k]; - } - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!util.isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especially happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!util.isNull(result.pathname) || !util.isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host || srcPath.length > 1) && - (last === '.' || last === '..') || last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last === '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especially happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!util.isNull(result.pathname) || !util.isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - - -/***/ }), -/* 64 */ -/***/ (function(module, exports, __webpack_require__) { - -// 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. - -var Buffer = __webpack_require__(5).Buffer; - -var isBufferEncoding = Buffer.isEncoding - || function(encoding) { - switch (encoding && encoding.toLowerCase()) { - case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; - default: return false; - } - } - - -function assertEncoding(encoding) { - if (encoding && !isBufferEncoding(encoding)) { - throw new Error('Unknown encoding: ' + encoding); + if (len === 0) { return; } + + utils.arraySet(strm.output, s.pending_buf, s.pending_out, len, strm.next_out); + strm.next_out += len; + s.pending_out += len; + strm.total_out += len; + strm.avail_out -= len; + s.pending -= len; + if (s.pending === 0) { + s.pending_out = 0; } } -// StringDecoder provides an interface for efficiently splitting a series of -// buffers into a series of JS strings without breaking apart multi-byte -// characters. CESU-8 is handled as part of the UTF-8 encoding. -// -// @TODO Handling all encodings inside a single object makes it very difficult -// to reason about this code, so it should be split up in the future. -// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code -// points as used by CESU-8. -var StringDecoder = exports.StringDecoder = function(encoding) { - this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); - assertEncoding(encoding); - switch (this.encoding) { - case 'utf8': - // CESU-8 represents each of Surrogate Pair by 3-bytes - this.surrogateSize = 3; - break; - case 'ucs2': - case 'utf16le': - // UTF-16 represents each of Surrogate Pair by 2-bytes - this.surrogateSize = 2; - this.detectIncompleteChar = utf16DetectIncompleteChar; - break; - case 'base64': - // Base-64 stores 3 bytes in 4 chars, and pads the remainder. - this.surrogateSize = 3; - this.detectIncompleteChar = base64DetectIncompleteChar; - break; - default: - this.write = passThroughWrite; - return; + +function flush_block_only(s, last) { + trees._tr_flush_block(s, (s.block_start >= 0 ? s.block_start : -1), s.strstart - s.block_start, last); + s.block_start = s.strstart; + flush_pending(s.strm); +} + + +function put_byte(s, b) { + s.pending_buf[s.pending++] = b; +} + + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +function putShortMSB(s, b) { +// put_byte(s, (Byte)(b >> 8)); +// put_byte(s, (Byte)(b & 0xff)); + s.pending_buf[s.pending++] = (b >>> 8) & 0xff; + s.pending_buf[s.pending++] = b & 0xff; +} + + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->input buffer and copying from it. + * (See also flush_pending()). + */ +function read_buf(strm, buf, start, size) { + var len = strm.avail_in; + + if (len > size) { len = size; } + if (len === 0) { return 0; } + + strm.avail_in -= len; + + // zmemcpy(buf, strm->next_in, len); + utils.arraySet(buf, strm.input, strm.next_in, len, start); + if (strm.state.wrap === 1) { + strm.adler = adler32(strm.adler, buf, len, start); } - // Enough space to store all bytes of a single character. UTF-8 needs 4 - // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). - this.charBuffer = new Buffer(6); - // Number of bytes received for the current incomplete multi-byte character. - this.charReceived = 0; - // Number of bytes expected for the current incomplete multi-byte character. - this.charLength = 0; -}; + else if (strm.state.wrap === 2) { + strm.adler = crc32(strm.adler, buf, len, start); + } + + strm.next_in += len; + strm.total_in += len; + + return len; +} -// write decodes the given buffer and returns it as JS string that is -// guaranteed to not contain any partial multi-byte characters. Any partial -// character found at the end of the buffer is buffered up, and will be -// returned when calling write again with the remaining bytes. -// -// Note: Converting a Buffer containing an orphan surrogate to a String -// currently works, but converting a String to a Buffer (via `new Buffer`, or -// Buffer#write) will replace incomplete surrogates with the unicode -// replacement character. See https://codereview.chromium.org/121173009/ . -StringDecoder.prototype.write = function(buffer) { - var charStr = ''; - // if our last write ended with an incomplete multibyte character - while (this.charLength) { - // determine how many remaining bytes this buffer has to offer for this char - var available = (buffer.length >= this.charLength - this.charReceived) ? - this.charLength - this.charReceived : - buffer.length; +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +function longest_match(s, cur_match) { + var chain_length = s.max_chain_length; /* max hash chain length */ + var scan = s.strstart; /* current string */ + var match; /* matched string */ + var len; /* length of current match */ + var best_len = s.prev_length; /* best match length so far */ + var nice_match = s.nice_match; /* stop if match long enough */ + var limit = (s.strstart > (s.w_size - MIN_LOOKAHEAD)) ? + s.strstart - (s.w_size - MIN_LOOKAHEAD) : 0/*NIL*/; - // add the new bytes to the char buffer - buffer.copy(this.charBuffer, this.charReceived, 0, available); - this.charReceived += available; + var _win = s.window; // shortcut - if (this.charReceived < this.charLength) { - // still not enough chars in this buffer? wait for more ... - return ''; - } + var wmask = s.w_mask; + var prev = s.prev; - // remove bytes belonging to the current character from the buffer - buffer = buffer.slice(available, buffer.length); + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ - // get the character that was split - charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + var strend = s.strstart + MAX_MATCH; + var scan_end1 = _win[scan + best_len - 1]; + var scan_end = _win[scan + best_len]; - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - var charCode = charStr.charCodeAt(charStr.length - 1); - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - this.charLength += this.surrogateSize; - charStr = ''; + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + // Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s.prev_length >= s.good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if (nice_match > s.lookahead) { nice_match = s.lookahead; } + + // Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + // Assert(cur_match < s->strstart, "no future"); + match = cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2. Note that the checks below + * for insufficient lookahead only occur occasionally for performance + * reasons. Therefore uninitialized memory will be accessed, and + * conditional jumps will be made that depend on those values. + * However the length of the match is limited to the lookahead, so + * the output of deflate is not affected by the uninitialized values. + */ + + if (_win[match + best_len] !== scan_end || + _win[match + best_len - 1] !== scan_end1 || + _win[match] !== _win[scan] || + _win[++match] !== _win[scan + 1]) { continue; } - this.charReceived = this.charLength = 0; - // if there are no more bytes in this buffer, just emit our char - if (buffer.length === 0) { - return charStr; - } - break; - } - - // determine and set charLength / charReceived - this.detectIncompleteChar(buffer); - - var end = buffer.length; - if (this.charLength) { - // buffer the incomplete character bytes we got - buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); - end -= this.charReceived; - } - - charStr += buffer.toString(this.encoding, 0, end); - - var end = charStr.length - 1; - var charCode = charStr.charCodeAt(end); - // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character - if (charCode >= 0xD800 && charCode <= 0xDBFF) { - var size = this.surrogateSize; - this.charLength += size; - this.charReceived += size; - this.charBuffer.copy(this.charBuffer, size, 0, size); - buffer.copy(this.charBuffer, 0, 0, size); - return charStr.substring(0, end); - } - - // or just emit the charStr - return charStr; -}; - -// detectIncompleteChar determines if there is an incomplete UTF-8 character at -// the end of the given buffer. If so, it sets this.charLength to the byte -// length that character, and sets this.charReceived to the number of bytes -// that are available for this character. -StringDecoder.prototype.detectIncompleteChar = function(buffer) { - // determine how many bytes we have to check at the end of this buffer - var i = (buffer.length >= 3) ? 3 : buffer.length; - - // Figure out if one of the last i bytes of our buffer announces an - // incomplete char. - for (; i > 0; i--) { - var c = buffer[buffer.length - i]; - - // See http://en.wikipedia.org/wiki/UTF-8#Description - - // 110XXXXX - if (i == 1 && c >> 5 == 0x06) { - this.charLength = 2; - break; - } - - // 1110XXXX - if (i <= 2 && c >> 4 == 0x0E) { - this.charLength = 3; - break; - } - - // 11110XXX - if (i <= 3 && c >> 3 == 0x1E) { - this.charLength = 4; - break; - } - } - this.charReceived = i; -}; - -StringDecoder.prototype.end = function(buffer) { - var res = ''; - if (buffer && buffer.length) - res = this.write(buffer); - - if (this.charReceived) { - var cr = this.charReceived; - var buf = this.charBuffer; - var enc = this.encoding; - res += buf.slice(0, cr).toString(enc); - } - - return res; -}; - -function passThroughWrite(buffer) { - return buffer.toString(this.encoding); -} - -function utf16DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 2; - this.charLength = this.charReceived ? 2 : 0; -} - -function base64DetectIncompleteChar(buffer) { - this.charReceived = buffer.length % 3; - this.charLength = this.charReceived ? 3 : 0; -} - - -/***/ }), -/* 65 */ -/***/ (function(module, exports, __webpack_require__) { - -const UserAgentManager = __webpack_require__(140); -const RESTMethods = __webpack_require__(137); -const SequentialRequestHandler = __webpack_require__(139); -const BurstRequestHandler = __webpack_require__(138); -const APIRequest = __webpack_require__(136); -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; - } - - destroy() { - for (const handlerID in this.handlers) { - this.handlers[handlerID].destroy(); - } - } - - 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; - - -/***/ }), -/* 66 */ -/***/ (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} + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. */ - this.restManager = restManager; + scan += 2; + match++; + // Assert(*scan == *match, "match[2]?"); - /** - * A list of requests that have yet to be processed. - * @type {APIRequest[]} + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. */ - this.queue = []; - } + do { + /*jshint noempty:false*/ + } while (_win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + _win[++scan] === _win[++match] && _win[++scan] === _win[++match] && + scan < strend); - /** - * Whether or not the client is being rate limited on every endpoint. - * @type {boolean} - * @readonly - */ - get globalLimit() { - return this.restManager.globallyRateLimited; - } + // Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); - set globalLimit(value) { - this.restManager.globallyRateLimited = value; - } + len = MAX_MATCH - (strend - scan); + scan = strend - MAX_MATCH; - /** - * 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() {} // eslint-disable-line no-empty-function - - destroy() { - this.queue = []; - } -} - -module.exports = RequestHandler; - - -/***/ }), -/* 67 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(Buffer) {const browser = __webpack_require__(23).platform() === 'browser'; -const EventEmitter = __webpack_require__(12); -const Constants = __webpack_require__(0); -const zlib = __webpack_require__(27); -const PacketManager = __webpack_require__(142); -const erlpack = (function findErlpack() { - try { - const e = __webpack_require__(187); - if (!e.pack) return null; - return e; - } catch (e) { - return null; - } -}()); - -const WebSocket = (function findWebSocket() { - if (browser) return window.WebSocket; // eslint-disable-line no-undef - try { - return __webpack_require__(188); - } catch (e) { - return __webpack_require__(189); - } -}()); - -/** - * Abstracts a WebSocket connection with decoding/encoding for the discord gateway - * @private - */ -class WebSocketConnection extends EventEmitter { - /** - * @param {WebSocketManager} manager the WebSocket manager - * @param {string} gateway Websocket gateway to connect to - */ - constructor(manager, gateway) { - super(); - /** - * WebSocket Manager of this connection - * @type {WebSocketManager} - */ - this.manager = manager; - /** - * Client this belongs to - * @type {Client} - */ - this.client = manager.client; - /** - * WebSocket connection itself - * @type {WebSocket} - */ - this.ws = null; - /** - * Current sequence of the WebSocket - * @type {number} - */ - this.sequence = -1; - /** - * Current status of the client - * @type {number} - */ - this.status = Constants.Status.IDLE; - /** - * Packet Manager of the connection - * @type {WebSocketPacketManager} - */ - this.packetManager = new PacketManager(this); - /** - * Last time a ping was sent (a timestamp) - * @type {number} - */ - this.lastPingTimestamp = 0; - /** - * Contains the rate limit queue and metadata - * @type {Object} - */ - this.ratelimit = { - queue: [], - remaining: 120, - resetTime: -1, - }; - this.connect(gateway); - /** - * Events that are disabled (will not be processed) - * @type {Object} - */ - this.disabledEvents = {}; - /** - * Sequence on WebSocket close - * @type {number} - */ - this.closeSequence = 0; - for (const event of this.client.options.disabledEvents) this.disabledEvents[event] = true; - } - - /** - * Causes the client to be marked as ready and emits the ready event - * @returns {void} - */ - triggerReady() { - if (this.status === Constants.Status.READY) { - this.debug('Tried to mark self as ready, but already ready'); - return; - } - this.status = Constants.Status.READY; - this.client.emit(Constants.Events.READY); - this.packetManager.handleQueue(); - } - - /** - * Checks whether the client is ready to be marked as ready - * @returns {void} - */ - checkIfReady() { - if (this.status === Constants.Status.READY || this.status === Constants.Status.NEARLY) return false; - let unavailableGuilds = 0; - for (const guild of this.client.guilds.values()) { - if (!guild.available) unavailableGuilds++; - } - if (unavailableGuilds === 0) { - this.status = Constants.Status.NEARLY; - if (!this.client.options.fetchAllMembers) return this.triggerReady(); - // Fetch all members before marking self as ready - const promises = this.client.guilds.map(g => g.fetchMembers()); - Promise.all(promises) - .then(() => this.triggerReady()) - .catch(e => { - this.debug(`Failed to fetch all members before ready! ${e}`); - this.triggerReady(); - }); - } - return true; - } - - // Util - /** - * Emits a debug message - * @param {string} message Debug message - * @returns {void} - */ - debug(message) { - if (message instanceof Error) message = message.stack; - return this.manager.debug(`[connection] ${message}`); - } - - /** - * Attempts to serialise data from the WebSocket - * @param {string|Object} data Data to unpack - * @returns {Object} - */ - unpack(data) { - if (erlpack && typeof data !== 'string') { - if (data instanceof ArrayBuffer) data = Buffer.from(new Uint8Array(data)); - return erlpack.unpack(data); - } else if (data instanceof ArrayBuffer || data instanceof Buffer) { - data = zlib.inflateSync(data).toString(); - } - return JSON.parse(data); - } - - /** - * Packs an object ready to be sent - * @param {Object} data Data to pack - * @returns {string|Buffer} - */ - pack(data) { - return erlpack ? erlpack.pack(data) : JSON.stringify(data); - } - - /** - * Processes the current WebSocket queue - */ - processQueue() { - if (this.ratelimit.remaining === 0) return; - if (this.ratelimit.queue.length === 0) return; - if (this.ratelimit.remaining === 120) { - this.ratelimit.resetTimer = setTimeout(() => { - this.ratelimit.remaining = 120; - this.processQueue(); - }, 120e3); // eslint-disable-line - } - while (this.ratelimit.remaining > 0) { - const item = this.ratelimit.queue.shift(); - if (!item) return; - this._send(item); - this.ratelimit.remaining--; - } - } - - /** - * Sends data, bypassing the queue - * @param {Object} data Packet to send - * @returns {void} - */ - _send(data) { - if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { - this.debug(`Tried to send packet ${data} but no WebSocket is available!`); - return; - } - this.ws.send(this.pack(data)); - } - - /** - * Adds data to the queue to be sent - * @param {Object} data Packet to send - * @returns {void} - */ - send(data) { - if (!this.ws || this.ws.readyState !== WebSocket.OPEN) { - this.debug(`Tried to send packet ${data} but no WebSocket is available!`); - return; - } - this.ratelimit.queue.push(data); - this.processQueue(); - } - - /** - * Creates a connection to a gateway - * @param {string} gateway Gateway to connect to - * @param {number} [after=0] How long to wait before connecting - * @param {boolean} [force=false] Whether or not to force a new connection even if one already exists - * @returns {boolean} - */ - connect(gateway = this.gateway, after = 0, force = false) { - if (after) return this.client.setTimeout(() => this.connect(gateway, 0, force), after); // eslint-disable-line - if (this.ws && !force) { - this.debug('WebSocket connection already exists'); - return false; - } else if (typeof gateway !== 'string') { - this.debug(`Tried to connect to an invalid gateway: ${gateway}`); - return false; - } - this.gateway = gateway; - this.debug(`Connecting to ${gateway}`); - const ws = this.ws = new WebSocket(gateway); - if (browser) ws.binaryType = 'arraybuffer'; - ws.onmessage = this.onMessage.bind(this); - ws.onopen = this.onOpen.bind(this); - ws.onerror = this.onError.bind(this); - ws.onclose = this.onClose.bind(this); - this.status = Constants.Status.CONNECTING; - return true; - } - - /** - * Destroys the connection - * @returns {boolean} - */ - destroy() { - const ws = this.ws; - if (!ws) { - this.debug('Attempted to destroy WebSocket but no connection exists!'); - return false; - } - this.heartbeat(-1); - ws.close(1000); - this.packetManager.handleQueue(); - this.ws = null; - this.status = Constants.Status.DISCONNECTED; - return true; - } - - /** - * Called whenever a message is received - * @param {Event} event Event received - * @returns {boolean} - */ - onMessage(event) { - try { - this.onPacket(this.unpack(event.data)); - return true; - } catch (err) { - this.debug(err); - return false; - } - } - - /** - * Sets the current sequence of the connection - * @param {number} s New sequence - */ - setSequence(s) { - this.sequence = s > this.sequence ? s : this.sequence; - } - - /** - * Called whenever a packet is received - * @param {Object} packet received packet - * @returns {boolean} - */ - onPacket(packet) { - if (!packet) { - this.debug('Received null packet'); - return false; - } - this.client.emit('raw', packet); - switch (packet.op) { - case Constants.OPCodes.HELLO: - return this.heartbeat(packet.d.heartbeat_interval); - case Constants.OPCodes.RECONNECT: - return this.reconnect(); - case Constants.OPCodes.INVALID_SESSION: - if (!packet.d) this.sessionID = null; - this.debug('Session invalidated -- will identify with a new session'); - return this.identify(packet.d ? 2500 : 0); - case Constants.OPCodes.HEARTBEAT_ACK: - return this.ackHeartbeat(); - case Constants.OPCodes.HEARTBEAT: - return this.heartbeat(); - default: - return this.packetManager.handle(packet); - } - } - - /** - * Called whenever a connection is opened to the gateway - * @param {Event} event Received open event - */ - onOpen(event) { - this.gateway = event.target.url; - this.debug(`Connected to gateway ${this.gateway}`); - this.identify(); - } - - /** - * Causes a reconnection to the gateway - */ - reconnect() { - this.debug('Attemping to reconnect in 5500ms...'); - this.client.emit(Constants.Events.RECONNECTING); - this.connect(this.gateway, 5500, true); - } - - /** - * Called whenever an error occurs with the WebSocket - * @param {Error} error Error that occurred - */ - onError(error) { - this.client.emit(Constants.Events.ERROR, error); - } - - /** - * @external CloseEvent - * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent} - */ - - /** - * Called whenever a connection to the gateway is closed - * @param {CloseEvent} event Close event that was received - */ - onClose(event) { - this.debug(`Closed: ${event.code}`); - this.closeSequence = this.sequence; - // Reset the state before trying to fix anything - this.emit('close', event); - this.heartbeat(-1); - // Should we reconnect? - if (Constants.WSCodes[event.code]) { - this.debug(Constants.WSCodes[event.code]); - this.destroy(); - return; - } - this.reconnect(); - } - - // Heartbeat - /** - * Acknowledges a heartbeat - */ - ackHeartbeat() { - this.debug(`Heartbeat acknowledged, latency of ${Date.now() - this.lastPingTimestamp}ms`); - this.client._pong(this.lastPingTimestamp); - } - - /** - * Sends a heartbeat or sets an interval for sending heartbeats. - * @param {number} [time] If -1, clears the interval, any other number sets an interval. - * If no value is given, a heartbeat will be sent instantly. - */ - heartbeat(time) { - if (!isNaN(time)) { - if (time === -1) { - this.debug('Clearing heartbeat interval'); - this.client.clearInterval(this.heartbeatInterval); - this.heartbeatInterval = null; - } else { - this.debug(`Setting a heartbeat interval for ${time}ms`); - this.heartbeatInterval = this.client.setInterval(() => this.heartbeat(), time); + if (len > best_len) { + s.match_start = cur_match; + best_len = len; + if (len >= nice_match) { + break; } - return; + scan_end1 = _win[scan + best_len - 1]; + scan_end = _win[scan + best_len]; } - this.debug('Sending a heartbeat'); - this.lastPingTimestamp = Date.now(); - this.send({ - op: Constants.OPCodes.HEARTBEAT, - d: this.sequence, - }); - } - - // Identification - /** - * Identifies the client on a connection - * @param {number} [after] How long to wait before identifying - * @returns {void} - */ - identify(after) { - if (after) return this.client.setTimeout(this.identify.apply(this), after); - return this.sessionID ? this.identifyResume() : this.identifyNew(); - } - - /** - * Identifies as a new connection on the gateway - * @returns {void} - */ - identifyNew() { - if (!this.client.token) { - this.debug('No token available to identify a new session with'); - return; - } - // Clone the generic payload and assign the token - const d = Object.assign({ token: this.client.token }, this.client.options.ws); - - // Sharding stuff - const { shardId, shardCount } = this.client.options; - if (shardCount > 0) d.shard = [Number(shardId), Number(shardCount)]; - - // Send the payload - this.debug('Identifying as a new session'); - this.send({ op: Constants.OPCodes.IDENTIFY, d }); - } - - /** - * Resumes a session on the gateway - * @returns {void} - */ - identifyResume() { - if (!this.sessionID) { - this.debug('Warning: wanted to resume but session ID not available; identifying as a new session instead'); - return this.identifyNew(); - } - this.debug(`Attempting to resume session ${this.sessionID}`); - - const d = { - token: this.client.token, - session_id: this.sessionID, - seq: this.sequence, - }; - - return this.send({ - op: Constants.OPCodes.RESUME, - d, - }); + } while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length !== 0); + + if (best_len <= s.lookahead) { + return best_len; } + return s.lookahead; } -/** - * Encoding the WebSocket connections will use - * @type {string} + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). */ -WebSocketConnection.ENCODING = erlpack ? 'etf' : 'json'; -WebSocketConnection.WebSocket = WebSocket; +function fill_window(s) { + var _w_size = s.w_size; + var p, n, m, more, str; -module.exports = WebSocketConnection; + //Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(5).Buffer)) + do { + more = s.window_size - s.lookahead - s.strstart; -/***/ }), -/* 68 */ -/***/ (function(module, exports, __webpack_require__) { + // JS ints have 32 bit, block below not needed + /* Deal with !@#$% 64K limit: */ + //if (sizeof(int) <= 2) { + // if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + // more = wsize; + // + // } else if (more == (unsigned)(-1)) { + // /* Very unlikely, but possible on 16 bit machine if + // * strstart == 0 && lookahead == 1 (input done a byte at time) + // */ + // more--; + // } + //} -/* WEBPACK VAR INJECTION */(function(process) {const os = __webpack_require__(23); -const EventEmitter = __webpack_require__(12).EventEmitter; -const Constants = __webpack_require__(0); -const Permissions = __webpack_require__(9); -const Util = __webpack_require__(4); -const RESTManager = __webpack_require__(65); -const ClientDataManager = __webpack_require__(105); -const ClientManager = __webpack_require__(106); -const ClientDataResolver = __webpack_require__(38); -const ClientVoiceManager = __webpack_require__(185); -const WebSocketManager = __webpack_require__(141); -const ActionsManager = __webpack_require__(107); -const Collection = __webpack_require__(3); -const Presence = __webpack_require__(11).Presence; -const ShardClientUtil = __webpack_require__(184); -const VoiceBroadcast = __webpack_require__(186); -/** - * The main hub for interacting with the Discord API, and the starting point for any 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} + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. */ - this.options = Util.mergeDefault(Constants.DefaultOptions, options); - this._validateOptions(); + if (s.strstart >= _w_size + (_w_size - MIN_LOOKAHEAD)) { - /** - * The REST manager of the client - * @type {RESTManager} - * @private - */ - this.rest = new RESTManager(this); + utils.arraySet(s.window, s.window, _w_size, _w_size, 0); + s.match_start -= _w_size; + s.strstart -= _w_size; + /* we now have strstart >= MAX_DIST */ + s.block_start -= _w_size; - /** - * 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 {@link ShardingManager}) - * @type {?ShardClientUtil} - */ - this.shard = process.send ? ShardClientUtil.singleton(this) : null; - - /** - * All of the {@link User} objects that have been cached at any point, mapped by their IDs - * @type {Collection} - */ - this.users = new Collection(); - - /** - * All of the guilds the client is currently handling, mapped by their IDs - - * as long as sharding isn't being used, this will be *every* guild the bot is a member of - * @type {Collection} - */ - this.guilds = new Collection(); - - /** - * All of the {@link Channel}s that the client is currently handling, mapped by their IDs - - * as long as sharding isn't being used, this will be *every* channel in *every* guild, and all DM channels - * @type {Collection} - */ - this.channels = new Collection(); - - /** - * Presences that have been received for the client user's friends, mapped by user IDs - * This is only filled when using a user account. - * @type {Collection} - */ - this.presences = new Collection(); - - if (!this.token && 'CLIENT_TOKEN' in process.env) { - /** - * Authorization token for the logged in user/bot - * This should be kept private at all times. - * @type {?string} + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) */ - this.token = process.env.CLIENT_TOKEN; - } else { - this.token = null; + + n = s.hash_size; + p = n; + do { + m = s.head[--p]; + s.head[p] = (m >= _w_size ? m - _w_size : 0); + } while (--n); + + n = _w_size; + p = n; + do { + m = s.prev[--p]; + s.prev[p] = (m >= _w_size ? m - _w_size : 0); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); + + more += _w_size; + } + if (s.strm.avail_in === 0) { + break; } - /** - * User that the client is logged in as - * @type {?ClientUser} + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. */ - this.user = null; + //Assert(more >= 2, "more < 2"); + n = read_buf(s.strm, s.window, s.strstart + s.lookahead, more); + s.lookahead += n; - /** - * Time at which the client was last regarded as being in the `READY` state - * (each time the client disconnects and successfully reconnects, this will be overwritten) - * @type {?Date} - */ - this.readyAt = null; + /* Initialize the hash value now that we have some input: */ + if (s.lookahead + s.insert >= MIN_MATCH) { + str = s.strstart - s.insert; + s.ins_h = s.window[str]; - /** - * Active voice broadcasts that have been created - * @type {VoiceBroadcast[]} - */ - this.broadcasts = []; + /* UPDATE_HASH(s, s->ins_h, s->window[str + 1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + 1]) & s.hash_mask; +//#if MIN_MATCH != 3 +// Call update_hash() MIN_MATCH-3 more times +//#endif + while (s.insert) { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; - /** - * Previous heartbeat pings of the websocket (most recent first, limited to three elements) - * @type {number[]} - */ - this.pings = []; - - /** - * Timeouts set by {@link Client#setTimeout} that are still active - * @type {Set} - * @private - */ - this._timeouts = new Set(); - - /** - * Intervals set by {@link Client#setInterval} that are still active - * @type {Set} - * @private - */ - this._intervals = new Set(); - - if (this.options.messageSweepInterval > 0) { - this.setInterval(this.sweepMessages.bind(this), this.options.messageSweepInterval * 1000); - } - } - - /** - * Timestamp of the latest ping's start time - * @type {number} - * @private - */ - get _pingTimestamp() { - return this.ws.connection ? this.ws.connection.lastPingTimestamp : 0; - } - - /** - * Current status of the client's connection to Discord - * @type {?number} - * @readonly - */ - get status() { - return this.ws.connection.status; - } - - /** - * How long it has been since the client last entered the `READY` state - * @type {?number} - * @readonly - */ - get uptime() { - return this.readyAt ? Date.now() - this.readyAt : null; - } - - /** - * Average heartbeat ping of the websocket, obtained by averaging the {@link Client#pings} property - * @type {number} - * @readonly - */ - get ping() { - return this.pings.reduce((prev, p) => prev + p, 0) / this.pings.length; - } - - /** - * All active voice connections that have been established, mapped by channel ID - * @type {Collection} - * @readonly - */ - get voiceConnections() { - if (this.browser) return new Collection(); - return this.voice.connections; - } - - /** - * All custom emojis that the client has access to, mapped by their IDs - * @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; - } - - /** - * Timestamp of the time 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 os.platform() === 'browser'; - } - - /** - * Creates a voice broadcast. - * @returns {VoiceBroadcast} - */ - createVoiceBroadcast() { - const broadcast = new VoiceBroadcast(this); - this.broadcasts.push(broadcast); - return broadcast; - } - - /** - * Logs the client in, establishing a websocket connection to Discord. - * Both bot and regular user accounts are supported, but it is highly recommended to use a bot account whenever - * possible. User accounts are subject to harsher ratelimits and other restrictions that don't apply to bot accounts. - * Bot accounts also have access to many features that user accounts cannot utilise. User accounts that are found to - * be abusing/overusing the API will be banned, locking you out of Discord entirely. - * @param {string} token Token of the account to log in with - * @returns {Promise} Token of the account used - * @example - * client.login('my token'); - */ - login(token) { - return this.rest.methods.login(token); - } - - /** - * Logs out, terminates the connection to Discord, and destroys the client. - * @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(); - return this.manager.destroy(); - } - - /** - * Requests a sync of guild data with Discord. - * This can be done automatically every 30 seconds by enabling {@link ClientOptions#sync}. - * 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), - }); - } - - /** - * Obtains a user from Discord, or the user cache if it's already available. - * This is only available when using a bot account. - * @param {Snowflake} id ID of the user - * @param {boolean} [cache=true] Whether to cache the new user object if it isn't already - * @returns {Promise} - */ - fetchUser(id, cache = true) { - if (this.users.has(id)) return Promise.resolve(this.users.get(id)); - return this.rest.methods.getUser(id, cache); - } - - /** - * Obtains an invite from Discord. - * @param {InviteResolvable} invite Invite code or URL - * @returns {Promise} - */ - fetchInvite(invite) { - const code = this.resolver.resolveInviteCode(invite); - return this.rest.methods.getInvite(code); - } - - /** - * Obtains a webhook from Discord. - * @param {Snowflake} id ID of the webhook - * @param {string} [token] Token for the webhook - * @returns {Promise} - */ - fetchWebhook(id, token) { - return this.rest.methods.getWebhook(id, token); - } - - /** - * Obtains the available voice regions from Discord. - * @returns {Collection} - */ - fetchVoiceRegions() { - return this.rest.methods.fetchVoiceRegions(); - } - - /** - * Sweeps all text-based 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 {@link ClientOptions#messageCacheLifetime}. - * @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++; + s.prev[str & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = str; + str++; + s.insert--; + if (s.lookahead + s.insert < MIN_MATCH) { + break; } } } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ - this.emit('debug', `Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`); - return messages; - } + } while (s.lookahead < MIN_LOOKAHEAD && s.strm.avail_in !== 0); - /** - * Obtains the OAuth Application of the bot from Discord. - * @param {Snowflake} [id='@me'] ID of application to fetch - * @returns {Promise} + /* If the WIN_INIT bytes after the end of the current data have never been + * written, then zero those bytes in order to avoid memory check reports of + * the use of uninitialized (or uninitialised as Julian writes) bytes by + * the longest match routines. Update the high water mark for the next + * time through here. WIN_INIT is set to MAX_MATCH since the longest match + * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. */ - fetchApplication(id = '@me') { - return this.rest.methods.getApplication(id); - } - - /** - * Generates a link that can be used to invite the bot to a guild. - * This is only available when using a bot account. - * @param {PermissionResolvable[]|number} [permissions] Permissions to request - * @returns {Promise} - * @example - * client.generateInvite(['SEND_MESSAGES', 'MANAGE_GUILD', 'MENTION_EVERYONE']) - * .then(link => { - * console.log(`Generated bot invite link: ${link}`); - * }); - */ - generateInvite(permissions) { - if (permissions) { - if (permissions instanceof Array) permissions = Permissions.resolve(permissions); - } else { - permissions = 0; - } - return this.fetchApplication().then(application => - `https://discordapp.com/oauth2/authorize?client_id=${application.id}&permissions=${permissions}&scope=bot` - ); - } - - /** - * 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 Arguments for the function - * @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 Arguments for the function - * @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); - } - - /** - * Adds a ping to {@link Client#pings}. - * @param {number} startTime Starting time of the ping - * @private - */ - _pong(startTime) { - this.pings.unshift(Date.now() - startTime); - if (this.pings.length > 3) this.pings.length = 3; - this.ws.lastHeartbeatAck = true; - } - - /** - * Adds/updates a friend's presence in {@link Client#presences}. - * @param {Snowflake} id ID of the user - * @param {Object} presence Raw presence object from Discord - * @private - */ - _setPresence(id, presence) { - if (this.presences.has(id)) { - this.presences.get(id).update(presence); - return; - } - this.presences.set(id, new Presence(presence)); - } - - /** - * Calls {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval} on a script - * with the client as `this`. - * @param {string} script Script to eval - * @returns {*} - * @private - */ - _eval(script) { - return eval(script); - } - - /** - * Validates the client options. - * @param {ClientOptions} [options=this.options] Options to validate - * @private - */ - _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.'); - } +// if (s.high_water < s.window_size) { +// var curr = s.strstart + s.lookahead; +// var init = 0; +// +// if (s.high_water < curr) { +// /* Previous high water mark below current data -- zero WIN_INIT +// * bytes or up to end of window, whichever is less. +// */ +// init = s.window_size - curr; +// if (init > WIN_INIT) +// init = WIN_INIT; +// zmemzero(s->window + curr, (unsigned)init); +// s->high_water = curr + init; +// } +// else if (s->high_water < (ulg)curr + WIN_INIT) { +// /* High water mark at or above current data, but below current data +// * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up +// * to end of window, whichever is less. +// */ +// init = (ulg)curr + WIN_INIT - s->high_water; +// if (init > s->window_size - s->high_water) +// init = s->window_size - s->high_water; +// zmemzero(s->window + s->high_water, (unsigned)init); +// s->high_water += init; +// } +// } +// +// Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +// "not enough room for search"); } -module.exports = Client; - -/** - * Emitted for general warnings - * @event Client#warn - * @param {string} info The warning +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. */ +function deflate_stored(s, flush) { + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + var max_block_size = 0xffff; -/** - * Emitted for general debugging information - * @event Client#debug - * @param {string} info The debug information + if (max_block_size > s.pending_buf_size - 5) { + max_block_size = s.pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s.lookahead <= 1) { + + //Assert(s->strstart < s->w_size+MAX_DIST(s) || + // s->block_start >= (long)s->w_size, "slide too late"); +// if (!(s.strstart < s.w_size + (s.w_size - MIN_LOOKAHEAD) || +// s.block_start >= s.w_size)) { +// throw new Error("slide too late"); +// } + + fill_window(s); + if (s.lookahead === 0 && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + + if (s.lookahead === 0) { + break; + } + /* flush the current block */ + } + //Assert(s->block_start >= 0L, "block gone"); +// if (s.block_start < 0) throw new Error("block gone"); + + s.strstart += s.lookahead; + s.lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + var max_start = s.block_start + max_block_size; + + if (s.strstart === 0 || s.strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s.lookahead = s.strstart - max_start; + s.strstart = max_start; + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + + + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s.strstart - s.block_start >= (s.w_size - MIN_LOOKAHEAD)) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + + s.insert = 0; + + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + + if (s.strstart > s.block_start) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + return BS_NEED_MORE; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. */ +function deflate_fast(s, flush) { + var hash_head; /* head of the hash chain */ + var bflush; /* set if current block must be flushed */ -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(6))) + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { + break; /* flush the current block */ + } + } -/***/ }), -/* 69 */ -/***/ (function(module, exports, __webpack_require__) { + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } -const Webhook = __webpack_require__(30); -const RESTManager = __webpack_require__(65); -const ClientDataResolver = __webpack_require__(38); -const Constants = __webpack_require__(0); -const Util = __webpack_require__(4); + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head !== 0/*NIL*/ && ((s.strstart - hash_head) <= (s.w_size - MIN_LOOKAHEAD))) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + } + if (s.match_length >= MIN_MATCH) { + // check_match(s, s.strstart, s.match_start, s.match_length); // for debug only -/** - * The Webhook Client - * @extends {Webhook} + /*** _tr_tally_dist(s, s.strstart - s.match_start, + s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, s.strstart - s.match_start, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ + if (s.match_length <= s.max_lazy_match/*max_insert_length*/ && s.lookahead >= MIN_MATCH) { + s.match_length--; /* string at strstart already in table */ + do { + s.strstart++; + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s.match_length !== 0); + s.strstart++; + } else + { + s.strstart += s.match_length; + s.match_length = 0; + s.ins_h = s.window[s.strstart]; + /* UPDATE_HASH(s, s.ins_h, s.window[s.strstart+1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + 1]) & s.hash_mask; + +//#if MIN_MATCH != 3 +// Call UPDATE_HASH() MIN_MATCH-3 more times +//#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s.window[s.strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = ((s.strstart < (MIN_MATCH - 1)) ? s.strstart : MIN_MATCH - 1); + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. */ -class WebhookClient extends Webhook { - /** - * @param {Snowflake} id ID of the webhook - * @param {string} token Token of the webhook - * @param {ClientOptions} [options] Options for the client - * @example - * // create a new webhook and send a message - * const hook = new Discord.WebhookClient('1234', 'abcdef'); - * hook.sendMessage('This will send a message').catch(console.error); - */ - constructor(id, token, options) { - super(null, id, token); +function deflate_slow(s, flush) { + var hash_head; /* head of hash chain */ + var bflush; /* set if current block must be flushed */ - /** - * The options the client was instantiated with - * @type {ClientOptions} + var max_insert; + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. */ - this.options = Util.mergeDefault(Constants.DefaultOptions, options); + if (s.lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s.lookahead < MIN_LOOKAHEAD && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ + } - /** - * The REST manager of the client - * @type {RESTManager} - * @private + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: */ - this.rest = new RESTManager(this); + hash_head = 0/*NIL*/; + if (s.lookahead >= MIN_MATCH) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } - /** - * The data resolver of the client - * @type {ClientDataResolver} - * @private + /* Find the longest match, discarding those <= prev_length. */ - this.resolver = new ClientDataResolver(this); + s.prev_length = s.match_length; + s.prev_match = s.match_start; + s.match_length = MIN_MATCH - 1; - /** - * Timeouts set by {@link WebhookClient#setTimeout} that are still active - * @type {Set} - * @private + if (hash_head !== 0/*NIL*/ && s.prev_length < s.max_lazy_match && + s.strstart - hash_head <= (s.w_size - MIN_LOOKAHEAD)/*MAX_DIST(s)*/) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + s.match_length = longest_match(s, hash_head); + /* longest_match() sets match_start */ + + if (s.match_length <= 5 && + (s.strategy === Z_FILTERED || (s.match_length === MIN_MATCH && s.strstart - s.match_start > 4096/*TOO_FAR*/))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s.match_length = MIN_MATCH - 1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: */ - this._timeouts = new Set(); + if (s.prev_length >= MIN_MATCH && s.match_length <= s.prev_length) { + max_insert = s.strstart + s.lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ - /** - * Intervals set by {@link WebhookClient#setInterval} that are still active - * @type {Set} - * @private - */ - this._intervals = new Set(); + //check_match(s, s.strstart-1, s.prev_match, s.prev_length); + + /***_tr_tally_dist(s, s.strstart - 1 - s.prev_match, + s.prev_length - MIN_MATCH, bflush);***/ + bflush = trees._tr_tally(s, s.strstart - 1 - s.prev_match, s.prev_length - MIN_MATCH); + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s.lookahead -= s.prev_length - 1; + s.prev_length -= 2; + do { + if (++s.strstart <= max_insert) { + /*** INSERT_STRING(s, s.strstart, hash_head); ***/ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[s.strstart + MIN_MATCH - 1]) & s.hash_mask; + hash_head = s.prev[s.strstart & s.w_mask] = s.head[s.ins_h]; + s.head[s.ins_h] = s.strstart; + /***/ + } + } while (--s.prev_length !== 0); + s.match_available = 0; + s.match_length = MIN_MATCH - 1; + s.strstart++; + + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + + } else if (s.match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + if (bflush) { + /*** FLUSH_BLOCK_ONLY(s, 0) ***/ + flush_block_only(s, false); + /***/ + } + s.strstart++; + s.lookahead--; + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s.match_available = 1; + s.strstart++; + s.lookahead--; + } + } + //Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s.match_available) { + //Tracevv((stderr,"%c", s->window[s->strstart-1])); + /*** _tr_tally_lit(s, s.window[s.strstart-1], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart - 1]); + + s.match_available = 0; + } + s.insert = s.strstart < MIN_MATCH - 1 ? s.strstart : MIN_MATCH - 1; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } - /** - * 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 Arguments for the function - * @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 Arguments for the function - * @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); - } - - - /** - * Destroys the client. - */ - destroy() { - for (const t of this._timeouts) clearTimeout(t); - for (const i of this._intervals) clearInterval(i); - this._timeouts.clear(); - this._intervals.clear(); - } + return BS_BLOCK_DONE; } -module.exports = WebhookClient; - -/***/ }), -/* 70 */ -/***/ (function(module, exports, __webpack_require__) { - -const ClientDataResolver = __webpack_require__(38); - -/** - * A rich embed to be sent with a message with a fluent interface for creation - * @param {Object} [data] Data to set in the rich embed +/* =========================================================================== + * For Z_RLE, simply look for runs of bytes, generate matches only of distance + * one. Do not maintain a hash table. (It will be regenerated if this run of + * deflate switches away from Z_RLE.) */ -class RichEmbed { - constructor(data = {}) { - /** - * Title for this Embed - * @type {string} +function deflate_rle(s, flush) { + var bflush; /* set if current block must be flushed */ + var prev; /* byte at distance one to match */ + var scan, strend; /* scan goes up to strend for length of run */ + + var _win = s.window; + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the longest run, plus one for the unrolled loop. */ - this.title = data.title; - - /** - * Description for this Embed - * @type {string} - */ - this.description = data.description; - - /** - * URL for this Embed - * @type {string} - */ - this.url = data.url; - - /** - * Color for this Embed - * @type {number} - */ - this.color = data.color; - - /** - * Author for this Embed - * @type {Object} - */ - this.author = data.author; - - /** - * Timestamp for this Embed - * @type {Date} - */ - this.timestamp = data.timestamp; - - /** - * Fields for this Embed - * @type {Object[]} - */ - this.fields = data.fields || []; - - /** - * Thumbnail for this Embed - * @type {Object} - */ - this.thumbnail = data.thumbnail; - - /** - * Image for this Embed - * @type {Object} - */ - this.image = data.image; - - /** - * Footer for this Embed - * @type {Object} - */ - this.footer = data.footer; - - /** - * File to upload alongside this Embed - * @type {string} - */ - this.file = data.file; - } - - /** - * Sets the title of this embed - * @param {StringResolvable} title The title - * @returns {RichEmbed} This embed - */ - setTitle(title) { - title = resolveString(title); - if (title.length > 256) throw new RangeError('RichEmbed titles may not exceed 256 characters.'); - this.title = title; - return this; - } - - /** - * Sets the description of this embed - * @param {StringResolvable} description The description - * @returns {RichEmbed} This embed - */ - setDescription(description) { - description = resolveString(description); - if (description.length > 2048) throw new RangeError('RichEmbed descriptions may not exceed 2048 characters.'); - this.description = description; - return this; - } - - /** - * Sets the URL of this embed - * @param {string} url The URL - * @returns {RichEmbed} This embed - */ - setURL(url) { - this.url = url; - return this; - } - - /** - * Sets the color of this embed - * @param {ColorResolvable} color The color of the embed - * @returns {RichEmbed} This embed - */ - setColor(color) { - this.color = ClientDataResolver.resolveColor(color); - return this; - } - - /** - * Sets the author of this embed - * @param {StringResolvable} name The name of the author - * @param {string} [icon] The icon URL of the author - * @param {string} [url] The URL of the author - * @returns {RichEmbed} This embed - */ - setAuthor(name, icon, url) { - this.author = { name: resolveString(name), icon_url: icon, url }; - return this; - } - - /** - * Sets the timestamp of this embed - * @param {Date} [timestamp=current date] The timestamp - * @returns {RichEmbed} This embed - */ - setTimestamp(timestamp = new Date()) { - this.timestamp = timestamp; - return this; - } - - /** - * Adds a field to the embed (max 25) - * @param {StringResolvable} name The name of the field - * @param {StringResolvable} value The value of the field - * @param {boolean} [inline=false] Set the field to display inline - * @returns {RichEmbed} This embed - */ - addField(name, value, inline = false) { - if (this.fields.length >= 25) throw new RangeError('RichEmbeds may not exceed 25 fields.'); - name = resolveString(name); - if (name.length > 256) throw new RangeError('RichEmbed field names may not exceed 256 characters.'); - if (!/\S/.test(name)) throw new RangeError('RichEmbed field names may not be empty.'); - value = resolveString(value); - if (value.length > 1024) throw new RangeError('RichEmbed field values may not exceed 1024 characters.'); - if (!/\S/.test(value)) throw new RangeError('RichEmbed field values may not be empty.'); - this.fields.push({ name, value, inline }); - return this; - } - - /** - * Convenience function for `.addField('\u200B', '\u200B', inline)`. - * @param {boolean} [inline=false] Set the field to display inline - * @returns {RichEmbed} This embed - */ - addBlankField(inline = false) { - return this.addField('\u200B', '\u200B', inline); - } - - /** - * Set the thumbnail of this embed - * @param {string} url The URL of the thumbnail - * @returns {RichEmbed} This embed - */ - setThumbnail(url) { - this.thumbnail = { url }; - return this; - } - - /** - * Set the image of this embed - * @param {string} url The URL of the image - * @returns {RichEmbed} This embed - */ - setImage(url) { - this.image = { url }; - return this; - } - - /** - * Sets the footer of this embed - * @param {StringResolvable} text The text of the footer - * @param {string} [icon] The icon URL of the footer - * @returns {RichEmbed} This embed - */ - setFooter(text, icon) { - text = resolveString(text); - if (text.length > 2048) throw new RangeError('RichEmbed footer text may not exceed 2048 characters.'); - this.footer = { text, icon_url: icon }; - return this; - } - - /** - * Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when - * setting an embed image or author/footer icons. Only one file may be attached. - * @param {FileOptions|string} file Local path or URL to the file to attach, or valid FileOptions for a file to attach - * @returns {RichEmbed} This embed - */ - attachFile(file) { - if (this.file) throw new RangeError('You may not upload more than one file at once.'); - this.file = file; - return this; - } -} - -module.exports = RichEmbed; - -function resolveString(data) { - if (typeof data === 'string') return data; - if (data instanceof Array) return data.join('\n'); - return String(data); -} - - -/***/ }), -/* 71 */ -/***/ (function(module, exports) { - -/* (ignored) */ - -/***/ }), -/* 72 */ -/***/ (function(module, exports) { - -/* (ignored) */ - -/***/ }), -/* 73 */ -/***/ (function(module, exports) { - -/* (ignored) */ - -/***/ }), -/* 74 */ -/***/ (function(module, exports, __webpack_require__) { - -"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('') -} - - -/***/ }), -/* 75 */ -/***/ (function(module, exports) { - -module.exports = { - "100": "Continue", - "101": "Switching Protocols", - "102": "Processing", - "200": "OK", - "201": "Created", - "202": "Accepted", - "203": "Non-Authoritative Information", - "204": "No Content", - "205": "Reset Content", - "206": "Partial Content", - "207": "Multi-Status", - "208": "Already Reported", - "226": "IM Used", - "300": "Multiple Choices", - "301": "Moved Permanently", - "302": "Found", - "303": "See Other", - "304": "Not Modified", - "305": "Use Proxy", - "307": "Temporary Redirect", - "308": "Permanent Redirect", - "400": "Bad Request", - "401": "Unauthorized", - "402": "Payment Required", - "403": "Forbidden", - "404": "Not Found", - "405": "Method Not Allowed", - "406": "Not Acceptable", - "407": "Proxy Authentication Required", - "408": "Request Timeout", - "409": "Conflict", - "410": "Gone", - "411": "Length Required", - "412": "Precondition Failed", - "413": "Payload Too Large", - "414": "URI Too Long", - "415": "Unsupported Media Type", - "416": "Range Not Satisfiable", - "417": "Expectation Failed", - "418": "I'm a teapot", - "421": "Misdirected Request", - "422": "Unprocessable Entity", - "423": "Locked", - "424": "Failed Dependency", - "425": "Unordered Collection", - "426": "Upgrade Required", - "428": "Precondition Required", - "429": "Too Many Requests", - "431": "Request Header Fields Too Large", - "451": "Unavailable For Legal Reasons", - "500": "Internal Server Error", - "501": "Not Implemented", - "502": "Bad Gateway", - "503": "Service Unavailable", - "504": "Gateway Timeout", - "505": "HTTP Version Not Supported", - "506": "Variant Also Negotiates", - "507": "Insufficient Storage", - "508": "Loop Detected", - "509": "Bandwidth Limit Exceeded", - "510": "Not Extended", - "511": "Network Authentication Required" -} - - -/***/ }), -/* 76 */ -/***/ (function(module, exports, __webpack_require__) { - -var http = __webpack_require__(61); - -var https = module.exports; - -for (var key in http) { - if (http.hasOwnProperty(key)) https[key] = http[key]; -}; - -https.request = function (params, cb) { - if (!params) params = {}; - params.scheme = 'https'; - params.protocol = 'https:'; - return http.request.call(this, params, cb); -} - - -/***/ }), -/* 77 */ -/***/ (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 (s.lookahead <= MAX_MATCH) { + fill_window(s); + if (s.lookahead <= MAX_MATCH && flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + if (s.lookahead === 0) { break; } /* flush the current block */ } - if (e + eBias >= 1) { - value += rt / c + + /* See how many times the previous byte repeats */ + s.match_length = 0; + if (s.lookahead >= MIN_MATCH && s.strstart > 0) { + scan = s.strstart - 1; + prev = _win[scan]; + if (prev === _win[++scan] && prev === _win[++scan] && prev === _win[++scan]) { + strend = s.strstart + MAX_MATCH; + do { + /*jshint noempty:false*/ + } while (prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + prev === _win[++scan] && prev === _win[++scan] && + scan < strend); + s.match_length = MAX_MATCH - (strend - scan); + if (s.match_length > s.lookahead) { + s.match_length = s.lookahead; + } + } + //Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); + } + + /* Emit match if have run of MIN_MATCH or longer, else emit literal */ + if (s.match_length >= MIN_MATCH) { + //check_match(s, s.strstart, s.strstart - 1, s.match_length); + + /*** _tr_tally_dist(s, 1, s.match_length - MIN_MATCH, bflush); ***/ + bflush = trees._tr_tally(s, 1, s.match_length - MIN_MATCH); + + s.lookahead -= s.match_length; + s.strstart += s.match_length; + s.match_length = 0; } else { - value += rt * Math.pow(2, 1 - eBias) - } - if (value * c >= 2) { - e++ - c /= 2 - } + /* No match, output a literal byte */ + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); - 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 + s.lookahead--; + s.strstart++; + } + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ } } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} - for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} +/* =========================================================================== + * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. + * (It will be regenerated if this run of deflate switches away from Huffman.) + */ +function deflate_huff(s, flush) { + var bflush; /* set if current block must be flushed */ - e = (e << mLen) | m - eLen += mLen - for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + for (;;) { + /* Make sure that we have a literal to write. */ + if (s.lookahead === 0) { + fill_window(s); + if (s.lookahead === 0) { + if (flush === Z_NO_FLUSH) { + return BS_NEED_MORE; + } + break; /* flush the current block */ + } + } - buffer[offset + i - d] |= s * 128 + /* Output a literal byte */ + s.match_length = 0; + //Tracevv((stderr,"%c", s->window[s->strstart])); + /*** _tr_tally_lit(s, s.window[s.strstart], bflush); ***/ + bflush = trees._tr_tally(s, 0, s.window[s.strstart]); + s.lookahead--; + s.strstart++; + if (bflush) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + } + s.insert = 0; + if (flush === Z_FINISH) { + /*** FLUSH_BLOCK(s, 1); ***/ + flush_block_only(s, true); + if (s.strm.avail_out === 0) { + return BS_FINISH_STARTED; + } + /***/ + return BS_FINISH_DONE; + } + if (s.last_lit) { + /*** FLUSH_BLOCK(s, 0); ***/ + flush_block_only(s, false); + if (s.strm.avail_out === 0) { + return BS_NEED_MORE; + } + /***/ + } + return BS_BLOCK_DONE; +} + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +function Config(good_length, max_lazy, nice_length, max_chain, func) { + this.good_length = good_length; + this.max_lazy = max_lazy; + this.nice_length = nice_length; + this.max_chain = max_chain; + this.func = func; +} + +var configuration_table; + +configuration_table = [ + /* good lazy nice chain */ + new Config(0, 0, 0, 0, deflate_stored), /* 0 store only */ + new Config(4, 4, 8, 4, deflate_fast), /* 1 max speed, no lazy matches */ + new Config(4, 5, 16, 8, deflate_fast), /* 2 */ + new Config(4, 6, 32, 32, deflate_fast), /* 3 */ + + new Config(4, 4, 16, 16, deflate_slow), /* 4 lazy matches */ + new Config(8, 16, 32, 32, deflate_slow), /* 5 */ + new Config(8, 16, 128, 128, deflate_slow), /* 6 */ + new Config(8, 32, 128, 256, deflate_slow), /* 7 */ + new Config(32, 128, 258, 1024, deflate_slow), /* 8 */ + new Config(32, 258, 258, 4096, deflate_slow) /* 9 max compression */ +]; + + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +function lm_init(s) { + s.window_size = 2 * s.w_size; + + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + + /* Set the default configuration parameters: + */ + s.max_lazy_match = configuration_table[s.level].max_lazy; + s.good_match = configuration_table[s.level].good_length; + s.nice_match = configuration_table[s.level].nice_length; + s.max_chain_length = configuration_table[s.level].max_chain; + + s.strstart = 0; + s.block_start = 0; + s.lookahead = 0; + s.insert = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + s.ins_h = 0; } -/***/ }), -/* 78 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(module, global) {var __WEBPACK_AMD_DEFINE_RESULT__;/*! https://mths.be/punycode v1.4.1 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw new RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * https://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.4.1', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - true - ) { - !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { - return punycode; - }.call(exports, __webpack_require__, exports, module), - __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { - // in Node.js, io.js, or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { - // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { - // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); - -/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(103)(module), __webpack_require__(8))) - -/***/ }), -/* 79 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// 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. - - - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); +function DeflateState() { + this.strm = null; /* pointer back to this zlib stream */ + this.status = 0; /* as the name implies */ + this.pending_buf = null; /* output still pending */ + this.pending_buf_size = 0; /* size of pending_buf */ + this.pending_out = 0; /* next pending byte to output to the stream */ + this.pending = 0; /* nb of bytes in the pending buffer */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.gzhead = null; /* gzip header information to write */ + this.gzindex = 0; /* where in extra, name, or comment */ + this.method = Z_DEFLATED; /* can only be DEFLATED */ + this.last_flush = -1; /* value of flush param for previous deflate call */ + + this.w_size = 0; /* LZ77 window size (32K by default) */ + this.w_bits = 0; /* log2(w_size) (8..16) */ + this.w_mask = 0; /* w_size - 1 */ + + this.window = null; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. + */ + + this.window_size = 0; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + this.prev = null; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + this.head = null; /* Heads of the hash chains or NIL. */ + + this.ins_h = 0; /* hash index of string to be inserted */ + this.hash_size = 0; /* number of elements in hash table */ + this.hash_bits = 0; /* log2(hash_size) */ + this.hash_mask = 0; /* hash_size-1 */ + + this.hash_shift = 0; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + this.block_start = 0; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + this.match_length = 0; /* length of best match */ + this.prev_match = 0; /* previous match */ + this.match_available = 0; /* set if previous match exists */ + this.strstart = 0; /* start of string to insert */ + this.match_start = 0; /* start of matching string */ + this.lookahead = 0; /* number of valid bytes ahead in window */ + + this.prev_length = 0; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + this.max_chain_length = 0; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + this.max_lazy_match = 0; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ + // That's alias to max_lazy_match, don't use directly + //this.max_insert_length = 0; + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + this.level = 0; /* compression level (1..9) */ + this.strategy = 0; /* favor or force Huffman coding*/ + + this.good_match = 0; + /* Use a faster search when the previous match is longer than this */ + + this.nice_match = 0; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + + /* Didn't use ct_data typedef below to suppress compiler warning */ + + // struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + // struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + // struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + // Use flat array of DOUBLE size, with interleaved fata, + // because JS does not support effective + this.dyn_ltree = new utils.Buf16(HEAP_SIZE * 2); + this.dyn_dtree = new utils.Buf16((2 * D_CODES + 1) * 2); + this.bl_tree = new utils.Buf16((2 * BL_CODES + 1) * 2); + zero(this.dyn_ltree); + zero(this.dyn_dtree); + zero(this.bl_tree); + + this.l_desc = null; /* desc. for literal tree */ + this.d_desc = null; /* desc. for distance tree */ + this.bl_desc = null; /* desc. for bit length tree */ + + //ush bl_count[MAX_BITS+1]; + this.bl_count = new utils.Buf16(MAX_BITS + 1); + /* number of codes at each bit length for an optimal tree */ + + //int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + this.heap = new utils.Buf16(2 * L_CODES + 1); /* heap used to build the Huffman trees */ + zero(this.heap); + + this.heap_len = 0; /* number of elements in the heap */ + this.heap_max = 0; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + this.depth = new utils.Buf16(2 * L_CODES + 1); //uch depth[2*L_CODES+1]; + zero(this.depth); + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + this.l_buf = 0; /* buffer index for literals or lengths */ + + this.lit_bufsize = 0; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + this.last_lit = 0; /* running index in l_buf */ + + this.d_buf = 0; + /* Buffer index for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + this.opt_len = 0; /* bit length of current block with optimal trees */ + this.static_len = 0; /* bit length of current block with static trees */ + this.matches = 0; /* number of string matches in current block */ + this.insert = 0; /* bytes at end of window left to insert */ + + + this.bi_buf = 0; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + this.bi_valid = 0; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + + // Used for window memory init. We safely ignore it for JS. That makes + // sense only for pointers and memory check tools. + //this.high_water = 0; + /* High water mark offset in window for initialized bytes -- bytes above + * this are set to zero in order to avoid memory check warnings when + * longest match routines access bytes past the input. This is then + * updated to the new high water mark. + */ } -module.exports = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - if (typeof qs !== 'string' || qs.length === 0) { - return obj; +function deflateResetKeep(strm) { + var s; + + if (!strm || !strm.state) { + return err(strm, Z_STREAM_ERROR); } - var regexp = /\+/g; - qs = qs.split(sep); + strm.total_in = strm.total_out = 0; + strm.data_type = Z_UNKNOWN; - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; + s = strm.state; + s.pending = 0; + s.pending_out = 0; + + if (s.wrap < 0) { + s.wrap = -s.wrap; + /* was made negative by deflate(..., Z_FINISH); */ + } + s.status = (s.wrap ? INIT_STATE : BUSY_STATE); + strm.adler = (s.wrap === 2) ? + 0 // crc32(0, Z_NULL, 0) + : + 1; // adler32(0, Z_NULL, 0) + s.last_flush = Z_NO_FLUSH; + trees._tr_init(s); + return Z_OK; +} + + +function deflateReset(strm) { + var ret = deflateResetKeep(strm); + if (ret === Z_OK) { + lm_init(strm.state); + } + return ret; +} + + +function deflateSetHeader(strm, head) { + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + if (strm.state.wrap !== 2) { return Z_STREAM_ERROR; } + strm.state.gzhead = head; + return Z_OK; +} + + +function deflateInit2(strm, level, method, windowBits, memLevel, strategy) { + if (!strm) { // === Z_NULL + return Z_STREAM_ERROR; + } + var wrap = 1; + + if (level === Z_DEFAULT_COMPRESSION) { + level = 6; } - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; + if (windowBits < 0) { /* suppress zlib wrapper */ + wrap = 0; + windowBits = -windowBits; } - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; + else if (windowBits > 15) { + wrap = 2; /* write gzip wrapper instead */ + windowBits -= 16; + } - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; + + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method !== Z_DEFLATED || + windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_FIXED) { + return err(strm, Z_STREAM_ERROR); + } + + + if (windowBits === 8) { + windowBits = 9; + } + /* until 256-byte window bug fixed */ + + var s = new DeflateState(); + + strm.state = s; + s.strm = strm; + + s.wrap = wrap; + s.gzhead = null; + s.w_bits = windowBits; + s.w_size = 1 << s.w_bits; + s.w_mask = s.w_size - 1; + + s.hash_bits = memLevel + 7; + s.hash_size = 1 << s.hash_bits; + s.hash_mask = s.hash_size - 1; + s.hash_shift = ~~((s.hash_bits + MIN_MATCH - 1) / MIN_MATCH); + + s.window = new utils.Buf8(s.w_size * 2); + s.head = new utils.Buf16(s.hash_size); + s.prev = new utils.Buf16(s.w_size); + + // Don't need mem init magic for JS. + //s.high_water = 0; /* nothing written to s->window yet */ + + s.lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + s.pending_buf_size = s.lit_bufsize * 4; + + //overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + //s->pending_buf = (uchf *) overlay; + s.pending_buf = new utils.Buf8(s.pending_buf_size); + + // It is offset from `s.pending_buf` (size is `s.lit_bufsize * 2`) + //s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s.d_buf = 1 * s.lit_bufsize; + + //s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + s.l_buf = (1 + 2) * s.lit_bufsize; + + s.level = level; + s.strategy = strategy; + s.method = method; + + return deflateReset(strm); +} + +function deflateInit(strm, level) { + return deflateInit2(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); +} + + +function deflate(strm, flush) { + var old_flush, s; + var beg, val; // for gzip header write only + + if (!strm || !strm.state || + flush > Z_BLOCK || flush < 0) { + return strm ? err(strm, Z_STREAM_ERROR) : Z_STREAM_ERROR; + } + + s = strm.state; + + if (!strm.output || + (!strm.input && strm.avail_in !== 0) || + (s.status === FINISH_STATE && flush !== Z_FINISH)) { + return err(strm, (strm.avail_out === 0) ? Z_BUF_ERROR : Z_STREAM_ERROR); + } + + s.strm = strm; /* just in case */ + old_flush = s.last_flush; + s.last_flush = flush; + + /* Write the header */ + if (s.status === INIT_STATE) { + + if (s.wrap === 2) { // GZIP header + strm.adler = 0; //crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (!s.gzhead) { // s->gzhead == Z_NULL + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s.status = BUSY_STATE; + } + else { + put_byte(s, (s.gzhead.text ? 1 : 0) + + (s.gzhead.hcrc ? 2 : 0) + + (!s.gzhead.extra ? 0 : 4) + + (!s.gzhead.name ? 0 : 8) + + (!s.gzhead.comment ? 0 : 16) + ); + put_byte(s, s.gzhead.time & 0xff); + put_byte(s, (s.gzhead.time >> 8) & 0xff); + put_byte(s, (s.gzhead.time >> 16) & 0xff); + put_byte(s, (s.gzhead.time >> 24) & 0xff); + put_byte(s, s.level === 9 ? 2 : + (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2 ? + 4 : 0)); + put_byte(s, s.gzhead.os & 0xff); + if (s.gzhead.extra && s.gzhead.extra.length) { + put_byte(s, s.gzhead.extra.length & 0xff); + put_byte(s, (s.gzhead.extra.length >> 8) & 0xff); + } + if (s.gzhead.hcrc) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending, 0); + } + s.gzindex = 0; + s.status = EXTRA_STATE; + } } + else // DEFLATE header + { + var header = (Z_DEFLATED + ((s.w_bits - 8) << 4)) << 8; + var level_flags = -1; - k = decodeURIComponent(kstr); - v = decodeURIComponent(vstr); - - if (!hasOwnProperty(obj, k)) { - obj[k] = v; - } else if (isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - - -/***/ }), -/* 80 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// 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. - - - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -module.exports = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return map(objectKeys(obj), function(k) { - var ks = encodeURIComponent(stringifyPrimitive(k)) + eq; - if (isArray(obj[k])) { - return map(obj[k], function(v) { - return ks + encodeURIComponent(stringifyPrimitive(v)); - }).join(sep); + if (s.strategy >= Z_HUFFMAN_ONLY || s.level < 2) { + level_flags = 0; + } else if (s.level < 6) { + level_flags = 1; + } else if (s.level === 6) { + level_flags = 2; } else { - return ks + encodeURIComponent(stringifyPrimitive(obj[k])); + level_flags = 3; } - }).join(sep); + header |= (level_flags << 6); + if (s.strstart !== 0) { header |= PRESET_DICT; } + header += 31 - (header % 31); - } + s.status = BUSY_STATE; + putShortMSB(s, header); - if (!name) return ''; - return encodeURIComponent(stringifyPrimitive(name)) + eq + - encodeURIComponent(stringifyPrimitive(obj)); -}; - -var isArray = Array.isArray || function (xs) { - return Object.prototype.toString.call(xs) === '[object Array]'; -}; - -function map (xs, f) { - if (xs.map) return xs.map(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - res.push(f(xs[i], i)); - } - return res; -} - -var objectKeys = Object.keys || function (obj) { - var res = []; - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key); - } - return res; -}; - - -/***/ }), -/* 81 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(13); - - -/***/ }), -/* 82 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -// a passthrough stream. -// basically just the most minimal sort of Transform stream. -// Every written chunk gets output as-is. - - - -module.exports = PassThrough; - -var Transform = __webpack_require__(58); - -/**/ -var util = __webpack_require__(20); -util.inherits = __webpack_require__(10); -/**/ - -util.inherits(PassThrough, Transform); - -function PassThrough(options) { - if (!(this instanceof PassThrough)) return new PassThrough(options); - - Transform.call(this, options); -} - -PassThrough.prototype._transform = function (chunk, encoding, cb) { - cb(null, chunk); -}; - -/***/ }), -/* 83 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var Buffer = __webpack_require__(5).Buffer; -/**/ -var bufferShim = __webpack_require__(32); -/**/ - -module.exports = BufferList; - -function BufferList() { - this.head = null; - this.tail = null; - this.length = 0; -} - -BufferList.prototype.push = function (v) { - var entry = { data: v, next: null }; - if (this.length > 0) this.tail.next = entry;else this.head = entry; - this.tail = entry; - ++this.length; -}; - -BufferList.prototype.unshift = function (v) { - var entry = { data: v, next: this.head }; - if (this.length === 0) this.tail = entry; - this.head = entry; - ++this.length; -}; - -BufferList.prototype.shift = function () { - if (this.length === 0) return; - var ret = this.head.data; - if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; - --this.length; - return ret; -}; - -BufferList.prototype.clear = function () { - this.head = this.tail = null; - this.length = 0; -}; - -BufferList.prototype.join = function (s) { - if (this.length === 0) return ''; - var p = this.head; - var ret = '' + p.data; - while (p = p.next) { - ret += s + p.data; - }return ret; -}; - -BufferList.prototype.concat = function (n) { - if (this.length === 0) return bufferShim.alloc(0); - if (this.length === 1) return this.head.data; - var ret = bufferShim.allocUnsafe(n >>> 0); - var p = this.head; - var i = 0; - while (p) { - p.data.copy(ret, i); - i += p.data.length; - p = p.next; - } - return ret; -}; - -/***/ }), -/* 84 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(21).PassThrough - - -/***/ }), -/* 85 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(21).Transform - - -/***/ }), -/* 86 */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(36); - - -/***/ }), -/* 87 */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) { - "use strict"; - - if (global.setImmediate) { - return; - } - - var nextHandle = 1; // Spec says greater than zero - var tasksByHandle = {}; - var currentlyRunningATask = false; - var doc = global.document; - var registerImmediate; - - function setImmediate(callback) { - // Callback can either be a function or a string - if (typeof callback !== "function") { - callback = new Function("" + callback); + /* Save the adler32 of the preset dictionary: */ + if (s.strstart !== 0) { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); } - // Copy function arguments - var args = new Array(arguments.length - 1); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i + 1]; - } - // Store and register the task - var task = { callback: callback, args: args }; - tasksByHandle[nextHandle] = task; - registerImmediate(nextHandle); - return nextHandle++; + strm.adler = 1; // adler32(0L, Z_NULL, 0); } + } - function clearImmediate(handle) { - delete tasksByHandle[handle]; - } +//#ifdef GZIP + if (s.status === EXTRA_STATE) { + if (s.gzhead.extra/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ - function run(task) { - var callback = task.callback; - var args = task.args; - switch (args.length) { - case 0: - callback(); - break; - case 1: - callback(args[0]); - break; - case 2: - callback(args[0], args[1]); - break; - case 3: - callback(args[0], args[1], args[2]); - break; - default: - callback.apply(undefined, args); + while (s.gzindex < (s.gzhead.extra.length & 0xffff)) { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { break; + } } + put_byte(s, s.gzhead.extra[s.gzindex] & 0xff); + s.gzindex++; + } + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (s.gzindex === s.gzhead.extra.length) { + s.gzindex = 0; + s.status = NAME_STATE; + } + } + else { + s.status = NAME_STATE; + } + } + if (s.status === NAME_STATE) { + if (s.gzhead.name/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.name.length) { + val = s.gzhead.name.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.gzindex = 0; + s.status = COMMENT_STATE; + } + } + else { + s.status = COMMENT_STATE; + } + } + if (s.status === COMMENT_STATE) { + if (s.gzhead.comment/* != Z_NULL*/) { + beg = s.pending; /* start of bytes to update crc */ + //int val; + + do { + if (s.pending === s.pending_buf_size) { + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + flush_pending(strm); + beg = s.pending; + if (s.pending === s.pending_buf_size) { + val = 1; + break; + } + } + // JS specific: little magic to add zero terminator to end of string + if (s.gzindex < s.gzhead.comment.length) { + val = s.gzhead.comment.charCodeAt(s.gzindex++) & 0xff; + } else { + val = 0; + } + put_byte(s, val); + } while (val !== 0); + + if (s.gzhead.hcrc && s.pending > beg) { + strm.adler = crc32(strm.adler, s.pending_buf, s.pending - beg, beg); + } + if (val === 0) { + s.status = HCRC_STATE; + } + } + else { + s.status = HCRC_STATE; + } + } + if (s.status === HCRC_STATE) { + if (s.gzhead.hcrc) { + if (s.pending + 2 > s.pending_buf_size) { + flush_pending(strm); + } + if (s.pending + 2 <= s.pending_buf_size) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + strm.adler = 0; //crc32(0L, Z_NULL, 0); + s.status = BUSY_STATE; + } + } + else { + s.status = BUSY_STATE; + } + } +//#endif + + /* Flush as much pending output as possible */ + if (s.pending !== 0) { + flush_pending(strm); + if (strm.avail_out === 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s.last_flush = -1; + return Z_OK; } - function runIfPresent(handle) { - // From the spec: "Wait until any invocations of this algorithm started before this one have completed." - // So if we're currently running a task, we'll need to delay this invocation. - if (currentlyRunningATask) { - // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a - // "too much recursion" error. - setTimeout(runIfPresent, 0, handle); - } else { - var task = tasksByHandle[handle]; - if (task) { - currentlyRunningATask = true; - try { - run(task); - } finally { - clearImmediate(handle); - currentlyRunningATask = false; + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUF_ERROR. + */ + } else if (strm.avail_in === 0 && rank(flush) <= rank(old_flush) && + flush !== Z_FINISH) { + return err(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s.status === FINISH_STATE && strm.avail_in !== 0) { + return err(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm.avail_in !== 0 || s.lookahead !== 0 || + (flush !== Z_NO_FLUSH && s.status !== FINISH_STATE)) { + var bstate = (s.strategy === Z_HUFFMAN_ONLY) ? deflate_huff(s, flush) : + (s.strategy === Z_RLE ? deflate_rle(s, flush) : + configuration_table[s.level].func(s, flush)); + + if (bstate === BS_FINISH_STARTED || bstate === BS_FINISH_DONE) { + s.status = FINISH_STATE; + } + if (bstate === BS_NEED_MORE || bstate === BS_FINISH_STARTED) { + if (strm.avail_out === 0) { + s.last_flush = -1; + /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate === BS_BLOCK_DONE) { + if (flush === Z_PARTIAL_FLUSH) { + trees._tr_align(s); + } + else if (flush !== Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ + + trees._tr_stored_block(s, 0, 0, false); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush === Z_FULL_FLUSH) { + /*** CLEAR_HASH(s); ***/ /* forget history */ + zero(s.head); // Fill with NIL (= 0); + + if (s.lookahead === 0) { + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + } + } + flush_pending(strm); + if (strm.avail_out === 0) { + s.last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + //Assert(strm->avail_out > 0, "bug2"); + //if (strm.avail_out <= 0) { throw new Error("bug2");} + + if (flush !== Z_FINISH) { return Z_OK; } + if (s.wrap <= 0) { return Z_STREAM_END; } + + /* Write the trailer */ + if (s.wrap === 2) { + put_byte(s, strm.adler & 0xff); + put_byte(s, (strm.adler >> 8) & 0xff); + put_byte(s, (strm.adler >> 16) & 0xff); + put_byte(s, (strm.adler >> 24) & 0xff); + put_byte(s, strm.total_in & 0xff); + put_byte(s, (strm.total_in >> 8) & 0xff); + put_byte(s, (strm.total_in >> 16) & 0xff); + put_byte(s, (strm.total_in >> 24) & 0xff); + } + else + { + putShortMSB(s, strm.adler >>> 16); + putShortMSB(s, strm.adler & 0xffff); + } + + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + if (s.wrap > 0) { s.wrap = -s.wrap; } + /* write the trailer only once! */ + return s.pending !== 0 ? Z_OK : Z_STREAM_END; +} + +function deflateEnd(strm) { + var status; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + status = strm.state.status; + if (status !== INIT_STATE && + status !== EXTRA_STATE && + status !== NAME_STATE && + status !== COMMENT_STATE && + status !== HCRC_STATE && + status !== BUSY_STATE && + status !== FINISH_STATE + ) { + return err(strm, Z_STREAM_ERROR); + } + + strm.state = null; + + return status === BUSY_STATE ? err(strm, Z_DATA_ERROR) : Z_OK; +} + + +/* ========================================================================= + * Initializes the compression dictionary from the given byte + * sequence without producing any compressed output. + */ +function deflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var s; + var str, n; + var wrap; + var avail; + var next; + var input; + var tmpDict; + + if (!strm/*== Z_NULL*/ || !strm.state/*== Z_NULL*/) { + return Z_STREAM_ERROR; + } + + s = strm.state; + wrap = s.wrap; + + if (wrap === 2 || (wrap === 1 && s.status !== INIT_STATE) || s.lookahead) { + return Z_STREAM_ERROR; + } + + /* when using zlib wrappers, compute Adler-32 for provided dictionary */ + if (wrap === 1) { + /* adler32(strm->adler, dictionary, dictLength); */ + strm.adler = adler32(strm.adler, dictionary, dictLength, 0); + } + + s.wrap = 0; /* avoid computing Adler-32 in read_buf */ + + /* if dictionary would fill window, just replace the history */ + if (dictLength >= s.w_size) { + if (wrap === 0) { /* already empty otherwise */ + /*** CLEAR_HASH(s); ***/ + zero(s.head); // Fill with NIL (= 0); + s.strstart = 0; + s.block_start = 0; + s.insert = 0; + } + /* use the tail */ + // dictionary = dictionary.slice(dictLength - s.w_size); + tmpDict = new utils.Buf8(s.w_size); + utils.arraySet(tmpDict, dictionary, dictLength - s.w_size, s.w_size, 0); + dictionary = tmpDict; + dictLength = s.w_size; + } + /* insert dictionary into window and hash */ + avail = strm.avail_in; + next = strm.next_in; + input = strm.input; + strm.avail_in = dictLength; + strm.next_in = 0; + strm.input = dictionary; + fill_window(s); + while (s.lookahead >= MIN_MATCH) { + str = s.strstart; + n = s.lookahead - (MIN_MATCH - 1); + do { + /* UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); */ + s.ins_h = ((s.ins_h << s.hash_shift) ^ s.window[str + MIN_MATCH - 1]) & s.hash_mask; + + s.prev[str & s.w_mask] = s.head[s.ins_h]; + + s.head[s.ins_h] = str; + str++; + } while (--n); + s.strstart = str; + s.lookahead = MIN_MATCH - 1; + fill_window(s); + } + s.strstart += s.lookahead; + s.block_start = s.strstart; + s.insert = s.lookahead; + s.lookahead = 0; + s.match_length = s.prev_length = MIN_MATCH - 1; + s.match_available = 0; + strm.next_in = next; + strm.input = input; + strm.avail_in = avail; + s.wrap = wrap; + return Z_OK; +} + + +exports.deflateInit = deflateInit; +exports.deflateInit2 = deflateInit2; +exports.deflateReset = deflateReset; +exports.deflateResetKeep = deflateResetKeep; +exports.deflateSetHeader = deflateSetHeader; +exports.deflate = deflate; +exports.deflateEnd = deflateEnd; +exports.deflateSetDictionary = deflateSetDictionary; +exports.deflateInfo = 'pako deflate (from Nodeca project)'; + +/* Not implemented +exports.deflateBound = deflateBound; +exports.deflateCopy = deflateCopy; +exports.deflateParams = deflateParams; +exports.deflatePending = deflatePending; +exports.deflatePrime = deflatePrime; +exports.deflateTune = deflateTune; +*/ + + +/***/ }, +/* 72 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +function GZheader() { + /* true if compressed data believed to be text */ + this.text = 0; + /* modification time */ + this.time = 0; + /* extra flags (not used when writing a gzip file) */ + this.xflags = 0; + /* operating system */ + this.os = 0; + /* pointer to extra field or Z_NULL if none */ + this.extra = null; + /* extra field length (valid if extra != Z_NULL) */ + this.extra_len = 0; // Actually, we don't need it in JS, + // but leave for few code modifications + + // + // Setup limits is not necessary because in js we should not preallocate memory + // for inflate use constant limit in 65536 bytes + // + + /* space at extra (only when reading header) */ + // this.extra_max = 0; + /* pointer to zero-terminated file name or Z_NULL */ + this.name = ''; + /* space at name (only when reading header) */ + // this.name_max = 0; + /* pointer to zero-terminated comment or Z_NULL */ + this.comment = ''; + /* space at comment (only when reading header) */ + // this.comm_max = 0; + /* true if there was or will be a header crc */ + this.hcrc = 0; + /* true when done reading gzip header (not used when writing a gzip file) */ + this.done = false; +} + +module.exports = GZheader; + + +/***/ }, +/* 73 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +// See state defs from inflate.js +var BAD = 30; /* got a data error -- remain here until reset */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state.mode === LEN + strm.avail_in >= 6 + strm.avail_out >= 258 + start >= strm.avail_out + state.bits < 8 + + On return, state.mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm.avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm.avail_out >= 258 for each loop to avoid checking for + output space. + */ +module.exports = function inflate_fast(strm, start) { + var state; + var _in; /* local strm.input */ + var last; /* have enough input while in < last */ + var _out; /* local strm.output */ + var beg; /* inflate()'s initial strm.output */ + var end; /* while out < end, enough space available */ +//#ifdef INFLATE_STRICT + var dmax; /* maximum distance from zlib header */ +//#endif + var wsize; /* window size or zero if not using window */ + var whave; /* valid bytes in the window */ + var wnext; /* window write index */ + // Use `s_window` instead `window`, avoid conflict with instrumentation tools + var s_window; /* allocated sliding window, if wsize != 0 */ + var hold; /* local strm.hold */ + var bits; /* local strm.bits */ + var lcode; /* local strm.lencode */ + var dcode; /* local strm.distcode */ + var lmask; /* mask for first level of length codes */ + var dmask; /* mask for first level of distance codes */ + var here; /* retrieved table entry */ + var op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + var len; /* match length, unused bytes */ + var dist; /* match distance */ + var from; /* where to copy match from */ + var from_source; + + + var input, output; // JS specific, because we have no pointers + + /* copy state to local variables */ + state = strm.state; + //here = state.here; + _in = strm.next_in; + input = strm.input; + last = _in + (strm.avail_in - 5); + _out = strm.next_out; + output = strm.output; + beg = _out - (start - strm.avail_out); + end = _out + (strm.avail_out - 257); +//#ifdef INFLATE_STRICT + dmax = state.dmax; +//#endif + wsize = state.wsize; + whave = state.whave; + wnext = state.wnext; + s_window = state.window; + hold = state.hold; + bits = state.bits; + lcode = state.lencode; + dcode = state.distcode; + lmask = (1 << state.lenbits) - 1; + dmask = (1 << state.distbits) - 1; + + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + + top: + do { + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + + here = lcode[hold & lmask]; + + dolen: + for (;;) { // Goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + if (op === 0) { /* literal */ + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + output[_out++] = here & 0xffff/*here.val*/; + } + else if (op & 16) { /* length base */ + len = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + len += hold & ((1 << op) - 1); + hold >>>= op; + bits -= op; + } + //Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += input[_in++] << bits; + bits += 8; + hold += input[_in++] << bits; + bits += 8; + } + here = dcode[hold & dmask]; + + dodist: + for (;;) { // goto emulation + op = here >>> 24/*here.bits*/; + hold >>>= op; + bits -= op; + op = (here >>> 16) & 0xff/*here.op*/; + + if (op & 16) { /* distance base */ + dist = here & 0xffff/*here.val*/; + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + if (bits < op) { + hold += input[_in++] << bits; + bits += 8; + } + } + dist += hold & ((1 << op) - 1); +//#ifdef INFLATE_STRICT + if (dist > dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; + } +//#endif + hold >>>= op; + bits -= op; + //Tracevv((stderr, "inflate: distance %u\n", dist)); + op = _out - beg; /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break top; } + +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// if (len <= op - whave) { +// do { +// output[_out++] = 0; +// } while (--len); +// continue top; +// } +// len -= op - whave; +// do { +// output[_out++] = 0; +// } while (--op > whave); +// if (op === 0) { +// from = _out - dist; +// do { +// output[_out++] = output[from++]; +// } while (--len); +// continue top; +// } +//#endif + } + from = 0; // window index + from_source = s_window; + if (wnext === 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = 0; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + output[_out++] = s_window[from++]; + } while (--op); + from = _out - dist; /* rest from output */ + from_source = output; + } + } + while (len > 2) { + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + output[_out++] = from_source[from++]; + len -= 3; + } + if (len) { + output[_out++] = from_source[from++]; + if (len > 1) { + output[_out++] = from_source[from++]; + } + } } - } - } - - function installNextTickImplementation() { - registerImmediate = function(handle) { - process.nextTick(function () { runIfPresent(handle); }); - }; - } - - function canUsePostMessage() { - // The test against `importScripts` prevents this implementation from being installed inside a web worker, - // where `global.postMessage` means something completely different and can't be used for this purpose. - if (global.postMessage && !global.importScripts) { - var postMessageIsAsynchronous = true; - var oldOnMessage = global.onmessage; - global.onmessage = function() { - postMessageIsAsynchronous = false; - }; - global.postMessage("", "*"); - global.onmessage = oldOnMessage; - return postMessageIsAsynchronous; - } - } - - function installPostMessageImplementation() { - // Installs an event handler on `global` for the `message` event: see - // * https://developer.mozilla.org/en/DOM/window.postMessage - // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages - - var messagePrefix = "setImmediate$" + Math.random() + "$"; - var onGlobalMessage = function(event) { - if (event.source === global && - typeof event.data === "string" && - event.data.indexOf(messagePrefix) === 0) { - runIfPresent(+event.data.slice(messagePrefix.length)); + else { + from = _out - dist; /* copy direct from output */ + do { /* minimum length is three */ + output[_out++] = output[from++]; + output[_out++] = output[from++]; + output[_out++] = output[from++]; + len -= 3; + } while (len > 2); + if (len) { + output[_out++] = output[from++]; + if (len > 1) { + output[_out++] = output[from++]; + } + } } - }; + } + else if ((op & 64) === 0) { /* 2nd level distance code */ + here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dodist; + } + else { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break top; + } - if (global.addEventListener) { - global.addEventListener("message", onGlobalMessage, false); - } else { - global.attachEvent("onmessage", onGlobalMessage); + break; // need to emulate goto via "continue" } + } + else if ((op & 64) === 0) { /* 2nd level length code */ + here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; + continue dolen; + } + else if (op & 32) { /* end-of-block */ + //Tracevv((stderr, "inflate: end of block\n")); + state.mode = TYPE; + break top; + } + else { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break top; + } - registerImmediate = function(handle) { - global.postMessage(messagePrefix + handle, "*"); - }; + break; // need to emulate goto via "continue" + } + } while (_in < last && _out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + _in -= len; + bits -= len << 3; + hold &= (1 << bits) - 1; + + /* update state and return */ + strm.next_in = _in; + strm.next_out = _out; + strm.avail_in = (_in < last ? 5 + (last - _in) : 5 - (_in - last)); + strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); + state.hold = hold; + state.bits = bits; + return; +}; + + +/***/ }, +/* 74 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = __webpack_require__(5); +var adler32 = __webpack_require__(45); +var crc32 = __webpack_require__(47); +var inflate_fast = __webpack_require__(73); +var inflate_table = __webpack_require__(75); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +/* Public constants ==========================================================*/ +/* ===========================================================================*/ + + +/* Allowed flush values; see deflate() and inflate() below for details */ +//var Z_NO_FLUSH = 0; +//var Z_PARTIAL_FLUSH = 1; +//var Z_SYNC_FLUSH = 2; +//var Z_FULL_FLUSH = 3; +var Z_FINISH = 4; +var Z_BLOCK = 5; +var Z_TREES = 6; + + +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ +var Z_OK = 0; +var Z_STREAM_END = 1; +var Z_NEED_DICT = 2; +//var Z_ERRNO = -1; +var Z_STREAM_ERROR = -2; +var Z_DATA_ERROR = -3; +var Z_MEM_ERROR = -4; +var Z_BUF_ERROR = -5; +//var Z_VERSION_ERROR = -6; + +/* The deflate compression method */ +var Z_DEFLATED = 8; + + +/* STATES ====================================================================*/ +/* ===========================================================================*/ + + +var HEAD = 1; /* i: waiting for magic header */ +var FLAGS = 2; /* i: waiting for method and flags (gzip) */ +var TIME = 3; /* i: waiting for modification time (gzip) */ +var OS = 4; /* i: waiting for extra flags and operating system (gzip) */ +var EXLEN = 5; /* i: waiting for extra length (gzip) */ +var EXTRA = 6; /* i: waiting for extra bytes (gzip) */ +var NAME = 7; /* i: waiting for end of file name (gzip) */ +var COMMENT = 8; /* i: waiting for end of comment (gzip) */ +var HCRC = 9; /* i: waiting for header crc (gzip) */ +var DICTID = 10; /* i: waiting for dictionary check value */ +var DICT = 11; /* waiting for inflateSetDictionary() call */ +var TYPE = 12; /* i: waiting for type bits, including last-flag bit */ +var TYPEDO = 13; /* i: same, but skip check to exit inflate on new block */ +var STORED = 14; /* i: waiting for stored size (length and complement) */ +var COPY_ = 15; /* i/o: same as COPY below, but only first time in */ +var COPY = 16; /* i/o: waiting for input or output to copy stored block */ +var TABLE = 17; /* i: waiting for dynamic block table lengths */ +var LENLENS = 18; /* i: waiting for code length code lengths */ +var CODELENS = 19; /* i: waiting for length/lit and distance code lengths */ +var LEN_ = 20; /* i: same as LEN below, but only first time in */ +var LEN = 21; /* i: waiting for length/lit/eob code */ +var LENEXT = 22; /* i: waiting for length extra bits */ +var DIST = 23; /* i: waiting for distance code */ +var DISTEXT = 24; /* i: waiting for distance extra bits */ +var MATCH = 25; /* o: waiting for output space to copy string */ +var LIT = 26; /* o: waiting for output space to write literal */ +var CHECK = 27; /* i: waiting for 32-bit check value */ +var LENGTH = 28; /* i: waiting for 32-bit length (gzip) */ +var DONE = 29; /* finished check, done -- remain here until reset */ +var BAD = 30; /* got a data error -- remain here until reset */ +var MEM = 31; /* got an inflate() memory error -- remain here until reset */ +var SYNC = 32; /* looking for synchronization bytes to restart inflate() */ + +/* ===========================================================================*/ + + + +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var MAX_WBITS = 15; +/* 32K LZ77 window */ +var DEF_WBITS = MAX_WBITS; + + +function zswap32(q) { + return (((q >>> 24) & 0xff) + + ((q >>> 8) & 0xff00) + + ((q & 0xff00) << 8) + + ((q & 0xff) << 24)); +} + + +function InflateState() { + this.mode = 0; /* current inflate mode */ + this.last = false; /* true if processing last block */ + this.wrap = 0; /* bit 0 true for zlib, bit 1 true for gzip */ + this.havedict = false; /* true if dictionary provided */ + this.flags = 0; /* gzip header method and flags (0 if zlib) */ + this.dmax = 0; /* zlib header max distance (INFLATE_STRICT) */ + this.check = 0; /* protected copy of check value */ + this.total = 0; /* protected copy of output count */ + // TODO: may be {} + this.head = null; /* where to save gzip header information */ + + /* sliding window */ + this.wbits = 0; /* log base 2 of requested window size */ + this.wsize = 0; /* window size or zero if not using window */ + this.whave = 0; /* valid bytes in the window */ + this.wnext = 0; /* window write index */ + this.window = null; /* allocated sliding window, if needed */ + + /* bit accumulator */ + this.hold = 0; /* input bit accumulator */ + this.bits = 0; /* number of bits in "in" */ + + /* for string and stored block copying */ + this.length = 0; /* literal or length of data to copy */ + this.offset = 0; /* distance back to copy string from */ + + /* for table and code decoding */ + this.extra = 0; /* extra bits needed */ + + /* fixed and dynamic code tables */ + this.lencode = null; /* starting table for length/literal codes */ + this.distcode = null; /* starting table for distance codes */ + this.lenbits = 0; /* index bits for lencode */ + this.distbits = 0; /* index bits for distcode */ + + /* dynamic table building */ + this.ncode = 0; /* number of code length code lengths */ + this.nlen = 0; /* number of length code lengths */ + this.ndist = 0; /* number of distance code lengths */ + this.have = 0; /* number of code lengths in lens[] */ + this.next = null; /* next available space in codes[] */ + + this.lens = new utils.Buf16(320); /* temporary storage for code lengths */ + this.work = new utils.Buf16(288); /* work area for code table building */ + + /* + because we don't have pointers in js, we use lencode and distcode directly + as buffers so we don't need codes + */ + //this.codes = new utils.Buf32(ENOUGH); /* space for code tables */ + this.lendyn = null; /* dynamic table for length/literal codes (JS specific) */ + this.distdyn = null; /* dynamic table for distance codes (JS specific) */ + this.sane = 0; /* if false, allow invalid distance too far */ + this.back = 0; /* bits back of last unprocessed length/lit */ + this.was = 0; /* initial length of match */ +} + +function inflateResetKeep(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + strm.total_in = strm.total_out = state.total = 0; + strm.msg = ''; /*Z_NULL*/ + if (state.wrap) { /* to support ill-conceived Java test suite */ + strm.adler = state.wrap & 1; + } + state.mode = HEAD; + state.last = 0; + state.havedict = 0; + state.dmax = 32768; + state.head = null/*Z_NULL*/; + state.hold = 0; + state.bits = 0; + //state.lencode = state.distcode = state.next = state.codes; + state.lencode = state.lendyn = new utils.Buf32(ENOUGH_LENS); + state.distcode = state.distdyn = new utils.Buf32(ENOUGH_DISTS); + + state.sane = 1; + state.back = -1; + //Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +function inflateReset(strm) { + var state; + + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + state.wsize = 0; + state.whave = 0; + state.wnext = 0; + return inflateResetKeep(strm); + +} + +function inflateReset2(strm, windowBits) { + var wrap; + var state; + + /* get the state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 1; + if (windowBits < 48) { + windowBits &= 15; + } + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) { + return Z_STREAM_ERROR; + } + if (state.window !== null && state.wbits !== windowBits) { + state.window = null; + } + + /* update state and reset the rest of it */ + state.wrap = wrap; + state.wbits = windowBits; + return inflateReset(strm); +} + +function inflateInit2(strm, windowBits) { + var ret; + var state; + + if (!strm) { return Z_STREAM_ERROR; } + //strm.msg = Z_NULL; /* in case we return an error */ + + state = new InflateState(); + + //if (state === Z_NULL) return Z_MEM_ERROR; + //Tracev((stderr, "inflate: allocated\n")); + strm.state = state; + state.window = null/*Z_NULL*/; + ret = inflateReset2(strm, windowBits); + if (ret !== Z_OK) { + strm.state = null/*Z_NULL*/; + } + return ret; +} + +function inflateInit(strm) { + return inflateInit2(strm, DEF_WBITS); +} + + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +var virgin = true; + +var lenfix, distfix; // We have no pointers in JS, so keep tables separate + +function fixedtables(state) { + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + var sym; + + lenfix = new utils.Buf32(512); + distfix = new utils.Buf32(32); + + /* literal/length table */ + sym = 0; + while (sym < 144) { state.lens[sym++] = 8; } + while (sym < 256) { state.lens[sym++] = 9; } + while (sym < 280) { state.lens[sym++] = 7; } + while (sym < 288) { state.lens[sym++] = 8; } + + inflate_table(LENS, state.lens, 0, 288, lenfix, 0, state.work, { bits: 9 }); + + /* distance table */ + sym = 0; + while (sym < 32) { state.lens[sym++] = 5; } + + inflate_table(DISTS, state.lens, 0, 32, distfix, 0, state.work, { bits: 5 }); + + /* do this just once */ + virgin = false; + } + + state.lencode = lenfix; + state.lenbits = 9; + state.distcode = distfix; + state.distbits = 5; +} + + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +function updatewindow(strm, src, end, copy) { + var dist; + var state = strm.state; + + /* if it hasn't been done already, allocate space for the window */ + if (state.window === null) { + state.wsize = 1 << state.wbits; + state.wnext = 0; + state.whave = 0; + + state.window = new utils.Buf8(state.wsize); + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state.wsize) { + utils.arraySet(state.window, src, end - state.wsize, state.wsize, 0); + state.wnext = 0; + state.whave = state.wsize; + } + else { + dist = state.wsize - state.wnext; + if (dist > copy) { + dist = copy; + } + //zmemcpy(state->window + state->wnext, end - copy, dist); + utils.arraySet(state.window, src, end - copy, dist, state.wnext); + copy -= dist; + if (copy) { + //zmemcpy(state->window, end - copy, copy); + utils.arraySet(state.window, src, end - copy, copy, 0); + state.wnext = copy; + state.whave = state.wsize; + } + else { + state.wnext += dist; + if (state.wnext === state.wsize) { state.wnext = 0; } + if (state.whave < state.wsize) { state.whave += dist; } + } + } + return 0; +} + +function inflate(strm, flush) { + var state; + var input, output; // input/output buffers + var next; /* next input INDEX */ + var put; /* next output INDEX */ + var have, left; /* available input and output */ + var hold; /* bit buffer */ + var bits; /* bits in bit buffer */ + var _in, _out; /* save starting available input and output */ + var copy; /* number of stored or match bytes to copy */ + var from; /* where to copy match bytes from */ + var from_source; + var here = 0; /* current decoding table entry */ + var here_bits, here_op, here_val; // paked "here" denormalized (JS specific) + //var last; /* parent table entry */ + var last_bits, last_op, last_val; // paked "last" denormalized (JS specific) + var len; /* length to copy for repeats, bits to drop */ + var ret; /* return code */ + var hbuf = new utils.Buf8(4); /* buffer for gzip header crc calculation */ + var opts; + + var n; // temporary var for NEED_BITS + + var order = /* permutation of code lengths */ + [ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 ]; + + + if (!strm || !strm.state || !strm.output || + (!strm.input && strm.avail_in !== 0)) { + return Z_STREAM_ERROR; + } + + state = strm.state; + if (state.mode === TYPE) { state.mode = TYPEDO; } /* skip check */ + + + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + _in = have; + _out = left; + ret = Z_OK; + + inf_leave: // goto emulation + for (;;) { + switch (state.mode) { + case HEAD: + if (state.wrap === 0) { + state.mode = TYPEDO; + break; + } + //=== NEEDBITS(16); + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((state.wrap & 2) && hold === 0x8b1f) { /* gzip header */ + state.check = 0/*crc32(0L, Z_NULL, 0)*/; + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = FLAGS; + break; + } + state.flags = 0; /* expect zlib header */ + if (state.head) { + state.head.done = false; + } + if (!(state.wrap & 1) || /* check if zlib header allowed */ + (((hold & 0xff)/*BITS(8)*/ << 8) + (hold >> 8)) % 31) { + strm.msg = 'incorrect header check'; + state.mode = BAD; + break; + } + if ((hold & 0x0f)/*BITS(4)*/ !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// + len = (hold & 0x0f)/*BITS(4)*/ + 8; + if (state.wbits === 0) { + state.wbits = len; + } + else if (len > state.wbits) { + strm.msg = 'invalid window size'; + state.mode = BAD; + break; + } + state.dmax = 1 << len; + //Tracev((stderr, "inflate: zlib header ok\n")); + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = hold & 0x200 ? DICTID : TYPE; + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + break; + case FLAGS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.flags = hold; + if ((state.flags & 0xff) !== Z_DEFLATED) { + strm.msg = 'unknown compression method'; + state.mode = BAD; + break; + } + if (state.flags & 0xe000) { + strm.msg = 'unknown header flags set'; + state.mode = BAD; + break; + } + if (state.head) { + state.head.text = ((hold >> 8) & 1); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = TIME; + /* falls through */ + case TIME: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.time = hold; + } + if (state.flags & 0x0200) { + //=== CRC4(state.check, hold) + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + hbuf[2] = (hold >>> 16) & 0xff; + hbuf[3] = (hold >>> 24) & 0xff; + state.check = crc32(state.check, hbuf, 4, 0); + //=== + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = OS; + /* falls through */ + case OS: + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (state.head) { + state.head.xflags = (hold & 0xff); + state.head.os = (hold >> 8); + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = EXLEN; + /* falls through */ + case EXLEN: + if (state.flags & 0x0400) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length = hold; + if (state.head) { + state.head.extra_len = hold; + } + if (state.flags & 0x0200) { + //=== CRC2(state.check, hold); + hbuf[0] = hold & 0xff; + hbuf[1] = (hold >>> 8) & 0xff; + state.check = crc32(state.check, hbuf, 2, 0); + //===// + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + else if (state.head) { + state.head.extra = null/*Z_NULL*/; + } + state.mode = EXTRA; + /* falls through */ + case EXTRA: + if (state.flags & 0x0400) { + copy = state.length; + if (copy > have) { copy = have; } + if (copy) { + if (state.head) { + len = state.head.extra_len - state.length; + if (!state.head.extra) { + // Use untyped array for more conveniend processing later + state.head.extra = new Array(state.head.extra_len); + } + utils.arraySet( + state.head.extra, + input, + next, + // extra field is limited to 65536 bytes + // - no need for additional size check + copy, + /*len + copy > state.head.extra_max - len ? state.head.extra_max : copy,*/ + len + ); + //zmemcpy(state.head.extra + len, next, + // len + copy > state.head.extra_max ? + // state.head.extra_max - len : copy); + } + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + state.length -= copy; + } + if (state.length) { break inf_leave; } + } + state.length = 0; + state.mode = NAME; + /* falls through */ + case NAME: + if (state.flags & 0x0800) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + // TODO: 2 or 1 bytes? + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.name_max*/)) { + state.head.name += String.fromCharCode(len); + } + } while (len && copy < have); + + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.name = null; + } + state.length = 0; + state.mode = COMMENT; + /* falls through */ + case COMMENT: + if (state.flags & 0x1000) { + if (have === 0) { break inf_leave; } + copy = 0; + do { + len = input[next + copy++]; + /* use constant limit because in js we should not preallocate memory */ + if (state.head && len && + (state.length < 65536 /*state.head.comm_max*/)) { + state.head.comment += String.fromCharCode(len); + } + } while (len && copy < have); + if (state.flags & 0x0200) { + state.check = crc32(state.check, input, copy, next); + } + have -= copy; + next += copy; + if (len) { break inf_leave; } + } + else if (state.head) { + state.head.comment = null; + } + state.mode = HCRC; + /* falls through */ + case HCRC: + if (state.flags & 0x0200) { + //=== NEEDBITS(16); */ + while (bits < 16) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.check & 0xffff)) { + strm.msg = 'header crc mismatch'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + } + if (state.head) { + state.head.hcrc = ((state.flags >> 9) & 1); + state.head.done = true; + } + strm.adler = state.check = 0; + state.mode = TYPE; + break; + case DICTID: + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + strm.adler = state.check = zswap32(hold); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = DICT; + /* falls through */ + case DICT: + if (state.havedict === 0) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + return Z_NEED_DICT; + } + strm.adler = state.check = 1/*adler32(0L, Z_NULL, 0)*/; + state.mode = TYPE; + /* falls through */ + case TYPE: + if (flush === Z_BLOCK || flush === Z_TREES) { break inf_leave; } + /* falls through */ + case TYPEDO: + if (state.last) { + //--- BYTEBITS() ---// + hold >>>= bits & 7; + bits -= bits & 7; + //---// + state.mode = CHECK; + break; + } + //=== NEEDBITS(3); */ + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.last = (hold & 0x01)/*BITS(1)*/; + //--- DROPBITS(1) ---// + hold >>>= 1; + bits -= 1; + //---// + + switch ((hold & 0x03)/*BITS(2)*/) { + case 0: /* stored block */ + //Tracev((stderr, "inflate: stored block%s\n", + // state.last ? " (last)" : "")); + state.mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + //Tracev((stderr, "inflate: fixed codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = LEN_; /* decode codes */ + if (flush === Z_TREES) { + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break inf_leave; + } + break; + case 2: /* dynamic block */ + //Tracev((stderr, "inflate: dynamic codes block%s\n", + // state.last ? " (last)" : "")); + state.mode = TABLE; + break; + case 3: + strm.msg = 'invalid block type'; + state.mode = BAD; + } + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + break; + case STORED: + //--- BYTEBITS() ---// /* go to byte boundary */ + hold >>>= bits & 7; + bits -= bits & 7; + //---// + //=== NEEDBITS(32); */ + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if ((hold & 0xffff) !== ((hold >>> 16) ^ 0xffff)) { + strm.msg = 'invalid stored block lengths'; + state.mode = BAD; + break; + } + state.length = hold & 0xffff; + //Tracev((stderr, "inflate: stored length %u\n", + // state.length)); + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + state.mode = COPY_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case COPY_: + state.mode = COPY; + /* falls through */ + case COPY: + copy = state.length; + if (copy) { + if (copy > have) { copy = have; } + if (copy > left) { copy = left; } + if (copy === 0) { break inf_leave; } + //--- zmemcpy(put, next, copy); --- + utils.arraySet(output, input, next, copy, put); + //---// + have -= copy; + next += copy; + left -= copy; + put += copy; + state.length -= copy; + break; + } + //Tracev((stderr, "inflate: stored end\n")); + state.mode = TYPE; + break; + case TABLE: + //=== NEEDBITS(14); */ + while (bits < 14) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.nlen = (hold & 0x1f)/*BITS(5)*/ + 257; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ndist = (hold & 0x1f)/*BITS(5)*/ + 1; + //--- DROPBITS(5) ---// + hold >>>= 5; + bits -= 5; + //---// + state.ncode = (hold & 0x0f)/*BITS(4)*/ + 4; + //--- DROPBITS(4) ---// + hold >>>= 4; + bits -= 4; + //---// +//#ifndef PKZIP_BUG_WORKAROUND + if (state.nlen > 286 || state.ndist > 30) { + strm.msg = 'too many length or distance symbols'; + state.mode = BAD; + break; + } +//#endif + //Tracev((stderr, "inflate: table sizes ok\n")); + state.have = 0; + state.mode = LENLENS; + /* falls through */ + case LENLENS: + while (state.have < state.ncode) { + //=== NEEDBITS(3); + while (bits < 3) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.lens[order[state.have++]] = (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + while (state.have < 19) { + state.lens[order[state.have++]] = 0; + } + // We have separate tables & no pointers. 2 commented lines below not needed. + //state.next = state.codes; + //state.lencode = state.next; + // Switch to use dynamic table + state.lencode = state.lendyn; + state.lenbits = 7; + + opts = { bits: state.lenbits }; + ret = inflate_table(CODES, state.lens, 0, 19, state.lencode, 0, state.work, opts); + state.lenbits = opts.bits; + + if (ret) { + strm.msg = 'invalid code lengths set'; + state.mode = BAD; + break; + } + //Tracev((stderr, "inflate: code lengths ok\n")); + state.have = 0; + state.mode = CODELENS; + /* falls through */ + case CODELENS: + while (state.have < state.nlen + state.ndist) { + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)];/*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_val < 16) { + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.lens[state.have++] = here_val; + } + else { + if (here_val === 16) { + //=== NEEDBITS(here.bits + 2); + n = here_bits + 2; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + if (state.have === 0) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + len = state.lens[state.have - 1]; + copy = 3 + (hold & 0x03);//BITS(2); + //--- DROPBITS(2) ---// + hold >>>= 2; + bits -= 2; + //---// + } + else if (here_val === 17) { + //=== NEEDBITS(here.bits + 3); + n = here_bits + 3; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 3 + (hold & 0x07);//BITS(3); + //--- DROPBITS(3) ---// + hold >>>= 3; + bits -= 3; + //---// + } + else { + //=== NEEDBITS(here.bits + 7); + n = here_bits + 7; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + len = 0; + copy = 11 + (hold & 0x7f);//BITS(7); + //--- DROPBITS(7) ---// + hold >>>= 7; + bits -= 7; + //---// + } + if (state.have + copy > state.nlen + state.ndist) { + strm.msg = 'invalid bit length repeat'; + state.mode = BAD; + break; + } + while (copy--) { + state.lens[state.have++] = len; + } + } + } + + /* handle error breaks in while */ + if (state.mode === BAD) { break; } + + /* check for end-of-block code (better have one) */ + if (state.lens[256] === 0) { + strm.msg = 'invalid code -- missing end-of-block'; + state.mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state.lenbits = 9; + + opts = { bits: state.lenbits }; + ret = inflate_table(LENS, state.lens, 0, state.nlen, state.lencode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.lenbits = opts.bits; + // state.lencode = state.next; + + if (ret) { + strm.msg = 'invalid literal/lengths set'; + state.mode = BAD; + break; + } + + state.distbits = 6; + //state.distcode.copy(state.codes); + // Switch to use dynamic table + state.distcode = state.distdyn; + opts = { bits: state.distbits }; + ret = inflate_table(DISTS, state.lens, state.nlen, state.ndist, state.distcode, 0, state.work, opts); + // We have separate tables & no pointers. 2 commented lines below not needed. + // state.next_index = opts.table_index; + state.distbits = opts.bits; + // state.distcode = state.next; + + if (ret) { + strm.msg = 'invalid distances set'; + state.mode = BAD; + break; + } + //Tracev((stderr, 'inflate: codes ok\n')); + state.mode = LEN_; + if (flush === Z_TREES) { break inf_leave; } + /* falls through */ + case LEN_: + state.mode = LEN; + /* falls through */ + case LEN: + if (have >= 6 && left >= 258) { + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + inflate_fast(strm, _out); + //--- LOAD() --- + put = strm.next_out; + output = strm.output; + left = strm.avail_out; + next = strm.next_in; + input = strm.input; + have = strm.avail_in; + hold = state.hold; + bits = state.bits; + //--- + + if (state.mode === TYPE) { + state.back = -1; + } + break; + } + state.back = 0; + for (;;) { + here = state.lencode[hold & ((1 << state.lenbits) - 1)]; /*BITS(state.lenbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if (here_bits <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if (here_op && (here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.lencode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + state.length = here_val; + if (here_op === 0) { + //Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + // "inflate: literal '%c'\n" : + // "inflate: literal 0x%02x\n", here.val)); + state.mode = LIT; + break; + } + if (here_op & 32) { + //Tracevv((stderr, "inflate: end of block\n")); + state.back = -1; + state.mode = TYPE; + break; + } + if (here_op & 64) { + strm.msg = 'invalid literal/length code'; + state.mode = BAD; + break; + } + state.extra = here_op & 15; + state.mode = LENEXT; + /* falls through */ + case LENEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.length += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } + //Tracevv((stderr, "inflate: length %u\n", state.length)); + state.was = state.length; + state.mode = DIST; + /* falls through */ + case DIST: + for (;;) { + here = state.distcode[hold & ((1 << state.distbits) - 1)];/*BITS(state.distbits)*/ + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + if ((here_op & 0xf0) === 0) { + last_bits = here_bits; + last_op = here_op; + last_val = here_val; + for (;;) { + here = state.distcode[last_val + + ((hold & ((1 << (last_bits + last_op)) - 1))/*BITS(last.bits + last.op)*/ >> last_bits)]; + here_bits = here >>> 24; + here_op = (here >>> 16) & 0xff; + here_val = here & 0xffff; + + if ((last_bits + here_bits) <= bits) { break; } + //--- PULLBYTE() ---// + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + //---// + } + //--- DROPBITS(last.bits) ---// + hold >>>= last_bits; + bits -= last_bits; + //---// + state.back += last_bits; + } + //--- DROPBITS(here.bits) ---// + hold >>>= here_bits; + bits -= here_bits; + //---// + state.back += here_bits; + if (here_op & 64) { + strm.msg = 'invalid distance code'; + state.mode = BAD; + break; + } + state.offset = here_val; + state.extra = (here_op) & 15; + state.mode = DISTEXT; + /* falls through */ + case DISTEXT: + if (state.extra) { + //=== NEEDBITS(state.extra); + n = state.extra; + while (bits < n) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + state.offset += hold & ((1 << state.extra) - 1)/*BITS(state.extra)*/; + //--- DROPBITS(state.extra) ---// + hold >>>= state.extra; + bits -= state.extra; + //---// + state.back += state.extra; + } +//#ifdef INFLATE_STRICT + if (state.offset > state.dmax) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +//#endif + //Tracevv((stderr, "inflate: distance %u\n", state.offset)); + state.mode = MATCH; + /* falls through */ + case MATCH: + if (left === 0) { break inf_leave; } + copy = _out - left; + if (state.offset > copy) { /* copy from window */ + copy = state.offset - copy; + if (copy > state.whave) { + if (state.sane) { + strm.msg = 'invalid distance too far back'; + state.mode = BAD; + break; + } +// (!) This block is disabled in zlib defailts, +// don't enable it for binary compatibility +//#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR +// Trace((stderr, "inflate.c too far\n")); +// copy -= state.whave; +// if (copy > state.length) { copy = state.length; } +// if (copy > left) { copy = left; } +// left -= copy; +// state.length -= copy; +// do { +// output[put++] = 0; +// } while (--copy); +// if (state.length === 0) { state.mode = LEN; } +// break; +//#endif + } + if (copy > state.wnext) { + copy -= state.wnext; + from = state.wsize - copy; + } + else { + from = state.wnext - copy; + } + if (copy > state.length) { copy = state.length; } + from_source = state.window; + } + else { /* copy from output */ + from_source = output; + from = put - state.offset; + copy = state.length; + } + if (copy > left) { copy = left; } + left -= copy; + state.length -= copy; + do { + output[put++] = from_source[from++]; + } while (--copy); + if (state.length === 0) { state.mode = LEN; } + break; + case LIT: + if (left === 0) { break inf_leave; } + output[put++] = state.length; + left--; + state.mode = LEN; + break; + case CHECK: + if (state.wrap) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + // Use '|' insdead of '+' to make sure that result is signed + hold |= input[next++] << bits; + bits += 8; + } + //===// + _out -= left; + strm.total_out += _out; + state.total += _out; + if (_out) { + strm.adler = state.check = + /*UPDATE(state.check, put - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, put - _out) : adler32(state.check, output, _out, put - _out)); + + } + _out = left; + // NB: crc32 stored as signed 32-bit int, zswap32 returns signed too + if ((state.flags ? hold : zswap32(hold)) !== state.check) { + strm.msg = 'incorrect data check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: check matches trailer\n")); + } + state.mode = LENGTH; + /* falls through */ + case LENGTH: + if (state.wrap && state.flags) { + //=== NEEDBITS(32); + while (bits < 32) { + if (have === 0) { break inf_leave; } + have--; + hold += input[next++] << bits; + bits += 8; + } + //===// + if (hold !== (state.total & 0xffffffff)) { + strm.msg = 'incorrect length check'; + state.mode = BAD; + break; + } + //=== INITBITS(); + hold = 0; + bits = 0; + //===// + //Tracev((stderr, "inflate: length matches trailer\n")); + } + state.mode = DONE; + /* falls through */ + case DONE: + ret = Z_STREAM_END; + break inf_leave; + case BAD: + ret = Z_DATA_ERROR; + break inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + /* falls through */ + default: + return Z_STREAM_ERROR; + } + } + + // inf_leave <- here is real place for "goto inf_leave", emulated via "break inf_leave" + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + + //--- RESTORE() --- + strm.next_out = put; + strm.avail_out = left; + strm.next_in = next; + strm.avail_in = have; + state.hold = hold; + state.bits = bits; + //--- + + if (state.wsize || (_out !== strm.avail_out && state.mode < BAD && + (state.mode < CHECK || flush !== Z_FINISH))) { + if (updatewindow(strm, strm.output, strm.next_out, _out - strm.avail_out)) { + state.mode = MEM; + return Z_MEM_ERROR; + } + } + _in -= strm.avail_in; + _out -= strm.avail_out; + strm.total_in += _in; + strm.total_out += _out; + state.total += _out; + if (state.wrap && _out) { + strm.adler = state.check = /*UPDATE(state.check, strm.next_out - _out, _out);*/ + (state.flags ? crc32(state.check, output, _out, strm.next_out - _out) : adler32(state.check, output, _out, strm.next_out - _out)); + } + strm.data_type = state.bits + (state.last ? 64 : 0) + + (state.mode === TYPE ? 128 : 0) + + (state.mode === LEN_ || state.mode === COPY_ ? 256 : 0); + if (((_in === 0 && _out === 0) || flush === Z_FINISH) && ret === Z_OK) { + ret = Z_BUF_ERROR; + } + return ret; +} + +function inflateEnd(strm) { + + if (!strm || !strm.state /*|| strm->zfree == (free_func)0*/) { + return Z_STREAM_ERROR; + } + + var state = strm.state; + if (state.window) { + state.window = null; + } + strm.state = null; + return Z_OK; +} + +function inflateGetHeader(strm, head) { + var state; + + /* check state */ + if (!strm || !strm.state) { return Z_STREAM_ERROR; } + state = strm.state; + if ((state.wrap & 2) === 0) { return Z_STREAM_ERROR; } + + /* save header structure */ + state.head = head; + head.done = false; + return Z_OK; +} + +function inflateSetDictionary(strm, dictionary) { + var dictLength = dictionary.length; + + var state; + var dictid; + var ret; + + /* check state */ + if (!strm /* == Z_NULL */ || !strm.state /* == Z_NULL */) { return Z_STREAM_ERROR; } + state = strm.state; + + if (state.wrap !== 0 && state.mode !== DICT) { + return Z_STREAM_ERROR; + } + + /* check for correct dictionary identifier */ + if (state.mode === DICT) { + dictid = 1; /* adler32(0, null, 0)*/ + /* dictid = adler32(dictid, dictionary, dictLength); */ + dictid = adler32(dictid, dictionary, dictLength, 0); + if (dictid !== state.check) { + return Z_DATA_ERROR; + } + } + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary, dictLength, dictLength); + if (ret) { + state.mode = MEM; + return Z_MEM_ERROR; + } + state.havedict = 1; + // Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +exports.inflateReset = inflateReset; +exports.inflateReset2 = inflateReset2; +exports.inflateResetKeep = inflateResetKeep; +exports.inflateInit = inflateInit; +exports.inflateInit2 = inflateInit2; +exports.inflate = inflate; +exports.inflateEnd = inflateEnd; +exports.inflateGetHeader = inflateGetHeader; +exports.inflateSetDictionary = inflateSetDictionary; +exports.inflateInfo = 'pako inflate (from Nodeca project)'; + +/* Not implemented +exports.inflateCopy = inflateCopy; +exports.inflateGetDictionary = inflateGetDictionary; +exports.inflateMark = inflateMark; +exports.inflatePrime = inflatePrime; +exports.inflateSync = inflateSync; +exports.inflateSyncPoint = inflateSyncPoint; +exports.inflateUndermine = inflateUndermine; +*/ + + +/***/ }, +/* 75 */ +/***/ function(module, exports, __webpack_require__) { + +"use strict"; + + +// (C) 1995-2013 Jean-loup Gailly and Mark Adler +// (C) 2014-2017 Vitaly Puzrin and Andrey Tupitsin +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +var utils = __webpack_require__(5); + +var MAXBITS = 15; +var ENOUGH_LENS = 852; +var ENOUGH_DISTS = 592; +//var ENOUGH = (ENOUGH_LENS+ENOUGH_DISTS); + +var CODES = 0; +var LENS = 1; +var DISTS = 2; + +var lbase = [ /* Length codes 257..285 base */ + 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, 0, 0 +]; + +var lext = [ /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 78 +]; + +var dbase = [ /* Distance codes 0..29 base */ + 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, 0, 0 +]; + +var dext = [ /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64 +]; + +module.exports = function inflate_table(type, lens, lens_index, codes, table, table_index, work, opts) +{ + var bits = opts.bits; + //here = opts.here; /* table entry for duplication */ + + var len = 0; /* a code's length in bits */ + var sym = 0; /* index of code symbols */ + var min = 0, max = 0; /* minimum and maximum code lengths */ + var root = 0; /* number of index bits for root table */ + var curr = 0; /* number of index bits for current table */ + var drop = 0; /* code bits to drop for sub-table */ + var left = 0; /* number of prefix codes available */ + var used = 0; /* code entries in table used */ + var huff = 0; /* Huffman code */ + var incr; /* for incrementing code, index */ + var fill; /* index for replicating entries */ + var low; /* low bits for current root entry */ + var mask; /* mask for low root bits */ + var next; /* next available space in table */ + var base = null; /* base value table to use */ + var base_index = 0; +// var shoextra; /* extra bits table to use */ + var end; /* use base and extra for symbol > end */ + var count = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* number of codes of each length */ + var offs = new utils.Buf16(MAXBITS + 1); //[MAXBITS+1]; /* offsets in table for each length */ + var extra = null; + var extra_index = 0; + + var here_bits, here_op, here_val; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) { + count[len] = 0; + } + for (sym = 0; sym < codes; sym++) { + count[lens[lens_index + sym]]++; + } + + /* bound code lengths, force root to be within code lengths */ + root = bits; + for (max = MAXBITS; max >= 1; max--) { + if (count[max] !== 0) { break; } + } + if (root > max) { + root = max; + } + if (max === 0) { /* no symbols to code at all */ + //table.op[opts.table_index] = 64; //here.op = (var char)64; /* invalid code marker */ + //table.bits[opts.table_index] = 1; //here.bits = (var char)1; + //table.val[opts.table_index++] = 0; //here.val = (var short)0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + + //table.op[opts.table_index] = 64; + //table.bits[opts.table_index] = 1; + //table.val[opts.table_index++] = 0; + table[table_index++] = (1 << 24) | (64 << 16) | 0; + + opts.bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) { + if (count[min] !== 0) { break; } + } + if (root < min) { + root = min; + } + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) { + return -1; + } /* over-subscribed */ + } + if (left > 0 && (type === CODES || max !== 1)) { + return -1; /* incomplete set */ + } + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) { + offs[len + 1] = offs[len] + count[len]; + } + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) { + if (lens[lens_index + sym] !== 0) { + work[offs[lens[lens_index + sym]]++] = sym; + } + } + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + // poor man optimization - use if-else instead of switch, + // to avoid deopts in old v8 + if (type === CODES) { + base = extra = work; /* dummy value--not used */ + end = 19; + + } else if (type === LENS) { + base = lbase; + base_index -= 257; + extra = lext; + extra_index -= 257; + end = 256; + + } else { /* DISTS */ + base = dbase; + extra = dext; + end = -1; + } + + /* initialize opts for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = table_index; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = -1; /* trigger new sub-table when len > root */ + used = 1 << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type === LENS && used > ENOUGH_LENS) || + (type === DISTS && used > ENOUGH_DISTS)) { + return 1; + } + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here_bits = len - drop; + if (work[sym] < end) { + here_op = 0; + here_val = work[sym]; + } + else if (work[sym] > end) { + here_op = extra[extra_index + work[sym]]; + here_val = base[base_index + work[sym]]; + } + else { + here_op = 32 + 64; /* end of block */ + here_val = 0; } - function installMessageChannelImplementation() { - var channel = new MessageChannel(); - channel.port1.onmessage = function(event) { - var handle = event.data; - runIfPresent(handle); - }; + /* replicate for those indices with low len bits equal to huff */ + incr = 1 << (len - drop); + fill = 1 << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + table[next + (huff >> drop) + fill] = (here_bits << 24) | (here_op << 16) | here_val |0; + } while (fill !== 0); - registerImmediate = function(handle) { - channel.port2.postMessage(handle); - }; + /* backwards increment the len-bit code huff */ + incr = 1 << (len - 1); + while (huff & incr) { + incr >>= 1; + } + if (incr !== 0) { + huff &= incr - 1; + huff += incr; + } else { + huff = 0; } - function installReadyStateChangeImplementation() { - var html = doc.documentElement; - registerImmediate = function(handle) { - // Create a