import type { Model } from './base'; import type { Session } from '../biscuit'; import { ChannelTypes, DefaultMessageNotificationLevels, DiscordBan, DiscordEmoji, DiscordGuild, DiscordGuildPreview, DiscordGuildWidget, DiscordGuildWidgetSettings, DiscordInvite, DiscordInviteMetadata, DiscordListActiveThreads, DiscordMemberWithUser, DiscordOverwrite, DiscordRole, DiscordVoiceRegion, DiscordChannel, ExplicitContentFilterLevels, GuildNsfwLevel, MakeRequired, SystemChannelFlags, VerificationLevels, VideoQualityModes, GetBans, GetInvite, ListGuildMembers, } from '@biscuitland/api-types'; import type { ImageFormat, ImageSize } from '../utils/util'; import { GuildFeatures, PremiumTiers } from '@biscuitland/api-types'; import { Snowflake } from '../snowflakes'; import { Util } from '../utils/util'; import { INVITE, GUILD_BANNER, GUILD_ICON, GUILD_SPLASH, USER_NICK, GUILD_EMOJI, GUILD_EMOJIS, GUILDS, GUILD_BANS, GUILD_VOICE_REGIONS, GUILD_BAN, GUILD_PRUNE, GUILD_INVITES, GUILD_MEMBER, GUILD_MEMBERS, GUILD_MEMBER_ROLE, GUILD_ROLE, GUILD_ROLES, THREAD_ACTIVE, GUILD_PREVIEW, GUILD_VANITY, GUILD_WIDGET, USER_GUILDS, CHANNEL, GUILD_CHANNELS, } from '@biscuitland/api-types'; import { ChannelFactory, GuildChannel, ReturnThreadsArchive, ThreadChannel, ChannelInGuild } from './channels'; import { Member, ThreadMember } from './members'; import { Role } from './role'; import { GuildEmoji } from './emojis'; import { urlToBase64 } from '../utils/url-to-base-64'; import { Invite } from './invite'; import { User } from './user'; import { Widget } from './widget'; import { Sticker } from './sticker'; import { WelcomeScreen } from './welcome'; /** BaseGuild */ /** * Class for {@link Guild} and {@link AnonymousGuild} */ export abstract class BaseGuild implements Model { constructor(session: Session, data: DiscordGuild) { this.session = session; this.id = data.id; this.name = data.name; this.iconHash = data.icon ? data.icon : undefined; this.features = data.features; } /** The session that instantiated the guild. */ readonly session: Session; /** Guild id. */ readonly id: Snowflake; /** Guild name. */ name: string; /** * Icon hash. Discord uses ids and hashes to render images in the client. * @link https://discord.com/developers/docs/reference#image-formatting */ iconHash?: string; /** * Enabled guild features (animated banner, news, auto moderation, etc). * @see {@link GuildFeatures} * @link https://discord.com/developers/docs/resources/guild#guild-object-guild-features */ features: GuildFeatures[]; /** createdTimestamp gets the current guild timestamp. */ get createdTimestamp(): number { return Snowflake.snowflakeToTimestamp(this.id); } /** createdAt gets the creation Date object of the guild. */ get createdAt(): Date { return new Date(this.createdTimestamp); } /** * If the guild features includes partnered. * @link https://discord.com/developers/docs/resources/guild#guild-object-guild-features */ get partnered(): boolean { return this.features.includes(GuildFeatures.Partnered); } /** * If the guild is verified. * @link https://discord.com/developers/docs/resources/guild#guild-object-guild-features */ get verified(): boolean { return this.features.includes(GuildFeatures.Verified); } /** * iconURL gets the current guild icon. * @link https://discord.com/developers/docs/reference#image-formatting */ iconURL( options: { size?: ImageSize; format?: ImageFormat } = { size: 128 } ): string | void { if (this.iconHash) { return Util.formatImageURL( GUILD_ICON(this.id, this.iconHash), options.size, options.format ); } } /** toString gets the guild name */ toString(): string { return this.name; } } /** AnonymousGuild */ /** * Class for anonymous guilds. * @see {@link BaseGuild} * @link https://discord.com/developers/docs/resources/guild#guild-resource */ export class AnonymousGuild extends BaseGuild implements Model { constructor(session: Session, data: Partial); // TODO: Improve this type (name and id are required) constructor(session: Session, data: DiscordGuild) { super(session, data); this.splashHash = data.splash ? data.splash : undefined; this.bannerHash = data.banner ? data.banner : undefined; this.verificationLevel = data.verification_level; this.vanityUrlCode = data.vanity_url_code ? data.vanity_url_code : undefined; this.nsfwLevel = data.nsfw_level; this.description = data.description ? data.description : undefined; this.premiumSubscriptionCount = data.premium_subscription_count; } /** * The guild's splash hash. * @link https://discord.com/developers/docs/reference#image-formatting */ splashHash?: string; /** * The guild's banner hash. * @link https://discord.com/developers/docs/reference#image-formatting */ bannerHash?: string; /** * The guild's verification level. * @see {@link VerificationLevels} * @link https://discord.com/developers/docs/resources/guild#guild-object-verification-level */ verificationLevel: VerificationLevels; /** The guild's vanity url code. */ vanityUrlCode?: string; /** * The guild's nsfw level. * @see {@link GuildNsfwLevel} * @link https://discord.com/developers/docs/resources/guild#guild-object-guild-nsfw-level */ nsfwLevel: GuildNsfwLevel; /** The guild's description. */ description?: string; /** The number of boosts this guild currently has. */ premiumSubscriptionCount?: number; /** * splashURL gets the current guild splash as a string. * @link https://discord.com/developers/docs/reference#image-formatting * @param options - Image options for the splash url. * @returns Splash url or void. */ splashURL( options: { size?: ImageSize; format?: ImageFormat } = { size: 128 } ): string | void { if (this.splashHash) { return Util.formatImageURL( GUILD_SPLASH(this.id, this.splashHash), options.size, options.format ); } } /** * bannerURL gets the current guild banner as a string. * @link https://discord.com/developers/docs/reference#image-formatting * @param options - Image options for the banner url. * @returns Banner url or void */ bannerURL( options: { size?: ImageSize; format?: ImageFormat } = { size: 128 } ): string | void { if (this.bannerHash) { return Util.formatImageURL( GUILD_BANNER(this.id, this.bannerHash), options.size, options.format ); } } } /** InviteGuild */ export class InviteGuild extends AnonymousGuild implements Model { constructor(session: Session, data: Partial) { super(session, data); if (data.welcome_screen) { this.welcomeScreen = new WelcomeScreen( session, data.welcome_screen ); } } welcomeScreen?: WelcomeScreen; } /** * Represent Discord Guild Preview Object * @link https://discord.com/developers/docs/resources/guild#guild-preview-object */ export class GuildPreview implements Model { constructor(session: Session, data: DiscordGuildPreview) { this.session = session; this.id = data.id; this.name = data.name; this.description = data.description ?? undefined; this.iconHash = data.icon ? Util.iconHashToBigInt(data.icon) : undefined; this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined; this.discoverySplashHash = data.discovery_splash ? Util.iconHashToBigInt(data.discovery_splash) : undefined; this.emojis = data.emojis.map( x => new GuildEmoji(this.session, x, this.id) ); this.features = data.features; this.approximateMemberCount = data.approximate_member_count; this.approximatePresenceCount = data.approximate_presence_count; this.stickers = data.stickers.map(x => new Sticker(this.session, x)); } session: Session; /** guild id */ id: Snowflake; /** guild name (2-100 characters) */ name: string; iconHash?: bigint; splashHash?: bigint; discoverySplashHash?: bigint; /** custom guild emojis */ emojis: GuildEmoji[]; /** enabled guild features */ features: GuildFeatures[]; /** approximate number of members in this guild */ approximateMemberCount: number; /** approximate number of online members in this guild */ approximatePresenceCount: number; /** the description for the guild */ description?: string; /** custom guild stickers */ stickers: Sticker[]; } /** Guild */ /** Maximun custom guild emojis per level */ export type MaxEmojis = 50 | 100 | 150 | 250; /** Maximun custom guild stickers per level */ export type MaxStickers = 5 | 15 | 30 | 60; export type EditBotNickname = { nick: string | null; reason?: string }; export interface CreateRole { name?: string; color?: number; iconHash?: string | bigint; unicodeEmoji?: string; hoist?: boolean; mentionable?: boolean; } export interface ModifyGuildRole { name?: string; color?: number; hoist?: boolean; mentionable?: boolean; unicodeEmoji?: string; } export interface CreateGuildEmoji { name: string; image: string; roles?: Snowflake[]; reason?: string; } export interface ModifyGuildEmoji { name?: string; roles?: Snowflake[]; } /** * @link https://discord.com/developers/docs/resources/guild#create-guild-ban */ export interface CreateGuildBan { deleteMessageDays?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7; reason?: string; } /** * @link https://discord.com/developers/docs/resources/guild#ban-object */ export interface GuildBan { reason?: string; user: User; } /** * @link https://discord.com/developers/docs/resources/guild#guild-widget-settings-object-guild-widget-settings-structure */ export interface GuildWidgetSettings { enabled: boolean; channelId?: Snowflake; } export interface PartialVanityURL { code: string; uses: number; } /** * @link https://discord.com/developers/docs/resources/guild#modify-guild-member */ export interface ModifyGuildMember { nick?: string; roles?: Snowflake[]; mute?: boolean; deaf?: boolean; channelId?: Snowflake; communicationDisabledUntil?: number; } /** * @link https://discord.com/developers/docs/resources/guild#begin-guild-prune */ export interface BeginGuildPrune { days?: number; computePruneCount?: boolean; includeRoles?: Snowflake[]; } export interface ModifyRolePositions { id: Snowflake; position?: number | null; } export interface GuildCreateOptionsRole { id: Snowflake; name?: string; color?: number; hoist?: boolean; position?: number; permissions?: bigint; mentionable?: boolean; icon?: string; unicodeEmoji?: string | null; } export interface GuildCreateOptionsChannel { id?: Snowflake; parentId?: Snowflake; type?: | ChannelTypes.GuildText | ChannelTypes.GuildVoice | ChannelTypes.GuildCategory; name: string; topic?: string | null; nsfw?: boolean; bitrate?: number; userLimit?: number; rtcRegion?: string | null; videoQualityMode?: VideoQualityModes; permissionOverwrites?: MakeRequired, 'id'>[]; rateLimitPerUser?: number; } /** * @link https://discord.com/developers/docs/resources/guild#create-guild */ export interface GuildCreateOptions { name: string; afkChannelId?: Snowflake; afkTimeout?: number; channels?: GuildCreateOptionsChannel[]; defaultMessageNotifications?: DefaultMessageNotificationLevels; explicitContentFilter?: ExplicitContentFilterLevels; icon?: string; roles?: GuildCreateOptionsRole[]; systemChannelFlags?: SystemChannelFlags; systemChannelId?: Snowflake; verificationLevel?: VerificationLevels; } /** * @link https://discord.com/developers/docs/resources/guild#modify-guild-json-params */ export interface GuildEditOptions extends Partial { ownerId?: Snowflake; splash?: string; banner?: string; discoverySplash?: string; features?: GuildFeatures[]; rulesChannelId?: Snowflake; publicUpdatesChannelId?: Snowflake; preferredLocale?: string | null; description?: string; premiumProgressBarEnabled?: boolean; } /** * Represents a guild. * @see {@link BaseGuild}. * @link https://discord.com/developers/docs/resources/guild#guild-object */ export class Guild extends BaseGuild implements Model { constructor(session: Session, data: DiscordGuild) { super(session, data); this.splashHash = data.splash ? Util.iconHashToBigInt(data.splash) : undefined; this.discoverySplashHash = data.discovery_splash ? Util.iconHashToBigInt(data.discovery_splash) : undefined; this.ownerId = data.owner_id; this.widgetEnabled = !!data.widget_enabled; this.widgetChannelId = data.widget_channel_id ? data.widget_channel_id : undefined; this.vefificationLevel = data.verification_level; this.defaultMessageNotificationLevel = data.default_message_notifications; this.explicitContentFilterLevel = data.explicit_content_filter; this.premiumTier = data.premium_tier; this.members = new Map( data.members?.map(member => [ data.id, new Member(session, { ...member, user: member.user! }, data.id), ]) ); this.roles = new Map( data.roles.map(role => [data.id, new Role(session, role, data.id)]) ); this.emojis = new Map( data.emojis.map(guildEmoji => [ guildEmoji.id!, new GuildEmoji(session, guildEmoji, data.id), ]) ); this.channels = new Map( data.channels?.map(guildChannel => [ guildChannel.id, new GuildChannel(session, guildChannel, data.id), ]) ); } /** * The guild's splash hash. * @link https://discord.com/developers/docs/reference#image-formatting */ splashHash?: bigint; /** * Only present for guilds with the "DISCOVERABLE" feature * @link https://discord.com/developers/docs/reference#image-formatting */ discoverySplashHash?: bigint; /** ID of the guild owner. */ ownerId: Snowflake; /** True if the server widget is enabled */ widgetEnabled: boolean; /** The channel id that the widget will generate an invite to, or undefined if set to no invite. */ widgetChannelId?: Snowflake; /** * Verification level required for the guild. * @see {@link VerificationLevels} * @link https://discord.com/developers/docs/resources/guild#guild-object-verification-level */ vefificationLevel: VerificationLevels; /** * The default message notification level. * @see {@link DefaultMessageNotificationLevels} * @link https://discord.com/developers/docs/resources/guild#guild-object-default-message-notification-level */ defaultMessageNotificationLevel: DefaultMessageNotificationLevels; /** * The explicit content filter level. * @see {@link ExplicitContentFilterLevels} * @link https://discord.com/developers/docs/resources/guild#guild-object-explicit-content-filter-level */ explicitContentFilterLevel: ExplicitContentFilterLevels; /** * Premium tier (Server Boost level). * @see {@link PremiumTiers} * @link https://discord.com/developers/docs/resources/guild#guild-object-premium-tier */ premiumTier: PremiumTiers; /** * A map with the guild's members. * @see {@link Member} * @link https://discord.com/developers/docs/resources/guild#guild-member-object */ members: Map; /** * A map with the guild's roles. * @see {@link Role} * @link https://discord.com/developers/docs/topics/permissions#role-object */ roles: Map; /** * A map with the guild's emojis. * @see {@link GuildEmoji} * @link https://discord.com/developers/docs/resources/emoji#emoji-object-emoji-structure */ emojis: Map; /** * A map with the guild's channels. * @see {@link GuildChannel} * @link https://discord.com/developers/docs/resources/channel#channel-object */ channels: Map; /** * Returns the maximum number of emoji slots */ get maxEmojis(): MaxEmojis { switch (this.premiumTier) { case 1: return 100; case 2: return 150; case 3: return 250; default: return 50; } } /** * Returns the maximum number of custom sticker slots */ get maxStickers(): MaxStickers { switch (this.premiumTier) { case 1: return 15; case 2: return 30; case 3: return 60; default: return 5; } } /** * edits the bot's nickname in the guild. * 'null' would reset the nickname. */ async editBotNickname( options: EditBotNickname ): Promise { const result = await this.session.rest.patch< { nick?: string } | undefined >(USER_NICK(this.id), options); return result?.nick; } /** * creates an emoji in the guild. * @see {@link CreateGuildEmoji} * @see {@link GuildEmoji} * @param options The options to create a emoji. * @returns A promise that resolves to the guild's new emoji. */ async createEmoji(options: CreateGuildEmoji): Promise { if (options.image && !options.image.startsWith('data:image/')) { options.image = await urlToBase64(options.image); } const emoji = await this.session.rest.post( GUILD_EMOJIS(this.id), options ); return new GuildEmoji(this.session, emoji, this.id); } /** * deletes an emoji from the guild. * @param id - The id of the emoji to delete. * @param reason - The reason for deleting the emoji. */ async deleteEmoji(id: Snowflake, reason?: string): Promise { await this.session.rest.delete(GUILD_EMOJI(this.id, id), { reason, }); } /** * edits an emoji in the guild. * @see {@link ModifyGuildEmoji} * @see {@link GuildEmoji} * @param id - The id of the emoji to edit. * @param options - Options to modify the emoji. * @returns A promise that resolves to the edited emoji. */ async editEmoji( id: Snowflake, options: ModifyGuildEmoji ): Promise { const emoji = await this.session.rest.patch( GUILD_EMOJI(this.id, id), options ); return new GuildEmoji(this.session, emoji, this.id); } /** * creates a role in the guild. * @see {@link CreateRole} * @see {@link Role} * @param options - Options to create a new role. */ async createRole(options: CreateRole): Promise { let icon: string | undefined; if (options.iconHash) { if (typeof options.iconHash === 'string') { icon = options.iconHash; } else { icon = Util.iconBigintToHash(options.iconHash); } } const role = await this.session.rest.put( GUILD_ROLES(this.id), { name: options.name, color: options.color, icon, unicode_emoji: options.unicodeEmoji, hoist: options.hoist, mentionable: options.mentionable, } ); return new Role(this.session, role, this.id); } /** * deletes a role from the guild. * @param roleId - The id of the role to delete. */ async deleteRole(roleId: Snowflake): Promise { await this.session.rest.delete( GUILD_ROLE(this.id, roleId), {} ); } /** * edits a role in the guild. * @see {@link ModifyGuildRole} * @see {@link Role} * @param roleId - The id of the role to edit. * @param options - Options to modify the role. */ async editRole(roleId: Snowflake, options: ModifyGuildRole): Promise { const role = await this.session.rest.patch( GUILD_ROLE(this.id, roleId), { name: options.name, color: options.color, hoist: options.hoist, mentionable: options.mentionable, } ); return new Role(this.session, role, this.id); } /** * adds a role to a user in the guild. * @param memberId - The id of the member to add a role to. * @param roleId - The id of the role to add. * @param reason - The reason for adding the role to the member. */ async addRole( memberId: Snowflake, roleId: Snowflake, reason?: string ): Promise { await this.session.rest.put( GUILD_MEMBER_ROLE(this.id, memberId, roleId), { reason } ); } /** * removes a role from a user in the guild. * @param memberId - The id of the member to remove a role from. * @param roleId - The id of the role to remove. * @param reason - The reason for removing the role from the member. */ async removeRole( memberId: Snowflake, roleId: Snowflake, reason?: string ): Promise { await this.session.rest.delete( GUILD_MEMBER_ROLE(this.id, memberId, roleId), { reason } ); } /** * the roles moved. * @see {@link ModifyRolePositions} * @see {@link Role} * @param options - Options to modify the roles. */ async moveRoles(options: ModifyRolePositions[]): Promise { const roles = await this.session.rest.patch( GUILD_ROLES(this.id), options ); return roles.map(role => new Role(this.session, role, this.id)); } /** * deletes an invite from the guild. * @param inviteCode - The invite code to get the invite for. */ async deleteInvite(inviteCode: string): Promise { await this.session.rest.delete(INVITE(inviteCode), {}); } /** * gets an invite from the guild. * @see {@link Routes.GetInvite} * @see {@link Invite} * @param inviteCode - The invite code to get the invite for. * @param options - Options to get the invite. * @returns Promise resolving to the invite. */ async fetchInvite(inviteCode: string, options: GetInvite): Promise { const inviteMetadata = await this.session.rest.get( INVITE(inviteCode, options) ); return new Invite(this.session, inviteMetadata); } /** * gets all invites from the guild. * @see {@link Invite} * @returns A promise that resolves to the guild's invites. */ async fetchInvites(): Promise { const invites = await this.session.rest.get( GUILD_INVITES(this.id) ); return invites.map(invite => new Invite(this.session, invite)); } /** * bans a member from the guild. * @see {@link CreateGuildBan} * @param memberId - The id of the member to ban. * @param options - Options to ban the member. */ async banMember( memberId: Snowflake, options: CreateGuildBan ): Promise { await this.session.rest.put( GUILD_BAN(this.id, memberId), options ? { delete_message_days: options.deleteMessageDays, reason: options.reason, } : {} ); } /** * kicks a member from the guild. * @param memberId - The id of the member to kick. * @param reason - The reason for kicking the member. */ async kickMember(memberId: Snowflake, reason?: string): Promise { await this.session.rest.delete( GUILD_MEMBER(this.id, memberId), { reason } ); } /** * unbans a member from the guild. * @param memberId - The id of the member to get. */ async unbanMember(memberId: Snowflake): Promise { await this.session.rest.delete( GUILD_BAN(this.id, memberId), {} ); } /** * edits a member in the guild. * @see {@link ModifyGuildMember} * @see {@link Member} * @param memberId - The id of the member to get. * @param options - Options to edit the member. * @returns Promise resolving to the edited member. */ async editMember( memberId: Snowflake, options: ModifyGuildMember ): Promise { const member = await this.session.rest.patch( GUILD_MEMBER(this.id, memberId), { nick: options.nick, roles: options.roles, mute: options.mute, deaf: options.deaf, channel_id: options.channelId, communication_disabled_until: options.communicationDisabledUntil ? new Date(options.communicationDisabledUntil).toISOString() : undefined, } ); return new Member(this.session, member, this.id); } /** * prunes members from the guild. * @see {@link BeginGuildPrune} * @param options - Options to prune the members. * @returns A promise that resolves to the number of members pruned. */ async pruneMembers(options: BeginGuildPrune): Promise { const result = await this.session.rest.post<{ pruned: number }>( GUILD_PRUNE(this.id), { days: options.days, compute_prune_count: options.computePruneCount, include_roles: options.includeRoles, } ); return result.pruned; } /** * gets the number of members that would be pruned. * @returns A promise that resolves to the number of members that would be pruned. */ async getPruneCount(): Promise { const result = await this.session.rest.get<{ pruned: number }>( GUILD_PRUNE(this.id) ); return result.pruned; } /** * gets the active threads in the guild. * @see {@link ReturnThreadsArchive} * @returns Promise resolving a ReturnThreadsArchive without hasMore property. */ async getActiveThreads(): Promise> { const { threads, members } = await this.session.rest.get( THREAD_ACTIVE(this.id) ); return { threads: Object.fromEntries( threads.map(thread => [ thread.id, new ThreadChannel(this.session, thread, this.id), ]) ), members: Object.fromEntries( members.map(threadMember => [ threadMember.id, new ThreadMember(this.session, threadMember), ]) ), }; } /** * * Deletes the guild. */ async delete_(): Promise { await this.session.rest.delete(GUILDS(this.id), {}); } /** * Leaves the guild. */ async leave(): Promise { await this.session.rest.delete(USER_GUILDS(this.id), {}); } /** * Creates a guild and returns its data, the bot joins the guild * This was modified from discord.js to make it compatible * precondition: Bot should be in less than 10 servers * @see {@link Session} * @see {@link GuildCreateOptions} * @see {@link Guild} * @param session - The session the guild should be created in. * @param options - Options to create the guild. * @returns A promise that resolves to the created guild. */ static async create( session: Session, options: GuildCreateOptions ): Promise { const guild = await session.rest.post(GUILDS(), { name: options.name, afk_channel_id: options.afkChannelId, afk_timeout: options.afkTimeout, default_message_notifications: options.defaultMessageNotifications, explicit_content_filter: options.explicitContentFilter, system_channel_flags: options.systemChannelFlags, verification_level: options.verificationLevel, icon: options.icon, channels: options.channels?.map(channel => ({ name: channel.name, nsfw: channel.nsfw, id: channel.id, bitrate: channel.bitrate, parent_id: channel.parentId, permission_overwrites: channel.permissionOverwrites, rtc_region: channel.rtcRegion, user_limit: channel.userLimit, video_quality_mode: channel.videoQualityMode, rate_limit_per_user: channel.rateLimitPerUser, })), roles: options.roles?.map(role => ({ name: role.name, id: role.id, color: role.color, mentionable: role.mentionable, hoist: role.hoist, position: role.position, unicode_emoji: role.unicodeEmoji, icon: options.icon, })), }); return new Guild(session, guild); } /** * sets a new splash for the guild. Same as Guild.edit({..., splash: 'splashURL'}) * @see {@link Guild} */ setSplash(splash: string): Promise { return this.edit({ splash }); } /** * sets a new banner for the guild. Same as Guild.edit({..., banner: 'bannerURL'}) * @see {@link Guild} */ setBanner(banner: string): Promise { return this.edit({ banner }); } /** * Sets a new guild discovery splash image. Same as Guild.edit({..., discoverySplashURL: 'discoverySplashURL'}) * @see {@link Guild} */ setDiscoverySplash(discoverySplash: string): Promise { return this.edit({ discoverySplash }); } /** * Sets a new guild icon image. Same as Guild.edit({..., icon: 'url'}) * @param icon - The new icon for the guild. * @see {@link Guild} */ setIcon(icon: string): Promise { return this.edit({ icon }); } /** * Edits a guild and returns its data. * @see {@link Guild} * @see {@link GuildEditOptions} * @param options - Options to edit the guild. * @returns A promise that resolves to the edited guild. */ async edit(options: GuildEditOptions): Promise { const guild = await this.session.rest.patch(GUILDS(), { name: options.name, afk_channel_id: options.afkChannelId, afk_timeout: options.afkTimeout, default_message_notifications: options.defaultMessageNotifications, explicit_content_filter: options.explicitContentFilter, system_channel_flags: options.systemChannelFlags, verification_level: options.verificationLevel, icon: options.icon, // extra props splash: options.splash, banner: options.banner, discovery_splash: options.discoverySplash, owner_id: options.ownerId, rules_channel_id: options.rulesChannelId, public_updates_channel_id: options.publicUpdatesChannelId, preferred_locale: options.preferredLocale, features: options.features, description: options.description, premiumProgressBarEnabled: options.premiumProgressBarEnabled, }); return new Guild(this.session, guild); } /** * gets the voice regions available for the guild. * @see {@link DiscordVoiceRegion} * @returns Promise that resolves to an array of voice regions. */ fetchVoiceRegions(): Promise { return this.session.rest.get( GUILD_VOICE_REGIONS(this.id) ); } /** * Fetches user ban in the guild * @param userId The user id * @returns Resolves Discord Ban */ async fetchBan(userId: Snowflake): Promise { const ban = await this.session.rest.get( GUILD_BAN(this.id, userId) ); return { reason: ban.reason ?? undefined, user: new User(this.session, ban.user), }; } /** * Fetches bans in the guild * @param options * @returns Resolve with list of bans */ async fetchBans(options?: GetBans): Promise { const bans = await this.session.rest.get( GUILD_BANS(this.id, options) ); return bans.map(x => { return { reason: x.reason ?? undefined, user: new User(this.session, x.user), }; }); } /** * Fetches settings for {@link Widget} in the guild * @returns Resolves with the settings */ async fetchWidgetSettings(): Promise { const widget = await this.session.rest.get( GUILD_WIDGET(this.id) ); return { enabled: !!widget.enabled, channelId: widget.channel_id ?? undefined, }; } /** * Fetches widget in the guild * @returns Resolves with the Widget */ async fetchWidget(): Promise { const widget = await this.session.rest.get( GUILD_WIDGET(this.id, { get: 'json' }) ); return new Widget(this.session, widget); } /** * Fetches vanity url invite * @see {@link Invite} * @returns Resolves a Invite */ async fetchVanityURL(): Promise> { const vanity = await this.session.rest.get( GUILD_VANITY(this.id) ); return new Invite(this.session, vanity); } /** * Fetches preview of the guild * @returns Resolves a Guild Preview object */ async fetchGuildPreview(): Promise { const preview = await this.session.rest.get( GUILD_PREVIEW(this.id) ); return new GuildPreview(this.session, preview); } async fetchChannel(channelId: string): Promise { const channel = await this.session.rest.get(CHANNEL(channelId)); return ChannelFactory.fromGuildChannel(this.session, channel); } async fetchChannels(): Promise { const channels = await this.session.rest.get(GUILD_CHANNELS(this.id)); return channels.map(channel => ChannelFactory.fromGuildChannel(this.session, channel)); } /** fetches a member */ async fetchMember(memberId: Snowflake): Promise { const member = await this.session.rest.get( GUILD_MEMBER(this.id, memberId) ); return new Member(this.session, member, this.id); } /** fetches multiple members */ async fetchMembers(options?: ListGuildMembers): Promise { const members = await this.session.rest.get( GUILD_MEMBERS(this.id, options) ); return members.map((member) => new Member(this.session, member, this.id)); } }