2023-06-24 13:47:42 -04:00
import Discord from 'discord.js' ;
import TClient from '../client.js' ;
import { Player , useTimeline , useQueue } from 'discord-player' ;
import { SpotifyExtractor } from '@discord-player/extractor' ;
export default {
async run ( client : TClient , interaction : Discord.ChatInputCommandInteraction < 'cached' > ) {
2023-06-26 00:13:31 -04:00
if ( ! client . config . botSwitches . music && ! client . config . whitelist . includes ( interaction . user . id ) ) return interaction . reply ( { content : 'Music module is currently disabled.' , ephemeral :true } ) ;
2023-08-12 12:40:18 -04:00
if ( ! client . isStaff ( interaction . member ) && ! client . config . whitelist . includes ( interaction . member . id ) ) return interaction . reply ( 'Music module is close to being completed, some parts may be incomplete or broken, so it has been restricted to staff for time-being.' ) ;
2023-06-24 13:47:42 -04:00
const player = Player . singleton ( client ) ;
2023-08-30 02:42:06 -04:00
await player . extractors . register ( SpotifyExtractor , { clientId : client.tokens.spotify.client , clientSecret : client.tokens.spotify.secret } ) ;
2023-07-07 09:49:24 -04:00
if ( ! interaction . member . voice . channel ) return interaction . reply ( 'Please join a voice channel first to use the command.' ) ;
2023-06-24 13:47:42 -04:00
player . nodes . create ( interaction . guildId , {
metadata : {
channel : interaction.channel ,
client : interaction.guild.members.me ,
requestedBy : interaction.member
} ,
selfDeaf : true ,
volume : 75 ,
skipOnNoStream : true ,
leaveOnEnd : false ,
leaveOnEmpty : false ,
bufferingTimeout : 30000 ,
connectionTimeout : 25000 ,
strategy : 'FIFO'
} ) ;
2023-08-12 12:40:18 -04:00
const queue = useQueue ( interaction . guildId ) ;
2023-06-24 13:47:42 -04:00
( {
play : async ( ) = > {
const url = interaction . options . getString ( 'url' ) ;
2023-07-19 05:13:59 -04:00
if ( ! url . includes ( 'https://open.spotify.com/' ) ) return interaction . reply ( 'Sorry, I can\'t play that. I can only accept Spotify links that contains `https://open.spotify.com/`' ) ; // Yes, I made it clear that it's intended typo.
if ( ! ( await player . search ( url , { requestedBy :interaction.user } ) ) . hasTracks ( ) ) return interaction . reply ( ` No results found for \` ${ url } \` \ nIt is either private, unavailable or you made a *tpyo* in your query. ` )
2023-06-24 13:47:42 -04:00
player . play ( interaction . member . voice . channel , url ) ;
2023-08-12 12:40:18 -04:00
await interaction . reply ( ` Added the ${ url . includes ( 'playlist/' ) ? 'playlist' : url . includes ( 'album/' ) ? 'album' : 'song' } to the queue. ` ) ;
2023-06-24 13:47:42 -04:00
} ,
stop : async ( ) = > {
player . destroy ( ) ;
await interaction . reply ( 'Player destroyed.' )
} ,
2023-06-26 00:13:31 -04:00
pause : ( ) = > {
queue . node . setPaused ( ! queue . node . isPaused ( ) ) ;
2023-08-12 12:40:18 -04:00
if ( queue . node . isPaused ( ) ) interaction . reply ( 'Music has been paused.' ) ;
else interaction . reply ( 'Music has been resumed.' )
2023-06-26 00:13:31 -04:00
} ,
2023-06-24 13:47:42 -04:00
now_playing : ( ) = > {
const { volume , timestamp , track } = useTimeline ( interaction . guildId ) ;
2023-08-12 12:40:18 -04:00
if ( ! track ) return interaction . reply ( 'There\'s nothing playing, why are you checking?' ) ;
else {
function convertNumberToText ( input :number ) {
switch ( input ) {
case 0 : return 'Off' ;
case 1 : return 'Track' ;
case 2 : return 'Queue' ;
case 3 : return 'Autoplay DJ' ;
}
}
interaction . reply ( { embeds : [
new client . embed ( ) . setColor ( client . config . embedColor ) . setTitle ( ` ${ track . title } - ${ track . author } ` ) . setThumbnail ( track . thumbnail ) . addFields (
{ name : 'Timestamp' , value : ` ** ${ timestamp . current . label } **/** ${ timestamp . total . label } ** ` , inline : true } ,
{ name : 'Volume' , value : ` ${ volume } % ` , inline : true } ,
{ name : 'Loop mode' , value : ` ${ convertNumberToText ( queue . repeatMode ) } ` , inline : true }
)
] } )
}
2023-06-26 00:13:31 -04:00
} ,
2023-08-12 12:40:18 -04:00
queue : async ( ) = > interaction . reply ( { embeds : [ new client . embed ( ) . setColor ( client . config . embedColor ) . setTitle ( ` Songs currently in the queue: ${ queue . tracks . size } ` ) . setDescription ( queue . tracks . size > 0 ? ` \` \` \` ${ queue . tracks . map ( i = > ` ${ i . title } - ${ i . author } \` \` \` ` ) . join ( '```\n' ) } ` . slice ( 0 , 1017 ) : '*No songs currently queued.*' ) ] } ) ,
2023-06-24 13:47:42 -04:00
volume : ( ) = > {
const vol = interaction . options . getNumber ( 'percentage' ) ;
2023-08-12 12:40:18 -04:00
queue . node . setVolume ( vol ) ;
2023-06-24 13:47:42 -04:00
interaction . reply ( ` Successfully adjusted the player's volume to ${ vol } % ` )
2023-06-26 00:13:31 -04:00
} ,
shuffle : ( ) = > {
2023-08-12 12:40:18 -04:00
queue . tracks . shuffle ( ) ;
2023-06-26 00:13:31 -04:00
interaction . reply ( 'Songs in the queue has been shuffled.' )
} ,
remove : ( ) = > {
2023-08-12 12:40:18 -04:00
queue . removeTrack ( interaction . options . getNumber ( 'id' , true ) ) ;
2023-06-26 00:13:31 -04:00
interaction . reply ( 'Song has been removed from the queue.' )
2023-07-19 04:25:42 -04:00
} ,
skip : ( ) = > {
2023-08-12 12:40:18 -04:00
queue . node . skip ( ) ;
2023-07-19 04:25:42 -04:00
interaction . reply ( 'Skipped the current song, now playing the next one in queue.' )
2023-08-12 12:40:18 -04:00
} ,
loop : ( ) = > {
const loopMode = interaction . options . getNumber ( 'mode' , true ) ;
queue . setRepeatMode ( loopMode ) ;
interaction . reply ( ` Loop mode is now ${ loopMode === 0 ? 'disabled.' : loopMode === 1 ? 'set to loop current track.' : loopMode === 2 ? 'looping through current queue.' : 'activating Autoplay DJ.' } ` )
2023-06-24 13:47:42 -04:00
}
} as any ) [ interaction . options . getSubcommand ( ) ] ( ) ;
} ,
data : new Discord . SlashCommandBuilder ( )
. setName ( 'music' )
. setDescription ( 'Music module' )
. addSubcommand ( x = > x
. setName ( 'play' )
. setDescription ( 'Play a Spotify song' )
. addStringOption ( x = > x
. setName ( 'url' )
. setDescription ( 'Spotify URL' )
. setRequired ( true ) ) )
. addSubcommand ( x = > x
. setName ( 'stop' )
. setDescription ( 'Stop playing music and disconnect the bot from voice channel' ) )
2023-07-19 04:25:42 -04:00
. addSubcommand ( x = > x
. setName ( 'skip' )
. setDescription ( 'Skip the current song and play the next one' ) )
2023-06-26 00:13:31 -04:00
. addSubcommand ( x = > x
. setName ( 'pause' )
. setDescription ( 'Pause/unpause the music' ) )
2023-06-24 13:47:42 -04:00
. addSubcommand ( x = > x
. setName ( 'now_playing' )
. setDescription ( 'Check what song is currently playing' ) )
2023-06-26 00:13:31 -04:00
. addSubcommand ( x = > x
. setName ( 'queue' )
. setDescription ( 'View the list of songs currently in queue' ) )
2023-06-24 13:47:42 -04:00
. addSubcommand ( x = > x
. setName ( 'volume' )
. setDescription ( 'Adjust the player\'s volume' )
. addNumberOption ( x = > x
. setName ( 'percentage' )
2023-06-26 00:13:31 -04:00
. setDescription ( 'Adjust the volume level, ranges from 5 to 100, default is 75' )
2023-06-24 13:47:42 -04:00
. setMaxValue ( 100 )
. setMinValue ( 5 )
. setRequired ( true ) ) )
2023-06-26 00:13:31 -04:00
. addSubcommand ( x = > x
. setName ( 'shuffle' )
. setDescription ( 'Shuffle the songs in a queue' ) )
2023-08-12 12:40:18 -04:00
. addSubcommand ( x = > x
. setName ( 'loop' )
. setDescription ( 'Loop through queue or current track or enable Autoplay DJ' )
. addNumberOption ( x = > x
. setName ( 'mode' )
. setDescription ( 'Select the available modes to use' )
. addChoices (
{ name : 'Off' , value : 0 } ,
{ name : 'Current track' , value : 1 } ,
{ name : 'Queue' , value : 2 } ,
{ name : 'Autoplay DJ (Play related songs based on queue)' , value : 3 }
)
. setRequired ( true ) ) )
2023-06-26 00:13:31 -04:00
. addSubcommand ( x = > x
. setName ( 'remove' )
. setDescription ( 'Remove a specific song from the queue' )
. addNumberOption ( x = > x
. setName ( 'id' )
. setDescription ( 'Song # in the queue to be removed' )
. setMinValue ( 0 )
. setMaxValue ( 9999 )
. setRequired ( true ) ) )
2023-06-24 13:47:42 -04:00
}