From ca7d143ddcdc36d3355c048c1b7b79fdbc4c142a Mon Sep 17 00:00:00 2001 From: Helloyunho Date: Fri, 23 Oct 2020 00:50:47 +0900 Subject: [PATCH] Finally got somewhat working :+1: Co-Authored-By: Aki <71239005+AkiaCode@users.noreply.github.com> Co-Authored-By: Lee Hyun Co-Authored-By: khk4912 <30457148+khk4912@users.noreply.github.com> Co-Authored-By: Choi Minseo Co-Authored-By: Junseo Park Co-Authored-By: Y <8479056+yky4589@users.noreply.github.com> --- src/consts/urlsAndVersions.ts | 2 +- src/models/client.ts | 23 +++ src/models/gateway.ts | 167 +++++++++++----- src/structures/base.ts | 13 +- src/structures/channel.ts | 29 +++ src/structures/dm.ts | 9 + src/structures/embed.ts | 32 +++ src/structures/emoji.ts | 26 +++ src/structures/guild.ts | 106 ++++++++++ src/structures/guildChannel.ts | 9 + src/structures/invite.ts | 29 +++ src/structures/member.ts | 28 +++ src/structures/message.ts | 70 ++++++- src/structures/role.ts | 26 +++ src/structures/textChannel.ts | 31 +++ src/structures/user.ts | 36 ++++ src/test/index.ts | 8 + src/test/test.ts | 25 +++ src/types/channelTypes.ts | 342 +++++++++++++++++---------------- src/types/emojiTypes.ts | 22 ++- src/types/endpoint.ts | 18 +- src/types/gatewayResponse.ts | 4 +- src/types/gatewayTypes.ts | 323 ++++++++++++++++++++++++++++++- src/types/guildTypes.ts | 178 +++++++++-------- src/types/inviteTypes.ts | 24 ++- src/types/presenceTypes.ts | 92 ++++----- src/types/roleTypes.ts | 20 +- src/types/snowflake.ts | 19 +- src/types/templateTypes.ts | 29 +-- src/types/userTypes.ts | 6 +- src/types/voiceTypes.ts | 13 +- src/types/webhookTypes.ts | 24 +-- 32 files changed, 1355 insertions(+), 428 deletions(-) create mode 100644 src/models/client.ts create mode 100644 src/structures/dm.ts create mode 100644 src/structures/emoji.ts create mode 100644 src/structures/guildChannel.ts create mode 100644 src/structures/invite.ts create mode 100644 src/structures/member.ts create mode 100644 src/structures/role.ts create mode 100644 src/structures/user.ts create mode 100644 src/test/index.ts create mode 100644 src/test/test.ts diff --git a/src/consts/urlsAndVersions.ts b/src/consts/urlsAndVersions.ts index c142df9..128dc52 100644 --- a/src/consts/urlsAndVersions.ts +++ b/src/consts/urlsAndVersions.ts @@ -1,6 +1,6 @@ export const DISCORD_API_URL = 'https://discord.com/api' -export const DISCORD_GATEWAY_URL = 'wss://gateway.discord.com' +export const DISCORD_GATEWAY_URL = 'wss://gateway.discord.gg' export const DISCORD_CDN_URL = 'https://cdn.discordapp.com' diff --git a/src/models/client.ts b/src/models/client.ts new file mode 100644 index 0000000..a200c95 --- /dev/null +++ b/src/models/client.ts @@ -0,0 +1,23 @@ +import { User } from '../structures/user.ts' +import { GatewayIntents } from '../types/gatewayTypes.ts' +import { Gateway } from './gateway.ts' + +/** + * Discord Client. + */ +export class Client { + gateway?: Gateway + user?: User + ping = 0 + + constructor () {} + + /** + * This function is used for connect to discord. + * @param token Your token. This is required. + * @param intents Gateway intents in array. This is required. + */ + connect (token: string, intents: GatewayIntents[]) { + this.gateway = new Gateway(this, token, intents) + } +} diff --git a/src/models/gateway.ts b/src/models/gateway.ts index d68bf3b..4885bf4 100644 --- a/src/models/gateway.ts +++ b/src/models/gateway.ts @@ -1,10 +1,16 @@ -import { inflate } from 'https://deno.land/x/denoflate/mod.ts' +import { unzlib } from 'https://deno.land/x/denoflate/mod.ts' +import { Client } from './client.ts' import { DISCORD_GATEWAY_URL, DISCORD_API_VERSION } from '../consts/urlsAndVersions.ts' import { GatewayResponse } from '../types/gatewayResponse.ts' -import { GatewayOpcodes, GatewayIntents } from '../types/gatewayTypes.ts' +import { + GatewayOpcodes, + GatewayIntents, + GatewayEvents +} from '../types/gatewayTypes.ts' +import { User } from '../structures/user.ts' /** * Handles Discord gateway connection. @@ -15,20 +21,31 @@ import { GatewayOpcodes, GatewayIntents } from '../types/gatewayTypes.ts' class Gateway { websocket: WebSocket token: string - intents: [GatewayIntents] + intents: GatewayIntents[] connected = false initialized = false heartbeatInterval = 0 heartbeatIntervalID?: number + heartbeatCheckerIntervalID?: number sequenceID?: number + sessionID?: string + lastPingTimestemp = 0 heartbeatServerResponded = false + client: Client - constructor (token: string, intents: [GatewayIntents]) { - this.websocket = new WebSocket( - `${DISCORD_GATEWAY_URL}/?v=${DISCORD_API_VERSION}&encoding=json` - ) + constructor (client: Client, token: string, intents: GatewayIntents[]) { this.token = token this.intents = intents + this.client = client + this.websocket = new WebSocket( + `${DISCORD_GATEWAY_URL}/?v=${DISCORD_API_VERSION}&encoding=json`, + [] + ) + this.websocket.binaryType = 'arraybuffer' + this.websocket.onopen = this.onopen.bind(this) + this.websocket.onmessage = this.onmessage.bind(this) + this.websocket.onclose = this.onclose.bind(this) + this.websocket.onerror = this.onerror.bind(this) } onopen () { @@ -41,16 +58,8 @@ class Gateway { data = new Uint8Array(data) } if (data instanceof Uint8Array) { - const dataSuffix = data.slice(-4) - - if ( - dataSuffix[0] === 0 && - dataSuffix[1] === 0 && - dataSuffix[2] === 0xff && - dataSuffix[3] === 0xff - ) { - data = inflate(data) - } + data = unzlib(data) + data = new TextDecoder('utf-8').decode(data) } const { op, d, s, t }: GatewayResponse = JSON.parse(data) @@ -59,56 +68,118 @@ class Gateway { case GatewayOpcodes.HELLO: this.heartbeatInterval = d.heartbeat_interval this.heartbeatIntervalID = setInterval(() => { + if (this.heartbeatServerResponded) { + this.heartbeatServerResponded = false + } else { + clearInterval(this.heartbeatIntervalID) + clearInterval(this.heartbeatCheckerIntervalID) + this.websocket.close() + this.initWebsocket() + return + } + this.websocket.send( JSON.stringify({ op: GatewayOpcodes.HEARTBEAT, d: this.sequenceID ?? null }) ) - - if (this.heartbeatServerResponded) { - this.heartbeatServerResponded = false - } else { - // TODO: Add heartbeat failed error - } + this.lastPingTimestemp = Date.now() }, this.heartbeatInterval) - this.websocket.send( - JSON.stringify({ - token: this.token, - properties: { - $os: Deno.build.os, - $browser: 'discord.deno', - $device: 'discord.deno' - }, - compress: true, - shard: [0, 1], // TODO: Make sharding possible - intents: this.intents.reduce( - (previous, current) => previous | current, - 0 - ), - presence: { - // TODO: User should can customize this - status: 'online', - since: null, - afk: false - } - }) - ) + if (!this.initialized) { + this.sendIdentify() + this.initialized = true + } else { + this.websocket.send( + JSON.stringify({ + op: GatewayOpcodes.RESUME, + d: { + token: this.token, + session_id: this.sessionID, + seq: this.sequenceID + } + }) + ) + } break case GatewayOpcodes.HEARTBEAT_ACK: this.heartbeatServerResponded = true + this.client.ping = Date.now() - this.lastPingTimestemp + break + + case GatewayOpcodes.INVALID_SESSION: + setTimeout(this.sendIdentify, 3000) break case GatewayOpcodes.DISPATCH: - switch (t) { + if (s !== null) { + this.sequenceID = s } - + switch (t) { + case GatewayEvents.Ready: + this.client.user = new User(this.client, d.user) + this.sessionID = d.session_id + break + default: + break + } + break default: - return + break } } + + onclose (event: CloseEvent) { + // TODO: Handle close event codes. + } + + onerror (event: Event | ErrorEvent) { + const eventError = event as ErrorEvent + + console.log(eventError) + } + + sendIdentify () { + this.websocket.send( + JSON.stringify({ + op: GatewayOpcodes.IDENTIFY, + d: { + token: this.token, + properties: { + $os: Deno.build.os, + $browser: 'discord.deno', + $device: 'discord.deno' + }, + compress: true, + shard: [0, 1], // TODO: Make sharding possible + intents: this.intents.reduce( + (previous, current) => previous | current, + 0 + ), + presence: { + // TODO: User should can customize this + status: 'online', + since: null, + afk: false + } + } + }) + ) + } + + initWebsocket () { + this.websocket = new WebSocket( + `${DISCORD_GATEWAY_URL}/?v=${DISCORD_API_VERSION}&encoding=json`, + [] + ) + this.websocket.binaryType = 'arraybuffer' + this.websocket.onopen = this.onopen.bind(this) + this.websocket.onmessage = this.onmessage.bind(this) + this.websocket.onclose = this.onclose.bind(this) + this.websocket.onerror = this.onerror.bind(this) + } } export { Gateway } diff --git a/src/structures/base.ts b/src/structures/base.ts index a2ccbc5..9bd008b 100644 --- a/src/structures/base.ts +++ b/src/structures/base.ts @@ -1,10 +1,11 @@ // 일단 대충 여러 봇 라이브러리에서 본 구조 가져오는 중.. +import { Client } from '../models/client.ts' -class Base { - id?: string - constructor (id: string | undefined) { - if (id) { - this.id = id - } +export class Base { + // property 읍 + client: Client + constructor (client: Client) { + this.client = client } } +// discord.js 보는중 diff --git a/src/structures/channel.ts b/src/structures/channel.ts index e69de29..50e5ae7 100644 --- a/src/structures/channel.ts +++ b/src/structures/channel.ts @@ -0,0 +1,29 @@ +import { Client } from '../models/client.ts' +import { ChannelPayload, ChannelTypes } from '../types/channelTypes.ts' +import { Base } from './base.ts' +import { PrivateChannel } from './dm.ts' +import { TextChannel } from './textChannel.ts' + +export class Channel extends Base { + type: ChannelTypes + id: string + + constructor (client: Client, data: ChannelPayload) { + super(client) + this.type = data.type + this.id = data.id + } + + get mention () { + return `<#${this.id}>` + } + + static from (data: ChannelPayload, client: Client) { + switch (data.type) { + case ChannelTypes.GUILD_TEXT: + return new TextChannel(client, data) + case ChannelTypes.DM: + return new PrivateChannel(client, data) + } + } +} diff --git a/src/structures/dm.ts b/src/structures/dm.ts new file mode 100644 index 0000000..3540419 --- /dev/null +++ b/src/structures/dm.ts @@ -0,0 +1,9 @@ +import { Client } from '../models/client.ts' +import { ChannelPayload } from '../types/channelTypes.ts' +import { Channel } from './channel.ts' + +export class PrivateChannel extends Channel implements ChannelPayload { + constructor (client: Client, data: ChannelPayload) { + super(client, data) + } +} diff --git a/src/structures/embed.ts b/src/structures/embed.ts index e69de29..13331ce 100644 --- a/src/structures/embed.ts +++ b/src/structures/embed.ts @@ -0,0 +1,32 @@ +import { Client } from '../models/client.ts' +import { + EmbedAuthor, + EmbedField, + EmbedFooter, + EmbedImage, + EmbedPayload, + EmbedProvider, + EmbedThumbnail, + EmbedTypes, + EmbedVideo +} from '../types/channelTypes.ts' +import { Base } from './base.ts' + +export class Embed extends Base implements EmbedPayload { + title?: string + type?: EmbedTypes + description?: string + url?: string + timestamp?: string + color?: number + footer?: EmbedFooter + image?: EmbedImage + thumbnail?: EmbedThumbnail + video?: EmbedVideo + provider?: EmbedProvider + author?: EmbedAuthor + fields?: EmbedField[] + constructor (client: Client, data: EmbedPayload) { + super(client) + } +} diff --git a/src/structures/emoji.ts b/src/structures/emoji.ts new file mode 100644 index 0000000..23b2883 --- /dev/null +++ b/src/structures/emoji.ts @@ -0,0 +1,26 @@ +import { Client } from '../models/client.ts' +import { EmojiPayload } from '../types/emojiTypes.ts' +import { Base } from './base.ts' +import { User } from './user.ts' + +export class Emoji extends Base implements EmojiPayload { + id: string + name: string + roles?: [] + user?: User + require_colons?: boolean + managed?: boolean + animated?: boolean + available?: boolean + constructor (client: Client, data: EmojiPayload) { + super(client) + this.id = data.id + this.name = data.name + this.roles = data.roles + this.user = data.user + this.require_colons = data.require_colons + this.managed = data.managed + this.animated = data.animated + this.available = data.available + } +} diff --git a/src/structures/guild.ts b/src/structures/guild.ts index e69de29..bdac283 100644 --- a/src/structures/guild.ts +++ b/src/structures/guild.ts @@ -0,0 +1,106 @@ +import { Client } from '../models/client.ts' +import { EmojiPayload } from '../types/emojiTypes.ts' +import { GuildFeatures, GuildPayload } from '../types/guildTypes.ts' +import { PresenceUpdatePayload } from '../types/presenceTypes.ts' +import { VoiceStatePayload } from '../types/voiceTypes.ts' +import { Base } from './base.ts' +import { Channel } from './channel.ts' +import { Emoji } from './emoji.ts' +import { Member } from './member.ts' +import { Role } from './role.ts' + +export class Guild extends Base implements GuildPayload { + id: string + name: string + icon: string | undefined + icon_hash?: string | undefined + splash: string | undefined + discovery_splash: string | undefined + owner?: boolean | undefined + owner_id: string + permissions?: string | undefined + region: string + afk_channel_id: string | undefined + afk_timeout: number + widget_enabled?: boolean | undefined + widge_channel_id?: string | undefined + verification_level: string + default_message_notifications: string + explicit_content_filter: string + roles: Role[] + emojis: Emoji[] + features: GuildFeatures[] + mfa_level: string + application_id: string | undefined + system_channel_id: string | undefined + system_channel_flags: string + rules_channel_id: string | undefined + joined_at?: string | undefined + large?: boolean | undefined + unavailable: boolean + member_count?: number | undefined + voice_states?: VoiceStatePayload[] | undefined + members?: Member[] | undefined + channels?: Channel[] | undefined + presences?: PresenceUpdatePayload[] | undefined + max_presences?: number | undefined + max_members?: number | undefined + vanity_url_code: string | undefined + description: string | undefined + banner: string | undefined + premium_tier: number + premium_subscription_count?: number | undefined + preferred_locale: string + public_updates_channel_id: string | undefined + max_video_channel_users?: number | undefined + approximate_number_count?: number | undefined + approximate_presence_count?: number | undefined + + constructor (client: Client, data: GuildPayload) { + super(client) + this.id = data.id + this.name = data.name + this.icon = data.icon + this.icon_hash = data.icon_hash + this.splash = data.splash + this.discovery_splash = data.discovery_splash + this.owner = data.owner + this.owner_id = data.owner_id + this.permissions = data.permissions + this.region = data.region + this.afk_timeout = data.afk_timeout + this.afk_channel_id = data.afk_channel_id + this.widget_enabled = data.widget_enabled + this.widge_channel_id = data.widge_channel_id + this.verification_level = data.verification_level + this.default_message_notifications = data.default_message_notifications + this.explicit_content_filter = data.explicit_content_filter + this.roles = data.roles + this.emojis = data.emojis + this.features = data.features + this.mfa_level = data.mfa_level + this.system_channel_id = data.system_channel_id + this.system_channel_flags = data.system_channel_flags + this.rules_channel_id = data.rules_channel_id + this.joined_at = data.joined_at + this.large = data.large + this.unavailable = data.unavailable + this.member_count = data.member_count + this.voice_states = data.voice_states + this.members = data.members + this.channels = data.channels + this.presences = data.presences + this.max_presences = data.max_presences + this.max_members = data.max_members + this.vanity_url_code = data.vanity_url_code + this.description = data.description + this.banner = data.banner + this.premium_tier = data.premium_tier + this.premium_subscription_count = data.premium_subscription_count + this.preferred_locale = data.preferred_locale + this.public_updates_channel_id = data.public_updates_channel_id + this.max_video_channel_users = data.max_video_channel_users + this.approximate_number_count = data.approximate_number_count + this.approximate_presence_count = data.approximate_presence_count + } +} diff --git a/src/structures/guildChannel.ts b/src/structures/guildChannel.ts new file mode 100644 index 0000000..576dfb7 --- /dev/null +++ b/src/structures/guildChannel.ts @@ -0,0 +1,9 @@ +import { Client } from '../models/client.ts' +import { ChannelPayload } from '../types/channelTypes.ts' +import { Channel } from './channel.ts' + +export class GuildChannel extends Channel { + constructor (client: Client, data: ChannelPayload) { + super(client, data) + } +} diff --git a/src/structures/invite.ts b/src/structures/invite.ts new file mode 100644 index 0000000..50743f5 --- /dev/null +++ b/src/structures/invite.ts @@ -0,0 +1,29 @@ +import { Client } from '../models/client.ts' +import { Channel } from '../structures/channel.ts' +import { Guild } from '../structures/guild.ts' +import { User } from '../structures/user.ts' +import { InvitePayload } from '../types/inviteTypes.ts' +import { Base } from './base.ts' + +export class Invite extends Base implements InvitePayload { + code: string + guild?: Guild + channel: Channel + inviter?: User + target_user?: User + target_user_type?: number + approximate_presence_count?: number + approximate_member_count?: number + + constructor (client: Client, data: InvitePayload) { + super(client) + this.code = data.code + this.guild = data.guild + this.channel = data.channel + this.inviter = data.inviter + this.target_user = data.target_user + this.target_user_type = data.target_user_type + this.approximate_member_count = data.approximate_member_count + this.approximate_presence_count = data.approximate_presence_count + } +} diff --git a/src/structures/member.ts b/src/structures/member.ts new file mode 100644 index 0000000..7208ea9 --- /dev/null +++ b/src/structures/member.ts @@ -0,0 +1,28 @@ +import { Client } from '../models/client.ts' +import { MemberPayload } from '../types/guildTypes.ts' +import { UserPayload } from '../types/userTypes.ts' +import { Base } from './base.ts' +import { Guild } from './guild.ts' +import { Role } from './role.ts' +import { User } from './user.ts' + +export class Member extends Base implements MemberPayload { + user: User + nick: string | undefined + roles: Role[] + joined_at: string + premium_since?: string | undefined + deaf: boolean + mute: boolean + + constructor (client: Client, data: MemberPayload) { + super(client) + this.user = data.user + this.nick = data.nick + this.roles = data.roles + this.joined_at = data.joined_at + this.premium_since = data.premium_since + this.deaf = data.deaf + this.mute = data.mute + } +} diff --git a/src/structures/message.ts b/src/structures/message.ts index 3c63375..a72acee 100644 --- a/src/structures/message.ts +++ b/src/structures/message.ts @@ -1 +1,69 @@ -// 여긴가 +import { Base } from './base.ts' +import { + Attachment, + ChannelMention, + EmbedPayload, + MessageActivity, + MessageApplication, + MessagePayload, + MessageReference, + Reaction +} from '../types/channelTypes.ts' +import { Client } from '../models/client.ts' +import { User } from './user.ts' +import { Role } from './role.ts' +import { Embed } from './embed.ts' + +class Message extends Base implements MessagePayload { + id: string + channel_id: string + guild_id?: string | undefined + author: User + member?: any + content: string + timestamp: string + edited_timestamp: string | undefined + tts: boolean + mention_everyone: boolean + mentions: User[] + mention_roles: Role[] + mention_channels?: ChannelMention[] | undefined + attachments: Attachment[] + embeds: EmbedPayload[] + reactions?: Reaction[] | undefined + nonce?: string | number | undefined + pinned: boolean + webhook_id?: string | undefined + type: number + activity?: MessageActivity + application?: MessageApplication + message_reference?: MessageReference + flags?: number | undefined + + constructor (client: Client, data: MessagePayload) { + super(client) + this.id = data.id + this.channel_id = data.channel_id + this.guild_id = data.guild_id + this.author = data.author + this.member = data.member + this.content = data.content + this.timestamp = data.timestamp + this.edited_timestamp = data.edited_timestamp + this.tts = data.tts + this.mention_everyone = data.mention_everyone + this.mentions = data.mentions + this.mention_roles = data.mention_roles + this.attachments = data.attachments + this.embeds = data.embeds + this.reactions = data.reactions + this.nonce = data.nonce + this.pinned = data.pinned + this.webhook_id = data.webhook_id + this.type = data.type + this.activity = data.activity + this.application = data.application + this.message_reference = data.message_reference + this.flags = data.flags + } +} diff --git a/src/structures/role.ts b/src/structures/role.ts new file mode 100644 index 0000000..2148bbf --- /dev/null +++ b/src/structures/role.ts @@ -0,0 +1,26 @@ +import { Client } from '../models/client.ts' +import { Base } from './base.ts' +import { RolePayload } from '../types/roleTypes.ts' + +export class Role extends Base implements RolePayload { + id: string + name: string + color: number + hoist: boolean + position: number + permissions: string + managed: boolean + mentionable: boolean + + constructor (client: Client, data: RolePayload) { + super(client) + this.id = data.id + this.name = data.name + this.color = data.color + this.hoist = data.hoist + this.position = data.position + this.permissions = data.permissions + this.managed = data.managed + this.mentionable = data.mentionable + } +} diff --git a/src/structures/textChannel.ts b/src/structures/textChannel.ts index e69de29..83c9392 100644 --- a/src/structures/textChannel.ts +++ b/src/structures/textChannel.ts @@ -0,0 +1,31 @@ +import { Client } from '../models/client.ts' +import { GuildChannel } from './guildChannel.ts' +import { ChannelPayload } from '../types/channelTypes.ts' +import { User } from './user.ts' + +export class TextChannel extends GuildChannel implements ChannelPayload { + id: string + type: number + guild_id?: string | undefined + position?: number | undefined + approximate_member_count?: any + name?: string | undefined + topic?: string | undefined + nsfw?: boolean | undefined + last_message_id?: string | undefined + bitrate?: number | undefined + user_limit?: number | undefined + rate_limit_per_user?: number | undefined + recipients?: User + icon?: string | undefined + owner_id?: string | undefined + application_id?: string | undefined + parent_id?: string | undefined + last_pin_timestamp?: string | undefined + + constructor (client: Client, data: ChannelPayload) { + super(client, data) + this.id = data.id + this.type = data.type + } +} diff --git a/src/structures/user.ts b/src/structures/user.ts new file mode 100644 index 0000000..ea7f64e --- /dev/null +++ b/src/structures/user.ts @@ -0,0 +1,36 @@ +import { Client } from '../models/client.ts' +import { UserPayload } from '../types/userTypes.ts' +import { Base } from './base.ts' + +export class User extends Base implements UserPayload { + id: string + username: string + discriminator: string + avatar?: string + bot?: boolean + system?: boolean + mfa_enabled?: boolean + locale?: string + verified?: boolean + email?: string + flags?: number + premium_type?: 0 | 1 | 2 + public_flags?: number + + constructor (client: Client, data: UserPayload) { + super(client) + this.id = data.id + this.username = data.username + this.discriminator = data.discriminator + this.avatar = data.avatar + this.bot = data.bot + this.system = data.system + this.mfa_enabled = data.mfa_enabled + this.locale = data.locale + this.verified = data.verified + this.email = data.email + this.flags = data.flags + this.premium_type = data.premium_type + this.public_flags = data.public_flags + } +} diff --git a/src/test/index.ts b/src/test/index.ts new file mode 100644 index 0000000..5b582bf --- /dev/null +++ b/src/test/index.ts @@ -0,0 +1,8 @@ +import { Client } from '../models/client.ts' +import { GatewayIntents } from '../types/gatewayTypes.ts' + +const bot = new Client() + +bot.connect('NDMzMjc2NDAyOTM1MjY3MzI4.WszOGA.KlnMe_LImd1DxcurGvj_x0HOEmc', [ + GatewayIntents.GUILD_MESSAGES +]) diff --git a/src/test/test.ts b/src/test/test.ts new file mode 100644 index 0000000..cc58873 --- /dev/null +++ b/src/test/test.ts @@ -0,0 +1,25 @@ +// How to run: +// deno run --allow-net=echo.websocket.org https://deno.land/posts/whats-new-in-deno-1-4/websocket.js + +// Start the connection to the WebSocket server at echo.websocket.org +const ws = new WebSocket('ws://echo.websocket.org/') + +// Register event listeners for the open, close, and message events +ws.onopen = () => { + console.log('WebSocket ready!') + + // Send a message over the WebSocket to the server + ws.send('Hello World!') +} +ws.onmessage = message => { + // Log the message we recieve: + console.log('Received data:', message.data) +} +ws.onclose = () => console.log('WebSocket closed!') +ws.onerror = err => console.log('WebSocket error:', err) + +// When running this the following is logged to the console: +// +// WebSocket ready! +// Received data: Hello World! +// WebSocket closed! diff --git a/src/types/channelTypes.ts b/src/types/channelTypes.ts index 20a5dbe..5b55656 100644 --- a/src/types/channelTypes.ts +++ b/src/types/channelTypes.ts @@ -1,231 +1,251 @@ -interface Channel { - id: string - type: number - guild_id?: string - position?: number - approximate_member_count?: Overwrite - name?: string - topic?: string | undefined - nsfw?: boolean - last_message_id?: string - bitrate?: number - user_limit?: number - rate_limit_per_user?: number - recipients?: User - icon?: string | undefined - owner_id?: string - application_id?: string - parent_id?: string | undefined - last_pin_timestamp?: string +import { Member } from '../structures/member.ts' +import { Role } from '../structures/role.ts' +import { User } from '../structures/user.ts' +import { EmojiPayload } from './emojiTypes.ts' + +interface ChannelPayload { + id: string + type: ChannelTypes + guild_id?: string + position?: number + approximate_member_count?: Overwrite + name?: string + topic?: string + nsfw?: boolean + last_message_id?: string + bitrate?: number + user_limit?: number + rate_limit_per_user?: number + recipients?: User + icon?: string + owner_id?: string + application_id?: string + parent_id?: string + last_pin_timestamp?: string } interface Overwrite { - id: string - type: number - allow: string - deny: string + id: string + type: number + allow: string + deny: string } enum ChannelTypes { - GUILD_TEXT = 0, - DM = 1, - GUILD_VOICE = 2, - GROUP_DM = 3, - GUILD_CATEGORY = 4, - GUILD_NEWS = 5, - GUILD_STORE = 6 + GUILD_TEXT = 0, + DM = 1, + GUILD_VOICE = 2, + GROUP_DM = 3, + GUILD_CATEGORY = 4, + GUILD_NEWS = 5, + GUILD_STORE = 6 } -interface Message { - id: string - channel_id: string - guild_id?: string - suthor: User - member?: GuildMember - content: string - timestamp: string - edited_timestamp: string | undefined - tts: boolean - mention_everyone: boolean - mentions: User[] - mention_roles: Role[] - mention_channels?: ChannelMention[] - attachments: Attachment[] - embeds: Embed[] - reactions?: Reaction[] - nonce?: number | string - pinned: boolean - webhook_id?: string - type: number - activity?: MessageActivity - application?: MessageApplication - message_reference?: MessageReference - flags?: number +interface MessagePayload { + id: string + channel_id: string + guild_id?: string + author: User + member?: Member + content: string + timestamp: string + edited_timestamp: string | undefined + tts: boolean + mention_everyone: boolean + mentions: User[] + mention_roles: Role[] + mention_channels?: ChannelMention[] + attachments: Attachment[] + embeds: EmbedPayload[] + reactions?: Reaction[] + nonce?: number | string + pinned: boolean + webhook_id?: string + type: number + activity?: MessageActivity + application?: MessageApplication + message_reference?: MessageReference + flags?: number } interface ChannelMention { - id: string - guild_id: string - type: ChannelTypes - name: string + id: string + guild_id: string + type: ChannelTypes + name: string } interface Attachment { - id: string - filename: string - size: number - url: string - proxy_url: string - height: number | undefined - width: number | undefined + id: string + filename: string + size: number + url: string + proxy_url: string + height: number | undefined + width: number | undefined } -interface Embed { - title?: string - type?: EmbedTypes - description?: string - url?: string - timestamp?: string - color?: number - footer?: EmbedFooter - image?: EmbedImage - thumbnail?: EmbedThumbnail - video?: EmbedVideo - provider?: EmbedProvider - author?: EmbedAuthor - fields?: EmbedField[] +interface EmbedPayload { + title?: string + type?: EmbedTypes + description?: string + url?: string + timestamp?: string + color?: number + footer?: EmbedFooter + image?: EmbedImage + thumbnail?: EmbedThumbnail + video?: EmbedVideo + provider?: EmbedProvider + author?: EmbedAuthor + fields?: EmbedField[] } -type EmbedTypes = - | "rich" - | "image" - | "video" - | "gifv" - | "article" - | "link" +type EmbedTypes = 'rich' | 'image' | 'video' | 'gifv' | 'article' | 'link' interface EmbedField { - name: string - value: string - inline?: boolean + name: string + value: string + inline?: boolean } interface EmbedAuthor { - name?: string - url?: string - icon_url?: string - proxy_icon_url?: string + name?: string + url?: string + icon_url?: string + proxy_icon_url?: string } interface EmbedFooter { - text: string - icon_url?: string - proxy_icon_url?: string + text: string + icon_url?: string + proxy_icon_url?: string } interface EmbedImage { - url?: string - proxy_url?: string - height?: number - width?: number + url?: string + proxy_url?: string + height?: number + width?: number } interface EmbedProvider { - name?: string - url?: string + name?: string + url?: string } interface EmbedVideo { - url?: string - height?: number - width?: number + url?: string + height?: number + width?: number } interface EmbedThumbnail { - url?: string - proxy_url?: string - height?: number - width?: number + url?: string + proxy_url?: string + height?: number + width?: number } interface Reaction { - count: number - me: boolean - emoji: Emoji + count: number + me: boolean + emoji: EmojiPayload } interface MessageActivity { - type: MessageTypes - party_id?: string + type: MessageTypes + party_id?: string } interface MessageApplication { - id: string - cover_image?: string - desription: string - icon: string | undefined - name: string + id: string + cover_image?: string + desription: string + icon: string | undefined + name: string } interface MessageReference { - message_id?: string - channel_id?: string - guild_id?: string + message_id?: string + channel_id?: string + guild_id?: string } enum MessageTypes { - DEFAULT = 0, - RECIPIENT_ADD = 1, - RECIPIENT_REMOVE = 2, - CALL = 3, - CHANNEL_NAME_CHANGE = 4, - CHANNEL_ICON_CHANGE = 5, - CHANNEL_PINNED_MESSAGE = 6, - GUILD_MEMBER_JOIN = 7, - USER_PREMIUM_GUILD_SUBSCRIPTION = 8, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10, - USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11, - CHANNEL_FOLLOW_ADD = 12, - GUILD_DISCOVERY_DISQUALIFIED = 14, - GUILD_DISCOVERY_REQUALIFIED = 15 + DEFAULT = 0, + RECIPIENT_ADD = 1, + RECIPIENT_REMOVE = 2, + CALL = 3, + CHANNEL_NAME_CHANGE = 4, + CHANNEL_ICON_CHANGE = 5, + CHANNEL_PINNED_MESSAGE = 6, + GUILD_MEMBER_JOIN = 7, + USER_PREMIUM_GUILD_SUBSCRIPTION = 8, + USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1 = 9, + USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2 = 10, + USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3 = 11, + CHANNEL_FOLLOW_ADD = 12, + GUILD_DISCOVERY_DISQUALIFIED = 14, + GUILD_DISCOVERY_REQUALIFIED = 15 } enum MessageActivityTypes { - JOIN = 1, - SPECTATE = 2, - LISTEN = 3, - JOIN_REQUEST = 4 + JOIN = 1, + SPECTATE = 2, + LISTEN = 3, + JOIN_REQUEST = 4 } enum MessageFlags { - CROSSPOSTED = 1 << 0, - IS_CROSSPOST = 1 << 1, - SUPPRESS_EMBEDS = 1 << 2, - SOURCE_MESSAGE_DELETED = 1 << 3, - URGENT = 1 << 4 + CROSSPOSTED = 1 << 0, + IS_CROSSPOST = 1 << 1, + SUPPRESS_EMBEDS = 1 << 2, + SOURCE_MESSAGE_DELETED = 1 << 3, + URGENT = 1 << 4 } interface FollowedChannel { - channel_id: string, - webhook_id: string + channel_id: string + webhook_id: string } interface Reaction { - count: number, - me: boolean - emoji: Emoji + count: number + me: boolean + emoji: EmojiPayload } interface Overwrite { - id: string, - type: number - allow: string - deny: string + id: string + type: number + allow: string + deny: string } interface ChannelMention { - id: string - guild_id: string - type: ChannelTypes - name: string -} \ No newline at end of file + id: string + guild_id: string + type: ChannelTypes + name: string +} + +export { + ChannelPayload, + ChannelTypes, + ChannelMention, + Attachment, + Reaction, + MessageActivity, + MessageApplication, + MessageReference, + MessagePayload, + EmbedPayload, + EmbedTypes, + EmbedFooter, + EmbedImage, + EmbedThumbnail, + EmbedVideo, + EmbedProvider, + EmbedAuthor, + EmbedField +} diff --git a/src/types/emojiTypes.ts b/src/types/emojiTypes.ts index 31a245a..15a5128 100644 --- a/src/types/emojiTypes.ts +++ b/src/types/emojiTypes.ts @@ -1,10 +1,12 @@ -interface Emoji { - id: string - name: string | undefined - roles?: [] - user?: User - require_colons?: boolean - managed?: boolean - animated?: boolean - available?: boolean -} \ No newline at end of file +import { User } from '../structures/user.ts' + +export interface EmojiPayload { + id: string + name: string + roles?: [] + user?: User + require_colons?: boolean + managed?: boolean + animated?: boolean + available?: boolean +} diff --git a/src/types/endpoint.ts b/src/types/endpoint.ts index 019063b..503519b 100644 --- a/src/types/endpoint.ts +++ b/src/types/endpoint.ts @@ -4,7 +4,7 @@ import { DISCORD_API_URL, DISCORD_API_VERSION, DISCORD_CDN_URL -} from "../consts/urlsAndVersions" +} from '../consts/urlsAndVersions.ts' //Guild Endpoints const GUILDS = `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/guilds` @@ -71,20 +71,20 @@ const MESSAGE_REACTIONS = (channelID: string, messageID: string) => const MESSAGE_REACTION = ( channelID: string, messageID: string, - emoji: string, + emoji: string ) => `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/channels/${channelID}/messages/${messageID}/reactions/${emoji}` const MESSAGE_REACTION_ME = ( channelID: string, messageID: string, - emojiID: string, + emojiID: string ) => `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/channels/${channelID}/messages/${messageID}/reactions/${emojiID}/@me` const MESSAGE_REACTION_USER = ( channelID: string, messageID: string, emojiID: string, - userID: string, + userID: string ) => `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/channels/${channelID}/messages/${messageID}/reactions/${emojiID}/${userID}` const CHANNEL_BULK_DELETE = (channelID: string) => @@ -106,11 +106,9 @@ const GROUP_RECIPIENT = (channelID: string, userID: string) => //User Endpoints const CURRENT_USER = `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me` -const CURRENT_USER_GUILDS = - `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/guilds` +const CURRENT_USER_GUILDS = `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/guilds` const USER_DM = `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/channels` -const USER_CONNECTIONS = - `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/connections` +const USER_CONNECTIONS = `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/connections` const LEAVE_GUILD = (guildID: string) => `${DISCORD_API_URL}/v${DISCORD_API_VERSION}/users/@me/guilds/${guildID}` const USER = (userID: string) => @@ -143,7 +141,7 @@ const GUILD_SPLASH = (guildID: string, guildSPLASH: string) => `${DISCORD_CDN_URL}/splashes/${guildID}/${guildSPLASH}.png` const GUILD_DISCOVERY_SPLASH = ( guildID: string, - guildDiscoverySplash: string, + guildDiscoverySplash: string ) => `${DISCORD_CDN_URL}/discovery-splashes/${guildID}/${guildDiscoverySplash}.png ` const GUILD_BANNER = (guildID: string, guildBANNER: string) => @@ -157,7 +155,7 @@ const APPLICATION_ASSET = (applicationID: string, assetID: number) => const ACHIEVEMENT_ICON = ( applicationID: string, achievementID: string, - iconHASH: string, + iconHASH: string ) => `${DISCORD_CDN_URL}/app-assets/${applicationID}/achievements/${achievementID}/icons/${iconHASH}.png` const TEAM_ICON = (teamID: string, iconID: string) => diff --git a/src/types/gatewayResponse.ts b/src/types/gatewayResponse.ts index 91fd4dd..a370ea7 100644 --- a/src/types/gatewayResponse.ts +++ b/src/types/gatewayResponse.ts @@ -1,4 +1,4 @@ -import { GatewayOpcodes } from '../types/gatewayTypes' +import { GatewayOpcodes, GatewayEvents } from '../types/gatewayTypes.ts' /** * Gateway response from Discord. @@ -8,7 +8,7 @@ interface GatewayResponse { op: GatewayOpcodes d: any s?: number - t?: string + t?: GatewayEvents } export { GatewayResponse } diff --git a/src/types/gatewayTypes.ts b/src/types/gatewayTypes.ts index 3875d89..11a232c 100644 --- a/src/types/gatewayTypes.ts +++ b/src/types/gatewayTypes.ts @@ -1,4 +1,10 @@ // https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway +// https://discord.com/developers/docs/topics/gateway#commands-and-events-gateway-events +import { Emoji } from '../structures/emoji.ts' +import { Role } from '../structures/role.ts' +import { User } from '../structures/user.ts' +import { MemberPayload } from './guildTypes.ts' +import { ActivityPayload, PresenceUpdatePayload } from './presenceTypes.ts' /** * Gateway OPcodes from Discord docs. @@ -55,4 +61,319 @@ enum GatewayIntents { DIRECT_MESSAGE_TYPING = 1 << 13 } -export { GatewayCloseCodes, GatewayOpcodes, GatewayIntents } +enum GatewayEvents { + Hello = 'HELLO', + Ready = 'READY', + Resumed = 'RESUMED', + Reconnect = 'RECONNECT', + Invalid_Session = 'INVALID_SESSION', + Channel_Create = 'CHANNEL_CREATE', + Channel_Update = 'CHANNEL_UPDATE', + Channel_Delete = 'CHANNEL_DELETE', + Channel_Pins_Update = 'CHANNEL_PIN_UPDATE', + Guild_Create = 'GUILD_CREATE', + Guild_Update = 'GUILD_UPDATE', + Guild_Delete = 'GUILD_DELETE', + Guild_Ban_Add = 'GUILD_BAN_ADD', + Guild_Ban_Remove = 'GUILD_BAN_REMOVE', + Guild_Emojis_Update = 'GUILD_EMOJIS_UPDATE', + Guild_Integrations_Update = 'GUILD_INTEGRATIONS_UPDATE', + Guild_Member_Add = 'GUILD_MEMBER_ADD', + Guild_Member_Remove = 'GUILD_MEMBER_REMOVE', + Guild_Member_Update = 'GUILD_MEMBER_UPDATE', + Guild_Members_Chunk = 'GUILD_MEMBERS_CHUNK', + Guild_Role_Create = 'GUILD_ROLE_CREATE', + Guild_Role_Update = 'GUILD_ROLE_UPDATE', + Guild_Role_Delete = 'GUILD_ROLE_DELETE', + Invite_Create = 'INVITE_CREATE', + Invite_Delete = 'INVITE_DELETE', + Message_Create = 'MESSAGE_CREATE', + Message_Update = 'MESSAGE_UPDATE', + Message_Delete = 'MESSAG_DELETE', + Message_Delete_Bulk = 'MESSAGE_DELETE_BULK', + Message_Reaction_Add = 'MESSAGE_REACTION_ADD', + Message_Reaction_Remove = 'MESSAGE_REACTION_REMOVE', + Message_Reaction_Remove_All = 'MESSAGE_REACTION_REMOVE_ALL', + Message_Reaction_Remove_Emoji = 'MESSAGE_REACTION_REMOVE_EMOJI', + Presence_Update = 'PRESENCE_UPDATE', + Typing_Start = 'TYPING_START', + User_Update = 'USER_UPDATE', + Voice_State_Update = 'VOICE_STATE_UPDATE', + Voice_Server_Update = 'VOICE_SERVER_UPDATE', + Webhooks_Update = 'WEBHOOKS_UPDATE' +} + +interface IdentityPayload { + token: string + properties: IdentityConnection + compress?: boolean + large_threshold?: number + shard?: number[] + presence?: UpdateStatus + guildSubscriptions?: boolean + intents: number +} + +enum UpdateStatus { + online = 'online', + dnd = 'dnd', + afk = 'idle', + invisible = 'invisible', + offline = 'offline' +} + +interface IdentityConnection { + $os: 'linux' + $browser: 'discord.deno' + $device: 'discord.deno' +} + +interface Resume { + token: string + session_id: string + seq: number +} + +interface GuildRequestMembers { + guild_id: string | string[] + query?: string + limit: number + presences?: boolean //do you have any problems? tell me! i am so handsome + user_ids?: string | string[] + nonce?: string +} + +interface GatewayVoiceStateUpdate { + guild_id: string + channel_id: string + self_mute: boolean + self_deaf: boolean +} + +interface GatewayStatusUpdate { + since: number | undefined + activities: ActivityPayload[] + status: string + afk: boolean +} + +interface Hello { + heartbeat_interval: number +} + +interface ReadyEvent { + v: number + user: User + privateChannels: [] + guilds: [] + session_id: string + shard?: number[] +} + +interface ChannelPinsUpdate { + guild_id?: string + channel_id: string + last_pin_timestamp?: string +} + +interface GuildBanAdd { + guild_id: string + user: User +} + +interface GuildBanRemove { + guild_id: string + user: User +} + +interface GuildEmojiUpdate { + guild_id: string + emojis: [] +} + +interface GuildIntegrationsUpdate { + guild_id: string +} + +interface GuildMemberAddExtra { + guild_id: string +} + +interface GuildMemberRemove { + guild_id: string + user: User +} +interface GuildMemberUpdate { + guild_id: string + roles: string[] + user: User + nick?: string | undefined + joined_at: string + premium_since?: string | undefined +} + +interface GuildMemberChunk { + guild_id: string + members: MemberPayload[] + chunk_index: number + chunk_count: number + not_found?: [] + presences?: PresenceUpdatePayload[] + nonce?: string +} + +interface GuildRoleCreate { + guild_id: string + role: Role +} + +interface GuildRoleUpdate { + guild_id: string + role: Role +} + +interface GuildRoleDelete { + guild_id: string + role_id: string +} + +interface InviteCreate { + channel_id: string + code: string + created_at: string + guild_id?: string + inviter?: User + max_age: number + max_uses: number + target_user?: User + target_user_type?: number + temporary: boolean + uses: number +} + +interface InviteDelete { + channel_id: string + guild_id?: string + code: string +} + +interface MessageDelete { + id: string + channel_id: string + guild_id?: string +} + +interface MessageDeleteBulk { + ids: string[] + channel_id: string + guild_id: string +} + +interface MessageReactionAdd { + user_id: string + channel_id: string + message_id: string + guild_id?: string + emoji: Emoji +} + +interface MessageReactionRemove { + user_id: string + channel_id: string + message_id: string + guild_id?: string + emoji: Emoji +} + +interface MessageReactionRemoveAll { + channel_id: string + guild_id?: string + message_id: string + emoji: Emoji +} + +interface MessageReactionRemove { + channel_id: string + guild_id?: string + message_id: string + emoji: Emoji +} + +interface PresenceUpdate { + user: User + guild_id: string + status: string + activities: ActivityPayload[] + client_status: UpdateStatus[] +} + +interface CilentStatus { + desktop?: string + moblie?: string + web?: string +} + +interface Activity { + name: string + type: number + url?: string | undefined + created_at: number + timestamps?: string + application_id: string + details?: string | undefined + state?: string | undefined + emoji?: Emoji | undefined + party?: ActivityParty + assets?: ActivityAssets + secrets?: ActivitySecrets + instance?: boolean + flags?: number +} + +enum ActivityTypes { + GAME = 0, + STREAMING = 1, + LISTENING = 2, + CUSTOM = 4, + COMPETING = 5 +} + +interface ActivityTimestamps { + start?: number + end?: number +} + +interface ActivityEmoji { + name: string + id?: string + animated?: boolean +} + +interface ActivityParty { + id?: string + size?: number[] +} + +interface ActivityAssets { + large_image?: string + large_text?: string + small_image?: string + small_text?: string +} +interface ActivitySecrets { + join?: string + spectate?: string + match?: string +} + +enum ActivityFlags { + INSTANCE = 1 << 0, + JOIN = 1 << 1, + SPECTATE = 1 << 2, + JOIN_REQUEST = 1 << 3, + SYNC = 1 << 4, + PLAY = 1 << 5 +} + +//https://discord.com/developers/docs/topics/gateway#typing-start-typing-start-event-fields +export { GatewayCloseCodes, GatewayOpcodes, GatewayIntents, GatewayEvents } diff --git a/src/types/guildTypes.ts b/src/types/guildTypes.ts index a77cf6a..31e01f6 100644 --- a/src/types/guildTypes.ts +++ b/src/types/guildTypes.ts @@ -1,107 +1,117 @@ -interface Guild { - id: string - name: string - icon: string | undefined - icon_hash?: string | undefined - splash: string | undefined - discovery_splash: string | undefined - owner?: boolean - owner_id: string - permissions?: string - region: string - afk_channel_id: string | undefined - afk_timeout: number - widget_enabled?: boolean - widge_channel_id?: string | undefined - verification_level: string - default_message_notifications: string - explicit_content_filter: string - roles: Role[] - emojis: Emoji[] - features: GuildFeatures[] - mfa_level: string - application_id: string | undefined - system_channel_id: string | undefined - system_channel_flags: string - rules_channel_id: string | undefined - joined_at?: string - large?: boolean - unavailable: boolean - member_count?: number - voice_states?: VoiceState[] - members?: GuildMember[] - channels?: Channel[] - presences?: PresenceUpdate[] - max_presences?: number | undefined - max_members?: number - vanity_url_code: string | undefined - description: string | undefined - banner: string | undefined - premium_tier: number - premium_subscription_count?: number - preferred_locale: string - public_updates_channel_id: string | undefined - max_video_channel_users?: number - approximate_number_count?: number - approximate_presence_count?: number +import { Channel } from '../structures/channel.ts' +import { Emoji } from '../structures/emoji.ts' +import { Member } from '../structures/member.ts' +import { Role } from '../structures/role.ts' +import { User } from '../structures/user.ts' +import { PresenceUpdatePayload } from './presenceTypes.ts' +import { VoiceStatePayload } from './voiceTypes.ts' + +interface GuildPayload { + id: string + name: string + icon: string | undefined + icon_hash?: string | undefined + splash: string | undefined + discovery_splash: string | undefined + owner?: boolean + owner_id: string + permissions?: string + region: string + afk_channel_id: string | undefined + afk_timeout: number + widget_enabled?: boolean + widge_channel_id?: string | undefined + verification_level: string + default_message_notifications: string + explicit_content_filter: string + roles: Role[] + emojis: Emoji[] + features: GuildFeatures[] + mfa_level: string + application_id: string | undefined + system_channel_id: string | undefined + system_channel_flags: string + rules_channel_id: string | undefined + joined_at?: string + large?: boolean + unavailable: boolean + member_count?: number + voice_states?: VoiceStatePayload[] + members?: Member[] + channels?: Channel[] + presences?: PresenceUpdatePayload[] + max_presences?: number | undefined + max_members?: number + vanity_url_code: string | undefined + description: string | undefined + banner: string | undefined + premium_tier: number + premium_subscription_count?: number + preferred_locale: string + public_updates_channel_id: string | undefined + max_video_channel_users?: number + approximate_number_count?: number + approximate_presence_count?: number } -interface GuildMember { - user?: User - nick: string | undefined - roles: Role[] - joined_at: string - premium_since?: string | undefined - deaf: boolean - mute: boolean +interface MemberPayload { + user: User + nick: string | undefined + roles: Role[] + joined_at: string + premium_since?: string | undefined + deaf: boolean + mute: boolean } enum MessageNotification { - ALL_MESSAGES = 0, - ONLY_MENTIONS = 1 + ALL_MESSAGES = 0, + ONLY_MENTIONS = 1 } enum ContentFilter { - DISABLED = 0, - MEMBERS_WITHOUT_ROLES = 1, - ALL_MEMBERS = 3, + DISABLED = 0, + MEMBERS_WITHOUT_ROLES = 1, + ALL_MEMBERS = 3 } enum MFA { - NONE = 0, - ELEVATED = 1 + NONE = 0, + ELEVATED = 1 } enum Verification { - NONE = 0, - LOW = 1, - MEDIUM = 2, - HIGH = 3, - VERY_HIGH = 4 + NONE = 0, + LOW = 1, + MEDIUM = 2, + HIGH = 3, + VERY_HIGH = 4 } enum PremiumTier { - NONE = 0, - TIER_1 = 1, - TIER_2 = 2, - TIER_3 = 3 + NONE = 0, + TIER_1 = 1, + TIER_2 = 2, + TIER_3 = 3 } enum SystemChannelFlags { - SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0, - SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1 + SUPPRESS_JOIN_NOTIFICATIONS = 1 << 0, + SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1 } type GuildFeatures = - | "INVITE_SPLASH" - | "VIP_REGIONS" - | "VANITY_URL" - | "VERIFIED" - | "PARTNERED" - | "PUBLIC" - | "COMMERCE" - | "NEWS" - | "DISCOVERABLE" - | "FEATURABLE" - | "ANIMATED_ICON" - | "BANNER" \ No newline at end of file + | 'INVITE_SPLASH' + | 'VIP_REGIONS' + | 'VANITY_URL' + | 'VERIFIED' + | 'PARTNERED' + | 'PUBLIC' + | 'COMMERCE' + | 'NEWS' + | 'DISCOVERABLE' + | 'FEATURABLE' + | 'ANIMATED_ICON' + | 'BANNER' + +export { MemberPayload, GuildPayload, GuildFeatures } diff --git a/src/types/inviteTypes.ts b/src/types/inviteTypes.ts index ac1caad..c53aae5 100644 --- a/src/types/inviteTypes.ts +++ b/src/types/inviteTypes.ts @@ -1,10 +1,14 @@ -interface Invite { - code: string - guild?: Guild - channel: Channel - inviter?: User - target_user?: User - target_user_type?: number - approximate_presence_count?: number - approximate_member_count?: number -} \ No newline at end of file +import { Channel } from '../structures/channel.ts' +import { Guild } from '../structures/guild.ts' +import { User } from '../structures/user.ts' + +export interface InvitePayload { + code: string + guild?: Guild + channel: Channel + inviter?: User + target_user?: User + target_user_type?: number + approximate_presence_count?: number + approximate_member_count?: number +} diff --git a/src/types/presenceTypes.ts b/src/types/presenceTypes.ts index a14bc01..a2aff4a 100644 --- a/src/types/presenceTypes.ts +++ b/src/types/presenceTypes.ts @@ -1,68 +1,72 @@ -interface PresenceUpdate { - user: User - guild_id: string - status: string - activities: Activity - client_status: ClientStatus +import { User } from '../structures/user.ts' + +interface PresenceUpdatePayload { + user: User + guild_id: string + status: string + activities: ActivityPayload + client_status: ClientStatus } interface ClientStatus { - desktop?: string - mobile?: string - web?: string + desktop?: string + mobile?: string + web?: string } -interface Activity { - name: string - type: 0 | 1 | 2 | 3 | 4 | 5 - url?: string | undefined - created_at: number - timestamps?: ActivityTimestamps - application_id?: string - details?: string | undefined - state?: string | undefined - emoji?: ActivityEmoji - party?: ActivityParty - assets?: ActivityAssets - secrets?: ActivitySecrets - instance?: boolean - flags?: number +interface ActivityPayload { + name: string + type: 0 | 1 | 2 | 3 | 4 | 5 + url?: string | undefined + created_at: number + timestamps?: ActivityTimestamps + application_id?: string + details?: string | undefined + state?: string | undefined + emoji?: ActivityEmoji + party?: ActivityParty + assets?: ActivityAssets + secrets?: ActivitySecrets + instance?: boolean + flags?: number } interface ActivityTimestamps { - start?: number - end?: number + start?: number + end?: number } interface ActivityEmoji { - name: string - id?: string - animated?: boolean + name: string + id?: string + animated?: boolean } interface ActivityParty { - id?: string - size?: number[] + id?: string + size?: number[] } interface ActivityAssets { - large_image?: string - large_text?: string - small_image?: string - small_text?: string + large_image?: string + large_text?: string + small_image?: string + small_text?: string } interface ActivitySecrets { - join?: string - spectate?: string - match?: string + join?: string + spectate?: string + match?: string } enum ActivityFlags { - INSTANCE = 1 << 0, - JOIN = 1 << 1, - SPECTATE = 1 << 2, - JOIN_REQUEST = 1 << 3, - SYNC = 1 << 4, - PLAY = 1 << 5 + INSTANCE = 1 << 0, + JOIN = 1 << 1, + SPECTATE = 1 << 2, + JOIN_REQUEST = 1 << 3, + SYNC = 1 << 4, + PLAY = 1 << 5 } + +export { ActivityPayload, PresenceUpdatePayload } diff --git a/src/types/roleTypes.ts b/src/types/roleTypes.ts index bed1522..78f43d6 100644 --- a/src/types/roleTypes.ts +++ b/src/types/roleTypes.ts @@ -1,10 +1,10 @@ -interface Role { - id: string - name: string - color: number - hoist: boolean - position: number - permissions: string - managed: boolean - mentionable: boolean -} \ No newline at end of file +export interface RolePayload { + id: string + name: string + color: number + hoist: boolean + position: number + permissions: string + managed: boolean + mentionable: boolean +} diff --git a/src/types/snowflake.ts b/src/types/snowflake.ts index f8ae6f6..b9409b8 100644 --- a/src/types/snowflake.ts +++ b/src/types/snowflake.ts @@ -1,17 +1,22 @@ export class Snowflake { id: string - constructor(id: string) { + constructor (id: string) { this.id = id } - deconstruct() { - const snowflake = BigInt.asUintN(64, BigInt(this.id)); + deconstruct () { + const snowflake = BigInt.asUintN(64, BigInt(this.id)) const res = { - timestamp: (snowflake << BigInt(22)) + BigInt(1420070400000), - workerId: (snowflake & BigInt(0x3E0000)) >> BigInt(17), - processId: (snowflake & BigInt(0x1F000)) >> BigInt(12), - increment: snowflake & BigInt(0xFFF), + timestamp: ((snowflake << BigInt(22)) + BigInt(1420070400000)).toString(), + workerId: ((snowflake & BigInt(0x3e0000)) >> BigInt(17)).toString(), + processId: ((snowflake & BigInt(0x1f000)) >> BigInt(12)).toString(), + increment: (snowflake & BigInt(0xfff)).toString() } return res } } + +// BigInt라서 이걸 어케 할까 고심끝에 나온게 toString 읍 +// 엄... + +// deconstruct가 소멸자임? 색 봐서는 아닌거같은데 diff --git a/src/types/templateTypes.ts b/src/types/templateTypes.ts index 6d9efb3..b303ef1 100644 --- a/src/types/templateTypes.ts +++ b/src/types/templateTypes.ts @@ -1,13 +1,16 @@ -interface Template { - code: string - name: string - description: string | undefined - usage_count: number - creator_id: string - creator: User - created_at: string - updated_at: string - source_guild_id: string - serialized_source_guild: Guild - is_dirty: boolean | undefined -} \ No newline at end of file +import { Guild } from '../structures/guild.ts' +import { User } from '../structures/user.ts' + +export interface TemplatePayload { + code: string + name: string + description: string | undefined + usage_count: number + creator_id: string + creator: User + created_at: string + updated_at: string + source_guild_id: string + serialized_source_guild: Guild + is_dirty: boolean | undefined +} diff --git a/src/types/userTypes.ts b/src/types/userTypes.ts index 7d4cd48..71fb878 100644 --- a/src/types/userTypes.ts +++ b/src/types/userTypes.ts @@ -1,14 +1,14 @@ -interface User { +export interface UserPayload { id: string username: string discriminator: string - avatar: string | undefined + avatar?: string bot?: boolean system?: boolean mfa_enabled?: boolean locale?: string verified?: boolean - email?: string | undefined + email?: string flags?: number premium_type?: 0 | 1 | 2 public_flags?: number diff --git a/src/types/voiceTypes.ts b/src/types/voiceTypes.ts index b05325a..c098146 100644 --- a/src/types/voiceTypes.ts +++ b/src/types/voiceTypes.ts @@ -1,4 +1,5 @@ // https://discord.com/developers/docs/topics/opcodes-and-status-codes#voice +import { Member } from '../structures/member.ts' enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC - IDENTIFY = 0, @@ -11,7 +12,7 @@ enum VoiceOpcodes { // VoiceOpcodes 추가 - UnderC - RESUME = 7, HELLO = 8, RESUMED = 9, - CLIENT_DISCONNECT = 13, + CLIENT_DISCONNECT = 13 } enum VoiceCloseCodes { @@ -25,14 +26,14 @@ enum VoiceCloseCodes { UNKNOWN_PROTOCOL = 4012, DISCONNECTED = 4014, VOICE_SERVER_CRASHED = 4015, - UNKNOWN_ENCRYPTION_MODE = 4016, + UNKNOWN_ENCRYPTION_MODE = 4016 } -interface VoiceState { +export interface VoiceStatePayload { guild_id?: string - channel_id: string | undefined + channel_id: string | undefined user_id: string - member?: GuildMember + member?: Member session_id: string deaf: boolean mute: boolean @@ -41,4 +42,4 @@ interface VoiceState { self_stream?: boolean self_video: boolean suppress: boolean -} \ No newline at end of file +} diff --git a/src/types/webhookTypes.ts b/src/types/webhookTypes.ts index e34c1d4..b43c21f 100644 --- a/src/types/webhookTypes.ts +++ b/src/types/webhookTypes.ts @@ -1,11 +1,13 @@ -interface Webhook { - id: string - type: 1 | 2 - guild_id?: string - channel_id: string - user?: User - name: string | undefined - avatar: string | undefined - token?: string - application_id: string | undefined -} \ No newline at end of file +import { User } from '../structures/user.ts' + +export interface WebhookPayload { + id: string + type: 1 | 2 + guild_id?: string + channel_id: string + user?: User + name: string | undefined + avatar: string | undefined + token?: string + application_id: string | undefined +}