Skip to content

Commit

Permalink
types(Partial): add partial reactions (#6066)
Browse files Browse the repository at this point in the history
Co-authored-by: Noel <[email protected]>
  • Loading branch information
DTrombett and iCrawl authored Jul 9, 2021
1 parent 5b6be0c commit d6c43a5
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 98 deletions.
10 changes: 10 additions & 0 deletions src/structures/Channel.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ class Channel extends Base {
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.
* @returns {string}
Expand Down
2 changes: 2 additions & 0 deletions src/structures/DMChannel.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ class DMChannel extends Channel {
*/
constructor(client, data) {
super(client, data);

// Override the channel type so partials have a known type
this.type = 'DM';

/**
* A manager of the messages belonging to this channel
* @type {MessageManager}
Expand Down
2 changes: 1 addition & 1 deletion src/structures/GuildMember.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class GuildMember extends Base {
if ('user' in data) {
/**
* The user that this guild member instance represents
* @type {User}
* @type {?User}
*/
this.user = this.client.users._add(data.user, true);
}
Expand Down
2 changes: 1 addition & 1 deletion src/structures/Message.js
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ class Message extends Base {
/**
* 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.
* @type {string}
* @type {?string}
* @readonly
*/
get cleanContent() {
Expand Down
125 changes: 29 additions & 96 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ export class Channel extends Base {
public readonly createdTimestamp: number;
public deleted: boolean;
public id: Snowflake;
public readonly partial: false;
public type: keyof typeof ChannelTypes;
public delete(): Promise<Channel>;
public fetch(force?: boolean): Promise<Channel>;
Expand Down Expand Up @@ -456,7 +457,6 @@ export class DMChannel extends TextBasedChannel(Channel, ['bulkDelete']) {
public constructor(client: Client, data?: unknown);
public messages: MessageManager;
public recipient: User;
public readonly partial: false;
public type: 'DM';
public fetch(force?: boolean): Promise<this>;
}
Expand Down Expand Up @@ -1187,11 +1187,11 @@ export class MessageReaction {
private _emoji: GuildEmoji | ReactionEmoji;

public readonly client: Client;
public count: number | null;
public count: number;
public readonly emoji: GuildEmoji | ReactionEmoji;
public me: boolean;
public message: Message | PartialMessage;
public readonly partial: boolean;
public readonly partial: false;
public users: ReactionUserManager;
public remove(): Promise<MessageReaction>;
public fetch(): Promise<MessageReaction>;
Expand Down Expand Up @@ -2493,6 +2493,8 @@ export interface AddGuildMemberOptions {

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 AllowedThreadTypeForTextChannel = 'GUILD_PUBLIC_THREAD' | 'GUILD_PRIVATE_THREAD' | 11 | 12;
Expand Down Expand Up @@ -2809,10 +2811,10 @@ export interface ClientEvents {
messageCreate: [message: Message];
messageDelete: [message: Message | PartialMessage];
messageReactionRemoveAll: [message: Message | PartialMessage];
messageReactionRemoveEmoji: [reaction: MessageReaction];
messageReactionRemoveEmoji: [reaction: MessageReaction | PartialMessageReaction];
messageDeleteBulk: [messages: Collection<Snowflake, Message | PartialMessage>];
messageReactionAdd: [message: MessageReaction, user: User | PartialUser];
messageReactionRemove: [reaction: MessageReaction, user: User | PartialUser];
messageReactionAdd: [message: MessageReaction | PartialMessageReaction, user: User | PartialUser];
messageReactionRemove: [reaction: MessageReaction | PartialMessageReaction, user: User | PartialUser];
messageUpdate: [oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage];
presenceUpdate: [oldPresence: Presence | null, newPresence: Presence];
rateLimit: [rateLimitData: RateLimitData];
Expand Down Expand Up @@ -3790,35 +3792,6 @@ export interface PresenceData {

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 {
id?: Snowflake | number;
name: string;
Expand All @@ -3828,62 +3801,29 @@ export interface PartialChannelData {
permissionOverwrites?: PartialOverwriteData[];
}

export interface PartialGuildMember
extends Partialize<
GuildMember,
| 'bannable'
| 'displayColor'
| 'displayHexColor'
| 'displayName'
| 'guild'
| 'kickable'
| 'permissions'
| 'roles'
| 'manageable'
| 'presence'
| 'voice'
> {
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 type Partialize<
T extends AllowedPartial,
N extends keyof T | null = null,
M extends keyof T | null = null,
E extends keyof T | '' = '',
> = {
readonly client: Client;
id: Snowflake;
partial: true;
} & {
[K in keyof Omit<T, 'client' | 'id' | 'partial' | E>]: K extends N ? null : K extends M ? T[K] | null : T[K];
};

export interface PartialDMChannel extends Partialize<DMChannel, null, null, 'lastMessageId'> {
lastMessageId: undefined;
}

export interface PartialGuildMember extends Partialize<GuildMember, 'joinedAt' | 'joinedTimestamp', 'user'> {}

export interface PartialMessage
extends Partialize<
Message,
| 'attachments'
| '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;
}
extends Partialize<Message, 'type' | 'system' | 'pinned' | 'tts', 'content' | 'cleanContent' | 'author'> {}

export interface PartialMessageReaction extends Partialize<MessageReaction, 'count'> {}

export interface PartialOverwriteData {
id: Snowflake | number;
Expand All @@ -3898,14 +3838,7 @@ export interface PartialRoleData extends RoleData {

export type PartialTypes = 'USER' | 'CHANNEL' | 'GUILD_MEMBER' | 'MESSAGE' | 'REACTION';

export interface PartialUser
extends Omit<Partialize<User, 'bot' | 'flags' | 'system' | 'tag' | 'username'>, 'deleted'> {
bot: null;
flags: User['flags'];
system: null;
readonly tag: null;
username: null;
}
export interface PartialUser extends Partialize<User, 'username' | 'tag' | 'discriminator'> {}

export type PresenceStatusData = ClientPresenceStatus | 'invisible';

Expand Down
22 changes: 22 additions & 0 deletions typings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -581,3 +581,25 @@ declare const guildEmojiManager: GuildEmojiManager;
assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch());
assertType<Promise<Collection<Snowflake, GuildEmoji>>>(guildEmojiManager.fetch(undefined, {}));
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);
});

0 comments on commit d6c43a5

Please sign in to comment.