format files and ready for v0.9.0

This commit is contained in:
Helloyunho 2020-12-02 21:29:52 +09:00
parent a80a68bf91
commit 5e5b4076ce
112 changed files with 4478 additions and 4282 deletions

View File

@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
deno: ["v1.x", "nightly"] deno: ['v1.x', 'nightly']
steps: steps:
- name: Setup repo - name: Setup repo

View File

@ -5,23 +5,22 @@ name: Lint Test
on: on:
push: push:
branches: [ main ] branches: [main]
pull_request: pull_request:
branches: [ main ] branches: [main]
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v2.1.2 uses: actions/setup-node@v2.1.2
- name: Setup ESLint - name: Setup ESLint
run: npm install run: npm install
- name: Test ESLint - name: Test ESLint
run: npx eslint src/ run: npx eslint src/

View File

@ -2,5 +2,7 @@
"tabWidth": 2, "tabWidth": 2,
"useTabs": false, "useTabs": false,
"semi": false, "semi": false,
"singleQuote": true "singleQuote": true,
"trailingComma": "none",
"arrowParens": "always"
} }

22
.vscode/settings.json vendored
View File

@ -1,11 +1,11 @@
{ {
"deno.enable": true, "deno.enable": true,
"deno.lint": false, "deno.lint": false,
"deno.unstable": false, "deno.unstable": false,
"deepscan.enable": true, "deepscan.enable": true,
"deno.import_intellisense_origins": { "deno.import_intellisense_origins": {
"https://deno.land": true "https://deno.land": true
}, },
"editor.tabSize": 2, "editor.tabSize": 2,
"editor.formatOnSave": true "editor.formatOnSave": true
} }

View File

@ -48,7 +48,7 @@ Here is a small example of how to use harmony,
import { import {
Client, Client,
Message, Message,
Intents, Intents
} from 'https://raw.githubusercontent.com/harmony-org/harmony/main/mod.ts' } from 'https://raw.githubusercontent.com/harmony-org/harmony/main/mod.ts'
const client = new Client() const client = new Client()
@ -78,11 +78,11 @@ import {
Command, Command,
CommandContext, CommandContext,
Message, Message,
Intents, Intents
} from 'https://raw.githubusercontent.com/harmony-org/harmony/main/mod.ts' } from 'https://raw.githubusercontent.com/harmony-org/harmony/main/mod.ts'
const client = new CommandClient({ const client = new CommandClient({
prefix: '!', prefix: '!'
}) })
// Listen for event when client is ready (Identified through gateway / Resumed) // Listen for event when client is ready (Identified through gateway / Resumed)

140
mod.ts
View File

@ -1,70 +1,70 @@
export * from './src/gateway/index.ts' export * from './src/gateway/index.ts'
export * from './src/models/client.ts' export * from './src/models/client.ts'
export * from './src/models/rest.ts' export * from './src/models/rest.ts'
export * from './src/models/cacheAdapter.ts' export * from './src/models/cacheAdapter.ts'
export * from './src/models/shard.ts' export * from './src/models/shard.ts'
export * from './src/models/command.ts' export * from './src/models/command.ts'
export * from './src/models/extensions.ts' export * from './src/models/extensions.ts'
export * from './src/models/commandClient.ts' export * from './src/models/commandClient.ts'
export * from './src/managers/base.ts' export * from './src/managers/base.ts'
export * from './src/managers/baseChild.ts' export * from './src/managers/baseChild.ts'
export * from './src/managers/channels.ts' export * from './src/managers/channels.ts'
export * from './src/managers/emojis.ts' export * from './src/managers/emojis.ts'
export * from './src/managers/gatewayCache.ts' export * from './src/managers/gatewayCache.ts'
export * from './src/managers/guildChannels.ts' export * from './src/managers/guildChannels.ts'
export * from './src/managers/guilds.ts' export * from './src/managers/guilds.ts'
export * from './src/managers/guildChannels.ts' export * from './src/managers/guildChannels.ts'
export * from './src/managers/guildEmojis.ts' export * from './src/managers/guildEmojis.ts'
export * from './src/managers/members.ts' export * from './src/managers/members.ts'
export * from './src/managers/messageReactions.ts' export * from './src/managers/messageReactions.ts'
export * from './src/managers/reactionUsers.ts' export * from './src/managers/reactionUsers.ts'
export * from './src/managers/messages.ts' export * from './src/managers/messages.ts'
export * from './src/managers/roles.ts' export * from './src/managers/roles.ts'
export * from './src/managers/users.ts' export * from './src/managers/users.ts'
export * from './src/structures/application.ts' export * from './src/structures/application.ts'
export * from './src/structures/base.ts' export * from './src/structures/base.ts'
export * from './src/structures/cdn.ts' export * from './src/structures/cdn.ts'
export * from './src/structures/channel.ts' export * from './src/structures/channel.ts'
export * from './src/structures/dmChannel.ts' export * from './src/structures/dmChannel.ts'
export * from './src/structures/embed.ts' export * from './src/structures/embed.ts'
export * from './src/structures/emoji.ts' export * from './src/structures/emoji.ts'
export * from './src/structures/groupChannel.ts' export * from './src/structures/groupChannel.ts'
export * from './src/structures/guild.ts' export * from './src/structures/guild.ts'
export * from './src/structures/guildCategoryChannel.ts' export * from './src/structures/guildCategoryChannel.ts'
export * from './src/structures/guildNewsChannel.ts' export * from './src/structures/guildNewsChannel.ts'
export * from './src/structures/guildVoiceChannel.ts' export * from './src/structures/guildVoiceChannel.ts'
export * from './src/structures/invite.ts' export * from './src/structures/invite.ts'
export * from './src/structures/member.ts' export * from './src/structures/member.ts'
export * from './src/structures/message.ts' export * from './src/structures/message.ts'
export * from './src/structures/messageMentions.ts' export * from './src/structures/messageMentions.ts'
export * from './src/structures/presence.ts' export * from './src/structures/presence.ts'
export * from './src/structures/role.ts' export * from './src/structures/role.ts'
export * from './src/structures/snowflake.ts' export * from './src/structures/snowflake.ts'
export * from './src/structures/textChannel.ts' export * from './src/structures/textChannel.ts'
export * from './src/structures/messageReaction.ts' export * from './src/structures/messageReaction.ts'
export * from './src/structures/user.ts' export * from './src/structures/user.ts'
export * from './src/structures/webhook.ts' export * from './src/structures/webhook.ts'
export * from './src/types/application.ts' export * from './src/types/application.ts'
export * from './src/types/cdn.ts' export * from './src/types/cdn.ts'
export * from './src/types/channel.ts' export * from './src/types/channel.ts'
export * from './src/types/emoji.ts' export * from './src/types/emoji.ts'
export * from './src/types/endpoint.ts' export * from './src/types/endpoint.ts'
export * from './src/types/gateway.ts' export * from './src/types/gateway.ts'
export * from './src/types/gatewayBot.ts' export * from './src/types/gatewayBot.ts'
export * from './src/types/gatewayResponse.ts' export * from './src/types/gatewayResponse.ts'
export * from './src/types/guild.ts' export * from './src/types/guild.ts'
export * from './src/types/invite.ts' export * from './src/types/invite.ts'
export * from './src/types/permissionFlags.ts' export * from './src/types/permissionFlags.ts'
export * from './src/types/presence.ts' export * from './src/types/presence.ts'
export * from './src/types/role.ts' export * from './src/types/role.ts'
export * from './src/types/template.ts' export * from './src/types/template.ts'
export * from './src/types/user.ts' export * from './src/types/user.ts'
export * from './src/types/voice.ts' export * from './src/types/voice.ts'
export * from './src/types/webhook.ts' export * from './src/types/webhook.ts'
export * from './src/utils/collection.ts' export * from './src/utils/collection.ts'
export * from './src/utils/intents.ts' export * from './src/utils/intents.ts'
export * from './src/utils/buildInfo.ts' export * from './src/utils/buildInfo.ts'
export * from './src/utils/permissions.ts' export * from './src/utils/permissions.ts'
export * from './src/utils/userFlags.ts' export * from './src/utils/userFlags.ts'
export * from './src/utils/bitfield.ts' export * from './src/utils/bitfield.ts'
export * from './src/utils/getChannelByType.ts' export * from './src/utils/getChannelByType.ts'

View File

@ -1,9 +1,9 @@
export const DISCORD_API_URL: string = 'https://discord.com/api' export const DISCORD_API_URL: string = 'https://discord.com/api'
export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg' export const DISCORD_GATEWAY_URL: string = 'wss://gateway.discord.gg'
export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com' export const DISCORD_CDN_URL: string = 'https://cdn.discordapp.com'
export const DISCORD_API_VERSION: number = 8 export const DISCORD_API_VERSION: number = 8
export const DISCORD_VOICE_VERSION: number = 4 export const DISCORD_VOICE_VERSION: number = 4

View File

@ -1,13 +1,13 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { ChannelPayload } from '../../types/channel.ts' import { ChannelPayload } from '../../types/channel.ts'
export const channelDelete: GatewayEventHandler = async ( export const channelDelete: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: ChannelPayload d: ChannelPayload
) => { ) => {
const channel = await gateway.client.channels.get(d.id) const channel = await gateway.client.channels.get(d.id)
if (channel !== undefined) { if (channel !== undefined) {
await gateway.client.channels.delete(d.id) await gateway.client.channels.delete(d.id)
gateway.client.emit('channelDelete', channel) gateway.client.emit('channelDelete', channel)
} }
} }

View File

@ -1,23 +1,23 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
import { ChannelPinsUpdatePayload } from '../../types/gateway.ts' import { ChannelPinsUpdatePayload } from '../../types/gateway.ts'
export const channelPinsUpdate: GatewayEventHandler = async ( export const channelPinsUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: ChannelPinsUpdatePayload d: ChannelPinsUpdatePayload
) => { ) => {
const after: const after:
| TextChannel | TextChannel
| undefined = await gateway.client.channels.get<TextChannel>(d.channel_id) | undefined = await gateway.client.channels.get<TextChannel>(d.channel_id)
if (after !== undefined) { if (after !== undefined) {
const before = after.refreshFromData({ const before = after.refreshFromData({
last_pin_timestamp: d.last_pin_timestamp, last_pin_timestamp: d.last_pin_timestamp
}) })
const raw = await gateway.client.channels._get(d.channel_id) const raw = await gateway.client.channels._get(d.channel_id)
await gateway.client.channels.set( await gateway.client.channels.set(
after.id, after.id,
Object.assign(raw, { last_pin_timestamp: d.last_pin_timestamp }) Object.assign(raw, { last_pin_timestamp: d.last_pin_timestamp })
) )
gateway.client.emit('channelPinsUpdate', before, after) gateway.client.emit('channelPinsUpdate', before, after)
} }
} }

View File

@ -1,22 +1,22 @@
import { Channel } from '../../structures/channel.ts' import { Channel } from '../../structures/channel.ts'
import { ChannelPayload } from '../../types/channel.ts' import { ChannelPayload } from '../../types/channel.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const channelUpdate: GatewayEventHandler = async ( export const channelUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: ChannelPayload d: ChannelPayload
) => { ) => {
const oldChannel = await gateway.client.channels.get(d.id) const oldChannel = await gateway.client.channels.get(d.id)
await gateway.client.channels.set(d.id, d) await gateway.client.channels.set(d.id, d)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const newChannel = (await gateway.client.channels.get(d.id)) as Channel const newChannel = (await gateway.client.channels.get(d.id)) as Channel
if (oldChannel !== undefined) { if (oldChannel !== undefined) {
// (DjDeveloperr): Already done by ChannelsManager. I'll recheck later // (DjDeveloperr): Already done by ChannelsManager. I'll recheck later
// if ('guild_id' in d) { // if ('guild_id' in d) {
// // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
// (newChannel as GuildChannel).guild = await gateway.client.guilds.get((d as GuildChannelPayload).guild_id) as Guild // (newChannel as GuildChannel).guild = await gateway.client.guilds.get((d as GuildChannelPayload).guild_id) as Guild
// } // }
gateway.client.emit('channelUpdate', oldChannel, newChannel) gateway.client.emit('channelUpdate', oldChannel, newChannel)
} else gateway.client.emit('channelUpdateUncached', newChannel) } else gateway.client.emit('channelUpdateUncached', newChannel)
} }

View File

@ -1,19 +1,19 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { User } from '../../structures/user.ts' import { User } from '../../structures/user.ts'
import { GuildBanAddPayload } from '../../types/gateway.ts' import { GuildBanAddPayload } from '../../types/gateway.ts'
export const guildBanAdd: GatewayEventHandler = async ( export const guildBanAdd: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildBanAddPayload d: GuildBanAddPayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
const user: User = const user: User =
(await gateway.client.users.get(d.user.id)) ?? (await gateway.client.users.get(d.user.id)) ??
new User(gateway.client, d.user) new User(gateway.client, d.user)
if (guild !== undefined) { if (guild !== undefined) {
// We don't have to delete member, already done with guildMemberRemove event // We don't have to delete member, already done with guildMemberRemove event
gateway.client.emit('guildBanAdd', guild, user) gateway.client.emit('guildBanAdd', guild, user)
} }
} }

View File

@ -1,18 +1,18 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { User } from '../../structures/user.ts' import { User } from '../../structures/user.ts'
import { GuildBanRemovePayload } from '../../types/gateway.ts' import { GuildBanRemovePayload } from '../../types/gateway.ts'
export const guildBanRemove: GatewayEventHandler = async ( export const guildBanRemove: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildBanRemovePayload d: GuildBanRemovePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
const user: User = const user: User =
(await gateway.client.users.get(d.user.id)) ?? (await gateway.client.users.get(d.user.id)) ??
new User(gateway.client, d.user) new User(gateway.client, d.user)
if (guild !== undefined) { if (guild !== undefined) {
gateway.client.emit('guildBanRemove', guild, user) gateway.client.emit('guildBanRemove', guild, user)
} }
} }

View File

@ -1,22 +1,22 @@
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildPayload } from '../../types/guild.ts' import { GuildPayload } from '../../types/guild.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const guildDelte: GatewayEventHandler = async ( export const guildDelte: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildPayload d: GuildPayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.id) const guild: Guild | undefined = await gateway.client.guilds.get(d.id)
if (guild !== undefined) { if (guild !== undefined) {
guild.refreshFromData(d) guild.refreshFromData(d)
await guild.members.flush() await guild.members.flush()
await guild.channels.flush() await guild.channels.flush()
await guild.roles.flush() await guild.roles.flush()
await guild.presences.flush() await guild.presences.flush()
await gateway.client.guilds.delete(d.id) await gateway.client.guilds.delete(d.id)
gateway.client.emit('guildDelete', guild) gateway.client.emit('guildDelete', guild)
} }
} }

View File

@ -1,53 +1,53 @@
import { Emoji } from '../../structures/emoji.ts' import { Emoji } from '../../structures/emoji.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { EmojiPayload } from '../../types/emoji.ts' import { EmojiPayload } from '../../types/emoji.ts'
import { GuildEmojiUpdatePayload } from '../../types/gateway.ts' import { GuildEmojiUpdatePayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const guildEmojiUpdate: GatewayEventHandler = async ( export const guildEmojiUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildEmojiUpdatePayload d: GuildEmojiUpdatePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
if (guild !== undefined) { if (guild !== undefined) {
const emojis = await guild.emojis.collection() const emojis = await guild.emojis.collection()
const deleted: Emoji[] = [] const deleted: Emoji[] = []
const added: Emoji[] = [] const added: Emoji[] = []
const updated: Array<{ before: Emoji; after: Emoji }> = [] const updated: Array<{ before: Emoji; after: Emoji }> = []
const _updated: EmojiPayload[] = [] const _updated: EmojiPayload[] = []
for (const raw of d.emojis) { for (const raw of d.emojis) {
const has = emojis.get(raw.id) const has = emojis.get(raw.id)
if (has === undefined) { if (has === undefined) {
await guild.emojis.set(raw.id, raw) await guild.emojis.set(raw.id, raw)
const emoji = (await guild.emojis.get(raw.id)) as Emoji const emoji = (await guild.emojis.get(raw.id)) as Emoji
added.push(emoji) added.push(emoji)
} else _updated.push(raw) } else _updated.push(raw)
} }
for (const emoji of emojis.values()) { for (const emoji of emojis.values()) {
const find = _updated.find((e) => emoji.id === e.id) const find = _updated.find((e) => emoji.id === e.id)
if (find === undefined) { if (find === undefined) {
await guild.emojis.delete(emoji.id) await guild.emojis.delete(emoji.id)
deleted.push(emoji) deleted.push(emoji)
} else { } else {
const before = (await guild.emojis.get(find.id)) as Emoji const before = (await guild.emojis.get(find.id)) as Emoji
await guild.emojis.set(find.id, find) await guild.emojis.set(find.id, find)
const after = (await guild.emojis.get(find.id)) as Emoji const after = (await guild.emojis.get(find.id)) as Emoji
updated.push({ before, after }) updated.push({ before, after })
} }
} }
for (const emoji of deleted) { for (const emoji of deleted) {
gateway.client.emit('guildEmojiDelete', guild, emoji) gateway.client.emit('guildEmojiDelete', guild, emoji)
} }
for (const emoji of added) { for (const emoji of added) {
gateway.client.emit('guildEmojiAdd', guild, emoji) gateway.client.emit('guildEmojiAdd', guild, emoji)
} }
for (const emoji of updated) { for (const emoji of updated) {
gateway.client.emit('guildEmojiUpdate', guild, emoji.before, emoji.after) gateway.client.emit('guildEmojiUpdate', guild, emoji.before, emoji.after)
} }
} }
} }

View File

@ -1,14 +1,14 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildIntegrationsUpdatePayload } from '../../types/gateway.ts' import { GuildIntegrationsUpdatePayload } from '../../types/gateway.ts'
export const guildIntegrationsUpdate: GatewayEventHandler = async ( export const guildIntegrationsUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildIntegrationsUpdatePayload d: GuildIntegrationsUpdatePayload
) => { ) => {
console.log(d) console.log(d)
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
if (guild === undefined) return if (guild === undefined) return
gateway.client.emit('guildIntegrationsUpdate', guild) gateway.client.emit('guildIntegrationsUpdate', guild)
} }

View File

@ -20,7 +20,7 @@ export const guildMemberUpdate: GatewayEventHandler = async (
nick: d.nick, nick: d.nick,
premium_since: d.premium_since, premium_since: d.premium_since,
deaf: member?.deaf ?? false, deaf: member?.deaf ?? false,
mute: member?.mute ?? false, mute: member?.mute ?? false
} }
await guild.members.set(d.user.id, newMemberPayload) await guild.members.set(d.user.id, newMemberPayload)
const newMember = await guild.members.get(d.user.id) const newMember = await guild.members.get(d.user.id)

View File

@ -1,37 +1,37 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildMemberChunkPayload } from '../../types/gateway.ts' import { GuildMemberChunkPayload } from '../../types/gateway.ts'
export const guildMembersChunk: GatewayEventHandler = async ( export const guildMembersChunk: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildMemberChunkPayload d: GuildMemberChunkPayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
// Weird case, shouldn't happen // Weird case, shouldn't happen
if (guild === undefined) return if (guild === undefined) return
for (const member of d.members) { for (const member of d.members) {
await guild.members.set(member.user.id, member) await guild.members.set(member.user.id, member)
} }
if (d.chunk_index === 0) await guild.presences.flush() if (d.chunk_index === 0) await guild.presences.flush()
if (d.presences !== undefined) { if (d.presences !== undefined) {
for (const pres of d.presences) { for (const pres of d.presences) {
await guild.presences.set(pres.user.id, pres) await guild.presences.set(pres.user.id, pres)
} }
} }
gateway.client.emit('guildMembersChunk', guild, { gateway.client.emit('guildMembersChunk', guild, {
members: d.members.map((m) => m.user.id), members: d.members.map((m) => m.user.id),
presences: presences:
d.presences === undefined ? undefined : d.presences.map((p) => p.user.id), d.presences === undefined ? undefined : d.presences.map((p) => p.user.id),
chunkIndex: d.chunk_index, chunkIndex: d.chunk_index,
chunkCount: d.chunk_count, chunkCount: d.chunk_count
}) })
// Guild is now completely chunked. Emit an event for that. // Guild is now completely chunked. Emit an event for that.
if (d.chunk_index >= d.chunk_count - 1) { if (d.chunk_index >= d.chunk_count - 1) {
gateway.client.emit('guildMembersChunked', guild, d.chunk_count) gateway.client.emit('guildMembersChunked', guild, d.chunk_count)
} }
} }

View File

@ -1,17 +1,17 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildRoleCreatePayload } from '../../types/gateway.ts' import { GuildRoleCreatePayload } from '../../types/gateway.ts'
import { Role } from '../../structures/role.ts' import { Role } from '../../structures/role.ts'
export const guildRoleCreate: GatewayEventHandler = async ( export const guildRoleCreate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildRoleCreatePayload d: GuildRoleCreatePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
// Weird case, shouldn't happen // Weird case, shouldn't happen
if (guild === undefined) return if (guild === undefined) return
await guild.roles.set(d.role.id, d.role) await guild.roles.set(d.role.id, d.role)
const role = (await guild.roles.get(d.role.id)) as Role const role = (await guild.roles.get(d.role.id)) as Role
gateway.client.emit('guildRoleCreate', role) gateway.client.emit('guildRoleCreate', role)
} }

View File

@ -1,18 +1,18 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildRoleDeletePayload } from '../../types/gateway.ts' import { GuildRoleDeletePayload } from '../../types/gateway.ts'
export const guildRoleDelete: GatewayEventHandler = async ( export const guildRoleDelete: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildRoleDeletePayload d: GuildRoleDeletePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
// Weird case, shouldn't happen // Weird case, shouldn't happen
if (guild === undefined) return if (guild === undefined) return
const role = await guild.roles.get(d.role_id) const role = await guild.roles.get(d.role_id)
// Shouldn't happen either // Shouldn't happen either
if (role === undefined) return if (role === undefined) return
gateway.client.emit('guildRoleDelete', role) gateway.client.emit('guildRoleDelete', role)
} }

View File

@ -1,23 +1,23 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildRoleUpdatePayload } from '../../types/gateway.ts' import { GuildRoleUpdatePayload } from '../../types/gateway.ts'
import { Role } from '../../structures/role.ts' import { Role } from '../../structures/role.ts'
export const guildRoleUpdate: GatewayEventHandler = async ( export const guildRoleUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildRoleUpdatePayload d: GuildRoleUpdatePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
// Weird case, shouldn't happen // Weird case, shouldn't happen
if (guild === undefined) return if (guild === undefined) return
const role = await guild.roles.get(d.role.id) const role = await guild.roles.get(d.role.id)
await guild.roles.set(d.role.id, d.role) await guild.roles.set(d.role.id, d.role)
const newRole = (await guild.roles.get(d.role.id)) as Role const newRole = (await guild.roles.get(d.role.id)) as Role
// Shouldn't happen either // Shouldn't happen either
if (role === undefined) if (role === undefined)
return gateway.client.emit('guildRoleUpdateUncached', newRole) return gateway.client.emit('guildRoleUpdateUncached', newRole)
gateway.client.emit('guildRoleUpdate', role, newRole) gateway.client.emit('guildRoleUpdate', role, newRole)
} }

View File

@ -1,14 +1,14 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { GuildPayload } from '../../types/guild.ts' import { GuildPayload } from '../../types/guild.ts'
export const guildUpdate: GatewayEventHandler = async ( export const guildUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: GuildPayload d: GuildPayload
) => { ) => {
const after: Guild | undefined = await gateway.client.guilds.get(d.id) const after: Guild | undefined = await gateway.client.guilds.get(d.id)
if (after === undefined) return if (after === undefined) return
const before = after.refreshFromData(d) const before = after.refreshFromData(d)
await gateway.client.guilds.set(d.id, d) await gateway.client.guilds.set(d.id, d)
gateway.client.emit('guildUpdate', before, after) gateway.client.emit('guildUpdate', before, after)
} }

View File

@ -1,156 +1,162 @@
import { GatewayEventHandler } from '../index.ts' import { GatewayEventHandler } from '../index.ts'
import { GatewayEvents, TypingStartGuildData } from '../../types/gateway.ts' import { GatewayEvents, TypingStartGuildData } from '../../types/gateway.ts'
import { channelCreate } from './channelCreate.ts' import { channelCreate } from './channelCreate.ts'
import { channelDelete } from './channelDelete.ts' import { channelDelete } from './channelDelete.ts'
import { channelUpdate } from './channelUpdate.ts' import { channelUpdate } from './channelUpdate.ts'
import { channelPinsUpdate } from './channelPinsUpdate.ts' import { channelPinsUpdate } from './channelPinsUpdate.ts'
import { guildCreate } from './guildCreate.ts' import { guildCreate } from './guildCreate.ts'
import { guildDelte as guildDelete } from './guildDelete.ts' import { guildDelte as guildDelete } from './guildDelete.ts'
import { guildUpdate } from './guildUpdate.ts' import { guildUpdate } from './guildUpdate.ts'
import { guildBanAdd } from './guildBanAdd.ts' import { guildBanAdd } from './guildBanAdd.ts'
import { ready } from './ready.ts' import { ready } from './ready.ts'
import { guildBanRemove } from './guildBanRemove.ts' import { guildBanRemove } from './guildBanRemove.ts'
import { messageCreate } from './messageCreate.ts' import { messageCreate } from './messageCreate.ts'
import { resume } from './resume.ts' import { resume } from './resume.ts'
import { reconnect } from './reconnect.ts' import { reconnect } from './reconnect.ts'
import { messageDelete } from './messageDelete.ts' import { messageDelete } from './messageDelete.ts'
import { messageUpdate } from './messageUpdate.ts' import { messageUpdate } from './messageUpdate.ts'
import { guildEmojiUpdate } from './guildEmojiUpdate.ts' import { guildEmojiUpdate } from './guildEmojiUpdate.ts'
import { guildMemberAdd } from './guildMemberAdd.ts' import { guildMemberAdd } from './guildMemberAdd.ts'
import { guildMemberRemove } from './guildMemberRemove.ts' import { guildMemberRemove } from './guildMemberRemove.ts'
import { guildMemberUpdate } from './guildMemberUpdate.ts' import { guildMemberUpdate } from './guildMemberUpdate.ts'
import { guildRoleCreate } from './guildRoleCreate.ts' import { guildRoleCreate } from './guildRoleCreate.ts'
import { guildRoleDelete } from './guildRoleDelete.ts' import { guildRoleDelete } from './guildRoleDelete.ts'
import { guildRoleUpdate } from './guildRoleUpdate.ts' import { guildRoleUpdate } from './guildRoleUpdate.ts'
import { guildIntegrationsUpdate } from './guildIntegrationsUpdate.ts' import { guildIntegrationsUpdate } from './guildIntegrationsUpdate.ts'
import { webhooksUpdate } from './webhooksUpdate.ts' import { webhooksUpdate } from './webhooksUpdate.ts'
import { messageDeleteBulk } from './messageDeleteBulk.ts' import { messageDeleteBulk } from './messageDeleteBulk.ts'
import { userUpdate } from './userUpdate.ts' import { userUpdate } from './userUpdate.ts'
import { typingStart } from './typingStart.ts' import { typingStart } from './typingStart.ts'
import { Channel } from '../../structures/channel.ts' import { GuildTextChannel } from '../../structures/textChannel.ts'
import { GuildTextChannel, TextChannel } from '../../structures/textChannel.ts' import { Guild } from '../../structures/guild.ts'
import { Guild } from '../../structures/guild.ts' import { User } from '../../structures/user.ts'
import { User } from '../../structures/user.ts' import { Emoji } from '../../structures/emoji.ts'
import { Emoji } from '../../structures/emoji.ts' import { Member } from '../../structures/member.ts'
import { Member } from '../../structures/member.ts' import { Role } from '../../structures/role.ts'
import { Role } from '../../structures/role.ts' import { Message } from '../../structures/message.ts'
import { Message } from '../../structures/message.ts' import { Collection } from '../../utils/collection.ts'
import { Collection } from '../../utils/collection.ts' import { voiceServerUpdate } from './voiceServerUpdate.ts'
import { voiceServerUpdate } from './voiceServerUpdate.ts' import { voiceStateUpdate } from './voiceStateUpdate.ts'
import { voiceStateUpdate } from './voiceStateUpdate.ts' import { VoiceState } from '../../structures/voiceState.ts'
import { VoiceState } from '../../structures/voiceState.ts' import { messageReactionAdd } from './messageReactionAdd.ts'
import { messageReactionAdd } from './messageReactionAdd.ts' import { messageReactionRemove } from './messageReactionRemove.ts'
import { messageReactionRemove } from './messageReactionRemove.ts' import { messageReactionRemoveAll } from './messageReactionRemoveAll.ts'
import { messageReactionRemoveAll } from './messageReactionRemoveAll.ts' import { messageReactionRemoveEmoji } from './messageReactionRemoveEmoji.ts'
import { messageReactionRemoveEmoji } from './messageReactionRemoveEmoji.ts' import { guildMembersChunk } from './guildMembersChunk.ts'
import { guildMembersChunk } from './guildMembersChunk.ts' import { presenceUpdate } from './presenceUpdate.ts'
import { presenceUpdate } from './presenceUpdate.ts' import { inviteCreate } from './inviteCreate.ts'
import { inviteCreate } from './inviteCreate.ts' import { inviteDelete } from './inviteDelete.ts'
import { inviteDelete } from './inviteDelete.ts' import { MessageReaction } from '../../structures/messageReaction.ts'
import { MessageReaction } from '../../structures/messageReaction.ts' import { Invite } from '../../structures/invite.ts'
import { Invite } from '../../structures/invite.ts' import { Presence } from '../../structures/presence.ts'
import { Presence } from '../../structures/presence.ts' import {
EveryChannelTypes,
export const gatewayHandlers: { EveryTextChannelTypes
[eventCode in GatewayEvents]: GatewayEventHandler | undefined } from '../../utils/getChannelByType.ts'
} = {
READY: ready, export const gatewayHandlers: {
RECONNECT: reconnect, [eventCode in GatewayEvents]: GatewayEventHandler | undefined
RESUMED: resume, } = {
CHANNEL_CREATE: channelCreate, READY: ready,
CHANNEL_DELETE: channelDelete, RECONNECT: reconnect,
CHANNEL_UPDATE: channelUpdate, RESUMED: resume,
CHANNEL_PINS_UPDATE: channelPinsUpdate, CHANNEL_CREATE: channelCreate,
GUILD_CREATE: guildCreate, CHANNEL_DELETE: channelDelete,
GUILD_DELETE: guildDelete, CHANNEL_UPDATE: channelUpdate,
GUILD_UPDATE: guildUpdate, CHANNEL_PINS_UPDATE: channelPinsUpdate,
GUILD_BAN_ADD: guildBanAdd, GUILD_CREATE: guildCreate,
GUILD_BAN_REMOVE: guildBanRemove, GUILD_DELETE: guildDelete,
GUILD_EMOJIS_UPDATE: guildEmojiUpdate, GUILD_UPDATE: guildUpdate,
GUILD_INTEGRATIONS_UPDATE: guildIntegrationsUpdate, GUILD_BAN_ADD: guildBanAdd,
GUILD_MEMBER_ADD: guildMemberAdd, GUILD_BAN_REMOVE: guildBanRemove,
GUILD_MEMBER_REMOVE: guildMemberRemove, GUILD_EMOJIS_UPDATE: guildEmojiUpdate,
GUILD_MEMBER_UPDATE: guildMemberUpdate, GUILD_INTEGRATIONS_UPDATE: guildIntegrationsUpdate,
GUILD_MEMBERS_CHUNK: guildMembersChunk, GUILD_MEMBER_ADD: guildMemberAdd,
GUILD_ROLE_CREATE: guildRoleCreate, GUILD_MEMBER_REMOVE: guildMemberRemove,
GUILD_ROLE_UPDATE: guildRoleUpdate, GUILD_MEMBER_UPDATE: guildMemberUpdate,
GUILD_ROLE_DELETE: guildRoleDelete, GUILD_MEMBERS_CHUNK: guildMembersChunk,
INVITE_CREATE: inviteCreate, GUILD_ROLE_CREATE: guildRoleCreate,
INVITE_DELETE: inviteDelete, GUILD_ROLE_UPDATE: guildRoleUpdate,
MESSAGE_CREATE: messageCreate, GUILD_ROLE_DELETE: guildRoleDelete,
MESSAGE_UPDATE: messageUpdate, INVITE_CREATE: inviteCreate,
MESSAGE_DELETE: messageDelete, INVITE_DELETE: inviteDelete,
MESSAGE_DELETE_BULK: messageDeleteBulk, MESSAGE_CREATE: messageCreate,
MESSAGE_REACTION_ADD: messageReactionAdd, MESSAGE_UPDATE: messageUpdate,
MESSAGE_REACTION_REMOVE: messageReactionRemove, MESSAGE_DELETE: messageDelete,
MESSAGE_REACTION_REMOVE_ALL: messageReactionRemoveAll, MESSAGE_DELETE_BULK: messageDeleteBulk,
MESSAGE_REACTION_REMOVE_EMOJI: messageReactionRemoveEmoji, MESSAGE_REACTION_ADD: messageReactionAdd,
PRESENCE_UPDATE: presenceUpdate, MESSAGE_REACTION_REMOVE: messageReactionRemove,
TYPING_START: typingStart, MESSAGE_REACTION_REMOVE_ALL: messageReactionRemoveAll,
USER_UPDATE: userUpdate, MESSAGE_REACTION_REMOVE_EMOJI: messageReactionRemoveEmoji,
VOICE_STATE_UPDATE: voiceStateUpdate, PRESENCE_UPDATE: presenceUpdate,
VOICE_SERVER_UPDATE: voiceServerUpdate, TYPING_START: typingStart,
WEBHOOKS_UPDATE: webhooksUpdate, USER_UPDATE: userUpdate,
} VOICE_STATE_UPDATE: voiceStateUpdate,
VOICE_SERVER_UPDATE: voiceServerUpdate,
export interface EventTypes { WEBHOOKS_UPDATE: webhooksUpdate
[name: string]: (...args: any[]) => void }
}
export interface EventTypes {
export interface VoiceServerUpdateData { [name: string]: (...args: any[]) => void
token: string }
endpoint: string
guild: Guild export interface VoiceServerUpdateData {
} token: string
endpoint: string
export interface ClientEvents extends EventTypes { guild: Guild
ready: () => void }
reconnect: () => void
resumed: () => void export interface ClientEvents extends EventTypes {
channelCreate: (channel: Channel) => void ready: () => void
channelDelete: (channel: Channel) => void reconnect: () => void
channelPinsUpdate: (before: TextChannel, after: TextChannel) => void resumed: () => void
channelUpdate: (before: Channel, after: Channel) => void channelCreate: (channel: EveryChannelTypes) => void
guildBanAdd: (guild: Guild, user: User) => void channelDelete: (channel: EveryChannelTypes) => void
guildBanRemove: (guild: Guild, user: User) => void channelPinsUpdate: (
guildCreate: (guild: Guild) => void before: EveryTextChannelTypes,
guildDelete: (guild: Guild) => void after: EveryTextChannelTypes
guildEmojiAdd: (guild: Guild, emoji: Emoji) => void ) => void
guildEmojiDelete: (guild: Guild, emoji: Emoji) => void channelUpdate: (before: EveryChannelTypes, after: EveryChannelTypes) => void
guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void guildBanAdd: (guild: Guild, user: User) => void
guildIntegrationsUpdate: (guild: Guild) => void guildBanRemove: (guild: Guild, user: User) => void
guildMemberAdd: (member: Member) => void guildCreate: (guild: Guild) => void
guildMemberRemove: (member: Member) => void guildDelete: (guild: Guild) => void
guildMemberUpdate: (before: Member, after: Member) => void guildEmojiAdd: (guild: Guild, emoji: Emoji) => void
guildRoleCreate: (role: Role) => void guildEmojiDelete: (guild: Guild, emoji: Emoji) => void
guildRoleDelete: (role: Role) => void guildEmojiUpdate: (guild: Guild, before: Emoji, after: Emoji) => void
guildRoleUpdate: (before: Role, after: Role) => void guildIntegrationsUpdate: (guild: Guild) => void
guildUpdate: (before: Guild, after: Guild) => void guildMemberAdd: (member: Member) => void
messageCreate: (message: Message) => void guildMemberRemove: (member: Member) => void
messageDelete: (message: Message) => void guildMemberUpdate: (before: Member, after: Member) => void
messageDeleteBulk: ( guildRoleCreate: (role: Role) => void
channel: GuildTextChannel, guildRoleDelete: (role: Role) => void
messages: Collection<string, Message>, guildRoleUpdate: (before: Role, after: Role) => void
uncached: Set<string> guildUpdate: (before: Guild, after: Guild) => void
) => void messageCreate: (message: Message) => void
messageUpdate: (before: Message, after: Message) => void messageDelete: (message: Message) => void
messageReactionAdd: (reaction: MessageReaction, user: User) => void messageDeleteBulk: (
messageReactionRemove: (reaction: MessageReaction, user: User) => void channel: GuildTextChannel,
messageReactionRemoveAll: (message: Message) => void messages: Collection<string, Message>,
messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void uncached: Set<string>
typingStart: ( ) => void
user: User, messageUpdate: (before: Message, after: Message) => void
channel: TextChannel, messageReactionAdd: (reaction: MessageReaction, user: User) => void
at: Date, messageReactionRemove: (reaction: MessageReaction, user: User) => void
guildData?: TypingStartGuildData messageReactionRemoveAll: (message: Message) => void
) => void messageReactionRemoveEmoji: (message: Message, emoji: Emoji) => void
inviteCreate: (invite: Invite) => void typingStart: (
inviteDelete: (invite: Invite) => void user: User,
userUpdate: (before: User, after: User) => void channel: EveryChannelTypes,
voiceServerUpdate: (data: VoiceServerUpdateData) => void at: Date,
voiceStateAdd: (state: VoiceState) => void guildData?: TypingStartGuildData
voiceStateRemove: (state: VoiceState) => void ) => void
voiceStateUpdate: (state: VoiceState, after: VoiceState) => void inviteCreate: (invite: Invite) => void
presenceUpdate: (presence: Presence) => void inviteDelete: (invite: Invite) => void
webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void userUpdate: (before: User, after: User) => void
} voiceServerUpdate: (data: VoiceServerUpdateData) => void
voiceStateAdd: (state: VoiceState) => void
voiceStateRemove: (state: VoiceState) => void
voiceStateUpdate: (state: VoiceState, after: VoiceState) => void
presenceUpdate: (presence: Presence) => void
webhooksUpdate: (guild: Guild, channel: GuildTextChannel) => void
}

View File

@ -1,7 +1,9 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { InviteCreatePayload } from '../../types/gateway.ts' import { InviteCreatePayload } from '../../types/gateway.ts'
import { ChannelPayload, GuildPayload, InvitePayload } from '../../../mod.ts' import { ChannelPayload } from '../../types/channel.ts'
import { GuildPayload } from '../../types/guild.ts'
import { InvitePayload } from '../../types/invite.ts'
import { Invite } from '../../structures/invite.ts' import { Invite } from '../../structures/invite.ts'
export const inviteCreate: GatewayEventHandler = async ( export const inviteCreate: GatewayEventHandler = async (
@ -32,7 +34,7 @@ export const inviteCreate: GatewayEventHandler = async (
channel: (cachedChannel as unknown) as ChannelPayload, channel: (cachedChannel as unknown) as ChannelPayload,
inviter: d.inviter, inviter: d.inviter,
target_user: d.target_user, target_user: d.target_user,
target_user_type: d.target_user_type, target_user_type: d.target_user_type
} }
await guild.invites.set(d.code, dataConverted) await guild.invites.set(d.code, dataConverted)

View File

@ -2,7 +2,7 @@ import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { InviteDeletePayload } from '../../types/gateway.ts' import { InviteDeletePayload } from '../../types/gateway.ts'
import { PartialInvitePayload } from '../../types/invite.ts' import { PartialInvitePayload } from '../../types/invite.ts'
import { Channel } from '../../../mod.ts' import { Channel } from '../../structures/channel.ts'
export const inviteDelete: GatewayEventHandler = async ( export const inviteDelete: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
@ -24,7 +24,7 @@ export const inviteDelete: GatewayEventHandler = async (
const uncachedInvite: PartialInvitePayload = { const uncachedInvite: PartialInvitePayload = {
guild: (cachedGuild as unknown) as Guild, guild: (cachedGuild as unknown) as Guild,
channel: (cachedChannel as unknown) as Channel, channel: (cachedChannel as unknown) as Channel,
code: d.code, code: d.code
} }
return gateway.client.emit('inviteDeleteUncached', uncachedInvite) return gateway.client.emit('inviteDeleteUncached', uncachedInvite)
} else { } else {

View File

@ -1,20 +1,20 @@
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
import { MessageDeletePayload } from '../../types/gateway.ts' import { MessageDeletePayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const messageDelete: GatewayEventHandler = async ( export const messageDelete: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageDeletePayload d: MessageDeletePayload
) => { ) => {
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id) let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
// Fetch the channel if not cached // Fetch the channel if not cached
if (channel === undefined) if (channel === undefined)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
channel = (await gateway.client.channels.fetch(d.channel_id)) as TextChannel channel = (await gateway.client.channels.fetch(d.channel_id)) as TextChannel
const message = await channel.messages.get(d.id) const message = await channel.messages.get(d.id)
if (message === undefined) if (message === undefined)
return gateway.client.emit('messageDeleteUncached', d) return gateway.client.emit('messageDeleteUncached', d)
await channel.messages.delete(d.id) await channel.messages.delete(d.id)
gateway.client.emit('messageDelete', message) gateway.client.emit('messageDelete', message)
} }

View File

@ -1,33 +1,33 @@
import { Message } from '../../structures/message.ts' import { Message } from '../../structures/message.ts'
import { GuildTextChannel } from '../../structures/textChannel.ts' import { GuildTextChannel } from '../../structures/textChannel.ts'
import { MessageDeleteBulkPayload } from '../../types/gateway.ts' import { MessageDeleteBulkPayload } from '../../types/gateway.ts'
import { Collection } from '../../utils/collection.ts' import { Collection } from '../../utils/collection.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const messageDeleteBulk: GatewayEventHandler = async ( export const messageDeleteBulk: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageDeleteBulkPayload d: MessageDeleteBulkPayload
) => { ) => {
let channel = await gateway.client.channels.get<GuildTextChannel>( let channel = await gateway.client.channels.get<GuildTextChannel>(
d.channel_id d.channel_id
) )
// Fetch the channel if not cached // Fetch the channel if not cached
if (channel === undefined) if (channel === undefined)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
channel = (await gateway.client.channels.fetch( channel = (await gateway.client.channels.fetch(
d.channel_id d.channel_id
)) as GuildTextChannel )) as GuildTextChannel
const messages = new Collection<string, Message>() const messages = new Collection<string, Message>()
const uncached = new Set<string>() const uncached = new Set<string>()
for (const id of d.ids) { for (const id of d.ids) {
const message = await channel.messages.get(id) const message = await channel.messages.get(id)
if (message === undefined) uncached.add(id) if (message === undefined) uncached.add(id)
else { else {
messages.set(id, message) messages.set(id, message)
await channel.messages.delete(id) await channel.messages.delete(id)
} }
} }
gateway.client.emit('messageDeleteBulk', channel, messages, uncached) gateway.client.emit('messageDeleteBulk', channel, messages, uncached)
} }

View File

@ -1,51 +1,51 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { MessageReactionAddPayload } from '../../types/gateway.ts' import { MessageReactionAddPayload } from '../../types/gateway.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
import { MessageReaction } from '../../structures/messageReaction.ts' import { MessageReaction } from '../../structures/messageReaction.ts'
import { UserPayload } from '../../types/user.ts' import { UserPayload } from '../../types/user.ts'
export const messageReactionAdd: GatewayEventHandler = async ( export const messageReactionAdd: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageReactionAddPayload d: MessageReactionAddPayload
) => { ) => {
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id) let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
if (channel === undefined) if (channel === undefined)
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id) channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
if (channel === undefined) return if (channel === undefined) return
let message = await channel.messages.get(d.message_id) let message = await channel.messages.get(d.message_id)
if (message === undefined) { if (message === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
message = await channel.messages.fetch(d.message_id) message = await channel.messages.fetch(d.message_id)
if (message === undefined) return if (message === undefined) return
} else return } else return
} }
let user = await gateway.client.users.get(d.user_id) let user = await gateway.client.users.get(d.user_id)
if (user === undefined) { if (user === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
user = await gateway.client.users.fetch(d.user_id) user = await gateway.client.users.fetch(d.user_id)
if (user === undefined) return if (user === undefined) return
} else return } else return
} }
let reaction = await message.reactions.get(d.emoji.id) let reaction = await message.reactions.get(d.emoji.id)
if (reaction === undefined) { if (reaction === undefined) {
await message.reactions.set(d.emoji.id, { await message.reactions.set(d.emoji.id, {
count: 1, count: 1,
emoji: d.emoji, emoji: d.emoji,
me: d.user_id === gateway.client.user?.id, me: d.user_id === gateway.client.user?.id
}) })
reaction = ((await message.reactions.get( reaction = ((await message.reactions.get(
d.emoji.id d.emoji.id
)) as unknown) as MessageReaction )) as unknown) as MessageReaction
} }
const rawUser = ((await gateway.client.users.get( const rawUser = ((await gateway.client.users.get(
d.user_id d.user_id
)) as unknown) as UserPayload )) as unknown) as UserPayload
reaction.users.set(rawUser.id, rawUser) reaction.users.set(rawUser.id, rawUser)
gateway.client.emit('messageReactionAdd', reaction, user) gateway.client.emit('messageReactionAdd', reaction, user)
} }

View File

@ -1,36 +1,36 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { MessageReactionRemovePayload } from '../../types/gateway.ts' import { MessageReactionRemovePayload } from '../../types/gateway.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
export const messageReactionRemove: GatewayEventHandler = async ( export const messageReactionRemove: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageReactionRemovePayload d: MessageReactionRemovePayload
) => { ) => {
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id) let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
if (channel === undefined) if (channel === undefined)
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id) channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
if (channel === undefined) return if (channel === undefined) return
let message = await channel.messages.get(d.message_id) let message = await channel.messages.get(d.message_id)
if (message === undefined) { if (message === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
message = await channel.messages.fetch(d.message_id) message = await channel.messages.fetch(d.message_id)
if (message === undefined) return if (message === undefined) return
} else return } else return
} }
let user = await gateway.client.users.get(d.user_id) let user = await gateway.client.users.get(d.user_id)
if (user === undefined) { if (user === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
user = await gateway.client.users.fetch(d.user_id) user = await gateway.client.users.fetch(d.user_id)
if (user === undefined) return if (user === undefined) return
} else return } else return
} }
const reaction = await message.reactions.get(d.emoji.id) const reaction = await message.reactions.get(d.emoji.id)
if (reaction === undefined) return if (reaction === undefined) return
reaction.users.delete(d.user_id) reaction.users.delete(d.user_id)
gateway.client.emit('messageReactionRemove', reaction, user) gateway.client.emit('messageReactionRemove', reaction, user)
} }

View File

@ -1,25 +1,25 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { MessageReactionRemoveAllPayload } from '../../types/gateway.ts' import { MessageReactionRemoveAllPayload } from '../../types/gateway.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
export const messageReactionRemoveAll: GatewayEventHandler = async ( export const messageReactionRemoveAll: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageReactionRemoveAllPayload d: MessageReactionRemoveAllPayload
) => { ) => {
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id) let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
if (channel === undefined) if (channel === undefined)
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id) channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
if (channel === undefined) return if (channel === undefined) return
let message = await channel.messages.get(d.message_id) let message = await channel.messages.get(d.message_id)
if (message === undefined) { if (message === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
message = await channel.messages.fetch(d.message_id) message = await channel.messages.fetch(d.message_id)
if (message === undefined) return if (message === undefined) return
} else return } else return
} }
await message.reactions.flush() await message.reactions.flush()
gateway.client.emit('messageReactionRemoveAll', message) gateway.client.emit('messageReactionRemoveAll', message)
} }

View File

@ -1,28 +1,28 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { MessageReactionRemoveEmojiPayload } from '../../types/gateway.ts' import { MessageReactionRemoveEmojiPayload } from '../../types/gateway.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
export const messageReactionRemoveEmoji: GatewayEventHandler = async ( export const messageReactionRemoveEmoji: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: MessageReactionRemoveEmojiPayload d: MessageReactionRemoveEmojiPayload
) => { ) => {
let channel = await gateway.client.channels.get<TextChannel>(d.channel_id) let channel = await gateway.client.channels.get<TextChannel>(d.channel_id)
if (channel === undefined) if (channel === undefined)
channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id) channel = await gateway.client.channels.fetch<TextChannel>(d.channel_id)
if (channel === undefined) return if (channel === undefined) return
let message = await channel.messages.get(d.message_id) let message = await channel.messages.get(d.message_id)
if (message === undefined) { if (message === undefined) {
if (gateway.client.fetchUncachedReactions === true) { if (gateway.client.fetchUncachedReactions === true) {
message = await channel.messages.fetch(d.message_id) message = await channel.messages.fetch(d.message_id)
if (message === undefined) return if (message === undefined) return
} else return } else return
} }
const reaction = await message.reactions.get(d.emoji.id) const reaction = await message.reactions.get(d.emoji.id)
if (reaction === undefined) return if (reaction === undefined) return
await reaction.users.flush() await reaction.users.flush()
gateway.client.emit('messageReactionRemoveEmoji', message, reaction.emoji) gateway.client.emit('messageReactionRemoveEmoji', message, reaction.emoji)
} }

View File

@ -1,16 +1,16 @@
import { PresenceUpdatePayload } from '../../types/gateway.ts' import { PresenceUpdatePayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const presenceUpdate: GatewayEventHandler = async ( export const presenceUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: PresenceUpdatePayload d: PresenceUpdatePayload
) => { ) => {
const guild = await gateway.client.guilds.get(d.guild_id) const guild = await gateway.client.guilds.get(d.guild_id)
if (guild === undefined) return if (guild === undefined) return
await guild.presences.set(d.user.id, d) await guild.presences.set(d.user.id, d)
const presence = await guild.presences.get(d.user.id) const presence = await guild.presences.get(d.user.id)
if (presence === undefined) return if (presence === undefined) return
gateway.client.emit('presenceUpdate', presence) gateway.client.emit('presenceUpdate', presence)
} }

View File

@ -1,8 +1,8 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const reconnect: GatewayEventHandler = async ( export const reconnect: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: any d: any
) => { ) => {
gateway.reconnect() gateway.reconnect()
} }

View File

@ -1,39 +1,39 @@
import { Member } from '../../structures/member.ts' import { Member } from '../../structures/member.ts'
import { TextChannel } from '../../structures/textChannel.ts' import { TextChannel } from '../../structures/textChannel.ts'
import { TypingStartPayload } from '../../types/gateway.ts' import { TypingStartPayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
// TODO: Do we need to add uncached events here? // TODO: Do we need to add uncached events here?
export const typingStart: GatewayEventHandler = async ( export const typingStart: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: TypingStartPayload d: TypingStartPayload
) => { ) => {
const user = await gateway.client.users.get(d.user_id) const user = await gateway.client.users.get(d.user_id)
if (user === undefined) return console.log('user not cached') if (user === undefined) return console.log('user not cached')
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const channel = (await gateway.client.channels.get( const channel = (await gateway.client.channels.get(
d.channel_id d.channel_id
)) as TextChannel )) as TextChannel
if (channel === undefined) return console.log(`channel not cached`) if (channel === undefined) return console.log(`channel not cached`)
const guild = const guild =
d.guild_id !== undefined d.guild_id !== undefined
? await gateway.client.guilds.get(d.guild_id) ? await gateway.client.guilds.get(d.guild_id)
: undefined : undefined
if (guild === undefined && d.guild_id !== undefined) if (guild === undefined && d.guild_id !== undefined)
return console.log('guild not cached') return console.log('guild not cached')
const member = const member =
d.member !== undefined && guild !== undefined d.member !== undefined && guild !== undefined
? new Member(gateway.client, d.member, user, guild) ? new Member(gateway.client, d.member, user, guild)
: undefined : undefined
gateway.client.emit( gateway.client.emit(
'typingStart', 'typingStart',
user, user,
channel, channel,
new Date(d.timestamp), new Date(d.timestamp),
guild !== undefined && member !== undefined ? { guild, member } : undefined guild !== undefined && member !== undefined ? { guild, member } : undefined
) )
} }

View File

@ -1,17 +1,17 @@
import { User } from '../../structures/user.ts' import { User } from '../../structures/user.ts'
import { UserPayload } from '../../types/user.ts' import { UserPayload } from '../../types/user.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const userUpdate: GatewayEventHandler = async ( export const userUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: UserPayload d: UserPayload
) => { ) => {
const oldUser: User | undefined = await gateway.client.users.get(d.id) const oldUser: User | undefined = await gateway.client.users.get(d.id)
await gateway.client.users.set(d.id, d) await gateway.client.users.set(d.id, d)
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
const newUser = (await gateway.client.users.get(d.id)) as User const newUser = (await gateway.client.users.get(d.id)) as User
if (oldUser !== undefined) { if (oldUser !== undefined) {
gateway.client.emit('userUpdate', oldUser, newUser) gateway.client.emit('userUpdate', oldUser, newUser)
} else gateway.client.emit('userUpdateUncached', newUser) } else gateway.client.emit('userUpdateUncached', newUser)
} }

View File

@ -1,14 +1,14 @@
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { VoiceServerUpdatePayload } from '../../types/gateway.ts' import { VoiceServerUpdatePayload } from '../../types/gateway.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const voiceServerUpdate: GatewayEventHandler = async ( export const voiceServerUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: VoiceServerUpdatePayload d: VoiceServerUpdatePayload
) => { ) => {
gateway.client.emit('voiceServerUpdate', { gateway.client.emit('voiceServerUpdate', {
token: d.token, token: d.token,
endpoint: d.endpoint, endpoint: d.endpoint,
guild: ((await gateway.client.guilds.get(d.guild_id)) as unknown) as Guild, guild: ((await gateway.client.guilds.get(d.guild_id)) as unknown) as Guild
}) })
} }

View File

@ -1,50 +1,50 @@
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { VoiceState } from '../../structures/voiceState.ts' import { VoiceState } from '../../structures/voiceState.ts'
import { MemberPayload } from '../../types/guild.ts' import { MemberPayload } from '../../types/guild.ts'
import { VoiceStatePayload } from '../../types/voice.ts' import { VoiceStatePayload } from '../../types/voice.ts'
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
export const voiceStateUpdate: GatewayEventHandler = async ( export const voiceStateUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: VoiceStatePayload d: VoiceStatePayload
) => { ) => {
// TODO(DjDeveloperr): Support self-bot here; they can be in DMs (Call) // TODO(DjDeveloperr): Support self-bot here; they can be in DMs (Call)
if (d.guild_id === undefined) return if (d.guild_id === undefined) return
const guild = ((await gateway.client.guilds.get( const guild = ((await gateway.client.guilds.get(
d.guild_id d.guild_id
)) as unknown) as Guild )) as unknown) as Guild
const voiceState = await guild.voiceStates.get(d.user_id) const voiceState = await guild.voiceStates.get(d.user_id)
if (d.channel_id === null) { if (d.channel_id === null) {
if (voiceState === undefined) { if (voiceState === undefined) {
await guild.members.set(d.user_id, (d.member as unknown) as MemberPayload) await guild.members.set(d.user_id, (d.member as unknown) as MemberPayload)
const member = ((await guild.members.get( const member = ((await guild.members.get(
d.user_id d.user_id
)) as unknown) as MemberPayload )) as unknown) as MemberPayload
return gateway.client.emit('voiceStateRemoveUncached', { guild, member }) return gateway.client.emit('voiceStateRemoveUncached', { guild, member })
} }
// No longer in the channel, so delete // No longer in the channel, so delete
await guild.voiceStates.delete(d.user_id) await guild.voiceStates.delete(d.user_id)
gateway.client.emit( gateway.client.emit(
'voiceStateRemove', 'voiceStateRemove',
(voiceState as unknown) as VoiceState (voiceState as unknown) as VoiceState
) )
return return
} }
await guild.voiceStates.set(d.user_id, d) await guild.voiceStates.set(d.user_id, d)
const newVoiceState = await guild.voiceStates.get(d.user_id) const newVoiceState = await guild.voiceStates.get(d.user_id)
if (voiceState === undefined) { if (voiceState === undefined) {
gateway.client.emit( gateway.client.emit(
'voiceStateAdd', 'voiceStateAdd',
(newVoiceState as unknown) as VoiceState (newVoiceState as unknown) as VoiceState
) )
} else { } else {
gateway.client.emit( gateway.client.emit(
'voiceStateUpdate', 'voiceStateUpdate',
voiceState, voiceState,
(newVoiceState as unknown) as VoiceState (newVoiceState as unknown) as VoiceState
) )
} }
} }

View File

@ -1,19 +1,19 @@
import { Gateway, GatewayEventHandler } from '../index.ts' import { Gateway, GatewayEventHandler } from '../index.ts'
import { Guild } from '../../structures/guild.ts' import { Guild } from '../../structures/guild.ts'
import { WebhooksUpdatePayload } from '../../types/gateway.ts' import { WebhooksUpdatePayload } from '../../types/gateway.ts'
import { GuildTextChannel } from '../../structures/textChannel.ts' import { GuildTextChannel } from '../../structures/textChannel.ts'
export const webhooksUpdate: GatewayEventHandler = async ( export const webhooksUpdate: GatewayEventHandler = async (
gateway: Gateway, gateway: Gateway,
d: WebhooksUpdatePayload d: WebhooksUpdatePayload
) => { ) => {
const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id) const guild: Guild | undefined = await gateway.client.guilds.get(d.guild_id)
if (guild === undefined) return if (guild === undefined) return
const channel: GuildTextChannel | undefined = (await guild.channels.get( const channel: GuildTextChannel | undefined = (await guild.channels.get(
d.channel_id d.channel_id
)) as GuildTextChannel )) as GuildTextChannel
if (channel === undefined) if (channel === undefined)
gateway.client.emit('webhooksUpdateUncached', guild, d.channel_id) gateway.client.emit('webhooksUpdateUncached', guild, d.channel_id)
else gateway.client.emit('webhooksUpdate', guild, channel) else gateway.client.emit('webhooksUpdate', guild, channel)
} }

View File

@ -2,7 +2,7 @@ import { unzlib } from 'https://deno.land/x/denoflate@1.1/mod.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { import {
DISCORD_GATEWAY_URL, DISCORD_GATEWAY_URL,
DISCORD_API_VERSION, DISCORD_API_VERSION
} from '../consts/urlsAndVersions.ts' } from '../consts/urlsAndVersions.ts'
import { GatewayResponse } from '../types/gatewayResponse.ts' import { GatewayResponse } from '../types/gatewayResponse.ts'
import { import {
@ -10,7 +10,7 @@ import {
GatewayIntents, GatewayIntents,
GatewayCloseCodes, GatewayCloseCodes,
IdentityPayload, IdentityPayload,
StatusUpdatePayload, StatusUpdatePayload
} from '../types/gateway.ts' } from '../types/gateway.ts'
import { gatewayHandlers } from './handlers/index.ts' import { gatewayHandlers } from './handlers/index.ts'
import { GATEWAY_BOT } from '../types/endpoint.ts' import { GATEWAY_BOT } from '../types/endpoint.ts'
@ -230,7 +230,7 @@ class Gateway {
properties: { properties: {
$os: Deno.build.os, $os: Deno.build.os,
$browser: 'harmony', $browser: 'harmony',
$device: 'harmony', $device: 'harmony'
}, },
compress: true, compress: true,
shard: [0, 1], // TODO: Make sharding possible shard: [0, 1], // TODO: Make sharding possible
@ -238,7 +238,7 @@ class Gateway {
(previous, current) => previous | current, (previous, current) => previous | current,
0 0
), ),
presence: this.client.presence.create(), presence: this.client.presence.create()
} }
if (this.client.bot === false) { if (this.client.bot === false) {
@ -250,13 +250,13 @@ class Gateway {
$browser: 'Firefox', $browser: 'Firefox',
$device: '', $device: '',
$referrer: '', $referrer: '',
$referring_domain: '', $referring_domain: ''
} }
} }
this.send({ this.send({
op: GatewayOpcodes.IDENTIFY, op: GatewayOpcodes.IDENTIFY,
d: payload, d: payload
}) })
} }
@ -272,8 +272,8 @@ class Gateway {
d: { d: {
token: this.token, token: this.token,
session_id: this.sessionID, session_id: this.sessionID,
seq: this.sequenceID ?? null, seq: this.sequenceID ?? null
}, }
} }
this.send(resumePayload) this.send(resumePayload)
} }
@ -292,8 +292,8 @@ class Gateway {
limit: options.limit, limit: options.limit,
presences: options.presences, presences: options.presences,
user_ids: options.users, user_ids: options.users,
nonce, nonce
}, }
}) })
return nonce return nonce
} }
@ -334,7 +334,7 @@ class Gateway {
op: data.op, op: data.op,
d: data.d, d: data.d,
s: typeof data.s === 'number' ? data.s : null, s: typeof data.s === 'number' ? data.s : null,
t: data.t === undefined ? null : data.t, t: data.t === undefined ? null : data.t
}) })
) )
return true return true
@ -343,14 +343,14 @@ class Gateway {
sendPresence(data: StatusUpdatePayload): void { sendPresence(data: StatusUpdatePayload): void {
this.send({ this.send({
op: GatewayOpcodes.PRESENCE_UPDATE, op: GatewayOpcodes.PRESENCE_UPDATE,
d: data, d: data
}) })
} }
sendHeartbeat(): void { sendHeartbeat(): void {
const payload = { const payload = {
op: GatewayOpcodes.HEARTBEAT, op: GatewayOpcodes.HEARTBEAT,
d: this.sequenceID ?? null, d: this.sequenceID ?? null
} }
this.send(payload) this.send(payload)

View File

@ -8,37 +8,37 @@ export class BaseManager<T, T2> {
/** Which data type does this cache have */ /** Which data type does this cache have */
DataType: any DataType: any
constructor (client: Client, cacheName: string, DataType: any) { constructor(client: Client, cacheName: string, DataType: any) {
this.client = client this.client = client
this.cacheName = cacheName this.cacheName = cacheName
this.DataType = DataType this.DataType = DataType
} }
async _get (key: string): Promise<T | undefined> { async _get(key: string): Promise<T | undefined> {
return this.client.cache.get(this.cacheName, key) return this.client.cache.get(this.cacheName, key)
} }
async get (key: string): Promise<T2 | undefined> { async get(key: string): Promise<T2 | undefined> {
const raw = await this._get(key) const raw = await this._get(key)
if (raw === undefined) return if (raw === undefined) return
return new this.DataType(this.client, raw) return new this.DataType(this.client, raw)
} }
async set (key: string, value: T): Promise<any> { async set(key: string, value: T): Promise<any> {
return this.client.cache.set(this.cacheName, key, value) return this.client.cache.set(this.cacheName, key, value)
} }
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)
} }
async array (): Promise<undefined | T2[]> { async array(): Promise<undefined | T2[]> {
let arr = await (this.client.cache.array(this.cacheName) as T[]) let arr = await (this.client.cache.array(this.cacheName) as T[])
if (arr === undefined) arr = [] if (arr === undefined) arr = []
return arr.map(e => new this.DataType(this.client, e)) as any return arr.map((e) => new this.DataType(this.client, e)) as any
} }
async collection (): Promise<Collection<string, T2>> { async collection(): Promise<Collection<string, T2>> {
const arr = await this.array() const arr = await this.array()
if (arr === undefined) return new Collection() if (arr === undefined) return new Collection()
const collection = new Collection() const collection = new Collection()
@ -49,7 +49,7 @@ export class BaseManager<T, T2> {
return collection return collection
} }
flush (): any { flush(): any {
return this.client.cache.deleteCache(this.cacheName) return this.client.cache.deleteCache(this.cacheName)
} }
} }

View File

@ -28,7 +28,7 @@ export class BaseChildManager<T, T2> {
} }
async collection(): Promise<Collection<string, T2>> { async collection(): Promise<Collection<string, T2>> {
const arr = await this.array() as undefined | T2[] const arr = (await this.array()) as undefined | T2[]
if (arr === undefined) return new Collection() if (arr === undefined) return new Collection()
const collection = new Collection() const collection = new Collection()
for (const elem of arr) { for (const elem of arr) {
@ -37,4 +37,4 @@ export class BaseChildManager<T, T2> {
} }
return collection return collection
} }
} }

View File

@ -6,12 +6,12 @@ import getChannelByType from '../utils/getChannelByType.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class ChannelsManager extends BaseManager<ChannelPayload, Channel> { export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
constructor (client: Client) { constructor(client: Client) {
super(client, 'channels', Channel) super(client, 'channels', Channel)
} }
// Override get method as Generic // Override get method as Generic
async get<T = Channel> (key: string): Promise<T | undefined> { async get<T = Channel>(key: string): Promise<T | undefined> {
const data = await this._get(key) const data = await this._get(key)
if (data === undefined) return if (data === undefined) return
let guild let guild
@ -25,7 +25,7 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
return res as any return res as any
} }
async array (): Promise<undefined | Channel[]> { async array(): Promise<undefined | Channel[]> {
const arr = await (this.client.cache.array( const arr = await (this.client.cache.array(
this.cacheName this.cacheName
) as ChannelPayload[]) ) as ChannelPayload[])
@ -43,19 +43,25 @@ export class ChannelsManager extends BaseManager<ChannelPayload, Channel> {
return result return result
} }
async fetch<T = Channel> (id: string): Promise<T> { async fetch<T = Channel>(id: string): Promise<T> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(CHANNEL(id)) .get(CHANNEL(id))
.then(async data => { .then(async (data) => {
this.set(id, data as ChannelPayload) this.set(id, data as ChannelPayload)
let guild let guild
if (data.guild_id !== undefined) { if (data.guild_id !== undefined) {
guild = await this.client.guilds.get(data.guild_id) guild = await this.client.guilds.get(data.guild_id)
} }
resolve((getChannelByType(this.client, data as ChannelPayload, guild) as unknown) as T) resolve(
(getChannelByType(
this.client,
data as ChannelPayload,
guild
) as unknown) as T
)
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }
} }

View File

@ -5,12 +5,11 @@ import { GUILD_EMOJI } from '../types/endpoint.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class EmojisManager extends BaseManager<EmojiPayload, Emoji> { export class EmojisManager extends BaseManager<EmojiPayload, Emoji> {
constructor(client: Client) {
constructor (client: Client) {
super(client, `emojis`, Emoji) super(client, `emojis`, Emoji)
} }
async get (key: string): Promise<Emoji | undefined> { async get(key: string): Promise<Emoji | undefined> {
const raw = await this._get(key) const raw = await this._get(key)
if (raw === undefined) return if (raw === undefined) return
const emoji = new this.DataType(this.client, raw) const emoji = new this.DataType(this.client, raw)
@ -21,15 +20,15 @@ export class EmojisManager extends BaseManager<EmojiPayload, Emoji> {
return emoji return emoji
} }
async fetch (guildID: string, id: string): Promise<Emoji> { async fetch(guildID: string, id: string): Promise<Emoji> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(GUILD_EMOJI(guildID, id)) .get(GUILD_EMOJI(guildID, id))
.then(async data => { .then(async (data) => {
await this.set(id, data as EmojiPayload) await this.set(id, data as EmojiPayload)
resolve(new Emoji(this.client, data as EmojiPayload)) resolve(new Emoji(this.client, data as EmojiPayload))
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }
} }

View File

@ -4,22 +4,22 @@ export class GatewayCache {
client: Client client: Client
cacheName: string = 'discord_gateway_cache' cacheName: string = 'discord_gateway_cache'
constructor (client: Client, cacheName?: string) { constructor(client: Client, cacheName?: string) {
this.client = client this.client = client
if (cacheName !== undefined) this.cacheName = cacheName if (cacheName !== undefined) this.cacheName = cacheName
} }
async get (key: string): Promise<undefined | any> { async get(key: string): Promise<undefined | any> {
const result = await this.client.cache.get(this.cacheName, key) const result = await this.client.cache.get(this.cacheName, key)
return result return result
} }
async set (key: string, value: any): Promise<any> { async set(key: string, value: any): Promise<any> {
const result = await this.client.cache.set(this.cacheName, key, value) const result = await this.client.cache.set(this.cacheName, key, value)
return result return result
} }
async delete (key: string): Promise<boolean> { async delete(key: string): Promise<boolean> {
const result = await this.client.cache.delete(this.cacheName, key) const result = await this.client.cache.delete(this.cacheName, key)
return result return result
} }

View File

@ -25,29 +25,29 @@ export class GuildChannelsManager extends BaseChildManager<
> { > {
guild: Guild guild: Guild
constructor (client: Client, parent: ChannelsManager, guild: Guild) { constructor(client: Client, parent: ChannelsManager, guild: Guild) {
super(client, parent as any) super(client, parent as any)
this.guild = guild this.guild = guild
} }
async get (id: string): Promise<GuildChannel | undefined> { async get(id: string): Promise<GuildChannel | undefined> {
const res = await this.parent.get(id) const res = await this.parent.get(id)
if (res !== undefined && res.guild.id === this.guild.id) return res if (res !== undefined && res.guild.id === this.guild.id) return res
else return undefined else return undefined
} }
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))
} }
async array (): Promise<GuildChannel[]> { async array(): Promise<GuildChannel[]> {
const arr = (await this.parent.array()) as Channel[] const arr = (await this.parent.array()) as Channel[]
return arr.filter( return arr.filter(
(c: any) => c.guild !== undefined && c.guild.id === this.guild.id (c: any) => c.guild !== undefined && c.guild.id === this.guild.id
) as any ) as any
} }
async flush (): Promise<boolean> { async flush(): Promise<boolean> {
const arr = await this.array() const arr = await this.array()
for (const elem of arr) { for (const elem of arr) {
this.parent.delete(elem.id) this.parent.delete(elem.id)

View File

@ -8,10 +8,7 @@ import { BaseChildManager } from './baseChild.ts'
import { EmojisManager } from './emojis.ts' import { EmojisManager } from './emojis.ts'
import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts' import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts'
export class GuildEmojisManager extends BaseChildManager< export class GuildEmojisManager extends BaseChildManager<EmojiPayload, Emoji> {
EmojiPayload,
Emoji
> {
guild: Guild guild: Guild
constructor(client: Client, parent: EmojisManager, guild: Guild) { constructor(client: Client, parent: EmojisManager, guild: Guild) {
@ -33,28 +30,34 @@ export class GuildEmojisManager extends BaseChildManager<
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(GUILD_EMOJI(this.guild.id, id)) .get(GUILD_EMOJI(this.guild.id, id))
.then(async data => { .then(async (data) => {
const emoji = new Emoji(this.client, data as EmojiPayload) const emoji = new Emoji(this.client, data as EmojiPayload)
data.guild_id = this.guild.id data.guild_id = this.guild.id
await this.set(id, data as EmojiPayload) await this.set(id, data as EmojiPayload)
emoji.guild = this.guild emoji.guild = this.guild
resolve(emoji) resolve(emoji)
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }
async create(name: string, url: string, roles?: Role[] | string[] | string): Promise<Emoji | undefined> { async create(
name: string,
url: string,
roles?: Role[] | string[] | string
): Promise<Emoji | undefined> {
let data = url let data = url
if (!data.startsWith("data:")) { if (!data.startsWith('data:')) {
data = await fetchAuto(url) data = await fetchAuto(url)
} }
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
let roleIDs: string[] = [] let roleIDs: string[] = []
if (roles !== undefined && typeof roles === "string") roleIDs = [roles] if (roles !== undefined && typeof roles === 'string') roleIDs = [roles]
else if (roles !== undefined) { else if (roles !== undefined) {
if (roles?.length === 0) reject(new Error("Empty Roles array was provided")) if (roles?.length === 0)
if (roles[0] instanceof Role) roleIDs = (roles as any).map((r: Role) => r.id) reject(new Error('Empty Roles array was provided'))
if (roles[0] instanceof Role)
roleIDs = (roles as any).map((r: Role) => r.id)
else roleIDs = roles as string[] else roleIDs = roles as string[]
} else roles = [this.guild.id] } else roles = [this.guild.id]
this.client.rest this.client.rest
@ -63,14 +66,14 @@ export class GuildEmojisManager extends BaseChildManager<
image: data, image: data,
roles: roleIDs roles: roleIDs
}) })
.then(async data => { .then(async (data) => {
const emoji = new Emoji(this.client, data as EmojiPayload) const emoji = new Emoji(this.client, data as EmojiPayload)
data.guild_id = this.guild.id data.guild_id = this.guild.id
await this.set(data.id, data as EmojiPayload) await this.set(data.id, data as EmojiPayload)
emoji.guild = this.guild emoji.guild = this.guild
resolve(emoji) resolve(emoji)
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }

View File

@ -1,48 +1,48 @@
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 { VoiceChannel } from '../structures/guildVoiceChannel.ts' import { VoiceChannel } from '../structures/guildVoiceChannel.ts'
import { User } from '../structures/user.ts' import { User } from '../structures/user.ts'
import { VoiceState } from '../structures/voiceState.ts' import { VoiceState } from '../structures/voiceState.ts'
import { VoiceStatePayload } from '../types/voice.ts' import { VoiceStatePayload } from '../types/voice.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class GuildVoiceStatesManager extends BaseManager< export class GuildVoiceStatesManager extends BaseManager<
VoiceStatePayload, VoiceStatePayload,
VoiceState VoiceState
> { > {
guild: Guild guild: Guild
constructor(client: Client, guild: Guild) { constructor(client: Client, guild: Guild) {
super(client, `vs:${guild.id}`, VoiceState) super(client, `vs:${guild.id}`, VoiceState)
this.guild = guild this.guild = guild
} }
async get(key: string): Promise<VoiceState | undefined> { async get(key: string): Promise<VoiceState | undefined> {
const raw = await this._get(key) const raw = await this._get(key)
if (raw === undefined) return if (raw === undefined) return
const guild = const guild =
raw.guild_id === undefined raw.guild_id === undefined
? undefined ? undefined
: await this.client.guilds.get(raw.guild_id) : await this.client.guilds.get(raw.guild_id)
return new VoiceState(this.client, raw, { return new VoiceState(this.client, raw, {
user: ((await this.client.users.get(raw.user_id)) as unknown) as User, user: ((await this.client.users.get(raw.user_id)) as unknown) as User,
channel: channel:
raw.channel_id == null raw.channel_id == null
? null ? null
: (((await this.client.channels.get<VoiceChannel>( : (((await this.client.channels.get<VoiceChannel>(
raw.channel_id raw.channel_id
)) as unknown) as VoiceChannel), )) as unknown) as VoiceChannel),
guild, guild,
member: member:
guild === undefined ? undefined : await guild.members.get(raw.user_id), guild === undefined ? undefined : await guild.members.get(raw.user_id)
}) })
} }
async fromPayload(d: VoiceStatePayload[]): Promise<void> { async fromPayload(d: VoiceStatePayload[]): Promise<void> {
for (const data of d) { for (const data of d) {
await this.set(data.user_id, data) await this.set(data.user_id, data)
} }
} }
} }

View File

@ -6,11 +6,11 @@ import { BaseManager } from './base.ts'
import { MembersManager } from './members.ts' import { MembersManager } from './members.ts'
export class GuildManager extends BaseManager<GuildPayload, Guild> { export class GuildManager extends BaseManager<GuildPayload, Guild> {
constructor (client: Client) { constructor(client: Client) {
super(client, 'guilds', Guild) super(client, 'guilds', Guild)
} }
async fetch (id: string): Promise<Guild> { async fetch(id: string): Promise<Guild> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(GUILD(id)) .get(GUILD(id))
@ -29,7 +29,7 @@ export class GuildManager extends BaseManager<GuildPayload, Guild> {
resolve(guild) resolve(guild)
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }
} }

View File

@ -1,81 +1,81 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { BaseChildManager } from './baseChild.ts' import { BaseChildManager } from './baseChild.ts'
import { RolePayload } from '../types/role.ts' import { RolePayload } from '../types/role.ts'
import { Role } from '../structures/role.ts' import { Role } from '../structures/role.ts'
import { Member } from '../structures/member.ts' import { Member } from '../structures/member.ts'
import { RolesManager } from './roles.ts' import { RolesManager } from './roles.ts'
import { MemberPayload } from '../types/guild.ts' import { MemberPayload } from '../types/guild.ts'
import { GUILD_MEMBER_ROLE } from '../types/endpoint.ts' import { GUILD_MEMBER_ROLE } from '../types/endpoint.ts'
export class MemberRolesManager extends BaseChildManager<RolePayload, Role> { export class MemberRolesManager extends BaseChildManager<RolePayload, Role> {
member: Member member: Member
constructor(client: Client, parent: RolesManager, member: Member) { constructor(client: Client, parent: RolesManager, member: Member) {
super(client, parent as any) super(client, parent as any)
this.member = member this.member = member
} }
async get(id: string): Promise<Role | undefined> { async get(id: string): Promise<Role | undefined> {
const res = await this.parent.get(id) const res = await this.parent.get(id)
const mem = (await (this.parent as any).guild.members._get( const mem = (await (this.parent as any).guild.members._get(
this.member.id this.member.id
)) as MemberPayload )) as MemberPayload
if ( if (
res !== undefined && res !== undefined &&
(mem.roles.includes(res.id) === true || res.id === this.member.guild.id) (mem.roles.includes(res.id) === true || res.id === this.member.guild.id)
) )
return res return res
else return undefined else return undefined
} }
async array(): Promise<Role[]> { async array(): Promise<Role[]> {
const arr = (await this.parent.array()) as Role[] const arr = (await this.parent.array()) as Role[]
const mem = (await (this.parent as any).guild.members._get( const mem = (await (this.parent as any).guild.members._get(
this.member.id this.member.id
)) as MemberPayload )) as MemberPayload
return arr.filter( return arr.filter(
(c: any) => (c: any) =>
(mem.roles.includes(c.id) as boolean) || c.id === this.member.guild.id (mem.roles.includes(c.id) as boolean) || c.id === this.member.guild.id
) as any ) as any
} }
async flush(): Promise<boolean> { async flush(): Promise<boolean> {
const arr = await this.array() const arr = await this.array()
for (const elem of arr) { for (const elem of arr) {
this.parent.delete(elem.id) this.parent.delete(elem.id)
} }
return true return true
} }
async add(role: string | Role): Promise<boolean> { async add(role: string | Role): Promise<boolean> {
const res = await this.client.rest.put( const res = await this.client.rest.put(
GUILD_MEMBER_ROLE( GUILD_MEMBER_ROLE(
this.member.guild.id, this.member.guild.id,
this.member.id, this.member.id,
typeof role === 'string' ? role : role.id typeof role === 'string' ? role : role.id
), ),
undefined, undefined,
undefined, undefined,
undefined, undefined,
true true
) )
return res.status === 204 return res.status === 204
} }
async remove(role: string | Role): Promise<boolean> { async remove(role: string | Role): Promise<boolean> {
const res = await this.client.rest.delete( const res = await this.client.rest.delete(
GUILD_MEMBER_ROLE( GUILD_MEMBER_ROLE(
this.member.guild.id, this.member.guild.id,
this.member.id, this.member.id,
typeof role === 'string' ? role : role.id typeof role === 'string' ? role : role.id
), ),
undefined, undefined,
undefined, undefined,
undefined, undefined,
true true
) )
return res.status === 204 return res.status === 204
} }
} }

View File

@ -5,7 +5,7 @@ import { Member } from '../structures/member.ts'
import { GUILD_MEMBER } from '../types/endpoint.ts' import { GUILD_MEMBER } from '../types/endpoint.ts'
import { MemberPayload } from '../types/guild.ts' import { MemberPayload } from '../types/guild.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
import { Permissions } from "../utils/permissions.ts" import { Permissions } from '../utils/permissions.ts'
export class MembersManager extends BaseManager<MemberPayload, Member> { export class MembersManager extends BaseManager<MemberPayload, Member> {
guild: Guild guild: Guild
@ -22,27 +22,47 @@ export class MembersManager extends BaseManager<MemberPayload, Member> {
const roles = await this.guild.roles.array() const roles = await this.guild.roles.array()
let permissions = new Permissions(Permissions.DEFAULT) let permissions = new Permissions(Permissions.DEFAULT)
if (roles !== undefined) { if (roles !== undefined) {
const mRoles = roles.filter(r => raw.roles.includes(r.id) as boolean || r.id === this.guild.id) const mRoles = roles.filter(
permissions = new Permissions(mRoles.map(r => r.permissions)) (r) => (raw.roles.includes(r.id) as boolean) || r.id === this.guild.id
)
permissions = new Permissions(mRoles.map((r) => r.permissions))
} }
const res = new this.DataType(this.client, raw, user, this.guild, permissions) const res = new this.DataType(
this.client,
raw,
user,
this.guild,
permissions
)
return res return res
} }
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.get(GUILD_MEMBER(this.guild.id, id)).then(async data => { this.client.rest
await this.set(id, data as MemberPayload) .get(GUILD_MEMBER(this.guild.id, id))
const user: User = new User(this.client, data.user) .then(async (data) => {
const roles = await this.guild.roles.array() await this.set(id, data as MemberPayload)
let permissions = new Permissions(Permissions.DEFAULT) const user: User = new User(this.client, data.user)
if (roles !== undefined) { const roles = await this.guild.roles.array()
const mRoles = roles.filter(r => data.roles.includes(r.id) as boolean || r.id === this.guild.id) let permissions = new Permissions(Permissions.DEFAULT)
permissions = new Permissions(mRoles.map(r => r.permissions)) if (roles !== undefined) {
} const mRoles = roles.filter(
const res = new Member(this.client, data as MemberPayload, user, this.guild, permissions) (r) =>
resolve(res) (data.roles.includes(r.id) as boolean) || r.id === this.guild.id
}).catch(e => reject(e)) )
permissions = new Permissions(mRoles.map((r) => r.permissions))
}
const res = new Member(
this.client,
data as MemberPayload,
user,
this.guild,
permissions
)
resolve(res)
})
.catch((e) => reject(e))
}) })
} }
@ -51,4 +71,4 @@ export class MembersManager extends BaseManager<MemberPayload, Member> {
await this.set(member.user.id, member) await this.set(member.user.id, member)
} }
} }
} }

View File

@ -1,44 +1,44 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Emoji } from '../structures/emoji.ts' import { Emoji } from '../structures/emoji.ts'
import { Guild } from '../structures/guild.ts' 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 { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class MessageReactionsManager extends BaseManager< export class MessageReactionsManager extends BaseManager<
Reaction, Reaction,
MessageReaction MessageReaction
> { > {
message: Message message: Message
constructor(client: Client, message: Message) { constructor(client: Client, message: Message) {
super(client, `reactions:${message.id}`, Guild) super(client, `reactions:${message.id}`, Guild)
this.message = message this.message = message
} }
async get(id: string): Promise<MessageReaction | undefined> { async get(id: string): Promise<MessageReaction | undefined> {
const raw = await this._get(id) const raw = await this._get(id)
if (raw === undefined) return if (raw === undefined) return
let emoji = await this.client.emojis.get(raw.emoji.id) let emoji = await this.client.emojis.get(raw.emoji.id)
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)
return reaction return reaction
} }
async set(key: string, value: Reaction): Promise<any> { async set(key: string, value: Reaction): Promise<any> {
return this.client.cache.set( return this.client.cache.set(
this.cacheName, this.cacheName,
key, key,
value, value,
this.client.reactionCacheLifetime this.client.reactionCacheLifetime
) )
} }
async flush(): Promise<any> { async flush(): Promise<any> {
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)
} }
} }

View File

@ -1,80 +1,80 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Message } from '../structures/message.ts' import { Message } from '../structures/message.ts'
import { TextChannel } from '../structures/textChannel.ts' import { TextChannel } from '../structures/textChannel.ts'
import { User } from '../structures/user.ts' import { User } from '../structures/user.ts'
import { MessagePayload } from '../types/channel.ts' import { MessagePayload } from '../types/channel.ts'
import { CHANNEL_MESSAGE } from '../types/endpoint.ts' import { CHANNEL_MESSAGE } from '../types/endpoint.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class MessagesManager extends BaseManager<MessagePayload, Message> { export class MessagesManager extends BaseManager<MessagePayload, Message> {
channel: TextChannel channel: TextChannel
constructor(client: Client, channel: TextChannel) { constructor(client: Client, channel: TextChannel) {
super(client, 'messages', Message) super(client, 'messages', Message)
this.channel = channel this.channel = channel
} }
async get(key: string): Promise<Message | undefined> { async get(key: string): Promise<Message | undefined> {
const raw = await this._get(key) const raw = await this._get(key)
if (raw === undefined) return if (raw === undefined) return
if (raw.author === undefined) return if (raw.author === undefined) return
let channel = await this.client.channels.get(raw.channel_id) let channel = await this.client.channels.get(raw.channel_id)
if (channel === undefined) if (channel === undefined)
channel = await this.client.channels.fetch(raw.channel_id) channel = await this.client.channels.fetch(raw.channel_id)
let author = ((await this.client.users.get( let author = ((await this.client.users.get(
raw.author.id raw.author.id
)) as unknown) as User )) as unknown) as User
if (author === undefined) author = new User(this.client, raw.author) if (author === undefined) author = new User(this.client, raw.author)
const res = new this.DataType(this.client, raw, channel, author) as any const res = new this.DataType(this.client, raw, channel, author) as any
await res.mentions.fromPayload(raw) await res.mentions.fromPayload(raw)
return res return res
} }
async set(key: string, value: MessagePayload): Promise<any> { async set(key: string, value: MessagePayload): Promise<any> {
return this.client.cache.set( return this.client.cache.set(
this.cacheName, this.cacheName,
key, key,
value, value,
this.client.messageCacheLifetime this.client.messageCacheLifetime
) )
} }
async fetch(id: string): Promise<Message> { async fetch(id: string): Promise<Message> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(CHANNEL_MESSAGE(this.channel.id, id)) .get(CHANNEL_MESSAGE(this.channel.id, id))
.then(async (data) => { .then(async (data) => {
await this.set(id, data as MessagePayload) await this.set(id, data as MessagePayload)
let channel: any = await this.client.channels.get<TextChannel>( let channel: any = await this.client.channels.get<TextChannel>(
this.channel.id this.channel.id
) )
if (channel === undefined) if (channel === undefined)
channel = await this.client.channels.fetch(this.channel.id) channel = await this.client.channels.fetch(this.channel.id)
const author = new User(this.client, (data as MessagePayload).author) const author = new User(this.client, (data as MessagePayload).author)
await this.client.users.set( await this.client.users.set(
author.id, author.id,
(data as MessagePayload).author (data as MessagePayload).author
) )
const res = new Message( const res = new Message(
this.client, this.client,
data as MessagePayload, data as MessagePayload,
channel as TextChannel, channel as TextChannel,
author author
) )
await res.mentions.fromPayload(data) await res.mentions.fromPayload(data)
resolve(res) resolve(res)
}) })
.catch((e) => reject(e)) .catch((e) => reject(e))
}) })
} }
} }

View File

@ -1,39 +1,39 @@
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 { Presence } from '../structures/presence.ts' import { Presence } from '../structures/presence.ts'
import { User } from '../structures/user.ts' import { User } from '../structures/user.ts'
import { PresenceUpdatePayload } from '../types/gateway.ts' import { PresenceUpdatePayload } from '../types/gateway.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class GuildPresencesManager extends BaseManager< export class GuildPresencesManager extends BaseManager<
PresenceUpdatePayload, PresenceUpdatePayload,
Presence Presence
> { > {
guild: Guild guild: Guild
constructor(client: Client, guild: Guild) { constructor(client: Client, guild: Guild) {
super(client, `presences:${guild.id}`, Presence) super(client, `presences:${guild.id}`, Presence)
this.guild = guild this.guild = guild
} }
async get(id: string): Promise<Presence | undefined> { async get(id: string): Promise<Presence | undefined> {
const raw = await this._get(id) const raw = await this._get(id)
if (raw === undefined) return if (raw === undefined) return
let user = await this.client.users.get(raw.user.id) let user = await this.client.users.get(raw.user.id)
if (user === undefined) user = new User(this.client, raw.user) if (user === undefined) user = new User(this.client, raw.user)
const guild = await this.client.guilds.get(raw.guild_id) const guild = await this.client.guilds.get(raw.guild_id)
if (guild === undefined) return if (guild === undefined) return
const presence = new Presence(this.client, raw, user, guild) const presence = new Presence(this.client, raw, user, guild)
return presence return presence
} }
async fromPayload( async fromPayload(
data: PresenceUpdatePayload[] data: PresenceUpdatePayload[]
): Promise<GuildPresencesManager> { ): Promise<GuildPresencesManager> {
await this.flush() await this.flush()
for (const pres of data) { for (const pres of data) {
await this.set(pres.user.id, pres) await this.set(pres.user.id, pres)
} }
return this return this
} }
} }

View File

@ -1,13 +1,13 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { MessageReaction } from '../structures/messageReaction.ts' import { MessageReaction } from '../structures/messageReaction.ts'
import { UserManager } from './users.ts' import { UserManager } from './users.ts'
export class ReactionUsersManager extends UserManager { export class ReactionUsersManager extends UserManager {
reaction: MessageReaction reaction: MessageReaction
constructor(client: Client, reaction: MessageReaction) { constructor(client: Client, reaction: MessageReaction) {
super(client) super(client)
this.cacheName = `reaction_users:${reaction.message.id}` this.cacheName = `reaction_users:${reaction.message.id}`
this.reaction = reaction this.reaction = reaction
} }
} }

View File

@ -8,20 +8,20 @@ import { BaseManager } from './base.ts'
export class RolesManager extends BaseManager<RolePayload, Role> { export class RolesManager extends BaseManager<RolePayload, Role> {
guild: Guild guild: Guild
constructor (client: Client, guild: Guild) { constructor(client: Client, guild: Guild) {
super(client, `roles:${guild.id}`, Role) super(client, `roles:${guild.id}`, Role)
this.guild = guild this.guild = guild
} }
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((data) => {
this.set(id, data as RolePayload) this.set(id, data as RolePayload)
resolve(new Role(this.client, data as RolePayload)) resolve(new Role(this.client, data as RolePayload))
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }

View File

@ -5,19 +5,19 @@ import { UserPayload } from '../types/user.ts'
import { BaseManager } from './base.ts' import { BaseManager } from './base.ts'
export class UserManager extends BaseManager<UserPayload, User> { export class UserManager extends BaseManager<UserPayload, User> {
constructor (client: Client) { constructor(client: Client) {
super(client, 'users', User) super(client, 'users', User)
} }
async fetch (id: string): Promise<User> { async fetch(id: string): Promise<User> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.rest this.client.rest
.get(USER(id)) .get(USER(id))
.then(data => { .then((data) => {
this.set(id, data as UserPayload) this.set(id, data as UserPayload)
resolve(new User(this.client, data as UserPayload)) resolve(new User(this.client, data as UserPayload))
}) })
.catch(e => reject(e)) .catch((e) => reject(e))
}) })
} }
} }

View File

@ -7,7 +7,12 @@ import {
export interface ICacheAdapter { export interface ICacheAdapter {
get: (cacheName: string, key: string) => Promise<any> | any get: (cacheName: string, key: string) => Promise<any> | any
set: (cacheName: string, key: string, value: any, expire?: number) => Promise<any> | any set: (
cacheName: string,
key: string,
value: any,
expire?: number
) => Promise<any> | any
delete: (cacheName: string, key: string) => Promise<boolean> | boolean delete: (cacheName: string, key: string) => Promise<boolean> | boolean
array: (cacheName: string) => undefined | any[] | Promise<any[] | undefined> array: (cacheName: string) => undefined | any[] | Promise<any[] | undefined>
deleteCache: (cacheName: string) => any deleteCache: (cacheName: string) => any
@ -24,16 +29,22 @@ export class DefaultCacheAdapter implements ICacheAdapter {
return cache.get(key) return cache.get(key)
} }
async set(cacheName: string, key: string, value: any, expire?: number): Promise<any> { async set(
cacheName: string,
key: string,
value: any,
expire?: number
): Promise<any> {
let cache = this.data[cacheName] let cache = this.data[cacheName]
if (cache === undefined) { if (cache === undefined) {
this.data[cacheName] = new Collection() this.data[cacheName] = new Collection()
cache = this.data[cacheName] cache = this.data[cacheName]
} }
cache.set(key, value) cache.set(key, value)
if (expire !== undefined) setTimeout(() => { if (expire !== undefined)
cache.delete(key) setTimeout(() => {
}, expire) cache.delete(key)
}, expire)
} }
async delete(cacheName: string, key: string): Promise<boolean> { async delete(cacheName: string, key: string): Promise<boolean> {
@ -64,7 +75,7 @@ export class RedisCacheAdapter implements ICacheAdapter {
constructor(options: RedisConnectOptions) { constructor(options: RedisConnectOptions) {
this._redis = connect(options) this._redis = connect(options)
this._redis.then( this._redis.then(
redis => { (redis) => {
this.redis = redis this.redis = redis
this.ready = true this.ready = true
this._startExpireInterval() this._startExpireInterval()
@ -79,11 +90,11 @@ export class RedisCacheAdapter implements ICacheAdapter {
this._expireInterval = setInterval(() => { this._expireInterval = setInterval(() => {
this.redis?.scan(0, { pattern: '*:expires' }).then(([_, names]) => { this.redis?.scan(0, { pattern: '*:expires' }).then(([_, names]) => {
for (const name of names) { for (const name of names) {
this.redis?.hvals(name).then(vals => { this.redis?.hvals(name).then((vals) => {
for (const val of vals) { for (const val of vals) {
const expireVal: { const expireVal: {
name: string, name: string
key: string, key: string
at: number at: number
} = JSON.parse(val) } = JSON.parse(val)
const expired = new Date().getTime() > expireVal.at const expired = new Date().getTime() > expireVal.at
@ -126,7 +137,11 @@ export class RedisCacheAdapter implements ICacheAdapter {
await this.redis?.hset( await this.redis?.hset(
`${cacheName}:expires`, `${cacheName}:expires`,
key, key,
JSON.stringify({ name: cacheName, key, at: new Date().getTime() + expire }) JSON.stringify({
name: cacheName,
key,
at: new Date().getTime() + expire
})
) )
} }
return result return result
@ -148,6 +163,6 @@ export class RedisCacheAdapter implements ICacheAdapter {
async deleteCache(cacheName: string): Promise<boolean> { async deleteCache(cacheName: string): Promise<boolean> {
await this._checkReady() await this._checkReady()
return await this.redis?.del(cacheName) !== 0 return (await this.redis?.del(cacheName)) !== 0
} }
} }

View File

@ -1,148 +1,147 @@
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'
import { RESTManager } from './rest.ts' import { RESTManager } from './rest.ts'
import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts' import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts'
import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts' import { DefaultCacheAdapter, ICacheAdapter } from './cacheAdapter.ts'
import { UserManager } from '../managers/users.ts' import { UserManager } from '../managers/users.ts'
import { GuildManager } from '../managers/guilds.ts' import { GuildManager } from '../managers/guilds.ts'
import { ChannelsManager } from '../managers/channels.ts' 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 { ClientEvents } from '../gateway/handlers/index.ts'
// import { Application } from "../../mod.ts"
/** Some Client Options to modify behaviour */
/** Some Client Options to modify behaviour */ export interface ClientOptions {
export interface ClientOptions { /** Token of the Bot/User */
/** Token of the Bot/User */ token?: string
token?: string /** Gateway Intents */
/** Gateway Intents */ intents?: GatewayIntents[]
intents?: GatewayIntents[] /** Cache Adapter to use, defaults to Collections one */
/** Cache Adapter to use, defaults to Collections one */ cache?: ICacheAdapter
cache?: ICacheAdapter /** Force New Session and don't use cached Session (by persistent caching) */
/** Force New Session and don't use cached Session (by persistent caching) */ forceNewSession?: boolean
forceNewSession?: boolean /** Startup presence of client */
/** Startup presence of client */ presence?: ClientPresence | ClientActivity | ActivityGame
presence?: ClientPresence | ClientActivity | ActivityGame /** Whether it's a bot user or not? Use this if selfbot! */
/** Whether it's a bot user or not? Use this if selfbot! */ bot?: boolean
bot?: boolean /** Force all requests to Canary API */
/** Force all requests to Canary API */ canary?: boolean
canary?: boolean /** Time till which Messages are to be cached, in MS. Default is 3600000 */
/** Time till which Messages are to be cached, in MS. Default is 3600000 */ messageCacheLifetime?: number
messageCacheLifetime?: number /** Time till which Message Reactions are to be cached, in MS. Default is 3600000 */
/** Time till which Message Reactions are to be cached, in MS. Default is 3600000 */ reactionCacheLifetime?: number
reactionCacheLifetime?: number /** Whether to fetch Uncached Message of Reaction or not? */
/** Whether to fetch Uncached Message of Reaction or not? */ fetchUncachedReactions?: boolean
fetchUncachedReactions?: boolean }
}
export declare interface Client {
export declare interface Client { on: <U extends string>(event: U, listener: ClientEvents[U]) => this
on: <U extends string>(event: U, listener: ClientEvents[U]) => this
emit: <U extends string>(
emit: <U extends string>( event: U,
event: U, ...args: Parameters<ClientEvents[U]>
...args: Parameters<ClientEvents[U]> ) => boolean
) => boolean }
}
/**
/** * Discord Client.
* Discord Client. */
*/ export class Client extends EventEmitter {
export class Client extends EventEmitter { /** Gateway object */
/** Gateway object */ gateway?: Gateway
gateway?: Gateway /** REST Manager - used to make all requests */
/** REST Manager - used to make all requests */ rest: RESTManager = new RESTManager(this)
rest: RESTManager = new RESTManager(this) /** User which Client logs in to, undefined until logs in */
/** User which Client logs in to, undefined until logs in */ user?: User
user?: User /** WebSocket ping of Client */
/** WebSocket ping of Client */ ping = 0
ping = 0 /** Token of the Bot/User */
/** Token of the Bot/User */ token?: string
token?: string /** Cache Adapter */
/** Cache Adapter */ cache: ICacheAdapter = new DefaultCacheAdapter()
cache: ICacheAdapter = new DefaultCacheAdapter() /** Gateway Intents */
/** Gateway Intents */ intents?: GatewayIntents[]
intents?: GatewayIntents[] /** Whether to force new session or not */
/** Whether to force new session or not */ forceNewSession?: boolean
forceNewSession?: boolean /** Time till messages to stay cached, in MS. */
/** Time till messages to stay cached, in MS. */ messageCacheLifetime: number = 3600000
messageCacheLifetime: number = 3600000 /** Time till messages to stay cached, in MS. */
/** Time till messages to stay cached, in MS. */ reactionCacheLifetime: number = 3600000
reactionCacheLifetime: number = 3600000 /** Whether to fetch Uncached Message of Reaction or not? */
/** Whether to fetch Uncached Message of Reaction or not? */ fetchUncachedReactions: boolean = false
fetchUncachedReactions: boolean = false
users: UserManager = new UserManager(this)
users: UserManager = new UserManager(this) guilds: GuildManager = new GuildManager(this)
guilds: GuildManager = new GuildManager(this) channels: ChannelsManager = new ChannelsManager(this)
channels: ChannelsManager = new ChannelsManager(this) emojis: EmojisManager = new EmojisManager(this)
emojis: EmojisManager = new EmojisManager(this)
/** Whether this client will login as bot user or not */
/** Whether this client will login as bot user or not */ bot: boolean = true
bot: boolean = true /** Whether the REST Manager will use Canary API or not */
/** Whether the REST Manager will use Canary API or not */ 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()
constructor(options: ClientOptions = {}) {
constructor(options: ClientOptions = {}) { super()
super() this.token = options.token
this.token = options.token this.intents = options.intents
this.intents = options.intents this.forceNewSession = options.forceNewSession
this.forceNewSession = options.forceNewSession if (options.cache !== undefined) this.cache = options.cache
if (options.cache !== undefined) this.cache = options.cache if (options.presence !== undefined)
if (options.presence !== undefined) this.presence =
this.presence = options.presence instanceof ClientPresence
options.presence instanceof ClientPresence ? options.presence
? options.presence : new ClientPresence(options.presence)
: new ClientPresence(options.presence) if (options.bot === false) this.bot = false
if (options.bot === false) this.bot = false if (options.canary === true) this.canary = true
if (options.canary === true) this.canary = true if (options.messageCacheLifetime !== undefined)
if (options.messageCacheLifetime !== undefined) this.messageCacheLifetime = options.messageCacheLifetime
this.messageCacheLifetime = options.messageCacheLifetime if (options.reactionCacheLifetime !== undefined)
if (options.reactionCacheLifetime !== undefined) this.reactionCacheLifetime = options.reactionCacheLifetime
this.reactionCacheLifetime = options.reactionCacheLifetime if (options.fetchUncachedReactions === true)
if (options.fetchUncachedReactions === true) this.fetchUncachedReactions = true
this.fetchUncachedReactions = true }
}
/** Set Cache Adapter */
/** Set Cache Adapter */ setAdapter(adapter: ICacheAdapter): Client {
setAdapter(adapter: ICacheAdapter): Client { this.cache = adapter
this.cache = adapter return this
return this }
}
/** Change Presence of Client */
/** Change Presence of Client */ setPresence(presence: ClientPresence | ClientActivity | ActivityGame): void {
setPresence(presence: ClientPresence | ClientActivity | ActivityGame): void { if (presence instanceof ClientPresence) {
if (presence instanceof ClientPresence) { this.presence = presence
this.presence = presence } else this.presence = new ClientPresence(presence)
} else this.presence = new ClientPresence(presence) this.gateway?.sendPresence(this.presence.create())
this.gateway?.sendPresence(this.presence.create()) }
}
/** Emit debug event */
/** Emit debug event */ debug(tag: string, msg: string): void {
debug(tag: string, msg: string): void { this.emit('debug', `[${tag}] ${msg}`)
this.emit('debug', `[${tag}] ${msg}`) }
}
// TODO(DjDeveloperr): Implement this
// TODO(DjDeveloperr): Implement this // fetchApplication(): Promise<Application>
// fetchApplication(): Promise<Application>
/**
/** * This function is used for connect to discord.
* This function is used for connect to discord. * @param token Your token. This is required.
* @param token Your token. This is required. * @param intents Gateway intents in array. This is required.
* @param intents Gateway intents in array. This is required. */
*/ connect(token?: string, intents?: GatewayIntents[]): void {
connect(token?: string, intents?: GatewayIntents[]): void { if (token === undefined && this.token !== undefined) token = this.token
if (token === undefined && this.token !== undefined) token = this.token else if (this.token === undefined && token !== undefined) {
else if (this.token === undefined && token !== undefined) { this.token = token
this.token = token } else throw new Error('No Token Provided')
} else throw new Error('No Token Provided') if (intents === undefined && this.intents !== undefined)
if (intents === undefined && this.intents !== undefined) intents = this.intents
intents = this.intents else if (intents !== undefined && this.intents === undefined) {
else if (intents !== undefined && this.intents === undefined) { this.intents = intents
this.intents = intents } 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) }
} }
}

View File

@ -1,428 +1,428 @@
import { Guild } from '../structures/guild.ts' import { Guild } from '../structures/guild.ts'
import { Message } from '../structures/message.ts' import { Message } from '../structures/message.ts'
import { TextChannel } from '../structures/textChannel.ts' import { TextChannel } from '../structures/textChannel.ts'
import { User } from '../structures/user.ts' import { User } from '../structures/user.ts'
import { Collection } from '../utils/collection.ts' import { Collection } from '../utils/collection.ts'
import { CommandClient } from './commandClient.ts' import { CommandClient } from './commandClient.ts'
import { Extension } from './extensions.ts' import { Extension } from './extensions.ts'
export interface CommandContext { export interface CommandContext {
/** The Client object */ /** The Client object */
client: CommandClient client: CommandClient
/** Message which was parsed for Command */ /** Message which was parsed for Command */
message: Message message: Message
/** The Author of the Message */ /** The Author of the Message */
author: User author: User
/** The Channel in which Command was used */ /** The Channel in which Command was used */
channel: TextChannel channel: TextChannel
/** Prefix which was used */ /** Prefix which was used */
prefix: string prefix: string
/** Oject of Command which was used */ /** Oject of Command which was used */
command: Command command: Command
/** Name of Command which was used */ /** Name of Command which was used */
name: string name: string
/** Array of Arguments used with Command */ /** Array of Arguments used with Command */
args: string[] args: string[]
/** Complete Raw String of Arguments */ /** Complete Raw String of Arguments */
argString: string argString: string
/** Guild which the command has called */ /** Guild which the command has called */
guild?: Guild guild?: Guild
} }
export class Command { export class Command {
/** Name of the Command */ /** Name of the Command */
name: string = '' name: string = ''
/** Description of the Command */ /** Description of the Command */
description?: string description?: string
/** Category of the Command */ /** Category of the Command */
category?: string category?: string
/** Array of Aliases of Command, or only string */ /** Array of Aliases of Command, or only string */
aliases?: string | string[] aliases?: string | string[]
/** Extension (Parent) of the Command */ /** Extension (Parent) of the Command */
extension?: Extension extension?: Extension
/** Usage of Command, only Argument Names */ /** Usage of Command, only Argument Names */
usage?: string | string[] usage?: string | string[]
/** Usage Example of Command, only Arguments (without Prefix and Name) */ /** Usage Example of Command, only Arguments (without Prefix and Name) */
examples?: string | string[] examples?: string | string[]
/** Does the Command take Arguments? Maybe number of required arguments? Or list of arguments? */ /** Does the Command take Arguments? Maybe number of required arguments? Or list of arguments? */
args?: number | boolean | string[] args?: number | boolean | string[]
/** Permissions(s) required by both User and Bot in order to use Command */ /** Permissions(s) required by both User and Bot in order to use Command */
permissions?: string | string[] permissions?: string | string[]
/** Permission(s) required for using Command */ /** Permission(s) required for using Command */
userPermissions?: string | string[] userPermissions?: string | string[]
/** Permission(s) bot will need in order to execute Command */ /** Permission(s) bot will need in order to execute Command */
botPermissions?: string | string[] botPermissions?: string | string[]
/** Role(s) user will require in order to use Command. List or one of ID or name */ /** Role(s) user will require in order to use Command. List or one of ID or name */
roles?: string | string[] roles?: string | string[]
/** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */ /** Whitelisted Guilds. Only these Guild(s) can execute Command. (List or one of IDs) */
whitelistedGuilds?: string | string[] whitelistedGuilds?: string | string[]
/** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */ /** Whitelisted Channels. Command can be executed only in these channels. (List or one of IDs) */
whitelistedChannels?: string | string[] whitelistedChannels?: string | string[]
/** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */ /** Whitelisted Users. Command can be executed only by these Users (List or one of IDs) */
whitelistedUsers?: string | string[] whitelistedUsers?: string | string[]
/** Whether the Command can only be used in Guild (if allowed in DMs) */ /** Whether the Command can only be used in Guild (if allowed in DMs) */
guildOnly?: boolean guildOnly?: boolean
/** Whether the Command can only be used in Bot's DMs (if allowed) */ /** Whether the Command can only be used in Bot's DMs (if allowed) */
dmOnly?: boolean dmOnly?: boolean
/** Whether the Command can only be used by Bot Owners */ /** Whether the Command can only be used by Bot Owners */
ownerOnly?: boolean ownerOnly?: boolean
/** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */ /** Method executed before executing actual command. Returns bool value - whether to continue or not (optional) */
beforeExecute(ctx: CommandContext): boolean | Promise<boolean> { beforeExecute(ctx: CommandContext): boolean | Promise<boolean> {
return true return true
} }
/** Actual command code, which is executed when all checks have passed. */ /** Actual command code, which is executed when all checks have passed. */
execute(ctx: CommandContext): any {} execute(ctx: CommandContext): any {}
/** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */ /** Method executed after executing command, passes on CommandContext and the value returned by execute too. (optional) */
afterExecute(ctx: CommandContext, executeResult: any): any {} afterExecute(ctx: CommandContext, executeResult: any): any {}
toString(): string { toString(): string {
return `Command: ${this.name}${ return `Command: ${this.name}${
this.extension !== undefined this.extension !== undefined
? ` [${this.extension.name}]` ? ` [${this.extension.name}]`
: this.category !== undefined : this.category !== undefined
? ` [${this.category}]` ? ` [${this.category}]`
: '' : ''
}` }`
} }
} }
export class CommandCategory { export class CommandCategory {
/** Name of the Category. */ /** Name of the Category. */
name: string = '' name: string = ''
/** Permissions(s) required by both User and Bot in order to use Category Commands */ /** Permissions(s) required by both User and Bot in order to use Category Commands */
permissions?: string | string[] permissions?: string | string[]
/** Permission(s) required for using Category Commands */ /** Permission(s) required for using Category Commands */
userPermissions?: string | string[] userPermissions?: string | string[]
/** Permission(s) bot will need in order to execute Category Commands */ /** Permission(s) bot will need in order to execute Category Commands */
botPermissions?: string | string[] botPermissions?: string | string[]
/** Role(s) user will require in order to use Category Commands. List or one of ID or name */ /** Role(s) user will require in order to use Category Commands. List or one of ID or name */
roles?: string | string[] roles?: string | string[]
/** Whitelisted Guilds. Only these Guild(s) can execute Category Commands. (List or one of IDs) */ /** Whitelisted Guilds. Only these Guild(s) can execute Category Commands. (List or one of IDs) */
whitelistedGuilds?: string | string[] whitelistedGuilds?: string | string[]
/** Whitelisted Channels. Category Commands can be executed only in these channels. (List or one of IDs) */ /** Whitelisted Channels. Category Commands can be executed only in these channels. (List or one of IDs) */
whitelistedChannels?: string | string[] whitelistedChannels?: string | string[]
/** Whitelisted Users. Category Commands can be executed only by these Users (List or one of IDs) */ /** Whitelisted Users. Category Commands can be executed only by these Users (List or one of IDs) */
whitelistedUsers?: string | string[] whitelistedUsers?: string | string[]
/** Whether the Category Commands can only be used in Guild (if allowed in DMs) */ /** Whether the Category Commands can only be used in Guild (if allowed in DMs) */
guildOnly?: boolean guildOnly?: boolean
/** Whether the Category Commands can only be used in Bot's DMs (if allowed) */ /** Whether the Category Commands can only be used in Bot's DMs (if allowed) */
dmOnly?: boolean dmOnly?: boolean
/** Whether the Category Commands can only be used by Bot Owners */ /** Whether the Category Commands can only be used by Bot Owners */
ownerOnly?: boolean ownerOnly?: boolean
} }
export class CommandBuilder extends Command { export class CommandBuilder extends Command {
setName(name: string): CommandBuilder { setName(name: string): CommandBuilder {
this.name = name this.name = name
return this return this
} }
setDescription(description?: string): CommandBuilder { setDescription(description?: string): CommandBuilder {
this.description = description this.description = description
return this return this
} }
setCategory(category?: string): CommandBuilder { setCategory(category?: string): CommandBuilder {
this.category = category this.category = category
return this return this
} }
setAlias(alias: string | string[]): CommandBuilder { setAlias(alias: string | string[]): CommandBuilder {
this.aliases = alias this.aliases = alias
return this return this
} }
addAlias(alias: string | string[]): CommandBuilder { addAlias(alias: string | string[]): CommandBuilder {
if (this.aliases === undefined) this.aliases = [] if (this.aliases === undefined) this.aliases = []
if (typeof this.aliases === 'string') this.aliases = [this.aliases] if (typeof this.aliases === 'string') this.aliases = [this.aliases]
this.aliases = [ this.aliases = [
...new Set( ...new Set(
...this.aliases, ...this.aliases,
...(typeof alias === 'string' ? [alias] : alias) ...(typeof alias === 'string' ? [alias] : alias)
), )
] ]
return this return this
} }
setExtension(extension?: Extension): CommandBuilder { setExtension(extension?: Extension): CommandBuilder {
this.extension = extension this.extension = extension
return this return this
} }
setUsage(usage: string | string[]): CommandBuilder { setUsage(usage: string | string[]): CommandBuilder {
this.usage = usage this.usage = usage
return this return this
} }
addUsage(usage: string | string[]): CommandBuilder { addUsage(usage: string | string[]): CommandBuilder {
if (this.usage === undefined) this.usage = [] if (this.usage === undefined) this.usage = []
if (typeof this.usage === 'string') this.usage = [this.usage] if (typeof this.usage === 'string') this.usage = [this.usage]
this.aliases = [ this.aliases = [
...new Set( ...new Set(
...this.usage, ...this.usage,
...(typeof usage === 'string' ? [usage] : usage) ...(typeof usage === 'string' ? [usage] : usage)
), )
] ]
return this return this
} }
setExample(examples: string | string[]): CommandBuilder { setExample(examples: string | string[]): CommandBuilder {
this.examples = examples this.examples = examples
return this return this
} }
addExample(examples: string | string[]): CommandBuilder { addExample(examples: string | string[]): CommandBuilder {
if (this.examples === undefined) this.examples = [] if (this.examples === undefined) this.examples = []
if (typeof this.examples === 'string') this.examples = [this.examples] if (typeof this.examples === 'string') this.examples = [this.examples]
this.examples = [ this.examples = [
...new Set( ...new Set(
...this.examples, ...this.examples,
...(typeof examples === 'string' ? [examples] : examples) ...(typeof examples === 'string' ? [examples] : examples)
), )
] ]
return this return this
} }
setPermissions(perms?: string | string[]): CommandBuilder { setPermissions(perms?: string | string[]): CommandBuilder {
this.permissions = perms this.permissions = perms
return this return this
} }
setUserPermissions(perms?: string | string[]): CommandBuilder { setUserPermissions(perms?: string | string[]): CommandBuilder {
this.userPermissions = perms this.userPermissions = perms
return this return this
} }
setBotPermissions(perms?: string | string[]): CommandBuilder { setBotPermissions(perms?: string | string[]): CommandBuilder {
this.botPermissions = perms this.botPermissions = perms
return this return this
} }
setRoles(roles: string | string[]): CommandBuilder { setRoles(roles: string | string[]): CommandBuilder {
this.roles = roles this.roles = roles
return this return this
} }
setWhitelistedGuilds(list: string | string[]): CommandBuilder { setWhitelistedGuilds(list: string | string[]): CommandBuilder {
this.whitelistedGuilds = list this.whitelistedGuilds = list
return this return this
} }
setWhitelistedUsers(list: string | string[]): CommandBuilder { setWhitelistedUsers(list: string | string[]): CommandBuilder {
this.whitelistedUsers = list this.whitelistedUsers = list
return this return this
} }
setWhitelistedChannels(list: string | string[]): CommandBuilder { setWhitelistedChannels(list: string | string[]): CommandBuilder {
this.whitelistedChannels = list this.whitelistedChannels = list
return this return this
} }
setGuildOnly(value: boolean = true): CommandBuilder { setGuildOnly(value: boolean = true): CommandBuilder {
this.guildOnly = value this.guildOnly = value
return this return this
} }
setOwnerOnly(value: boolean = true): CommandBuilder { setOwnerOnly(value: boolean = true): CommandBuilder {
this.ownerOnly = value this.ownerOnly = value
return this return this
} }
onBeforeExecute(fn: (ctx: CommandContext) => boolean | any): CommandBuilder { onBeforeExecute(fn: (ctx: CommandContext) => boolean | any): CommandBuilder {
this.beforeExecute = fn this.beforeExecute = fn
return this return this
} }
onExecute(fn: (ctx: CommandContext) => any): CommandBuilder { onExecute(fn: (ctx: CommandContext) => any): CommandBuilder {
this.execute = fn this.execute = fn
return this return this
} }
onAfterExecute( onAfterExecute(
fn: (ctx: CommandContext, executeResult?: any) => any fn: (ctx: CommandContext, executeResult?: any) => any
): CommandBuilder { ): CommandBuilder {
this.afterExecute = fn this.afterExecute = fn
return this return this
} }
} }
export class CommandsManager { export class CommandsManager {
client: CommandClient client: CommandClient
list: Collection<string, Command> = new Collection() list: Collection<string, Command> = new Collection()
disabled: Set<string> = new Set() disabled: Set<string> = new Set()
constructor(client: CommandClient) { constructor(client: CommandClient) {
this.client = client this.client = client
} }
/** Number of loaded Commands */ /** Number of loaded Commands */
get count(): number { get count(): number {
return this.list.size return this.list.size
} }
/** Find a Command by name/alias */ /** Find a Command by name/alias */
find(search: string): Command | undefined { find(search: string): Command | undefined {
if (this.client.caseSensitive === false) search = search.toLowerCase() if (this.client.caseSensitive === false) search = search.toLowerCase()
return this.list.find((cmd: Command): boolean => { return this.list.find((cmd: Command): boolean => {
const name = const name =
this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase() this.client.caseSensitive === true ? cmd.name : cmd.name.toLowerCase()
if (name === search) return true if (name === search) return true
else if (cmd.aliases !== undefined) { else if (cmd.aliases !== undefined) {
let aliases: string[] let aliases: string[]
if (typeof cmd.aliases === 'string') aliases = [cmd.aliases] if (typeof cmd.aliases === 'string') aliases = [cmd.aliases]
else aliases = cmd.aliases else aliases = cmd.aliases
if (this.client.caseSensitive === false) if (this.client.caseSensitive === false)
aliases = aliases.map((e) => e.toLowerCase()) aliases = aliases.map((e) => e.toLowerCase())
return aliases.includes(search) return aliases.includes(search)
} else return false } else return false
}) })
} }
/** Fetch a Command including disable checks */ /** Fetch a Command including disable checks */
fetch(name: string, bypassDisable?: boolean): Command | undefined { fetch(name: string, bypassDisable?: boolean): Command | undefined {
const cmd = this.find(name) const cmd = this.find(name)
if (cmd === undefined) return if (cmd === undefined) return
if (this.isDisabled(cmd) && bypassDisable !== true) return if (this.isDisabled(cmd) && bypassDisable !== true) return
return cmd return cmd
} }
/** Check whether a Command exists or not */ /** Check whether a Command exists or not */
exists(search: Command | string): boolean { exists(search: Command | string): boolean {
let exists = false let exists = false
if (typeof search === 'string') return this.find(search) !== undefined if (typeof search === 'string') return this.find(search) !== undefined
else { else {
exists = this.find(search.name) !== undefined exists = this.find(search.name) !== undefined
if (search.aliases !== undefined) { if (search.aliases !== undefined) {
const aliases: string[] = const aliases: string[] =
typeof search.aliases === 'string' ? [search.aliases] : search.aliases typeof search.aliases === 'string' ? [search.aliases] : search.aliases
exists = exists =
aliases aliases
.map((alias) => this.find(alias) !== undefined) .map((alias) => this.find(alias) !== undefined)
.find((e) => e) ?? false .find((e) => e) ?? false
} }
return exists return exists
} }
} }
/** Add a Command */ /** Add a Command */
add(cmd: Command | typeof Command): boolean { add(cmd: Command | typeof Command): boolean {
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
if (!(cmd instanceof Command)) cmd = new cmd() if (!(cmd instanceof Command)) cmd = new cmd()
if (this.exists(cmd)) if (this.exists(cmd))
throw new Error( throw new Error(
`Failed to add Command '${cmd.toString()}' with name/alias already exists.` `Failed to add Command '${cmd.toString()}' with name/alias already exists.`
) )
this.list.set(cmd.name, cmd) this.list.set(cmd.name, cmd)
return true return true
} }
/** Delete a Command */ /** Delete a Command */
delete(cmd: string | Command): boolean { delete(cmd: string | Command): boolean {
const find = typeof cmd === 'string' ? this.find(cmd) : cmd const find = typeof cmd === 'string' ? this.find(cmd) : cmd
if (find === undefined) return false if (find === undefined) return false
else return this.list.delete(find.name) else return this.list.delete(find.name)
} }
/** Check whether a Command is disabled or not */ /** Check whether a Command is disabled or not */
isDisabled(name: string | Command): boolean { isDisabled(name: string | Command): boolean {
const cmd = typeof name === 'string' ? this.find(name) : name const cmd = typeof name === 'string' ? this.find(name) : name
if (cmd === undefined) return false if (cmd === undefined) return false
const exists = this.exists(name) const exists = this.exists(name)
if (!exists) return false if (!exists) return false
return this.disabled.has(cmd.name) return this.disabled.has(cmd.name)
} }
/** Disable a Command */ /** Disable a Command */
disable(name: string | Command): boolean { disable(name: string | Command): boolean {
const cmd = typeof name === 'string' ? this.find(name) : name const cmd = typeof name === 'string' ? this.find(name) : name
if (cmd === undefined) return false if (cmd === undefined) return false
if (this.isDisabled(cmd)) return false if (this.isDisabled(cmd)) return false
this.disabled.add(cmd.name) this.disabled.add(cmd.name)
return true return true
} }
/** Get all commands of a Category */ /** Get all commands of a Category */
category(category: string): Collection<string, Command> { category(category: string): Collection<string, Command> {
return this.list.filter( return this.list.filter(
(cmd) => cmd.category !== undefined && cmd.category === category (cmd) => cmd.category !== undefined && cmd.category === category
) )
} }
} }
export class CategoriesManager { export class CategoriesManager {
client: CommandClient client: CommandClient
list: Collection<string, CommandCategory> = new Collection() list: Collection<string, CommandCategory> = new Collection()
constructor(client: CommandClient) { constructor(client: CommandClient) {
this.client = client this.client = client
} }
/** Get a Collection of Categories */ /** Get a Collection of Categories */
all(): Collection<string, CommandCategory> { all(): Collection<string, CommandCategory> {
return this.list return this.list
} }
/** Get a list of names of Categories added */ /** Get a list of names of Categories added */
names(): string[] { names(): string[] {
return [...this.list.keys()] return [...this.list.keys()]
} }
/** Check if a Category exists or not */ /** Check if a Category exists or not */
has(category: string | CommandCategory): boolean { has(category: string | CommandCategory): boolean {
return this.list.has( return this.list.has(
typeof category === 'string' ? category : category.name typeof category === 'string' ? category : category.name
) )
} }
/** Get a Category by name */ /** Get a Category by name */
get(name: string): CommandCategory | undefined { get(name: string): CommandCategory | undefined {
return this.list.get(name) return this.list.get(name)
} }
/** Add a Category to the Manager */ /** Add a Category to the Manager */
add(category: CommandCategory): CategoriesManager { add(category: CommandCategory): CategoriesManager {
if (this.has(category)) if (this.has(category))
throw new Error(`Category ${category.name} already exists`) throw new Error(`Category ${category.name} already exists`)
this.list.set(category.name, category) this.list.set(category.name, category)
return this return this
} }
/** Remove a Category from the Manager */ /** Remove a Category from the Manager */
remove(category: string | CommandCategory): boolean { remove(category: string | CommandCategory): boolean {
if (!this.has(category)) return false if (!this.has(category)) return false
this.list.delete(typeof category === 'string' ? category : category.name) this.list.delete(typeof category === 'string' ? category : category.name)
return true return true
} }
} }
export interface ParsedCommand { export interface ParsedCommand {
name: string name: string
args: string[] args: string[]
argString: string argString: string
} }
export const parseCommand = ( export const parseCommand = (
client: CommandClient, client: CommandClient,
msg: Message, msg: Message,
prefix: string prefix: string
): ParsedCommand => { ): ParsedCommand => {
let content = msg.content.slice(prefix.length) let content = msg.content.slice(prefix.length)
if (client.spacesAfterPrefix === true) content = content.trim() if (client.spacesAfterPrefix === true) content = content.trim()
const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/) const args = content.split(client.betterArgs === true ? /[\S\s]*/ : / +/)
const name = args.shift() as string const name = args.shift() as string
const argString = content.slice(name.length).trim() const argString = content.slice(name.length).trim()
return { return {
name, name,
args, args,
argString, argString
} }
} }

View File

@ -1,332 +1,332 @@
import { Message } from '../../mod.ts' import { Message } from '../structures/message.ts'
import { awaitSync } from '../utils/mixedPromise.ts' import { awaitSync } from '../utils/mixedPromise.ts'
import { Client, ClientOptions } from './client.ts' import { Client, ClientOptions } from './client.ts'
import { import {
CategoriesManager, CategoriesManager,
CommandContext, CommandContext,
CommandsManager, CommandsManager,
parseCommand, parseCommand
} from './command.ts' } from './command.ts'
import { ExtensionsManager } from './extensions.ts' import { ExtensionsManager } from './extensions.ts'
type PrefixReturnType = string | string[] | Promise<string | string[]> type PrefixReturnType = string | string[] | Promise<string | string[]>
export interface CommandClientOptions extends ClientOptions { export interface CommandClientOptions extends ClientOptions {
prefix: string | string[] prefix: string | string[]
mentionPrefix?: boolean mentionPrefix?: boolean
getGuildPrefix?: (guildID: string) => PrefixReturnType getGuildPrefix?: (guildID: string) => PrefixReturnType
getUserPrefix?: (userID: string) => PrefixReturnType getUserPrefix?: (userID: string) => PrefixReturnType
isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean> isGuildBlacklisted?: (guildID: string) => boolean | Promise<boolean>
isUserBlacklisted?: (guildID: string) => boolean | Promise<boolean> isUserBlacklisted?: (guildID: string) => boolean | Promise<boolean>
isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean> isChannelBlacklisted?: (guildID: string) => boolean | Promise<boolean>
spacesAfterPrefix?: boolean spacesAfterPrefix?: boolean
betterArgs?: boolean betterArgs?: boolean
owners?: string[] owners?: string[]
allowBots?: boolean allowBots?: boolean
allowDMs?: boolean allowDMs?: boolean
caseSensitive?: boolean caseSensitive?: boolean
} }
export class CommandClient extends Client implements CommandClientOptions { export class CommandClient extends Client implements CommandClientOptions {
prefix: string | string[] prefix: string | string[]
mentionPrefix: boolean mentionPrefix: boolean
getGuildPrefix: (guildID: string) => PrefixReturnType getGuildPrefix: (guildID: string) => PrefixReturnType
getUserPrefix: (userID: string) => PrefixReturnType getUserPrefix: (userID: string) => PrefixReturnType
isGuildBlacklisted: (guildID: string) => boolean | Promise<boolean> isGuildBlacklisted: (guildID: string) => boolean | Promise<boolean>
isUserBlacklisted: (guildID: string) => boolean | Promise<boolean> isUserBlacklisted: (guildID: string) => boolean | Promise<boolean>
isChannelBlacklisted: (guildID: string) => boolean | Promise<boolean> isChannelBlacklisted: (guildID: string) => boolean | Promise<boolean>
spacesAfterPrefix: boolean spacesAfterPrefix: boolean
betterArgs: boolean betterArgs: boolean
owners: string[] owners: string[]
allowBots: boolean allowBots: boolean
allowDMs: boolean allowDMs: boolean
caseSensitive: boolean caseSensitive: boolean
extensions: ExtensionsManager = new ExtensionsManager(this) extensions: ExtensionsManager = new ExtensionsManager(this)
commands: CommandsManager = new CommandsManager(this) commands: CommandsManager = new CommandsManager(this)
categories: CategoriesManager = new CategoriesManager(this) categories: CategoriesManager = new CategoriesManager(this)
constructor(options: CommandClientOptions) { constructor(options: CommandClientOptions) {
super(options) super(options)
this.prefix = options.prefix this.prefix = options.prefix
this.mentionPrefix = this.mentionPrefix =
options.mentionPrefix === undefined ? false : options.mentionPrefix options.mentionPrefix === undefined ? false : options.mentionPrefix
this.getGuildPrefix = this.getGuildPrefix =
options.getGuildPrefix === undefined options.getGuildPrefix === undefined
? (id: string) => this.prefix ? (id: string) => this.prefix
: options.getGuildPrefix : options.getGuildPrefix
this.getUserPrefix = this.getUserPrefix =
options.getUserPrefix === undefined options.getUserPrefix === undefined
? (id: string) => this.prefix ? (id: string) => this.prefix
: options.getUserPrefix : options.getUserPrefix
this.isUserBlacklisted = this.isUserBlacklisted =
options.isUserBlacklisted === undefined options.isUserBlacklisted === undefined
? (id: string) => false ? (id: string) => false
: options.isUserBlacklisted : options.isUserBlacklisted
this.isGuildBlacklisted = this.isGuildBlacklisted =
options.isGuildBlacklisted === undefined options.isGuildBlacklisted === undefined
? (id: string) => false ? (id: string) => false
: options.isGuildBlacklisted : options.isGuildBlacklisted
this.isChannelBlacklisted = this.isChannelBlacklisted =
options.isChannelBlacklisted === undefined options.isChannelBlacklisted === undefined
? (id: string) => false ? (id: string) => false
: options.isChannelBlacklisted : options.isChannelBlacklisted
this.spacesAfterPrefix = this.spacesAfterPrefix =
options.spacesAfterPrefix === undefined options.spacesAfterPrefix === undefined
? false ? false
: options.spacesAfterPrefix : options.spacesAfterPrefix
this.betterArgs = this.betterArgs =
options.betterArgs === undefined ? false : options.betterArgs options.betterArgs === undefined ? false : options.betterArgs
this.owners = options.owners === undefined ? [] : options.owners this.owners = options.owners === undefined ? [] : options.owners
this.allowBots = options.allowBots === undefined ? false : options.allowBots this.allowBots = options.allowBots === undefined ? false : options.allowBots
this.allowDMs = options.allowDMs === undefined ? true : options.allowDMs this.allowDMs = options.allowDMs === undefined ? true : options.allowDMs
this.caseSensitive = this.caseSensitive =
options.caseSensitive === undefined ? false : options.caseSensitive options.caseSensitive === undefined ? false : options.caseSensitive
this.on( this.on(
'messageCreate', 'messageCreate',
async (msg: Message) => await this.processMessage(msg) async (msg: Message) => await this.processMessage(msg)
) )
} }
async processMessage(msg: Message): Promise<any> { async processMessage(msg: Message): Promise<any> {
if (!this.allowBots && msg.author.bot === true) return if (!this.allowBots && msg.author.bot === true) return
const isUserBlacklisted = await awaitSync( const isUserBlacklisted = await awaitSync(
this.isUserBlacklisted(msg.author.id) this.isUserBlacklisted(msg.author.id)
) )
if (isUserBlacklisted === true) return if (isUserBlacklisted === true) return
const isChannelBlacklisted = await awaitSync( const isChannelBlacklisted = await awaitSync(
this.isChannelBlacklisted(msg.channel.id) this.isChannelBlacklisted(msg.channel.id)
) )
if (isChannelBlacklisted === true) return if (isChannelBlacklisted === true) return
if (msg.guild !== undefined) { if (msg.guild !== undefined) {
const isGuildBlacklisted = await awaitSync( const isGuildBlacklisted = await awaitSync(
this.isGuildBlacklisted(msg.guild.id) this.isGuildBlacklisted(msg.guild.id)
) )
if (isGuildBlacklisted === true) return if (isGuildBlacklisted === true) return
} }
let prefix: string | string[] = this.prefix let prefix: string | string[] = await awaitSync(
this.getUserPrefix(msg.author.id)
if (msg.guild !== undefined) { )
prefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
} else { if (msg.guild !== undefined) {
prefix = await awaitSync(this.getUserPrefix(msg.author.id)) prefix = await awaitSync(this.getGuildPrefix(msg.guild.id))
} }
let mentionPrefix = false let mentionPrefix = false
if (typeof prefix === 'string') { if (typeof prefix === 'string') {
if (msg.content.startsWith(prefix) === false) { if (msg.content.startsWith(prefix) === false) {
if (this.mentionPrefix) mentionPrefix = true if (this.mentionPrefix) mentionPrefix = true
else return else return
} }
} else { } else {
const usedPrefix = prefix.find((v) => msg.content.startsWith(v)) const usedPrefix = prefix.find((v) => msg.content.startsWith(v))
if (usedPrefix === undefined) { if (usedPrefix === undefined) {
if (this.mentionPrefix) mentionPrefix = true if (this.mentionPrefix) mentionPrefix = true
else return else return
} else prefix = usedPrefix } else prefix = usedPrefix
} }
if (mentionPrefix) { if (mentionPrefix) {
if (msg.content.startsWith(this.user?.mention as string) === true) if (msg.content.startsWith(this.user?.mention as string) === true)
prefix = this.user?.mention as string prefix = this.user?.mention as string
else if ( else if (
msg.content.startsWith(this.user?.nickMention as string) === true msg.content.startsWith(this.user?.nickMention as string) === true
) )
prefix = this.user?.nickMention as string prefix = this.user?.nickMention as string
else return else return
} }
if (typeof prefix !== 'string') return if (typeof prefix !== 'string') return
const parsed = parseCommand(this, msg, prefix) const parsed = parseCommand(this, msg, prefix)
const command = this.commands.find(parsed.name) const command = this.commands.find(parsed.name)
if (command === undefined) return if (command === undefined) return
const category = const category =
command.category !== undefined command.category !== undefined
? this.categories.get(command.category) ? this.categories.get(command.category)
: undefined : undefined
// Guild whitelist exists, and if does and Command used in a Guild, is this Guild allowed? // Guild whitelist exists, and if does and Command used in a Guild, is this Guild allowed?
// This is a bit confusing here, if these settings on a Command exist, and also do on Category, Command overrides them // This is a bit confusing here, if these settings on a Command exist, and also do on Category, Command overrides them
if ( if (
command.whitelistedGuilds === undefined && command.whitelistedGuilds === undefined &&
category?.whitelistedGuilds !== undefined && category?.whitelistedGuilds !== undefined &&
msg.guild !== undefined && msg.guild !== undefined &&
category.whitelistedGuilds.includes(msg.guild.id) === false category.whitelistedGuilds.includes(msg.guild.id) === false
) )
return return
if ( if (
command.whitelistedGuilds !== undefined && command.whitelistedGuilds !== undefined &&
msg.guild !== undefined && msg.guild !== undefined &&
command.whitelistedGuilds.includes(msg.guild.id) === false command.whitelistedGuilds.includes(msg.guild.id) === false
) )
return return
// Checks for Channel Whitelist // Checks for Channel Whitelist
if ( if (
command.whitelistedChannels === undefined && command.whitelistedChannels === undefined &&
category?.whitelistedChannels !== undefined && category?.whitelistedChannels !== undefined &&
category.whitelistedChannels.includes(msg.channel.id) === false category.whitelistedChannels.includes(msg.channel.id) === false
) )
return return
if ( if (
command.whitelistedChannels !== undefined && command.whitelistedChannels !== undefined &&
command.whitelistedChannels.includes(msg.channel.id) === false command.whitelistedChannels.includes(msg.channel.id) === false
) )
return return
// Checks for Users Whitelist // Checks for Users Whitelist
if ( if (
command.whitelistedUsers === undefined && command.whitelistedUsers === undefined &&
category?.whitelistedUsers !== undefined && category?.whitelistedUsers !== undefined &&
category.whitelistedUsers.includes(msg.author.id) === false category.whitelistedUsers.includes(msg.author.id) === false
) )
return return
if ( if (
command.whitelistedUsers !== undefined && command.whitelistedUsers !== undefined &&
command.whitelistedUsers.includes(msg.author.id) === false command.whitelistedUsers.includes(msg.author.id) === false
) )
return return
const ctx: CommandContext = { const ctx: CommandContext = {
client: this, client: this,
name: parsed.name, name: parsed.name,
prefix, prefix,
args: parsed.args, args: parsed.args,
argString: parsed.argString, argString: parsed.argString,
message: msg, message: msg,
author: msg.author, author: msg.author,
command, command,
channel: msg.channel, channel: msg.channel,
guild: msg.guild, guild: msg.guild
} }
// In these checks too, Command overrides Category if present // In these checks too, Command overrides Category if present
// Check if Command is only for Owners // Check if Command is only for Owners
if ( if (
(command.ownerOnly !== undefined || category === undefined (command.ownerOnly !== undefined || category === undefined
? command.ownerOnly ? command.ownerOnly
: category.ownerOnly) === true && : category.ownerOnly) === true &&
!this.owners.includes(msg.author.id) !this.owners.includes(msg.author.id)
) )
return this.emit('commandOwnerOnly', ctx, command) return this.emit('commandOwnerOnly', ctx, command)
// Check if Command is only for Guild // Check if Command is only for Guild
if ( if (
(command.guildOnly !== undefined || category === undefined (command.guildOnly !== undefined || category === undefined
? command.guildOnly ? command.guildOnly
: category.guildOnly) === true && : category.guildOnly) === true &&
msg.guild === undefined msg.guild === undefined
) )
return this.emit('commandGuildOnly', ctx, command) return this.emit('commandGuildOnly', ctx, command)
// Check if Command is only for DMs // Check if Command is only for DMs
if ( if (
(command.dmOnly !== undefined || category === undefined (command.dmOnly !== undefined || category === undefined
? command.dmOnly ? command.dmOnly
: category.dmOnly) === true && : category.dmOnly) === true &&
msg.guild !== undefined msg.guild !== undefined
) )
return this.emit('commandDmOnly', ctx, command) return this.emit('commandDmOnly', ctx, command)
const allPermissions = const allPermissions =
command.permissions !== undefined command.permissions !== undefined
? command.permissions ? command.permissions
: category?.permissions : category?.permissions
if ( if (
(command.botPermissions !== undefined || (command.botPermissions !== undefined ||
category?.permissions !== undefined) && category?.permissions !== undefined) &&
msg.guild !== undefined msg.guild !== undefined
) { ) {
// TODO: Check Overwrites too // TODO: Check Overwrites too
const me = await msg.guild.me() const me = await msg.guild.me()
const missing: string[] = [] const missing: string[] = []
let permissions = let permissions =
command.botPermissions === undefined command.botPermissions === undefined
? category?.permissions ? category?.permissions
: command.botPermissions : command.botPermissions
if (permissions !== undefined) { if (permissions !== undefined) {
if (typeof permissions === 'string') permissions = [permissions] if (typeof permissions === 'string') permissions = [permissions]
if (allPermissions !== undefined) if (allPermissions !== undefined)
permissions = [...new Set(...permissions, ...allPermissions)] permissions = [...new Set(...permissions, ...allPermissions)]
for (const perm of permissions) { for (const perm of permissions) {
if (me.permissions.has(perm) === false) missing.push(perm) if (me.permissions.has(perm) === false) missing.push(perm)
} }
if (missing.length !== 0) if (missing.length !== 0)
return this.emit( return this.emit(
'commandBotMissingPermissions', 'commandBotMissingPermissions',
ctx, ctx,
command, command,
missing missing
) )
} }
} }
if ( if (
(command.userPermissions !== undefined || (command.userPermissions !== undefined ||
category?.userPermissions !== undefined) && category?.userPermissions !== undefined) &&
msg.guild !== undefined msg.guild !== undefined
) { ) {
let permissions = let permissions =
command.userPermissions !== undefined command.userPermissions !== undefined
? command.userPermissions ? command.userPermissions
: category?.userPermissions : category?.userPermissions
if (permissions !== undefined) { if (permissions !== undefined) {
if (typeof permissions === 'string') permissions = [permissions] if (typeof permissions === 'string') permissions = [permissions]
if (allPermissions !== undefined) if (allPermissions !== undefined)
permissions = [...new Set(...permissions, ...allPermissions)] permissions = [...new Set(...permissions, ...allPermissions)]
const missing: string[] = [] const missing: string[] = []
for (const perm of permissions) { for (const perm of permissions) {
const has = msg.member?.permissions.has(perm) const has = msg.member?.permissions.has(perm)
if (has !== true) missing.push(perm) if (has !== true) missing.push(perm)
} }
if (missing.length !== 0) if (missing.length !== 0)
return this.emit( return this.emit(
'commandUserMissingPermissions', 'commandUserMissingPermissions',
command, command,
missing, missing,
ctx ctx
) )
} }
} }
if (command.args !== undefined) { if (command.args !== undefined) {
if (typeof command.args === 'boolean' && parsed.args.length === 0) if (typeof command.args === 'boolean' && parsed.args.length === 0)
return this.emit('commandMissingArgs', ctx, command) return this.emit('commandMissingArgs', ctx, command)
else if ( else if (
typeof command.args === 'number' && typeof command.args === 'number' &&
parsed.args.length < command.args parsed.args.length < command.args
) )
this.emit('commandMissingArgs', ctx, command) this.emit('commandMissingArgs', ctx, command)
} }
try { try {
this.emit('commandUsed', ctx, command) this.emit('commandUsed', ctx, command)
const beforeExecute = await awaitSync(command.beforeExecute(ctx)) const beforeExecute = await awaitSync(command.beforeExecute(ctx))
if (beforeExecute === false) return if (beforeExecute === false) return
const result = await awaitSync(command.execute(ctx)) const result = await awaitSync(command.execute(ctx))
command.afterExecute(ctx, result) command.afterExecute(ctx, result)
} catch (e) { } catch (e) {
this.emit('commandError', command, ctx, e) this.emit('commandError', command, ctx, e)
} }
} }
} }

View File

@ -1,6 +1,6 @@
import { Collection } from "../utils/collection.ts"; import { Collection } from '../utils/collection.ts'
import { Command } from "./command.ts"; import { Command } from './command.ts'
import { CommandClient } from "./commandClient.ts"; import { CommandClient } from './commandClient.ts'
export type ExtensionEventCallback = (ext: Extension, ...args: any[]) => any export type ExtensionEventCallback = (ext: Extension, ...args: any[]) => any
@ -12,7 +12,9 @@ export class ExtensionCommands {
} }
get list(): Collection<string, Command> { get list(): Collection<string, Command> {
return this.extension.client.commands.list.filter(c => c.extension?.name === this.extension.name) return this.extension.client.commands.list.filter(
(c) => c.extension?.name === this.extension.name
)
} }
get(cmd: string): Command | undefined { get(cmd: string): Command | undefined {
@ -31,9 +33,15 @@ export class ExtensionCommands {
} }
delete(cmd: Command | string): boolean { delete(cmd: Command | string): boolean {
const find = this.extension.client.commands.find(typeof cmd === 'string' ? cmd : cmd.name) const find = this.extension.client.commands.find(
typeof cmd === 'string' ? cmd : cmd.name
)
if (find === undefined) return false if (find === undefined) return false
if (find.extension !== undefined && find.extension.name !== this.extension.name) return false if (
find.extension !== undefined &&
find.extension.name !== this.extension.name
)
return false
else return this.extension.client.commands.delete(find) else return this.extension.client.commands.delete(find)
} }
@ -61,7 +69,7 @@ export class Extension {
const fn = (...args: any[]): any => { const fn = (...args: any[]): any => {
// eslint-disable-next-line standard/no-callback-literal // eslint-disable-next-line standard/no-callback-literal
cb(this, ...args) cb(this, ...args)
}; }
this.client.on(event, fn) this.client.on(event, fn)
this.events[event] = fn this.events[event] = fn
return true return true
@ -91,7 +99,8 @@ export class ExtensionsManager {
load(ext: Extension | typeof Extension): void { load(ext: Extension | typeof Extension): void {
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
if (!(ext instanceof Extension)) ext = new ext(this.client) if (!(ext instanceof Extension)) ext = new ext(this.client)
if (this.exists(ext.name)) throw new Error(`Extension with name '${ext.name}' already exists`) if (this.exists(ext.name))
throw new Error(`Extension with name '${ext.name}' already exists`)
this.list.set(ext.name, ext) this.list.set(ext.name, ext)
ext.load() ext.load()
} }
@ -109,4 +118,4 @@ export class ExtensionsManager {
extension.unload() extension.unload()
return this.list.delete(name) return this.list.delete(name)
} }
} }

View File

@ -22,7 +22,7 @@ export enum HttpResponseCode {
NotFound = 404, NotFound = 404,
MethodNotAllowed = 405, MethodNotAllowed = 405,
TooManyRequests = 429, TooManyRequests = 429,
GatewayUnavailable = 502, GatewayUnavailable = 502
} }
export interface RequestHeaders { export interface RequestHeaders {
@ -109,7 +109,7 @@ export class RESTManager {
if (result?.rateLimited !== undefined) { if (result?.rateLimited !== undefined) {
this.queue({ this.queue({
...request, ...request,
bucket: result.bucket ?? request.bucket, bucket: result.bucket ?? request.bucket
}) })
} }
} }
@ -121,7 +121,7 @@ export class RESTManager {
if (result?.rateLimited !== undefined) { if (result?.rateLimited !== undefined) {
this.queue({ this.queue({
...request, ...request,
bucket: result.bucket ?? request.bucket, bucket: result.bucket ?? request.bucket
}) })
} }
} }
@ -141,7 +141,7 @@ export class RESTManager {
prepare(body: any, method: RequestMethods): { [key: string]: any } { prepare(body: any, method: RequestMethods): { [key: string]: any } {
const headers: RequestHeaders = { const headers: RequestHeaders = {
'User-Agent': `DiscordBot (harmony, https://github.com/harmony-org/harmony)`, 'User-Agent': `DiscordBot (harmony, https://github.com/harmony-org/harmony)`
} }
if (this.client !== undefined) if (this.client !== undefined)
@ -168,7 +168,7 @@ export class RESTManager {
const data: { [name: string]: any } = { const data: { [name: string]: any } = {
headers, headers,
body: body?.file ?? JSON.stringify(body), body: body?.file ?? JSON.stringify(body),
method: method.toUpperCase(), method: method.toUpperCase()
} }
if (this.client?.bot === false) { if (this.client?.bot === false) {
@ -222,14 +222,14 @@ export class RESTManager {
this.rateLimits.set(url, { this.rateLimits.set(url, {
url, url,
resetAt: Number(resetAt) * 1000, resetAt: Number(resetAt) * 1000,
bucket, bucket
}) })
if (bucket !== null) { if (bucket !== null) {
this.rateLimits.set(bucket, { this.rateLimits.set(bucket, {
url, url,
resetAt: Number(resetAt) * 1000, resetAt: Number(resetAt) * 1000,
bucket, bucket
}) })
} }
} }
@ -242,14 +242,14 @@ export class RESTManager {
this.rateLimits.set('global', { this.rateLimits.set('global', {
url: 'global', url: 'global',
resetAt: reset, resetAt: reset,
bucket, bucket
}) })
if (bucket !== null) { if (bucket !== null) {
this.rateLimits.set(bucket, { this.rateLimits.set(bucket, {
url: 'global', url: 'global',
resetAt: reset, resetAt: reset,
bucket, bucket
}) })
} }
} }
@ -286,7 +286,7 @@ export class RESTManager {
url: response.url, url: response.url,
status, status,
method: data.method, method: data.method,
body: data.body, body: data.body
} }
if (body !== undefined) error = Object.assign(error, body) if (body !== undefined) error = Object.assign(error, body)
@ -295,7 +295,7 @@ export class RESTManager {
HttpResponseCode.BadRequest, HttpResponseCode.BadRequest,
HttpResponseCode.NotFound, HttpResponseCode.NotFound,
HttpResponseCode.Forbidden, HttpResponseCode.Forbidden,
HttpResponseCode.MethodNotAllowed, HttpResponseCode.MethodNotAllowed
].includes(status) ].includes(status)
) { ) {
throw new DiscordAPIError(Deno.inspect(error)) throw new DiscordAPIError(Deno.inspect(error))
@ -320,7 +320,7 @@ export class RESTManager {
return { return {
rateLimited: rateLimitResetIn, rateLimited: rateLimitResetIn,
before: true, before: true,
bucket, bucket
} }
} }
@ -367,7 +367,7 @@ export class RESTManager {
return { return {
rateLimited: json.retry_after, rateLimited: json.retry_after,
before: false, before: false,
bucket: bucketFromHeaders, bucket: bucketFromHeaders
} }
} }
return resolve(rawResponse === true ? { response, body: json } : json) return resolve(rawResponse === true ? { response, body: json } : json)
@ -379,7 +379,7 @@ export class RESTManager {
this.queue({ this.queue({
onComplete, onComplete,
bucket, bucket,
url, url
}) })
if (!this.processing) { if (!this.processing) {
this.processing = true this.processing = true

View File

@ -1 +1 @@
// TODO: write code // TODO: write code

View File

@ -1,26 +1,26 @@
import { Guild } from "../structures/guild.ts" import { Guild } from '../structures/guild.ts'
import { VoiceChannel } from "../structures/guildVoiceChannel.ts" import { VoiceChannel } from '../structures/guildVoiceChannel.ts'
import { Client } from './client.ts' import { Client } from './client.ts'
export interface VoiceOptions { export interface VoiceOptions {
guild: Guild, guild: Guild
channel: VoiceChannel channel: VoiceChannel
} }
export class VoiceClient { export class VoiceClient {
client: Client client: Client
ws?: WebSocket ws?: WebSocket
guild: Guild guild: Guild
channel: VoiceChannel channel: VoiceChannel
constructor(client: Client, options: VoiceOptions) { constructor(client: Client, options: VoiceOptions) {
this.client = client this.client = client
this.guild = options.guild this.guild = options.guild
this.channel = options.channel this.channel = options.channel
} }
async connect(): Promise<VoiceClient> { async connect(): Promise<VoiceClient> {
// TODO(DjDeveloperr): Actually understand what the hell docs say // TODO(DjDeveloperr): Actually understand what the hell docs say
return this return this
} }
} }

View File

@ -1,24 +1,24 @@
import { Client } from "../models/client.ts"; import { Client } from '../models/client.ts'
import { ApplicationPayload } from "../types/application.ts"; import { ApplicationPayload } from '../types/application.ts'
import { Base } from "./base.ts"; import { Base } from './base.ts'
import { User } from "./user.ts"; import { User } from './user.ts'
export class Application extends Base { export class Application extends Base {
id: string id: string
name: string name: string
icon: string icon: string
description: string description: string
summary: string summary: string
bot?: User bot?: User
constructor(client: Client, data: ApplicationPayload) { constructor(client: Client, data: ApplicationPayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.name = data.name this.name = data.name
this.icon = data.icon this.icon = data.icon
this.description = data.description this.description = data.description
this.summary = data.summary this.summary = data.summary
this.bot = data.bot !== undefined ? new User(client, data.bot) : undefined this.bot = data.bot !== undefined ? new User(client, data.bot) : undefined
} }
} }

View File

@ -13,18 +13,21 @@ export class Base {
static useCache?: boolean = true static useCache?: boolean = true
static restFunc?: (...restURLfuncArgs: string[]) => string static restFunc?: (...restURLfuncArgs: string[]) => string
constructor (client: Client, _data?: any) { constructor(client: Client, _data?: any) {
this.client = client this.client = client
} }
static async autoInit ( static async autoInit(
client: Client, client: Client,
{ useCache, endpoint, restURLfuncArgs }: IInit { useCache, endpoint, restURLfuncArgs }: IInit
): Promise<any> { ): Promise<any> {
this.useCache = useCache this.useCache = useCache
const cacheID = restURLfuncArgs.join(':') const cacheID = restURLfuncArgs.join(':')
if (this.useCache !== undefined) { if (this.useCache !== undefined) {
const cached = await client.cache.get(this.cacheName ?? this.name, cacheID) const cached = await client.cache.get(
this.cacheName ?? this.name,
cacheID
)
if (cached !== undefined) { if (cached !== undefined) {
return cached return cached
} }
@ -35,7 +38,7 @@ export class Base {
return new this(client, jsonParsed) return new this(client, jsonParsed)
} }
async refreshFromAPI ( async refreshFromAPI(
client: Client, client: Client,
{ endpoint, restURLfuncArgs }: IInit { endpoint, restURLfuncArgs }: IInit
): Promise<this> { ): Promise<this> {
@ -48,13 +51,13 @@ export class Base {
return oldOne return oldOne
} }
refreshFromData (data: { [k: string]: any }): this { refreshFromData(data: { [k: string]: any }): this {
const oldOne = Object.assign(Object.create(this), this) const oldOne = Object.assign(Object.create(this), this)
this.readFromData(data) this.readFromData(data)
return oldOne return oldOne
} }
protected readFromData (data: { [k: string]: any }): void {} protected readFromData(data: { [k: string]: any }): void {}
// toJSON() {} // toJSON() {}
} }

View File

@ -6,11 +6,11 @@ export class Channel extends Base {
type: ChannelTypes type: ChannelTypes
id: string id: string
static cacheName = 'channel' static cacheName = 'channel'
get mention (): string { get mention(): string {
return `<#${this.id}>` return `<#${this.id}>`
} }
constructor (client: Client, data: ChannelPayload) { constructor(client: Client, data: ChannelPayload) {
super(client, data) super(client, data)
this.type = data.type this.type = data.type
this.id = data.id this.id = data.id
@ -18,7 +18,7 @@ export class Channel extends Base {
// this.client.channels.set(this.id, data) // this.client.channels.set(this.id, data)
} }
protected readFromData (data: ChannelPayload): void { protected readFromData(data: ChannelPayload): void {
super.readFromData(data) super.readFromData(data)
this.type = data.type ?? this.type this.type = data.type ?? this.type
this.id = data.id ?? this.id this.id = data.id ?? this.id

View File

@ -6,12 +6,12 @@ import { TextChannel } from './textChannel.ts'
export class DMChannel extends TextChannel { export class DMChannel extends TextChannel {
recipients: UserPayload[] recipients: UserPayload[]
constructor (client: Client, data: DMChannelPayload) { constructor(client: Client, data: DMChannelPayload) {
super(client, data) super(client, data)
this.recipients = data.recipients this.recipients = data.recipients
} }
protected readFromData (data: DMChannelPayload): void { protected readFromData(data: DMChannelPayload): void {
super.readFromData(data) super.readFromData(data)
this.recipients = data.recipients ?? this.recipients this.recipients = data.recipients ?? this.recipients
} }

View File

@ -25,7 +25,7 @@ export class Embed {
author?: EmbedAuthor author?: EmbedAuthor
fields?: EmbedField[] fields?: EmbedField[]
constructor (data?: EmbedPayload) { constructor(data?: EmbedPayload) {
this.title = data?.title this.title = data?.title
this.type = data?.type this.type = data?.type
this.description = data?.description this.description = data?.description
@ -42,7 +42,7 @@ export class Embed {
} }
// khk4912 // khk4912
toJSON (): EmbedPayload { toJSON(): EmbedPayload {
return { return {
title: this.title, title: this.title,
type: this.type, type: this.type,
@ -60,72 +60,72 @@ export class Embed {
} }
} }
setTitle (title: string): Embed { setTitle(title: string): Embed {
this.title = title this.title = title
return this return this
} }
setDescription (description: string): Embed { setDescription(description: string): Embed {
this.description = description this.description = description
return this return this
} }
setType (type: EmbedTypes): Embed { setType(type: EmbedTypes): Embed {
this.type = type this.type = type
return this return this
} }
setURL (url: string): Embed { setURL(url: string): Embed {
this.url = url this.url = url
return this return this
} }
setTimestamp (timestamp: string): Embed { setTimestamp(timestamp: string): Embed {
this.timestamp = timestamp this.timestamp = timestamp
return this return this
} }
setColor (hex: number): Embed { setColor(hex: number): Embed {
this.color = hex this.color = hex
return this return this
} }
setFooter (footer: EmbedFooter): Embed { setFooter(footer: EmbedFooter): Embed {
this.footer = footer this.footer = footer
return this return this
} }
setImage (image: EmbedImage): Embed { setImage(image: EmbedImage): Embed {
this.image = image this.image = image
return this return this
} }
setThumbnail (thumbnail: EmbedThumbnail): Embed { setThumbnail(thumbnail: EmbedThumbnail): Embed {
this.thumbnail = thumbnail this.thumbnail = thumbnail
return this return this
} }
setVideo (video: EmbedVideo): Embed { setVideo(video: EmbedVideo): Embed {
this.video = video this.video = video
return this return this
} }
setProvider (provider: EmbedProvider): Embed { setProvider(provider: EmbedProvider): Embed {
this.provider = provider this.provider = provider
return this return this
} }
setAuthor (author: EmbedAuthor): Embed { setAuthor(author: EmbedAuthor): Embed {
this.author = author this.author = author
return this return this
} }
setFields (fields: EmbedField[]): Embed { setFields(fields: EmbedField[]): Embed {
this.fields = fields this.fields = fields
return this return this
} }
addField (name: string, value: string, inline?: boolean): Embed { addField(name: string, value: string, inline?: boolean): Embed {
if (this.fields === undefined) { if (this.fields === undefined) {
this.fields = [ this.fields = [
{ {

View File

@ -16,7 +16,7 @@ export class Emoji extends Base {
animated?: boolean animated?: boolean
available?: boolean available?: boolean
get getEmojiString (): string { get getEmojiString(): string {
if (this.animated === false) { if (this.animated === false) {
return `<:${this.name}:${this.id}>` return `<:${this.name}:${this.id}>`
} else return `<a:${this.name}:${this.id}>` } else return `<a:${this.name}:${this.id}>`
@ -26,7 +26,7 @@ export class Emoji extends Base {
return this.getEmojiString return this.getEmojiString
} }
constructor (client: Client, data: EmojiPayload) { constructor(client: Client, data: EmojiPayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.name = data.name this.name = data.name
@ -38,7 +38,7 @@ export class Emoji extends Base {
this.available = data.available this.available = data.available
} }
protected readFromData (data: EmojiPayload): void { protected readFromData(data: EmojiPayload): void {
super.readFromData(data) super.readFromData(data)
this.id = data.id ?? this.id this.id = data.id ?? this.id
this.name = data.name ?? this.name this.name = data.name ?? this.name
@ -51,7 +51,7 @@ export class Emoji extends Base {
User.autoInit(this.client, { User.autoInit(this.client, {
endpoint: USER, endpoint: USER,
restURLfuncArgs: [data.user.id] restURLfuncArgs: [data.user.id]
}).then(user => (this.user = user)) }).then((user) => (this.user = user))
} }
} }
} }

View File

@ -7,7 +7,7 @@ export class GroupDMChannel extends Channel {
icon?: string icon?: string
ownerID: string ownerID: string
constructor (client: Client, data: GroupDMChannelPayload) { constructor(client: Client, data: GroupDMChannelPayload) {
super(client, data) super(client, data)
this.name = data.name this.name = data.name
@ -17,7 +17,7 @@ export class GroupDMChannel extends Channel {
// cache.set('groupchannel', this.id, this) // cache.set('groupchannel', this.id, this)
} }
protected readFromData (data: GroupDMChannelPayload): void { protected readFromData(data: GroupDMChannelPayload): void {
super.readFromData(data) super.readFromData(data)
this.name = data.name ?? this.name this.name = data.name ?? this.name
this.icon = data.icon ?? this.icon this.icon = data.icon ?? this.icon

View File

@ -1,377 +1,377 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { import {
GuildBanPayload, GuildBanPayload,
GuildFeatures, GuildFeatures,
GuildIntegrationPayload, GuildIntegrationPayload,
GuildPayload, GuildPayload,
IntegrationAccountPayload, IntegrationAccountPayload,
IntegrationExpireBehavior, IntegrationExpireBehavior
} from '../types/guild.ts' } from '../types/guild.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
import { RolesManager } from '../managers/roles.ts' import { RolesManager } from '../managers/roles.ts'
import { InviteManager } from '../managers/invites.ts' import { InviteManager } from '../managers/invites.ts'
import { GuildChannelsManager } from '../managers/guildChannels.ts' import { GuildChannelsManager } from '../managers/guildChannels.ts'
import { MembersManager } from '../managers/members.ts' import { MembersManager } from '../managers/members.ts'
import { Role } from './role.ts' import { Role } from './role.ts'
import { GuildEmojisManager } from '../managers/guildEmojis.ts' import { GuildEmojisManager } from '../managers/guildEmojis.ts'
import { Member } from './member.ts' import { Member } from './member.ts'
import { User } from './user.ts' import { User } from './user.ts'
import { Application } from './application.ts' import { Application } from './application.ts'
import { GUILD_BAN, GUILD_BANS, GUILD_INTEGRATIONS } from '../types/endpoint.ts' import { GUILD_BAN, GUILD_BANS, GUILD_INTEGRATIONS } from '../types/endpoint.ts'
import { GuildVoiceStatesManager } from '../managers/guildVoiceStates.ts' import { GuildVoiceStatesManager } from '../managers/guildVoiceStates.ts'
import { RequestMembersOptions } from '../gateway/index.ts' import { RequestMembersOptions } from '../gateway/index.ts'
import { GuildPresencesManager } from '../managers/presences.ts' import { GuildPresencesManager } from '../managers/presences.ts'
export class GuildBan extends Base { export class GuildBan extends Base {
guild: Guild guild: Guild
reason?: string reason?: string
user: User user: User
constructor(client: Client, data: GuildBanPayload, guild: Guild) { constructor(client: Client, data: GuildBanPayload, guild: Guild) {
super(client, data) super(client, data)
this.guild = guild this.guild = guild
this.reason = data.reason === null ? undefined : data.reason this.reason = data.reason === null ? undefined : data.reason
this.user = new User(client, data.user) this.user = new User(client, data.user)
} }
} }
export class GuildBans { export class GuildBans {
client: Client client: Client
guild: Guild guild: Guild
constructor(client: Client, guild: Guild) { constructor(client: Client, guild: Guild) {
this.client = client this.client = client
this.guild = guild this.guild = guild
} }
/** /**
* Get all bans in the Guild. * Get all bans in the Guild.
*/ */
async all(): Promise<GuildBan[]> { async all(): Promise<GuildBan[]> {
const res = await this.client.rest.get(GUILD_BANS(this.guild.id)) const res = await this.client.rest.get(GUILD_BANS(this.guild.id))
if (typeof res !== 'object' || !Array.isArray(res)) if (typeof res !== 'object' || !Array.isArray(res))
throw new Error('Failed to fetch Guild Bans') throw new Error('Failed to fetch Guild Bans')
const bans = (res as GuildBanPayload[]).map( const bans = (res as GuildBanPayload[]).map(
(ban) => new GuildBan(this.client, ban, this.guild) (ban) => new GuildBan(this.client, ban, this.guild)
) )
return bans return bans
} }
/** /**
* Get ban details of a User if any. * Get ban details of a User if any.
* @param user User to get ban of, ID or User object. * @param user User to get ban of, ID or User object.
*/ */
async get(user: string | User): Promise<GuildBan> { async get(user: string | User): Promise<GuildBan> {
const res = await this.client.rest.get( const res = await this.client.rest.get(
GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id) GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id)
) )
if (typeof res !== 'object') throw new Error('Failed to fetch Guild Ban') if (typeof res !== 'object') throw new Error('Failed to fetch Guild Ban')
return new GuildBan(this.client, res, this.guild) return new GuildBan(this.client, res, this.guild)
} }
/** /**
* Ban a User. * Ban a User.
* @param user User to ban, ID or User object. * @param user User to ban, ID or User object.
* @param reason Reason for the Ban. * @param reason Reason for the Ban.
* @param deleteMessagesDays Delete Old Messages? If yes, how much days. * @param deleteMessagesDays Delete Old Messages? If yes, how much days.
*/ */
async add( async add(
user: string | User, user: string | User,
reason?: string, reason?: string,
deleteMessagesDays?: number deleteMessagesDays?: number
): Promise<void> { ): Promise<void> {
const res = await this.client.rest.put( const res = await this.client.rest.put(
GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id), GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id),
{ {
reason, reason,
delete_message_days: deleteMessagesDays, delete_message_days: deleteMessagesDays
}, },
undefined, undefined,
null, null,
true true
) )
if (res.status !== 204) throw new Error('Failed to Add Guild Ban') if (res.status !== 204) throw new Error('Failed to Add Guild Ban')
} }
/** /**
* Unban (remove ban from) a User. * Unban (remove ban from) a User.
* @param user User to unban, ID or User object. * @param user User to unban, ID or User object.
*/ */
async remove(user: string | User): Promise<boolean> { async remove(user: string | User): Promise<boolean> {
const res = await this.client.rest.delete( const res = await this.client.rest.delete(
GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id), GUILD_BAN(this.guild.id, typeof user === 'string' ? user : user.id),
undefined, undefined,
undefined, undefined,
null, null,
true true
) )
if (res.status !== 204) return false if (res.status !== 204) return false
else return true else return true
} }
} }
export class Guild extends Base { export class Guild extends Base {
id: string id: string
name?: string name?: string
icon?: string icon?: string
iconHash?: string iconHash?: string
splash?: string splash?: string
discoverySplash?: string discoverySplash?: string
owner?: boolean owner?: boolean
ownerID?: string ownerID?: string
permissions?: string permissions?: string
region?: string region?: string
afkChannelID?: string afkChannelID?: string
afkTimeout?: number afkTimeout?: number
widgetEnabled?: boolean widgetEnabled?: boolean
widgetChannelID?: string widgetChannelID?: string
verificationLevel?: string verificationLevel?: string
defaultMessageNotifications?: string defaultMessageNotifications?: string
explicitContentFilter?: string explicitContentFilter?: string
roles: RolesManager roles: RolesManager
emojis: GuildEmojisManager emojis: GuildEmojisManager
invites: InviteManager invites: InviteManager
features?: GuildFeatures[] features?: GuildFeatures[]
mfaLevel?: string mfaLevel?: string
applicationID?: string applicationID?: string
systemChannelID?: string systemChannelID?: string
systemChannelFlags?: string systemChannelFlags?: string
rulesChannelID?: string rulesChannelID?: string
joinedAt?: string joinedAt?: string
large?: boolean large?: boolean
unavailable: boolean unavailable: boolean
memberCount?: number memberCount?: number
voiceStates: GuildVoiceStatesManager voiceStates: GuildVoiceStatesManager
members: MembersManager members: MembersManager
channels: GuildChannelsManager channels: GuildChannelsManager
presences: GuildPresencesManager presences: GuildPresencesManager
maxPresences?: number maxPresences?: number
maxMembers?: number maxMembers?: number
vanityURLCode?: string vanityURLCode?: string
description?: string description?: string
banner?: string banner?: string
premiumTier?: number premiumTier?: number
premiumSubscriptionCount?: number premiumSubscriptionCount?: number
preferredLocale?: string preferredLocale?: string
publicUpdatesChannelID?: string publicUpdatesChannelID?: string
maxVideoChannelUsers?: number maxVideoChannelUsers?: number
approximateNumberCount?: number approximateNumberCount?: number
approximatePresenceCount?: number approximatePresenceCount?: number
bans: GuildBans bans: GuildBans
constructor(client: Client, data: GuildPayload) { constructor(client: Client, data: GuildPayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.bans = new GuildBans(client, this) this.bans = new GuildBans(client, this)
this.unavailable = data.unavailable this.unavailable = data.unavailable
this.members = new MembersManager(this.client, this) this.members = new MembersManager(this.client, this)
this.voiceStates = new GuildVoiceStatesManager(client, this) this.voiceStates = new GuildVoiceStatesManager(client, this)
this.presences = new GuildPresencesManager(client, this) this.presences = new GuildPresencesManager(client, this)
this.channels = new GuildChannelsManager( this.channels = new GuildChannelsManager(
this.client, this.client,
this.client.channels, this.client.channels,
this this
) )
this.roles = new RolesManager(this.client, this) this.roles = new RolesManager(this.client, this)
this.emojis = new GuildEmojisManager(this.client, this.client.emojis, this) this.emojis = new GuildEmojisManager(this.client, this.client.emojis, this)
this.invites = new InviteManager(this.client, this) this.invites = new InviteManager(this.client, this)
if (!this.unavailable) { if (!this.unavailable) {
this.name = data.name this.name = data.name
this.icon = data.icon this.icon = data.icon
this.iconHash = data.icon_hash this.iconHash = data.icon_hash
this.splash = data.splash this.splash = data.splash
this.discoverySplash = data.discovery_splash this.discoverySplash = data.discovery_splash
this.owner = data.owner this.owner = data.owner
this.ownerID = data.owner_id this.ownerID = data.owner_id
this.permissions = data.permissions this.permissions = data.permissions
this.region = data.region this.region = data.region
this.afkTimeout = data.afk_timeout this.afkTimeout = data.afk_timeout
this.afkChannelID = data.afk_channel_id this.afkChannelID = data.afk_channel_id
this.widgetEnabled = data.widget_enabled this.widgetEnabled = data.widget_enabled
this.widgetChannelID = data.widget_channel_id this.widgetChannelID = data.widget_channel_id
this.verificationLevel = data.verification_level this.verificationLevel = data.verification_level
this.defaultMessageNotifications = data.default_message_notifications this.defaultMessageNotifications = data.default_message_notifications
this.explicitContentFilter = data.explicit_content_filter this.explicitContentFilter = data.explicit_content_filter
this.features = data.features this.features = data.features
this.mfaLevel = data.mfa_level this.mfaLevel = data.mfa_level
this.systemChannelID = data.system_channel_id this.systemChannelID = data.system_channel_id
this.systemChannelFlags = data.system_channel_flags this.systemChannelFlags = data.system_channel_flags
this.rulesChannelID = data.rules_channel_id this.rulesChannelID = data.rules_channel_id
this.joinedAt = data.joined_at this.joinedAt = data.joined_at
this.large = data.large this.large = data.large
this.memberCount = data.member_count this.memberCount = data.member_count
this.maxPresences = data.max_presences this.maxPresences = data.max_presences
this.maxMembers = data.max_members this.maxMembers = data.max_members
this.vanityURLCode = data.vanity_url_code this.vanityURLCode = data.vanity_url_code
this.description = data.description this.description = data.description
this.banner = data.banner this.banner = data.banner
this.premiumTier = data.premium_tier this.premiumTier = data.premium_tier
this.premiumSubscriptionCount = data.premium_subscription_count this.premiumSubscriptionCount = data.premium_subscription_count
this.preferredLocale = data.preferred_locale this.preferredLocale = data.preferred_locale
this.publicUpdatesChannelID = data.public_updates_channel_id this.publicUpdatesChannelID = data.public_updates_channel_id
this.maxVideoChannelUsers = data.max_video_channel_users this.maxVideoChannelUsers = data.max_video_channel_users
this.approximateNumberCount = data.approximate_number_count this.approximateNumberCount = data.approximate_number_count
this.approximatePresenceCount = data.approximate_presence_count this.approximatePresenceCount = data.approximate_presence_count
} }
} }
protected readFromData(data: GuildPayload): void { protected readFromData(data: GuildPayload): void {
super.readFromData(data) super.readFromData(data)
this.id = data.id ?? this.id this.id = data.id ?? this.id
this.unavailable = data.unavailable ?? this.unavailable this.unavailable = data.unavailable ?? this.unavailable
if (!this.unavailable) { if (!this.unavailable) {
this.name = data.name ?? this.name this.name = data.name ?? this.name
this.icon = data.icon ?? this.icon this.icon = data.icon ?? this.icon
this.iconHash = data.icon_hash ?? this.iconHash this.iconHash = data.icon_hash ?? this.iconHash
this.splash = data.splash ?? this.splash this.splash = data.splash ?? this.splash
this.discoverySplash = data.discovery_splash ?? this.discoverySplash this.discoverySplash = data.discovery_splash ?? this.discoverySplash
this.owner = data.owner ?? this.owner this.owner = data.owner ?? this.owner
this.ownerID = data.owner_id ?? this.ownerID this.ownerID = data.owner_id ?? this.ownerID
this.permissions = data.permissions ?? this.permissions this.permissions = data.permissions ?? this.permissions
this.region = data.region ?? this.region this.region = data.region ?? this.region
this.afkTimeout = data.afk_timeout ?? this.afkTimeout this.afkTimeout = data.afk_timeout ?? this.afkTimeout
this.afkChannelID = data.afk_channel_id ?? this.afkChannelID this.afkChannelID = data.afk_channel_id ?? this.afkChannelID
this.widgetEnabled = data.widget_enabled ?? this.widgetEnabled this.widgetEnabled = data.widget_enabled ?? this.widgetEnabled
this.widgetChannelID = data.widget_channel_id ?? this.widgetChannelID this.widgetChannelID = data.widget_channel_id ?? this.widgetChannelID
this.verificationLevel = data.verification_level ?? this.verificationLevel this.verificationLevel = data.verification_level ?? this.verificationLevel
this.defaultMessageNotifications = this.defaultMessageNotifications =
data.default_message_notifications ?? this.defaultMessageNotifications data.default_message_notifications ?? this.defaultMessageNotifications
this.explicitContentFilter = this.explicitContentFilter =
data.explicit_content_filter ?? this.explicitContentFilter data.explicit_content_filter ?? this.explicitContentFilter
this.features = data.features ?? this.features this.features = data.features ?? this.features
this.mfaLevel = data.mfa_level ?? this.mfaLevel this.mfaLevel = data.mfa_level ?? this.mfaLevel
this.systemChannelID = data.system_channel_id ?? this.systemChannelID this.systemChannelID = data.system_channel_id ?? this.systemChannelID
this.systemChannelFlags = this.systemChannelFlags =
data.system_channel_flags ?? this.systemChannelFlags data.system_channel_flags ?? this.systemChannelFlags
this.rulesChannelID = data.rules_channel_id ?? this.rulesChannelID this.rulesChannelID = data.rules_channel_id ?? this.rulesChannelID
this.joinedAt = data.joined_at ?? this.joinedAt this.joinedAt = data.joined_at ?? this.joinedAt
this.large = data.large ?? this.large this.large = data.large ?? this.large
this.memberCount = data.member_count ?? this.memberCount this.memberCount = data.member_count ?? this.memberCount
this.maxPresences = data.max_presences ?? this.maxPresences this.maxPresences = data.max_presences ?? this.maxPresences
this.maxMembers = data.max_members ?? this.maxMembers this.maxMembers = data.max_members ?? this.maxMembers
this.vanityURLCode = data.vanity_url_code ?? this.vanityURLCode this.vanityURLCode = data.vanity_url_code ?? this.vanityURLCode
this.description = data.description ?? this.description this.description = data.description ?? this.description
this.banner = data.banner ?? this.banner this.banner = data.banner ?? this.banner
this.premiumTier = data.premium_tier ?? this.premiumTier this.premiumTier = data.premium_tier ?? this.premiumTier
this.premiumSubscriptionCount = this.premiumSubscriptionCount =
data.premium_subscription_count ?? this.premiumSubscriptionCount data.premium_subscription_count ?? this.premiumSubscriptionCount
this.preferredLocale = data.preferred_locale ?? this.preferredLocale this.preferredLocale = data.preferred_locale ?? this.preferredLocale
this.publicUpdatesChannelID = this.publicUpdatesChannelID =
data.public_updates_channel_id ?? this.publicUpdatesChannelID data.public_updates_channel_id ?? this.publicUpdatesChannelID
this.maxVideoChannelUsers = this.maxVideoChannelUsers =
data.max_video_channel_users ?? this.maxVideoChannelUsers data.max_video_channel_users ?? this.maxVideoChannelUsers
this.approximateNumberCount = this.approximateNumberCount =
data.approximate_number_count ?? this.approximateNumberCount data.approximate_number_count ?? this.approximateNumberCount
this.approximatePresenceCount = this.approximatePresenceCount =
data.approximate_presence_count ?? this.approximatePresenceCount data.approximate_presence_count ?? this.approximatePresenceCount
} }
} }
/** /**
* Get Everyone role of the Guild * Get Everyone role of the Guild
*/ */
async getEveryoneRole(): Promise<Role> { async getEveryoneRole(): Promise<Role> {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
return (await this.roles.get(this.id)) as Role return (await this.roles.get(this.id)) as Role
} }
/** /**
* Get current client's member in the Guild * Get current client's member in the Guild
*/ */
async me(): Promise<Member> { async me(): Promise<Member> {
const get = await this.members.get(this.client.user?.id as string) const get = await this.members.get(this.client.user?.id as string)
if (get === undefined) throw new Error('Guild#me is not cached') if (get === undefined) throw new Error('Guild#me is not cached')
return get return get
} }
/** /**
* Fetch Guild's Integrations (Webhooks, Bots, etc.) * Fetch Guild's Integrations (Webhooks, Bots, etc.)
*/ */
async fetchIntegrations(): Promise<GuildIntegration[]> { async fetchIntegrations(): Promise<GuildIntegration[]> {
const raw = (await this.client.rest.get( const raw = (await this.client.rest.get(
GUILD_INTEGRATIONS(this.id) GUILD_INTEGRATIONS(this.id)
)) as GuildIntegrationPayload[] )) as GuildIntegrationPayload[]
return raw.map((e) => new GuildIntegration(this.client, e)) return raw.map((e) => new GuildIntegration(this.client, e))
} }
/** /**
* Chunk the Guild Members, i.e. cache them. * Chunk the Guild Members, i.e. cache them.
* @param options Options regarding the Members Request * @param options Options regarding the Members Request
* @param wait Whether to wait for all Members to come before resolving Promise or not. * @param wait Whether to wait for all Members to come before resolving Promise or not.
* @param timeout Configurable timeout to cancel the wait to safely remove listener. * @param timeout Configurable timeout to cancel the wait to safely remove listener.
*/ */
async chunk( async chunk(
options: RequestMembersOptions, options: RequestMembersOptions,
wait: boolean = false, wait: boolean = false,
timeout: number = 60000 timeout: number = 60000
): Promise<Guild> { ): Promise<Guild> {
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
this.client.gateway?.requestMembers(this.id, options) this.client.gateway?.requestMembers(this.id, options)
if (!wait) return resolve(this) if (!wait) return resolve(this)
else { else {
let chunked = false let chunked = false
const listener = (guild: Guild): void => { const listener = (guild: Guild): void => {
if (guild.id === this.id) { if (guild.id === this.id) {
chunked = true chunked = true
this.client.removeListener('guildMembersChunked', listener) this.client.removeListener('guildMembersChunked', listener)
resolve(this) resolve(this)
} }
} }
this.client.on('guildMembersChunked', listener) this.client.on('guildMembersChunked', listener)
setTimeout(() => { setTimeout(() => {
if (!chunked) { if (!chunked) {
this.client.removeListener('guildMembersChunked', listener) this.client.removeListener('guildMembersChunked', listener)
} }
}, timeout) }, timeout)
} }
resolve(this) resolve(this)
}) })
} }
} }
export class GuildIntegration extends Base { export class GuildIntegration extends Base {
id: string id: string
name: string name: string
type: string type: string
enabled: boolean enabled: boolean
syncing?: boolean syncing?: boolean
roleID?: string roleID?: string
enableEmoticons?: boolean enableEmoticons?: boolean
expireBehaviour?: IntegrationExpireBehavior expireBehaviour?: IntegrationExpireBehavior
expireGracePeriod?: number expireGracePeriod?: number
user?: User user?: User
account: IntegrationAccountPayload account: IntegrationAccountPayload
syncedAt?: string // Actually a ISO Timestamp, but we parse in constructor' syncedAt?: string // Actually a ISO Timestamp, but we parse in constructor'
subscriberCount?: number subscriberCount?: number
revoked?: boolean revoked?: boolean
application?: Application application?: Application
constructor(client: Client, data: GuildIntegrationPayload) { constructor(client: Client, data: GuildIntegrationPayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.name = data.name this.name = data.name
this.type = data.type this.type = data.type
this.enabled = data.enabled this.enabled = data.enabled
this.syncing = data.syncing this.syncing = data.syncing
this.roleID = data.role_id this.roleID = data.role_id
this.enableEmoticons = data.enable_emoticons this.enableEmoticons = data.enable_emoticons
this.expireBehaviour = data.expire_behaviour this.expireBehaviour = data.expire_behaviour
this.expireGracePeriod = data.expire_grace_period this.expireGracePeriod = data.expire_grace_period
this.user = this.user =
data.user !== undefined ? new User(client, data.user) : undefined data.user !== undefined ? new User(client, data.user) : undefined
this.account = data.account this.account = data.account
this.syncedAt = data.synced_at this.syncedAt = data.synced_at
this.subscriberCount = data.subscriber_count this.subscriberCount = data.subscriber_count
this.revoked = data.revoked this.revoked = data.revoked
this.application = this.application =
data.application !== undefined data.application !== undefined
? new Application(client, data.application) ? new Application(client, data.application)
: undefined : undefined
} }
} }

View File

@ -1,9 +1,6 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Channel } from './channel.ts' import { Channel } from './channel.ts'
import { import { GuildChannelCategoryPayload, Overwrite } from '../types/channel.ts'
GuildChannelCategoryPayload,
Overwrite
} from '../types/channel.ts'
import { Guild } from './guild.ts' import { Guild } from './guild.ts'
export class CategoryChannel extends Channel { export class CategoryChannel extends Channel {
@ -15,7 +12,7 @@ export class CategoryChannel extends Channel {
guild: Guild guild: Guild
parentID?: string parentID?: string
constructor (client: Client, data: GuildChannelCategoryPayload, guild: Guild) { constructor(client: Client, data: GuildChannelCategoryPayload, guild: Guild) {
super(client, data) super(client, data)
this.guildID = data.guild_id this.guildID = data.guild_id
this.name = data.name this.name = data.name
@ -28,7 +25,7 @@ export class CategoryChannel extends Channel {
// cache.set('guildcategorychannel', this.id, this) // cache.set('guildcategorychannel', this.id, this)
} }
protected readFromData (data: GuildChannelCategoryPayload): void { protected readFromData(data: GuildChannelCategoryPayload): void {
super.readFromData(data) super.readFromData(data)
this.guildID = data.guild_id ?? this.guildID this.guildID = data.guild_id ?? this.guildID
this.name = data.name ?? this.name this.name = data.name ?? this.name

View File

@ -13,7 +13,7 @@ export class NewsChannel extends TextChannel {
parentID?: string parentID?: string
topic?: string topic?: string
constructor (client: Client, data: GuildNewsChannelPayload, guild: Guild) { constructor(client: Client, data: GuildNewsChannelPayload, guild: Guild) {
super(client, data) super(client, data)
this.guildID = data.guild_id this.guildID = data.guild_id
this.name = data.name this.name = data.name
@ -25,7 +25,7 @@ export class NewsChannel extends TextChannel {
this.topic = data.topic this.topic = data.topic
} }
protected readFromData (data: GuildNewsChannelPayload): void { protected readFromData(data: GuildNewsChannelPayload): void {
super.readFromData(data) super.readFromData(data)
this.guildID = data.guild_id ?? this.guildID this.guildID = data.guild_id ?? this.guildID
this.name = data.name ?? this.name this.name = data.name ?? this.name

View File

@ -14,7 +14,7 @@ export class VoiceChannel extends Channel {
nsfw: boolean nsfw: boolean
parentID?: string parentID?: string
constructor (client: Client, data: GuildVoiceChannelPayload, guild: Guild) { constructor(client: Client, data: GuildVoiceChannelPayload, guild: Guild) {
super(client, data) super(client, data)
this.bitrate = data.bitrate this.bitrate = data.bitrate
this.userLimit = data.user_limit this.userLimit = data.user_limit
@ -29,7 +29,7 @@ export class VoiceChannel extends Channel {
// cache.set('guildvoicechannel', this.id, this) // cache.set('guildvoicechannel', this.id, this)
} }
protected readFromData (data: GuildVoiceChannelPayload): void { protected readFromData(data: GuildVoiceChannelPayload): void {
super.readFromData(data) super.readFromData(data)
this.bitrate = data.bitrate ?? this.bitrate this.bitrate = data.bitrate ?? this.bitrate
this.userLimit = data.user_limit ?? this.userLimit this.userLimit = data.user_limit ?? this.userLimit

View File

@ -1,47 +1,47 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { ChannelPayload } from '../types/channel.ts' import { ChannelPayload } from '../types/channel.ts'
import { GuildPayload } from '../types/guild.ts' import { GuildPayload } from '../types/guild.ts'
import { InvitePayload } from '../types/invite.ts' import { InvitePayload } from '../types/invite.ts'
import { UserPayload } from '../types/user.ts' import { UserPayload } from '../types/user.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
export class Invite extends Base { export class Invite extends Base {
code: string code: string
guild?: GuildPayload guild?: GuildPayload
channel: ChannelPayload channel: ChannelPayload
inviter?: UserPayload inviter?: UserPayload
targetUser?: UserPayload targetUser?: UserPayload
targetUserType?: number targetUserType?: number
approximatePresenceCount?: number approximatePresenceCount?: number
approximateMemberCount?: number approximateMemberCount?: number
get link(): string { get link(): string {
return `https://discord.gg/${this.code}` return `https://discord.gg/${this.code}`
} }
constructor(client: Client, data: InvitePayload) { constructor(client: Client, data: InvitePayload) {
super(client) super(client)
this.code = data.code this.code = data.code
this.guild = data.guild this.guild = data.guild
this.channel = data.channel this.channel = data.channel
this.inviter = data.inviter this.inviter = data.inviter
this.targetUser = data.target_user this.targetUser = data.target_user
this.targetUserType = data.target_user_type this.targetUserType = data.target_user_type
this.approximateMemberCount = data.approximate_member_count this.approximateMemberCount = data.approximate_member_count
this.approximatePresenceCount = data.approximate_presence_count this.approximatePresenceCount = data.approximate_presence_count
} }
protected readFromData(data: InvitePayload): void { protected readFromData(data: InvitePayload): void {
super.readFromData(data) super.readFromData(data)
this.code = data.code ?? this.code this.code = data.code ?? this.code
this.guild = data.guild ?? this.guild this.guild = data.guild ?? this.guild
this.channel = data.channel ?? this.channel this.channel = data.channel ?? this.channel
this.inviter = data.inviter ?? this.inviter this.inviter = data.inviter ?? this.inviter
this.targetUser = data.target_user ?? this.targetUser this.targetUser = data.target_user ?? this.targetUser
this.targetUserType = data.target_user_type ?? this.targetUserType this.targetUserType = data.target_user_type ?? this.targetUserType
this.approximateMemberCount = this.approximateMemberCount =
data.approximate_member_count ?? this.approximateMemberCount data.approximate_member_count ?? this.approximateMemberCount
this.approximatePresenceCount = this.approximatePresenceCount =
data.approximate_presence_count ?? this.approximatePresenceCount data.approximate_presence_count ?? this.approximatePresenceCount
} }
} }

View File

@ -1,173 +1,173 @@
import { MemberRolesManager } from '../managers/memberRoles.ts' import { MemberRolesManager } from '../managers/memberRoles.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { GUILD_MEMBER } from '../types/endpoint.ts' import { GUILD_MEMBER } from '../types/endpoint.ts'
import { MemberPayload } from '../types/guild.ts' import { MemberPayload } from '../types/guild.ts'
import { Permissions } from '../utils/permissions.ts' import { Permissions } from '../utils/permissions.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 { Role } from './role.ts'
import { User } from './user.ts' import { User } from './user.ts'
export interface MemberData { export interface MemberData {
nick?: string | null nick?: string | null
roles?: Array<Role | string> roles?: Array<Role | string>
deaf?: boolean deaf?: boolean
mute?: boolean mute?: boolean
} }
export class Member extends Base { export class Member extends Base {
id: string id: string
user: User user: User
nick?: string nick?: string
roles: MemberRolesManager roles: MemberRolesManager
joinedAt: string joinedAt: string
premiumSince?: string premiumSince?: string
deaf: boolean deaf: boolean
mute: boolean mute: boolean
guild: Guild guild: Guild
permissions: Permissions permissions: Permissions
constructor( constructor(
client: Client, client: Client,
data: MemberPayload, data: MemberPayload,
user: User, user: User,
guild: Guild, guild: Guild,
perms?: Permissions perms?: Permissions
) { ) {
super(client) super(client)
this.id = data.user.id this.id = data.user.id
this.user = user this.user = user
this.nick = data.nick this.nick = data.nick
this.guild = guild this.guild = guild
this.roles = new MemberRolesManager(this.client, this.guild.roles, this) this.roles = new MemberRolesManager(this.client, this.guild.roles, this)
this.joinedAt = data.joined_at this.joinedAt = data.joined_at
this.premiumSince = data.premium_since this.premiumSince = data.premium_since
this.deaf = data.deaf this.deaf = data.deaf
this.mute = data.mute this.mute = data.mute
if (perms !== undefined) this.permissions = perms if (perms !== undefined) this.permissions = perms
else this.permissions = new Permissions(Permissions.DEFAULT) else this.permissions = new Permissions(Permissions.DEFAULT)
} }
get displayName(): string { get displayName(): string {
return this.nick !== undefined ? this.nick : this.user.username return this.nick !== undefined ? this.nick : this.user.username
} }
toString(): string { toString(): string {
return this.user.nickMention return this.user.nickMention
} }
protected readFromData(data: MemberPayload): void { protected readFromData(data: MemberPayload): void {
super.readFromData(data.user) super.readFromData(data.user)
this.nick = data.nick ?? this.nick this.nick = data.nick ?? this.nick
this.joinedAt = data.joined_at ?? this.joinedAt this.joinedAt = data.joined_at ?? this.joinedAt
this.premiumSince = data.premium_since ?? this.premiumSince this.premiumSince = data.premium_since ?? this.premiumSince
this.deaf = data.deaf ?? this.deaf this.deaf = data.deaf ?? this.deaf
this.mute = data.mute ?? this.mute this.mute = data.mute ?? this.mute
} }
/** /**
* Update the Member data in cache (and this object). * Update the Member data in cache (and this object).
*/ */
async fetch(): Promise<Member> { async fetch(): Promise<Member> {
const raw = await this.client.rest.get(this.id) const raw = await this.client.rest.get(this.id)
if (typeof raw !== 'object') throw new Error('Member not found') if (typeof raw !== 'object') throw new Error('Member not found')
await this.guild.members.set(this.id, raw) await this.guild.members.set(this.id, raw)
this.readFromData(raw) this.readFromData(raw)
return this return this
} }
/** /**
* Edit the Member * Edit the Member
* @param data Data to apply * @param data Data to apply
*/ */
async edit(data: MemberData): Promise<Member> { async edit(data: MemberData): Promise<Member> {
const payload = { const payload = {
nick: data.nick, nick: data.nick,
roles: data.roles?.map((e) => (typeof e === 'string' ? e : e.id)), roles: data.roles?.map((e) => (typeof e === 'string' ? e : e.id)),
deaf: data.deaf, deaf: data.deaf,
mute: data.mute, mute: data.mute
} }
const res = await this.client.rest.patch( const res = await this.client.rest.patch(
GUILD_MEMBER(this.guild.id, this.id), GUILD_MEMBER(this.guild.id, this.id),
payload, payload,
undefined, undefined,
null, null,
true true
) )
if (res.ok === true) { if (res.ok === true) {
if (data.nick !== undefined) if (data.nick !== undefined)
this.nick = data.nick === null ? undefined : data.nick this.nick = data.nick === null ? undefined : data.nick
if (data.deaf !== undefined) this.deaf = data.deaf if (data.deaf !== undefined) this.deaf = data.deaf
if (data.mute !== undefined) this.mute = data.mute if (data.mute !== undefined) this.mute = data.mute
} }
return this return this
} }
/** /**
* New nickname to set. If empty, nick is reset * New nickname to set. If empty, nick is reset
* @param nick New nickname * @param nick New nickname
*/ */
async setNickname(nick?: string): Promise<Member> { async setNickname(nick?: string): Promise<Member> {
return await this.edit({ return await this.edit({
nick: nick === undefined ? null : nick, nick: nick === undefined ? null : nick
}) })
} }
/** /**
* Reset nickname of the Member * Reset nickname of the Member
*/ */
async resetNickname(): Promise<Member> { async resetNickname(): Promise<Member> {
return await this.setNickname() return await this.setNickname()
} }
/** /**
* Set mute of a Member in VC * Set mute of a Member in VC
* @param mute Value to set * @param mute Value to set
*/ */
async setMute(mute?: boolean): Promise<Member> { async setMute(mute?: boolean): Promise<Member> {
return await this.edit({ return await this.edit({
mute: mute === undefined ? false : mute, mute: mute === undefined ? false : mute
}) })
} }
/** /**
* Set deaf of a Member in VC * Set deaf of a Member in VC
* @param deaf Value to set * @param deaf Value to set
*/ */
async setDeaf(deaf?: boolean): Promise<Member> { async setDeaf(deaf?: boolean): Promise<Member> {
return await this.edit({ return await this.edit({
deaf: deaf === undefined ? false : deaf, deaf: deaf === undefined ? false : deaf
}) })
} }
/** /**
* Unmute the Member from VC. * Unmute the Member from VC.
*/ */
async unmute(): Promise<Member> { async unmute(): Promise<Member> {
return await this.setMute(false) return await this.setMute(false)
} }
/** /**
* Kick the member. * Kick the member.
*/ */
async kick(): Promise<boolean> { async kick(): Promise<boolean> {
const resp = await this.client.rest.delete( const resp = await this.client.rest.delete(
GUILD_MEMBER(this.guild.id, this.id), GUILD_MEMBER(this.guild.id, this.id),
undefined, undefined,
undefined, undefined,
null, null,
true true
) )
if (resp.ok !== true) return false if (resp.ok !== true) return false
else return true else return true
} }
/** /**
* Ban the Member. * Ban the Member.
* @param reason Reason for the Ban. * @param reason Reason for the Ban.
* @param deleteMessagesDays Delete Old Messages? If yes, how much days. * @param deleteMessagesDays Delete Old Messages? If yes, how much days.
*/ */
async ban(reason?: string, deleteOldMessages?: number): Promise<void> { async ban(reason?: string, deleteOldMessages?: number): Promise<void> {
return this.guild.bans.add(this.id, reason, deleteOldMessages) return this.guild.bans.add(this.id, reason, deleteOldMessages)
} }
} }

View File

@ -1,129 +1,129 @@
import { Base } from './base.ts' import { Base } from './base.ts'
import { import {
Attachment, Attachment,
ChannelMention, ChannelMention,
MessageActivity, MessageActivity,
MessageApplication, MessageApplication,
MessageOption, MessageOption,
MessagePayload, MessagePayload,
MessageReference, MessageReference
} from '../types/channel.ts' } from '../types/channel.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { User } from './user.ts' import { User } from './user.ts'
import { Member } from './member.ts' import { Member } from './member.ts'
import { Embed } from './embed.ts' import { Embed } from './embed.ts'
import { CHANNEL_MESSAGE } from '../types/endpoint.ts' import { CHANNEL_MESSAGE } from '../types/endpoint.ts'
import { MessageMentions } from './messageMentions.ts' import { MessageMentions } from './messageMentions.ts'
import { TextChannel } from './textChannel.ts' import { TextChannel } from './textChannel.ts'
import { Guild } from './guild.ts' import { Guild } from './guild.ts'
import { MessageReactionsManager } from '../managers/messageReactions.ts' import { MessageReactionsManager } from '../managers/messageReactions.ts'
type AllMessageOptions = MessageOption | Embed type AllMessageOptions = MessageOption | Embed
export class Message extends Base { export class Message extends Base {
id: string id: string
channelID: string channelID: string
channel: TextChannel channel: TextChannel
guildID?: string guildID?: string
guild?: Guild guild?: Guild
author: User author: User
member?: Member member?: Member
content: string content: string
timestamp: string timestamp: string
editedTimestamp?: string editedTimestamp?: string
tts: boolean tts: boolean
mentionEveryone: boolean mentionEveryone: boolean
mentions: MessageMentions mentions: MessageMentions
mentionRoles: string[] mentionRoles: string[]
mentionChannels?: ChannelMention[] mentionChannels?: ChannelMention[]
attachments: Attachment[] attachments: Attachment[]
embeds: Embed[] embeds: Embed[]
reactions: MessageReactionsManager reactions: MessageReactionsManager
nonce?: string | number nonce?: string | number
pinned: boolean pinned: boolean
webhookID?: string webhookID?: string
type: number type: number
activity?: MessageActivity activity?: MessageActivity
application?: MessageApplication application?: MessageApplication
messageReference?: MessageReference messageReference?: MessageReference
flags?: number flags?: number
constructor( constructor(
client: Client, client: Client,
data: MessagePayload, data: MessagePayload,
channel: TextChannel, channel: TextChannel,
author: User author: User
) { ) {
super(client) super(client)
this.id = data.id this.id = data.id
this.channelID = data.channel_id this.channelID = data.channel_id
this.guildID = data.guild_id this.guildID = data.guild_id
this.author = author this.author = author
this.content = data.content this.content = data.content
this.timestamp = data.timestamp this.timestamp = data.timestamp
this.editedTimestamp = data.edited_timestamp this.editedTimestamp = data.edited_timestamp
this.tts = data.tts this.tts = data.tts
this.mentionEveryone = data.mention_everyone this.mentionEveryone = data.mention_everyone
this.mentions = new MessageMentions(this.client, this) this.mentions = new MessageMentions(this.client, this)
this.mentionRoles = data.mention_roles this.mentionRoles = data.mention_roles
this.mentionChannels = data.mention_channels this.mentionChannels = data.mention_channels
this.attachments = data.attachments this.attachments = data.attachments
this.embeds = data.embeds.map((v) => new Embed(v)) this.embeds = data.embeds.map((v) => new Embed(v))
this.reactions = new MessageReactionsManager(this.client, this) this.reactions = new MessageReactionsManager(this.client, this)
this.nonce = data.nonce this.nonce = data.nonce
this.pinned = data.pinned this.pinned = data.pinned
this.webhookID = data.webhook_id this.webhookID = data.webhook_id
this.type = data.type this.type = data.type
this.activity = data.activity this.activity = data.activity
this.application = data.application this.application = data.application
this.messageReference = data.message_reference this.messageReference = data.message_reference
this.flags = data.flags this.flags = data.flags
this.channel = channel this.channel = channel
} }
protected readFromData(data: MessagePayload): void { protected readFromData(data: MessagePayload): void {
super.readFromData(data) super.readFromData(data)
this.channelID = data.channel_id ?? this.channelID this.channelID = data.channel_id ?? this.channelID
this.guildID = data.guild_id ?? this.guildID this.guildID = data.guild_id ?? this.guildID
this.content = data.content ?? this.content this.content = data.content ?? this.content
this.timestamp = data.timestamp ?? this.timestamp this.timestamp = data.timestamp ?? this.timestamp
this.editedTimestamp = data.edited_timestamp ?? this.editedTimestamp this.editedTimestamp = data.edited_timestamp ?? this.editedTimestamp
this.tts = data.tts ?? this.tts this.tts = data.tts ?? this.tts
this.mentionEveryone = data.mention_everyone ?? this.mentionEveryone this.mentionEveryone = data.mention_everyone ?? this.mentionEveryone
this.mentionRoles = data.mention_roles ?? this.mentionRoles this.mentionRoles = data.mention_roles ?? this.mentionRoles
this.mentionChannels = data.mention_channels ?? this.mentionChannels this.mentionChannels = data.mention_channels ?? this.mentionChannels
this.attachments = data.attachments ?? this.attachments this.attachments = data.attachments ?? this.attachments
this.embeds = data.embeds.map((v) => new Embed(v)) ?? this.embeds this.embeds = data.embeds.map((v) => new Embed(v)) ?? this.embeds
this.nonce = data.nonce ?? this.nonce this.nonce = data.nonce ?? this.nonce
this.pinned = data.pinned ?? this.pinned this.pinned = data.pinned ?? this.pinned
this.webhookID = data.webhook_id ?? this.webhookID this.webhookID = data.webhook_id ?? this.webhookID
this.type = data.type ?? this.type this.type = data.type ?? this.type
this.activity = data.activity ?? this.activity this.activity = data.activity ?? this.activity
this.application = data.application ?? this.application this.application = data.application ?? this.application
this.messageReference = data.message_reference ?? this.messageReference this.messageReference = data.message_reference ?? this.messageReference
this.flags = data.flags ?? this.flags this.flags = data.flags ?? this.flags
} }
/** Edit this message. */ /** Edit this message. */
async edit(text?: string, option?: MessageOption): Promise<Message> { async edit(text?: string, option?: MessageOption): Promise<Message> {
if ( if (
this.client.user !== undefined && this.client.user !== undefined &&
this.author.id !== this.client.user?.id this.author.id !== this.client.user?.id
) )
throw new Error("Cannot edit other users' messages") throw new Error("Cannot edit other users' messages")
return this.channel.editMessage(this.id, text, option) return this.channel.editMessage(this.id, text, option)
} }
/** Create a Reply to this Message. */ /** Create a Reply to this Message. */
async reply( async reply(
text?: string | AllMessageOptions, text?: string | AllMessageOptions,
option?: AllMessageOptions option?: AllMessageOptions
): Promise<Message> { ): Promise<Message> {
return this.channel.send(text, option, this) return this.channel.send(text, option, this)
} }
/** Delete the Message. */ /** Delete the Message. */
async delete(): Promise<void> { async delete(): Promise<void> {
return this.client.rest.delete(CHANNEL_MESSAGE(this.channelID, this.id)) return this.client.rest.delete(CHANNEL_MESSAGE(this.channelID, this.id))
} }
} }

View File

@ -1,63 +1,63 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { MessagePayload } from '../types/channel.ts' import { MessagePayload } from '../types/channel.ts'
import { Collection } from '../utils/collection.ts' import { Collection } from '../utils/collection.ts'
import { GuildTextChannel } from './textChannel.ts' import { GuildTextChannel } from './textChannel.ts'
import { Message } from './message.ts' import { Message } from './message.ts'
import { Role } from './role.ts' import { Role } from './role.ts'
import { User } from './user.ts' import { User } from './user.ts'
export class MessageMentions { export class MessageMentions {
client: Client client: Client
message: Message message: Message
users: Collection<string, User> = new Collection() users: Collection<string, User> = new Collection()
roles: Collection<string, Role> = new Collection() roles: Collection<string, Role> = new Collection()
channels: Collection<string, GuildTextChannel> = new Collection() channels: Collection<string, GuildTextChannel> = new Collection()
everyone: boolean = false everyone: boolean = false
static EVERYONE_MENTION = /@(everyone|here)/g static EVERYONE_MENTION = /@(everyone|here)/g
static USER_MENTION = /<@!?(\d{17,19})>/g static USER_MENTION = /<@!?(\d{17,19})>/g
static ROLE_MENTION = /<@&(\d{17,19})>/g static ROLE_MENTION = /<@&(\d{17,19})>/g
static CHANNEL_MENTION = /<#(\d{17,19})>/g static CHANNEL_MENTION = /<#(\d{17,19})>/g
constructor(client: Client, message: Message) { constructor(client: Client, message: Message) {
this.client = client this.client = client
this.message = message this.message = message
} }
async fromPayload(payload: MessagePayload): Promise<MessageMentions> { async fromPayload(payload: MessagePayload): Promise<MessageMentions> {
if (this.message === undefined) return this if (this.message === undefined) return this
if (payload.mentions !== undefined) if (payload.mentions !== undefined)
payload.mentions.forEach((rawUser) => { payload.mentions.forEach((rawUser) => {
this.users.set(rawUser.id, new User(this.client, rawUser)) this.users.set(rawUser.id, new User(this.client, rawUser))
}) })
if (this.message.guild !== undefined) { if (this.message.guild !== undefined) {
for (const id of payload.mention_roles) { for (const id of payload.mention_roles) {
const role = await this.message.guild.roles.get(id) const role = await this.message.guild.roles.get(id)
if (role !== undefined) this.roles.set(role.id, role) if (role !== undefined) this.roles.set(role.id, role)
} }
} }
if (payload.mention_channels !== undefined) { if (payload.mention_channels !== undefined) {
for (const mentionChannel of payload.mention_channels) { for (const mentionChannel of payload.mention_channels) {
const channel = await this.client.channels.get<GuildTextChannel>( const channel = await this.client.channels.get<GuildTextChannel>(
mentionChannel.id mentionChannel.id
) )
if (channel !== undefined) this.channels.set(channel.id, channel) if (channel !== undefined) this.channels.set(channel.id, channel)
} }
} }
const matchChannels = this.message.content.match( const matchChannels = this.message.content.match(
MessageMentions.CHANNEL_MENTION MessageMentions.CHANNEL_MENTION
) )
if (matchChannels !== null) { if (matchChannels !== null) {
for (const id of matchChannels) { for (const id of matchChannels) {
const parsedID = id.substr(2, id.length - 3) const parsedID = id.substr(2, id.length - 3)
const channel = await this.client.channels.get<GuildTextChannel>( const channel = await this.client.channels.get<GuildTextChannel>(
parsedID parsedID
) )
if (channel !== undefined) this.channels.set(channel.id, channel) if (channel !== undefined) this.channels.set(channel.id, channel)
} }
} }
this.everyone = payload.mention_everyone this.everyone = payload.mention_everyone
return this return this
} }
} }

View File

@ -1,28 +1,28 @@
import { ReactionUsersManager } from '../managers/reactionUsers.ts' import { ReactionUsersManager } from '../managers/reactionUsers.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Reaction } from '../types/channel.ts' import { Reaction } from '../types/channel.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
import { Emoji } from './emoji.ts' import { Emoji } from './emoji.ts'
import { Message } from './message.ts' import { Message } from './message.ts'
export class MessageReaction extends Base { export class MessageReaction extends Base {
message: Message message: Message
count: number = 0 count: number = 0
emoji: Emoji emoji: Emoji
me: boolean = false me: boolean = false
users: ReactionUsersManager users: ReactionUsersManager
constructor(client: Client, data: Reaction, message: Message, emoji: Emoji) { constructor(client: Client, data: Reaction, message: Message, emoji: Emoji) {
super(client, data) super(client, data)
this.message = message this.message = message
this.emoji = emoji this.emoji = emoji
this.count = data.count this.count = data.count
this.me = data.me this.me = data.me
this.users = new ReactionUsersManager(client, this) this.users = new ReactionUsersManager(client, this)
} }
fromPayload(data: Reaction): void { fromPayload(data: Reaction): void {
this.count = data.count this.count = data.count
this.me = data.me this.me = data.me
} }
} }

View File

@ -3,7 +3,7 @@ import {
ActivityPayload, ActivityPayload,
ClientActivity, ClientActivity,
ClientStatus, ClientStatus,
StatusType, StatusType
} from '../types/presence.ts' } from '../types/presence.ts'
import { PresenceUpdatePayload, StatusUpdatePayload } from '../types/gateway.ts' import { PresenceUpdatePayload, StatusUpdatePayload } from '../types/gateway.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
@ -17,7 +17,7 @@ enum ActivityTypes {
LISTENING = 2, LISTENING = 2,
WATCHING = 3, WATCHING = 3,
CUSTOM_STATUS = 4, CUSTOM_STATUS = 4,
COMPETING = 5, COMPETING = 5
} }
export class Presence extends Base { export class Presence extends Base {
@ -88,7 +88,7 @@ export class ClientPresence {
afk: this.afk === undefined ? false : this.afk, afk: this.afk === undefined ? false : this.afk,
activities: this.createActivity(), activities: this.createActivity(),
since: this.since === undefined ? null : this.since, since: this.since === undefined ? null : this.since,
status: this.status === undefined ? 'online' : this.status, status: this.status === undefined ? 'online' : this.status
} }
} }

View File

@ -1,7 +1,7 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
import { RolePayload } from '../types/role.ts' import { RolePayload } from '../types/role.ts'
import { Permissions } from "../utils/permissions.ts" import { Permissions } from '../utils/permissions.ts'
export class Role extends Base { export class Role extends Base {
id: string id: string
@ -13,13 +13,15 @@ export class Role extends Base {
managed: boolean managed: boolean
mentionable: boolean mentionable: boolean
get mention (): string { get mention(): string {
return `<@&${this.id}>` return `<@&${this.id}>`
} }
toString(): string { return this.mention } toString(): string {
return this.mention
}
constructor (client: Client, data: RolePayload) { constructor(client: Client, data: RolePayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.name = data.name this.name = data.name
@ -31,13 +33,16 @@ export class Role extends Base {
this.mentionable = data.mentionable this.mentionable = data.mentionable
} }
protected readFromData (data: RolePayload): void { protected readFromData(data: RolePayload): void {
super.readFromData(data) super.readFromData(data)
this.name = data.name ?? this.name this.name = data.name ?? this.name
this.color = data.color ?? this.color this.color = data.color ?? this.color
this.hoist = data.hoist ?? this.hoist this.hoist = data.hoist ?? this.hoist
this.position = data.position ?? this.position this.position = data.position ?? this.position
this.permissions = new Permissions(data.permissions) ?? this.permissions this.permissions =
data.permissions !== undefined
? new Permissions(data.permissions)
: this.permissions
this.managed = data.managed ?? this.managed this.managed = data.managed ?? this.managed
this.mentionable = data.mentionable ?? this.mentionable this.mentionable = data.mentionable ?? this.mentionable
} }

View File

@ -1,22 +1,22 @@
export class Snowflake { export class Snowflake {
snowflake: bigint snowflake: bigint
constructor (id: string) { constructor(id: string) {
this.snowflake = BigInt.asUintN(64, BigInt(id)) this.snowflake = BigInt.asUintN(64, BigInt(id))
} }
get timestamp (): string { get timestamp(): string {
return ((this.snowflake >> 22n) + 1420070400000n).toString() return ((this.snowflake >> 22n) + 1420070400000n).toString()
} }
get workerID (): string { get workerID(): string {
return ((this.snowflake & 0x3e0000n) >> 17n).toString() return ((this.snowflake & 0x3e0000n) >> 17n).toString()
} }
get processID (): string { get processID(): string {
return ((this.snowflake & 0x1f00n) >> 12n).toString() return ((this.snowflake & 0x1f00n) >> 12n).toString()
} }
get increment (): string { get increment(): string {
return (this.snowflake & 0xfffn).toString() return (this.snowflake & 0xfffn).toString()
} }
} }

View File

@ -1,156 +1,167 @@
import { MessagesManager } from "../../mod.ts" import { MessagesManager } from '../managers/messages.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { GuildTextChannelPayload, MessageOption, MessageReference, Overwrite, TextChannelPayload } from '../types/channel.ts' import {
import { CHANNEL_MESSAGE, CHANNEL_MESSAGES } from '../types/endpoint.ts' GuildTextChannelPayload,
import { Channel } from './channel.ts' MessageOption,
import { Embed } from './embed.ts' MessageReference,
import { Guild } from "./guild.ts" Overwrite,
import { Message } from './message.ts' TextChannelPayload
} from '../types/channel.ts'
export type AllMessageOptions = MessageOption | Embed import { CHANNEL_MESSAGE, CHANNEL_MESSAGES } from '../types/endpoint.ts'
import { Channel } from './channel.ts'
export class TextChannel extends Channel { import { Embed } from './embed.ts'
lastMessageID?: string import { Guild } from './guild.ts'
lastPinTimestamp?: string import { Message } from './message.ts'
messages: MessagesManager
export type AllMessageOptions = MessageOption | Embed
constructor(client: Client, data: TextChannelPayload) {
super(client, data) export class TextChannel extends Channel {
this.messages = new MessagesManager(this.client, this) lastMessageID?: string
this.lastMessageID = data.last_message_id lastPinTimestamp?: string
this.lastPinTimestamp = data.last_pin_timestamp messages: MessagesManager
}
constructor(client: Client, data: TextChannelPayload) {
protected readFromData(data: TextChannelPayload): void { super(client, data)
super.readFromData(data) this.messages = new MessagesManager(this.client, this)
this.lastMessageID = data.last_message_id ?? this.lastMessageID this.lastMessageID = data.last_message_id
this.lastPinTimestamp = data.last_pin_timestamp ?? this.lastPinTimestamp this.lastPinTimestamp = data.last_pin_timestamp
} }
/** protected readFromData(data: TextChannelPayload): void {
* super.readFromData(data)
* @param text Text content of the Message to send. this.lastMessageID = data.last_message_id ?? this.lastMessageID
* @param option Various other Message options. this.lastPinTimestamp = data.last_pin_timestamp ?? this.lastPinTimestamp
* @param reply Reference to a Message object to reply-to. }
*/
async send(text?: string | AllMessageOptions, option?: AllMessageOptions, reply?: Message): Promise<Message> { /**
if (typeof text === "object") { *
option = text * @param text Text content of the Message to send.
text = undefined * @param option Various other Message options.
} * @param reply Reference to a Message object to reply-to.
if (text === undefined && option === undefined) { */
throw new Error('Either text or option is necessary.') async send(
} text?: string | AllMessageOptions,
if (option instanceof Embed) option = { option?: AllMessageOptions,
embed: option reply?: Message
} ): Promise<Message> {
if (typeof text === 'object') {
const payload: any = { option = text
content: text, text = undefined
embed: option?.embed, }
file: option?.file, if (text === undefined && option === undefined) {
tts: option?.tts, throw new Error('Either text or option is necessary.')
allowed_mentions: option?.allowedMentions }
} if (option instanceof Embed)
option = {
if (reply !== undefined) { embed: option
const reference: MessageReference = { }
message_id: reply.id,
channel_id: reply.channel.id, const payload: any = {
guild_id: reply.guild?.id, content: text,
} embed: option?.embed,
payload.message_reference = reference file: option?.file,
} tts: option?.tts,
allowed_mentions: option?.allowedMentions
const resp = await this.client.rest.post(CHANNEL_MESSAGES(this.id), payload) }
const res = new Message(this.client, resp, this, this.client.user as any) if (reply !== undefined) {
await res.mentions.fromPayload(resp) const reference: MessageReference = {
return res message_id: reply.id,
} channel_id: reply.channel.id,
guild_id: reply.guild?.id
/** }
* payload.message_reference = reference
* @param message Message to edit. ID or the Message object itself. }
* @param text New text contents of the Message.
* @param option Other options to edit the message. const resp = await this.client.rest.post(CHANNEL_MESSAGES(this.id), payload)
*/
async editMessage( const res = new Message(this.client, resp, this, this.client.user as any)
message: Message | string, await res.mentions.fromPayload(resp)
text?: string, return res
option?: MessageOption }
): Promise<Message> {
if (text === undefined && option === undefined) { /**
throw new Error('Either text or option is necessary.') *
} * @param message Message to edit. ID or the Message object itself.
* @param text New text contents of the Message.
if (this.client.user === undefined) { * @param option Other options to edit the message.
throw new Error('Client user has not initialized.') */
} async editMessage(
message: Message | string,
const newMsg = await this.client.rest.patch( text?: string,
CHANNEL_MESSAGE( option?: MessageOption
this.id, ): Promise<Message> {
typeof message === 'string' ? message : message.id if (text === undefined && option === undefined) {
), throw new Error('Either text or option is necessary.')
{ }
content: text,
embed: option?.embed !== undefined ? option.embed.toJSON() : undefined, if (this.client.user === undefined) {
// Cannot upload new files with Message throw new Error('Client user has not initialized.')
// file: option?.file, }
tts: option?.tts,
allowed_mentions: option?.allowedMentions const newMsg = await this.client.rest.patch(
} CHANNEL_MESSAGE(
) this.id,
typeof message === 'string' ? message : message.id
const res = new Message(this.client, newMsg, this, this.client.user) ),
await res.mentions.fromPayload(newMsg) {
return res content: text,
} embed: option?.embed !== undefined ? option.embed.toJSON() : undefined,
} // Cannot upload new files with Message
// file: option?.file,
export class GuildTextChannel extends TextChannel { tts: option?.tts,
guildID: string allowed_mentions: option?.allowedMentions
name: string }
position: number )
permissionOverwrites: Overwrite[]
nsfw: boolean const res = new Message(this.client, newMsg, this, this.client.user)
parentID?: string await res.mentions.fromPayload(newMsg)
rateLimit: number return res
topic?: string }
guild: Guild }
get mention(): string { export class GuildTextChannel extends TextChannel {
return `<#${this.id}>` guildID: string
} name: string
position: number
toString(): string { permissionOverwrites: Overwrite[]
return this.mention nsfw: boolean
} parentID?: string
rateLimit: number
constructor(client: Client, data: GuildTextChannelPayload, guild: Guild) { topic?: string
super(client, data) guild: Guild
this.guildID = data.guild_id
this.name = data.name get mention(): string {
this.guild = guild return `<#${this.id}>`
this.position = data.position }
this.permissionOverwrites = data.permission_overwrites
this.nsfw = data.nsfw toString(): string {
this.parentID = data.parent_id return this.mention
this.topic = data.topic }
this.rateLimit = data.rate_limit_per_user
} constructor(client: Client, data: GuildTextChannelPayload, guild: Guild) {
super(client, data)
protected readFromData(data: GuildTextChannelPayload): void { this.guildID = data.guild_id
super.readFromData(data) this.name = data.name
this.guildID = data.guild_id ?? this.guildID this.guild = guild
this.name = data.name ?? this.name this.position = data.position
this.position = data.position ?? this.position this.permissionOverwrites = data.permission_overwrites
this.permissionOverwrites = this.nsfw = data.nsfw
data.permission_overwrites ?? this.permissionOverwrites this.parentID = data.parent_id
this.nsfw = data.nsfw ?? this.nsfw this.topic = data.topic
this.parentID = data.parent_id ?? this.parentID this.rateLimit = data.rate_limit_per_user
this.topic = data.topic ?? this.topic }
this.rateLimit = data.rate_limit_per_user ?? this.rateLimit
} protected readFromData(data: GuildTextChannelPayload): void {
} super.readFromData(data)
this.guildID = data.guild_id ?? this.guildID
this.name = data.name ?? this.name
this.position = data.position ?? this.position
this.permissionOverwrites =
data.permission_overwrites ?? this.permissionOverwrites
this.nsfw = data.nsfw ?? this.nsfw
this.parentID = data.parent_id ?? this.parentID
this.topic = data.topic ?? this.topic
this.rateLimit = data.rate_limit_per_user ?? this.rateLimit
}
}

View File

@ -1,76 +1,80 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { UserPayload } from '../types/user.ts' import { UserPayload } from '../types/user.ts'
import { UserFlagsManager } from "../utils/userFlags.ts" import { UserFlagsManager } from '../utils/userFlags.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
export class User extends Base { export class User extends Base {
id: string id: string
username: string username: string
discriminator: string discriminator: string
avatar?: string avatar?: string
bot?: boolean bot?: boolean
system?: boolean system?: boolean
mfaEnabled?: boolean mfaEnabled?: boolean
locale?: string locale?: string
verified?: boolean verified?: boolean
email?: string email?: string
flags?: UserFlagsManager flags: UserFlagsManager
/** /**
* Nitro type of the User. * Nitro type of the User.
* *
* 0 = No Nitro * 0 = No Nitro
* 1 = Classic Nitro * 1 = Classic Nitro
* 2 = Regular Nitro * 2 = Regular Nitro
*/ */
premiumType?: 0 | 1 | 2 premiumType?: 0 | 1 | 2
publicFlags?: UserFlagsManager publicFlags: UserFlagsManager
get tag (): string { get tag(): string {
return `${this.username}#${this.discriminator}` return `${this.username}#${this.discriminator}`
} }
get nickMention (): string { get nickMention(): string {
return `<@!${this.id}>` return `<@!${this.id}>`
} }
get mention (): string { get mention(): string {
return `<@${this.id}>` return `<@${this.id}>`
} }
constructor (client: Client, data: UserPayload) { constructor(client: Client, data: UserPayload) {
super(client, data) super(client, data)
this.id = data.id this.id = data.id
this.username = data.username this.username = data.username
this.discriminator = data.discriminator this.discriminator = data.discriminator
this.avatar = data.avatar this.avatar = data.avatar
this.bot = data.bot this.bot = data.bot
this.system = data.system this.system = data.system
this.mfaEnabled = data.mfa_enabled this.mfaEnabled = data.mfa_enabled
this.locale = data.locale this.locale = data.locale
this.verified = data.verified this.verified = data.verified
this.email = data.email this.email = data.email
this.flags = new UserFlagsManager(data.flags) this.flags = new UserFlagsManager(data.flags)
this.premiumType = data.premium_type this.premiumType = data.premium_type
this.publicFlags = new UserFlagsManager(data.public_flags) this.publicFlags = new UserFlagsManager(data.public_flags)
} }
protected readFromData (data: UserPayload): void { protected readFromData(data: UserPayload): void {
super.readFromData(data) super.readFromData(data)
this.username = data.username ?? this.username this.username = data.username ?? this.username
this.discriminator = data.discriminator ?? this.discriminator this.discriminator = data.discriminator ?? this.discriminator
this.avatar = data.avatar ?? this.avatar this.avatar = data.avatar ?? this.avatar
this.bot = data.bot ?? this.bot this.bot = data.bot ?? this.bot
this.system = data.system ?? this.system this.system = data.system ?? this.system
this.mfaEnabled = data.mfa_enabled ?? this.mfaEnabled this.mfaEnabled = data.mfa_enabled ?? this.mfaEnabled
this.locale = data.locale ?? this.locale this.locale = data.locale ?? this.locale
this.verified = data.verified ?? this.verified this.verified = data.verified ?? this.verified
this.email = data.email ?? this.email this.email = data.email ?? this.email
this.flags = new UserFlagsManager(data.flags) ?? this.flags this.flags =
this.premiumType = data.premium_type ?? this.premiumType data.flags !== undefined ? new UserFlagsManager(data.flags) : this.flags
this.publicFlags = new UserFlagsManager(data.public_flags) ?? this.publicFlags this.premiumType = data.premium_type ?? this.premiumType
} this.publicFlags =
data.public_flags !== undefined
toString (): string { ? new UserFlagsManager(data.public_flags)
return this.mention : this.publicFlags
} }
}
toString(): string {
return this.mention
}
}

View File

@ -1,53 +1,57 @@
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { VoiceStatePayload } from '../types/voice.ts' import { VoiceStatePayload } from '../types/voice.ts'
import { Base } from './base.ts' import { Base } from './base.ts'
import { Guild } from "./guild.ts" import { Guild } from './guild.ts'
import { VoiceChannel } from "./guildVoiceChannel.ts" import { VoiceChannel } from './guildVoiceChannel.ts'
import { Member } from "./member.ts" import { Member } from './member.ts'
import { User } from "./user.ts" import { User } from './user.ts'
export class VoiceState extends Base { export class VoiceState extends Base {
guild?: Guild guild?: Guild
channel: VoiceChannel | null channel: VoiceChannel | null
user: User user: User
member?: Member member?: Member
sessionID: string sessionID: string
deaf: boolean deaf: boolean
mute: boolean mute: boolean
stream?: boolean stream?: boolean
video: boolean video: boolean
suppress: boolean suppress: boolean
constructor (client: Client, data: VoiceStatePayload, _data: { constructor(
user: User, client: Client,
channel: VoiceChannel | null, data: VoiceStatePayload,
member?: Member, _data: {
guild?: Guild user: User
}) { channel: VoiceChannel | null
super(client, data) member?: Member
this.channel = _data.channel guild?: Guild
this.sessionID = data.session_id }
this.user = _data.user ) {
this.member = _data.member super(client, data)
this.guild = _data.guild this.channel = _data.channel
this.deaf = data.deaf this.sessionID = data.session_id
this.mute = data.mute this.user = _data.user
this.deaf = data.self_deaf this.member = _data.member
this.mute = data.self_mute this.guild = _data.guild
this.stream = data.self_stream this.deaf = data.deaf
this.video = data.self_video this.mute = data.mute
this.suppress = data.suppress this.deaf = data.self_deaf
} this.mute = data.self_mute
this.stream = data.self_stream
protected readFromData (data: VoiceStatePayload): void { this.video = data.self_video
super.readFromData(data) this.suppress = data.suppress
this.sessionID = data.session_id ?? this.sessionID }
this.deaf = data.deaf ?? this.deaf
this.mute = data.mute ?? this.mute protected readFromData(data: VoiceStatePayload): void {
this.deaf = data.self_deaf ?? this.deaf super.readFromData(data)
this.mute = data.self_mute ?? this.mute this.sessionID = data.session_id ?? this.sessionID
this.stream = data.self_stream ?? this.stream this.deaf = data.deaf ?? this.deaf
this.video = data.self_video ?? this.video this.mute = data.mute ?? this.mute
this.suppress = data.suppress ?? this.suppress this.deaf = data.self_deaf ?? this.deaf
} this.mute = data.self_mute ?? this.mute
} this.stream = data.self_stream ?? this.stream
this.video = data.self_video ?? this.video
this.suppress = data.suppress ?? this.suppress
}
}

View File

@ -1,194 +1,194 @@
import { import {
DISCORD_API_URL, DISCORD_API_URL,
DISCORD_API_VERSION DISCORD_API_VERSION
} from '../consts/urlsAndVersions.ts' } from '../consts/urlsAndVersions.ts'
import { Client } from '../models/client.ts' import { Client } from '../models/client.ts'
import { RESTManager } from '../models/rest.ts' import { RESTManager } from '../models/rest.ts'
import { MessageOption } from '../types/channel.ts' import { MessageOption } from '../types/channel.ts'
import { UserPayload } from '../types/user.ts' import { UserPayload } from '../types/user.ts'
import { WebhookPayload } from '../types/webhook.ts' import { WebhookPayload } from '../types/webhook.ts'
import { Embed } from './embed.ts' import { Embed } from './embed.ts'
import { Message } from './message.ts' import { Message } from './message.ts'
import { TextChannel } from './textChannel.ts' import { TextChannel } from './textChannel.ts'
import { User } from './user.ts' import { User } from './user.ts'
import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts' import { fetchAuto } from 'https://raw.githubusercontent.com/DjDeveloperr/fetch-base64/main/mod.ts'
export interface WebhookMessageOptions extends MessageOption { export interface WebhookMessageOptions extends MessageOption {
embeds?: Embed[] embeds?: Embed[]
name?: string name?: string
avatar?: string avatar?: string
} }
export type AllWebhookMessageOptions = string | WebhookMessageOptions export type AllWebhookMessageOptions = string | WebhookMessageOptions
export interface WebhookEditOptions { export interface WebhookEditOptions {
/** New name to set for Webhook. */ /** New name to set for Webhook. */
name?: string name?: string
/** New avatar to set for Webhook. URL of image or base64 encoded data. */ /** New avatar to set for Webhook. URL of image or base64 encoded data. */
avatar?: string avatar?: string
/** New channel for Webhook. Requires authentication. */ /** New channel for Webhook. Requires authentication. */
channelID?: string channelID?: string
} }
/** Webhook follows different way of instantiation */ /** Webhook follows different way of instantiation */
export class Webhook { export class Webhook {
client?: Client client?: Client
id: string id: string
type: 1 | 2 type: 1 | 2
guildID?: string guildID?: string
channelID: string channelID: string
user?: User user?: User
userRaw?: UserPayload userRaw?: UserPayload
name?: string name?: string
avatar?: string avatar?: string
token?: string token?: string
applicationID?: string applicationID?: string
rest: RESTManager rest: RESTManager
get url (): string { get url(): string {
return `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${this.id}/${this.token}` return `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/webhooks/${this.id}/${this.token}`
} }
constructor (data: WebhookPayload, client?: Client, rest?: RESTManager) { constructor(data: WebhookPayload, client?: Client, rest?: RESTManager) {
this.id = data.id this.id = data.id
this.type = data.type this.type = data.type
this.channelID = data.channel_id this.channelID = data.channel_id
this.guildID = data.guild_id this.guildID = data.guild_id
this.user = this.user =
data.user === undefined || client === undefined data.user === undefined || client === undefined
? undefined ? undefined
: new User(client, data.user) : new User(client, data.user)
if (data.user !== undefined && client === undefined) if (data.user !== undefined && client === undefined)
this.userRaw = data.user this.userRaw = data.user
this.name = data.name this.name = data.name
this.avatar = data.avatar this.avatar = data.avatar
this.token = data.token this.token = data.token
this.applicationID = data.application_id this.applicationID = data.application_id
if (rest !== undefined) this.rest = rest if (rest !== undefined) this.rest = rest
else if (client !== undefined) this.rest = client.rest else if (client !== undefined) this.rest = client.rest
else this.rest = new RESTManager() else this.rest = new RESTManager()
} }
private fromPayload (data: WebhookPayload): Webhook { private fromPayload(data: WebhookPayload): Webhook {
this.id = data.id this.id = data.id
this.type = data.type this.type = data.type
this.channelID = data.channel_id this.channelID = data.channel_id
this.guildID = data.guild_id this.guildID = data.guild_id
this.user = this.user =
data.user === undefined || this.client === undefined data.user === undefined || this.client === undefined
? undefined ? undefined
: new User(this.client, data.user) : new User(this.client, data.user)
if (data.user !== undefined && this.client === undefined) if (data.user !== undefined && this.client === undefined)
this.userRaw = data.user this.userRaw = data.user
this.name = data.name this.name = data.name
this.avatar = data.avatar this.avatar = data.avatar
this.token = data.token this.token = data.token
this.applicationID = data.application_id this.applicationID = data.application_id
return this return this
} }
/** Send a Message through Webhook. */ /** Send a Message through Webhook. */
async send ( async send(
text?: string | AllWebhookMessageOptions, text?: string | AllWebhookMessageOptions,
option?: AllWebhookMessageOptions option?: AllWebhookMessageOptions
): Promise<Message> { ): Promise<Message> {
if (typeof text === 'object') { if (typeof text === 'object') {
option = text option = text
text = undefined text = undefined
} }
if (text === undefined && option === undefined) { if (text === undefined && option === undefined) {
throw new Error('Either text or option is necessary.') throw new Error('Either text or option is necessary.')
} }
if (option instanceof Embed) if (option instanceof Embed)
option = { option = {
embeds: [option] embeds: [option]
} }
const payload: any = { const payload: any = {
content: text, content: text,
embeds: embeds:
(option as WebhookMessageOptions)?.embed !== undefined (option as WebhookMessageOptions)?.embed !== undefined
? [(option as WebhookMessageOptions).embed] ? [(option as WebhookMessageOptions).embed]
: (option as WebhookMessageOptions)?.embeds !== undefined : (option as WebhookMessageOptions)?.embeds !== undefined
? (option as WebhookMessageOptions).embeds ? (option as WebhookMessageOptions).embeds
: undefined, : undefined,
file: (option as WebhookMessageOptions)?.file, file: (option as WebhookMessageOptions)?.file,
tts: (option as WebhookMessageOptions)?.tts, tts: (option as WebhookMessageOptions)?.tts,
allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions allowed_mentions: (option as WebhookMessageOptions)?.allowedMentions
} }
if ((option as WebhookMessageOptions)?.name !== undefined) { if ((option as WebhookMessageOptions)?.name !== undefined) {
payload.username = (option as WebhookMessageOptions)?.name payload.username = (option as WebhookMessageOptions)?.name
} }
if ((option as WebhookMessageOptions)?.avatar !== undefined) { if ((option as WebhookMessageOptions)?.avatar !== undefined) {
payload.avatar = (option as WebhookMessageOptions)?.avatar payload.avatar = (option as WebhookMessageOptions)?.avatar
} }
if ( if (
payload.embeds !== undefined && payload.embeds !== undefined &&
payload.embeds instanceof Array && payload.embeds instanceof Array &&
payload.embeds.length > 10 payload.embeds.length > 10
) )
throw new Error(`Cannot send more than 10 embeds through Webhook`) throw new Error(`Cannot send more than 10 embeds through Webhook`)
const resp = await this.rest.post(this.url + '?wait=true', payload) const resp = await this.rest.post(this.url + '?wait=true', payload)
const res = new Message( const res = new Message(
this.client as Client, this.client as Client,
resp, resp,
(this as unknown) as TextChannel, (this as unknown) as TextChannel,
(this as unknown) as User (this as unknown) as User
) )
await res.mentions.fromPayload(resp) await res.mentions.fromPayload(resp)
return res return res
} }
/** /**
* Create a Webhook object from URL * Create a Webhook object from URL
* @param url URL of the Webhook * @param url URL of the Webhook
* @param client Client (bot) object, if any. * @param client Client (bot) object, if any.
*/ */
static async fromURL (url: string | URL, client?: Client): Promise<Webhook> { static async fromURL(url: string | URL, client?: Client): Promise<Webhook> {
const rest = client !== undefined ? client.rest : new RESTManager() const rest = client !== undefined ? client.rest : new RESTManager()
const raw = await rest.get(typeof url === 'string' ? url : url.toString()) const raw = await rest.get(typeof url === 'string' ? url : url.toString())
if (typeof raw !== 'object') if (typeof raw !== 'object')
throw new Error(`Failed to load Webhook from URL: ${url}`) throw new Error(`Failed to load Webhook from URL: ${url}`)
const webhook = new Webhook(raw, client, rest) const webhook = new Webhook(raw, client, rest)
return webhook return webhook
} }
/** /**
* Edit the Webhook name, avatar, or channel (requires authentication). * Edit the Webhook name, avatar, or channel (requires authentication).
* @param options Options to edit the Webhook. * @param options Options to edit the Webhook.
*/ */
async edit (options: WebhookEditOptions): Promise<Webhook> { async edit(options: WebhookEditOptions): Promise<Webhook> {
if (options.channelID !== undefined && this.rest.client === undefined) if (options.channelID !== undefined && this.rest.client === undefined)
throw new Error('Authentication is required for editing Webhook Channel') throw new Error('Authentication is required for editing Webhook Channel')
if ( if (
options.avatar !== undefined && options.avatar !== undefined &&
(options.avatar.startsWith('http:') || (options.avatar.startsWith('http:') ||
options.avatar.startsWith('https:')) options.avatar.startsWith('https:'))
) { ) {
options.avatar = await fetchAuto(options.avatar) options.avatar = await fetchAuto(options.avatar)
} }
const data = await this.rest.patch(this.url, options) const data = await this.rest.patch(this.url, options)
this.fromPayload(data) this.fromPayload(data)
return this return this
} }
/** Delete the Webhook. */ /** Delete the Webhook. */
async delete (): Promise<boolean> { async delete(): Promise<boolean> {
const resp = await this.rest.delete(this.url, undefined, 0, undefined, true) const resp = await this.rest.delete(this.url, undefined, 0, undefined, true)
if (resp.response.status !== 204) return false if (resp.response.status !== 204) return false
else return true else return true
} }
} }

View File

@ -1,165 +1,165 @@
import { import {
Command, Command,
CommandClient, CommandClient,
Intents, Intents,
GuildChannel, GuildChannel,
CommandContext, CommandContext,
Extension, Extension
} from '../../mod.ts' } from '../../mod.ts'
import { Invite } from '../structures/invite.ts' import { Invite } from '../structures/invite.ts'
import { TOKEN } from './config.ts' import { TOKEN } from './config.ts'
const client = new CommandClient({ const client = new CommandClient({
prefix: ['pls', '!'], prefix: ['pls', '!'],
spacesAfterPrefix: true, spacesAfterPrefix: true,
mentionPrefix: true, mentionPrefix: true
}) })
client.on('debug', console.log) client.on('debug', console.log)
client.on('ready', () => { client.on('ready', () => {
console.log(`[Login] Logged in as ${client.user?.tag}!`) console.log(`[Login] Logged in as ${client.user?.tag}!`)
}) })
client.on('messageDelete', (msg) => { client.on('messageDelete', (msg) => {
console.log(`Message Deleted: ${msg.id}, ${msg.author.tag}, ${msg.content}`) console.log(`Message Deleted: ${msg.id}, ${msg.author.tag}, ${msg.content}`)
}) })
client.on('messageUpdate', (before, after) => { client.on('messageUpdate', (before, after) => {
console.log('Message Update') console.log('Message Update')
console.log(`Before: ${before.author.tag}: ${before.content}`) console.log(`Before: ${before.author.tag}: ${before.content}`)
console.log(`After: ${after.author.tag}: ${after.content}`) console.log(`After: ${after.author.tag}: ${after.content}`)
}) })
client.on('messageUpdateUncached', (msg) => { client.on('messageUpdateUncached', (msg) => {
console.log(`Message: ${msg.author.tag}: ${msg.content}`) console.log(`Message: ${msg.author.tag}: ${msg.content}`)
}) })
client.on('guildMemberAdd', (member) => { client.on('guildMemberAdd', (member) => {
console.log(`Member Join: ${member.user.tag}`) console.log(`Member Join: ${member.user.tag}`)
}) })
client.on('guildMemberRemove', (member) => { client.on('guildMemberRemove', (member) => {
console.log(`Member Leave: ${member.user.tag}`) console.log(`Member Leave: ${member.user.tag}`)
}) })
client.on('guildRoleCreate', (role) => { client.on('guildRoleCreate', (role) => {
console.log(`Role Create: ${role.name}`) console.log(`Role Create: ${role.name}`)
}) })
client.on('guildRoleDelete', (role) => { client.on('guildRoleDelete', (role) => {
console.log(`Role Delete: ${role.name}`) console.log(`Role Delete: ${role.name}`)
}) })
client.on('guildRoleUpdate', (role, after) => { client.on('guildRoleUpdate', (role, after) => {
console.log(`Role Update: ${role.name}, ${after.name}`) console.log(`Role Update: ${role.name}, ${after.name}`)
}) })
client.on('guildIntegrationsUpdate', (guild) => { client.on('guildIntegrationsUpdate', (guild) => {
console.log(`Guild Integrations Update: ${guild.name}`) console.log(`Guild Integrations Update: ${guild.name}`)
}) })
client.on('webhooksUpdate', (guild, channel) => { client.on('webhooksUpdate', (guild, channel) => {
console.log(`Webhooks Updated in #${channel.name} from ${guild.name}`) console.log(`Webhooks Updated in #${channel.name} from ${guild.name}`)
}) })
client.on('commandError', console.error) client.on('commandError', console.error)
client.on('inviteCreate', (invite: Invite) => { client.on('inviteCreate', (invite: Invite) => {
console.log(`Invite Create: ${invite.code}`) console.log(`Invite Create: ${invite.code}`)
}) })
client.on('inviteDelete', (invite: Invite) => { client.on('inviteDelete', (invite: Invite) => {
console.log(`Invite Delete: ${invite.code}`) console.log(`Invite Delete: ${invite.code}`)
}) })
client.on('inviteDeleteUncached', (invite: Invite) => { client.on('inviteDeleteUncached', (invite: Invite) => {
console.log(invite) console.log(invite)
}) })
client.on('commandError', console.error) client.on('commandError', console.error)
class ChannelLog extends Extension { class ChannelLog extends Extension {
onChannelCreate(ext: Extension, channel: GuildChannel): void { onChannelCreate(ext: Extension, channel: GuildChannel): void {
console.log(`Channel Created: ${channel.name}`) console.log(`Channel Created: ${channel.name}`)
} }
load(): void { load(): void {
this.listen('channelCreate', this.onChannelCreate) this.listen('channelCreate', this.onChannelCreate)
class Pong extends Command { class Pong extends Command {
name = 'Pong' name = 'Pong'
execute(ctx: CommandContext): any { execute(ctx: CommandContext): any {
ctx.message.reply('Ping!') ctx.message.reply('Ping!')
} }
} }
this.commands.add(Pong) this.commands.add(Pong)
} }
} }
client.extensions.load(ChannelLog) client.extensions.load(ChannelLog)
client.on('messageDeleteBulk', (channel, messages, uncached) => { client.on('messageDeleteBulk', (channel, messages, uncached) => {
console.log( console.log(
`=== Message Delete Bulk ===\nMessages: ${messages `=== Message Delete Bulk ===\nMessages: ${messages
.map((m) => m.id) .map((m) => m.id)
.join(', ')}\nUncached: ${[...uncached.values()].join(', ')}` .join(', ')}\nUncached: ${[...uncached.values()].join(', ')}`
) )
}) })
client.on('channelUpdate', (before, after) => { client.on('channelUpdate', (before, after) => {
console.log( console.log(
`Channel Update: ${(before as GuildChannel).name}, ${ `Channel Update: ${(before as GuildChannel).name}, ${
(after as GuildChannel).name (after as GuildChannel).name
}` }`
) )
}) })
client.on('typingStart', (user, channel, at, guildData) => { client.on('typingStart', (user, channel, at, guildData) => {
console.log( console.log(
`${user.tag} started typing in ${channel.id} at ${at}${ `${user.tag} started typing in ${channel.id} at ${at}${
guildData !== undefined ? `\nGuild: ${guildData.guild.name}` : '' guildData !== undefined ? `\nGuild: ${guildData.guild.name}` : ''
}` }`
) )
}) })
client.on('voiceStateAdd', (state) => { client.on('voiceStateAdd', (state) => {
console.log('VC Join', state) console.log('VC Join', state)
}) })
client.on('voiceStateRemove', (state) => { client.on('voiceStateRemove', (state) => {
console.log('VC Leave', state) console.log('VC Leave', state)
}) })
client.on('messageReactionAdd', (reaction, user) => { client.on('messageReactionAdd', (reaction, user) => {
console.log(`${user.tag} reacted with ${reaction.emoji.name}`) console.log(`${user.tag} reacted with ${reaction.emoji.name}`)
}) })
client.on('messageReactionRemove', (reaction, user) => { client.on('messageReactionRemove', (reaction, user) => {
console.log(`${user.tag} removed reaction ${reaction.emoji.name}`) console.log(`${user.tag} removed reaction ${reaction.emoji.name}`)
}) })
client.on('messageReactionRemoveEmoji', (message, emoji) => { client.on('messageReactionRemoveEmoji', (message, emoji) => {
console.log(`All ${emoji.name} emoji reactions removed from ${message.id}`) console.log(`All ${emoji.name} emoji reactions removed from ${message.id}`)
}) })
client.on('messageReactionRemoveAll', (message) => { client.on('messageReactionRemoveAll', (message) => {
console.log(`All reactions remove from Message: ${message.id}`) console.log(`All reactions remove from Message: ${message.id}`)
}) })
// client.on('raw', (evt: string) => console.log(`EVENT: ${evt}`)) // client.on('raw', (evt: string) => console.log(`EVENT: ${evt}`))
const files = Deno.readDirSync('./src/test/cmds') const files = Deno.readDirSync('./src/test/cmds')
for (const file of files) { for (const file of files) {
const module = await import(`./cmds/${file.name}`) const module = await import(`./cmds/${file.name}`)
// eslint-disable-next-line new-cap // eslint-disable-next-line new-cap
const cmd = new module.default() const cmd = new module.default()
client.commands.add(cmd) client.commands.add(cmd)
console.log(`Loaded command ${cmd.name}!`) console.log(`Loaded command ${cmd.name}!`)
} }
console.log(`Loaded ${client.commands.count} commands!`) console.log(`Loaded ${client.commands.count} commands!`)
client.connect(TOKEN, Intents.create(['GUILD_MEMBERS', 'GUILD_PRESENCES'])) client.connect(TOKEN, Intents.create(['GUILD_MEMBERS', 'GUILD_PRESENCES']))

View File

@ -3,7 +3,7 @@ import { CommandContext } from '../../models/command.ts'
export default class AddEmojiCommand extends Command { export default class AddEmojiCommand extends Command {
name = 'addemoji' name = 'addemoji'
aliases = [ 'ae', 'emojiadd' ] aliases = ['ae', 'emojiadd']
args = 2 args = 2
guildOnly = true guildOnly = true
@ -12,11 +12,16 @@ export default class AddEmojiCommand extends Command {
if (name === undefined) return ctx.message.reply('No name was given!') if (name === undefined) return ctx.message.reply('No name was given!')
const url = ctx.argString.slice(name.length).trim() const url = ctx.argString.slice(name.length).trim()
if (url === '') return ctx.message.reply('No URL was given!') if (url === '') return ctx.message.reply('No URL was given!')
ctx.message.guild?.emojis.create(name, url).then(emoji => { ctx.message.guild?.emojis
.create(name, url)
.then((emoji) => {
if (emoji === undefined) throw new Error('Unknown') if (emoji === undefined) throw new Error('Unknown')
ctx.message.reply(`Successfuly added emoji ${emoji.toString()} ${emoji.name}!`) ctx.message.reply(
}).catch(e => { `Successfuly added emoji ${emoji.toString()} ${emoji.name}!`
)
})
.catch((e) => {
ctx.message.reply(`Failed to add emoji. Reason: ${e.message}`) ctx.message.reply(`Failed to add emoji. Reason: ${e.message}`)
}) })
} }
} }

View File

@ -2,17 +2,35 @@ import { Command, Embed } from '../../../mod.ts'
import { CommandContext } from '../../models/command.ts' import { CommandContext } from '../../models/command.ts'
export default class PingCommand extends Command { export default class PingCommand extends Command {
name = "mentions" name = 'mentions'
aliases = ["m"] aliases = ['m']
execute(ctx: CommandContext): void { execute(ctx: CommandContext): void {
const embed = new Embed() const embed = new Embed()
.setTitle('Mentions') .setTitle('Mentions')
.addField('Users', `${ctx.message.mentions.users.size === 0 ? `None` : ''}${ctx.message.mentions.users.map(u => u.toString()).join(", ")}`) .addField(
.addField('Channels', `${ctx.message.mentions.channels.size === 0 ? `None` : ''}${ctx.message.mentions.channels.map(u => u.toString()).join(", ")}`) 'Users',
.addField('Roles', `${ctx.message.mentions.roles.size === 0 ? `None` : ''}${ctx.message.mentions.roles.map(u => u.toString()).join(", ")}`) `${
.addField('Everyone?', ctx.message.mentions.everyone === true ? 'Yes' : 'No') ctx.message.mentions.users.size === 0 ? `None` : ''
}${ctx.message.mentions.users.map((u) => u.toString()).join(', ')}`
)
.addField(
'Channels',
`${
ctx.message.mentions.channels.size === 0 ? `None` : ''
}${ctx.message.mentions.channels.map((u) => u.toString()).join(', ')}`
)
.addField(
'Roles',
`${
ctx.message.mentions.roles.size === 0 ? `None` : ''
}${ctx.message.mentions.roles.map((u) => u.toString()).join(', ')}`
)
.addField(
'Everyone?',
ctx.message.mentions.everyone === true ? 'Yes' : 'No'
)
.setColor(0xff0000) .setColor(0xff0000)
ctx.message.channel.send(embed) ctx.message.channel.send(embed)
} }
} }

View File

@ -2,9 +2,9 @@ import { Command } from '../../../mod.ts'
import { CommandContext } from '../../models/command.ts' import { CommandContext } from '../../models/command.ts'
export default class PingCommand extends Command { export default class PingCommand extends Command {
name = "ping" name = 'ping'
execute(ctx: CommandContext): void { execute(ctx: CommandContext): void {
ctx.message.reply(`Pong! Latency: ${ctx.client.ping}ms`) ctx.message.reply(`Pong! Latency: ${ctx.client.ping}ms`)
} }
} }

View File

@ -1,20 +1,23 @@
import { Command, Member, CommandContext, Embed } from '../../../mod.ts' import { Command, Member, CommandContext, Embed } from '../../../mod.ts'
export default class UserinfoCommand extends Command { export default class UserinfoCommand extends Command {
name = "userinfo" name = 'userinfo'
guildOnly = true guildOnly = true
aliases = [ 'u', 'user' ] aliases = ['u', 'user']
async execute(ctx: CommandContext): Promise<void> { async execute(ctx: CommandContext): Promise<void> {
const member: Member = ctx.message.member as any const member: Member = ctx.message.member as any
const roles = await member.roles.array() const roles = await member.roles.array()
const embed = new Embed() const embed = new Embed()
.setTitle(`User Info`) .setTitle(`User Info`)
.setAuthor({ name: member.user.tag }) .setAuthor({ name: member.user.tag })
.addField("ID", member.id) .addField('ID', member.id)
.addField("Roles", roles.map(r => r.name).join(", ")) .addField('Roles', roles.map((r) => r.name).join(', '))
.addField('Permissions', JSON.stringify(member.permissions.has('ADMINISTRATOR'))) .addField(
.setColor(0xff00ff) 'Permissions',
ctx.channel.send(embed) JSON.stringify(member.permissions.has('ADMINISTRATOR'))
} )
} .setColor(0xff00ff)
ctx.channel.send(embed)
}
}

View File

@ -1,9 +1,11 @@
import { Webhook } from '../../mod.ts' import { Webhook } from '../../mod.ts'
import { WEBHOOK } from "./config.ts" import { WEBHOOK } from './config.ts'
const webhook = await Webhook.fromURL(WEBHOOK) const webhook = await Webhook.fromURL(WEBHOOK)
console.log('Fetched webhook!') console.log('Fetched webhook!')
webhook.send('Hello World', { webhook
name: 'OwO' .send('Hello World', {
}).then(() => 'Sent message!') name: 'OwO'
})
.then(() => 'Sent message!')

View File

@ -1,11 +1,24 @@
import { Client, Intents, GuildTextChannel, Message, ClientPresence, Member, Role, GuildChannel, Embed, Guild } from '../../mod.ts' import {
Client,
Intents,
Message,
ClientPresence,
Member,
Role,
GuildChannel,
Embed,
Guild,
EveryChannelTypes,
ChannelTypes,
GuildTextChannel
} from '../../mod.ts'
import { TOKEN } from './config.ts' import { TOKEN } from './config.ts'
const client = new Client({ const client = new Client({
presence: new ClientPresence({ presence: new ClientPresence({
name: 'Pokémon Sword', name: 'Pokémon Sword',
type: 'COMPETING' type: 'COMPETING'
}), })
// bot: false, // bot: false,
// cache: new RedisCacheAdapter({ // cache: new RedisCacheAdapter({
// hostname: '127.0.0.1', // hostname: '127.0.0.1',
@ -19,13 +32,19 @@ client.on('ready', () => {
client.on('debug', console.log) client.on('debug', console.log)
client.on('channelUpdate', (before: GuildTextChannel, after: GuildTextChannel) => { client.on('channelUpdate', (b: EveryChannelTypes, a: EveryChannelTypes) => {
console.log(before.send('', { if (b.type === ChannelTypes.GUILD_TEXT) {
embed: new Embed({ const before = (b as unknown) as GuildTextChannel
title: 'Channel Update', const after = (a as unknown) as GuildTextChannel
description: `Name Before: ${before.name}\nName After: ${after.name}` console.log(
}) before.send('', {
})) embed: new Embed({
title: 'Channel Update',
description: `Name Before: ${before.name}\nName After: ${after.name}`
})
})
)
}
}) })
client.on('messageCreate', async (msg: Message) => { client.on('messageCreate', async (msg: Message) => {
@ -35,26 +54,40 @@ client.on('messageCreate', async (msg: Message) => {
msg.reply(`Pong! Ping: ${client.ping}ms`) msg.reply(`Pong! Ping: ${client.ping}ms`)
} else if (msg.content === '!members') { } else if (msg.content === '!members') {
const col = await msg.guild?.members.collection() const col = await msg.guild?.members.collection()
const data = col?.array().map((c: Member, i: number) => { const data = col
return `${i + 1}. ${c.user.tag}` ?.array()
}).join("\n") as string .map((c: Member, i: number) => {
msg.channel.send("Member List:\n" + data) return `${i + 1}. ${c.user.tag}`
})
.join('\n') as string
msg.channel.send('Member List:\n' + data)
} else if (msg.content === '!guilds') { } else if (msg.content === '!guilds') {
const guilds = await msg.client.guilds.collection() const guilds = await msg.client.guilds.collection()
msg.channel.send('Guild List:\n' + (guilds.array().map((c: Guild, i: number) => { msg.channel.send(
return `${i + 1}. ${c.name} - ${c.memberCount} members` 'Guild List:\n' +
}).join("\n") as string)) (guilds
.array()
.map((c: Guild, i: number) => {
return `${i + 1}. ${c.name} - ${c.memberCount} members`
})
.join('\n') as string)
)
} else if (msg.content === '!roles') { } else if (msg.content === '!roles') {
const col = await msg.guild?.roles.collection() const col = await msg.guild?.roles.collection()
const data = col?.array().map((c: Role, i: number) => { const data = col
return `${i + 1}. ${c.name}` ?.array()
}).join("\n") as string .map((c: Role, i: number) => {
msg.channel.send("Roles List:\n" + data) return `${i + 1}. ${c.name}`
})
.join('\n') as string
msg.channel.send('Roles List:\n' + data)
} else if (msg.content === '!channels') { } else if (msg.content === '!channels') {
const col = await msg.guild?.channels.array() const col = await msg.guild?.channels.array()
const data = col?.map((c: GuildChannel, i: number) => { const data = col
return `${i + 1}. ${c.name}` ?.map((c: GuildChannel, i: number) => {
}).join("\n") as string return `${i + 1}. ${c.name}`
})
.join('\n') as string
msg.channel.send('Channels List:\n' + data) msg.channel.send('Channels List:\n' + data)
} }
}) })

View File

@ -1,10 +1,10 @@
import { UserPayload } from "./user.ts"; import { UserPayload } from './user.ts'
export interface ApplicationPayload { export interface ApplicationPayload {
id: string id: string
name: string name: string
icon: string icon: string
description: string description: string
summary: string summary: string
bot?: UserPayload bot?: UserPayload
} }

View File

@ -1,2 +1,2 @@
export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 export type ImageSize = 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048
export type ImageFormats = "jpg" | "jpeg" | "png" | "webp" | "gif" export type ImageFormats = 'jpg' | 'jpeg' | 'png' | 'webp' | 'gif'

View File

@ -8,7 +8,7 @@ import {
ActivityGame, ActivityGame,
ActivityPayload, ActivityPayload,
StatusType, StatusType,
ClientStatus, ClientStatus
} from './presence.ts' } from './presence.ts'
import { RolePayload } from './role.ts' import { RolePayload } from './role.ts'
import { UserPayload } from './user.ts' import { UserPayload } from './user.ts'
@ -27,7 +27,7 @@ export enum GatewayOpcodes { // 문서를 확인해본 결과 Opcode 5번은 비
REQUEST_GUILD_MEMBERS = 8, REQUEST_GUILD_MEMBERS = 8,
INVALID_SESSION = 9, INVALID_SESSION = 9,
HELLO = 10, HELLO = 10,
HEARTBEAT_ACK = 11, HEARTBEAT_ACK = 11
} }
/** /**
@ -47,7 +47,7 @@ export enum GatewayCloseCodes {
SHARDING_REQUIRED = 4011, SHARDING_REQUIRED = 4011,
INVALID_API_VERSION = 4012, INVALID_API_VERSION = 4012,
INVALID_INTENTS = 4013, INVALID_INTENTS = 4013,
DISALLOWED_INTENTS = 4014, DISALLOWED_INTENTS = 4014
} }
export enum GatewayIntents { export enum GatewayIntents {
@ -65,7 +65,7 @@ export enum GatewayIntents {
GUILD_MESSAGE_TYPING = 1 << 11, GUILD_MESSAGE_TYPING = 1 << 11,
DIRECT_MESSAGES = 1 << 12, DIRECT_MESSAGES = 1 << 12,
DIRECT_MESSAGE_REACTIONS = 1 << 13, DIRECT_MESSAGE_REACTIONS = 1 << 13,
DIRECT_MESSAGE_TYPING = 1 << 13, DIRECT_MESSAGE_TYPING = 1 << 13
} }
export enum GatewayEvents { export enum GatewayEvents {
@ -105,7 +105,7 @@ export enum GatewayEvents {
User_Update = 'USER_UPDATE', User_Update = 'USER_UPDATE',
Voice_Server_Update = 'VOICE_SERVER_UPDATE', Voice_Server_Update = 'VOICE_SERVER_UPDATE',
Voice_State_Update = 'VOICE_STATE_UPDATE', Voice_State_Update = 'VOICE_STATE_UPDATE',
Webhooks_Update = 'WEBHOOKS_UPDATE', Webhooks_Update = 'WEBHOOKS_UPDATE'
} }
export interface IdentityPayload { export interface IdentityPayload {

View File

@ -8,4 +8,4 @@ export interface GatewayBotPayload {
url: string url: string
shards: number shards: number
session_start_limit: ISessionStartLimit session_start_limit: ISessionStartLimit
} }

View File

@ -1,148 +1,148 @@
import { ApplicationPayload } from './application.ts' import { ApplicationPayload } from './application.ts'
import { ChannelPayload } from './channel.ts' import { ChannelPayload } from './channel.ts'
import { EmojiPayload } from './emoji.ts' import { EmojiPayload } from './emoji.ts'
import { PresenceUpdatePayload } from './gateway.ts' import { PresenceUpdatePayload } from './gateway.ts'
import { RolePayload } from './role.ts' import { RolePayload } from './role.ts'
import { UserPayload } from './user.ts' import { UserPayload } from './user.ts'
import { VoiceStatePayload } from './voice.ts' import { VoiceStatePayload } from './voice.ts'
export interface GuildPayload { export interface GuildPayload {
id: string id: string
name: string name: string
icon?: string icon?: string
icon_hash?: string icon_hash?: string
splash?: string splash?: string
discovery_splash?: string discovery_splash?: string
owner?: boolean owner?: boolean
owner_id: string owner_id: string
permissions?: string permissions?: string
region: string region: string
afk_channel_id?: string afk_channel_id?: string
afk_timeout: number afk_timeout: number
widget_enabled?: boolean widget_enabled?: boolean
widget_channel_id?: string widget_channel_id?: string
verification_level: string verification_level: string
default_message_notifications: string default_message_notifications: string
explicit_content_filter: string explicit_content_filter: string
roles: RolePayload[] roles: RolePayload[]
emojis: EmojiPayload[] emojis: EmojiPayload[]
features: GuildFeatures[] features: GuildFeatures[]
mfa_level: string mfa_level: string
application_id?: string application_id?: string
system_channel_id?: string system_channel_id?: string
system_channel_flags: string system_channel_flags: string
rules_channel_id?: string rules_channel_id?: string
joined_at?: string joined_at?: string
large?: boolean large?: boolean
unavailable: boolean unavailable: boolean
member_count?: number member_count?: number
voice_states?: VoiceStatePayload[] voice_states?: VoiceStatePayload[]
members?: MemberPayload[] members?: MemberPayload[]
channels?: ChannelPayload[] channels?: ChannelPayload[]
presences?: PresenceUpdatePayload[] presences?: PresenceUpdatePayload[]
max_presences?: number max_presences?: number
max_members?: number max_members?: number
vanity_url_code?: string vanity_url_code?: string
description?: string description?: string
banner?: string banner?: string
premium_tier: number premium_tier: number
premium_subscription_count?: number premium_subscription_count?: number
preferred_locale: string preferred_locale: string
public_updates_channel_id?: string public_updates_channel_id?: string
max_video_channel_users?: number max_video_channel_users?: number
approximate_number_count?: number approximate_number_count?: number
approximate_presence_count?: number approximate_presence_count?: number
} }
export interface MemberPayload { export interface MemberPayload {
user: UserPayload user: UserPayload
nick?: string nick?: string
roles: string[] roles: string[]
joined_at: string joined_at: string
premium_since?: string premium_since?: string
deaf: boolean deaf: boolean
mute: boolean mute: boolean
} }
export enum MessageNotification { export enum MessageNotification {
ALL_MESSAGES = 0, ALL_MESSAGES = 0,
ONLY_MENTIONS = 1, ONLY_MENTIONS = 1
} }
export enum ContentFilter { export enum ContentFilter {
DISABLED = 0, DISABLED = 0,
MEMBERS_WITHOUT_ROLES = 1, MEMBERS_WITHOUT_ROLES = 1,
ALL_MEMBERS = 3, ALL_MEMBERS = 3
} }
export enum MFA { export enum MFA {
NONE = 0, NONE = 0,
ELEVATED = 1, ELEVATED = 1
} }
export enum Verification { export enum Verification {
NONE = 0, NONE = 0,
LOW = 1, LOW = 1,
MEDIUM = 2, MEDIUM = 2,
HIGH = 3, HIGH = 3,
VERY_HIGH = 4, VERY_HIGH = 4
} }
export enum PremiumTier { export enum PremiumTier {
NONE = 0, NONE = 0,
TIER_1 = 1, TIER_1 = 1,
TIER_2 = 2, TIER_2 = 2,
TIER_3 = 3, TIER_3 = 3
} }
export enum SystemChannelFlags { export enum SystemChannelFlags {
SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0, SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0,
SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1, SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1
} }
export type GuildFeatures = export type GuildFeatures =
| 'INVITE_SPLASH' | 'INVITE_SPLASH'
| 'VIP_REGIONS' | 'VIP_REGIONS'
| 'VANITY_URL' | 'VANITY_URL'
| 'VERIFIED' | 'VERIFIED'
| 'PARTNERED' | 'PARTNERED'
| 'PUBLIC' | 'PUBLIC'
| 'COMMERCE' | 'COMMERCE'
| 'NEWS' | 'NEWS'
| 'DISCOVERABLE' | 'DISCOVERABLE'
| 'FEATURABLE' | 'FEATURABLE'
| 'ANIMATED_ICON' | 'ANIMATED_ICON'
| 'BANNER' | 'BANNER'
export enum IntegrationExpireBehavior { export enum IntegrationExpireBehavior {
REMOVE_ROLE = 0, REMOVE_ROLE = 0,
KICK = 1, KICK = 1
} }
export interface IntegrationAccountPayload { export interface IntegrationAccountPayload {
id: string id: string
name: string name: string
} }
export interface GuildIntegrationPayload { export interface GuildIntegrationPayload {
id: string id: string
name: string name: string
type: string type: string
enabled: boolean enabled: boolean
syncing?: boolean syncing?: boolean
role_id?: string role_id?: string
enable_emoticons?: boolean enable_emoticons?: boolean
expire_behaviour?: IntegrationExpireBehavior expire_behaviour?: IntegrationExpireBehavior
expire_grace_period?: number expire_grace_period?: number
user?: UserPayload user?: UserPayload
account: IntegrationAccountPayload account: IntegrationAccountPayload
synced_at?: string // Actually a ISO Timestamp, but we parse in constructor' synced_at?: string // Actually a ISO Timestamp, but we parse in constructor'
subscriber_count?: number subscriber_count?: number
revoked?: boolean revoked?: boolean
application?: ApplicationPayload application?: ApplicationPayload
} }
export interface GuildBanPayload { export interface GuildBanPayload {
reason: string | null reason: string | null
user: UserPayload user: UserPayload
} }

View File

@ -31,5 +31,5 @@ export const PermissionFlags: { [key: string]: number } = {
MANAGE_NICKNAMES: 1 << 27, MANAGE_NICKNAMES: 1 << 27,
MANAGE_ROLES: 1 << 28, MANAGE_ROLES: 1 << 28,
MANAGE_WEBHOOKS: 1 << 29, MANAGE_WEBHOOKS: 1 << 29,
MANAGE_EMOJIS: 1 << 30, MANAGE_EMOJIS: 1 << 30
} }

View File

@ -56,7 +56,7 @@ export enum ActivityFlags {
SPECTATE = 1 << 2, SPECTATE = 1 << 2,
JOIN_REQUEST = 1 << 3, JOIN_REQUEST = 1 << 3,
SYNC = 1 << 4, SYNC = 1 << 4,
PLAY = 1 << 5, PLAY = 1 << 5
} }
export type ActivityType = export type ActivityType =

Some files were not shown because too many files have changed in this diff Show More