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
				
			
		
							
								
								
									
										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 { GatewayIntents } from '../types/gatewayTypes.ts' | ||||
| import { Gateway } from './gateway.ts' | ||||
| import { Gateway } from '../gateway/index.ts' | ||||
| import { Rest } from './rest.ts' | ||||
| import EventEmitter from 'https://deno.land/std@0.74.0/node/events.ts' | ||||
| 
 | ||||
| /** | ||||
|  * 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 | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: { [k: string]: any }): void {} | ||||
|   protected readFromData (data: { [k: string]: any }): void {} | ||||
| 
 | ||||
|   // toJSON() {}
 | ||||
| } | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ export class Channel extends Base { | |||
|     cache.set('channel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: ChannelPayload): void { | ||||
|   protected readFromData (data: ChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.type = data.type ?? this.type | ||||
|     this.id = data.id ?? this.id | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ export class DMChannel extends TextChannel { | |||
|     cache.set('dmchannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: DMChannelPayload): void { | ||||
|   protected readFromData (data: DMChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.recipients = data.recipients ?? this.recipients | ||||
|   } | ||||
|  |  | |||
|  | @ -37,7 +37,7 @@ export class Emoji extends Base { | |||
|     this.available = data.available | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: EmojiPayload): void { | ||||
|   protected readFromData (data: EmojiPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.id = data.id ?? this.id | ||||
|     this.name = data.name ?? this.name | ||||
|  |  | |||
|  | @ -17,7 +17,7 @@ export class GroupDMChannel extends Channel { | |||
|     cache.set('groupchannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: GroupDMChannelPayload): void { | ||||
|   protected readFromData (data: GroupDMChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.name = data.name ?? this.name | ||||
|     this.icon = data.icon ?? this.icon | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import { Member } from './member.ts' | |||
| import { Role } from './role.ts' | ||||
| import { VoiceState } from './voiceState.ts' | ||||
| import cache from '../models/cache.ts' | ||||
| import getChannelByType from '../utils/getChannelByType.ts' | ||||
| 
 | ||||
| export class Guild extends Base { | ||||
|   id: string | ||||
|  | @ -103,7 +104,7 @@ export class Guild extends Base { | |||
|           new Member(client, v) | ||||
|       ) | ||||
|       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.maxPresences = data.max_presences | ||||
|  | @ -122,7 +123,7 @@ export class Guild extends Base { | |||
|     cache.set('guild', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: GuildPayload): void { | ||||
|   protected readFromData (data: GuildPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.id = data.id ?? this.id | ||||
|     this.unavailable = data.unavailable ?? this.unavailable | ||||
|  | @ -177,7 +178,7 @@ export class Guild extends Base { | |||
|         ) ?? this.members | ||||
|       this.channels = | ||||
|         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.presences = data.presences ?? this.presences | ||||
|       this.maxPresences = data.max_presences ?? this.maxPresences | ||||
|  |  | |||
|  | @ -25,7 +25,7 @@ export class CategoryChannel extends Channel { | |||
|     cache.set('guildcategorychannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: GuildChannelCategoryPayload): void { | ||||
|   protected readFromData (data: GuildChannelCategoryPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.guildID = data.guild_id ?? this.guildID | ||||
|     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 { GuildChannel } from './guildChannel.ts' | ||||
| import { GuildTextChannelPayload } from '../types/channelTypes.ts' | ||||
| import { GuildTextChannelPayload, Overwrite } from '../types/channelTypes.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 | ||||
|   topic?: string | ||||
| 
 | ||||
|  | @ -13,13 +19,26 @@ export class GuildTextChannel extends GuildChannel { | |||
| 
 | ||||
|   constructor (client: Client, data: GuildTextChannelPayload) { | ||||
|     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.rateLimit = data.rate_limit_per_user | ||||
|     cache.set('guildtextchannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: GuildTextChannelPayload): void { | ||||
|   protected readFromData (data: GuildTextChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.guildID = data.guild_id ?? this.guildID | ||||
|     this.name = data.name ?? this.name | ||||
|     this.position = data.position ?? this.position | ||||
|     this.permissionOverwrites = | ||||
|       data.permission_overwrites ?? this.permissionOverwrites | ||||
|     this.nsfw = data.nsfw ?? this.nsfw | ||||
|     this.parentID = data.parent_id ?? this.parentID | ||||
|     this.topic = data.topic ?? this.topic | ||||
|     this.rateLimit = data.rate_limit_per_user ?? this.rateLimit | ||||
|   } | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ export class VoiceChannel extends Channel { | |||
|     cache.set('guildvoicechannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: GuildVoiceChannelPayload): void { | ||||
|   protected readFromData (data: GuildVoiceChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.bitrate = data.bitrate ?? this.bitrate | ||||
|     this.userLimit = data.user_limit ?? this.userLimit | ||||
|  |  | |||
|  | @ -1,10 +1,36 @@ | |||
| import { Client } from '../models/client.ts' | ||||
| import { Channel } from './channel.ts' | ||||
| import { GuildNewsChannelPayload } from '../types/channelTypes.ts' | ||||
| import { GuildNewsChannelPayload, Overwrite } 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) { | ||||
|     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 | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: InvitePayload): void { | ||||
|   protected readFromData (data: InvitePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.code = data.code ?? this.code | ||||
|     this.guild = data.guild ?? this.guild | ||||
|  |  | |||
|  | @ -1,9 +1,12 @@ | |||
| import cache from '../models/cache.ts' | ||||
| import { Client } from '../models/client.ts' | ||||
| import { MemberPayload } from '../types/guildTypes.ts' | ||||
| import { Base } from './base.ts' | ||||
| import { User } from './user.ts' | ||||
| 
 | ||||
| export class Member extends User { | ||||
| export class Member extends Base { | ||||
|   id: string | ||||
|   user: User | ||||
|   nick?: string | ||||
|   roles: string[] | ||||
|   joinedAt: string | ||||
|  | @ -12,7 +15,10 @@ export class Member extends User { | |||
|   mute: boolean | ||||
| 
 | ||||
|   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.roles = data.roles | ||||
|     this.joinedAt = data.joined_at | ||||
|  | @ -22,8 +28,8 @@ export class Member extends User { | |||
|     cache.set('member', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: MemberPayload): void { | ||||
|     super.readFromData(data) | ||||
|   protected readFromData (data: MemberPayload): void { | ||||
|     super.readFromData(data.user) | ||||
|     this.nick = data.nick ?? this.nick | ||||
|     this.roles = data.roles ?? this.roles | ||||
|     this.joinedAt = data.joined_at ?? this.joinedAt | ||||
|  |  | |||
|  | @ -76,14 +76,14 @@ export class Message extends Base { | |||
|     cache.set('message', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: MessagePayload): void { | ||||
|   protected readFromData (data: MessagePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.channelID = data.channel_id ?? this.channelID | ||||
|     this.guildID = data.guild_id ?? this.guildID | ||||
|     this.author = | ||||
|       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.timestamp = data.timestamp ?? this.timestamp | ||||
|     this.editedTimestamp = data.edited_timestamp ?? this.editedTimestamp | ||||
|  |  | |||
|  | @ -30,7 +30,7 @@ export class Role extends Base { | |||
|     cache.set('role', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: RolePayload): void { | ||||
|   protected readFromData (data: RolePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.name = data.name ?? this.name | ||||
|     this.color = data.color ?? this.color | ||||
|  |  | |||
|  | @ -16,7 +16,7 @@ export class TextChannel extends Channel { | |||
|     cache.set('textchannel', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: TextChannelPayload): void { | ||||
|   protected readFromData (data: TextChannelPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.lastMessageID = data.last_message_id ?? this.lastMessageID | ||||
|     this.lastPinTimestamp = data.last_pin_timestamp ?? this.lastPinTimestamp | ||||
|  |  | |||
|  | @ -44,7 +44,7 @@ export class User extends Base { | |||
|     cache.set('user', this.id, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: UserPayload): void { | ||||
|   protected readFromData (data: UserPayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.username = data.username ?? this.username | ||||
|     this.discriminator = data.discriminator ?? this.discriminator | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ export class VoiceState extends Base { | |||
|     cache.set('voiceState', `${this.guildID}:${this.userID}`, this) | ||||
|   } | ||||
| 
 | ||||
|   readFromData (data: VoiceStatePayload): void { | ||||
|   protected readFromData (data: VoiceStatePayload): void { | ||||
|     super.readFromData(data) | ||||
|     this.channelID = data.channel_id ?? this.channelID | ||||
|     this.sessionID = data.session_id ?? this.sessionID | ||||
|  |  | |||
|  | @ -1,10 +1,11 @@ | |||
| import { Client } from '../models/client.ts' | ||||
| import { GatewayIntents } from '../types/gatewayTypes.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 { 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() | ||||
| 
 | ||||
|  | @ -12,18 +13,66 @@ bot.on('ready', () => { | |||
|   console.log('READY!') | ||||
| }) | ||||
| 
 | ||||
| bot.on('channelDelete', (channel: Channel) => { | ||||
|   console.log('channelDelete', channel.id) | ||||
| }) | ||||
| 
 | ||||
| bot.on('channelUpdate', (before: Channel, after: Channel) => { | ||||
|   if (before instanceof GuildTextChannel && after instanceof GuildTextChannel) { | ||||
|     console.log(before.name) | ||||
|     console.log(after.name) | ||||
|     console.log('channelUpdate', before.name) | ||||
|     console.log('channelUpdate', after.name) | ||||
|   } else { | ||||
|     console.log(before) | ||||
|     console.log(after) | ||||
|     console.log('channelUpdate', before.id) | ||||
|     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, [ | ||||
|   GatewayIntents.GUILD_MEMBERS, | ||||
|   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 { UserPayload } from './userTypes.ts' | ||||
| 
 | ||||
| interface ChannelPayload { | ||||
| export interface ChannelPayload { | ||||
|   id: string | ||||
|   type: ChannelTypes | ||||
| } | ||||
| 
 | ||||
| interface TextChannelPayload extends ChannelPayload { | ||||
| export interface TextChannelPayload extends ChannelPayload { | ||||
|   last_message_id?: string | ||||
|   last_pin_timestamp?: string | ||||
| } | ||||
| 
 | ||||
| interface GuildChannelPayload extends ChannelPayload { | ||||
| export interface GuildChannelPayload extends ChannelPayload { | ||||
|   guild_id: string | ||||
|   name: string | ||||
|   position: number | ||||
|  | @ -22,46 +22,46 @@ interface GuildChannelPayload extends ChannelPayload { | |||
|   parent_id?: string | ||||
| } | ||||
| 
 | ||||
| interface GuildTextChannelPayload | ||||
| export interface GuildTextChannelPayload | ||||
|   extends TextChannelPayload, | ||||
|     GuildChannelPayload { | ||||
|   rate_limit_per_user: number | ||||
|   topic?: string | ||||
| } | ||||
| 
 | ||||
| interface GuildNewsChannelPayload | ||||
| export interface GuildNewsChannelPayload | ||||
|   extends TextChannelPayload, | ||||
|     GuildChannelPayload { | ||||
|   topic?: string | ||||
| } | ||||
| 
 | ||||
| interface GuildVoiceChannelPayload extends GuildChannelPayload { | ||||
| export interface GuildVoiceChannelPayload extends GuildChannelPayload { | ||||
|   bitrate: string | ||||
|   user_limit: number | ||||
| } | ||||
| 
 | ||||
| interface DMChannelPayload extends TextChannelPayload { | ||||
| export interface DMChannelPayload extends TextChannelPayload { | ||||
|   recipients: UserPayload[] | ||||
| } | ||||
| 
 | ||||
| interface GroupDMChannelPayload extends DMChannelPayload { | ||||
| export interface GroupDMChannelPayload extends DMChannelPayload { | ||||
|   name: string | ||||
|   icon?: string | ||||
|   owner_id: string | ||||
| } | ||||
| 
 | ||||
| interface GuildChannelCategoryPayload | ||||
| export interface GuildChannelCategoryPayload | ||||
|   extends ChannelPayload, | ||||
|     GuildChannelPayload {} | ||||
| 
 | ||||
| interface Overwrite { | ||||
| export interface Overwrite { | ||||
|   id: string | ||||
|   type: number | ||||
|   allow: string | ||||
|   deny: string | ||||
| } | ||||
| 
 | ||||
| enum ChannelTypes { | ||||
| export enum ChannelTypes { | ||||
|   GUILD_TEXT = 0, | ||||
|   DM = 1, | ||||
|   GUILD_VOICE = 2, | ||||
|  | @ -71,7 +71,7 @@ enum ChannelTypes { | |||
|   GUILD_STORE = 6 | ||||
| } | ||||
| 
 | ||||
| interface MessagePayload { | ||||
| export interface MessagePayload { | ||||
|   id: string | ||||
|   channel_id: string | ||||
|   guild_id?: string | ||||
|  | @ -98,7 +98,7 @@ interface MessagePayload { | |||
|   flags?: number | ||||
| } | ||||
| 
 | ||||
| interface MessageOption { | ||||
| export interface MessageOption { | ||||
|   tts: boolean | ||||
|   embed: Embed | ||||
|   file: Attachment | ||||
|  | @ -109,14 +109,14 @@ interface MessageOption { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| interface ChannelMention { | ||||
| export interface ChannelMention { | ||||
|   id: string | ||||
|   guild_id: string | ||||
|   type: ChannelTypes | ||||
|   name: string | ||||
| } | ||||
| 
 | ||||
| interface Attachment { | ||||
| export interface Attachment { | ||||
|   id: string | ||||
|   filename: string | ||||
|   size: number | ||||
|  | @ -126,7 +126,7 @@ interface Attachment { | |||
|   width: number | undefined | ||||
| } | ||||
| 
 | ||||
| interface EmbedPayload { | ||||
| export interface EmbedPayload { | ||||
|   title?: string | ||||
|   type?: EmbedTypes | ||||
|   description?: string | ||||
|  | @ -142,64 +142,70 @@ interface EmbedPayload { | |||
|   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 | ||||
|   value: string | ||||
|   inline?: boolean | ||||
| } | ||||
| 
 | ||||
| interface EmbedAuthor { | ||||
| export interface EmbedAuthor { | ||||
|   name?: string | ||||
|   url?: string | ||||
|   icon_url?: string | ||||
|   proxy_icon_url?: string | ||||
| } | ||||
| 
 | ||||
| interface EmbedFooter { | ||||
| export interface EmbedFooter { | ||||
|   text: string | ||||
|   icon_url?: string | ||||
|   proxy_icon_url?: string | ||||
| } | ||||
| 
 | ||||
| interface EmbedImage { | ||||
| export interface EmbedImage { | ||||
|   url?: string | ||||
|   proxy_url?: string | ||||
|   height?: number | ||||
|   width?: number | ||||
| } | ||||
| 
 | ||||
| interface EmbedProvider { | ||||
| export interface EmbedProvider { | ||||
|   name?: string | ||||
|   url?: string | ||||
| } | ||||
| 
 | ||||
| interface EmbedVideo { | ||||
| export interface EmbedVideo { | ||||
|   url?: string | ||||
|   height?: number | ||||
|   width?: number | ||||
| } | ||||
| 
 | ||||
| interface EmbedThumbnail { | ||||
| export interface EmbedThumbnail { | ||||
|   url?: string | ||||
|   proxy_url?: string | ||||
|   height?: number | ||||
|   width?: number | ||||
| } | ||||
| 
 | ||||
| interface Reaction { | ||||
| export interface Reaction { | ||||
|   count: number | ||||
|   me: boolean | ||||
|   emoji: EmojiPayload | ||||
| } | ||||
| 
 | ||||
| interface MessageActivity { | ||||
| export interface MessageActivity { | ||||
|   type: MessageTypes | ||||
|   party_id?: string | ||||
| } | ||||
| 
 | ||||
| interface MessageApplication { | ||||
| export interface MessageApplication { | ||||
|   id: string | ||||
|   cover_image?: string | ||||
|   desription: string | ||||
|  | @ -207,13 +213,13 @@ interface MessageApplication { | |||
|   name: string | ||||
| } | ||||
| 
 | ||||
| interface MessageReference { | ||||
| export interface MessageReference { | ||||
|   message_id?: string | ||||
|   channel_id?: string | ||||
|   guild_id?: string | ||||
| } | ||||
| 
 | ||||
| enum MessageTypes { | ||||
| export enum MessageTypes { | ||||
|   DEFAULT = 0, | ||||
|   RECIPIENT_ADD = 1, | ||||
|   RECIPIENT_REMOVE = 2, | ||||
|  | @ -231,14 +237,14 @@ enum MessageTypes { | |||
|   GUILD_DISCOVERY_REQUALIFIED = 15 | ||||
| } | ||||
| 
 | ||||
| enum MessageActivityTypes { | ||||
| export enum MessageActivityTypes { | ||||
|   JOIN = 1, | ||||
|   SPECTATE = 2, | ||||
|   LISTEN = 3, | ||||
|   JOIN_REQUEST = 4 | ||||
| } | ||||
| 
 | ||||
| enum MessageFlags { | ||||
| export enum MessageFlags { | ||||
|   CROSSPOSTED = 1 << 0, | ||||
|   IS_CROSSPOST = 1 << 1, | ||||
|   SUPPRESS_EMBEDS = 1 << 2, | ||||
|  | @ -246,54 +252,7 @@ enum MessageFlags { | |||
|   URGENT = 1 << 4 | ||||
| } | ||||
| 
 | ||||
| interface FollowedChannel { | ||||
| export interface FollowedChannel { | ||||
|   channel_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. | ||||
|  * | ||||
|  */ | ||||
| interface GatewayResponse { | ||||
| export interface GatewayResponse { | ||||
|   op: GatewayOpcodes | ||||
|   d: any | ||||
|   s?: number | ||||
|   t?: GatewayEvents | ||||
| } | ||||
| 
 | ||||
| export { GatewayResponse } | ||||
|  |  | |||
|  | @ -62,11 +62,9 @@ enum 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', | ||||
|  | @ -89,7 +87,7 @@ enum GatewayEvents { | |||
|   Invite_Delete = 'INVITE_DELETE', | ||||
|   Message_Create = 'MESSAGE_CREATE', | ||||
|   Message_Update = 'MESSAGE_UPDATE', | ||||
|   Message_Delete = 'MESSAG_DELETE', | ||||
|   Message_Delete = 'MESSAGE_DELETE', | ||||
|   Message_Delete_Bulk = 'MESSAGE_DELETE_BULK', | ||||
|   Message_Reaction_Add = 'MESSAGE_REACTION_ADD', | ||||
|   Message_Reaction_Remove = 'MESSAGE_REACTION_REMOVE', | ||||
|  | @ -98,7 +96,6 @@ enum GatewayEvents { | |||
|   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' | ||||
| } | ||||
|  | @ -395,5 +392,5 @@ interface WebhooksUpdate { | |||
|   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 } | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import { RolePayload } from './roleTypes.ts' | |||
| import { UserPayload } from './userTypes.ts' | ||||
| import { VoiceStatePayload } from './voiceTypes.ts' | ||||
| 
 | ||||
| interface GuildPayload { | ||||
| export interface GuildPayload { | ||||
|   id: string | ||||
|   name: string | ||||
|   icon?: string | ||||
|  | @ -53,7 +53,7 @@ interface GuildPayload { | |||
|   approximate_presence_count?: number | ||||
| } | ||||
| 
 | ||||
| interface MemberPayload { | ||||
| export interface MemberPayload { | ||||
|   user: UserPayload | ||||
|   nick?: string | ||||
|   roles: string[] | ||||
|  | @ -99,7 +99,7 @@ enum SystemChannelFlags { | |||
|   SUPPRESS_PREMIUM_SUBSCRIPTIONS = 1 << 1 | ||||
| } | ||||
| 
 | ||||
| type GuildFeatures = | ||||
| export type GuildFeatures = | ||||
|   | 'INVITE_SPLASH' | ||||
|   | 'VIP_REGIONS' | ||||
|   | 'VANITY_URL' | ||||
|  | @ -112,5 +112,3 @@ type GuildFeatures = | |||
|   | 'FEATURABLE' | ||||
|   | 'ANIMATED_ICON' | ||||
|   | 'BANNER' | ||||
| 
 | ||||
| export { MemberPayload, GuildPayload, GuildFeatures } | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { UserPayload } from './userTypes.ts' | ||||
| 
 | ||||
| interface PresenceUpdatePayload { | ||||
| export interface PresenceUpdatePayload { | ||||
|   user: UserPayload | ||||
|   guild_id: string | ||||
|   status: string | ||||
|  | @ -14,7 +14,7 @@ interface ClientStatus { | |||
|   web?: string | ||||
| } | ||||
| 
 | ||||
| interface ActivityPayload { | ||||
| export interface ActivityPayload { | ||||
|   name: string | ||||
|   type: 0 | 1 | 2 | 3 | 4 | 5 | ||||
|   url?: string | undefined | ||||
|  | @ -68,5 +68,3 @@ enum ActivityFlags { | |||
|   SYNC = 1 << 4, | ||||
|   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 } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue