MASSIVE UPDATE NOW WITH EVENTS
Co-Authored-By: Y <8479056+yky4589@users.noreply.github.com> Co-Authored-By: Aki <71239005+AkiaCode@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									e899738b55
								
							
						
					
					
						commit
						f319e0df91
					
				
					 42 changed files with 641 additions and 483 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -110,5 +110,3 @@ yarn.lock | ||||||
| # PRIVACY XDDDD | # PRIVACY XDDDD | ||||||
| src/test/config.ts | src/test/config.ts | ||||||
| .vscode | .vscode | ||||||
| 
 |  | ||||||
| src/test/ |  | ||||||
							
								
								
									
										13
									
								
								src/gateway/handlers/channelCreate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/gateway/handlers/channelCreate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import getChannelByType from '../../utils/getChannelByType.ts' | ||||||
|  | 
 | ||||||
|  | export const channelCreate: GatewayEventHandler = ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: any | ||||||
|  | ) => { | ||||||
|  |   const channel = getChannelByType(gateway.client, d) | ||||||
|  | 
 | ||||||
|  |   if (channel !== undefined) { | ||||||
|  |     gateway.client.emit('channelCreate', channel) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/gateway/handlers/channelDelete.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/gateway/handlers/channelDelete.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Channel } from '../../structures/channel.ts' | ||||||
|  | 
 | ||||||
|  | export const channelDelete: GatewayEventHandler = ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: any | ||||||
|  | ) => { | ||||||
|  |   const channel: Channel = cache.get('channel', d.id) | ||||||
|  |   if (channel !== undefined) { | ||||||
|  |     cache.del('channel', d.id) | ||||||
|  |     gateway.client.emit('channelDelete', channel) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								src/gateway/handlers/channelPinsUpdate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								src/gateway/handlers/channelPinsUpdate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { TextChannel } from '../../structures/textChannel.ts' | ||||||
|  | 
 | ||||||
|  | export const channelPinsUpdate: GatewayEventHandler = ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: any | ||||||
|  | ) => { | ||||||
|  |   const after: TextChannel = cache.get('textchannel', d.channel_id) | ||||||
|  |   if (after !== undefined) { | ||||||
|  |     const before = after.refreshFromData({ | ||||||
|  |       last_pin_timestamp: d.last_pin_timestamp | ||||||
|  |     }) | ||||||
|  |     gateway.client.emit('channelPinsUpdate', before, after) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										21
									
								
								src/gateway/handlers/channelUpdate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/gateway/handlers/channelUpdate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Channel } from '../../structures/channel.ts' | ||||||
|  | import getChannelByType from '../../utils/getChannelByType.ts' | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | 
 | ||||||
|  | export const channelUpdate: GatewayEventHandler = ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: any | ||||||
|  | ) => { | ||||||
|  |   const oldChannel: Channel = cache.get('channel', d.id) | ||||||
|  | 
 | ||||||
|  |   if (oldChannel !== undefined) { | ||||||
|  |     if (oldChannel.type !== d.type) { | ||||||
|  |       const channel: Channel = getChannelByType(gateway.client, d) ?? oldChannel | ||||||
|  |       gateway.client.emit('channelUpdate', oldChannel, channel) | ||||||
|  |     } else { | ||||||
|  |       const before = oldChannel.refreshFromData(d) | ||||||
|  |       gateway.client.emit('channelUpdate', before, oldChannel) | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/gateway/handlers/guildBanAdd.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/gateway/handlers/guildBanAdd.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | import { User } from '../../structures/user.ts' | ||||||
|  | 
 | ||||||
|  | export const guildBanAdd: GatewayEventHandler = (gateway: Gateway, d: any) => { | ||||||
|  |   const guild: Guild = cache.get('guild', d.guild_id) | ||||||
|  |   const user: User = | ||||||
|  |     cache.get('user', d.user.id) ?? new User(gateway.client, d.user) | ||||||
|  | 
 | ||||||
|  |   if (guild !== undefined) { | ||||||
|  |     gateway.client.emit('guildBanAdd', guild, user) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								src/gateway/handlers/guildBanRemove.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/gateway/handlers/guildBanRemove.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | import { User } from '../../structures/user.ts' | ||||||
|  | 
 | ||||||
|  | export const guildBanRemove: GatewayEventHandler = ( | ||||||
|  |   gateway: Gateway, | ||||||
|  |   d: any | ||||||
|  | ) => { | ||||||
|  |   const guild: Guild = cache.get('guild', d.guild_id) | ||||||
|  |   const user: User = | ||||||
|  |     cache.get('user', d.user.id) ?? new User(gateway.client, d.user) | ||||||
|  | 
 | ||||||
|  |   if (guild !== undefined) { | ||||||
|  |     gateway.client.emit('guildBanRemove', guild, user) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										14
									
								
								src/gateway/handlers/guildCreate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/gateway/handlers/guildCreate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | 
 | ||||||
|  | export const guildCreate: GatewayEventHandler = (gateway: Gateway, d: any) => { | ||||||
|  |   let guild: Guild = cache.get('guild', d.id) | ||||||
|  |   if (guild !== undefined) { | ||||||
|  |     guild.refreshFromData(d) | ||||||
|  |   } else { | ||||||
|  |     guild = new Guild(gateway.client, d) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   gateway.client.emit('guildCreate', guild) | ||||||
|  | } | ||||||
							
								
								
									
										13
									
								
								src/gateway/handlers/guildDelete.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/gateway/handlers/guildDelete.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | 
 | ||||||
|  | export const guildDelte: GatewayEventHandler = (gateway: Gateway, d: any) => { | ||||||
|  |   const guild: Guild = cache.get('guild', d.id) | ||||||
|  | 
 | ||||||
|  |   if (guild !== undefined) { | ||||||
|  |     guild.refreshFromData(d) | ||||||
|  |     cache.del('guild', d.id) | ||||||
|  |     gateway.client.emit('guildDelete', guild) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								src/gateway/handlers/guildUpdate.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/gateway/handlers/guildUpdate.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | import cache from '../../models/cache.ts' | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | 
 | ||||||
|  | export const guildUpdate: GatewayEventHandler = (gateway: Gateway, d: any) => { | ||||||
|  |   const after: Guild = cache.get('guild', d.id) | ||||||
|  |   if (after !== undefined) { | ||||||
|  |     const before: Guild = after.refreshFromData(d) | ||||||
|  |     gateway.client.emit('guildUpdate', before, after) | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										53
									
								
								src/gateway/handlers/index.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/gateway/handlers/index.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | import { GatewayEventHandler } from '../index.ts' | ||||||
|  | import { GatewayEvents } from '../../types/gatewayTypes.ts' | ||||||
|  | import { channelCreate } from './channelCreate.ts' | ||||||
|  | import { channelDelete } from './channelDelete.ts' | ||||||
|  | import { channelUpdate } from './channelUpdate.ts' | ||||||
|  | import { channelPinsUpdate } from './channelPinsUpdate.ts' | ||||||
|  | import { guildCreate } from './guildCreate.ts' | ||||||
|  | import { guildDelte as guildDelete } from './guildDelete.ts' | ||||||
|  | import { guildUpdate } from './guildUpdate.ts' | ||||||
|  | import { guildBanAdd } from './guildBanAdd.ts' | ||||||
|  | import { ready } from './ready.ts' | ||||||
|  | import { guildBanRemove } from './guildBanRemove.ts' | ||||||
|  | 
 | ||||||
|  | export const gatewayHandlers: { | ||||||
|  |   [eventCode in GatewayEvents]: GatewayEventHandler | undefined | ||||||
|  | } = { | ||||||
|  |   READY: ready, | ||||||
|  |   RECONNECT: undefined, | ||||||
|  |   RESUMED: undefined, | ||||||
|  |   CHANNEL_CREATE: channelCreate, | ||||||
|  |   CHANNEL_DELETE: channelDelete, | ||||||
|  |   CHANNEL_UPDATE: channelUpdate, | ||||||
|  |   CHANNEL_PINS_UPDATE: channelPinsUpdate, | ||||||
|  |   GUILD_CREATE: guildCreate, | ||||||
|  |   GUILD_DELETE: guildDelete, | ||||||
|  |   GUILD_UPDATE: guildUpdate, | ||||||
|  |   GUILD_BAN_ADD: guildBanAdd, | ||||||
|  |   GUILD_BAN_REMOVE: guildBanRemove, | ||||||
|  |   GUILD_EMOJIS_UPDATE: undefined, | ||||||
|  |   GUILD_INTEGRATIONS_UPDATE: undefined, | ||||||
|  |   GUILD_MEMBER_ADD: undefined, | ||||||
|  |   GUILD_MEMBER_REMOVE: undefined, | ||||||
|  |   GUILD_MEMBER_UPDATE: undefined, | ||||||
|  |   GUILD_MEMBERS_CHUNK: undefined, | ||||||
|  |   GUILD_ROLE_CREATE: undefined, | ||||||
|  |   GUILD_ROLE_UPDATE: undefined, | ||||||
|  |   GUILD_ROLE_DELETE: undefined, | ||||||
|  |   INVITE_CREATE: undefined, | ||||||
|  |   INVITE_DELETE: undefined, | ||||||
|  |   MESSAGE_CREATE: undefined, | ||||||
|  |   MESSAGE_UPDATE: undefined, | ||||||
|  |   MESSAGE_DELETE: undefined, | ||||||
|  |   MESSAGE_DELETE_BULK: undefined, | ||||||
|  |   MESSAGE_REACTION_ADD: undefined, | ||||||
|  |   MESSAGE_REACTION_REMOVE: undefined, | ||||||
|  |   MESSAGE_REACTION_REMOVE_ALL: undefined, | ||||||
|  |   MESSAGE_REACTION_REMOVE_EMOJI: undefined, | ||||||
|  |   PRESENCE_UPDATE: undefined, | ||||||
|  |   TYPING_START: undefined, | ||||||
|  |   USER_UPDATE: undefined, | ||||||
|  |   VOICE_SERVER_UPDATE: undefined, | ||||||
|  |   WEBHOOKS_UPDATE: undefined | ||||||
|  | } | ||||||
							
								
								
									
										11
									
								
								src/gateway/handlers/ready.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/gateway/handlers/ready.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,11 @@ | ||||||
|  | import { Guild } from '../../structures/guild.ts' | ||||||
|  | import { User } from '../../structures/user.ts' | ||||||
|  | import { GuildPayload } from '../../types/guildTypes.ts' | ||||||
|  | import { Gateway, GatewayEventHandler } from '../index.ts' | ||||||
|  | 
 | ||||||
|  | export const ready: GatewayEventHandler = (gateway: Gateway, d: any) => { | ||||||
|  |   gateway.client.user = new User(gateway.client, d.user) | ||||||
|  |   gateway.sessionID = d.session_id | ||||||
|  |   d.guilds.forEach((guild: GuildPayload) => new Guild(gateway.client, guild)) | ||||||
|  |   gateway.client.emit('ready') | ||||||
|  | } | ||||||
							
								
								
									
										199
									
								
								src/gateway/index.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								src/gateway/index.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,199 @@ | ||||||
|  | import { unzlib } from 'https://deno.land/x/denoflate/mod.ts' | ||||||
|  | import { Client } from '../models/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 { gatewayHandlers } from './handlers/index.ts' | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Handles Discord gateway connection. | ||||||
|  |  * You should not use this and rather use Client class. | ||||||
|  |  * | ||||||
|  |  * @beta | ||||||
|  |  */ | ||||||
|  | class Gateway { | ||||||
|  |   websocket: WebSocket | ||||||
|  |   token: string | ||||||
|  |   intents: GatewayIntents[] | ||||||
|  |   connected = false | ||||||
|  |   initialized = false | ||||||
|  |   heartbeatInterval = 0 | ||||||
|  |   heartbeatIntervalID?: number | ||||||
|  |   sequenceID?: number | ||||||
|  |   sessionID?: string | ||||||
|  |   lastPingTimestemp = 0 | ||||||
|  |   private heartbeatServerResponded = false | ||||||
|  |   client: Client | ||||||
|  | 
 | ||||||
|  |   constructor (client: Client, token: string, intents: GatewayIntents[]) { | ||||||
|  |     this.token = token | ||||||
|  |     this.intents = intents | ||||||
|  |     this.client = client | ||||||
|  |     this.websocket = new WebSocket( | ||||||
|  |       // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
 | ||||||
|  |       `${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) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private onopen (): void { | ||||||
|  |     this.connected = true | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private onmessage (event: MessageEvent): void { | ||||||
|  |     let data = event.data | ||||||
|  |     if (data instanceof ArrayBuffer) { | ||||||
|  |       data = new Uint8Array(data) | ||||||
|  |     } | ||||||
|  |     if (data instanceof Uint8Array) { | ||||||
|  |       data = unzlib(data) | ||||||
|  |       data = new TextDecoder('utf-8').decode(data) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const { op, d, s, t }: GatewayResponse = JSON.parse(data) | ||||||
|  | 
 | ||||||
|  |     switch (op) { | ||||||
|  |       case GatewayOpcodes.HELLO: | ||||||
|  |         this.heartbeatInterval = d.heartbeat_interval | ||||||
|  |         this.heartbeatIntervalID = setInterval(() => { | ||||||
|  |           if (this.heartbeatServerResponded) { | ||||||
|  |             this.heartbeatServerResponded = false | ||||||
|  |           } else { | ||||||
|  |             clearInterval(this.heartbeatIntervalID) | ||||||
|  |             this.websocket.close() | ||||||
|  |             this.initWebsocket() | ||||||
|  |             return | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           this.websocket.send( | ||||||
|  |             JSON.stringify({ | ||||||
|  |               op: GatewayOpcodes.HEARTBEAT, | ||||||
|  |               d: this.sequenceID ?? null | ||||||
|  |             }) | ||||||
|  |           ) | ||||||
|  |           this.lastPingTimestemp = Date.now() | ||||||
|  |         }, this.heartbeatInterval) | ||||||
|  | 
 | ||||||
|  |         if (!this.initialized) { | ||||||
|  |           this.sendIdentify() | ||||||
|  |           this.initialized = true | ||||||
|  |         } else { | ||||||
|  |           this.sendResume() | ||||||
|  |         } | ||||||
|  |         break | ||||||
|  | 
 | ||||||
|  |       case GatewayOpcodes.HEARTBEAT_ACK: | ||||||
|  |         this.heartbeatServerResponded = true | ||||||
|  |         this.client.ping = Date.now() - this.lastPingTimestemp | ||||||
|  |         break | ||||||
|  | 
 | ||||||
|  |       case GatewayOpcodes.INVALID_SESSION: | ||||||
|  |         // Because we know this gonna be bool
 | ||||||
|  |         // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
 | ||||||
|  |         if (!d) { | ||||||
|  |           setTimeout(this.sendResume, 3000) | ||||||
|  |         } else { | ||||||
|  |           setTimeout(this.sendIdentify, 3000) | ||||||
|  |         } | ||||||
|  |         break | ||||||
|  | 
 | ||||||
|  |       case GatewayOpcodes.DISPATCH: { | ||||||
|  |         this.heartbeatServerResponded = true | ||||||
|  |         if (s !== null) { | ||||||
|  |           this.sequenceID = s | ||||||
|  |         } | ||||||
|  |         if (t !== null && t !== undefined) { | ||||||
|  |           const handler = gatewayHandlers[t] | ||||||
|  | 
 | ||||||
|  |           if (handler !== undefined) { | ||||||
|  |             handler(this, d) | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |         break | ||||||
|  |       } | ||||||
|  |       default: | ||||||
|  |         break | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private onclose (event: CloseEvent): void { | ||||||
|  |     console.log(event.code) | ||||||
|  |     // TODO: Handle close event codes.
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private onerror (event: Event | ErrorEvent): void { | ||||||
|  |     const eventError = event as ErrorEvent | ||||||
|  | 
 | ||||||
|  |     console.log(eventError) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private sendIdentify (): void { | ||||||
|  |     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 | ||||||
|  |           } | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   private sendResume (): void { | ||||||
|  |     this.websocket.send( | ||||||
|  |       JSON.stringify({ | ||||||
|  |         op: GatewayOpcodes.RESUME, | ||||||
|  |         d: { | ||||||
|  |           token: this.token, | ||||||
|  |           session_id: this.sessionID, | ||||||
|  |           seq: this.sequenceID | ||||||
|  |         } | ||||||
|  |       }) | ||||||
|  |     ) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   initWebsocket (): void { | ||||||
|  |     this.websocket = new WebSocket( | ||||||
|  |       // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
 | ||||||
|  |       `${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) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   close (): void { | ||||||
|  |     this.websocket.close(1000) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export type GatewayEventHandler = (gateway: Gateway, d: any) => void | ||||||
|  | 
 | ||||||
|  | export { Gateway } | ||||||
|  | @ -1,8 +1,9 @@ | ||||||
| import { User } from '../structures/user.ts' | import { User } from '../structures/user.ts' | ||||||
| import { GatewayIntents } from '../types/gatewayTypes.ts' | import { GatewayIntents } from '../types/gatewayTypes.ts' | ||||||
| import { Gateway } from './gateway.ts' | import { Gateway } from '../gateway/index.ts' | ||||||
| import { Rest } from './rest.ts' | import { Rest } 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' | ||||||
|  | 
 | ||||||
| /** | /** | ||||||
|  * Discord Client. |  * Discord Client. | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -1,309 +0,0 @@ | ||||||
| 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, |  | ||||||
|   GatewayEvents |  | ||||||
| } from '../types/gatewayTypes.ts' |  | ||||||
| import { GuildPayload } from '../types/guildTypes.ts' |  | ||||||
| import { User } from '../structures/user.ts' |  | ||||||
| import * as cache from './cache.ts' |  | ||||||
| import { Guild } from '../structures/guild.ts' |  | ||||||
| import { Channel } from '../structures/channel.ts' |  | ||||||
| import { ChannelTypes } from '../types/channelTypes.ts' |  | ||||||
| import { DMChannel } from '../structures/dmChannel.ts' |  | ||||||
| import { GroupDMChannel } from '../structures/groupChannel.ts' |  | ||||||
| import { GuildTextChannel } from '../structures/guildTextChannel.ts' |  | ||||||
| import { VoiceChannel } from '../structures/guildVoiceChannel.ts' |  | ||||||
| import { CategoryChannel } from '../structures/guildCategoryChannel.ts' |  | ||||||
| import { NewsChannel } from '../structures/guildNewsChannel.ts' |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Handles Discord gateway connection. |  | ||||||
|  * You should not use this and rather use Client class. |  | ||||||
|  * |  | ||||||
|  * @beta |  | ||||||
|  */ |  | ||||||
| class Gateway { |  | ||||||
|   websocket: WebSocket |  | ||||||
|   token: string |  | ||||||
|   intents: GatewayIntents[] |  | ||||||
|   connected = false |  | ||||||
|   initialized = false |  | ||||||
|   private heartbeatInterval = 0 |  | ||||||
|   private heartbeatIntervalID?: number |  | ||||||
|   private sequenceID?: number |  | ||||||
|   private sessionID?: string |  | ||||||
|   lastPingTimestemp = 0 |  | ||||||
|   private heartbeatServerResponded = false |  | ||||||
|   client: Client |  | ||||||
| 
 |  | ||||||
|   constructor (client: Client, token: string, intents: GatewayIntents[]) { |  | ||||||
|     this.token = token |  | ||||||
|     this.intents = intents |  | ||||||
|     this.client = client |  | ||||||
|     this.websocket = new WebSocket( |  | ||||||
|       // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
 |  | ||||||
|       `${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) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private onopen (): void { |  | ||||||
|     this.connected = true |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private onmessage (event: MessageEvent): void { |  | ||||||
|     let data = event.data |  | ||||||
|     if (data instanceof ArrayBuffer) { |  | ||||||
|       data = new Uint8Array(data) |  | ||||||
|     } |  | ||||||
|     if (data instanceof Uint8Array) { |  | ||||||
|       data = unzlib(data) |  | ||||||
|       data = new TextDecoder('utf-8').decode(data) |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     const { op, d, s, t }: GatewayResponse = JSON.parse(data) |  | ||||||
| 
 |  | ||||||
|     switch (op) { |  | ||||||
|       case GatewayOpcodes.HELLO: |  | ||||||
|         this.heartbeatInterval = d.heartbeat_interval |  | ||||||
|         this.heartbeatIntervalID = setInterval(() => { |  | ||||||
|           if (this.heartbeatServerResponded) { |  | ||||||
|             this.heartbeatServerResponded = false |  | ||||||
|           } else { |  | ||||||
|             clearInterval(this.heartbeatIntervalID) |  | ||||||
|             this.websocket.close() |  | ||||||
|             this.initWebsocket() |  | ||||||
|             return |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           this.websocket.send( |  | ||||||
|             JSON.stringify({ |  | ||||||
|               op: GatewayOpcodes.HEARTBEAT, |  | ||||||
|               d: this.sequenceID ?? null |  | ||||||
|             }) |  | ||||||
|           ) |  | ||||||
|           this.lastPingTimestemp = Date.now() |  | ||||||
|         }, this.heartbeatInterval) |  | ||||||
| 
 |  | ||||||
|         if (!this.initialized) { |  | ||||||
|           this.sendIdentify() |  | ||||||
|           this.initialized = true |  | ||||||
|         } else { |  | ||||||
|           this.sendResume() |  | ||||||
|         } |  | ||||||
|         break |  | ||||||
| 
 |  | ||||||
|       case GatewayOpcodes.HEARTBEAT_ACK: |  | ||||||
|         this.heartbeatServerResponded = true |  | ||||||
|         this.client.ping = Date.now() - this.lastPingTimestemp |  | ||||||
|         break |  | ||||||
| 
 |  | ||||||
|       case GatewayOpcodes.INVALID_SESSION: |  | ||||||
|         // Because we know this gonna be bool
 |  | ||||||
|         // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
 |  | ||||||
|         if (!d) { |  | ||||||
|           setTimeout(this.sendResume, 3000) |  | ||||||
|         } else { |  | ||||||
|           setTimeout(this.sendIdentify, 3000) |  | ||||||
|         } |  | ||||||
|         break |  | ||||||
| 
 |  | ||||||
|       case GatewayOpcodes.DISPATCH: |  | ||||||
|         this.heartbeatServerResponded = true |  | ||||||
|         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 |  | ||||||
|             d.guilds.forEach((guild: GuildPayload) => { |  | ||||||
|               cache.set('guild', guild.id, new Guild(this.client, guild)) |  | ||||||
|             }) |  | ||||||
|             this.client.emit('ready') |  | ||||||
|             break |  | ||||||
|           case GatewayEvents.Channel_Create: { |  | ||||||
|             let channel: Channel | undefined |  | ||||||
|             switch (d.type) { |  | ||||||
|               case ChannelTypes.DM: |  | ||||||
|                 channel = new DMChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               case ChannelTypes.GROUP_DM: |  | ||||||
|                 channel = new GroupDMChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               case ChannelTypes.GUILD_TEXT: |  | ||||||
|                 channel = new GuildTextChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               case ChannelTypes.GUILD_VOICE: |  | ||||||
|                 channel = new VoiceChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               case ChannelTypes.GUILD_CATEGORY: |  | ||||||
|                 channel = new CategoryChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               case ChannelTypes.GUILD_NEWS: |  | ||||||
|                 channel = new NewsChannel(this.client, d) |  | ||||||
|                 break |  | ||||||
|               default: |  | ||||||
|                 break |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             if (channel !== undefined) { |  | ||||||
|               cache.set('channel', channel.id, channel) |  | ||||||
|               this.client.emit('channelCreate', channel) |  | ||||||
|             } |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           case GatewayEvents.Channel_Update: { |  | ||||||
|             const oldChannel: Channel = cache.get('channel', d.id) |  | ||||||
| 
 |  | ||||||
|             if (oldChannel !== undefined) { |  | ||||||
|               if (oldChannel.type !== d.type) { |  | ||||||
|                 let channel: Channel = oldChannel |  | ||||||
|                 switch (d.type) { |  | ||||||
|                   case ChannelTypes.DM: |  | ||||||
|                     channel = new DMChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   case ChannelTypes.GROUP_DM: |  | ||||||
|                     channel = new GroupDMChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   case ChannelTypes.GUILD_TEXT: |  | ||||||
|                     channel = new GuildTextChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   case ChannelTypes.GUILD_VOICE: |  | ||||||
|                     channel = new VoiceChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   case ChannelTypes.GUILD_CATEGORY: |  | ||||||
|                     channel = new CategoryChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   case ChannelTypes.GUILD_NEWS: |  | ||||||
|                     channel = new NewsChannel(this.client, d) |  | ||||||
|                     break |  | ||||||
|                   default: |  | ||||||
|                     break |  | ||||||
|                 } |  | ||||||
|                 cache.set('channel', channel.id, channel) |  | ||||||
|                 this.client.emit('channelUpdate', oldChannel, channel) |  | ||||||
|               } else { |  | ||||||
|                 const before = oldChannel.refreshFromData(d) |  | ||||||
|                 this.client.emit('channelUpdate', before, oldChannel) |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           case GatewayEvents.Channel_Delete: { |  | ||||||
|             const channel: Channel = cache.get('channel', d.id) |  | ||||||
|             if (channel !== undefined) { |  | ||||||
|               cache.del('channel', d.id) |  | ||||||
|               this.client.emit('channelDelete', channel) |  | ||||||
|             } |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           case GatewayEvents.Channel_Pins_Update: { |  | ||||||
|             const channel: Channel = cache.get('channel', d.channel_id) |  | ||||||
|             if (channel !== undefined && d.last_pin_timestamp !== null) { |  | ||||||
|               channel.refreshFromData({ |  | ||||||
|                 last_pin_timestamp: d.last_pin_timestamp |  | ||||||
|               }) |  | ||||||
|               this.client.emit('channelPinsUpdate', channel) |  | ||||||
|             } |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           case GatewayEvents.Guild_Create: { |  | ||||||
|             const guild: Guild = cache.get('guild', d.id) |  | ||||||
|             if (guild !== undefined) { |  | ||||||
|               guild.refreshFromData(guild) |  | ||||||
|             } |  | ||||||
|             break |  | ||||||
|           } |  | ||||||
|           default: |  | ||||||
|             break |  | ||||||
|         } |  | ||||||
|         break |  | ||||||
|       default: |  | ||||||
|         break |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private onclose (event: CloseEvent): void { |  | ||||||
|     console.log(event.code) |  | ||||||
|     // TODO: Handle close event codes.
 |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private onerror (event: Event | ErrorEvent): void { |  | ||||||
|     const eventError = event as ErrorEvent |  | ||||||
| 
 |  | ||||||
|     console.log(eventError) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private sendIdentify (): void { |  | ||||||
|     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 |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   private sendResume (): void { |  | ||||||
|     this.websocket.send( |  | ||||||
|       JSON.stringify({ |  | ||||||
|         op: GatewayOpcodes.RESUME, |  | ||||||
|         d: { |  | ||||||
|           token: this.token, |  | ||||||
|           session_id: this.sessionID, |  | ||||||
|           seq: this.sequenceID |  | ||||||
|         } |  | ||||||
|       }) |  | ||||||
|     ) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   initWebsocket (): void { |  | ||||||
|     this.websocket = new WebSocket( |  | ||||||
|       // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
 |  | ||||||
|       `${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) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   close (): void { |  | ||||||
|     this.websocket.close(1000) |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export { Gateway } |  | ||||||
|  | @ -65,7 +65,7 @@ export class Base { | ||||||
|     return oldOne |     return oldOne | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readFromData (data: { [k: string]: any }): void {} |   protected readFromData (data: { [k: string]: any }): void {} | ||||||
| 
 | 
 | ||||||
|   // toJSON() {}
 |   // toJSON() {}
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ export class Channel extends Base { | ||||||
|     cache.set('channel', this.id, this) |     cache.set('channel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ export class DMChannel extends TextChannel { | ||||||
|     cache.set('dmchannel', this.id, this) |     cache.set('dmchannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -37,7 +37,7 @@ export class Emoji extends Base { | ||||||
|     this.available = data.available |     this.available = data.available | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -17,7 +17,7 @@ export class GroupDMChannel extends Channel { | ||||||
|     cache.set('groupchannel', this.id, this) |     cache.set('groupchannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ import { Member } from './member.ts' | ||||||
| import { Role } from './role.ts' | import { Role } from './role.ts' | ||||||
| import { VoiceState } from './voiceState.ts' | import { VoiceState } from './voiceState.ts' | ||||||
| import cache from '../models/cache.ts' | import cache from '../models/cache.ts' | ||||||
|  | import getChannelByType from '../utils/getChannelByType.ts' | ||||||
| 
 | 
 | ||||||
| export class Guild extends Base { | export class Guild extends Base { | ||||||
|   id: string |   id: string | ||||||
|  | @ -103,7 +104,7 @@ export class Guild extends Base { | ||||||
|           new Member(client, v) |           new Member(client, v) | ||||||
|       ) |       ) | ||||||
|       this.channels = data.channels?.map( |       this.channels = data.channels?.map( | ||||||
|         v => cache.get('channel', v.id) ?? new Channel(client, v) |         v => cache.get('channel', v.id) ?? getChannelByType(this.client, v) | ||||||
|       ) |       ) | ||||||
|       this.presences = data.presences |       this.presences = data.presences | ||||||
|       this.maxPresences = data.max_presences |       this.maxPresences = data.max_presences | ||||||
|  | @ -122,7 +123,7 @@ export class Guild extends Base { | ||||||
|     cache.set('guild', this.id, this) |     cache.set('guild', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  | @ -177,7 +178,7 @@ export class Guild extends Base { | ||||||
|         ) ?? this.members |         ) ?? this.members | ||||||
|       this.channels = |       this.channels = | ||||||
|         data.channels?.map( |         data.channels?.map( | ||||||
|           v => cache.get('channel', v.id) ?? new Channel(this.client, v) |           v => cache.get('channel', v.id) ?? getChannelByType(this.client, v) | ||||||
|         ) ?? this.members |         ) ?? this.members | ||||||
|       this.presences = data.presences ?? this.presences |       this.presences = data.presences ?? this.presences | ||||||
|       this.maxPresences = data.max_presences ?? this.maxPresences |       this.maxPresences = data.max_presences ?? this.maxPresences | ||||||
|  |  | ||||||
|  | @ -25,7 +25,7 @@ export class CategoryChannel extends Channel { | ||||||
|     cache.set('guildcategorychannel', this.id, this) |     cache.set('guildcategorychannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -1,35 +0,0 @@ | ||||||
| import cache from '../models/cache.ts' |  | ||||||
| import { Client } from '../models/client.ts' |  | ||||||
| import { GuildChannelPayload, Overwrite } from '../types/channelTypes.ts' |  | ||||||
| import { Channel } from './channel.ts' |  | ||||||
| 
 |  | ||||||
| export class GuildChannel extends Channel { |  | ||||||
|   guildID: string |  | ||||||
|   name: string |  | ||||||
|   position: number |  | ||||||
|   permissionOverwrites: Overwrite[] |  | ||||||
|   nsfw: boolean |  | ||||||
|   parentID?: string |  | ||||||
| 
 |  | ||||||
|   constructor (client: Client, data: GuildChannelPayload) { |  | ||||||
|     super(client, data) |  | ||||||
|     this.guildID = data.guild_id |  | ||||||
|     this.name = data.name |  | ||||||
|     this.position = data.position |  | ||||||
|     this.permissionOverwrites = data.permission_overwrites |  | ||||||
|     this.nsfw = data.nsfw |  | ||||||
|     this.parentID = data.parent_id |  | ||||||
|     cache.set('guildchannel', this.id, this) |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   readFromData (data: GuildChannelPayload): 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 |  | ||||||
|   } |  | ||||||
| } |  | ||||||
|  | @ -1,9 +1,15 @@ | ||||||
| import { Client } from '../models/client.ts' | import { Client } from '../models/client.ts' | ||||||
| import { GuildChannel } from './guildChannel.ts' | import { GuildTextChannelPayload, Overwrite } from '../types/channelTypes.ts' | ||||||
| import { GuildTextChannelPayload } from '../types/channelTypes.ts' |  | ||||||
| import cache from '../models/cache.ts' | import cache from '../models/cache.ts' | ||||||
|  | import { TextChannel } from './textChannel.ts' | ||||||
| 
 | 
 | ||||||
| export class GuildTextChannel extends GuildChannel { | export class GuildTextChannel extends TextChannel { | ||||||
|  |   guildID: string | ||||||
|  |   name: string | ||||||
|  |   position: number | ||||||
|  |   permissionOverwrites: Overwrite[] | ||||||
|  |   nsfw: boolean | ||||||
|  |   parentID?: string | ||||||
|   rateLimit: number |   rateLimit: number | ||||||
|   topic?: string |   topic?: string | ||||||
| 
 | 
 | ||||||
|  | @ -13,13 +19,26 @@ export class GuildTextChannel extends GuildChannel { | ||||||
| 
 | 
 | ||||||
|   constructor (client: Client, data: GuildTextChannelPayload) { |   constructor (client: Client, data: GuildTextChannelPayload) { | ||||||
|     super(client, data) |     super(client, data) | ||||||
|  |     this.guildID = data.guild_id | ||||||
|  |     this.name = data.name | ||||||
|  |     this.position = data.position | ||||||
|  |     this.permissionOverwrites = data.permission_overwrites | ||||||
|  |     this.nsfw = data.nsfw | ||||||
|  |     this.parentID = data.parent_id | ||||||
|     this.topic = data.topic |     this.topic = data.topic | ||||||
|     this.rateLimit = data.rate_limit_per_user |     this.rateLimit = data.rate_limit_per_user | ||||||
|     cache.set('guildtextchannel', this.id, this) |     cache.set('guildtextchannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readFromData (data: GuildTextChannelPayload): void { |   protected readFromData (data: GuildTextChannelPayload): void { | ||||||
|     super.readFromData(data) |     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.topic = data.topic ?? this.topic | ||||||
|     this.rateLimit = data.rate_limit_per_user ?? this.rateLimit |     this.rateLimit = data.rate_limit_per_user ?? this.rateLimit | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  | @ -26,7 +26,7 @@ export class VoiceChannel extends Channel { | ||||||
|     cache.set('guildvoicechannel', this.id, this) |     cache.set('guildvoicechannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -1,10 +1,36 @@ | ||||||
| import { Client } from '../models/client.ts' | import { Client } from '../models/client.ts' | ||||||
| import { Channel } from './channel.ts' | import { GuildNewsChannelPayload, Overwrite } from '../types/channelTypes.ts' | ||||||
| import { GuildNewsChannelPayload } from '../types/channelTypes.ts' | import { TextChannel } from './textChannel.ts' | ||||||
|  | 
 | ||||||
|  | export class NewsChannel extends TextChannel { | ||||||
|  |   guildID: string | ||||||
|  |   name: string | ||||||
|  |   position: number | ||||||
|  |   permissionOverwrites: Overwrite[] | ||||||
|  |   nsfw: boolean | ||||||
|  |   parentID?: string | ||||||
|  |   topic?: string | ||||||
| 
 | 
 | ||||||
| export class NewsChannel extends Channel { |  | ||||||
|   // eslint-disable-next-line @typescript-eslint/no-useless-constructor
 |  | ||||||
|   constructor (client: Client, data: GuildNewsChannelPayload) { |   constructor (client: Client, data: GuildNewsChannelPayload) { | ||||||
|     super(client, data) |     super(client, data) | ||||||
|  |     this.guildID = data.guild_id | ||||||
|  |     this.name = data.name | ||||||
|  |     this.position = data.position | ||||||
|  |     this.permissionOverwrites = data.permission_overwrites | ||||||
|  |     this.nsfw = data.nsfw | ||||||
|  |     this.parentID = data.parent_id | ||||||
|  |     this.topic = data.topic | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   protected readFromData (data: GuildNewsChannelPayload): 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 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -31,7 +31,7 @@ export class Invite extends Base { | ||||||
|     this.approximatePresenceCount = data.approximate_presence_count |     this.approximatePresenceCount = data.approximate_presence_count | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -1,9 +1,12 @@ | ||||||
| import cache from '../models/cache.ts' | import cache from '../models/cache.ts' | ||||||
| import { Client } from '../models/client.ts' | import { Client } from '../models/client.ts' | ||||||
| import { MemberPayload } from '../types/guildTypes.ts' | import { MemberPayload } from '../types/guildTypes.ts' | ||||||
|  | import { Base } from './base.ts' | ||||||
| import { User } from './user.ts' | import { User } from './user.ts' | ||||||
| 
 | 
 | ||||||
| export class Member extends User { | export class Member extends Base { | ||||||
|  |   id: string | ||||||
|  |   user: User | ||||||
|   nick?: string |   nick?: string | ||||||
|   roles: string[] |   roles: string[] | ||||||
|   joinedAt: string |   joinedAt: string | ||||||
|  | @ -12,7 +15,10 @@ export class Member extends User { | ||||||
|   mute: boolean |   mute: boolean | ||||||
| 
 | 
 | ||||||
|   constructor (client: Client, data: MemberPayload) { |   constructor (client: Client, data: MemberPayload) { | ||||||
|     super(client, data.user) |     super(client) | ||||||
|  |     this.id = data.user.id | ||||||
|  |     this.user = | ||||||
|  |       cache.get('user', data.user.id) ?? new User(this.client, data.user) | ||||||
|     this.nick = data.nick |     this.nick = data.nick | ||||||
|     this.roles = data.roles |     this.roles = data.roles | ||||||
|     this.joinedAt = data.joined_at |     this.joinedAt = data.joined_at | ||||||
|  | @ -22,8 +28,8 @@ export class Member extends User { | ||||||
|     cache.set('member', this.id, this) |     cache.set('member', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readFromData (data: MemberPayload): void { |   protected readFromData (data: MemberPayload): void { | ||||||
|     super.readFromData(data) |     super.readFromData(data.user) | ||||||
|     this.nick = data.nick ?? this.nick |     this.nick = data.nick ?? this.nick | ||||||
|     this.roles = data.roles ?? this.roles |     this.roles = data.roles ?? this.roles | ||||||
|     this.joinedAt = data.joined_at ?? this.joinedAt |     this.joinedAt = data.joined_at ?? this.joinedAt | ||||||
|  |  | ||||||
|  | @ -76,14 +76,14 @@ export class Message extends Base { | ||||||
|     cache.set('message', this.id, this) |     cache.set('message', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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.author = |     this.author = | ||||||
|       cache.get('user', data.author.id) ?? |       cache.get('user', data.author.id) ?? | ||||||
|       new User(this.client, data.author) ?? |       this.author ?? | ||||||
|       this.author |       new User(this.client, data.author) | ||||||
|     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 | ||||||
|  |  | ||||||
|  | @ -30,7 +30,7 @@ export class Role extends Base { | ||||||
|     cache.set('role', this.id, this) |     cache.set('role', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ export class TextChannel extends Channel { | ||||||
|     cache.set('textchannel', this.id, this) |     cache.set('textchannel', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readFromData (data: TextChannelPayload): void { |   protected readFromData (data: TextChannelPayload): void { | ||||||
|     super.readFromData(data) |     super.readFromData(data) | ||||||
|     this.lastMessageID = data.last_message_id ?? this.lastMessageID |     this.lastMessageID = data.last_message_id ?? this.lastMessageID | ||||||
|     this.lastPinTimestamp = data.last_pin_timestamp ?? this.lastPinTimestamp |     this.lastPinTimestamp = data.last_pin_timestamp ?? this.lastPinTimestamp | ||||||
|  |  | ||||||
|  | @ -44,7 +44,7 @@ export class User extends Base { | ||||||
|     cache.set('user', this.id, this) |     cache.set('user', this.id, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   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 | ||||||
|  |  | ||||||
|  | @ -33,7 +33,7 @@ export class VoiceState extends Base { | ||||||
|     cache.set('voiceState', `${this.guildID}:${this.userID}`, this) |     cache.set('voiceState', `${this.guildID}:${this.userID}`, this) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   readFromData (data: VoiceStatePayload): void { |   protected readFromData (data: VoiceStatePayload): void { | ||||||
|     super.readFromData(data) |     super.readFromData(data) | ||||||
|     this.channelID = data.channel_id ?? this.channelID |     this.channelID = data.channel_id ?? this.channelID | ||||||
|     this.sessionID = data.session_id ?? this.sessionID |     this.sessionID = data.session_id ?? this.sessionID | ||||||
|  |  | ||||||
|  | @ -1,10 +1,11 @@ | ||||||
| import { Client } from '../models/client.ts' | import { Client } from '../models/client.ts' | ||||||
| import { GatewayIntents } from '../types/gatewayTypes.ts' | import { GatewayIntents } from '../types/gatewayTypes.ts' | ||||||
| import { TOKEN } from './config.ts' | import { TOKEN } from './config.ts' | ||||||
| import * as cache from '../models/cache.ts' |  | ||||||
| import { Member } from '../structures/member.ts' |  | ||||||
| import { Channel } from '../structures/channel.ts' | import { Channel } from '../structures/channel.ts' | ||||||
| import { GuildTextChannel } from '../structures/guildTextChannel.ts' | import { GuildTextChannel } from '../structures/guildTextChannel.ts' | ||||||
|  | import { TextChannel } from '../structures/textChannel.ts' | ||||||
|  | import { Guild } from '../structures/guild.ts' | ||||||
|  | import { User } from '../structures/user.ts' | ||||||
| 
 | 
 | ||||||
| const bot = new Client() | const bot = new Client() | ||||||
| 
 | 
 | ||||||
|  | @ -12,18 +13,66 @@ bot.on('ready', () => { | ||||||
|   console.log('READY!') |   console.log('READY!') | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
|  | bot.on('channelDelete', (channel: Channel) => { | ||||||
|  |   console.log('channelDelete', channel.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
| bot.on('channelUpdate', (before: Channel, after: Channel) => { | bot.on('channelUpdate', (before: Channel, after: Channel) => { | ||||||
|   if (before instanceof GuildTextChannel && after instanceof GuildTextChannel) { |   if (before instanceof GuildTextChannel && after instanceof GuildTextChannel) { | ||||||
|     console.log(before.name) |     console.log('channelUpdate', before.name) | ||||||
|     console.log(after.name) |     console.log('channelUpdate', after.name) | ||||||
|   } else { |   } else { | ||||||
|     console.log(before) |     console.log('channelUpdate', before.id) | ||||||
|     console.log(after) |     console.log('channelUpdate', after.id) | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
|  | bot.on('channelCreate', (channel: Channel) => { | ||||||
|  |   console.log('channelCreate', channel.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('channelPinsUpdate', (before: TextChannel, after: TextChannel) => { | ||||||
|  |   console.log( | ||||||
|  |     'channelPinsUpdate', | ||||||
|  |     before.lastPinTimestamp, | ||||||
|  |     after.lastPinTimestamp | ||||||
|  |   ) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('guildBanAdd', (guild: Guild, user: User) => { | ||||||
|  |   console.log('guildBanAdd', guild.id, user.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('guildBanRemove', (guild: Guild, user: User) => { | ||||||
|  |   console.log('guildBanRemove', guild.id, user.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('guildCreate', (guild: Guild) => { | ||||||
|  |   console.log('guildCreate', guild.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('guildDelete', (guild: Guild) => { | ||||||
|  |   console.log('guildDelete', guild.id) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
|  | bot.on('guildUpdate', (before: Guild, after: Guild) => { | ||||||
|  |   console.log('guildUpdate', before.name, after.name) | ||||||
|  | }) | ||||||
|  | 
 | ||||||
| bot.connect(TOKEN, [ | bot.connect(TOKEN, [ | ||||||
|   GatewayIntents.GUILD_MEMBERS, |   GatewayIntents.GUILD_MEMBERS, | ||||||
|   GatewayIntents.GUILD_PRESENCES, |   GatewayIntents.GUILD_PRESENCES, | ||||||
|   GatewayIntents.GUILD_MESSAGES |   GatewayIntents.GUILD_MESSAGES, | ||||||
|  |   GatewayIntents.DIRECT_MESSAGES, | ||||||
|  |   GatewayIntents.DIRECT_MESSAGE_REACTIONS, | ||||||
|  |   GatewayIntents.DIRECT_MESSAGE_TYPING, | ||||||
|  |   GatewayIntents.GUILDS, | ||||||
|  |   GatewayIntents.GUILD_BANS, | ||||||
|  |   GatewayIntents.GUILD_EMOJIS, | ||||||
|  |   GatewayIntents.GUILD_INTEGRATIONS, | ||||||
|  |   GatewayIntents.GUILD_INVITES, | ||||||
|  |   GatewayIntents.GUILD_MESSAGE_REACTIONS, | ||||||
|  |   GatewayIntents.GUILD_MESSAGE_TYPING, | ||||||
|  |   GatewayIntents.GUILD_VOICE_STATES, | ||||||
|  |   GatewayIntents.GUILD_WEBHOOKS | ||||||
| ]) | ]) | ||||||
|  |  | ||||||
|  | @ -3,17 +3,17 @@ import { EmojiPayload } from './emojiTypes.ts' | ||||||
| import { MemberPayload } from './guildTypes.ts' | import { MemberPayload } from './guildTypes.ts' | ||||||
| import { UserPayload } from './userTypes.ts' | import { UserPayload } from './userTypes.ts' | ||||||
| 
 | 
 | ||||||
| interface ChannelPayload { | export interface ChannelPayload { | ||||||
|   id: string |   id: string | ||||||
|   type: ChannelTypes |   type: ChannelTypes | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface TextChannelPayload extends ChannelPayload { | export interface TextChannelPayload extends ChannelPayload { | ||||||
|   last_message_id?: string |   last_message_id?: string | ||||||
|   last_pin_timestamp?: string |   last_pin_timestamp?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GuildChannelPayload extends ChannelPayload { | export interface GuildChannelPayload extends ChannelPayload { | ||||||
|   guild_id: string |   guild_id: string | ||||||
|   name: string |   name: string | ||||||
|   position: number |   position: number | ||||||
|  | @ -22,46 +22,46 @@ interface GuildChannelPayload extends ChannelPayload { | ||||||
|   parent_id?: string |   parent_id?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GuildTextChannelPayload | export interface GuildTextChannelPayload | ||||||
|   extends TextChannelPayload, |   extends TextChannelPayload, | ||||||
|     GuildChannelPayload { |     GuildChannelPayload { | ||||||
|   rate_limit_per_user: number |   rate_limit_per_user: number | ||||||
|   topic?: string |   topic?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GuildNewsChannelPayload | export interface GuildNewsChannelPayload | ||||||
|   extends TextChannelPayload, |   extends TextChannelPayload, | ||||||
|     GuildChannelPayload { |     GuildChannelPayload { | ||||||
|   topic?: string |   topic?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GuildVoiceChannelPayload extends GuildChannelPayload { | export interface GuildVoiceChannelPayload extends GuildChannelPayload { | ||||||
|   bitrate: string |   bitrate: string | ||||||
|   user_limit: number |   user_limit: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface DMChannelPayload extends TextChannelPayload { | export interface DMChannelPayload extends TextChannelPayload { | ||||||
|   recipients: UserPayload[] |   recipients: UserPayload[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GroupDMChannelPayload extends DMChannelPayload { | export interface GroupDMChannelPayload extends DMChannelPayload { | ||||||
|   name: string |   name: string | ||||||
|   icon?: string |   icon?: string | ||||||
|   owner_id: string |   owner_id: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface GuildChannelCategoryPayload | export interface GuildChannelCategoryPayload | ||||||
|   extends ChannelPayload, |   extends ChannelPayload, | ||||||
|     GuildChannelPayload {} |     GuildChannelPayload {} | ||||||
| 
 | 
 | ||||||
| interface Overwrite { | export interface Overwrite { | ||||||
|   id: string |   id: string | ||||||
|   type: number |   type: number | ||||||
|   allow: string |   allow: string | ||||||
|   deny: string |   deny: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum ChannelTypes { | export enum ChannelTypes { | ||||||
|   GUILD_TEXT = 0, |   GUILD_TEXT = 0, | ||||||
|   DM = 1, |   DM = 1, | ||||||
|   GUILD_VOICE = 2, |   GUILD_VOICE = 2, | ||||||
|  | @ -71,7 +71,7 @@ enum ChannelTypes { | ||||||
|   GUILD_STORE = 6 |   GUILD_STORE = 6 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MessagePayload { | export interface MessagePayload { | ||||||
|   id: string |   id: string | ||||||
|   channel_id: string |   channel_id: string | ||||||
|   guild_id?: string |   guild_id?: string | ||||||
|  | @ -98,7 +98,7 @@ interface MessagePayload { | ||||||
|   flags?: number |   flags?: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MessageOption { | export interface MessageOption { | ||||||
|   tts: boolean |   tts: boolean | ||||||
|   embed: Embed |   embed: Embed | ||||||
|   file: Attachment |   file: Attachment | ||||||
|  | @ -109,14 +109,14 @@ interface MessageOption { | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface ChannelMention { | export interface ChannelMention { | ||||||
|   id: string |   id: string | ||||||
|   guild_id: string |   guild_id: string | ||||||
|   type: ChannelTypes |   type: ChannelTypes | ||||||
|   name: string |   name: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface Attachment { | export interface Attachment { | ||||||
|   id: string |   id: string | ||||||
|   filename: string |   filename: string | ||||||
|   size: number |   size: number | ||||||
|  | @ -126,7 +126,7 @@ interface Attachment { | ||||||
|   width: number | undefined |   width: number | undefined | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedPayload { | export interface EmbedPayload { | ||||||
|   title?: string |   title?: string | ||||||
|   type?: EmbedTypes |   type?: EmbedTypes | ||||||
|   description?: string |   description?: string | ||||||
|  | @ -142,64 +142,70 @@ interface EmbedPayload { | ||||||
|   fields?: EmbedField[] |   fields?: EmbedField[] | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type EmbedTypes = 'rich' | 'image' | 'video' | 'gifv' | 'article' | 'link' | export type EmbedTypes = | ||||||
|  |   | 'rich' | ||||||
|  |   | 'image' | ||||||
|  |   | 'video' | ||||||
|  |   | 'gifv' | ||||||
|  |   | 'article' | ||||||
|  |   | 'link' | ||||||
| 
 | 
 | ||||||
| interface EmbedField { | export interface EmbedField { | ||||||
|   name: string |   name: string | ||||||
|   value: string |   value: string | ||||||
|   inline?: boolean |   inline?: boolean | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedAuthor { | export interface EmbedAuthor { | ||||||
|   name?: string |   name?: string | ||||||
|   url?: string |   url?: string | ||||||
|   icon_url?: string |   icon_url?: string | ||||||
|   proxy_icon_url?: string |   proxy_icon_url?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedFooter { | export interface EmbedFooter { | ||||||
|   text: string |   text: string | ||||||
|   icon_url?: string |   icon_url?: string | ||||||
|   proxy_icon_url?: string |   proxy_icon_url?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedImage { | export interface EmbedImage { | ||||||
|   url?: string |   url?: string | ||||||
|   proxy_url?: string |   proxy_url?: string | ||||||
|   height?: number |   height?: number | ||||||
|   width?: number |   width?: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedProvider { | export interface EmbedProvider { | ||||||
|   name?: string |   name?: string | ||||||
|   url?: string |   url?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedVideo { | export interface EmbedVideo { | ||||||
|   url?: string |   url?: string | ||||||
|   height?: number |   height?: number | ||||||
|   width?: number |   width?: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface EmbedThumbnail { | export interface EmbedThumbnail { | ||||||
|   url?: string |   url?: string | ||||||
|   proxy_url?: string |   proxy_url?: string | ||||||
|   height?: number |   height?: number | ||||||
|   width?: number |   width?: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface Reaction { | export interface Reaction { | ||||||
|   count: number |   count: number | ||||||
|   me: boolean |   me: boolean | ||||||
|   emoji: EmojiPayload |   emoji: EmojiPayload | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MessageActivity { | export interface MessageActivity { | ||||||
|   type: MessageTypes |   type: MessageTypes | ||||||
|   party_id?: string |   party_id?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MessageApplication { | export interface MessageApplication { | ||||||
|   id: string |   id: string | ||||||
|   cover_image?: string |   cover_image?: string | ||||||
|   desription: string |   desription: string | ||||||
|  | @ -207,13 +213,13 @@ interface MessageApplication { | ||||||
|   name: string |   name: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MessageReference { | export interface MessageReference { | ||||||
|   message_id?: string |   message_id?: string | ||||||
|   channel_id?: string |   channel_id?: string | ||||||
|   guild_id?: string |   guild_id?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum MessageTypes { | export enum MessageTypes { | ||||||
|   DEFAULT = 0, |   DEFAULT = 0, | ||||||
|   RECIPIENT_ADD = 1, |   RECIPIENT_ADD = 1, | ||||||
|   RECIPIENT_REMOVE = 2, |   RECIPIENT_REMOVE = 2, | ||||||
|  | @ -231,14 +237,14 @@ enum MessageTypes { | ||||||
|   GUILD_DISCOVERY_REQUALIFIED = 15 |   GUILD_DISCOVERY_REQUALIFIED = 15 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum MessageActivityTypes { | export enum MessageActivityTypes { | ||||||
|   JOIN = 1, |   JOIN = 1, | ||||||
|   SPECTATE = 2, |   SPECTATE = 2, | ||||||
|   LISTEN = 3, |   LISTEN = 3, | ||||||
|   JOIN_REQUEST = 4 |   JOIN_REQUEST = 4 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum MessageFlags { | export enum MessageFlags { | ||||||
|   CROSSPOSTED = 1 << 0, |   CROSSPOSTED = 1 << 0, | ||||||
|   IS_CROSSPOST = 1 << 1, |   IS_CROSSPOST = 1 << 1, | ||||||
|   SUPPRESS_EMBEDS = 1 << 2, |   SUPPRESS_EMBEDS = 1 << 2, | ||||||
|  | @ -246,54 +252,7 @@ enum MessageFlags { | ||||||
|   URGENT = 1 << 4 |   URGENT = 1 << 4 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface FollowedChannel { | export interface FollowedChannel { | ||||||
|   channel_id: string |   channel_id: string | ||||||
|   webhook_id: string |   webhook_id: string | ||||||
| } | } | ||||||
| 
 |  | ||||||
| interface Overwrite { |  | ||||||
|   id: string |  | ||||||
|   type: number |  | ||||||
|   allow: string |  | ||||||
|   deny: string |  | ||||||
| } |  | ||||||
| interface ChannelMention { |  | ||||||
|   id: string |  | ||||||
|   guild_id: string |  | ||||||
|   type: ChannelTypes |  | ||||||
|   name: string |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| export { |  | ||||||
|   ChannelPayload, |  | ||||||
|   TextChannelPayload, |  | ||||||
|   GuildChannelPayload, |  | ||||||
|   GuildNewsChannelPayload, |  | ||||||
|   GuildTextChannelPayload, |  | ||||||
|   GuildVoiceChannelPayload, |  | ||||||
|   GuildChannelCategoryPayload, |  | ||||||
|   DMChannelPayload, |  | ||||||
|   GroupDMChannelPayload, |  | ||||||
|   Overwrite, |  | ||||||
|   ChannelTypes, |  | ||||||
|   ChannelMention, |  | ||||||
|   Attachment, |  | ||||||
|   Reaction, |  | ||||||
|   MessageActivity, |  | ||||||
|   MessageActivityTypes, |  | ||||||
|   MessageFlags, |  | ||||||
|   FollowedChannel, |  | ||||||
|   MessageApplication, |  | ||||||
|   MessageReference, |  | ||||||
|   MessagePayload, |  | ||||||
|   MessageOption, |  | ||||||
|   EmbedPayload, |  | ||||||
|   EmbedTypes, |  | ||||||
|   EmbedFooter, |  | ||||||
|   EmbedImage, |  | ||||||
|   EmbedThumbnail, |  | ||||||
|   EmbedVideo, |  | ||||||
|   EmbedProvider, |  | ||||||
|   EmbedAuthor, |  | ||||||
|   EmbedField |  | ||||||
| } |  | ||||||
|  |  | ||||||
|  | @ -4,11 +4,9 @@ import { GatewayOpcodes, GatewayEvents } from '../types/gatewayTypes.ts' | ||||||
|  * Gateway response from Discord. |  * Gateway response from Discord. | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| interface GatewayResponse { | export interface GatewayResponse { | ||||||
|   op: GatewayOpcodes |   op: GatewayOpcodes | ||||||
|   d: any |   d: any | ||||||
|   s?: number |   s?: number | ||||||
|   t?: GatewayEvents |   t?: GatewayEvents | ||||||
| } | } | ||||||
| 
 |  | ||||||
| export { GatewayResponse } |  | ||||||
|  |  | ||||||
|  | @ -62,11 +62,9 @@ enum GatewayIntents { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| enum GatewayEvents { | enum GatewayEvents { | ||||||
|   Hello = 'HELLO', |  | ||||||
|   Ready = 'READY', |   Ready = 'READY', | ||||||
|   Resumed = 'RESUMED', |   Resumed = 'RESUMED', | ||||||
|   Reconnect = 'RECONNECT', |   Reconnect = 'RECONNECT', | ||||||
|   Invalid_Session = 'INVALID_SESSION', |  | ||||||
|   Channel_Create = 'CHANNEL_CREATE', |   Channel_Create = 'CHANNEL_CREATE', | ||||||
|   Channel_Update = 'CHANNEL_UPDATE', |   Channel_Update = 'CHANNEL_UPDATE', | ||||||
|   Channel_Delete = 'CHANNEL_DELETE', |   Channel_Delete = 'CHANNEL_DELETE', | ||||||
|  | @ -89,7 +87,7 @@ enum GatewayEvents { | ||||||
|   Invite_Delete = 'INVITE_DELETE', |   Invite_Delete = 'INVITE_DELETE', | ||||||
|   Message_Create = 'MESSAGE_CREATE', |   Message_Create = 'MESSAGE_CREATE', | ||||||
|   Message_Update = 'MESSAGE_UPDATE', |   Message_Update = 'MESSAGE_UPDATE', | ||||||
|   Message_Delete = 'MESSAG_DELETE', |   Message_Delete = 'MESSAGE_DELETE', | ||||||
|   Message_Delete_Bulk = 'MESSAGE_DELETE_BULK', |   Message_Delete_Bulk = 'MESSAGE_DELETE_BULK', | ||||||
|   Message_Reaction_Add = 'MESSAGE_REACTION_ADD', |   Message_Reaction_Add = 'MESSAGE_REACTION_ADD', | ||||||
|   Message_Reaction_Remove = 'MESSAGE_REACTION_REMOVE', |   Message_Reaction_Remove = 'MESSAGE_REACTION_REMOVE', | ||||||
|  | @ -98,7 +96,6 @@ enum GatewayEvents { | ||||||
|   Presence_Update = 'PRESENCE_UPDATE', |   Presence_Update = 'PRESENCE_UPDATE', | ||||||
|   Typing_Start = 'TYPING_START', |   Typing_Start = 'TYPING_START', | ||||||
|   User_Update = 'USER_UPDATE', |   User_Update = 'USER_UPDATE', | ||||||
|   Voice_State_Update = 'VOICE_STATE_UPDATE', |  | ||||||
|   Voice_Server_Update = 'VOICE_SERVER_UPDATE', |   Voice_Server_Update = 'VOICE_SERVER_UPDATE', | ||||||
|   Webhooks_Update = 'WEBHOOKS_UPDATE' |   Webhooks_Update = 'WEBHOOKS_UPDATE' | ||||||
| } | } | ||||||
|  | @ -395,5 +392,5 @@ interface WebhooksUpdate { | ||||||
|   channel_id: string |   channel_id: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //https://discord.com/developers/docs/topics/gateway#typing-start-typing-start-event-fields
 | // https://discord.com/developers/docs/topics/gateway#typing-start-typing-start-event-fields
 | ||||||
| export { GatewayCloseCodes, GatewayOpcodes, GatewayIntents, GatewayEvents } | export { GatewayCloseCodes, GatewayOpcodes, GatewayIntents, GatewayEvents } | ||||||
|  |  | ||||||
|  | @ -5,7 +5,7 @@ import { RolePayload } from './roleTypes.ts' | ||||||
| import { UserPayload } from './userTypes.ts' | import { UserPayload } from './userTypes.ts' | ||||||
| import { VoiceStatePayload } from './voiceTypes.ts' | import { VoiceStatePayload } from './voiceTypes.ts' | ||||||
| 
 | 
 | ||||||
| interface GuildPayload { | export interface GuildPayload { | ||||||
|   id: string |   id: string | ||||||
|   name: string |   name: string | ||||||
|   icon?: string |   icon?: string | ||||||
|  | @ -53,7 +53,7 @@ interface GuildPayload { | ||||||
|   approximate_presence_count?: number |   approximate_presence_count?: number | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MemberPayload { | export interface MemberPayload { | ||||||
|   user: UserPayload |   user: UserPayload | ||||||
|   nick?: string |   nick?: string | ||||||
|   roles: string[] |   roles: string[] | ||||||
|  | @ -99,7 +99,7 @@ enum SystemChannelFlags { | ||||||
|   SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1 |   SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type GuildFeatures = | export type GuildFeatures = | ||||||
|   | 'INVITE_SPLASH' |   | 'INVITE_SPLASH' | ||||||
|   | 'VIP_REGIONS' |   | 'VIP_REGIONS' | ||||||
|   | 'VANITY_URL' |   | 'VANITY_URL' | ||||||
|  | @ -112,5 +112,3 @@ type GuildFeatures = | ||||||
|   | 'FEATURABLE' |   | 'FEATURABLE' | ||||||
|   | 'ANIMATED_ICON' |   | 'ANIMATED_ICON' | ||||||
|   | 'BANNER' |   | 'BANNER' | ||||||
| 
 |  | ||||||
| export { MemberPayload, GuildPayload, GuildFeatures } |  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| import { UserPayload } from './userTypes.ts' | import { UserPayload } from './userTypes.ts' | ||||||
| 
 | 
 | ||||||
| interface PresenceUpdatePayload { | export interface PresenceUpdatePayload { | ||||||
|   user: UserPayload |   user: UserPayload | ||||||
|   guild_id: string |   guild_id: string | ||||||
|   status: string |   status: string | ||||||
|  | @ -14,7 +14,7 @@ interface ClientStatus { | ||||||
|   web?: string |   web?: string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface ActivityPayload { | export interface ActivityPayload { | ||||||
|   name: string |   name: string | ||||||
|   type: 0 | 1 | 2 | 3 | 4 | 5 |   type: 0 | 1 | 2 | 3 | 4 | 5 | ||||||
|   url?: string | undefined |   url?: string | undefined | ||||||
|  | @ -68,5 +68,3 @@ enum ActivityFlags { | ||||||
|   SYNC = 1 << 4, |   SYNC = 1 << 4, | ||||||
|   PLAY = 1 << 5 |   PLAY = 1 << 5 | ||||||
| } | } | ||||||
| 
 |  | ||||||
| export { ActivityPayload, PresenceUpdatePayload } |  | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								src/utils/getChannelByType.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/utils/getChannelByType.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | import { Client } from '../models/client.ts' | ||||||
|  | import { | ||||||
|  |   ChannelPayload, | ||||||
|  |   ChannelTypes, | ||||||
|  |   DMChannelPayload, | ||||||
|  |   GroupDMChannelPayload, | ||||||
|  |   GuildChannelCategoryPayload, | ||||||
|  |   GuildNewsChannelPayload, | ||||||
|  |   GuildTextChannelPayload, | ||||||
|  |   GuildVoiceChannelPayload | ||||||
|  | } from '../types/channelTypes.ts' | ||||||
|  | import { DMChannel } from '../structures/dmChannel.ts' | ||||||
|  | import { GroupDMChannel } from '../structures/groupChannel.ts' | ||||||
|  | import { CategoryChannel } from '../structures/guildCategoryChannel.ts' | ||||||
|  | import { NewsChannel } from '../structures/guildNewsChannel.ts' | ||||||
|  | import { VoiceChannel } from '../structures/guildVoiceChannel.ts' | ||||||
|  | import { TextChannel } from '../structures/textChannel.ts' | ||||||
|  | 
 | ||||||
|  | const getChannelByType = ( | ||||||
|  |   client: Client, | ||||||
|  |   data: | ||||||
|  |     | GuildChannelCategoryPayload | ||||||
|  |     | GuildNewsChannelPayload | ||||||
|  |     | GuildTextChannelPayload | ||||||
|  |     | GuildVoiceChannelPayload | ||||||
|  |     | DMChannelPayload | ||||||
|  |     | GroupDMChannelPayload | ||||||
|  |     | ChannelPayload | ||||||
|  | ): | ||||||
|  |   | CategoryChannel | ||||||
|  |   | NewsChannel | ||||||
|  |   | TextChannel | ||||||
|  |   | VoiceChannel | ||||||
|  |   | DMChannel | ||||||
|  |   | GroupDMChannel | ||||||
|  |   | undefined => { | ||||||
|  |   switch (data.type) { | ||||||
|  |     case ChannelTypes.GUILD_CATEGORY: | ||||||
|  |       return new CategoryChannel(client, data as GuildChannelCategoryPayload) | ||||||
|  |     case ChannelTypes.GUILD_NEWS: | ||||||
|  |       return new NewsChannel(client, data as GuildNewsChannelPayload) | ||||||
|  |     case ChannelTypes.GUILD_TEXT: | ||||||
|  |       return new TextChannel(client, data as GuildTextChannelPayload) | ||||||
|  |     case ChannelTypes.GUILD_VOICE: | ||||||
|  |       return new VoiceChannel(client, data as GuildVoiceChannelPayload) | ||||||
|  |     case ChannelTypes.DM: | ||||||
|  |       return new DMChannel(client, data as DMChannelPayload) | ||||||
|  |     case ChannelTypes.GROUP_DM: | ||||||
|  |       return new GroupDMChannel(client, data as GroupDMChannelPayload) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default getChannelByType | ||||||
							
								
								
									
										3
									
								
								src/utils/index.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/utils/index.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | import getChannelByType from './getChannelByType.ts' | ||||||
|  | 
 | ||||||
|  | export default { getChannelByType } | ||||||
|  | @ -25,7 +25,7 @@ | ||||||
|     // "noEmit": true,                        /* Do not emit outputs. */ |     // "noEmit": true,                        /* Do not emit outputs. */ | ||||||
|     // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */ |     // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */ | ||||||
|     // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ |     // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ | ||||||
|     // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ |     "isolatedModules": true /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */, | ||||||
|     /* Strict Type-Checking Options */ |     /* Strict Type-Checking Options */ | ||||||
|     "strict": true, |     "strict": true, | ||||||
|     /* Enable all strict type-checking options. */ |     /* Enable all strict type-checking options. */ | ||||||
|  | @ -61,7 +61,7 @@ | ||||||
|     // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ |     // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ | ||||||
|     /* Experimental Options */ |     /* Experimental Options */ | ||||||
|     // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */ |     // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */ | ||||||
|     // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */ |     "emitDecoratorMetadata": false /* Enables experimental support for emitting type metadata for decorators. */, | ||||||
|     /* Advanced Options */ |     /* Advanced Options */ | ||||||
|     "skipLibCheck": true, |     "skipLibCheck": true, | ||||||
|     /* Skip type checking of declaration files. */ |     /* Skip type checking of declaration files. */ | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue