buddy

node MVC discord bot
Log | Files | Refs | README

Guild.js (40795B)


      1 'use strict';
      2 
      3 const Base = require('./Base');
      4 const GuildAuditLogs = require('./GuildAuditLogs');
      5 const GuildPreview = require('./GuildPreview');
      6 const Integration = require('./Integration');
      7 const Invite = require('./Invite');
      8 const VoiceRegion = require('./VoiceRegion');
      9 const Webhook = require('./Webhook');
     10 const GuildChannelManager = require('../managers/GuildChannelManager');
     11 const GuildEmojiManager = require('../managers/GuildEmojiManager');
     12 const GuildMemberManager = require('../managers/GuildMemberManager');
     13 const PresenceManager = require('../managers/PresenceManager');
     14 const RoleManager = require('../managers/RoleManager');
     15 const VoiceStateManager = require('../managers/VoiceStateManager');
     16 const Collection = require('../util/Collection');
     17 const {
     18   ChannelTypes,
     19   DefaultMessageNotifications,
     20   PartialTypes,
     21   VerificationLevels,
     22   ExplicitContentFilterLevels,
     23 } = require('../util/Constants');
     24 const DataResolver = require('../util/DataResolver');
     25 const Snowflake = require('../util/Snowflake');
     26 const SystemChannelFlags = require('../util/SystemChannelFlags');
     27 const Util = require('../util/Util');
     28 
     29 /**
     30  * Represents a guild (or a server) on Discord.
     31  * <info>It's recommended to see if a guild is available before performing operations or reading data from it. You can
     32  * check this with `guild.available`.</info>
     33  * @extends {Base}
     34  */
     35 class Guild extends Base {
     36   /**
     37    * @param {Client} client The instantiating client
     38    * @param {Object} data The data for the guild
     39    */
     40   constructor(client, data) {
     41     super(client);
     42 
     43     /**
     44      * A manager of the members belonging to this guild
     45      * @type {GuildMemberManager}
     46      */
     47     this.members = new GuildMemberManager(this);
     48 
     49     /**
     50      * A manager of the channels belonging to this guild
     51      * @type {GuildChannelManager}
     52      */
     53     this.channels = new GuildChannelManager(this);
     54 
     55     /**
     56      * A manager of the roles belonging to this guild
     57      * @type {RoleManager}
     58      */
     59     this.roles = new RoleManager(this);
     60 
     61     /**
     62      * A manager of the presences belonging to this guild
     63      * @type {PresenceManager}
     64      */
     65     this.presences = new PresenceManager(this.client);
     66 
     67     /**
     68      * A manager of the voice states of this guild
     69      * @type {VoiceStateManager}
     70      */
     71     this.voiceStates = new VoiceStateManager(this);
     72 
     73     /**
     74      * Whether the bot has been removed from the guild
     75      * @type {boolean}
     76      */
     77     this.deleted = false;
     78 
     79     if (!data) return;
     80     if (data.unavailable) {
     81       /**
     82        * Whether the guild is available to access. If it is not available, it indicates a server outage
     83        * @type {boolean}
     84        */
     85       this.available = false;
     86 
     87       /**
     88        * The Unique ID of the guild, useful for comparisons
     89        * @type {Snowflake}
     90        */
     91       this.id = data.id;
     92     } else {
     93       this._patch(data);
     94       if (!data.channels) this.available = false;
     95     }
     96 
     97     /**
     98      * The id of the shard this Guild belongs to.
     99      * @type {number}
    100      */
    101     this.shardID = data.shardID;
    102   }
    103 
    104   /**
    105    * The Shard this Guild belongs to.
    106    * @type {WebSocketShard}
    107    * @readonly
    108    */
    109   get shard() {
    110     return this.client.ws.shards.get(this.shardID);
    111   }
    112 
    113   /**
    114    * Sets up the guild.
    115    * @param {*} data The raw data of the guild
    116    * @private
    117    */
    118   _patch(data) {
    119     /**
    120      * The name of the guild
    121      * @type {string}
    122      */
    123     this.name = data.name;
    124 
    125     /**
    126      * The hash of the guild icon
    127      * @type {?string}
    128      */
    129     this.icon = data.icon;
    130 
    131     /**
    132      * The hash of the guild splash image (VIP only)
    133      * @type {?string}
    134      */
    135     this.splash = data.splash;
    136 
    137     /**
    138      * The region the guild is located in
    139      * @type {string}
    140      */
    141     this.region = data.region;
    142 
    143     /**
    144      * The full amount of members in this guild
    145      * @type {number}
    146      */
    147     this.memberCount = data.member_count || this.memberCount;
    148 
    149     /**
    150      * Whether the guild is "large" (has more than 250 members)
    151      * @type {boolean}
    152      */
    153     this.large = Boolean('large' in data ? data.large : this.large);
    154 
    155     /**
    156      * An array of enabled guild features, here are the possible values:
    157      * * ANIMATED_ICON
    158      * * BANNER
    159      * * COMMERCE
    160      * * DISCOVERABLE
    161      * * FEATURABLE
    162      * * INVITE_SPLASH
    163      * * NEWS
    164      * * PARTNERED
    165      * * PUBLIC
    166      * * PUBLIC_DISABLED
    167      * * VANITY_URL
    168      * * VERIFIED
    169      * * VIP_REGIONS
    170      * * WELCOME_SCREEN_ENABLED
    171      * @typedef {string} Features
    172      */
    173 
    174     /**
    175      * An array of guild features partnered guilds have enabled
    176      * @type {Features[]}
    177      */
    178     this.features = data.features;
    179 
    180     /**
    181      * The ID of the application that created this guild (if applicable)
    182      * @type {?Snowflake}
    183      */
    184     this.applicationID = data.application_id;
    185 
    186     /**
    187      * The time in seconds before a user is counted as "away from keyboard"
    188      * @type {?number}
    189      */
    190     this.afkTimeout = data.afk_timeout;
    191 
    192     /**
    193      * The ID of the voice channel where AFK members are moved
    194      * @type {?Snowflake}
    195      */
    196     this.afkChannelID = data.afk_channel_id;
    197 
    198     /**
    199      * The ID of the system channel
    200      * @type {?Snowflake}
    201      */
    202     this.systemChannelID = data.system_channel_id;
    203 
    204     /**
    205      * Whether embedded images are enabled on this guild
    206      * @type {boolean}
    207      */
    208     this.embedEnabled = data.embed_enabled;
    209 
    210     /**
    211      * The type of premium tier:
    212      * * 0: NONE
    213      * * 1: TIER_1
    214      * * 2: TIER_2
    215      * * 3: TIER_3
    216      * @typedef {number} PremiumTier
    217      */
    218 
    219     /**
    220      * The premium tier on this guild
    221      * @type {PremiumTier}
    222      */
    223     this.premiumTier = data.premium_tier;
    224 
    225     /**
    226      * The total number of users currently boosting this server
    227      * @type {?number}
    228      * @name Guild#premiumSubscriptionCount
    229      */
    230     if (typeof data.premium_subscription_count !== 'undefined') {
    231       this.premiumSubscriptionCount = data.premium_subscription_count;
    232     }
    233 
    234     /**
    235      * Whether widget images are enabled on this guild
    236      * @type {?boolean}
    237      * @name Guild#widgetEnabled
    238      */
    239     if (typeof data.widget_enabled !== 'undefined') this.widgetEnabled = data.widget_enabled;
    240 
    241     /**
    242      * The widget channel ID, if enabled
    243      * @type {?string}
    244      * @name Guild#widgetChannelID
    245      */
    246     if (typeof data.widget_channel_id !== 'undefined') this.widgetChannelID = data.widget_channel_id;
    247 
    248     /**
    249      * The embed channel ID, if enabled
    250      * @type {?string}
    251      * @name Guild#embedChannelID
    252      */
    253     if (typeof data.embed_channel_id !== 'undefined') this.embedChannelID = data.embed_channel_id;
    254 
    255     /**
    256      * The verification level of the guild
    257      * @type {VerificationLevel}
    258      */
    259     this.verificationLevel = VerificationLevels[data.verification_level];
    260 
    261     /**
    262      * The explicit content filter level of the guild
    263      * @type {ExplicitContentFilterLevel}
    264      */
    265     this.explicitContentFilter = ExplicitContentFilterLevels[data.explicit_content_filter];
    266 
    267     /**
    268      * The required MFA level for the guild
    269      * @type {number}
    270      */
    271     this.mfaLevel = data.mfa_level;
    272 
    273     /**
    274      * The timestamp the client user joined the guild at
    275      * @type {number}
    276      */
    277     this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp;
    278 
    279     /**
    280      * The value set for the guild's default message notifications
    281      * @type {DefaultMessageNotifications|number}
    282      */
    283     this.defaultMessageNotifications =
    284       DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications;
    285 
    286     /**
    287      * The value set for the guild's system channel flags
    288      * @type {Readonly<SystemChannelFlags>}
    289      */
    290     this.systemChannelFlags = new SystemChannelFlags(data.system_channel_flags).freeze();
    291 
    292     /**
    293      * The maximum amount of members the guild can have
    294      * <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
    295      * @type {?number}
    296      * @name Guild#maximumMembers
    297      */
    298     if (typeof data.max_members !== 'undefined') this.maximumMembers = data.max_members || 250000;
    299 
    300     /**
    301      * The maximum amount of presences the guild can have
    302      * <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
    303      * @type {?number}
    304      * @name Guild#maximumPresences
    305      */
    306     if (typeof data.max_presences !== 'undefined') this.maximumPresences = data.max_presences || 25000;
    307 
    308     /**
    309      * The vanity URL code of the guild, if any
    310      * @type {?string}
    311      */
    312     this.vanityURLCode = data.vanity_url_code;
    313 
    314     /**
    315      * The description of the guild, if any
    316      * @type {?string}
    317      */
    318     this.description = data.description;
    319 
    320     /**
    321      * The hash of the guild banner
    322      * @type {?string}
    323      */
    324     this.banner = data.banner;
    325 
    326     this.id = data.id;
    327     this.available = !data.unavailable;
    328     this.features = data.features || this.features || [];
    329 
    330     /**
    331      * The ID of the rules channel for the guild
    332      * <info>This is only available on guilds with the `PUBLIC` feature</info>
    333      * @type {?Snowflake}
    334      */
    335     this.rulesChannelID = data.rules_channel_id;
    336 
    337     /**
    338      * The ID of the public updates channel for the guild
    339      * <info>This is only available on guilds with the `PUBLIC` feature</info>
    340      * @type {?Snowflake}
    341      */
    342     this.publicUpdatesChannelID = data.public_updates_channel_id;
    343 
    344     if (data.channels) {
    345       this.channels.cache.clear();
    346       for (const rawChannel of data.channels) {
    347         this.client.channels.add(rawChannel, this);
    348       }
    349     }
    350 
    351     if (data.roles) {
    352       this.roles.cache.clear();
    353       for (const role of data.roles) this.roles.add(role);
    354     }
    355 
    356     if (data.members) {
    357       this.members.cache.clear();
    358       for (const guildUser of data.members) this.members.add(guildUser);
    359     }
    360 
    361     if (data.owner_id) {
    362       /**
    363        * The user ID of this guild's owner
    364        * @type {Snowflake}
    365        */
    366       this.ownerID = data.owner_id;
    367     }
    368 
    369     if (data.presences) {
    370       for (const presence of data.presences) {
    371         this.presences.add(Object.assign(presence, { guild: this }));
    372       }
    373     }
    374 
    375     if (data.voice_states) {
    376       this.voiceStates.cache.clear();
    377       for (const voiceState of data.voice_states) {
    378         this.voiceStates.add(voiceState);
    379       }
    380     }
    381 
    382     if (!this.emojis) {
    383       /**
    384        * A manager of the emojis belonging to this guild
    385        * @type {GuildEmojiManager}
    386        */
    387       this.emojis = new GuildEmojiManager(this);
    388       if (data.emojis) for (const emoji of data.emojis) this.emojis.add(emoji);
    389     } else if (data.emojis) {
    390       this.client.actions.GuildEmojisUpdate.handle({
    391         guild_id: this.id,
    392         emojis: data.emojis,
    393       });
    394     }
    395   }
    396 
    397   /**
    398    * The URL to this guild's banner.
    399    * @param {ImageURLOptions} [options={}] Options for the Image URL
    400    * @returns {?string}
    401    */
    402   bannerURL({ format, size } = {}) {
    403     if (!this.banner) return null;
    404     return this.client.rest.cdn.Banner(this.id, this.banner, format, size);
    405   }
    406 
    407   /**
    408    * The timestamp the guild was created at
    409    * @type {number}
    410    * @readonly
    411    */
    412   get createdTimestamp() {
    413     return Snowflake.deconstruct(this.id).timestamp;
    414   }
    415 
    416   /**
    417    * The time the guild was created at
    418    * @type {Date}
    419    * @readonly
    420    */
    421   get createdAt() {
    422     return new Date(this.createdTimestamp);
    423   }
    424 
    425   /**
    426    * The time the client user joined the guild
    427    * @type {Date}
    428    * @readonly
    429    */
    430   get joinedAt() {
    431     return new Date(this.joinedTimestamp);
    432   }
    433 
    434   /**
    435    * If this guild is partnered
    436    * @type {boolean}
    437    * @readonly
    438    */
    439   get partnered() {
    440     return this.features.includes('PARTNERED');
    441   }
    442 
    443   /**
    444    * If this guild is verified
    445    * @type {boolean}
    446    * @readonly
    447    */
    448   get verified() {
    449     return this.features.includes('VERIFIED');
    450   }
    451 
    452   /**
    453    * The URL to this guild's icon.
    454    * @param {ImageURLOptions} [options={}] Options for the Image URL
    455    * @returns {?string}
    456    */
    457   iconURL({ format, size, dynamic } = {}) {
    458     if (!this.icon) return null;
    459     return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic);
    460   }
    461 
    462   /**
    463    * The acronym that shows up in place of a guild icon.
    464    * @type {string}
    465    * @readonly
    466    */
    467   get nameAcronym() {
    468     return this.name.replace(/\w+/g, name => name[0]).replace(/\s/g, '');
    469   }
    470 
    471   /**
    472    * The URL to this guild's splash.
    473    * @param {ImageURLOptions} [options={}] Options for the Image URL
    474    * @returns {?string}
    475    */
    476   splashURL({ format, size } = {}) {
    477     if (!this.splash) return null;
    478     return this.client.rest.cdn.Splash(this.id, this.splash, format, size);
    479   }
    480 
    481   /**
    482    * The owner of the guild
    483    * @type {?GuildMember}
    484    * @readonly
    485    */
    486   get owner() {
    487     return (
    488       this.members.cache.get(this.ownerID) ||
    489       (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
    490         ? this.members.add({ user: { id: this.ownerID } }, true)
    491         : null)
    492     );
    493   }
    494 
    495   /**
    496    * AFK voice channel for this guild
    497    * @type {?VoiceChannel}
    498    * @readonly
    499    */
    500   get afkChannel() {
    501     return this.client.channels.cache.get(this.afkChannelID) || null;
    502   }
    503 
    504   /**
    505    * System channel for this guild
    506    * @type {?TextChannel}
    507    * @readonly
    508    */
    509   get systemChannel() {
    510     return this.client.channels.cache.get(this.systemChannelID) || null;
    511   }
    512 
    513   /**
    514    * Widget channel for this guild
    515    * @type {?TextChannel}
    516    * @readonly
    517    */
    518   get widgetChannel() {
    519     return this.client.channels.cache.get(this.widgetChannelID) || null;
    520   }
    521 
    522   /**
    523    * Embed channel for this guild
    524    * @type {?TextChannel}
    525    * @readonly
    526    */
    527   get embedChannel() {
    528     return this.client.channels.cache.get(this.embedChannelID) || null;
    529   }
    530 
    531   /**
    532    * Rules channel for this guild
    533    * <info>This is only available on guilds with the `PUBLIC` feature</info>
    534    * @type {?TextChannel}
    535    * @readonly
    536    */
    537   get rulesChannel() {
    538     return this.client.channels.cache.get(this.rulesChannelID) || null;
    539   }
    540 
    541   /**
    542    * Public updates channel for this guild
    543    * <info>This is only available on guilds with the `PUBLIC` feature</info>
    544    * @type {?TextChannel}
    545    * @readonly
    546    */
    547   get publicUpdatesChannel() {
    548     return this.client.channels.cache.get(this.publicUpdatesChannelID) || null;
    549   }
    550 
    551   /**
    552    * The client user as a GuildMember of this guild
    553    * @type {?GuildMember}
    554    * @readonly
    555    */
    556   get me() {
    557     return (
    558       this.members.cache.get(this.client.user.id) ||
    559       (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
    560         ? this.members.add({ user: { id: this.client.user.id } }, true)
    561         : null)
    562     );
    563   }
    564 
    565   /**
    566    * The voice state for the client user of this guild, if any
    567    * @type {?VoiceState}
    568    * @readonly
    569    */
    570   get voice() {
    571     return this.voiceStates.cache.get(this.client.user.id);
    572   }
    573 
    574   /**
    575    * Returns the GuildMember form of a User object, if the user is present in the guild.
    576    * @param {UserResolvable} user The user that you want to obtain the GuildMember of
    577    * @returns {?GuildMember}
    578    * @example
    579    * // Get the guild member of a user
    580    * const member = guild.member(message.author);
    581    */
    582   member(user) {
    583     return this.members.resolve(user);
    584   }
    585 
    586   /**
    587    * Fetches this guild.
    588    * @returns {Promise<Guild>}
    589    */
    590   fetch() {
    591     return this.client.api
    592       .guilds(this.id)
    593       .get()
    594       .then(data => {
    595         this._patch(data);
    596         return this;
    597       });
    598   }
    599 
    600   /**
    601    * An object containing information about a guild member's ban.
    602    * @typedef {Object} BanInfo
    603    * @property {User} user User that was banned
    604    * @property {?string} reason Reason the user was banned
    605    */
    606 
    607   /**
    608    * Fetches information on a banned user from this guild.
    609    * @param {UserResolvable} user The User to fetch the ban info of
    610    * @returns {Promise<BanInfo>}
    611    */
    612   fetchBan(user) {
    613     const id = this.client.users.resolveID(user);
    614     if (!id) throw new Error('FETCH_BAN_RESOLVE_ID');
    615     return this.client.api
    616       .guilds(this.id)
    617       .bans(id)
    618       .get()
    619       .then(ban => ({
    620         reason: ban.reason,
    621         user: this.client.users.add(ban.user),
    622       }));
    623   }
    624 
    625   /**
    626    * Fetches a collection of banned users in this guild.
    627    * @returns {Promise<Collection<Snowflake, BanInfo>>}
    628    */
    629   fetchBans() {
    630     return this.client.api
    631       .guilds(this.id)
    632       .bans.get()
    633       .then(bans =>
    634         bans.reduce((collection, ban) => {
    635           collection.set(ban.user.id, {
    636             reason: ban.reason,
    637             user: this.client.users.add(ban.user),
    638           });
    639           return collection;
    640         }, new Collection()),
    641       );
    642   }
    643 
    644   /**
    645    * Fetches a collection of integrations to this guild.
    646    * Resolves with a collection mapping integrations by their ids.
    647    * @returns {Promise<Collection<string, Integration>>}
    648    * @example
    649    * // Fetch integrations
    650    * guild.fetchIntegrations()
    651    *   .then(integrations => console.log(`Fetched ${integrations.size} integrations`))
    652    *   .catch(console.error);
    653    */
    654   fetchIntegrations() {
    655     return this.client.api
    656       .guilds(this.id)
    657       .integrations.get()
    658       .then(data =>
    659         data.reduce(
    660           (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)),
    661           new Collection(),
    662         ),
    663       );
    664   }
    665 
    666   /**
    667    * The data for creating an integration.
    668    * @typedef {Object} IntegrationData
    669    * @property {string} id The integration id
    670    * @property {string} type The integration type
    671    */
    672 
    673   /**
    674    * Creates an integration by attaching an integration object
    675    * @param {IntegrationData} data The data for the integration
    676    * @param {string} reason Reason for creating the integration
    677    * @returns {Promise<Guild>}
    678    */
    679   createIntegration(data, reason) {
    680     return this.client.api
    681       .guilds(this.id)
    682       .integrations.post({ data, reason })
    683       .then(() => this);
    684   }
    685 
    686   /**
    687    * Fetches a collection of invites to this guild.
    688    * Resolves with a collection mapping invites by their codes.
    689    * @returns {Promise<Collection<string, Invite>>}
    690    * @example
    691    * // Fetch invites
    692    * guild.fetchInvites()
    693    *   .then(invites => console.log(`Fetched ${invites.size} invites`))
    694    *   .catch(console.error);
    695    * @example
    696    * // Fetch invite creator by their id
    697    * guild.fetchInvites()
    698    *  .then(invites => console.log(invites.find(invite => invite.inviter.id === '84484653687267328')))
    699    *  .catch(console.error);
    700    */
    701   fetchInvites() {
    702     return this.client.api
    703       .guilds(this.id)
    704       .invites.get()
    705       .then(inviteItems => {
    706         const invites = new Collection();
    707         for (const inviteItem of inviteItems) {
    708           const invite = new Invite(this.client, inviteItem);
    709           invites.set(invite.code, invite);
    710         }
    711         return invites;
    712       });
    713   }
    714 
    715   /**
    716    * Obtains a guild preview for this guild from Discord, only available for public guilds.
    717    * @returns {Promise<GuildPreview>}
    718    */
    719   fetchPreview() {
    720     return this.client.api
    721       .guilds(this.id)
    722       .preview.get()
    723       .then(data => new GuildPreview(this.client, data));
    724   }
    725 
    726   /**
    727    * Fetches the vanity url invite code to this guild.
    728    * Resolves with a string matching the vanity url invite code, not the full url.
    729    * @returns {Promise<string>}
    730    * @example
    731    * // Fetch invites
    732    * guild.fetchVanityCode()
    733    *   .then(code => {
    734    *     console.log(`Vanity URL: https://discord.gg/${code}`);
    735    *   })
    736    *   .catch(console.error);
    737    */
    738   fetchVanityCode() {
    739     if (!this.features.includes('VANITY_URL')) {
    740       return Promise.reject(new Error('VANITY_URL'));
    741     }
    742     return this.client.api
    743       .guilds(this.id, 'vanity-url')
    744       .get()
    745       .then(res => res.code);
    746   }
    747 
    748   /**
    749    * Fetches all webhooks for the guild.
    750    * @returns {Promise<Collection<Snowflake, Webhook>>}
    751    * @example
    752    * // Fetch webhooks
    753    * guild.fetchWebhooks()
    754    *   .then(webhooks => console.log(`Fetched ${webhooks.size} webhooks`))
    755    *   .catch(console.error);
    756    */
    757   fetchWebhooks() {
    758     return this.client.api
    759       .guilds(this.id)
    760       .webhooks.get()
    761       .then(data => {
    762         const hooks = new Collection();
    763         for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook));
    764         return hooks;
    765       });
    766   }
    767 
    768   /**
    769    * Fetches available voice regions.
    770    * @returns {Promise<Collection<string, VoiceRegion>>}
    771    */
    772   fetchVoiceRegions() {
    773     return this.client.api
    774       .guilds(this.id)
    775       .regions.get()
    776       .then(res => {
    777         const regions = new Collection();
    778         for (const region of res) regions.set(region.id, new VoiceRegion(region));
    779         return regions;
    780       });
    781   }
    782 
    783   /**
    784    * The Guild Embed object
    785    * @typedef {Object} GuildEmbedData
    786    * @property {boolean} enabled Whether the embed is enabled
    787    * @property {?GuildChannel} channel The embed channel
    788    */
    789 
    790   /**
    791    * Fetches the guild embed.
    792    * @returns {Promise<GuildEmbedData>}
    793    * @example
    794    * // Fetches the guild embed
    795    * guild.fetchEmbed()
    796    *   .then(embed => console.log(`The embed is ${embed.enabled ? 'enabled' : 'disabled'}`))
    797    *   .catch(console.error);
    798    */
    799   fetchEmbed() {
    800     return this.client.api
    801       .guilds(this.id)
    802       .embed.get()
    803       .then(data => ({
    804         enabled: data.enabled,
    805         channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null,
    806       }));
    807   }
    808 
    809   /**
    810    * Fetches audit logs for this guild.
    811    * @param {Object} [options={}] Options for fetching audit logs
    812    * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry
    813    * @param {number} [options.limit] Limit number of entries
    814    * @param {UserResolvable} [options.user] Only show entries involving this user
    815    * @param {AuditLogAction|number} [options.type] Only show entries involving this action type
    816    * @returns {Promise<GuildAuditLogs>}
    817    * @example
    818    * // Output audit log entries
    819    * guild.fetchAuditLogs()
    820    *   .then(audit => console.log(audit.entries.first()))
    821    *   .catch(console.error);
    822    */
    823   fetchAuditLogs(options = {}) {
    824     if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id;
    825     if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type];
    826 
    827     return this.client.api
    828       .guilds(this.id)
    829       ['audit-logs'].get({
    830         query: {
    831           before: options.before,
    832           limit: options.limit,
    833           user_id: this.client.users.resolveID(options.user),
    834           action_type: options.type,
    835         },
    836       })
    837       .then(data => GuildAuditLogs.build(this, data));
    838   }
    839 
    840   /**
    841    * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission.
    842    * @param {UserResolvable} user User to add to the guild
    843    * @param {Object} options Options for the addition
    844    * @param {string} options.accessToken An OAuth2 access token for the user with the `guilds.join` scope granted to the
    845    * bot's application
    846    * @param {string} [options.nick] Nickname to give the member (requires `MANAGE_NICKNAMES`)
    847    * @param {Collection<Snowflake, Role>|RoleResolvable[]} [options.roles] Roles to add to the member
    848    * (requires `MANAGE_ROLES`)
    849    * @param {boolean} [options.mute] Whether the member should be muted (requires `MUTE_MEMBERS`)
    850    * @param {boolean} [options.deaf] Whether the member should be deafened (requires `DEAFEN_MEMBERS`)
    851    * @returns {Promise<GuildMember>}
    852    */
    853   addMember(user, options) {
    854     user = this.client.users.resolveID(user);
    855     if (!user) return Promise.reject(new TypeError('INVALID_TYPE', 'user', 'UserResolvable'));
    856     if (this.members.cache.has(user)) return Promise.resolve(this.members.cache.get(user));
    857     options.access_token = options.accessToken;
    858     if (options.roles) {
    859       const roles = [];
    860       for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) {
    861         role = this.roles.resolve(role);
    862         if (!role) {
    863           return Promise.reject(
    864             new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true),
    865           );
    866         }
    867         roles.push(role.id);
    868       }
    869       options.roles = roles;
    870     }
    871     return this.client.api
    872       .guilds(this.id)
    873       .members(user)
    874       .put({ data: options })
    875       .then(data => this.members.add(data));
    876   }
    877 
    878   /**
    879    * The data for editing a guild.
    880    * @typedef {Object} GuildEditData
    881    * @property {string} [name] The name of the guild
    882    * @property {string} [region] The region of the guild
    883    * @property {VerificationLevel|number} [verificationLevel] The verification level of the guild
    884    * @property {ExplicitContentFilterLevel|number} [explicitContentFilter] The level of the explicit content filter
    885    * @property {ChannelResolvable} [afkChannel] The AFK channel of the guild
    886    * @property {ChannelResolvable} [systemChannel] The system channel of the guild
    887    * @property {number} [afkTimeout] The AFK timeout of the guild
    888    * @property {Base64Resolvable} [icon] The icon of the guild
    889    * @property {GuildMemberResolvable} [owner] The owner of the guild
    890    * @property {Base64Resolvable} [splash] The splash screen of the guild
    891    * @property {Base64Resolvable} [banner] The banner of the guild
    892    * @property {DefaultMessageNotifications|number} [defaultMessageNotifications] The default message notifications
    893    * @property {SystemChannelFlagsResolvable} [systemChannelFlags] The system channel flags of the guild
    894    */
    895 
    896   /**
    897    * Updates the guild with new information - e.g. a new name.
    898    * @param {GuildEditData} data The data to update the guild with
    899    * @param {string} [reason] Reason for editing this guild
    900    * @returns {Promise<Guild>}
    901    * @example
    902    * // Set the guild name and region
    903    * guild.edit({
    904    *   name: 'Discord Guild',
    905    *   region: 'london',
    906    * })
    907    *   .then(updated => console.log(`New guild name ${updated} in region ${updated.region}`))
    908    *   .catch(console.error);
    909    */
    910   edit(data, reason) {
    911     const _data = {};
    912     if (data.name) _data.name = data.name;
    913     if (data.region) _data.region = data.region;
    914     if (typeof data.verificationLevel !== 'undefined') {
    915       _data.verification_level =
    916         typeof data.verificationLevel === 'number'
    917           ? Number(data.verificationLevel)
    918           : VerificationLevels.indexOf(data.verificationLevel);
    919     }
    920     if (typeof data.afkChannel !== 'undefined') {
    921       _data.afk_channel_id = this.client.channels.resolveID(data.afkChannel);
    922     }
    923     if (typeof data.systemChannel !== 'undefined') {
    924       _data.system_channel_id = this.client.channels.resolveID(data.systemChannel);
    925     }
    926     if (data.afkTimeout) _data.afk_timeout = Number(data.afkTimeout);
    927     if (typeof data.icon !== 'undefined') _data.icon = data.icon;
    928     if (data.owner) _data.owner_id = this.client.users.resolveID(data.owner);
    929     if (data.splash) _data.splash = data.splash;
    930     if (data.banner) _data.banner = data.banner;
    931     if (typeof data.explicitContentFilter !== 'undefined') {
    932       _data.explicit_content_filter =
    933         typeof data.explicitContentFilter === 'number'
    934           ? data.explicitContentFilter
    935           : ExplicitContentFilterLevels.indexOf(data.explicitContentFilter);
    936     }
    937     if (typeof data.defaultMessageNotifications !== 'undefined') {
    938       _data.default_message_notifications =
    939         typeof data.defaultMessageNotifications === 'string'
    940           ? DefaultMessageNotifications.indexOf(data.defaultMessageNotifications)
    941           : data.defaultMessageNotifications;
    942     }
    943     if (typeof data.systemChannelFlags !== 'undefined') {
    944       _data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags);
    945     }
    946     return this.client.api
    947       .guilds(this.id)
    948       .patch({ data: _data, reason })
    949       .then(newData => this.client.actions.GuildUpdate.handle(newData).updated);
    950   }
    951 
    952   /**
    953    * Edits the level of the explicit content filter.
    954    * @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter
    955    * @param {string} [reason] Reason for changing the level of the guild's explicit content filter
    956    * @returns {Promise<Guild>}
    957    */
    958   setExplicitContentFilter(explicitContentFilter, reason) {
    959     return this.edit({ explicitContentFilter }, reason);
    960   }
    961 
    962   /* eslint-disable max-len */
    963   /**
    964    * Edits the setting of the default message notifications of the guild.
    965    * @param {DefaultMessageNotifications|number} defaultMessageNotifications The new setting for the default message notifications
    966    * @param {string} [reason] Reason for changing the setting of the default message notifications
    967    * @returns {Promise<Guild>}
    968    */
    969   setDefaultMessageNotifications(defaultMessageNotifications, reason) {
    970     return this.edit({ defaultMessageNotifications }, reason);
    971   }
    972   /* eslint-enable max-len */
    973 
    974   /**
    975    * Edits the flags of the default message notifications of the guild.
    976    * @param {SystemChannelFlagsResolvable} systemChannelFlags The new flags for the default message notifications
    977    * @param {string} [reason] Reason for changing the flags of the default message notifications
    978    * @returns {Promise<Guild>}
    979    */
    980   setSystemChannelFlags(systemChannelFlags, reason) {
    981     return this.edit({ systemChannelFlags }, reason);
    982   }
    983 
    984   /**
    985    * Edits the name of the guild.
    986    * @param {string} name The new name of the guild
    987    * @param {string} [reason] Reason for changing the guild's name
    988    * @returns {Promise<Guild>}
    989    * @example
    990    * // Edit the guild name
    991    * guild.setName('Discord Guild')
    992    *  .then(updated => console.log(`Updated guild name to ${guild}`))
    993    *  .catch(console.error);
    994    */
    995   setName(name, reason) {
    996     return this.edit({ name }, reason);
    997   }
    998 
    999   /**
   1000    * Edits the region of the guild.
   1001    * @param {string} region The new region of the guild
   1002    * @param {string} [reason] Reason for changing the guild's region
   1003    * @returns {Promise<Guild>}
   1004    * @example
   1005    * // Edit the guild region
   1006    * guild.setRegion('london')
   1007    *  .then(updated => console.log(`Updated guild region to ${updated.region}`))
   1008    *  .catch(console.error);
   1009    */
   1010   setRegion(region, reason) {
   1011     return this.edit({ region }, reason);
   1012   }
   1013 
   1014   /**
   1015    * Edits the verification level of the guild.
   1016    * @param {VerificationLevel|number} verificationLevel The new verification level of the guild
   1017    * @param {string} [reason] Reason for changing the guild's verification level
   1018    * @returns {Promise<Guild>}
   1019    * @example
   1020    * // Edit the guild verification level
   1021    * guild.setVerificationLevel(1)
   1022    *  .then(updated => console.log(`Updated guild verification level to ${guild.verificationLevel}`))
   1023    *  .catch(console.error);
   1024    */
   1025   setVerificationLevel(verificationLevel, reason) {
   1026     return this.edit({ verificationLevel }, reason);
   1027   }
   1028 
   1029   /**
   1030    * Edits the AFK channel of the guild.
   1031    * @param {ChannelResolvable} afkChannel The new AFK channel
   1032    * @param {string} [reason] Reason for changing the guild's AFK channel
   1033    * @returns {Promise<Guild>}
   1034    * @example
   1035    * // Edit the guild AFK channel
   1036    * guild.setAFKChannel(channel)
   1037    *  .then(updated => console.log(`Updated guild AFK channel to ${guild.afkChannel.name}`))
   1038    *  .catch(console.error);
   1039    */
   1040   setAFKChannel(afkChannel, reason) {
   1041     return this.edit({ afkChannel }, reason);
   1042   }
   1043 
   1044   /**
   1045    * Edits the system channel of the guild.
   1046    * @param {ChannelResolvable} systemChannel The new system channel
   1047    * @param {string} [reason] Reason for changing the guild's system channel
   1048    * @returns {Promise<Guild>}
   1049    * @example
   1050    * // Edit the guild system channel
   1051    * guild.setSystemChannel(channel)
   1052    *  .then(updated => console.log(`Updated guild system channel to ${guild.systemChannel.name}`))
   1053    *  .catch(console.error);
   1054    */
   1055   setSystemChannel(systemChannel, reason) {
   1056     return this.edit({ systemChannel }, reason);
   1057   }
   1058 
   1059   /**
   1060    * Edits the AFK timeout of the guild.
   1061    * @param {number} afkTimeout The time in seconds that a user must be idle to be considered AFK
   1062    * @param {string} [reason] Reason for changing the guild's AFK timeout
   1063    * @returns {Promise<Guild>}
   1064    * @example
   1065    * // Edit the guild AFK channel
   1066    * guild.setAFKTimeout(60)
   1067    *  .then(updated => console.log(`Updated guild AFK timeout to ${guild.afkTimeout}`))
   1068    *  .catch(console.error);
   1069    */
   1070   setAFKTimeout(afkTimeout, reason) {
   1071     return this.edit({ afkTimeout }, reason);
   1072   }
   1073 
   1074   /**
   1075    * Sets a new guild icon.
   1076    * @param {Base64Resolvable|BufferResolvable} icon The new icon of the guild
   1077    * @param {string} [reason] Reason for changing the guild's icon
   1078    * @returns {Promise<Guild>}
   1079    * @example
   1080    * // Edit the guild icon
   1081    * guild.setIcon('./icon.png')
   1082    *  .then(updated => console.log('Updated the guild icon'))
   1083    *  .catch(console.error);
   1084    */
   1085   async setIcon(icon, reason) {
   1086     return this.edit({ icon: await DataResolver.resolveImage(icon), reason });
   1087   }
   1088 
   1089   /**
   1090    * Sets a new owner of the guild.
   1091    * @param {GuildMemberResolvable} owner The new owner of the guild
   1092    * @param {string} [reason] Reason for setting the new owner
   1093    * @returns {Promise<Guild>}
   1094    * @example
   1095    * // Edit the guild owner
   1096    * guild.setOwner(guild.members.cache.first())
   1097    *  .then(updated => console.log(`Updated the guild owner to ${updated.owner.displayName}`))
   1098    *  .catch(console.error);
   1099    */
   1100   setOwner(owner, reason) {
   1101     return this.edit({ owner }, reason);
   1102   }
   1103 
   1104   /**
   1105    * Sets a new guild splash screen.
   1106    * @param {Base64Resolvable|BufferResolvable} splash The new splash screen of the guild
   1107    * @param {string} [reason] Reason for changing the guild's splash screen
   1108    * @returns {Promise<Guild>}
   1109    * @example
   1110    * // Edit the guild splash
   1111    * guild.setSplash('./splash.png')
   1112    *  .then(updated => console.log('Updated the guild splash'))
   1113    *  .catch(console.error);
   1114    */
   1115   async setSplash(splash, reason) {
   1116     return this.edit({ splash: await DataResolver.resolveImage(splash), reason });
   1117   }
   1118 
   1119   /**
   1120    * Sets a new guild banner.
   1121    * @param {Base64Resolvable|BufferResolvable} banner The new banner of the guild
   1122    * @param {string} [reason] Reason for changing the guild's banner
   1123    * @returns {Promise<Guild>}
   1124    * @example
   1125    * guild.setBanner('./banner.png')
   1126    *  .then(updated => console.log('Updated the guild banner'))
   1127    *  .catch(console.error);
   1128    */
   1129   async setBanner(banner, reason) {
   1130     return this.edit({ banner: await DataResolver.resolveImage(banner), reason });
   1131   }
   1132 
   1133   /**
   1134    * The data needed for updating a channel's position.
   1135    * @typedef {Object} ChannelPosition
   1136    * @property {ChannelResolvable} channel Channel to update
   1137    * @property {number} position New position for the channel
   1138    */
   1139 
   1140   /**
   1141    * Batch-updates the guild's channels' positions.
   1142    * @param {ChannelPosition[]} channelPositions Channel positions to update
   1143    * @returns {Promise<Guild>}
   1144    * @example
   1145    * guild.setChannelPositions([{ channel: channelID, position: newChannelIndex }])
   1146    *   .then(guild => console.log(`Updated channel positions for ${guild}`))
   1147    *   .catch(console.error);
   1148    */
   1149   setChannelPositions(channelPositions) {
   1150     const updatedChannels = channelPositions.map(r => ({
   1151       id: this.client.channels.resolveID(r.channel),
   1152       position: r.position,
   1153     }));
   1154 
   1155     return this.client.api
   1156       .guilds(this.id)
   1157       .channels.patch({ data: updatedChannels })
   1158       .then(
   1159         () =>
   1160           this.client.actions.GuildChannelsPositionUpdate.handle({
   1161             guild_id: this.id,
   1162             channels: updatedChannels,
   1163           }).guild,
   1164       );
   1165   }
   1166 
   1167   /**
   1168    * The data needed for updating a guild role's position
   1169    * @typedef {Object} GuildRolePosition
   1170    * @property {RoleResolveable} role The ID of the role
   1171    * @property {number} position The position to update
   1172    */
   1173 
   1174   /**
   1175    * Batch-updates the guild's role positions
   1176    * @param {GuildRolePosition[]} rolePositions Role positions to update
   1177    * @returns {Promise<Guild>}
   1178    * @example
   1179    * guild.setRolePositions([{ role: roleID, position: updatedRoleIndex }])
   1180    *  .then(guild => console.log(`Role permissions updated for ${guild}`))
   1181    *  .catch(console.error);
   1182    */
   1183   setRolePositions(rolePositions) {
   1184     // Make sure rolePositions are prepared for API
   1185     rolePositions = rolePositions.map(o => ({
   1186       id: this.roles.resolveID(o.role),
   1187       position: o.position,
   1188     }));
   1189 
   1190     // Call the API to update role positions
   1191     return this.client.api
   1192       .guilds(this.id)
   1193       .roles.patch({
   1194         data: rolePositions,
   1195       })
   1196       .then(
   1197         () =>
   1198           this.client.actions.GuildRolesPositionUpdate.handle({
   1199             guild_id: this.id,
   1200             roles: rolePositions,
   1201           }).guild,
   1202       );
   1203   }
   1204 
   1205   /**
   1206    * Edits the guild's embed.
   1207    * @param {GuildEmbedData} embed The embed for the guild
   1208    * @param {string} [reason] Reason for changing the guild's embed
   1209    * @returns {Promise<Guild>}
   1210    */
   1211   setEmbed(embed, reason) {
   1212     return this.client.api
   1213       .guilds(this.id)
   1214       .embed.patch({
   1215         data: {
   1216           enabled: embed.enabled,
   1217           channel_id: this.channels.resolveID(embed.channel),
   1218         },
   1219         reason,
   1220       })
   1221       .then(() => this);
   1222   }
   1223 
   1224   /**
   1225    * Leaves the guild.
   1226    * @returns {Promise<Guild>}
   1227    * @example
   1228    * // Leave a guild
   1229    * guild.leave()
   1230    *   .then(g => console.log(`Left the guild ${g}`))
   1231    *   .catch(console.error);
   1232    */
   1233   leave() {
   1234     if (this.ownerID === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED'));
   1235     return this.client.api
   1236       .users('@me')
   1237       .guilds(this.id)
   1238       .delete()
   1239       .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
   1240   }
   1241 
   1242   /**
   1243    * Deletes the guild.
   1244    * @returns {Promise<Guild>}
   1245    * @example
   1246    * // Delete a guild
   1247    * guild.delete()
   1248    *   .then(g => console.log(`Deleted the guild ${g}`))
   1249    *   .catch(console.error);
   1250    */
   1251   delete() {
   1252     return this.client.api
   1253       .guilds(this.id)
   1254       .delete()
   1255       .then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
   1256   }
   1257 
   1258   /**
   1259    * Whether this guild equals another guild. It compares all properties, so for most operations
   1260    * it is advisable to just compare `guild.id === guild2.id` as it is much faster and is often
   1261    * what most users need.
   1262    * @param {Guild} guild The guild to compare with
   1263    * @returns {boolean}
   1264    */
   1265   equals(guild) {
   1266     let equal =
   1267       guild &&
   1268       guild instanceof this.constructor &&
   1269       this.id === guild.id &&
   1270       this.available === guild.available &&
   1271       this.splash === guild.splash &&
   1272       this.region === guild.region &&
   1273       this.name === guild.name &&
   1274       this.memberCount === guild.memberCount &&
   1275       this.large === guild.large &&
   1276       this.icon === guild.icon &&
   1277       this.ownerID === guild.ownerID &&
   1278       this.verificationLevel === guild.verificationLevel &&
   1279       this.embedEnabled === guild.embedEnabled &&
   1280       (this.features === guild.features ||
   1281         (this.features.length === guild.features.length &&
   1282           this.features.every((feat, i) => feat === guild.features[i])));
   1283 
   1284     if (equal) {
   1285       if (this.embedChannel) {
   1286         if (!guild.embedChannel || this.embedChannel.id !== guild.embedChannel.id) equal = false;
   1287       } else if (guild.embedChannel) {
   1288         equal = false;
   1289       }
   1290     }
   1291 
   1292     return equal;
   1293   }
   1294 
   1295   /**
   1296    * When concatenated with a string, this automatically returns the guild's name instead of the Guild object.
   1297    * @returns {string}
   1298    * @example
   1299    * // Logs: Hello from My Guild!
   1300    * console.log(`Hello from ${guild}!`);
   1301    */
   1302   toString() {
   1303     return this.name;
   1304   }
   1305 
   1306   toJSON() {
   1307     const json = super.toJSON({
   1308       available: false,
   1309       createdTimestamp: true,
   1310       nameAcronym: true,
   1311       presences: false,
   1312       voiceStates: false,
   1313     });
   1314     json.iconURL = this.iconURL();
   1315     json.splashURL = this.splashURL();
   1316     json.bannerURL = this.bannerURL();
   1317     return json;
   1318   }
   1319 
   1320   /**
   1321    * Creates a collection of this guild's roles, sorted by their position and IDs.
   1322    * @returns {Collection<Role>}
   1323    * @private
   1324    */
   1325   _sortedRoles() {
   1326     return Util.discordSort(this.roles.cache);
   1327   }
   1328 
   1329   /**
   1330    * Creates a collection of this guild's or a specific category's channels, sorted by their position and IDs.
   1331    * @param {GuildChannel} [channel] Category to get the channels of
   1332    * @returns {Collection<GuildChannel>}
   1333    * @private
   1334    */
   1335   _sortedChannels(channel) {
   1336     const category = channel.type === ChannelTypes.CATEGORY;
   1337     return Util.discordSort(
   1338       this.channels.cache.filter(
   1339         c =>
   1340           (['text', 'news', 'store'].includes(channel.type)
   1341             ? ['text', 'news', 'store'].includes(c.type)
   1342             : c.type === channel.type) &&
   1343           (category || c.parent === channel.parent),
   1344       ),
   1345     );
   1346   }
   1347 }
   1348 
   1349 module.exports = Guild;