types(Partial): add partial reactions (#6066)

Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
DTrombett
2021-07-09 13:25:59 +02:00
committed by GitHub
parent 5b6be0cebc
commit d6c43a50bd
6 changed files with 65 additions and 98 deletions

View File

@@ -63,6 +63,16 @@ class Channel extends Base {
return new Date(this.createdTimestamp); return new Date(this.createdTimestamp);
} }
/**
* Whether this Channel is a partial
* <info>This is always false outside of DM channels.</info>
* @type {boolean}
* @readonly
*/
get partial() {
return false;
}
/** /**
* When concatenated with a string, this automatically returns the channel's mention instead of the Channel object. * When concatenated with a string, this automatically returns the channel's mention instead of the Channel object.
* @returns {string} * @returns {string}

View File

@@ -16,8 +16,10 @@ class DMChannel extends Channel {
*/ */
constructor(client, data) { constructor(client, data) {
super(client, data); super(client, data);
// Override the channel type so partials have a known type // Override the channel type so partials have a known type
this.type = 'DM'; this.type = 'DM';
/** /**
* A manager of the messages belonging to this channel * A manager of the messages belonging to this channel
* @type {MessageManager} * @type {MessageManager}

View File

@@ -65,7 +65,7 @@ class GuildMember extends Base {
if ('user' in data) { if ('user' in data) {
/** /**
* The user that this guild member instance represents * The user that this guild member instance represents
* @type {User} * @type {?User}
*/ */
this.user = this.client.users._add(data.user, true); this.user = this.client.users._add(data.user, true);
} }

View File

@@ -388,7 +388,7 @@ class Message extends Base {
/** /**
* The message contents with all mentions replaced by the equivalent text. * The message contents with all mentions replaced by the equivalent text.
* If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted. * If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted.
* @type {string} * @type {?string}
* @readonly * @readonly
*/ */
get cleanContent() { get cleanContent() {

125
typings/index.d.ts vendored
View File

@@ -269,6 +269,7 @@ export class Channel extends Base {
public readonly createdTimestamp: number; public readonly createdTimestamp: number;
public deleted: boolean; public deleted: boolean;
public id: Snowflake; public id: Snowflake;
public readonly partial: false;
public type: keyof typeof ChannelTypes; public type: keyof typeof ChannelTypes;
public delete(): Promise<Channel>; public delete(): Promise<Channel>;
public fetch(force?: boolean): Promise<Channel>; public fetch(force?: boolean): Promise<Channel>;
@@ -456,7 +457,6 @@ export class DMChannel extends TextBasedChannel(Channel, ['bulkDelete']) {
public constructor(client: Client, data?: unknown); public constructor(client: Client, data?: unknown);
public messages: MessageManager; public messages: MessageManager;
public recipient: User; public recipient: User;
public readonly partial: false;
public type: 'DM'; public type: 'DM';
public fetch(force?: boolean): Promise<this>; public fetch(force?: boolean): Promise<this>;
} }
@@ -1187,11 +1187,11 @@ export class MessageReaction {
private _emoji: GuildEmoji | ReactionEmoji; private _emoji: GuildEmoji | ReactionEmoji;
public readonly client: Client; public readonly client: Client;
public count: number | null; public count: number;
public readonly emoji: GuildEmoji | ReactionEmoji; public readonly emoji: GuildEmoji | ReactionEmoji;
public me: boolean; public me: boolean;
public message: Message | PartialMessage; public message: Message | PartialMessage;
public readonly partial: boolean; public readonly partial: false;
public users: ReactionUserManager; public users: ReactionUserManager;
public remove(): Promise<MessageReaction>; public remove(): Promise<MessageReaction>;
public fetch(): Promise<MessageReaction>; public fetch(): Promise<MessageReaction>;
@@ -2493,6 +2493,8 @@ export interface AddGuildMemberOptions {
export type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif'; export type AllowedImageFormat = 'webp' | 'png' | 'jpg' | 'jpeg' | 'gif';
export type AllowedPartial = User | Channel | GuildMember | Message | MessageReaction;
export type AllowedThreadTypeForNewsChannel = 'GUILD_NEWS_THREAD' | 10; export type AllowedThreadTypeForNewsChannel = 'GUILD_NEWS_THREAD' | 10;
export type AllowedThreadTypeForTextChannel = 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD' | 11 | 12; export type AllowedThreadTypeForTextChannel = 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD' | 11 | 12;
@@ -2809,10 +2811,10 @@ export interface ClientEvents {
messageCreate: [message: Message]; messageCreate: [message: Message];
messageDelete: [message: Message | PartialMessage]; messageDelete: [message: Message | PartialMessage];
messageReactionRemoveAll: [message: Message | PartialMessage]; messageReactionRemoveAll: [message: Message | PartialMessage];
messageReactionRemoveEmoji: [reaction: MessageReaction]; messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction];
messageDeleteBulk: [messages: Collection<Snowflake, Message | PartialMessage>]; messageDeleteBulk: [messages: Collection<Snowflake, Message | PartialMessage>];
messageReactionAdd: [message: MessageReaction, user: User | PartialUser]; messageReactionAdd: [message: MessageReaction | PartialMessageReaction, user: User | PartialUser];
messageReactionRemove: [reaction: MessageReaction, user: User | PartialUser]; messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser];
messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage]; messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage];
presenceUpdate: [oldPresence: Presence | null, newPresence: Presence]; presenceUpdate: [oldPresence: Presence | null, newPresence: Presence];
rateLimit: [rateLimitData: RateLimitData]; rateLimit: [rateLimitData: RateLimitData];
@@ -3790,35 +3792,6 @@ export interface PresenceData {
export type PresenceResolvable = Presence | UserResolvable | Snowflake; export type PresenceResolvable = Presence | UserResolvable | Snowflake;
export type Partialize<T, O extends string> = {
readonly client: Client;
readonly createdAt: Date;
readonly createdTimestamp: number;
deleted: boolean;
id: Snowflake;
partial: true;
fetch(): Promise<T>;
} & {
[K in keyof Omit<
T,
'client' | 'createdAt' | 'createdTimestamp' | 'id' | 'partial' | 'fetch' | 'deleted' | O
>]: T[K] extends (...args: any[]) => void ? T[K] : T[K] | null;
};
export interface PartialDMChannel
extends Partialize<
DMChannel,
'lastMessage' | 'lastMessageId' | 'messages' | 'recipient' | 'type' | 'typing' | 'typingCount'
> {
lastMessage: null;
lastMessageId: undefined;
messages: MessageManager;
recipient: User | PartialUser;
type: 'DM';
readonly typing: boolean;
readonly typingCount: number;
}
export interface PartialChannelData { export interface PartialChannelData {
id?: Snowflake | number; id?: Snowflake | number;
name: string; name: string;
@@ -3828,62 +3801,29 @@ export interface PartialChannelData {
permissionOverwrites?: PartialOverwriteData[]; permissionOverwrites?: PartialOverwriteData[];
} }
export interface PartialGuildMember export type Partialize<
extends Partialize< T extends AllowedPartial,
GuildMember, N extends keyof T | null = null,
| 'bannable' M extends keyof T | null = null,
| 'displayColor' E extends keyof T | '' = '',
| 'displayHexColor' > = {
| 'displayName' readonly client: Client;
| 'guild' id: Snowflake;
| 'kickable' partial: true;
| 'permissions' } & {
| 'roles' [K in keyof Omit<T, 'client' | 'id' | 'partial' | E>]: K extends N ? null : K extends M ? T[K] | null : T[K];
| 'manageable' };
| 'presence'
| 'voice' export interface PartialDMChannel extends Partialize<DMChannel, null, null, 'lastMessageId'> {
> { lastMessageId: undefined;
readonly bannable: boolean;
readonly displayColor: number;
readonly displayHexColor: HexColorString;
readonly displayName: string;
guild: Guild;
readonly manageable: boolean;
joinedAt: null;
joinedTimestamp: null;
readonly kickable: boolean;
readonly permissions: GuildMember['permissions'];
readonly presence: GuildMember['presence'];
readonly roles: GuildMember['roles'];
readonly voice: GuildMember['voice'];
} }
export interface PartialGuildMember extends Partialize<GuildMember, 'joinedAt' | 'joinedTimestamp', 'user'> {}
export interface PartialMessage export interface PartialMessage
extends Partialize< extends Partialize<Message, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}
Message,
| 'attachments' export interface PartialMessageReaction extends Partialize<MessageReaction, 'count'> {}
| 'channel'
| 'deletable'
| 'crosspostable'
| 'editable'
| 'mentions'
| 'pinnable'
| 'url'
| 'flags'
| 'embeds'
> {
attachments: Message['attachments'];
channel: Message['channel'];
readonly deletable: boolean;
readonly crosspostable: boolean;
readonly editable: boolean;
embeds: Message['embeds'];
flags: Message['flags'];
mentions: Message['mentions'];
readonly pinnable: boolean;
reactions: Message['reactions'];
readonly url: string;
}
export interface PartialOverwriteData { export interface PartialOverwriteData {
id: Snowflake | number; id: Snowflake | number;
@@ -3898,14 +3838,7 @@ export interface PartialRoleData extends RoleData {
export type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION'; export type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION';
export interface PartialUser export interface PartialUser extends Partialize<User, 'username' | 'tag' | 'discriminator'> {}
extends Omit<Partialize<User, 'bot' | 'flags' | 'system' | 'tag' | 'username'>, 'deleted'> {
bot: null;
flags: User['flags'];
system: null;
readonly tag: null;
username: null;
}
export type PresenceStatusData = ClientPresenceStatus | 'invisible'; export type PresenceStatusData = ClientPresenceStatus | 'invisible';

View File

@@ -581,3 +581,25 @@ declare const guildEmojiManager: GuildEmojiManager;
assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch()); assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch());
assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch(undefined, {})); assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch(undefined, {}));
assertType<Promise<GuildEmoji | null>>(guildEmojiManager.fetch('0')); assertType<Promise<GuildEmoji | null>>(guildEmojiManager.fetch('0'));
// Test partials structures
client.on('typingStart', (channel, user) => {
if (channel.partial) assertType<undefined>(channel.lastMessageId);
if (user.partial) return assertType<null>(user.username);
assertType<string>(user.username);
});
client.on('guildMemberRemove', member => {
if (member.partial) return assertType<null>(member.joinedAt);
assertType<Date | null>(member.joinedAt);
});
client.on('messageReactionAdd', async reaction => {
if (reaction.partial) {
assertType<null>(reaction.count);
reaction = await reaction.fetch();
}
assertType<number>(reaction.count);
if (reaction.message.partial) return assertType<string | null>(reaction.message.content);
assertType<string>(reaction.message.content);
});