From 9c048686c8d6ae7127b36e3695eb86172cfe131d Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:31:53 +0400 Subject: [PATCH 01/25] feat(structures): add Emoji methods --- src/structures/emoji.ts | 25 ++++++++++++++++++++++--- src/types/emoji.ts | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 0fbc8fe..cee279c 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -1,15 +1,14 @@ import { Client } from '../models/client.ts' import { EmojiPayload } from '../types/emoji.ts' +import { EMOJI } from '../types/endpoint.ts' import { Base } from './base.ts' -import { Guild } from './guild.ts' import { User } from './user.ts' export class Emoji extends Base { - id: string + id: string | null; name: string roles?: string[] user?: User - guild?: Guild requireColons?: boolean managed?: boolean animated?: boolean @@ -37,6 +36,18 @@ export class Emoji extends Base { this.available = data.available } + /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ + async edit(guildID: string, data: ModifyGuildEmojiParams) { + const res = await this.client.rest.patch(EMOJI(guildID, this.id!)); + return new Emoji(this.client, res); + } + + /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ + async delete(guildID: string): Promise { + await this.client.rest.patch(EMOJI(guildID, this.id!)); + return true; + } + readFromData(data: EmojiPayload): void { this.id = data.id ?? this.id this.name = data.name ?? this.name @@ -48,3 +59,11 @@ export class Emoji extends Base { if (data.user !== undefined) this.user = new User(this.client, data.user) } } + +/** https://discord.com/developers/docs/resources/emoji#modify-guild-emoji-json-params */ +export interface ModifyGuildEmojiParams { + /** Name of the emoji */ + name: string; + /** Roles to which this emoji will be whitelisted */ + roles: string[] | null; +} \ No newline at end of file diff --git a/src/types/emoji.ts b/src/types/emoji.ts index ab0216c..65d6f39 100644 --- a/src/types/emoji.ts +++ b/src/types/emoji.ts @@ -1,7 +1,7 @@ import { UserPayload } from './user.ts' export interface EmojiPayload { - id: string + id: string | null name: string roles?: string[] user?: UserPayload From c59d8f16393f57993fe12a116ba853814309e81b Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:33:45 +0400 Subject: [PATCH 02/25] style: format structures/emoji.ts --- src/structures/emoji.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index cee279c..0dfedda 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -5,7 +5,7 @@ import { Base } from './base.ts' import { User } from './user.ts' export class Emoji extends Base { - id: string | null; + id: string | null name: string roles?: string[] user?: User @@ -38,14 +38,14 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(guildID: string, data: ModifyGuildEmojiParams) { - const res = await this.client.rest.patch(EMOJI(guildID, this.id!)); - return new Emoji(this.client, res); + const res = await this.client.rest.patch(EMOJI(guildID, this.id!)) + return new Emoji(this.client, res) } /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(guildID: string): Promise { - await this.client.rest.patch(EMOJI(guildID, this.id!)); - return true; + await this.client.rest.patch(EMOJI(guildID, this.id!)) + return true } readFromData(data: EmojiPayload): void { @@ -63,7 +63,7 @@ export class Emoji extends Base { /** https://discord.com/developers/docs/resources/emoji#modify-guild-emoji-json-params */ export interface ModifyGuildEmojiParams { /** Name of the emoji */ - name: string; + name: string /** Roles to which this emoji will be whitelisted */ - roles: string[] | null; -} \ No newline at end of file + roles: string[] | null +} From 6c6334ee07a4d854dbdfa4141c4479eea56e3350 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:36:23 +0400 Subject: [PATCH 03/25] fix: add Emoji#guild property back --- src/structures/emoji.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 0dfedda..3fae41a 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -2,6 +2,7 @@ import { Client } from '../models/client.ts' import { EmojiPayload } from '../types/emoji.ts' import { EMOJI } from '../types/endpoint.ts' import { Base } from './base.ts' +import { Guild } from "./guild.ts" import { User } from './user.ts' export class Emoji extends Base { @@ -9,6 +10,7 @@ export class Emoji extends Base { name: string roles?: string[] user?: User + guild?: Guild; requireColons?: boolean managed?: boolean animated?: boolean @@ -37,14 +39,16 @@ export class Emoji extends Base { } /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ - async edit(guildID: string, data: ModifyGuildEmojiParams) { - const res = await this.client.rest.patch(EMOJI(guildID, this.id!)) + async edit(data: ModifyGuildEmojiParams) { + if (!this.guild) throw new Error("Guild is undefined"); + const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id!), data) return new Emoji(this.client, res) } /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ - async delete(guildID: string): Promise { - await this.client.rest.patch(EMOJI(guildID, this.id!)) + async delete(): Promise { + if (!this.guild) throw new Error("Guild is undefined"); + await this.client.rest.patch(EMOJI(this.guild.id, this.id!)) return true } From f3fa4ca380d75c866c684d93f426039a545d62a7 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:38:06 +0400 Subject: [PATCH 04/25] fix: remove type "null" from Emoji#id --- src/structures/emoji.ts | 6 +++--- src/types/emoji.ts | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 3fae41a..ae4acdf 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -6,7 +6,7 @@ import { Guild } from "./guild.ts" import { User } from './user.ts' export class Emoji extends Base { - id: string | null + id: string name: string roles?: string[] user?: User @@ -41,14 +41,14 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(data: ModifyGuildEmojiParams) { if (!this.guild) throw new Error("Guild is undefined"); - const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id!), data) + const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), data) return new Emoji(this.client, res) } /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { if (!this.guild) throw new Error("Guild is undefined"); - await this.client.rest.patch(EMOJI(this.guild.id, this.id!)) + await this.client.rest.patch(EMOJI(this.guild.id, this.id)) return true } diff --git a/src/types/emoji.ts b/src/types/emoji.ts index 65d6f39..ab0216c 100644 --- a/src/types/emoji.ts +++ b/src/types/emoji.ts @@ -1,7 +1,7 @@ import { UserPayload } from './user.ts' export interface EmojiPayload { - id: string | null + id: string name: string roles?: string[] user?: UserPayload From bef4d45a404711f5eee0a331aacc2c272e2585aa Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:38:43 +0400 Subject: [PATCH 05/25] style: format files --- src/structures/emoji.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index ae4acdf..51006d5 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -2,7 +2,7 @@ import { Client } from '../models/client.ts' import { EmojiPayload } from '../types/emoji.ts' import { EMOJI } from '../types/endpoint.ts' import { Base } from './base.ts' -import { Guild } from "./guild.ts" +import { Guild } from './guild.ts' import { User } from './user.ts' export class Emoji extends Base { @@ -10,7 +10,7 @@ export class Emoji extends Base { name: string roles?: string[] user?: User - guild?: Guild; + guild?: Guild requireColons?: boolean managed?: boolean animated?: boolean @@ -40,14 +40,17 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(data: ModifyGuildEmojiParams) { - if (!this.guild) throw new Error("Guild is undefined"); - const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), data) + if (!this.guild) throw new Error('Guild is undefined') + const res = await this.client.rest.patch( + EMOJI(this.guild.id, this.id), + data + ) return new Emoji(this.client, res) } /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { - if (!this.guild) throw new Error("Guild is undefined"); + if (!this.guild) throw new Error('Guild is undefined') await this.client.rest.patch(EMOJI(this.guild.id, this.id)) return true } From 6dd40afd3e6fe12a4b5b4baaa41fd5fa33496e43 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:41:21 +0400 Subject: [PATCH 06/25] Make linter happy :) --- src/structures/emoji.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 51006d5..16c22bb 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -39,8 +39,8 @@ export class Emoji extends Base { } /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ - async edit(data: ModifyGuildEmojiParams) { - if (!this.guild) throw new Error('Guild is undefined') + async edit(data: ModifyGuildEmojiParams): Promise { + if (this.guild === undefined) throw new Error('Guild is undefined') const res = await this.client.rest.patch( EMOJI(this.guild.id, this.id), data @@ -50,7 +50,7 @@ export class Emoji extends Base { /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { - if (!this.guild) throw new Error('Guild is undefined') + if (this.guild === undefined) throw new Error('Guild is undefined') await this.client.rest.patch(EMOJI(this.guild.id, this.id)) return true } From 104aa4249e984ac718b1a8417830b6469b621774 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 20:45:21 +0400 Subject: [PATCH 07/25] chore: consistent return type --- src/structures/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 16c22bb..1be0bc1 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -50,7 +50,7 @@ export class Emoji extends Base { /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { - if (this.guild === undefined) throw new Error('Guild is undefined') + if (this.guild === undefined) return false await this.client.rest.patch(EMOJI(this.guild.id, this.id)) return true } From 1e753cf51d5c34d008c668d397d520ce7670c081 Mon Sep 17 00:00:00 2001 From: ayntee Date: Fri, 25 Dec 2020 22:29:26 +0400 Subject: [PATCH 08/25] feat: add Role#tags prop --- src/structures/role.ts | 26 ++++++++++++++++++-------- src/types/role.ts | 10 ++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/structures/role.ts b/src/structures/role.ts index 01ada1d..a725127 100644 --- a/src/structures/role.ts +++ b/src/structures/role.ts @@ -12,14 +12,7 @@ export class Role extends Base { permissions: Permissions managed: boolean mentionable: boolean - - get mention(): string { - return `<@&${this.id}>` - } - - toString(): string { - return this.mention - } + tags?: RoleTags constructor(client: Client, data: RolePayload) { super(client, data) @@ -31,6 +24,14 @@ export class Role extends Base { this.permissions = new Permissions(data.permissions) this.managed = data.managed this.mentionable = data.mentionable + this.tags = + data.tags !== null + ? { + botID: data.tags?.bot_id, + integrationID: data.tags?.integration_id, + premiumSubscriber: 'premium_subscriber' in (data.tags ?? {}) + } + : undefined } readFromData(data: RolePayload): void { @@ -46,3 +47,12 @@ export class Role extends Base { this.mentionable = data.mentionable ?? this.mentionable } } + +export interface RoleTags { + /** The id of the bot who has this role */ + botID?: string + /** Whether this is the premium subscriber role for this guild */ + premiumSubscriber: boolean + /** The id of the integration this role belongs to */ + integrationID?: string +} diff --git a/src/types/role.ts b/src/types/role.ts index 78f43d6..d91aef8 100644 --- a/src/types/role.ts +++ b/src/types/role.ts @@ -7,4 +7,14 @@ export interface RolePayload { permissions: string managed: boolean mentionable: boolean + tags: RoleTagsPayload | null +} + +export interface RoleTagsPayload { + /** The id of the bot who has this role */ + bot_id?: string + /** Whether this is the premium subscriber role for this guild */ + premium_subscriber?: null + /** The id of the integration this role belongs to */ + integration_id?: string } From 6c576bec0a3d4cfb3c9b2275c268982c8272c239 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:11:26 +0400 Subject: [PATCH 09/25] chore: implement role resolution internally --- src/structures/emoji.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 1be0bc1..261de63 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -3,6 +3,7 @@ import { EmojiPayload } from '../types/emoji.ts' import { EMOJI } from '../types/endpoint.ts' import { Base } from './base.ts' import { Guild } from './guild.ts' +import { Role } from './role.ts' import { User } from './user.ts' export class Emoji extends Base { @@ -41,10 +42,10 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(data: ModifyGuildEmojiParams): Promise { if (this.guild === undefined) throw new Error('Guild is undefined') - const res = await this.client.rest.patch( - EMOJI(this.guild.id, this.id), - data - ) + const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), { + ...data, + roles: data.roles?.map((role) => role.id) + }) return new Emoji(this.client, res) } @@ -70,7 +71,7 @@ export class Emoji extends Base { /** https://discord.com/developers/docs/resources/emoji#modify-guild-emoji-json-params */ export interface ModifyGuildEmojiParams { /** Name of the emoji */ - name: string + name?: string /** Roles to which this emoji will be whitelisted */ - roles: string[] | null + roles?: Role[] } From 73e9ba9a254bc9846167b4212a90a938fbb719d4 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:17:54 +0400 Subject: [PATCH 10/25] fix: DELETE request instead of PATCH --- src/structures/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 261de63..7e78e1e 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -52,7 +52,7 @@ export class Emoji extends Base { /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { if (this.guild === undefined) return false - await this.client.rest.patch(EMOJI(this.guild.id, this.id)) + await this.client.rest.delete(EMOJI(this.guild.id, this.id)) return true } From a69988b6531b821c9a1ce8376e00c3d8f0e5d79c Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:34:15 +0400 Subject: [PATCH 11/25] ci: add Emoji#id check --- src/structures/emoji.ts | 8 +++++--- src/types/emoji.ts | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 7e78e1e..3ac4bba 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -7,8 +7,8 @@ import { Role } from './role.ts' import { User } from './user.ts' export class Emoji extends Base { - id: string - name: string + id: string | null + name: string | null roles?: string[] user?: User guild?: Guild @@ -41,8 +41,9 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(data: ModifyGuildEmojiParams): Promise { + if (this.id === null) throw new Error("Emoji ID is not valid."); if (this.guild === undefined) throw new Error('Guild is undefined') - const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), { + const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id!), { ...data, roles: data.roles?.map((role) => role.id) }) @@ -51,6 +52,7 @@ export class Emoji extends Base { /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { + if (this.id === null) return false; if (this.guild === undefined) return false await this.client.rest.delete(EMOJI(this.guild.id, this.id)) return true diff --git a/src/types/emoji.ts b/src/types/emoji.ts index ab0216c..c50f238 100644 --- a/src/types/emoji.ts +++ b/src/types/emoji.ts @@ -1,8 +1,8 @@ import { UserPayload } from './user.ts' export interface EmojiPayload { - id: string - name: string + id: string | null + name: string | null roles?: string[] user?: UserPayload require_colons?: boolean From 0a066a32e46a16af5fcc7ca3e1621d2e37a3aac0 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:36:52 +0400 Subject: [PATCH 12/25] Goddamn it, i gotta install prettier plugin on vim --- src/structures/emoji.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 8715379..3157ae7 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -19,7 +19,7 @@ export class Emoji extends Base { get getEmojiString(): string { if (this.id === null) { - return this.name as string; + return this.name as string } else { if (this.animated === false) { return `<:${this.name}:${this.id}>` @@ -45,7 +45,7 @@ export class Emoji extends Base { /** Modify the given emoji. Requires the MANAGE_EMOJIS permission. Returns the updated emoji object on success. Fires a Guild Emojis Update Gateway event. */ async edit(data: ModifyGuildEmojiParams): Promise { - if (this.id === null) throw new Error("Emoji ID is not valid."); + if (this.id === null) throw new Error('Emoji ID is not valid.') if (this.guild === undefined) throw new Error('Guild is undefined') const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id!), { ...data, @@ -56,7 +56,7 @@ export class Emoji extends Base { /** Delete the given emoji. Requires the MANAGE_EMOJIS permission. Returns `true` on success. Fires a Guild Emojis Update Gateway event. */ async delete(): Promise { - if (this.id === null) return false; + if (this.id === null) return false if (this.guild === undefined) return false await this.client.rest.delete(EMOJI(this.guild.id, this.id)) return true From 678e988aece698fb05d8bc1732f485e8b87b2f33 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:38:20 +0400 Subject: [PATCH 13/25] Remove redundant null assertion --- src/structures/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 3157ae7..daa5b03 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -47,7 +47,7 @@ export class Emoji extends Base { async edit(data: ModifyGuildEmojiParams): Promise { if (this.id === null) throw new Error('Emoji ID is not valid.') if (this.guild === undefined) throw new Error('Guild is undefined') - const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id!), { + const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), { ...data, roles: data.roles?.map((role) => role.id) }) From e25b7a8f5be36b949f858b86f87f831b9f1ee88d Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:47:13 +0400 Subject: [PATCH 14/25] Make CI happy --- src/managers/guildEmojis.ts | 2 +- src/managers/messageReactions.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/managers/guildEmojis.ts b/src/managers/guildEmojis.ts index dde2225..bab24c9 100644 --- a/src/managers/guildEmojis.ts +++ b/src/managers/guildEmojis.ts @@ -88,7 +88,7 @@ export class GuildEmojisManager extends BaseChildManager { const arr = await this.array() for (const elem of arr) { const emojiID = elem.id !== null ? elem.id : elem.name - this.parent.delete(emojiID) + this.parent.delete(emojiID as string) } return true } diff --git a/src/managers/messageReactions.ts b/src/managers/messageReactions.ts index 7c43ae6..e102ba4 100644 --- a/src/managers/messageReactions.ts +++ b/src/managers/messageReactions.ts @@ -23,7 +23,7 @@ export class MessageReactionsManager extends BaseManager< const emojiID = raw.emoji.id !== null ? raw.emoji.id : raw.emoji.name - let emoji = await this.client.emojis.get(emojiID) + let emoji = await this.client.emojis.get(emojiID as string) if (emoji === undefined) emoji = new Emoji(this.client, raw.emoji) const reaction = new MessageReaction(this.client, raw, this.message, emoji) @@ -46,7 +46,7 @@ export class MessageReactionsManager extends BaseManager< return await Promise.all( arr.map(async (raw) => { const emojiID = raw.emoji.id !== null ? raw.emoji.id : raw.emoji.name - let emoji = await this.client.emojis.get(emojiID) + let emoji = await this.client.emojis.get(emojiID as string) if (emoji === undefined) emoji = new Emoji(this.client, raw.emoji) return new MessageReaction(this.client, raw, this.message, emoji) From c7d117cd5442bcca0c81d60c57ea63fe32db4664 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 10:49:52 +0400 Subject: [PATCH 15/25] Make CI happy x2 --- src/gateway/handlers/guildEmojiUpdate.ts | 6 +++--- src/gateway/handlers/messageReactionAdd.ts | 2 +- src/gateway/handlers/messageReactionRemove.ts | 2 +- src/gateway/handlers/messageReactionRemoveEmoji.ts | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gateway/handlers/guildEmojiUpdate.ts b/src/gateway/handlers/guildEmojiUpdate.ts index db5e254..fddb657 100644 --- a/src/gateway/handlers/guildEmojiUpdate.ts +++ b/src/gateway/handlers/guildEmojiUpdate.ts @@ -17,7 +17,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async ( const _updated: EmojiPayload[] = [] for (const raw of d.emojis) { - const emojiID = raw.id !== null ? raw.id : raw.name + const emojiID = (raw.id !== null ? raw.id : raw.name) as string const has = emojis.get(emojiID) if (has === undefined) { await guild.emojis.set(emojiID, raw) @@ -27,7 +27,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async ( } for (const emoji of emojis.values()) { - const emojiID = emoji.id !== null ? emoji.id : emoji.name + const emojiID = (emoji.id !== null ? emoji.id : emoji.name) as string const find = _updated.find((e) => { const eID = e.id !== null ? e.id : e.name return emojiID === eID @@ -36,7 +36,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async ( await guild.emojis.delete(emojiID) deleted.push(emoji) } else { - const foundID = find.id !== null ? find.id : find.name + const foundID = (find.id !== null ? find.id : find.name) as string const before = (await guild.emojis.get(foundID)) as Emoji await guild.emojis.set(foundID, find) const after = (await guild.emojis.get(foundID)) as Emoji diff --git a/src/gateway/handlers/messageReactionAdd.ts b/src/gateway/handlers/messageReactionAdd.ts index 5b05ddd..edc88ae 100644 --- a/src/gateway/handlers/messageReactionAdd.ts +++ b/src/gateway/handlers/messageReactionAdd.ts @@ -29,7 +29,7 @@ export const messageReactionAdd: GatewayEventHandler = async ( } else return } - const emojiID = d.emoji.id !== null ? d.emoji.id : d.emoji.name + const emojiID = (d.emoji.id !== null ? d.emoji.id : d.emoji.name) as string let reaction = await message.reactions.get(emojiID) if (reaction === undefined) { await message.reactions.set(emojiID, { diff --git a/src/gateway/handlers/messageReactionRemove.ts b/src/gateway/handlers/messageReactionRemove.ts index 9cf50fa..77ca7df 100644 --- a/src/gateway/handlers/messageReactionRemove.ts +++ b/src/gateway/handlers/messageReactionRemove.ts @@ -27,7 +27,7 @@ export const messageReactionRemove: GatewayEventHandler = async ( } else return } - const emojiID = d.emoji.id !== null ? d.emoji.id : d.emoji.name + const emojiID = (d.emoji.id !== null ? d.emoji.id : d.emoji.name) as string const reaction = await message.reactions.get(emojiID) if (reaction === undefined) return diff --git a/src/gateway/handlers/messageReactionRemoveEmoji.ts b/src/gateway/handlers/messageReactionRemoveEmoji.ts index 0d1cd05..273ebc1 100644 --- a/src/gateway/handlers/messageReactionRemoveEmoji.ts +++ b/src/gateway/handlers/messageReactionRemoveEmoji.ts @@ -19,7 +19,7 @@ export const messageReactionRemoveEmoji: GatewayEventHandler = async ( } else return } - const emojiID = d.emoji.id !== null ? d.emoji.id : d.emoji.name + const emojiID = (d.emoji.id !== null ? d.emoji.id : d.emoji.name) as string const reaction = await message.reactions.get(emojiID) if (reaction === undefined) return From 95c220038631c85631360a15ec0d5ec268d5c03c Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 11:05:26 +0400 Subject: [PATCH 16/25] Make DjDev happy --- src/structures/emoji.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index daa5b03..ec8104b 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -47,9 +47,12 @@ export class Emoji extends Base { async edit(data: ModifyGuildEmojiParams): Promise { if (this.id === null) throw new Error('Emoji ID is not valid.') if (this.guild === undefined) throw new Error('Guild is undefined') + const roles = Array.isArray(data.roles) + ? data.roles?.map((role) => (role instanceof Role ? role.id : role)) + : [data.roles instanceof Role ? data.roles.id : data.roles] const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), { ...data, - roles: data.roles?.map((role) => role.id) + roles }) return new Emoji(this.client, res) } @@ -79,5 +82,5 @@ export interface ModifyGuildEmojiParams { /** Name of the emoji */ name?: string /** Roles to which this emoji will be whitelisted */ - roles?: Role[] + roles?: string | Role | (string | Role)[] } From 900f6c3c3b175b43ba53625a4b9dadbd80240a7a Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 11:07:33 +0400 Subject: [PATCH 17/25] Make linter happy --- src/structures/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index ec8104b..7f0fcf1 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -82,5 +82,5 @@ export interface ModifyGuildEmojiParams { /** Name of the emoji */ name?: string /** Roles to which this emoji will be whitelisted */ - roles?: string | Role | (string | Role)[] + roles?: string | Role | string[] | Array; } From 4cf153aaac411a0d154d5438005316db35bf1a43 Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 11:09:09 +0400 Subject: [PATCH 18/25] I have no idea what I am doing --- src/structures/emoji.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index 7f0fcf1..f135091 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -82,5 +82,5 @@ export interface ModifyGuildEmojiParams { /** Name of the emoji */ name?: string /** Roles to which this emoji will be whitelisted */ - roles?: string | Role | string[] | Array; + roles?: string | Role | string[] | Role[]; } From 93eee2f15d9e66328c3dc724f6bc04ff7d79b49f Mon Sep 17 00:00:00 2001 From: ayntee Date: Sat, 26 Dec 2020 11:12:06 +0400 Subject: [PATCH 19/25] I have no idea what I am doing x2 --- src/structures/emoji.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts index f135091..072a3e5 100644 --- a/src/structures/emoji.ts +++ b/src/structures/emoji.ts @@ -48,7 +48,7 @@ export class Emoji extends Base { if (this.id === null) throw new Error('Emoji ID is not valid.') if (this.guild === undefined) throw new Error('Guild is undefined') const roles = Array.isArray(data.roles) - ? data.roles?.map((role) => (role instanceof Role ? role.id : role)) + ? data.roles.map(role => (role instanceof Role ? role.id : role)) : [data.roles instanceof Role ? data.roles.id : data.roles] const res = await this.client.rest.patch(EMOJI(this.guild.id, this.id), { ...data, @@ -82,5 +82,5 @@ export interface ModifyGuildEmojiParams { /** Name of the emoji */ name?: string /** Roles to which this emoji will be whitelisted */ - roles?: string | Role | string[] | Role[]; + roles?: string | Role | Array; } From b7a93a280fde5fb1bdaf442bde85a91242c45761 Mon Sep 17 00:00:00 2001 From: Ayyan Date: Mon, 28 Dec 2020 12:14:10 +0400 Subject: [PATCH 20/25] Update role.ts --- src/types/role.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/types/role.ts b/src/types/role.ts index d91aef8..5ddfee8 100644 --- a/src/types/role.ts +++ b/src/types/role.ts @@ -7,7 +7,7 @@ export interface RolePayload { permissions: string managed: boolean mentionable: boolean - tags: RoleTagsPayload | null + tags?: RoleTagsPayload } export interface RoleTagsPayload { From e37e0c38853f5b97e52d28c3f8693e2d7f2a01dc Mon Sep 17 00:00:00 2001 From: Ayyan Date: Mon, 28 Dec 2020 12:18:09 +0400 Subject: [PATCH 21/25] Update role.ts --- src/structures/role.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/role.ts b/src/structures/role.ts index a725127..ed2e821 100644 --- a/src/structures/role.ts +++ b/src/structures/role.ts @@ -25,7 +25,7 @@ export class Role extends Base { this.managed = data.managed this.mentionable = data.mentionable this.tags = - data.tags !== null + data.tags !== undefined ? { botID: data.tags?.bot_id, integrationID: data.tags?.integration_id, From 9178e6cec12c23766277a9db5f8a5be00a003157 Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Mon, 28 Dec 2020 18:05:08 +0530 Subject: [PATCH 22/25] feat: new rest methods --- src/managers/base.ts | 7 +++- src/managers/guildChannels.ts | 1 + src/managers/invites.ts | 9 ++--- src/managers/memberRoles.ts | 4 +-- src/managers/members.ts | 1 + src/managers/messageReactions.ts | 19 +++++++++++ src/managers/roles.ts | 57 +++++++++++++++++++++++++++++--- src/models/client.ts | 14 ++++++++ 8 files changed, 101 insertions(+), 11 deletions(-) diff --git a/src/managers/base.ts b/src/managers/base.ts index 5fef9d2..9d5bd7e 100644 --- a/src/managers/base.ts +++ b/src/managers/base.ts @@ -37,10 +37,15 @@ export class BaseManager { } /** Deletes a key from Cache */ - async delete(key: string): Promise { + async _delete(key: string): Promise { return this.client.cache.delete(this.cacheName, key) } + /** Alias to _delete (cache) for compatibility purposes */ + async delete(key: string): Promise { + return await this._delete(key) + } + /** Gets an Array of values from Cache */ async array(): Promise { let arr = await (this.client.cache.array(this.cacheName) as T[]) diff --git a/src/managers/guildChannels.ts b/src/managers/guildChannels.ts index a6854a8..3bdaed8 100644 --- a/src/managers/guildChannels.ts +++ b/src/managers/guildChannels.ts @@ -36,6 +36,7 @@ export class GuildChannelsManager extends BaseChildManager< else return undefined } + /** Delete a Guild Channel */ async delete(id: string): Promise { return this.client.rest.delete(CHANNEL(id)) } diff --git a/src/managers/invites.ts b/src/managers/invites.ts index 6af3896..e5baf27 100644 --- a/src/managers/invites.ts +++ b/src/managers/invites.ts @@ -1,7 +1,7 @@ import { Client } from '../models/client.ts' import { Guild } from '../structures/guild.ts' import { Invite } from '../structures/invite.ts' -import { GUILD_INVITES } from '../types/endpoint.ts' +import { INVITE } from '../types/endpoint.ts' import { InvitePayload } from '../types/invite.ts' import { BaseManager } from './base.ts' @@ -19,14 +19,15 @@ export class InviteManager extends BaseManager { return new Invite(this.client, raw) } - async fetch(id: string): Promise { + /** Fetch an Invite */ + async fetch(id: string): Promise { return await new Promise((resolve, reject) => { this.client.rest - .get(GUILD_INVITES(this.guild.id)) + .get(INVITE(id)) .then(async (data) => { this.set(id, data as InvitePayload) const newInvite = await this.get(data.code) - resolve(newInvite) + resolve(newInvite as Invite) }) .catch((e) => reject(e)) }) diff --git a/src/managers/memberRoles.ts b/src/managers/memberRoles.ts index bb715e0..a405340 100644 --- a/src/managers/memberRoles.ts +++ b/src/managers/memberRoles.ts @@ -60,7 +60,7 @@ export class MemberRolesManager extends BaseChildManager { true ) - return res.status === 204 + return res.response.status === 204 } async remove(role: string | Role): Promise { @@ -76,6 +76,6 @@ export class MemberRolesManager extends BaseChildManager { true ) - return res.status === 204 + return res.response.status === 204 } } diff --git a/src/managers/members.ts b/src/managers/members.ts index b06bb06..200e890 100644 --- a/src/managers/members.ts +++ b/src/managers/members.ts @@ -58,6 +58,7 @@ export class MembersManager extends BaseManager { ) } + /** Fetch a Guild Member */ async fetch(id: string): Promise { return await new Promise((resolve, reject) => { this.client.rest diff --git a/src/managers/messageReactions.ts b/src/managers/messageReactions.ts index 7c43ae6..baccc4c 100644 --- a/src/managers/messageReactions.ts +++ b/src/managers/messageReactions.ts @@ -4,6 +4,7 @@ import { Guild } from '../structures/guild.ts' import { Message } from '../structures/message.ts' import { MessageReaction } from '../structures/messageReaction.ts' import { Reaction } from '../types/channel.ts' +import { MESSAGE_REACTION, MESSAGE_REACTIONS } from '../types/endpoint.ts' import { BaseManager } from './base.ts' export class MessageReactionsManager extends BaseManager< @@ -58,4 +59,22 @@ export class MessageReactionsManager extends BaseManager< await this.client.cache.deleteCache(`reaction_users:${this.message.id}`) return this.client.cache.deleteCache(this.cacheName) } + + /** Remove all Reactions from the Message */ + async removeAll(): Promise { + await this.client.rest.delete( + MESSAGE_REACTIONS(this.message.channel.id, this.message.id) + ) + } + + /** Remove a specific Emoji from Reactions */ + async removeEmoji(emoji: Emoji | string): Promise { + const val = encodeURIComponent( + typeof emoji === 'object' ? emoji.id ?? emoji.name : emoji + ) + await this.client.rest.delete( + MESSAGE_REACTION(this.message.channel.id, this.message.id, val) + ) + return this + } } diff --git a/src/managers/roles.ts b/src/managers/roles.ts index 437c6c0..0ad93ef 100644 --- a/src/managers/roles.ts +++ b/src/managers/roles.ts @@ -1,10 +1,19 @@ +import { Permissions } from '../../mod.ts' import { Client } from '../models/client.ts' import { Guild } from '../structures/guild.ts' import { Role } from '../structures/role.ts' -import { GUILD_ROLE } from '../types/endpoint.ts' +import { GUILD_ROLE, GUILD_ROLES } from '../types/endpoint.ts' import { RolePayload } from '../types/role.ts' import { BaseManager } from './base.ts' +export interface CreateGuildRoleOptions { + name?: string + permissions?: number | string | Permissions + color?: number | string + hoist?: boolean + mentionable?: boolean +} + export class RolesManager extends BaseManager { guild: Guild @@ -13,13 +22,14 @@ export class RolesManager extends BaseManager { this.guild = guild } + /** Fetch a Guild Role (from API) */ async fetch(id: string): Promise { return await new Promise((resolve, reject) => { this.client.rest .get(GUILD_ROLE(this.guild.id, id)) - .then((data) => { - this.set(id, data as RolePayload) - resolve(new Role(this.client, data as RolePayload)) + .then(async (data) => { + await this.set(id, data as RolePayload) + resolve(((await this.get(id)) as unknown) as Role) }) .catch((e) => reject(e)) }) @@ -31,4 +41,43 @@ export class RolesManager extends BaseManager { } return true } + + /** Create a Guild Role */ + async create(data?: CreateGuildRoleOptions): Promise { + if (typeof data?.color === 'string') { + if (data.color.startsWith('#')) data.color = data.color.slice(1) + } + + const roleRaw = ((await this.client.rest.post(GUILD_ROLES(this.guild.id), { + name: data?.name, + permissions: + data?.permissions === undefined + ? undefined + : (typeof data.permissions === 'object' + ? data.permissions.bitfield + : data.permissions + ).toString(), + color: + data?.color === undefined + ? undefined + : typeof data.color === 'string' + ? isNaN(parseInt(data.color, 16)) + ? 0 + : parseInt(data.color, 16) + : data.color, + hoist: data?.hoist ?? false, + mentionable: data?.mentionable ?? false + })) as unknown) as RolePayload + + await this.set(roleRaw.id, roleRaw) + return ((await this.get(roleRaw.id)) as unknown) as Role + } + + /** Delete a Guild Role */ + async delete(role: Role | string): Promise { + await this.client.rest.delete( + GUILD_ROLE(this.guild.id, typeof role === 'object' ? role.id : role) + ) + return true + } } diff --git a/src/models/client.ts b/src/models/client.ts index f0bcc73..ac96ab8 100644 --- a/src/models/client.ts +++ b/src/models/client.ts @@ -17,6 +17,8 @@ import { Interaction } from '../structures/slash.ts' import { SlashModule } from './slashModule.ts' import type { ShardManager } from './shard.ts' import { Application } from '../structures/application.ts' +import { Invite } from '../structures/invite.ts' +import { INVITE } from '../types/endpoint.ts' /** OS related properties sent with Gateway Identify */ export interface ClientProperties { @@ -211,6 +213,18 @@ export class Client extends EventEmitter { return new Application(this, app) } + /** Fetch an Invite */ + async fetch(id: string): Promise { + return await new Promise((resolve, reject) => { + this.rest + .get(INVITE(id)) + .then((data) => { + resolve(new Invite(this, data)) + }) + .catch((e) => reject(e)) + }) + } + /** * This function is used for connecting to discord. * @param token Your token. This is required. From 991770d211f7e04f43217b6550495b4b159c449c Mon Sep 17 00:00:00 2001 From: Helloyunho Date: Tue, 29 Dec 2020 11:52:30 +0900 Subject: [PATCH 23/25] Change the event typing way and add .waitFor method --- src/gateway/handlers/index.ts | 110 ++++++++++++++++++---------------- src/models/client.ts | 80 +++++++++++++++++++------ src/test/index.ts | 8 +++ 3 files changed, 130 insertions(+), 68 deletions(-) diff --git a/src/gateway/handlers/index.ts b/src/gateway/handlers/index.ts index a85d8fc..8efa31e 100644 --- a/src/gateway/handlers/index.ts +++ b/src/gateway/handlers/index.ts @@ -99,238 +99,248 @@ export const gatewayHandlers: { INTERACTION_CREATE: interactionCreate } -export interface EventTypes { - [name: string]: (...args: any[]) => void -} - export interface VoiceServerUpdateData { token: string endpoint: string guild: Guild } -export interface ClientEvents extends EventTypes { +export interface ClientEvents { /** When Client has successfully connected to Discord */ - ready: () => void + ready: [] /** When a successful reconnect has been made */ - reconnect: () => void + reconnect: [] /** When a successful session resume has been done */ - resumed: () => void + resumed: [] /** * When a new Channel is created * @param channel New Channel object */ - channelCreate: (channel: EveryChannelTypes) => void + channelCreate: [channel: EveryChannelTypes] /** * When a Channel was deleted * @param channel Channel object which was deleted */ - channelDelete: (channel: EveryChannelTypes) => void + channelDelete: [channel: EveryChannelTypes] /** * Channel's Pinned Messages were updated * @param before Channel object before update * @param after Channel object after update */ - channelPinsUpdate: ( + channelPinsUpdate: [ before: EveryTextChannelTypes, after: EveryTextChannelTypes - ) => void + ] /** * A Channel was updated * @param before Channel object before update * @param after Channel object after update */ - channelUpdate: (before: EveryChannelTypes, after: EveryChannelTypes) => void + channelUpdate: [before: EveryChannelTypes, after: EveryChannelTypes] /** * A User was banned from a Guild * @param guild The Guild from which User was banned * @param user The User who was banned */ - guildBanAdd: (guild: Guild, user: User) => void + guildBanAdd: [guild: Guild, user: User] /** * A ban from a User in Guild was elevated * @param guild Guild from which ban was removed * @param user User of which ban was elevated */ - guildBanRemove: (guild: Guild, user: User) => void + guildBanRemove: [guild: Guild, user: User] /** * Client has joined a new Guild. * @param guild The new Guild object */ - guildCreate: (guild: Guild) => void + guildCreate: [guild: Guild] /** * A Guild in which Client was either deleted, or bot was kicked * @param guild The Guild object */ - guildDelete: (guild: Guild) => void + guildDelete: [guild: Guild] /** * A new Emoji was added to Guild * @param guild Guild in which Emoji was added * @param emoji The Emoji which was added */ - guildEmojiAdd: (guild: Guild, emoji: Emoji) => void + guildEmojiAdd: [guild: Guild, emoji: Emoji] /** * An Emoji was deleted from Guild * @param guild Guild from which Emoji was deleted * @param emoji Emoji which was deleted */ - guildEmojiDelete: (guild: Guild, emoji: Emoji) => void + guildEmojiDelete: [Guild, Emoji] /** * An Emoji in a Guild was updated * @param guild Guild in which Emoji was updated * @param before Emoji object before update * @param after Emoji object after update */ - guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void + guildEmojiUpdate: [guild: Guild, before: Emoji, after: Emoji] /** * Guild's Integrations were updated * @param guild The Guild object */ - guildIntegrationsUpdate: (guild: Guild) => void + guildIntegrationsUpdate: [guild: Guild] /** * A new Member has joined a Guild * @param member The Member object */ - guildMemberAdd: (member: Member) => void + guildMemberAdd: [member: Member] /** * A Guild Member has either left or was kicked from Guild * @param member The Member object */ - guildMemberRemove: (member: Member) => void + guildMemberRemove: [member: Member] /** * A Guild Member was updated. Nickname changed, role assigned, etc. * @param before Member object before update * @param after Meber object after update */ - guildMemberUpdate: (before: Member, after: Member) => void + guildMemberUpdate: [before: Member, after: Member] /** * A new Role was created in Guild * @param role The new Role object */ - guildRoleCreate: (role: Role) => void + guildRoleCreate: [role: Role] /** * A Role was deleted from the Guild * @param role The Role object */ - guildRoleDelete: (role: Role) => void + guildRoleDelete: [role: Role] /** * A Role was updated in a Guild * @param before Role object before update * @param after Role object after updated */ - guildRoleUpdate: (before: Role, after: Role) => void + guildRoleUpdate: [before: Role, after: Role] /** * A Guild has been updated. For example name, icon, etc. * @param before Guild object before update * @param after Guild object after update */ - guildUpdate: (before: Guild, after: Guild) => void + guildUpdate: [before: Guild, after: Guild] /** * A new Message was created (sent) * @param message The new Message object */ - messageCreate: (message: Message) => void + messageCreate: [message: Message] /** * A Message was deleted. * @param message The Message object */ - messageDelete: (message: Message) => void + messageDelete: [message: Message] /** * Messages were bulk deleted in a Guild Text Channel * @param channel Channel in which Messages were deleted * @param messages Collection of Messages deleted * @param uncached Set of Messages deleted's IDs which were not cached */ - messageDeleteBulk: ( + messageDeleteBulk: [ channel: GuildTextChannel, messages: Collection, uncached: Set - ) => void + ] /** * A Message was updated. For example content, embed, etc. * @param before Message object before update * @param after Message object after update */ - messageUpdate: (before: Message, after: Message) => void + messageUpdate: [before: Message, after: Message] /** * Reaction was added to a Message * @param reaction Reaction object * @param user User who added the reaction */ - messageReactionAdd: (reaction: MessageReaction, user: User) => void + messageReactionAdd: [reaction: MessageReaction, user: User] /** * Reaction was removed fro a Message * @param reaction Reaction object * @param user User to who removed the reaction */ - messageReactionRemove: (reaction: MessageReaction, user: User) => void + messageReactionRemove: [reaction: MessageReaction, user: User] /** * All reactions were removed from a Message * @param message Message from which reactions were removed */ - messageReactionRemoveAll: (message: Message) => void + messageReactionRemoveAll: [message: Message] /** * All reactions of a single Emoji were removed * @param message The Message object * @param emoji The Emoji object */ - messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void + messageReactionRemoveEmoji: [message: Message, emoji: Emoji] /** * A User has started typing in a Text Channel + * @param user User who started typing + * @param channel Channel which user started typing in + * @param at Date when user started typing + * @param guild Guild which user started typing in (can be undefined) */ - typingStart: ( + typingStart: [ user: User, channel: TextChannel, at: Date, - guildData?: TypingStartGuildData - ) => void + guild: TypingStartGuildData | undefined + ] /** * A new Invite was created * @param invite New Invite object */ - inviteCreate: (invite: Invite) => void + inviteCreate: [invite: Invite] /** * An Invite was deleted * @param invite Invite object */ - inviteDelete: (invite: Invite) => void + inviteDelete: [invite: Invite] /** * A User was updated. For example username, avatar, etc. * @param before The User object before update * @param after The User object after update */ - userUpdate: (before: User, after: User) => void + userUpdate: [before: User, after: User] /** * Client has received credentials for establishing connection to Voice Server + * @param data Updated voice server object */ - voiceServerUpdate: (data: VoiceServerUpdateData) => void + voiceServerUpdate: [data: VoiceServerUpdateData] /** * A User has joined a Voice Channel + * @param state Added voice state object */ - voiceStateAdd: (state: VoiceState) => void + voiceStateAdd: [state: VoiceState] /** * A User has left a Voice Channel + * @param state Removed voice state object */ - voiceStateRemove: (state: VoiceState) => void + voiceStateRemove: [state: VoiceState] /** * Voice State of a User has been updated * @param before Voice State object before update * @param after Voice State object after update */ - voiceStateUpdate: (state: VoiceState, after: VoiceState) => void + voiceStateUpdate: [before: VoiceState, after: VoiceState] /** * A User's presence has been updated * @param presence New Presence */ - presenceUpdate: (presence: Presence) => void + presenceUpdate: [presence: Presence] /** * Webhooks of a Channel in a Guild has been updated * @param guild Guild in which Webhooks were updated * @param channel Channel of which Webhooks were updated */ - webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void + webhooksUpdate: [guild: Guild, channel: GuildTextChannel] /** * An Interaction was created + * @param interaction Created interaction object */ - interactionCreate: (interaction: Interaction) => void + interactionCreate: [interaction: Interaction] + + /** + * When debug message was made + * @param message Debug message + */ + debug: [message: string] } diff --git a/src/models/client.ts b/src/models/client.ts index f0bcc73..e72854e 100644 --- a/src/models/client.ts +++ b/src/models/client.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/method-signature-style */ import { User } from '../structures/user.ts' import { GatewayIntents } from '../types/gateway.ts' import { Gateway } from '../gateway/index.ts' @@ -10,13 +11,13 @@ import { ChannelsManager } from '../managers/channels.ts' import { ClientPresence } from '../structures/presence.ts' import { EmojisManager } from '../managers/emojis.ts' import { ActivityGame, ClientActivity } from '../types/presence.ts' -import { ClientEvents } from '../gateway/handlers/index.ts' import { Extension } from './extensions.ts' import { SlashClient } from './slashClient.ts' import { Interaction } from '../structures/slash.ts' import { SlashModule } from './slashModule.ts' import type { ShardManager } from './shard.ts' import { Application } from '../structures/application.ts' +import { ClientEvents } from '../gateway/handlers/index.ts' /** OS related properties sent with Gateway Identify */ export interface ClientProperties { @@ -53,6 +54,32 @@ export interface ClientOptions { enableSlash?: boolean } +export declare interface Client { + on( + event: K, + listener: (...args: ClientEvents[K]) => void + ): this + on(event: string | symbol, listener: (...args: any[]) => void): this + + once( + event: K, + listener: (...args: ClientEvents[K]) => void + ): this + once(event: string | symbol, listener: (...args: any[]) => void): this + + emit( + event: K, + ...args: ClientEvents[K] + ): boolean + emit(event: string | symbol, ...args: any[]): boolean + + off( + event: K, + listener: (...args: ClientEvents[K]) => void + ): this + off(event: string | symbol, listener: (...args: any[]) => void): this +} + /** * Discord Client. */ @@ -93,7 +120,10 @@ export class Client extends EventEmitter { canary: boolean = false /** Client's presence. Startup one if set before connecting */ presence: ClientPresence = new ClientPresence() - _decoratedEvents?: { [name: string]: (...args: any[]) => any } + _decoratedEvents?: { + [name: string]: (...args: any[]) => void + } + _decoratedSlash?: Array<{ name: string guild?: string @@ -105,18 +135,6 @@ export class Client extends EventEmitter { _decoratedSlashModules?: SlashModule[] _id?: string - private readonly _untypedOn = this.on - - private readonly _untypedEmit = this.emit - - public on = (event: K, listener: ClientEvents[K]): this => - this._untypedOn(event, listener) - - public emit = ( - event: K, - ...args: Parameters - ): boolean => this._untypedEmit(event, ...args) - /** Shard on which this Client is */ shard: number = 0 /** Shard Manager of this Client if Sharded */ @@ -233,17 +251,43 @@ export class Client extends EventEmitter { } else throw new Error('No Gateway Intents were provided') this.gateway = new Gateway(this, token, intents) } + + async waitFor( + event: K, + checkFunction: (...args: ClientEvents[K]) => boolean, + timeout?: number + ): Promise { + return await new Promise((resolve) => { + let timeoutID: number | undefined + if (timeout !== undefined) { + timeoutID = setTimeout(() => { + this.off(event, eventFunc) + resolve([]) + }, timeout) + } + const eventFunc = (...args: ClientEvents[K]): void => { + if (checkFunction(...args)) { + resolve(args) + this.off(event, eventFunc) + if (timeoutID !== undefined) clearTimeout(timeoutID) + } + } + this.on(event, eventFunc) + }) + } } -export function event(name?: string) { - return function (client: Client | Extension, prop: string) { +export function event(name?: keyof ClientEvents) { + return function (client: Client | Extension, prop: keyof ClientEvents) { const listener = ((client as unknown) as { - [name: string]: (...args: any[]) => any + [name in keyof ClientEvents]: (...args: ClientEvents[name]) => any })[prop] if (typeof listener !== 'function') throw new Error('@event decorator requires a function') if (client._decoratedEvents === undefined) client._decoratedEvents = {} - client._decoratedEvents[name === undefined ? prop : name] = listener + const key = name === undefined ? prop : name + + client._decoratedEvents[key] = listener } } diff --git a/src/test/index.ts b/src/test/index.ts index c0d14c3..72a4fcf 100644 --- a/src/test/index.ts +++ b/src/test/index.ts @@ -114,6 +114,14 @@ client.on('messageCreate', async (msg: Message) => { } } else if (msg.content === '!react') { msg.addReaction('🤔') + } else if (msg.content === '!wait_for') { + msg.channel.send('Send anything!') + const [receivedMsg] = await client.waitFor( + 'messageCreate', + (message) => message.author.id === msg.author.id + ) + + msg.channel.send(`Received: ${receivedMsg?.content}`) } }) From 63ae6f43128bd818db73e7976e250a984def4e06 Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Tue, 29 Dec 2020 10:13:28 +0530 Subject: [PATCH 24/25] feat: rename fetch -> fetchInvite --- src/models/client.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/client.ts b/src/models/client.ts index ac96ab8..7bb6a91 100644 --- a/src/models/client.ts +++ b/src/models/client.ts @@ -214,7 +214,7 @@ export class Client extends EventEmitter { } /** Fetch an Invite */ - async fetch(id: string): Promise { + async fetchInvite(id: string): Promise { return await new Promise((resolve, reject) => { this.rest .get(INVITE(id)) From 2ddb6bf5a5f055fe04ac13ea4c34981fafc03bd4 Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Tue, 29 Dec 2020 11:47:36 +0530 Subject: [PATCH 25/25] fix --- src/managers/messageReactions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/managers/messageReactions.ts b/src/managers/messageReactions.ts index ed46276..000c5f9 100644 --- a/src/managers/messageReactions.ts +++ b/src/managers/messageReactions.ts @@ -70,7 +70,7 @@ export class MessageReactionsManager extends BaseManager< /** Remove a specific Emoji from Reactions */ async removeEmoji(emoji: Emoji | string): Promise { const val = encodeURIComponent( - typeof emoji === 'object' ? emoji.id ?? emoji.name : emoji + (typeof emoji === 'object' ? emoji.id ?? emoji.name : emoji) as string ) await this.client.rest.delete( MESSAGE_REACTION(this.message.channel.id, this.message.id, val)