feat(WelcomeScreen): welcome screens (#5490)

Co-authored-by: Jan <66554238+vaporox@users.noreply.github.com>
Co-authored-by: izexi <43889168+izexi@users.noreply.github.com>
Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
This commit is contained in:
Souji
2021-06-19 17:44:45 +02:00
committed by GitHub
parent 807ea2d3c1
commit 44e2ee7b20
11 changed files with 342 additions and 63 deletions

View File

@@ -23,7 +23,7 @@ class ChannelManager extends BaseManager {
const existing = this.cache.get(data.id); const existing = this.cache.get(data.id);
if (existing) { if (existing) {
if (existing._patch && cache) existing._patch(data); if (existing._patch && cache) existing._patch(data);
if (guild) guild.channels.add(existing); if (guild) guild.channels?.add(existing);
return existing; return existing;
} }

View File

@@ -0,0 +1,78 @@
'use strict';
const BaseGuild = require('./BaseGuild');
const { VerificationLevels, NSFWLevels } = require('../util/Constants');
/**
* Bundles common attributes and methods between {@link Guild} and {@link InviteGuild}
* @abstract
*/
class AnonymousGuild extends BaseGuild {
constructor(client, data) {
super(client, data);
this._patch(data);
}
_patch(data) {
this.features = data.features;
/**
* The hash of the guild invite splash image
* @type {?string}
*/
this.splash = data.splash;
/**
* The hash of the guild banner
* @type {?string}
*/
this.banner = data.banner;
/**
* The description of the guild, if any
* @type {?string}
*/
this.description = data.description;
/**
* The verification level of the guild
* @type {VerificationLevel}
*/
this.verificationLevel = VerificationLevels[data.verification_level];
/**
* The vanity invite code of the guild, if any
* @type {?string}
*/
this.vanityURLCode = data.vanity_url_code;
if ('nsfw_level' in data) {
/**
* The NSFW level of this guild
* @type {NSFWLevel}
*/
this.nsfwLevel = NSFWLevels[data.nsfw_level];
}
}
/**
* The URL to this guild's banner.
* @param {ImageURLOptions} [options={}] Options for the Image URL
* @returns {?string}
*/
bannerURL({ format, size } = {}) {
if (!this.banner) return null;
return this.client.rest.cdn.Banner(this.id, this.banner, format, size);
}
/**
* The URL to this guild's invite splash image.
* @param {ImageURLOptions} [options={}] Options for the Image URL
* @returns {?string}
*/
splashURL({ format, size } = {}) {
if (!this.splash) return null;
return this.client.rest.cdn.Splash(this.id, this.splash, format, size);
}
}
module.exports = AnonymousGuild;

View File

@@ -4,8 +4,9 @@ const Base = require('./Base');
const SnowflakeUtil = require('../util/SnowflakeUtil'); const SnowflakeUtil = require('../util/SnowflakeUtil');
/** /**
* The base class for {@link Guild} and {@link OAuth2Guild}. * The base class for {@link Guild}, {@link OAuth2Guild} and {@link InviteGuild}.
* @extends {Base} * @extends {Base}
* @abstract
*/ */
class BaseGuild extends Base { class BaseGuild extends Base {
constructor(client, data) { constructor(client, data) {

View File

@@ -153,7 +153,7 @@ class Channel extends Base {
break; break;
} }
} }
if (channel) guild.channels.cache.set(channel.id, channel); if (channel) guild.channels?.cache.set(channel.id, channel);
} }
} }
return channel; return channel;

View File

@@ -20,9 +20,9 @@ class Emoji extends Base {
super(client); super(client);
/** /**
* Whether this emoji is animated * Whether this emoji is animated
* @type {boolean} * @type {?boolean}
*/ */
this.animated = emoji.animated; this.animated = emoji.animated ?? null;
/** /**
* The name of this emoji * The name of this emoji

View File

@@ -1,12 +1,13 @@
'use strict'; 'use strict';
const BaseGuild = require('./BaseGuild'); const AnonymousGuild = require('./AnonymousGuild');
const GuildAuditLogs = require('./GuildAuditLogs'); const GuildAuditLogs = require('./GuildAuditLogs');
const GuildPreview = require('./GuildPreview'); const GuildPreview = require('./GuildPreview');
const GuildTemplate = require('./GuildTemplate'); const GuildTemplate = require('./GuildTemplate');
const Integration = require('./Integration'); const Integration = require('./Integration');
const Invite = require('./Invite'); const Invite = require('./Invite');
const Webhook = require('./Webhook'); const Webhook = require('./Webhook');
const WelcomeScreen = require('./WelcomeScreen');
const { Error, TypeError } = require('../errors'); const { Error, TypeError } = require('../errors');
const GuildApplicationCommandManager = require('../managers/GuildApplicationCommandManager'); const GuildApplicationCommandManager = require('../managers/GuildApplicationCommandManager');
const GuildBanManager = require('../managers/GuildBanManager'); const GuildBanManager = require('../managers/GuildBanManager');
@@ -24,7 +25,6 @@ const {
PartialTypes, PartialTypes,
VerificationLevels, VerificationLevels,
ExplicitContentFilterLevels, ExplicitContentFilterLevels,
NSFWLevels,
Status, Status,
MFALevels, MFALevels,
PremiumTiers, PremiumTiers,
@@ -37,9 +37,9 @@ const Util = require('../util/Util');
* Represents a guild (or a server) on Discord. * Represents a guild (or a server) on Discord.
* <info>It's recommended to see if a guild is available before performing operations or reading data from it. You can * <info>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`.</info> * check this with `guild.available`.</info>
* @extends {BaseGuild} * @extends {AnonymousGuild}
*/ */
class Guild extends BaseGuild { class Guild extends AnonymousGuild {
constructor(client, data) { constructor(client, data) {
super(client, data); super(client, data);
@@ -131,18 +131,12 @@ class Guild extends BaseGuild {
* @private * @private
*/ */
_patch(data) { _patch(data) {
super._patch(data);
this.id = data.id; this.id = data.id;
this.name = data.name; this.name = data.name;
this.icon = data.icon; this.icon = data.icon;
this.features = data.features;
this.available = !data.unavailable; this.available = !data.unavailable;
/**
* The hash of the guild invite splash image
* @type {?string}
*/
this.splash = data.splash;
/** /**
* The hash of the guild discovery splash image * The hash of the guild discovery splash image
* @type {?string} * @type {?string}
@@ -155,14 +149,6 @@ class Guild extends BaseGuild {
*/ */
this.memberCount = data.member_count || this.memberCount; this.memberCount = data.member_count || this.memberCount;
if ('nsfw_level' in data) {
/**
* The NSFW level of this guild
* @type {NSFWLevel}
*/
this.nsfwLevel = NSFWLevels[data.nsfw_level];
}
/** /**
* Whether the guild is "large" (has more than large_threshold members, 50 by default) * Whether the guild is "large" (has more than large_threshold members, 50 by default)
* @type {boolean} * @type {boolean}
@@ -247,12 +233,6 @@ class Guild extends BaseGuild {
this.widgetChannelID = data.widget_channel_id; this.widgetChannelID = data.widget_channel_id;
} }
/**
* The verification level of the guild
* @type {VerificationLevel}
*/
this.verificationLevel = VerificationLevels[data.verification_level];
/** /**
* The explicit content filter level of the guild * The explicit content filter level of the guild
* @type {ExplicitContentFilterLevel} * @type {ExplicitContentFilterLevel}
@@ -326,12 +306,6 @@ class Guild extends BaseGuild {
this.approximatePresenceCount = null; this.approximatePresenceCount = null;
} }
/**
* The vanity invite code of the guild, if any
* @type {?string}
*/
this.vanityURLCode = data.vanity_url_code;
/** /**
* The use count of the vanity URL code of the guild, if any * The use count of the vanity URL code of the guild, if any
* <info>You will need to fetch this parameter using {@link Guild#fetchVanityData} if you want to receive it</info> * <info>You will need to fetch this parameter using {@link Guild#fetchVanityData} if you want to receive it</info>
@@ -339,18 +313,6 @@ class Guild extends BaseGuild {
*/ */
this.vanityURLUses = null; this.vanityURLUses = null;
/**
* The description of the guild, if any
* @type {?string}
*/
this.description = data.description;
/**
* The hash of the guild banner
* @type {?string}
*/
this.banner = data.banner;
/** /**
* The ID of the rules channel for the guild * The ID of the rules channel for the guild
* @type {?Snowflake} * @type {?Snowflake}
@@ -576,6 +538,15 @@ class Guild extends BaseGuild {
); );
} }
/**
* Fetches the welcome screen for this guild.
* @returns {Promise<WelcomeScreen>}
*/
async fetchWelcomeScreen() {
const data = await this.client.api.guilds(this.id, 'welcome-screen').get();
return new WelcomeScreen(this, data);
}
/** /**
* The data for creating an integration. * The data for creating an integration.
* @typedef {Object} IntegrationData * @typedef {Object} IntegrationData
@@ -900,6 +871,60 @@ class Guild extends BaseGuild {
.then(newData => this.client.actions.GuildUpdate.handle(newData).updated); .then(newData => this.client.actions.GuildUpdate.handle(newData).updated);
} }
/**
* Welcome channel data
* @typedef {Object} WelcomeChannelData
* @property {string} description The description to show for this welcome channel
* @property {GuildTextChannelResolvable} channel The channel to link for this welcome channel
* @property {EmojiIdentifierResolvable} [emoji] The emoji to display for this welcome channel
*/
/**
* Welcome screen edit data
* @typedef {Object} WelcomeScreenEditData
* @property {boolean} [enabled] Whether the welcome screen is enabled
* @property {string} [description] The description for the welcome screen
* @property {WelcomeChannelData[]} [welcomeChannels] The welcome channel data for the welcome screen
*/
/**
* Updates the guild's welcome screen
* @param {WelcomeScreenEditData} data Data to edit the welcome screen with
* @returns {Promise<WelcomeScreen>}
* @example
* guild.editWelcomeScreen({
* description: 'Hello World',
* enabled: true,
* welcomeChannels: [
* {
* description: 'foobar',
* channel: '222197033908436994',
* }
* ],
* })
*/
async editWelcomeScreen(data) {
const { enabled, description, welcomeChannels } = data;
const welcome_channels = welcomeChannels?.map(welcomeChannelData => {
const emoji = this.emojis.resolve(welcomeChannelData.emoji);
return {
emoji_id: emoji?.id ?? null,
emoji_name: emoji?.name ?? welcomeChannelData.emoji,
channel_id: this.channels.resolveID(welcomeChannelData.channel),
description: welcomeChannelData.description,
};
});
const patchData = await this.client.api.guilds(this.id, 'welcome-screen').patch({
data: {
welcome_channels,
description,
enabled,
},
});
return new WelcomeScreen(this, patchData);
}
/** /**
* Edits the level of the explicit content filter. * Edits the level of the explicit content filter.
* @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter * @param {ExplicitContentFilterLevel|number} explicitContentFilter The new level of the explicit content filter

View File

@@ -19,11 +19,16 @@ class Invite extends Base {
} }
_patch(data) { _patch(data) {
const InviteGuild = require('./InviteGuild');
const Guild = require('./Guild');
/** /**
* The guild the invite is for * The guild the invite is for including welcome screen data if present
* @type {?Guild} * @type {?(Guild|InviteGuild)}
*/ */
this.guild = data.guild ? this.client.guilds.add(data.guild, false) : null; this.guild = null;
if (data.guild) {
this.guild = data.guild instanceof Guild ? data.guild : new InviteGuild(this.client, data.guild);
}
/** /**
* The code for this invite * The code for this invite

View File

@@ -0,0 +1,23 @@
'use strict';
const AnonymousGuild = require('./AnonymousGuild');
const WelcomeScreen = require('./WelcomeScreen');
/**
* Represents a guild received from an invite, includes welcome screen data if available.
* @extends {AnonymousGuild}
*/
class InviteGuild extends AnonymousGuild {
constructor(client, data) {
super(client, data);
/**
* The welcome screen for this invite guild
* @type {?WelcomeScreen}
*/
this.welcomeScreen =
typeof data.welcome_screen !== 'undefined' ? new WelcomeScreen(this, data.welcome_screen) : null;
}
}
module.exports = InviteGuild;

View File

@@ -0,0 +1,60 @@
'use strict';
const Base = require('./Base');
const Emoji = require('./Emoji');
/**
* Represents a channel link in a guild's welcome screen.
* @extends {Base}
*/
class WelcomeChannel extends Base {
constructor(guild, data) {
super(guild.client);
/**
* The guild for this welcome channel
* @type {Guild|WelcomeGuild}
*/
this.guild = guild;
/**
* The description of this welcome channel
* @type {string}
*/
this.description = data.description;
/**
* The raw emoji data
* @type {Object}
* @private
*/
this._emoji = {
name: data.emoji_name,
id: data.emoji_id,
};
/**
* The id of this welcome channel
* @type {Snowflake}
*/
this.channelID = data.channel_id;
}
/**
* The channel of this welcome channel
* @type {?TextChannel|NewsChannel}
*/
get channel() {
return this.client.channels.resolve(this.channelID);
}
/**
* The emoji of this welcome channel
* @type {GuildEmoji|Emoji}
*/
get emoji() {
return this.client.emojis.resolve(this._emoji.id) ?? new Emoji(this.client, this._emoji);
}
}
module.exports = WelcomeChannel;

View File

@@ -0,0 +1,48 @@
'use strict';
const Base = require('./Base');
const WelcomeChannel = require('./WelcomeChannel');
const Collection = require('../util/Collection');
/**
* Represents a welcome screen.
* @extends {Base}
*/
class WelcomeScreen extends Base {
constructor(guild, data) {
super(guild.client);
/**
* The guild for this welcome screen
* @type {Guild}
*/
this.guild = guild;
/**
* The description of this welcome screen
* @type {?string}
*/
this.description = data.description ?? null;
/**
* Collection of welcome channels belonging to this welcome screen
* @type {Collection<Snowflake, WelcomeChannel>}
*/
this.welcomeChannels = new Collection();
for (const channel of data.welcome_channels) {
const welcomeChannel = new WelcomeChannel(this.guild, channel);
this.welcomeChannels.set(welcomeChannel.channelID, welcomeChannel);
}
}
/**
* Whether the welcome screen is enabled on the guild or not
* @type {boolean}
*/
get enabled() {
return this.guild.features.includes('WELCOME_SCREEN_ENABLED');
}
}
module.exports = WelcomeScreen;

63
typings/index.d.ts vendored
View File

@@ -187,6 +187,17 @@ declare module 'discord.js' {
public static resolve(bit?: BitFieldResolvable<ActivityFlagsString, number>): number; public static resolve(bit?: BitFieldResolvable<ActivityFlagsString, number>): number;
} }
export abstract class AnonymousGuild extends BaseGuild {
public banner: string | null;
public description: string | null;
public nsfwLevel: NSFWLevel;
public splash: string | null;
public vanityURLCode: string | null;
public verificationLevel: VerificationLevel;
public bannerURL(options?: StaticImageURLOptions): string | null;
public splashURL(options?: StaticImageURLOptions): string | null;
}
export class APIMessage { export class APIMessage {
constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions); constructor(target: MessageTarget, options: MessageOptions | WebhookMessageOptions);
public data: unknown | null; public data: unknown | null;
@@ -282,7 +293,7 @@ declare module 'discord.js' {
public toJSON(...props: { [key: string]: boolean | string }[]): unknown; public toJSON(...props: { [key: string]: boolean | string }[]): unknown;
} }
export class BaseGuild extends Base { export abstract class BaseGuild extends Base {
public readonly createdAt: Date; public readonly createdAt: Date;
public readonly createdTimestamp: number; public readonly createdTimestamp: number;
public features: GuildFeatures[]; public features: GuildFeatures[];
@@ -759,7 +770,7 @@ declare module 'discord.js' {
export class Emoji extends Base { export class Emoji extends Base {
constructor(client: Client, emoji: unknown); constructor(client: Client, emoji: unknown);
public animated: boolean; public animated: boolean | null;
public readonly createdAt: Date | null; public readonly createdAt: Date | null;
public readonly createdTimestamp: number | null; public readonly createdTimestamp: number | null;
public deleted: boolean; public deleted: boolean;
@@ -771,7 +782,7 @@ declare module 'discord.js' {
public toString(): string; public toString(): string;
} }
export class Guild extends BaseGuild { export class Guild extends AnonymousGuild {
constructor(client: Client, data: unknown); constructor(client: Client, data: unknown);
private _sortedRoles(): Collection<Snowflake, Role>; private _sortedRoles(): Collection<Snowflake, Role>;
private _sortedChannels(channel: Channel): Collection<Snowflake, GuildChannel>; private _sortedChannels(channel: Channel): Collection<Snowflake, GuildChannel>;
@@ -783,13 +794,11 @@ declare module 'discord.js' {
public approximateMemberCount: number | null; public approximateMemberCount: number | null;
public approximatePresenceCount: number | null; public approximatePresenceCount: number | null;
public available: boolean; public available: boolean;
public banner: string | null;
public bans: GuildBanManager; public bans: GuildBanManager;
public channels: GuildChannelManager; public channels: GuildChannelManager;
public commands: GuildApplicationCommandManager; public commands: GuildApplicationCommandManager;
public defaultMessageNotifications: DefaultMessageNotificationLevel | number; public defaultMessageNotifications: DefaultMessageNotificationLevel | number;
public deleted: boolean; public deleted: boolean;
public description: string | null;
public discoverySplash: string | null; public discoverySplash: string | null;
public emojis: GuildEmojiManager; public emojis: GuildEmojiManager;
public explicitContentFilter: ExplicitContentFilterLevel; public explicitContentFilter: ExplicitContentFilterLevel;
@@ -802,7 +811,6 @@ declare module 'discord.js' {
public memberCount: number; public memberCount: number;
public members: GuildMemberManager; public members: GuildMemberManager;
public mfaLevel: MFALevel; public mfaLevel: MFALevel;
public nsfwLevel: NSFWLevel;
public ownerID: Snowflake; public ownerID: Snowflake;
public preferredLocale: string; public preferredLocale: string;
public premiumSubscriptionCount: number | null; public premiumSubscriptionCount: number | null;
@@ -815,26 +823,23 @@ declare module 'discord.js' {
public rulesChannelID: Snowflake | null; public rulesChannelID: Snowflake | null;
public readonly shard: WebSocketShard; public readonly shard: WebSocketShard;
public shardID: number; public shardID: number;
public splash: string | null;
public stageInstances: StageInstanceManager; public stageInstances: StageInstanceManager;
public readonly systemChannel: TextChannel | null; public readonly systemChannel: TextChannel | null;
public systemChannelFlags: Readonly<SystemChannelFlags>; public systemChannelFlags: Readonly<SystemChannelFlags>;
public systemChannelID: Snowflake | null; public systemChannelID: Snowflake | null;
public vanityURLCode: string | null;
public vanityURLUses: number | null; public vanityURLUses: number | null;
public verificationLevel: VerificationLevel;
public readonly voiceAdapterCreator: DiscordGatewayAdapterCreator; public readonly voiceAdapterCreator: DiscordGatewayAdapterCreator;
public readonly voiceStates: VoiceStateManager; public readonly voiceStates: VoiceStateManager;
public readonly widgetChannel: TextChannel | null; public readonly widgetChannel: TextChannel | null;
public widgetChannelID: Snowflake | null; public widgetChannelID: Snowflake | null;
public widgetEnabled: boolean | null; public widgetEnabled: boolean | null;
public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise<GuildMember>; public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise<GuildMember>;
public bannerURL(options?: StaticImageURLOptions): string | null;
public createIntegration(data: IntegrationData, reason?: string): Promise<Guild>; public createIntegration(data: IntegrationData, reason?: string): Promise<Guild>;
public createTemplate(name: string, description?: string): Promise<GuildTemplate>; public createTemplate(name: string, description?: string): Promise<GuildTemplate>;
public delete(): Promise<Guild>; public delete(): Promise<Guild>;
public discoverySplashURL(options?: StaticImageURLOptions): string | null; public discoverySplashURL(options?: StaticImageURLOptions): string | null;
public edit(data: GuildEditData, reason?: string): Promise<Guild>; public edit(data: GuildEditData, reason?: string): Promise<Guild>;
public editWelcomeScreen(data: WelcomeScreenEditData): Promise<WelcomeScreen>;
public equals(guild: Guild): boolean; public equals(guild: Guild): boolean;
public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise<GuildAuditLogs>; public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise<GuildAuditLogs>;
public fetchIntegrations(): Promise<Collection<string, Integration>>; public fetchIntegrations(): Promise<Collection<string, Integration>>;
@@ -845,6 +850,7 @@ declare module 'discord.js' {
public fetchVanityData(): Promise<Vanity>; public fetchVanityData(): Promise<Vanity>;
public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>; public fetchVoiceRegions(): Promise<Collection<string, VoiceRegion>>;
public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>; public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
public fetchWelcomeScreen(): Promise<WelcomeScreen>;
public fetchWidget(): Promise<GuildWidget>; public fetchWidget(): Promise<GuildWidget>;
public leave(): Promise<Guild>; public leave(): Promise<Guild>;
public setAFKChannel(afkChannel: ChannelResolvable | null, reason?: string): Promise<Guild>; public setAFKChannel(afkChannel: ChannelResolvable | null, reason?: string): Promise<Guild>;
@@ -872,7 +878,6 @@ declare module 'discord.js' {
public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise<Guild>; public setSystemChannelFlags(systemChannelFlags: SystemChannelFlagsResolvable, reason?: string): Promise<Guild>;
public setVerificationLevel(verificationLevel: VerificationLevel | number, reason?: string): Promise<Guild>; public setVerificationLevel(verificationLevel: VerificationLevel | number, reason?: string): Promise<Guild>;
public setWidget(widget: GuildWidgetData, reason?: string): Promise<Guild>; public setWidget(widget: GuildWidgetData, reason?: string): Promise<Guild>;
public splashURL(options?: StaticImageURLOptions): string | null;
public toJSON(): unknown; public toJSON(): unknown;
} }
@@ -1176,7 +1181,7 @@ declare module 'discord.js' {
public createdTimestamp: number | null; public createdTimestamp: number | null;
public readonly expiresAt: Date | null; public readonly expiresAt: Date | null;
public readonly expiresTimestamp: number | null; public readonly expiresTimestamp: number | null;
public guild: Guild | null; public guild: InviteGuild | Guild | null;
public inviter: User | null; public inviter: User | null;
public maxAge: number | null; public maxAge: number | null;
public maxUses: number | null; public maxUses: number | null;
@@ -1207,6 +1212,11 @@ declare module 'discord.js' {
public readonly guild: Guild | null; public readonly guild: Guild | null;
} }
export class InviteGuild extends AnonymousGuild {
constructor(client: Client, data: unknown);
public welcomeScreen: WelcomeScreen | null;
}
export class Message extends Base { export class Message extends Base {
constructor(client: Client, data: unknown, channel: TextChannel | DMChannel | NewsChannel); constructor(client: Client, data: unknown, channel: TextChannel | DMChannel | NewsChannel);
private patch(data: unknown): Message; private patch(data: unknown): Message;
@@ -2117,6 +2127,22 @@ declare module 'discord.js' {
public activity?: WidgetActivity; public activity?: WidgetActivity;
} }
export class WelcomeChannel extends Base {
private _emoji: unknown;
public channelID: Snowflake;
public guild: Guild | InviteGuild;
public description: string;
public readonly channel: TextChannel | NewsChannel | null;
public readonly emoji: GuildEmoji | Emoji;
}
export class WelcomeScreen extends Base {
public readonly enabled: boolean;
public guild: Guild | InviteGuild;
public description: string | null;
public welcomeChannels: Collection<Snowflake, WelcomeChannel>;
}
//#endregion //#endregion
//#region Collections //#region Collections
@@ -2714,6 +2740,7 @@ declare module 'discord.js' {
position?: number; position?: number;
} }
type GuildTextChannelResolvable = TextChannel | NewsChannel | Snowflake;
type ChannelResolvable = Channel | Snowflake; type ChannelResolvable = Channel | Snowflake;
interface ChannelWebhookCreateOptions { interface ChannelWebhookCreateOptions {
@@ -3967,6 +3994,18 @@ declare module 'discord.js' {
position: number; position: number;
} }
interface WelcomeChannelData {
description: string;
channel: GuildChannelResolvable;
emoji?: EmojiIdentifierResolvable;
}
interface WelcomeScreenEditData {
enabled?: boolean;
description?: string;
welcomeChannels?: WelcomeChannelData[];
}
type WSEventType = type WSEventType =
| 'READY' | 'READY'
| 'RESUMED' | 'RESUMED'