2022-12-07 00:10:31 +00:00
const { SnowTransfer } = require ( "snowtransfer" )
const { Client : CloudStorm } = require ( "cloudstorm" )
let wasReadyBefore = false
class DiscordClient {
/ * *
* @ param { string } discordToken
* /
constructor ( discordToken ) {
this . discordToken = discordToken
this . snow = new SnowTransfer ( discordToken )
this . cloud = new CloudStorm ( discordToken , {
shards : "auto" ,
reconnect : true ,
snowtransferInstance : this . snow ,
intents : [
"DIRECT_MESSAGES" , "DIRECT_MESSAGE_REACTIONS" , "DIRECT_MESSAGE_TYPING" ,
"GUILDS" , "GUILD_EMOJIS_AND_STICKERS" , "GUILD_MESSAGES" , "GUILD_MESSAGE_REACTIONS" , "GUILD_MESSAGE_TYPING" , "GUILD_WEBHOOKS" ,
"MESSAGE_CONTENT"
] ,
ws : {
compress : false ,
encoding : "json"
}
} )
2022-12-07 20:34:05 +00:00
/** @type {import("discord-typings").User} */
// @ts-ignore avoid setting as or null because we know we need to wait for ready anyways
2022-12-07 00:10:31 +00:00
this . user = null
2022-12-07 20:34:05 +00:00
/** @type {import("discord-typings").Application} */
// @ts-ignore
2022-12-07 00:10:31 +00:00
this . application = null
/** @type {Map<string, import("discord-typings").Channel>} */
this . channels = new Map ( )
2022-12-07 20:34:05 +00:00
/** @type {Map<string, import("discord-typings").Guild>} */
this . guilds = new Map ( )
/ * *
* @ type { Map < string , Array < string >> }
* @ private
* /
this . guildChannelMap = new Map ( )
2022-12-07 00:10:31 +00:00
this . cloud . on ( "event" , this . onPacket . bind ( this ) )
}
/ * *
* @ param { import ( "cloudstorm" ) . IGatewayMessage } message
* @ private
* /
onPacket ( message ) {
if ( message . t === "READY" ) {
if ( wasReadyBefore ) return
2022-12-07 20:34:05 +00:00
wasReadyBefore = true
2022-12-07 00:10:31 +00:00
/** @type {import("discord-typings").ReadyPayload} */
const typed = message . d
this . user = typed . user
this . application = typed . application
console . log ( ` Discord logged in as ${ this . user . username } # ${ this . user . discriminator } ( ${ this . user . id } ) ` )
2022-12-07 20:34:05 +00:00
2022-12-07 00:10:31 +00:00
} else if ( message . t === "GUILD_CREATE" ) {
/** @type {import("discord-typings").Guild} */
const typed = message . d
2022-12-07 20:34:05 +00:00
this . guilds . set ( typed . id , typed )
const arr = [ ]
this . guildChannelMap . set ( typed . id , arr )
2022-12-07 00:10:31 +00:00
for ( const channel of typed . channels || [ ] ) {
2022-12-07 20:34:05 +00:00
arr . push ( channel . id )
2022-12-07 00:10:31 +00:00
this . channels . set ( channel . id , channel )
}
2022-12-07 20:34:05 +00:00
} else if ( message . t === "GUILD_DELETE" ) {
/** @type {import("discord-typings").Guild} */
const typed = message . d
this . guilds . delete ( typed . id )
const channels = this . guildChannelMap . get ( typed . id )
if ( channels ) {
for ( const id of channels ) this . channels . delete ( id )
}
this . guildChannelMap . delete ( typed . id )
2022-12-07 00:10:31 +00:00
} else if ( message . t === "CHANNEL_CREATE" || message . t === "CHANNEL_DELETE" ) {
/** @type {import("discord-typings").Channel} */
const typed = message . d
2022-12-07 20:34:05 +00:00
if ( message . t === "CHANNEL_CREATE" ) {
this . channels . set ( typed . id , typed )
if ( typed [ "guild_id" ] ) { // obj[prop] notation can be used to access a property without typescript complaining that it doesn't exist on all values something can have
const channels = this . guildChannelMap . get ( typed [ "guild_id" ] )
if ( channels && ! channels . includes ( typed . id ) ) channels . push ( typed . id )
}
} else {
this . channels . delete ( typed . id )
if ( typed [ "guild_id" ] ) {
const channels = this . guildChannelMap . get ( typed [ "guild_id" ] )
if ( channels ) {
const previous = channels . indexOf ( typed . id )
if ( previous !== - 1 ) channels . splice ( previous , 1 )
}
}
}
2022-12-07 00:10:31 +00:00
}
}
}
module . exports = DiscordClient