Merge branch 'main' into main

This commit is contained in:
Helloyunho 2020-12-29 15:30:41 +09:00 committed by GitHub
commit e1a8a8526a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 303 additions and 99 deletions

View file

@ -17,7 +17,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async (
const _updated: EmojiPayload[] = [] const _updated: EmojiPayload[] = []
for (const raw of d.emojis) { 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) const has = emojis.get(emojiID)
if (has === undefined) { if (has === undefined) {
await guild.emojis.set(emojiID, raw) await guild.emojis.set(emojiID, raw)
@ -27,7 +27,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async (
} }
for (const emoji of emojis.values()) { 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 find = _updated.find((e) => {
const eID = e.id !== null ? e.id : e.name const eID = e.id !== null ? e.id : e.name
return emojiID === eID return emojiID === eID
@ -36,7 +36,7 @@ export const guildEmojiUpdate: GatewayEventHandler = async (
await guild.emojis.delete(emojiID) await guild.emojis.delete(emojiID)
deleted.push(emoji) deleted.push(emoji)
} else { } 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 const before = (await guild.emojis.get(foundID)) as Emoji
await guild.emojis.set(foundID, find) await guild.emojis.set(foundID, find)
const after = (await guild.emojis.get(foundID)) as Emoji const after = (await guild.emojis.get(foundID)) as Emoji

View file

@ -99,238 +99,248 @@ export const gatewayHandlers: {
INTERACTION_CREATE: interactionCreate INTERACTION_CREATE: interactionCreate
} }
export interface EventTypes {
[name: string]: (...args: any[]) => void
}
export interface VoiceServerUpdateData { export interface VoiceServerUpdateData {
token: string token: string
endpoint: string endpoint: string
guild: Guild guild: Guild
} }
export interface ClientEvents extends EventTypes { export interface ClientEvents {
/** When Client has successfully connected to Discord */ /** When Client has successfully connected to Discord */
ready: () => void ready: []
/** When a successful reconnect has been made */ /** When a successful reconnect has been made */
reconnect: () => void reconnect: []
/** When a successful session resume has been done */ /** When a successful session resume has been done */
resumed: () => void resumed: []
/** /**
* When a new Channel is created * When a new Channel is created
* @param channel New Channel object * @param channel New Channel object
*/ */
channelCreate: (channel: EveryChannelTypes) => void channelCreate: [channel: EveryChannelTypes]
/** /**
* When a Channel was deleted * When a Channel was deleted
* @param channel Channel object which was deleted * @param channel Channel object which was deleted
*/ */
channelDelete: (channel: EveryChannelTypes) => void channelDelete: [channel: EveryChannelTypes]
/** /**
* Channel's Pinned Messages were updated * Channel's Pinned Messages were updated
* @param before Channel object before update * @param before Channel object before update
* @param after Channel object after update * @param after Channel object after update
*/ */
channelPinsUpdate: ( channelPinsUpdate: [
before: EveryTextChannelTypes, before: EveryTextChannelTypes,
after: EveryTextChannelTypes after: EveryTextChannelTypes
) => void ]
/** /**
* A Channel was updated * A Channel was updated
* @param before Channel object before update * @param before Channel object before update
* @param after Channel object after 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 * A User was banned from a Guild
* @param guild The Guild from which User was banned * @param guild The Guild from which User was banned
* @param user The User who 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 * A ban from a User in Guild was elevated
* @param guild Guild from which ban was removed * @param guild Guild from which ban was removed
* @param user User of which ban was elevated * @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. * Client has joined a new Guild.
* @param guild The new Guild object * @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 * A Guild in which Client was either deleted, or bot was kicked
* @param guild The Guild object * @param guild The Guild object
*/ */
guildDelete: (guild: Guild) => void guildDelete: [guild: Guild]
/** /**
* A new Emoji was added to Guild * A new Emoji was added to Guild
* @param guild Guild in which Emoji was added * @param guild Guild in which Emoji was added
* @param emoji The Emoji which 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 * An Emoji was deleted from Guild
* @param guild Guild from which Emoji was deleted * @param guild Guild from which Emoji was deleted
* @param emoji Emoji which was deleted * @param emoji Emoji which was deleted
*/ */
guildEmojiDelete: (guild: Guild, emoji: Emoji) => void guildEmojiDelete: [Guild, Emoji]
/** /**
* An Emoji in a Guild was updated * An Emoji in a Guild was updated
* @param guild Guild in which Emoji was updated * @param guild Guild in which Emoji was updated
* @param before Emoji object before update * @param before Emoji object before update
* @param after Emoji object after 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 * Guild's Integrations were updated
* @param guild The Guild object * @param guild The Guild object
*/ */
guildIntegrationsUpdate: (guild: Guild) => void guildIntegrationsUpdate: [guild: Guild]
/** /**
* A new Member has joined a Guild * A new Member has joined a Guild
* @param member The Member object * @param member The Member object
*/ */
guildMemberAdd: (member: Member) => void guildMemberAdd: [member: Member]
/** /**
* A Guild Member has either left or was kicked from Guild * A Guild Member has either left or was kicked from Guild
* @param member The Member object * @param member The Member object
*/ */
guildMemberRemove: (member: Member) => void guildMemberRemove: [member: Member]
/** /**
* A Guild Member was updated. Nickname changed, role assigned, etc. * A Guild Member was updated. Nickname changed, role assigned, etc.
* @param before Member object before update * @param before Member object before update
* @param after Member object after update * @param after Member object after update
*/ */
guildMemberUpdate: (before: Member, after: Member) => void guildMemberUpdate: [before: Member, after: Member]
/** /**
* A new Role was created in Guild * A new Role was created in Guild
* @param role The new Role object * @param role The new Role object
*/ */
guildRoleCreate: (role: Role) => void guildRoleCreate: [role: Role]
/** /**
* A Role was deleted from the Guild * A Role was deleted from the Guild
* @param role The Role object * @param role The Role object
*/ */
guildRoleDelete: (role: Role) => void guildRoleDelete: [role: Role]
/** /**
* A Role was updated in a Guild * A Role was updated in a Guild
* @param before Role object before update * @param before Role object before update
* @param after Role object after updated * @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. * A Guild has been updated. For example name, icon, etc.
* @param before Guild object before update * @param before Guild object before update
* @param after Guild object after update * @param after Guild object after update
*/ */
guildUpdate: (before: Guild, after: Guild) => void guildUpdate: [before: Guild, after: Guild]
/** /**
* A new Message was created (sent) * A new Message was created (sent)
* @param message The new Message object * @param message The new Message object
*/ */
messageCreate: (message: Message) => void messageCreate: [message: Message]
/** /**
* A Message was deleted. * A Message was deleted.
* @param message The Message object * @param message The Message object
*/ */
messageDelete: (message: Message) => void messageDelete: [message: Message]
/** /**
* Messages were bulk deleted in a Guild Text Channel * Messages were bulk deleted in a Guild Text Channel
* @param channel Channel in which Messages were deleted * @param channel Channel in which Messages were deleted
* @param messages Collection of Messages deleted * @param messages Collection of Messages deleted
* @param uncached Set of Messages deleted's IDs which were not cached * @param uncached Set of Messages deleted's IDs which were not cached
*/ */
messageDeleteBulk: ( messageDeleteBulk: [
channel: GuildTextChannel, channel: GuildTextChannel,
messages: Collection<string, Message>, messages: Collection<string, Message>,
uncached: Set<string> uncached: Set<string>
) => void ]
/** /**
* A Message was updated. For example content, embed, etc. * A Message was updated. For example content, embed, etc.
* @param before Message object before update * @param before Message object before update
* @param after Message object after update * @param after Message object after update
*/ */
messageUpdate: (before: Message, after: Message) => void messageUpdate: [before: Message, after: Message]
/** /**
* Reaction was added to a Message * Reaction was added to a Message
* @param reaction Reaction object * @param reaction Reaction object
* @param user User who added the reaction * @param user User who added the reaction
*/ */
messageReactionAdd: (reaction: MessageReaction, user: User) => void messageReactionAdd: [reaction: MessageReaction, user: User]
/** /**
* Reaction was removed fro a Message * Reaction was removed fro a Message
* @param reaction Reaction object * @param reaction Reaction object
* @param user User to who removed the reaction * @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 * All reactions were removed from a Message
* @param message Message from which reactions were removed * @param message Message from which reactions were removed
*/ */
messageReactionRemoveAll: (message: Message) => void messageReactionRemoveAll: [message: Message]
/** /**
* All reactions of a single Emoji were removed * All reactions of a single Emoji were removed
* @param message The Message object * @param message The Message object
* @param emoji The Emoji 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 * 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, user: User,
channel: TextChannel, channel: TextChannel,
at: Date, at: Date,
guildData?: TypingStartGuildData guild: TypingStartGuildData | undefined
) => void ]
/** /**
* A new Invite was created * A new Invite was created
* @param invite New Invite object * @param invite New Invite object
*/ */
inviteCreate: (invite: Invite) => void inviteCreate: [invite: Invite]
/** /**
* An Invite was deleted * An Invite was deleted
* @param invite Invite object * @param invite Invite object
*/ */
inviteDelete: (invite: Invite) => void inviteDelete: [invite: Invite]
/** /**
* A User was updated. For example username, avatar, etc. * A User was updated. For example username, avatar, etc.
* @param before The User object before update * @param before The User object before update
* @param after The User object after 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 * 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 * 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 * 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 * Voice State of a User has been updated
* @param before Voice State object before update * @param before Voice State object before update
* @param after Voice State object after 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 * A User's presence has been updated
* @param presence New Presence * @param presence New Presence
*/ */
presenceUpdate: (presence: Presence) => void presenceUpdate: [presence: Presence]
/** /**
* Webhooks of a Channel in a Guild has been updated * Webhooks of a Channel in a Guild has been updated
* @param guild Guild in which Webhooks were updated * @param guild Guild in which Webhooks were updated
* @param channel Channel of 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 * 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]
} }

View file

@ -29,7 +29,7 @@ export const messageReactionAdd: GatewayEventHandler = async (
} else return } 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) let reaction = await message.reactions.get(emojiID)
if (reaction === undefined) { if (reaction === undefined) {
await message.reactions.set(emojiID, { await message.reactions.set(emojiID, {

View file

@ -27,7 +27,7 @@ export const messageReactionRemove: GatewayEventHandler = async (
} else return } 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) const reaction = await message.reactions.get(emojiID)
if (reaction === undefined) return if (reaction === undefined) return

View file

@ -19,7 +19,7 @@ export const messageReactionRemoveEmoji: GatewayEventHandler = async (
} else return } 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) const reaction = await message.reactions.get(emojiID)
if (reaction === undefined) return if (reaction === undefined) return

View file

@ -37,10 +37,15 @@ export class BaseManager<T, T2> {
} }
/** Deletes a key from Cache */ /** Deletes a key from Cache */
async delete(key: string): Promise<boolean> { async _delete(key: string): Promise<boolean> {
return this.client.cache.delete(this.cacheName, key) return this.client.cache.delete(this.cacheName, key)
} }
/** Alias to _delete (cache) for compatibility purposes */
async delete(key: string): Promise<boolean> {
return await this._delete(key)
}
/** Gets an Array of values from Cache */ /** Gets an Array of values from Cache */
async array(): Promise<T2[]> { async array(): Promise<T2[]> {
let arr = await (this.client.cache.array(this.cacheName) as T[]) let arr = await (this.client.cache.array(this.cacheName) as T[])

View file

@ -36,6 +36,7 @@ export class GuildChannelsManager extends BaseChildManager<
else return undefined else return undefined
} }
/** Delete a Guild Channel */
async delete(id: string): Promise<boolean> { async delete(id: string): Promise<boolean> {
return this.client.rest.delete(CHANNEL(id)) return this.client.rest.delete(CHANNEL(id))
} }

View file

@ -88,7 +88,7 @@ export class GuildEmojisManager extends BaseChildManager<EmojiPayload, Emoji> {
const arr = await this.array() const arr = await this.array()
for (const elem of arr) { for (const elem of arr) {
const emojiID = elem.id !== null ? elem.id : elem.name const emojiID = elem.id !== null ? elem.id : elem.name
this.parent.delete(emojiID) this.parent.delete(emojiID as string)
} }
return true return true
} }

View file

@ -1,7 +1,7 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Guild } from '../structures/guild.ts' import { Guild } from '../structures/guild.ts'
import { Invite } from '../structures/invite.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 { InvitePayload } from '../types/invite.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
@ -19,14 +19,15 @@ export class InviteManager extends BaseManager<InvitePayload, Invite> {
return new Invite(this.client, raw) return new Invite(this.client, raw)
} }
async fetch(id: string): Promise<Invite | undefined> { /** Fetch an Invite */
async fetch(id: string): Promise<Invite> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(GUILD_INVITES(this.guild.id)) .get(INVITE(id))
.then(async (data) => { .then(async (data) => {
this.set(id, data as InvitePayload) this.set(id, data as InvitePayload)
const newInvite = await this.get(data.code) const newInvite = await this.get(data.code)
resolve(newInvite) resolve(newInvite as Invite)
}) })
.catch((e) => reject(e)) .catch((e) => reject(e))
}) })

View file

@ -60,7 +60,7 @@ export class MemberRolesManager extends BaseChildManager<RolePayload, Role> {
true true
) )
return res.status === 204 return res.response.status === 204
} }
async remove(role: string | Role): Promise<boolean> { async remove(role: string | Role): Promise<boolean> {
@ -76,6 +76,6 @@ export class MemberRolesManager extends BaseChildManager<RolePayload, Role> {
true true
) )
return res.status === 204 return res.response.status === 204
} }
} }

View file

@ -58,6 +58,7 @@ export class MembersManager extends BaseManager<MemberPayload, Member> {
) )
} }
/** Fetch a Guild Member */
async fetch(id: string): Promise<Member> { async fetch(id: string): Promise<Member> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest

View file

@ -4,6 +4,7 @@ import { Guild } from '../structures/guild.ts'
import { Message } from '../structures/message.ts' import { Message } from '../structures/message.ts'
import { MessageReaction } from '../structures/messageReaction.ts' import { MessageReaction } from '../structures/messageReaction.ts'
import { Reaction } from '../types/channel.ts' import { Reaction } from '../types/channel.ts'
import { MESSAGE_REACTION, MESSAGE_REACTIONS } from '../types/endpoint.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class MessageReactionsManager extends BaseManager< export class MessageReactionsManager extends BaseManager<
@ -23,7 +24,7 @@ export class MessageReactionsManager extends BaseManager<
const emojiID = raw.emoji.id !== null ? raw.emoji.id : raw.emoji.name 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) if (emoji === undefined) emoji = new Emoji(this.client, raw.emoji)
const reaction = new MessageReaction(this.client, raw, this.message, emoji) const reaction = new MessageReaction(this.client, raw, this.message, emoji)
@ -46,7 +47,7 @@ export class MessageReactionsManager extends BaseManager<
return await Promise.all( return await Promise.all(
arr.map(async (raw) => { arr.map(async (raw) => {
const emojiID = raw.emoji.id !== null ? raw.emoji.id : raw.emoji.name 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) if (emoji === undefined) emoji = new Emoji(this.client, raw.emoji)
return new MessageReaction(this.client, raw, this.message, emoji) return new MessageReaction(this.client, raw, this.message, emoji)
@ -58,4 +59,22 @@ export class MessageReactionsManager extends BaseManager<
await this.client.cache.deleteCache(`reaction_users:${this.message.id}`) await this.client.cache.deleteCache(`reaction_users:${this.message.id}`)
return this.client.cache.deleteCache(this.cacheName) return this.client.cache.deleteCache(this.cacheName)
} }
/** Remove all Reactions from the Message */
async removeAll(): Promise<void> {
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<MessageReactionsManager> {
const val = encodeURIComponent(
(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)
)
return this
}
} }

View file

@ -1,10 +1,19 @@
import { Permissions } from '../../mod.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Guild } from '../structures/guild.ts' import { Guild } from '../structures/guild.ts'
import { Role } from '../structures/role.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 { RolePayload } from '../types/role.ts'
import { BaseManager } from './base.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<RolePayload, Role> { export class RolesManager extends BaseManager<RolePayload, Role> {
guild: Guild guild: Guild
@ -13,13 +22,14 @@ export class RolesManager extends BaseManager<RolePayload, Role> {
this.guild = guild this.guild = guild
} }
/** Fetch a Guild Role (from API) */
async fetch(id: string): Promise<Role> { async fetch(id: string): Promise<Role> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(GUILD_ROLE(this.guild.id, id)) .get(GUILD_ROLE(this.guild.id, id))
.then((data) => { .then(async (data) => {
this.set(id, data as RolePayload) await this.set(id, data as RolePayload)
resolve(new Role(this.client, data as RolePayload)) resolve(((await this.get(id)) as unknown) as Role)
}) })
.catch((e) => reject(e)) .catch((e) => reject(e))
}) })
@ -31,4 +41,43 @@ export class RolesManager extends BaseManager<RolePayload, Role> {
} }
return true return true
} }
/** Create a Guild Role */
async create(data?: CreateGuildRoleOptions): Promise<Role> {
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<boolean> {
await this.client.rest.delete(
GUILD_ROLE(this.guild.id, typeof role === 'object' ? role.id : role)
)
return true
}
} }

View file

@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/method-signature-style */
import { User } from '../structures/user.ts' import { User } from '../structures/user.ts'
import { GatewayIntents } from '../types/gateway.ts' import { GatewayIntents } from '../types/gateway.ts'
import { Gateway } from '../gateway/index.ts' import { Gateway } from '../gateway/index.ts'
@ -10,13 +11,15 @@ import { ChannelsManager } from '../managers/channels.ts'
import { ClientPresence } from '../structures/presence.ts' import { ClientPresence } from '../structures/presence.ts'
import { EmojisManager } from '../managers/emojis.ts' import { EmojisManager } from '../managers/emojis.ts'
import { ActivityGame, ClientActivity } from '../types/presence.ts' import { ActivityGame, ClientActivity } from '../types/presence.ts'
import { ClientEvents } from '../gateway/handlers/index.ts'
import { Extension } from './extensions.ts' import { Extension } from './extensions.ts'
import { SlashClient } from './slashClient.ts' import { SlashClient } from './slashClient.ts'
import { Interaction } from '../structures/slash.ts' import { Interaction } from '../structures/slash.ts'
import { SlashModule } from './slashModule.ts' import { SlashModule } from './slashModule.ts'
import type { ShardManager } from './shard.ts' import type { ShardManager } from './shard.ts'
import { Application } from '../structures/application.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'
/** OS related properties sent with Gateway Identify */ /** OS related properties sent with Gateway Identify */
export interface ClientProperties { export interface ClientProperties {
@ -53,6 +56,32 @@ export interface ClientOptions {
enableSlash?: boolean enableSlash?: boolean
} }
export declare interface Client {
on<K extends keyof ClientEvents>(
event: K,
listener: (...args: ClientEvents[K]) => void
): this
on(event: string | symbol, listener: (...args: any[]) => void): this
once<K extends keyof ClientEvents>(
event: K,
listener: (...args: ClientEvents[K]) => void
): this
once(event: string | symbol, listener: (...args: any[]) => void): this
emit<K extends keyof ClientEvents>(
event: K,
...args: ClientEvents[K]
): boolean
emit(event: string | symbol, ...args: any[]): boolean
off<K extends keyof ClientEvents>(
event: K,
listener: (...args: ClientEvents[K]) => void
): this
off(event: string | symbol, listener: (...args: any[]) => void): this
}
/** /**
* Discord Client. * Discord Client.
*/ */
@ -93,7 +122,10 @@ export class Client extends EventEmitter {
canary: boolean = false canary: boolean = false
/** Client's presence. Startup one if set before connecting */ /** Client's presence. Startup one if set before connecting */
presence: ClientPresence = new ClientPresence() presence: ClientPresence = new ClientPresence()
_decoratedEvents?: { [name: string]: (...args: any[]) => any } _decoratedEvents?: {
[name: string]: (...args: any[]) => void
}
_decoratedSlash?: Array<{ _decoratedSlash?: Array<{
name: string name: string
guild?: string guild?: string
@ -105,18 +137,6 @@ export class Client extends EventEmitter {
_decoratedSlashModules?: SlashModule[] _decoratedSlashModules?: SlashModule[]
_id?: string _id?: string
public on = <K extends string>(event: K, listener: ClientEvents[K]): this =>
this._untypedOn(event, listener)
public emit = <K extends string>(
event: K,
...args: Parameters<ClientEvents[K]>
): boolean => this._untypedEmit(event, ...args)
private readonly _untypedOn = this.on
private readonly _untypedEmit = this.emit
/** Shard on which this Client is */ /** Shard on which this Client is */
shard: number = 0 shard: number = 0
/** Shard Manager of this Client if Sharded */ /** Shard Manager of this Client if Sharded */
@ -211,6 +231,18 @@ export class Client extends EventEmitter {
return new Application(this, app) return new Application(this, app)
} }
/** Fetch an Invite */
async fetchInvite(id: string): Promise<Invite> {
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. * This function is used for connecting to discord.
* @param token Your token. This is required. * @param token Your token. This is required.
@ -233,17 +265,43 @@ export class Client extends EventEmitter {
} else throw new Error('No Gateway Intents were provided') } else throw new Error('No Gateway Intents were provided')
this.gateway = new Gateway(this, token, intents) this.gateway = new Gateway(this, token, intents)
} }
async waitFor<K extends keyof ClientEvents>(
event: K,
checkFunction: (...args: ClientEvents[K]) => boolean,
timeout?: number
): Promise<ClientEvents[K] | []> {
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) { export function event(name?: keyof ClientEvents) {
return function (client: Client | Extension, prop: string) { return function (client: Client | Extension, prop: keyof ClientEvents) {
const listener = ((client as unknown) as { const listener = ((client as unknown) as {
[name: string]: (...args: any[]) => any [name in keyof ClientEvents]: (...args: ClientEvents[name]) => any
})[prop] })[prop]
if (typeof listener !== 'function') if (typeof listener !== 'function')
throw new Error('@event decorator requires a function') throw new Error('@event decorator requires a function')
if (client._decoratedEvents === undefined) client._decoratedEvents = {} if (client._decoratedEvents === undefined) client._decoratedEvents = {}
client._decoratedEvents[name === undefined ? prop : name] = listener const key = name === undefined ? prop : name
client._decoratedEvents[key] = listener
} }
} }

View file

@ -1,12 +1,14 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { EmojiPayload } from '../types/emoji.ts' import { EmojiPayload } from '../types/emoji.ts'
import { EMOJI } from '../types/endpoint.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
import { Guild } from './guild.ts' import { Guild } from './guild.ts'
import { Role } from './role.ts'
import { User } from './user.ts' import { User } from './user.ts'
export class Emoji extends Base { export class Emoji extends Base {
id: string | null id: string | null
name: string name: string | null
roles?: string[] roles?: string[]
user?: User user?: User
guild?: Guild guild?: Guild
@ -17,7 +19,7 @@ export class Emoji extends Base {
get getEmojiString(): string { get getEmojiString(): string {
if (this.id === null) { if (this.id === null) {
return this.name return this.name as string
} else { } else {
if (this.animated === false) { if (this.animated === false) {
return `<:${this.name}:${this.id}>` return `<:${this.name}:${this.id}>`
@ -41,6 +43,28 @@ export class Emoji extends Base {
this.available = data.available 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(data: ModifyGuildEmojiParams): Promise<Emoji> {
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
})
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<boolean> {
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
}
readFromData(data: EmojiPayload): void { readFromData(data: EmojiPayload): void {
this.id = data.id ?? this.id this.id = data.id ?? this.id
this.name = data.name ?? this.name this.name = data.name ?? this.name
@ -52,3 +76,11 @@ export class Emoji extends Base {
if (data.user !== undefined) this.user = new User(this.client, data.user) 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 | Role | Array<string | Role>;
}

View file

@ -12,14 +12,7 @@ export class Role extends Base {
permissions: Permissions permissions: Permissions
managed: boolean managed: boolean
mentionable: boolean mentionable: boolean
tags?: RoleTags
get mention(): string {
return `<@&${this.id}>`
}
toString(): string {
return this.mention
}
constructor(client: Client, data: RolePayload) { constructor(client: Client, data: RolePayload) {
super(client, data) super(client, data)
@ -31,6 +24,14 @@ export class Role extends Base {
this.permissions = new Permissions(data.permissions) this.permissions = new Permissions(data.permissions)
this.managed = data.managed this.managed = data.managed
this.mentionable = data.mentionable this.mentionable = data.mentionable
this.tags =
data.tags !== undefined
? {
botID: data.tags?.bot_id,
integrationID: data.tags?.integration_id,
premiumSubscriber: 'premium_subscriber' in (data.tags ?? {})
}
: undefined
} }
readFromData(data: RolePayload): void { readFromData(data: RolePayload): void {
@ -46,3 +47,12 @@ export class Role extends Base {
this.mentionable = data.mentionable ?? this.mentionable 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
}

View file

@ -114,6 +114,14 @@ client.on('messageCreate', async (msg: Message) => {
} }
} else if (msg.content === '!react') { } else if (msg.content === '!react') {
msg.addReaction('🤔') 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}`)
} }
}) })

View file

@ -2,7 +2,7 @@ import { UserPayload } from './user.ts'
export interface EmojiPayload { export interface EmojiPayload {
id: string | null id: string | null
name: string name: string | null
roles?: string[] roles?: string[]
user?: UserPayload user?: UserPayload
require_colons?: boolean require_colons?: boolean

View file

@ -7,4 +7,14 @@ export interface RolePayload {
permissions: string permissions: string
managed: boolean managed: boolean
mentionable: boolean mentionable: boolean
tags?: RoleTagsPayload
}
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
} }