From 22e041f4402d8f20f2732e5a61711d30120c56db Mon Sep 17 00:00:00 2001 From: DjDeveloperr Date: Sun, 4 Apr 2021 11:12:15 +0530 Subject: [PATCH] refactor --- deploy.ts | 28 +- mod.ts | 34 +- .../cacheAdapter.ts => cache/adapter.ts} | 0 src/{models/redisCache.ts => cache/redis.ts} | 10 +- src/{models => client}/client.ts | 874 +++++------ src/{models => client}/collectors.ts | 2 +- src/client/mod.ts | 3 + src/{models => client}/shard.ts | 4 +- .../commandClient.ts => commands/client.ts} | 4 +- src/{models => commands}/command.ts | 4 +- .../extensions.ts => commands/extension.ts} | 2 +- src/commands/mod.ts | 3 + src/consts/urlsAndVersions.ts | 9 - .../handlers/applicationCommandCreate.ts | 4 +- .../handlers/applicationCommandDelete.ts | 4 +- .../handlers/applicationCommandUpdate.ts | 4 +- src/gateway/handlers/channelCreate.ts | 2 +- src/gateway/handlers/channelDelete.ts | 2 +- src/gateway/handlers/channelPinsUpdate.ts | 2 +- src/gateway/handlers/channelUpdate.ts | 2 +- src/gateway/handlers/guildBanAdd.ts | 2 +- src/gateway/handlers/guildBanRemove.ts | 2 +- src/gateway/handlers/guildCreate.ts | 2 +- src/gateway/handlers/guildDelete.ts | 2 +- src/gateway/handlers/guildEmojiUpdate.ts | 2 +- .../handlers/guildIntegrationsUpdate.ts | 2 +- src/gateway/handlers/guildMemberAdd.ts | 2 +- src/gateway/handlers/guildMemberRemove.ts | 2 +- src/gateway/handlers/guildMemberUpdate.ts | 2 +- src/gateway/handlers/guildMembersChunk.ts | 2 +- src/gateway/handlers/guildRoleCreate.ts | 2 +- src/gateway/handlers/guildRoleDelete.ts | 2 +- src/gateway/handlers/guildRoleUpdate.ts | 2 +- src/gateway/handlers/guildUpdate.ts | 2 +- src/gateway/handlers/interactionCreate.ts | 2 +- src/gateway/handlers/inviteCreate.ts | 2 +- src/gateway/handlers/inviteDelete.ts | 2 +- src/gateway/handlers/messageCreate.ts | 2 +- src/gateway/handlers/messageDelete.ts | 2 +- src/gateway/handlers/messageDeleteBulk.ts | 2 +- src/gateway/handlers/messageReactionAdd.ts | 2 +- src/gateway/handlers/messageReactionRemove.ts | 2 +- .../handlers/messageReactionRemoveAll.ts | 2 +- .../handlers/messageReactionRemoveEmoji.ts | 2 +- src/gateway/handlers/messageUpdate.ts | 2 +- src/gateway/handlers/{index.ts => mod.ts} | 8 +- src/gateway/handlers/presenceUpdate.ts | 2 +- src/gateway/handlers/ready.ts | 2 +- src/gateway/handlers/reconnect.ts | 2 +- src/gateway/handlers/resume.ts | 2 +- src/gateway/handlers/typingStart.ts | 2 +- src/gateway/handlers/userUpdate.ts | 2 +- src/gateway/handlers/voiceServerUpdate.ts | 2 +- src/gateway/handlers/voiceStateUpdate.ts | 2 +- src/gateway/handlers/webhooksUpdate.ts | 2 +- src/gateway/{index.ts => mod.ts} | 11 +- src/interactions/mod.ts | 3 + src/{models => interactions}/slashClient.ts | 351 +---- src/interactions/slashCommand.ts | 349 +++++ src/{models => interactions}/slashModule.ts | 0 src/managers/base.ts | 2 +- src/managers/baseChild.ts | 2 +- src/managers/channels.ts | 2 +- src/managers/emojis.ts | 2 +- src/managers/gatewayCache.ts | 2 +- src/managers/guildChannelVoiceStates.ts | 2 +- src/managers/guildChannels.ts | 2 +- src/managers/guildEmojis.ts | 2 +- src/managers/guildVoiceStates.ts | 2 +- src/managers/guilds.ts | 2 +- src/managers/invites.ts | 2 +- src/managers/memberRoles.ts | 2 +- src/managers/members.ts | 2 +- src/managers/messageReactions.ts | 2 +- src/managers/messages.ts | 2 +- src/managers/presences.ts | 2 +- src/managers/reactionUsers.ts | 2 +- src/managers/roles.ts | 2 +- src/managers/users.ts | 2 +- src/{models/rest.ts => rest/manager.ts} | 1321 ++++++++--------- src/rest/mod.ts | 2 + src/rest/types.ts | 37 + src/structures/application.ts | 2 +- src/structures/base.ts | 2 +- src/structures/channel.ts | 23 +- src/structures/dmChannel.ts | 2 +- src/structures/emoji.ts | 2 +- src/structures/groupChannel.ts | 2 +- src/structures/guild.ts | 6 +- src/structures/guildTextChannel.ts | 2 +- src/structures/guildVoiceChannel.ts | 6 +- src/structures/invite.ts | 2 +- src/structures/member.ts | 2 +- src/structures/message.ts | 2 +- src/structures/messageMentions.ts | 2 +- src/structures/messageReaction.ts | 2 +- src/structures/messageSticker.ts | 2 +- src/structures/presence.ts | 2 +- src/structures/role.ts | 2 +- src/structures/slash.ts | 2 +- src/structures/template.ts | 2 +- src/structures/textChannel.ts | 2 +- src/structures/user.ts | 2 +- src/structures/voiceState.ts | 2 +- src/structures/webhook.ts | 13 +- src/test/music.ts | 2 +- src/types/constants.ts | 7 + src/types/endpoint.ts | 161 +- src/types/mod.ts | 20 + src/utils/getChannelByType.ts | 2 +- src/utils/index.ts | 3 - 111 files changed, 1753 insertions(+), 1713 deletions(-) rename src/{models/cacheAdapter.ts => cache/adapter.ts} (100%) rename src/{models/redisCache.ts => cache/redis.ts} (91%) rename src/{models => client}/client.ts (93%) rename src/{models => client}/collectors.ts (95%) create mode 100644 src/client/mod.ts rename src/{models => client}/shard.ts (97%) rename src/{models/commandClient.ts => commands/client.ts} (99%) rename src/{models => commands}/command.ts (99%) rename src/{models/extensions.ts => commands/extension.ts} (98%) create mode 100644 src/commands/mod.ts delete mode 100644 src/consts/urlsAndVersions.ts rename src/gateway/handlers/{index.ts => mod.ts} (98%) rename src/gateway/{index.ts => mod.ts} (98%) create mode 100644 src/interactions/mod.ts rename src/{models => interactions}/slashClient.ts (54%) create mode 100644 src/interactions/slashCommand.ts rename src/{models => interactions}/slashModule.ts (100%) rename src/{models/rest.ts => rest/manager.ts} (94%) create mode 100644 src/rest/mod.ts create mode 100644 src/rest/types.ts create mode 100644 src/types/constants.ts create mode 100644 src/types/mod.ts delete mode 100644 src/utils/index.ts diff --git a/deploy.ts b/deploy.ts index e5d149b..ed5ab84 100644 --- a/deploy.ts +++ b/deploy.ts @@ -2,7 +2,7 @@ import { SlashCommandsManager, SlashClient, SlashCommandHandlerCallback -} from './src/models/slashClient.ts' +} from './src/interactions/mod.ts' import { InteractionResponseType, InteractionType } from './src/types/slash.ts' export interface DeploySlashInitOptions { @@ -41,7 +41,7 @@ export function init(options: DeploySlashInitOptions): void { try { const d = await client.verifyFetchEvent({ respondWith: (...args: any[]) => evt.respondWith(...args), - request: evt.request, + request: evt.request }) if (d === false) { await evt.respondWith( @@ -72,11 +72,11 @@ export function handle( cmd: | string | { - name: string - parent?: string - group?: string - guild?: string - }, + name: string + parent?: string + group?: string + guild?: string + }, handler: SlashCommandHandlerCallback ): void { const handle = { @@ -85,9 +85,15 @@ export function handle( ...(typeof cmd === 'string' ? {} : cmd) } - if (typeof handle.name === 'string' && handle.name.includes(' ') && handle.parent === undefined && handle.group === undefined) { - const parts = handle.name.split(/ +/).filter(e => e !== '') - if (parts.length > 3 || parts.length < 1) throw new Error('Invalid command name') + if ( + typeof handle.name === 'string' && + handle.name.includes(' ') && + handle.parent === undefined && + handle.group === undefined + ) { + const parts = handle.name.split(/ +/).filter((e) => e !== '') + if (parts.length > 3 || parts.length < 1) + throw new Error('Invalid command name') const root = parts.shift() as string const group = parts.length === 2 ? parts.shift() : undefined const sub = parts.shift() @@ -103,4 +109,4 @@ export function handle( export { commands, client } export * from './src/types/slash.ts' export * from './src/structures/slash.ts' -export * from './src/models/slashClient.ts' +export * from './src/interactions/mod.ts' diff --git a/mod.ts b/mod.ts index 70faacb..4ebaf42 100644 --- a/mod.ts +++ b/mod.ts @@ -1,20 +1,18 @@ export { GatewayIntents } from './src/types/gateway.ts' export { Base } from './src/structures/base.ts' -export { Gateway } from './src/gateway/index.ts' -export type { GatewayTypedEvents } from './src/gateway/index.ts' -export type { ClientEvents } from './src/gateway/handlers/index.ts' -export * from './src/models/client.ts' -export * from './src/models/slashClient.ts' +export { Gateway } from './src/gateway/mod.ts' +export type { GatewayTypedEvents } from './src/gateway/mod.ts' +export type { ClientEvents } from './src/gateway/handlers/mod.ts' +export * from './src/client/mod.ts' +export * from './src/interactions/mod.ts' export { RESTManager, TokenType, HttpResponseCode, DiscordAPIError -} from './src/models/rest.ts' -export type { APIMap, DiscordAPIErrorPayload } from './src/models/rest.ts' -export type { RequestHeaders } from './src/models/rest.ts' -export type { RESTOptions } from './src/models/rest.ts' -export * from './src/models/cacheAdapter.ts' +} from './src/rest/mod.ts' +export * from './src/rest/mod.ts' +export * from './src/cache/adapter.ts' export { Command, CommandBuilder, @@ -22,16 +20,16 @@ export { CommandsManager, CategoriesManager, CommandsLoader -} from './src/models/command.ts' -export type { CommandContext, CommandOptions } from './src/models/command.ts' +} from './src/commands/command.ts' +export type { CommandContext, CommandOptions } from './src/commands/command.ts' export { Extension, ExtensionCommands, ExtensionsManager -} from './src/models/extensions.ts' -export { SlashModule } from './src/models/slashModule.ts' -export { CommandClient, command } from './src/models/commandClient.ts' -export type { CommandClientOptions } from './src/models/commandClient.ts' +} from './src/commands/extension.ts' +export { SlashModule } from './src/interactions/slashModule.ts' +export { CommandClient, command } from './src/commands/client.ts' +export type { CommandClientOptions } from './src/commands/client.ts' export { BaseManager } from './src/managers/base.ts' export { BaseChildManager } from './src/managers/baseChild.ts' export { ChannelsManager } from './src/managers/channels.ts' @@ -165,8 +163,8 @@ export type { UserPayload } from './src/types/user.ts' export { UserFlags } from './src/types/userFlags.ts' export type { VoiceStatePayload } from './src/types/voice.ts' export type { WebhookPayload } from './src/types/webhook.ts' -export * from './src/models/collectors.ts' +export * from './src/client/collectors.ts' export type { Dict } from './src/utils/dict.ts' -export * from './src/models/redisCache.ts' +export * from './src/cache/redis.ts' export { ColorUtil } from './src/utils/colorutil.ts' export type { Colors } from './src/utils/colorutil.ts' diff --git a/src/models/cacheAdapter.ts b/src/cache/adapter.ts similarity index 100% rename from src/models/cacheAdapter.ts rename to src/cache/adapter.ts diff --git a/src/models/redisCache.ts b/src/cache/redis.ts similarity index 91% rename from src/models/redisCache.ts rename to src/cache/redis.ts index 0820213..7ce9182 100644 --- a/src/models/redisCache.ts +++ b/src/cache/redis.ts @@ -1,5 +1,9 @@ -import { ICacheAdapter } from './cacheAdapter.ts' -import { connect, Redis, RedisConnectOptions } from 'https://deno.land/x/redis@v0.14.1/mod.ts' +import { ICacheAdapter } from './adapter.ts' +import { + connect, + Redis, + RedisConnectOptions +} from 'https://deno.land/x/redis@v0.14.1/mod.ts' /** Redis Cache Adapter for using Redis as a cache-provider. */ export class RedisCacheAdapter implements ICacheAdapter { @@ -102,4 +106,4 @@ export class RedisCacheAdapter implements ICacheAdapter { await this._checkReady() return (await this.redis?.del(cacheName)) !== 0 } -} \ No newline at end of file +} diff --git a/src/models/client.ts b/src/client/client.ts similarity index 93% rename from src/models/client.ts rename to src/client/client.ts index dc40e24..a8d3709 100644 --- a/src/models/client.ts +++ b/src/client/client.ts @@ -1,437 +1,437 @@ -/* 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' -import { RESTManager, RESTOptions, TokenType } from './rest.ts' -import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts' -import { UsersManager } from '../managers/users.ts' -import { GuildManager } from '../managers/guilds.ts' -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 { Extension } from './extensions.ts' -import { SlashClient } from './slashClient.ts' -import { Interaction } from '../structures/slash.ts' -import { ShardManager } from './shard.ts' -import { Application } from '../structures/application.ts' -import { Invite } from '../structures/invite.ts' -import { INVITE } from '../types/endpoint.ts' -import { ClientEvents } from '../gateway/handlers/index.ts' -import type { Collector } from './collectors.ts' -import { HarmonyEventEmitter } from '../utils/events.ts' -import { VoiceRegion } from '../types/voice.ts' -import { fetchAuto } from '../../deps.ts' -import { DMChannel } from '../structures/dmChannel.ts' -import { Template } from '../structures/template.ts' - -/** OS related properties sent with Gateway Identify */ -export interface ClientProperties { - os?: 'darwin' | 'windows' | 'linux' | 'custom_os' | string - browser?: 'harmony' | string - device?: 'harmony' | string -} - -/** Some Client Options to modify behaviour */ -export interface ClientOptions { - /** ID of the Client/Application to initialize Slash Client REST */ - id?: string - /** Token of the Bot/User */ - token?: string - /** Gateway Intents */ - intents?: GatewayIntents[] - /** Cache Adapter to use, defaults to Collections one */ - cache?: ICacheAdapter - /** Force New Session and don't use cached Session (by persistent caching) */ - forceNewSession?: boolean - /** Startup presence of client */ - presence?: ClientPresence | ClientActivity | ActivityGame - /** Force all requests to Canary API */ - canary?: boolean - /** Time till which Messages are to be cached, in MS. Default is 3600000 */ - messageCacheLifetime?: number - /** Time till which Message Reactions are to be cached, in MS. Default is 3600000 */ - reactionCacheLifetime?: number - /** Whether to fetch Uncached Message of Reaction or not? */ - fetchUncachedReactions?: boolean - /** Client Properties */ - clientProperties?: ClientProperties - /** Enable/Disable Slash Commands Integration (enabled by default) */ - enableSlash?: boolean - /** Disable taking token from env if not provided (token is taken from env if present by default) */ - disableEnvToken?: boolean - /** Override REST Options */ - restOptions?: RESTOptions - /** Whether to fetch Gateway info or not */ - fetchGatewayInfo?: boolean - /** ADVANCED: Shard ID to launch on */ - shard?: number - /** ADVACNED: Shard count. */ - shardCount?: number | 'auto' -} - -/** - * Discord Client. - */ -export class Client extends HarmonyEventEmitter { - /** REST Manager - used to make all requests */ - rest: RESTManager - /** User which Client logs in to, undefined until logs in */ - user?: User - /** WebSocket ping of Client */ - ping = 0 - /** Token of the Bot/User */ - token?: string - /** Cache Adapter */ - cache: ICacheAdapter = new DefaultCacheAdapter() - /** Gateway Intents */ - intents?: GatewayIntents[] - /** Whether to force new session or not */ - forceNewSession?: boolean - /** Time till messages to stay cached, in MS. */ - messageCacheLifetime: number = 3600000 - /** Time till messages to stay cached, in MS. */ - reactionCacheLifetime: number = 3600000 - /** Whether to fetch Uncached Message of Reaction or not? */ - fetchUncachedReactions: boolean = false - /** Client Properties */ - clientProperties: ClientProperties - /** Slash-Commands Management client */ - slash: SlashClient - /** Whether to fetch Gateway info or not */ - fetchGatewayInfo: boolean = true - - /** Users Manager, containing all Users cached */ - users: UsersManager = new UsersManager(this) - /** Guilds Manager, providing cache & API interface to Guilds */ - guilds: GuildManager = new GuildManager(this) - /** Channels Manager, providing cache interface to Channels */ - channels: ChannelsManager = new ChannelsManager(this) - /** Channels Manager, providing cache interface to Channels */ - emojis: EmojisManager = new EmojisManager(this) - - /** Last READY timestamp */ - upSince?: Date - - /** Client's presence. Startup one if set before connecting */ - presence: ClientPresence = new ClientPresence() - _decoratedEvents?: { - [name: string]: (...args: any[]) => void - } - - _decoratedSlash?: Array<{ - name: string - guild?: string - parent?: string - group?: string - handler: (interaction: Interaction) => any - }> - - _id?: string - - /** Shard on which this Client is */ - shard?: number - /** Shard Count */ - shardCount: number | 'auto' = 'auto' - /** Shard Manager of this Client if Sharded */ - shards: ShardManager - /** Collectors set */ - collectors: Set = new Set() - - /** Since when is Client online (ready). */ - get uptime(): number { - if (this.upSince === undefined) return 0 - else { - const dif = Date.now() - this.upSince.getTime() - if (dif < 0) return 0 - else return dif - } - } - - get gateway(): Gateway { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion - return this.shards.list.get('0') as Gateway - } - - applicationID?: string - applicationFlags?: number - - constructor(options: ClientOptions = {}) { - super() - this._id = options.id - this.token = options.token - this.intents = options.intents - this.shards = new ShardManager(this) - this.forceNewSession = options.forceNewSession - if (options.cache !== undefined) this.cache = options.cache - if (options.presence !== undefined) - this.presence = - options.presence instanceof ClientPresence - ? options.presence - : new ClientPresence(options.presence) - if (options.messageCacheLifetime !== undefined) - this.messageCacheLifetime = options.messageCacheLifetime - if (options.reactionCacheLifetime !== undefined) - this.reactionCacheLifetime = options.reactionCacheLifetime - if (options.fetchUncachedReactions === true) - this.fetchUncachedReactions = true - - if ( - this._decoratedEvents !== undefined && - Object.keys(this._decoratedEvents).length !== 0 - ) { - Object.entries(this._decoratedEvents).forEach((entry) => { - this.on(entry[0] as keyof ClientEvents, entry[1].bind(this)) - }) - this._decoratedEvents = undefined - } - - this.clientProperties = - options.clientProperties === undefined - ? { - os: Deno.build.os, - browser: 'harmony', - device: 'harmony' - } - : options.clientProperties - - if (options.shard !== undefined) this.shard = options.shard - if (options.shardCount !== undefined) this.shardCount = options.shardCount - - this.fetchGatewayInfo = options.fetchGatewayInfo ?? true - - if (this.token === undefined) { - try { - const token = Deno.env.get('DISCORD_TOKEN') - if (token !== undefined) { - this.token = token - this.debug('Info', 'Found token in ENV') - } - } catch (e) { } - } - - const restOptions: RESTOptions = { - token: () => this.token, - tokenType: TokenType.Bot, - canary: options.canary, - client: this - } - - if (options.restOptions !== undefined) - Object.assign(restOptions, options.restOptions) - this.rest = new RESTManager(restOptions) - - this.slash = new SlashClient({ - id: () => this.getEstimatedID(), - client: this, - enabled: options.enableSlash - }) - } - - /** - * Sets Cache Adapter - * - * Should NOT be set after bot is already logged in or using current cache. - * Please look into using `cache` option. - */ - setAdapter(adapter: ICacheAdapter): Client { - this.cache = adapter - return this - } - - /** Changes Presence of Client */ - setPresence(presence: ClientPresence | ClientActivity | ActivityGame): void { - if (presence instanceof ClientPresence) { - this.presence = presence - } else this.presence = new ClientPresence(presence) - this.gateway?.sendPresence(this.presence.create()) - } - - /** Emits debug event */ - debug(tag: string, msg: string): void { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.emit('debug', `[${tag}] ${msg}`) - } - - getEstimatedID(): string { - if (this.user !== undefined) return this.user.id - else if (this.token !== undefined) { - try { - return atob(this.token.split('.')[0]) - } catch (e) { - return this._id ?? 'unknown' - } - } else { - return this._id ?? 'unknown' - } - } - - /** Fetch Application of the Client */ - async fetchApplication(): Promise { - const app = await this.rest.api.oauth2.applications['@me'].get() - return new Application(this, app) - } - - /** Fetch an Invite */ - async fetchInvite(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 if not given in ClientOptions. - * @param intents Gateway intents in array. This is required if not given in ClientOptions. - */ - async connect(token?: string, intents?: GatewayIntents[]): Promise { - token ??= this.token - if (token === undefined) throw new Error('No Token Provided') - this.token = token - if (intents !== undefined && this.intents !== undefined) { - this.debug( - 'client', - 'Intents were set in both client and connect function. Using the one in the connect function...' - ) - } else if (intents === undefined && this.intents !== undefined) { - intents = this.intents - } else if (intents !== undefined && this.intents === undefined) { - this.intents = intents - } else throw new Error('No Gateway Intents were provided') - - this.rest.token = token - if (this.shard !== undefined) { - if (typeof this.shardCount === 'number') - this.shards.cachedShardCount = this.shardCount - await this.shards.launch(this.shard) - } else await this.shards.connect() - return this.waitFor('ready', () => true).then(() => this) - } - - /** Destroy the Gateway connection */ - async destroy(): Promise { - this.gateway.initialized = false - this.gateway.sequenceID = undefined - this.gateway.sessionID = undefined - await this.gateway.cache.delete('seq') - await this.gateway.cache.delete('session_id') - this.gateway.close() - this.user = undefined - this.upSince = undefined - return this - } - - /** Attempt to Close current Gateway connection and Resume */ - async reconnect(): Promise { - this.gateway.close() - this.gateway.initWebsocket() - return this.waitFor('ready', () => true).then(() => this) - } - - /** Add a new Collector */ - addCollector(collector: Collector): boolean { - if (this.collectors.has(collector)) return false - else { - this.collectors.add(collector) - return true - } - } - - /** Remove a Collector */ - removeCollector(collector: Collector): boolean { - if (!this.collectors.has(collector)) return false - else { - this.collectors.delete(collector) - return true - } - } - - async emit(event: keyof ClientEvents, ...args: any[]): Promise { - const collectors: Collector[] = [] - for (const collector of this.collectors.values()) { - if (collector.event === event) collectors.push(collector) - } - if (collectors.length !== 0) { - this.collectors.forEach((collector) => collector._fire(...args)) - } - // TODO(DjDeveloperr): Fix this ts-ignore - // eslint-disable-next-line @typescript-eslint/prefer-ts-expect-error - // @ts-ignore - return super.emit(event, ...args) - } - - /** Returns an array of voice region objects that can be used when creating servers. */ - async fetchVoiceRegions(): Promise { - return this.rest.api.voice.regions.get() - } - - /** Modify current (Client) User. */ - async editUser(data: { - username?: string - avatar?: string - }): Promise { - if (data.username === undefined && data.avatar === undefined) - throw new Error( - 'Either username or avatar or both must be specified to edit' - ) - - if (data.avatar?.startsWith('http') === true) { - data.avatar = await fetchAuto(data.avatar) - } - - await this.rest.api.users['@me'].patch({ - username: data.username, - avatar: data.avatar - }) - return this - } - - /** Change Username of the Client User */ - async setUsername(username: string): Promise { - return await this.editUser({ username }) - } - - /** Change Avatar of the Client User */ - async setAvatar(avatar: string): Promise { - return await this.editUser({ avatar }) - } - - /** Create a DM Channel with a User */ - async createDM(user: User | string): Promise { - const id = typeof user === 'object' ? user.id : user - const dmPayload = await this.rest.api.users['@me'].channels.post({ - recipient_id: id - }) - await this.channels.set(dmPayload.id, dmPayload) - return (this.channels.get(dmPayload.id) as unknown) as DMChannel - } - - /** Returns a template object for the given code. */ - async fetchTemplate(code: string): Promise