2019-10-24 18:54:23 +00:00
const logger = require ( "./logger.js" ) ;
2020-06-27 17:18:26 +00:00
const fetch = require ( "node-fetch" ) ;
2021-03-05 21:13:54 +00:00
const fs = require ( "fs" ) ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
const day = require ( "dayjs" ) ;
const duration = require ( "dayjs/plugin/duration" ) ;
day . extend ( duration ) ;
2021-03-05 18:06:22 +00:00
const { Manager } = require ( "lavacord" ) ;
2019-09-13 20:02:41 +00:00
2021-03-05 21:13:54 +00:00
let nodes ;
2020-06-27 17:18:26 +00:00
2020-07-06 20:19:30 +00:00
exports . players = new Map ( ) ;
2020-09-02 02:52:12 +00:00
exports . queues = new Map ( ) ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
exports . skipVotes = new Map ( ) ;
2020-07-06 20:19:30 +00:00
exports . manager ;
2020-06-27 21:34:31 +00:00
exports . status = false ;
2020-07-16 14:28:09 +00:00
exports . connected = false ;
2020-06-27 21:34:31 +00:00
exports . checkStatus = async ( ) => {
2021-03-05 21:13:54 +00:00
const json = await fs . promises . readFile ( "./servers.json" , { encoding : "utf8" } ) ;
nodes = JSON . parse ( json ) . lava ;
2020-12-11 22:46:05 +00:00
const newNodes = [ ] ;
2020-06-27 21:34:31 +00:00
for ( const node of nodes ) {
try {
const response = await fetch ( ` http:// ${ node . host } : ${ node . port } /version ` , { headers : { Authorization : node . password } } ) . then ( res => res . text ( ) ) ;
2020-12-11 22:46:05 +00:00
if ( response ) newNodes . push ( node ) ;
2020-06-27 21:34:31 +00:00
} catch {
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
logger . error ( ` Failed to get status of Lavalink node ${ node . host } . ` ) ;
2020-06-27 21:34:31 +00:00
}
}
2020-12-11 22:46:05 +00:00
nodes = newNodes ;
this . status = newNodes . length === 0 ? true : false ;
2020-06-27 21:34:31 +00:00
return this . status ;
} ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
exports . connect = async ( client ) => {
2021-03-05 18:06:22 +00:00
this . manager = new Manager ( nodes , {
user : client . user . id ,
shards : client . shards . size || 1 ,
send : ( packet ) => {
const guild = client . guilds . get ( packet . d . guild _id ) ;
if ( ! guild ) return ;
return guild . shard . sendWS ( packet . op , packet . d ) ;
}
2020-06-27 17:18:26 +00:00
} ) ;
2020-07-06 20:19:30 +00:00
const { length } = await this . manager . connect ( ) ;
2020-06-27 17:18:26 +00:00
logger . log ( ` Successfully connected to ${ length } Lavalink node(s). ` ) ;
2020-07-16 14:28:09 +00:00
exports . connected = true ;
2020-07-06 20:19:30 +00:00
this . manager . on ( "error" , ( error , node ) => {
2020-06-27 17:18:26 +00:00
logger . error ( ` An error occurred on Lavalink node ${ node } : ${ error } ` ) ;
} ) ;
2021-01-08 18:08:10 +00:00
return length ;
2020-06-27 17:18:26 +00:00
} ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
exports . play = async ( client , sound , message , music = false ) => {
2021-05-11 16:12:01 +00:00
if ( ! this . manager ) return "The sound commands are still starting up!" ;
if ( ! message . channel . guild ) return "This command only works in servers!" ;
if ( ! message . member . voiceState . channelID ) return "You need to be in a voice channel first!" ;
if ( ! message . channel . permissionsOf ( client . user . id ) . has ( "voiceConnect" ) ) return "I can't join this voice channel!" ;
2020-07-06 20:19:30 +00:00
const voiceChannel = message . channel . guild . channels . get ( message . member . voiceState . channelID ) ;
2021-05-11 16:12:01 +00:00
if ( ! voiceChannel . permissionsOf ( client . user . id ) . has ( "voiceConnect" ) ) return "I don't have permission to join this voice channel!" ;
2020-11-05 21:40:18 +00:00
const player = this . players . get ( message . channel . guild . id ) ;
2021-05-11 16:12:01 +00:00
if ( ! music && this . manager . voiceStates . has ( message . channel . guild . id ) && ( player && player . type === "music" ) ) return "I can't play a sound effect while playing music!" ;
2020-07-06 20:19:30 +00:00
const node = this . manager . idealNodes [ 0 ] ;
2021-01-04 16:29:18 +00:00
if ( ! music && ! nodes . filter ( obj => obj . host === node . host ) [ 0 ] . local ) {
sound = sound . replace ( /\.\// , "https://raw.githubusercontent.com/esmBot/esmBot/master/" ) ;
}
2020-07-06 20:19:30 +00:00
const { tracks } = await fetch ( ` http:// ${ node . host } : ${ node . port } /loadtracks?identifier= ${ sound } ` , { headers : { Authorization : node . password } } ) . then ( res => res . json ( ) ) ;
2020-09-02 02:52:12 +00:00
const oldQueue = this . queues . get ( voiceChannel . guild . id ) ;
2021-05-11 16:12:01 +00:00
if ( ! tracks || tracks . length === 0 ) return "I couldn't find that song!" ;
2020-09-22 20:33:07 +00:00
if ( music ) {
2020-12-14 16:58:31 +00:00
this . queues . set ( voiceChannel . guild . id , oldQueue ? [ ... oldQueue , tracks [ 0 ] . track ] : [ tracks [ 0 ] . track ] ) ;
2020-09-22 20:33:07 +00:00
}
2020-11-05 21:40:18 +00:00
let connection ;
if ( player ) {
2020-12-11 19:52:02 +00:00
connection = player . player ;
2020-11-05 21:40:18 +00:00
} else {
connection = await this . manager . join ( {
guild : voiceChannel . guild . id ,
channel : voiceChannel . id ,
node : node . id
} ) ;
}
2020-07-06 20:19:30 +00:00
2020-09-22 20:33:07 +00:00
if ( oldQueue && music ) {
2021-05-11 16:12:01 +00:00
return ` Your tune \` ${ tracks [ 0 ] . info . title } \` has been added to the queue! ` ;
2019-09-13 20:02:41 +00:00
} else {
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
this . nextSong ( client , message , connection , tracks [ 0 ] . track , tracks [ 0 ] . info , music , voiceChannel , player ? player . loop : false ) ;
2020-12-11 19:52:02 +00:00
return ;
2019-09-13 20:02:41 +00:00
}
} ;
2020-07-06 20:19:30 +00:00
2021-07-06 13:25:12 +00:00
exports . nextSong = async ( client , message , connection , track , info , music , voiceChannel , loop = false , inQueue = false , lastTrack = null ) => {
2020-07-06 20:19:30 +00:00
const parts = Math . floor ( ( 0 / info . length ) * 10 ) ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
let playingMessage ;
2021-07-06 13:25:12 +00:00
if ( ! music && this . players . get ( voiceChannel . guild . id ) ) {
const playMessage = this . players . get ( voiceChannel . guild . id ) . playMessage ;
if ( playMessage . channel . messages . get ( playMessage . id ) ) playMessage . delete ( ) ;
}
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
if ( lastTrack === track ) {
2021-07-06 13:25:12 +00:00
playingMessage = this . players . get ( voiceChannel . guild . id ) . playMessage ;
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
} else {
playingMessage = await client . createMessage ( message . channel . id , ! music ? "🔊 Playing sound..." : {
"embed" : {
"color" : 16711680 ,
"author" : {
"name" : "Now Playing" ,
"icon_url" : client . user . avatarURL
} ,
"fields" : [ {
"name" : "ℹ ️ Title:" ,
"value" : info . title
} ,
{
"name" : "🎤 Artist:" ,
"value" : info . author
} ,
{
"name" : "💬 Channel:" ,
"value" : voiceChannel . name
} ,
{
"name" : ` ${ "▬" . repeat ( parts ) } 🔘 ${ "▬" . repeat ( 10 - parts ) } ` ,
"value" : ` ${ day . duration ( 0 ) . format ( "m:ss" , { trim : false } )}/ ${ info . isStream ? "∞" : day . duration ( info . length ) . format ( "m:ss" , { trim : false } )} `
} ]
}
} ) ;
}
2020-07-06 20:19:30 +00:00
await connection . play ( track ) ;
2021-07-06 13:25:12 +00:00
this . players . set ( voiceChannel . guild . id , { player : connection , type : music ? "music" : "sound" , host : message . author . id , voiceChannel : voiceChannel , originalChannel : message . channel , loop : loop , playMessage : playingMessage } ) ;
2020-11-05 21:40:18 +00:00
if ( inQueue && connection . listeners ( "error" ) . length === 0 ) {
2020-08-16 16:48:37 +00:00
connection . on ( "error" , ( error ) => {
2020-09-23 19:12:39 +00:00
if ( playingMessage . channel . messages . get ( playingMessage . id ) ) playingMessage . delete ( ) ;
2021-07-06 13:25:12 +00:00
const playMessage = this . players . get ( voiceChannel . guild . id ) . playMessage ;
if ( playMessage . channel . messages . get ( playMessage . id ) ) playMessage . delete ( ) ;
2020-08-16 16:48:37 +00:00
this . manager . leave ( voiceChannel . guild . id ) ;
connection . destroy ( ) ;
this . players . delete ( voiceChannel . guild . id ) ;
2020-09-02 02:52:12 +00:00
this . queues . delete ( voiceChannel . guild . id ) ;
2020-08-16 16:48:37 +00:00
logger . error ( error ) ;
} ) ;
}
2020-11-05 21:40:18 +00:00
if ( connection . listeners ( "end" ) . length === 0 ) {
connection . on ( "end" , async ( data ) => {
if ( data . reason === "REPLACED" ) return ;
const queue = this . queues . get ( voiceChannel . guild . id ) ;
2021-07-06 14:23:27 +00:00
const player = this . players . get ( voiceChannel . guild . id ) ;
2020-12-11 19:52:02 +00:00
let newQueue ;
2021-07-06 13:25:12 +00:00
if ( player . loop ) {
2020-12-11 19:52:02 +00:00
queue . push ( queue . shift ( ) ) ;
newQueue = queue ;
} else {
newQueue = queue ? queue . slice ( 1 ) : [ ] ;
}
2020-11-05 21:40:18 +00:00
this . queues . set ( voiceChannel . guild . id , newQueue ) ;
if ( newQueue . length === 0 ) {
this . manager . leave ( voiceChannel . guild . id ) ;
connection . destroy ( ) ;
this . players . delete ( voiceChannel . guild . id ) ;
this . queues . delete ( voiceChannel . guild . id ) ;
if ( music ) await client . createMessage ( message . channel . id , "🔊 The current voice channel session has ended." ) ;
2021-07-06 14:23:27 +00:00
try {
if ( playingMessage . channel . messages . get ( playingMessage . id ) ) await playingMessage . delete ( ) ;
if ( player . playMessage . channel . messages . get ( player . playMessage . id ) ) await player . playMessage . delete ( ) ;
} catch {
// no-op
}
2020-11-05 21:40:18 +00:00
} else {
Class commands, improved sharding, and many other changes (#88)
* Load commands recursively
* Sort commands
* Missed a couple of spots
* missed even more spots apparently
* Ported commands in "fun" category to new class-based format, added babel eslint plugin
* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of
* Missed a spot
* Removed unnecessary abort-controller package, add deprecation warning for mongo database
* Added imagereload, clarified premature end message
* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts
* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner
* Converted music/soundboard commands to class format
* Cleanup unnecessary logs
* awful tag command class port
* I literally somehow just learned that you can leave out the constructor in classes
* Pass client directly to commands/events, cleaned up command handler
* Migrated bot to eris-sharder, fixed some error handling stuff
* Remove unused modules
* Fixed type returning
* Switched back to Eris stable
* Some fixes and cleanup
* might wanna correct this
* Implement image command ratelimiting
* Added Bot token prefix, added imagestats, added running endpoint to API
2021-04-12 16:16:12 +00:00
const newTrack = await fetch ( ` http:// ${ connection . node . host } : ${ connection . node . port } /decodetrack?track= ${ encodeURIComponent ( newQueue [ 0 ] ) } ` , { headers : { Authorization : connection . node . password } } ) . then ( res => res . json ( ) ) ;
2021-07-06 13:25:12 +00:00
this . nextSong ( client , message , connection , newQueue [ 0 ] , newTrack , music , voiceChannel , player . loop , true , track ) ;
2021-07-06 14:23:27 +00:00
try {
if ( newQueue [ 0 ] !== track && playingMessage . channel . messages . get ( playingMessage . id ) ) await playingMessage . delete ( ) ;
if ( newQueue [ 0 ] !== track && player . playMessage . channel . messages . get ( player . playMessage . id ) ) await player . playMessage . delete ( ) ;
} catch {
// no-op
}
2020-11-05 21:40:18 +00:00
}
} ) ;
}
2020-07-06 20:19:30 +00:00
} ;