mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-19 13:03:31 +01:00
src: add news and store channels, and missing guild props (#3168)
* src: Implement store and news channels! * src: Remove code dupe * src: Add missing guild properties * docs: Add a small notice that the channel type may also change * src: Remove re-creation of the MessageStore * lint: Unused Import * src: Requested changes for StoreChannels * typings: Fix typings * src: Moar guild updates * src: Set maximumPresence to the data prop, the already existent one, or default to 5000 * typings: afkChannel is a VC I keep confusing them, ffs Co-Authored-By: vladfrangu <kingdgrizzle@gmail.com> * docs: Document that maximumMembers and maximumPresences may be inaccurate before fetching * src Appels requested changes
This commit is contained in:
@@ -1,14 +1,25 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const Action = require('./Action');
|
const Action = require('./Action');
|
||||||
|
const Channel = require('../../structures/Channel');
|
||||||
|
const { ChannelTypes } = require('../../util/Constants');
|
||||||
|
|
||||||
class ChannelUpdateAction extends Action {
|
class ChannelUpdateAction extends Action {
|
||||||
handle(data) {
|
handle(data) {
|
||||||
const client = this.client;
|
const client = this.client;
|
||||||
|
|
||||||
const channel = client.channels.get(data.id);
|
let channel = client.channels.get(data.id);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
const old = channel._update(data);
|
const old = channel._update(data);
|
||||||
|
|
||||||
|
if (ChannelTypes[channel.type.toUpperCase()] !== data.type) {
|
||||||
|
const newChannel = Channel.create(this.client, data, channel.guild);
|
||||||
|
for (const [id, message] of channel.messages) newChannel.messages.set(id, message);
|
||||||
|
newChannel._typing = new Map(channel._typing);
|
||||||
|
channel = newChannel;
|
||||||
|
this.client.channels.set(channel.id, channel);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
old,
|
old,
|
||||||
updated: channel,
|
updated: channel,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ module.exports = (client, packet) => {
|
|||||||
const { old, updated } = client.actions.ChannelUpdate.handle(packet.d);
|
const { old, updated } = client.actions.ChannelUpdate.handle(packet.d);
|
||||||
if (old && updated) {
|
if (old && updated) {
|
||||||
/**
|
/**
|
||||||
* Emitted whenever a channel is updated - e.g. name change, topic change.
|
* Emitted whenever a channel is updated - e.g. name change, topic change, channel type change.
|
||||||
* @event Client#channelUpdate
|
* @event Client#channelUpdate
|
||||||
* @param {DMChannel|GuildChannel} oldChannel The channel before the update
|
* @param {DMChannel|GuildChannel} oldChannel The channel before the update
|
||||||
* @param {DMChannel|GuildChannel} newChannel The channel after the update
|
* @param {DMChannel|GuildChannel} newChannel The channel after the update
|
||||||
|
|||||||
@@ -116,6 +116,16 @@ class Channel extends Base {
|
|||||||
channel = new CategoryChannel(guild, data);
|
channel = new CategoryChannel(guild, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case ChannelTypes.NEWS: {
|
||||||
|
const NewsChannel = Structures.get('NewsChannel');
|
||||||
|
channel = new NewsChannel(guild, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ChannelTypes.STORE: {
|
||||||
|
const StoreChannel = Structures.get('StoreChannel');
|
||||||
|
channel = new StoreChannel(guild, data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (channel) guild.channels.set(channel.id, channel);
|
if (channel) guild.channels.set(channel.id, channel);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,6 +186,27 @@ class Guild extends Base {
|
|||||||
*/
|
*/
|
||||||
this.embedEnabled = data.embed_enabled;
|
this.embedEnabled = data.embed_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether widget images are enabled on this guild
|
||||||
|
* @type {?boolean}
|
||||||
|
* @name Guild#widgetEnabled
|
||||||
|
*/
|
||||||
|
if (typeof data.widget_enabled !== 'undefined') this.widgetEnabled = data.widget_enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The widget channel ID, if enabled
|
||||||
|
* @type {?string}
|
||||||
|
* @name Guild#widgetChannelID
|
||||||
|
*/
|
||||||
|
if (typeof data.widget_channel_id !== 'undefined') this.widgetChannelID = data.widget_channel_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The embed channel ID, if enabled
|
||||||
|
* @type {?string}
|
||||||
|
* @name Guild#embedChannelID
|
||||||
|
*/
|
||||||
|
if (typeof data.embed_channel_id !== 'undefined') this.embedChannelID = data.embed_channel_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The verification level of the guild
|
* The verification level of the guild
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@@ -211,12 +232,46 @@ class Guild extends Base {
|
|||||||
this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp;
|
this.joinedTimestamp = data.joined_at ? new Date(data.joined_at).getTime() : this.joinedTimestamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value set for a guild's default message notifications
|
* The value set for the guild's default message notifications
|
||||||
* @type {DefaultMessageNotifications|number}
|
* @type {DefaultMessageNotifications|number}
|
||||||
*/
|
*/
|
||||||
this.defaultMessageNotifications = DefaultMessageNotifications[data.default_message_notifications] ||
|
this.defaultMessageNotifications = DefaultMessageNotifications[data.default_message_notifications] ||
|
||||||
data.default_message_notifications;
|
data.default_message_notifications;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of members the guild can have
|
||||||
|
* <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
|
||||||
|
* @type {?number}
|
||||||
|
* @name Guild#maximumMembers
|
||||||
|
*/
|
||||||
|
if (typeof data.max_members !== 'undefined') this.maximumMembers = data.max_members || 250000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of presences the guild can have
|
||||||
|
* <info>You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter</info>
|
||||||
|
* @type {?number}
|
||||||
|
* @name Guild#maximumPresences
|
||||||
|
*/
|
||||||
|
if (typeof data.max_presences !== 'undefined') this.maximumPresences = data.max_presences || 5000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vanity URL code of the guild, if any
|
||||||
|
* @type {?string}
|
||||||
|
*/
|
||||||
|
this.vanityURLCode = data.vanity_url_code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
this.id = data.id;
|
this.id = data.id;
|
||||||
this.available = !data.unavailable;
|
this.available = !data.unavailable;
|
||||||
this.features = data.features || this.features || [];
|
this.features = data.features || this.features || [];
|
||||||
@@ -274,6 +329,16 @@ class Guild extends Base {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 timestamp the guild was created at
|
* The timestamp the guild was created at
|
||||||
* @type {number}
|
* @type {number}
|
||||||
@@ -368,6 +433,24 @@ class Guild extends Base {
|
|||||||
return this.client.channels.get(this.systemChannelID) || null;
|
return this.client.channels.get(this.systemChannelID) || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Widget channel for this guild
|
||||||
|
* @type {?TextChannel}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get widgetChannel() {
|
||||||
|
return this.client.channels.get(this.widgetChannelID) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Embed channel for this guild
|
||||||
|
* @type {?TextChannel}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
get embedChannel() {
|
||||||
|
return this.client.channels.get(this.embedChannelID) || null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The `@everyone` role of the guild
|
* The `@everyone` role of the guild
|
||||||
* @type {?Role}
|
* @type {?Role}
|
||||||
@@ -409,6 +492,17 @@ class Guild extends Base {
|
|||||||
return this.members.resolve(user);
|
return this.members.resolve(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches this guild.
|
||||||
|
* @returns {Promise<Guild>}
|
||||||
|
*/
|
||||||
|
fetch() {
|
||||||
|
return this.client.api.guilds(this.id).get().then(data => {
|
||||||
|
this._patch(data);
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object containing information about a guild member's ban.
|
* An object containing information about a guild member's ban.
|
||||||
* @typedef {Object} BanInfo
|
* @typedef {Object} BanInfo
|
||||||
@@ -975,6 +1069,7 @@ class Guild extends Base {
|
|||||||
});
|
});
|
||||||
json.iconURL = this.iconURL();
|
json.iconURL = this.iconURL();
|
||||||
json.splashURL = this.splashURL();
|
json.splashURL = this.splashURL();
|
||||||
|
json.bannerURL = this.bannerURL();
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
18
src/structures/NewsChannel.js
Normal file
18
src/structures/NewsChannel.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const TextChannel = require('./TextChannel');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a guild news channel on Discord.
|
||||||
|
* @extends {TextChannel}
|
||||||
|
*/
|
||||||
|
class NewsChannel extends TextChannel {
|
||||||
|
_patch(data) {
|
||||||
|
super._patch(data);
|
||||||
|
|
||||||
|
// News channels don't have a rate limit per user, remove it
|
||||||
|
this.rateLimitPerUser = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = NewsChannel;
|
||||||
22
src/structures/StoreChannel.js
Normal file
22
src/structures/StoreChannel.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const GuildChannel = require('./GuildChannel');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a guild store channel on Discord.
|
||||||
|
* @extends {GuildChannel}
|
||||||
|
*/
|
||||||
|
class StoreChannel extends GuildChannel {
|
||||||
|
_patch(data) {
|
||||||
|
super._patch(data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the guild considers this channel NSFW
|
||||||
|
* @type {boolean}
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
this.nsfw = data.nsfw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = StoreChannel;
|
||||||
@@ -139,7 +139,6 @@ class TextChannel extends GuildChannel {
|
|||||||
awaitMessages() {}
|
awaitMessages() {}
|
||||||
bulkDelete() {}
|
bulkDelete() {}
|
||||||
acknowledge() {}
|
acknowledge() {}
|
||||||
_cacheMessage() {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TextBasedChannel.applyToClass(TextChannel, true);
|
TextBasedChannel.applyToClass(TextChannel, true);
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ exports.Endpoints = {
|
|||||||
if (format === 'default') format = hash.startsWith('a_') ? 'gif' : 'webp';
|
if (format === 'default') format = hash.startsWith('a_') ? 'gif' : 'webp';
|
||||||
return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size });
|
return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size });
|
||||||
},
|
},
|
||||||
|
Banner: (guildID, hash, format = 'webp', size) =>
|
||||||
|
makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }),
|
||||||
Icon: (guildID, hash, format = 'webp', size) =>
|
Icon: (guildID, hash, format = 'webp', size) =>
|
||||||
makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size }),
|
makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size }),
|
||||||
AppIcon: (clientID, hash, { format = 'webp', size } = {}) =>
|
AppIcon: (clientID, hash, { format = 'webp', size } = {}) =>
|
||||||
@@ -409,6 +411,8 @@ exports.ChannelTypes = {
|
|||||||
VOICE: 2,
|
VOICE: 2,
|
||||||
GROUP: 3,
|
GROUP: 3,
|
||||||
CATEGORY: 4,
|
CATEGORY: 4,
|
||||||
|
NEWS: 5,
|
||||||
|
STORE: 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.ClientApplicationAssetTypes = {
|
exports.ClientApplicationAssetTypes = {
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ const structures = {
|
|||||||
TextChannel: require('../structures/TextChannel'),
|
TextChannel: require('../structures/TextChannel'),
|
||||||
VoiceChannel: require('../structures/VoiceChannel'),
|
VoiceChannel: require('../structures/VoiceChannel'),
|
||||||
CategoryChannel: require('../structures/CategoryChannel'),
|
CategoryChannel: require('../structures/CategoryChannel'),
|
||||||
|
NewsChannel: require('../structures/NewsChannel'),
|
||||||
|
StoreChannel: require('../structures/StoreChannel'),
|
||||||
GuildMember: require('../structures/GuildMember'),
|
GuildMember: require('../structures/GuildMember'),
|
||||||
Guild: require('../structures/Guild'),
|
Guild: require('../structures/Guild'),
|
||||||
Message: require('../structures/Message'),
|
Message: require('../structures/Message'),
|
||||||
|
|||||||
34
typings/index.d.ts
vendored
34
typings/index.d.ts
vendored
@@ -122,7 +122,7 @@ declare module 'discord.js' {
|
|||||||
public readonly createdTimestamp: number;
|
public readonly createdTimestamp: number;
|
||||||
public deleted: boolean;
|
public deleted: boolean;
|
||||||
public id: Snowflake;
|
public id: Snowflake;
|
||||||
public type: 'dm' | 'text' | 'voice' | 'category' | 'unknown';
|
public type: 'dm' | 'text' | 'voice' | 'category' | 'news' | 'store' | 'unknown';
|
||||||
public delete(reason?: string): Promise<Channel>;
|
public delete(reason?: string): Promise<Channel>;
|
||||||
public fetch(): Promise<Channel>;
|
public fetch(): Promise<Channel>;
|
||||||
public toString(): string;
|
public toString(): string;
|
||||||
@@ -393,9 +393,7 @@ declare module 'discord.js' {
|
|||||||
private _sortedChannels(channel: Channel): Collection<Snowflake, GuildChannel>;
|
private _sortedChannels(channel: Channel): Collection<Snowflake, GuildChannel>;
|
||||||
private _memberSpeakUpdate(user: Snowflake, speaking: boolean): void;
|
private _memberSpeakUpdate(user: Snowflake, speaking: boolean): void;
|
||||||
|
|
||||||
protected setup(data: any): void;
|
public readonly afkChannel: VoiceChannel;
|
||||||
|
|
||||||
public readonly afkChannel: VoiceChannel | null;
|
|
||||||
public afkChannelID: Snowflake;
|
public afkChannelID: Snowflake;
|
||||||
public afkTimeout: number;
|
public afkTimeout: number;
|
||||||
public applicationID: Snowflake;
|
public applicationID: Snowflake;
|
||||||
@@ -432,13 +430,25 @@ declare module 'discord.js' {
|
|||||||
public readonly systemChannel: TextChannel | null;
|
public readonly systemChannel: TextChannel | null;
|
||||||
public systemChannelID: Snowflake;
|
public systemChannelID: Snowflake;
|
||||||
public verificationLevel: number;
|
public verificationLevel: number;
|
||||||
|
public maximumMembers: number;
|
||||||
|
public maximumPresences: number;
|
||||||
|
public vanityURLCode: string;
|
||||||
|
public description: string;
|
||||||
|
public banner: string;
|
||||||
|
public widgetEnabled: boolean;
|
||||||
|
public widgetChannelID: Snowflake;
|
||||||
|
public readonly widgetChannel: TextChannel;
|
||||||
|
public embedChannelID: Snowflake;
|
||||||
|
public readonly embedChannel: TextChannel;
|
||||||
public readonly verified: boolean;
|
public readonly verified: boolean;
|
||||||
public readonly voiceConnection: VoiceConnection | null;
|
public readonly voiceConnection: VoiceConnection | null;
|
||||||
public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise<GuildMember>;
|
public addMember(user: UserResolvable, options: AddGuildMemberOptions): Promise<GuildMember>;
|
||||||
|
public bannerURL(options?: AvatarOptions): string;
|
||||||
public createIntegration(data: IntegrationData, reason?: string): Promise<Guild>;
|
public createIntegration(data: IntegrationData, reason?: string): Promise<Guild>;
|
||||||
public delete(): Promise<Guild>;
|
public delete(): Promise<Guild>;
|
||||||
public edit(data: GuildEditData, reason?: string): Promise<Guild>;
|
public edit(data: GuildEditData, reason?: string): Promise<Guild>;
|
||||||
public equals(guild: Guild): boolean;
|
public equals(guild: Guild): boolean;
|
||||||
|
public fetch(): Promise<Guild>;
|
||||||
public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise<GuildAuditLogs>;
|
public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise<GuildAuditLogs>;
|
||||||
public fetchBans(): Promise<Collection<Snowflake, { user: User, reason: string }>>;
|
public fetchBans(): Promise<Collection<Snowflake, { user: User, reason: string }>>;
|
||||||
public fetchIntegrations(): Promise<Collection<string, Integration>>;
|
public fetchIntegrations(): Promise<Collection<string, Integration>>;
|
||||||
@@ -532,6 +542,11 @@ declare module 'discord.js' {
|
|||||||
public updateOverwrite(userOrRole: RoleResolvable | UserResolvable, options: PermissionOverwriteOption, reason?: string): Promise<GuildChannel>;
|
public updateOverwrite(userOrRole: RoleResolvable | UserResolvable, options: PermissionOverwriteOption, reason?: string): Promise<GuildChannel>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class StoreChannel extends GuildChannel {
|
||||||
|
constructor(guild: Guild, data?: object);
|
||||||
|
public nsfw: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class GuildEmoji extends Emoji {
|
export class GuildEmoji extends Emoji {
|
||||||
constructor(client: Client, data: object, guild: Guild);
|
constructor(client: Client, data: object, guild: Guild);
|
||||||
private _roles: string[];
|
private _roles: string[];
|
||||||
@@ -1064,6 +1079,17 @@ declare module 'discord.js' {
|
|||||||
public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class NewsChannel extends TextBasedChannel(GuildChannel) {
|
||||||
|
constructor(guild: Guild, data?: object);
|
||||||
|
public readonly members: Collection<Snowflake, GuildMember>;
|
||||||
|
public messages: MessageStore;
|
||||||
|
public nsfw: boolean;
|
||||||
|
public topic: string;
|
||||||
|
public createWebhook(name: string, options?: { avatar?: BufferResolvable | Base64Resolvable, reason?: string }): Promise<Webhook>;
|
||||||
|
public setNSFW(nsfw: boolean, reason?: string): Promise<NewsChannel>;
|
||||||
|
public fetchWebhooks(): Promise<Collection<Snowflake, Webhook>>;
|
||||||
|
}
|
||||||
|
|
||||||
export class User extends PartialTextBasedChannel(Base) {
|
export class User extends PartialTextBasedChannel(Base) {
|
||||||
constructor(client: Client, data: object);
|
constructor(client: Client, data: object);
|
||||||
public avatar: string | null;
|
public avatar: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user