2019-05-30 09:01:25 +00:00
const { Client , Util } = require ( 'discord.js' ) ;
const Discord = require ( 'discord.js' ) ;
const YouTube = require ( 'simple-youtube-api' )
const ytdl = require ( 'ytdl-core' ) ;
const GOOGLE _API _KEY = ( process . env . API _KEY )
const PREFIX = ( '!' )
const client = new Client ( { disableEveryone : true } ) ;
const youtube = new YouTube ( GOOGLE _API _KEY ) ;
const queue = new Map ( ) ;
client . on ( 'warn' , console . warn ) ;
client . on ( 'error' , console . error ) ;
client . on ( 'disconnect' , ( ) => console . log ( '- Disconnected -' ) ) ;
client . on ( 'reconnecting' , ( ) => console . log ( '- Reconnecting -' ) ) ;
client . on ( 'ready' , ( ) => { //startup stuff
console . log ( '- Connected -' ) ;
client . user . setActivity ( '!help' , { type : 'LISTENING' } )
client . user . setStatus ( 'dnd' ) ;
} ) ;
client . on ( 'message' , msg => {
if ( msg . content === '!test' ) {
if ( msg . author . username === 'Matte' ) {
msg . channel . send ( 'Bot is currently online hosted!' )
}
}
if ( msg . content === ` ${ PREFIX } help ` ) {
const embed = new Discord . RichEmbed ( )
. setTitle ( 'Commands for Musix!' )
. addField ( '```!play```' , 'Play a song.' , true )
. addField ( '```!queue```' , 'Display the queue.' , true )
. addField ( '```!np```' , 'Display whats currently playing.' , true )
. addField ( '```!volume```' , 'Change or check the volume.' , true )
. addField ( '```!pause```' , 'Pause the music.' , true )
. addField ( '```!resume```' , 'Resume the music.' , true )
. addField ( '```!stop```' , 'Stop the music, Clear the queue and leave the current voice channel.' , true )
. addField ( '```!skip```' , 'Skip a song.' , true )
. addField ( '```!invitemusix```' , 'Invite Musix.' , true )
2019-05-30 11:08:30 +00:00
. addField ( '```!info```' , 'Display info and instructions.' , true )
. addField ( '```!help```' , 'Display the help.' , true )
2019-05-30 09:01:25 +00:00
. setAuthor ( 'Musix' , 'https://cdn.discordapp.com/avatars/572405135658188800/04c6f22b7600ddecfbc245dd3ec10f9f.png?size=2048' )
. setColor ( '#b50002' )
msg . channel . send ( embed ) ;
}
if ( msg . content === ` ${ PREFIX } info ` ) {
2019-05-30 13:58:34 +00:00
var dj = msg . guild . roles . find ( x => x . name === 'DJ' ) ? true : false ;
2019-05-30 09:01:25 +00:00
const embed = new Discord . RichEmbed ( )
2019-05-30 11:08:30 +00:00
. setTitle ( '**Musix instructions and info**:' )
2019-05-31 12:57:17 +00:00
. addField ( 'On any errors you should use the !stop command end the music and reset the queue.' , 'Remember to __try again__ before contacting support!' , true )
2019-05-30 13:50:56 +00:00
. addField ( 'If your guild has a role called \'DJ\' you will need it to play music! If you don\'t, Everyone can play music.' , 'DJ role existance: ' + dj , true )
2019-05-30 17:24:40 +00:00
. addField ( 'Musix support server' , 'https://discord.gg/rvHuJtB' , true )
. addField ( 'If you have any problems with musix please contact Matte#5254!' , '(creator and developer of Musix)' , true )
2019-05-30 09:01:25 +00:00
. setAuthor ( 'Musix' , 'https://cdn.discordapp.com/avatars/572405135658188800/04c6f22b7600ddecfbc245dd3ec10f9f.png?size=2048' )
. setColor ( '#b50002' )
msg . channel . send ( embed ) ;
}
if ( msg . content === ` ${ PREFIX } musixinvite ` ) {
msg . channel . send ( 'https://bit.ly/2V3D0p7' )
}
} ) ;
client . on ( 'message' , async msg => {
2019-05-30 11:04:07 +00:00
if ( msg . author . bot ) return undefined ;
if ( msg . content . startsWith ( ` ${ PREFIX } ` ) ) {
if ( msg . member . guild . roles . find ( x => x . name === 'DJ' ) ) {
if ( ! msg . member . roles . find ( x => x . name === 'DJ' ) ) {
2019-05-30 13:46:31 +00:00
msg . channel . send ( ':x: i\'m sorry you need to have the \'DJ\' role!' )
2019-05-30 09:01:25 +00:00
}
2019-05-30 11:04:07 +00:00
if ( msg . member . roles . find ( x => x . name === 'DJ' ) ) {
const args = msg . content . split ( ' ' ) ;
const searchString = args . slice ( 1 ) . join ( ' ' ) ;
const url = args [ 1 ] ? args [ 1 ] . replace ( /<(.+)>/g , '$1' ) : '' ;
const serverQueue = queue . get ( msg . guild . id ) ;
let command = msg . content . toLowerCase ( ) . split ( ' ' ) [ 0 ] ;
command = command . slice ( PREFIX . length )
if ( command === 'play' ) {
2019-05-30 13:55:40 +00:00
if ( ! args [ 1 ] ) return msg . channel . send ( ':x: I\'m sorry but you didn\'t specify the song' ) ;
2019-05-30 11:04:07 +00:00
const voiceChannel = msg . member . voiceChannel ;
if ( ! voiceChannel ) return msg . channel . send ( ':x: I\'m sorry but you need to be in a voice channel to play music!' ) ;
const permissions = voiceChannel . permissionsFor ( msg . client . user ) ;
if ( ! permissions . has ( 'CONNECT' ) ) {
return msg . channel . send ( ':x: I cannot connect to your voice channel, make sure I have the proper permissions!' ) ;
}
if ( ! permissions . has ( 'SPEAK' ) ) {
return msg . channel . send ( ':x: I cannot speak in this voice channel, make sure I have the proper permissions!' ) ;
2019-05-30 09:01:25 +00:00
}
2019-05-30 11:04:07 +00:00
if ( url . match ( /^https?:\/\/(www.youtube.com|youtube.com)\/playlist(.*)$/ ) ) {
const playlist = await youtube . getPlaylist ( url ) ;
const videos = await playlist . getVideos ( ) ;
for ( const video of Object . values ( videos ) ) {
const video2 = await youtube . getVideoByID ( video . id ) ; // eslint-disable-line no-await-in-loop
await handleVideo ( video2 , msg , voiceChannel , true ) ; // eslint-disable-line no-await-in-loop
}
return msg . channel . send ( ` :white_check_mark: Playlist: ** ${ playlist . title } ** has been added to the queue! ` ) ;
} else {
2019-05-30 09:01:25 +00:00
try {
2019-05-30 11:04:07 +00:00
var video = await youtube . getVideo ( url ) ;
} catch ( error ) {
2019-05-30 09:01:25 +00:00
try {
2019-05-30 11:04:07 +00:00
var videos = await youtube . searchVideos ( searchString , 10 ) ;
let index = 0 ;
msg . channel . send ( `
_ _ * * Song selection : * * _ _
2019-05-30 18:05:16 +00:00
$ { videos . map ( video2 => ` ** ${ ++ index } -** ${ video2 . title } ` ) . join ( '\n' ) }
2019-05-30 18:14:31 +00:00
Please provide a value to select one of the search results ranging from _ _1 - 10__ .
2019-05-30 11:04:07 +00:00
` );
// eslint-disable-next-line max-depth
try {
var response = await msg . channel . awaitMessages ( msg2 => msg2 . content > 0 && msg2 . content < 11 , {
maxMatches : 1 ,
time : 10000 ,
errors : [ 'time' ]
} ) ;
} catch ( err ) {
console . error ( err ) ;
return msg . channel . send ( ':x: No or invalid value entered, cancelling video selection.' ) ;
}
const videoIndex = parseInt ( response . first ( ) . content ) ;
var video = await youtube . getVideoByID ( videos [ videoIndex - 1 ] . id ) ;
2019-05-30 09:01:25 +00:00
} catch ( err ) {
console . error ( err ) ;
2019-05-30 11:04:07 +00:00
return msg . channel . send ( ':x: I could not obtain any search results.' ) ;
2019-05-30 09:01:25 +00:00
}
}
2019-05-30 11:04:07 +00:00
return handleVideo ( video , msg , voiceChannel ) ;
2019-05-30 09:01:25 +00:00
}
2019-05-30 11:04:07 +00:00
} else if ( command === 'skip' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing that I could skip for you.' ) ;
serverQueue . connection . dispatcher . end ( 'Skipped :thumbsup:' ) ;
return undefined ;
} else if ( command === 'stop' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing that I could stop for you.' ) ;
serverQueue . songs = [ ] ;
serverQueue . connection . dispatcher . end ( 'Stopped!' ) ;
return undefined ;
} else if ( command === 'volume' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
if ( ! args [ 1 ] ) return msg . channel . send ( ` The current volume is: ** ${ serverQueue . volume } ** :speaker: ` ) ;
serverQueue . volume = args [ 1 ] ;
serverQueue . connection . dispatcher . setVolumeLogarithmic ( args [ 1 ] / 5 ) ;
return msg . channel . send ( ` I set the volume to: ** ${ args [ 1 ] } ** 🔊 ` ) ;
} else if ( command === 'np' ) {
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
return msg . channel . send ( ` :musical_note: Now playing: ** ${ serverQueue . songs [ 0 ] . title } ** ` ) ;
} else if ( command === 'queue' ) {
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
return msg . channel . send ( `
_ _ * * Song queue : * * _ _
$ { serverQueue . songs . map ( song => ` **-** ${ song . title } ` ) . join ( '\n' ) }
* * Now playing : * * $ { serverQueue . songs [ 0 ] . title } : musical _note :
` );
} else if ( command === 'pause' ) {
if ( serverQueue && serverQueue . playing ) {
serverQueue . playing = false ;
serverQueue . connection . dispatcher . pause ( ) ;
return msg . channel . send ( ':pause_button: Paused the music for you!' ) ;
}
return msg . channel . send ( ':x: There is nothing playing.' ) ;
} else if ( command === 'resume' ) {
if ( serverQueue && ! serverQueue . playing ) {
serverQueue . playing = true ;
serverQueue . connection . dispatcher . resume ( ) ;
return msg . channel . send ( ':play_pause: Resumed the music for you!' ) ;
}
return msg . channel . send ( ':x: There is nothing playing.' ) ;
2019-05-30 09:01:25 +00:00
}
2019-05-30 11:04:07 +00:00
2019-05-30 09:01:25 +00:00
return undefined ;
2019-05-30 11:04:07 +00:00
}
}
else {
const args = msg . content . split ( ' ' ) ;
const searchString = args . slice ( 1 ) . join ( ' ' ) ;
const url = args [ 1 ] ? args [ 1 ] . replace ( /<(.+)>/g , '$1' ) : '' ;
const serverQueue = queue . get ( msg . guild . id ) ;
let command = msg . content . toLowerCase ( ) . split ( ' ' ) [ 0 ] ;
command = command . slice ( PREFIX . length )
if ( command === 'play' ) {
if ( ! args [ 1 ] ) return msg . channel . send ( ':x: I think you forgot what you wanted to play!' ) ;
const voiceChannel = msg . member . voiceChannel ;
if ( ! voiceChannel ) return msg . channel . send ( ':x: I\'m sorry but you need to be in a voice channel to play music!' ) ;
const permissions = voiceChannel . permissionsFor ( msg . client . user ) ;
if ( ! permissions . has ( 'CONNECT' ) ) {
return msg . channel . send ( ':x: I cannot connect to your voice channel, make sure I have the proper permissions!' ) ;
}
if ( ! permissions . has ( 'SPEAK' ) ) {
return msg . channel . send ( ':x: I cannot speak in this voice channel, make sure I have the proper permissions!' ) ;
}
if ( url . match ( /^https?:\/\/(www.youtube.com|youtube.com)\/playlist(.*)$/ ) ) {
const playlist = await youtube . getPlaylist ( url ) ;
const videos = await playlist . getVideos ( ) ;
for ( const video of Object . values ( videos ) ) {
const video2 = await youtube . getVideoByID ( video . id ) ; // eslint-disable-line no-await-in-loop
await handleVideo ( video2 , msg , voiceChannel , true ) ; // eslint-disable-line no-await-in-loop
}
return msg . channel . send ( ` :white_check_mark: Playlist: ** ${ playlist . title } ** has been added to the queue! ` ) ;
} else {
try {
var video = await youtube . getVideo ( url ) ;
} catch ( error ) {
try {
var videos = await youtube . searchVideos ( searchString , 10 ) ;
let index = 0 ;
msg . channel . send ( `
_ _ * * Song selection : * * _ _
$ { videos . map ( video2 => ` ** ${ ++ index } -** ${ video2 . title } ` ) . join ( '\n' ) }
Please provide a value to select one of the search results ranging from 1 - 10.
` );
// eslint-disable-next-line max-depth
try {
var response = await msg . channel . awaitMessages ( msg2 => msg2 . content > 0 && msg2 . content < 11 , {
maxMatches : 1 ,
time : 10000 ,
errors : [ 'time' ]
} ) ;
} catch ( err ) {
console . error ( err ) ;
return msg . channel . send ( ':x: No or invalid value entered, cancelling video selection.' ) ;
}
const videoIndex = parseInt ( response . first ( ) . content ) ;
var video = await youtube . getVideoByID ( videos [ videoIndex - 1 ] . id ) ;
} catch ( err ) {
console . error ( err ) ;
return msg . channel . send ( ':x: I could not obtain any search results.' ) ;
}
}
return handleVideo ( video , msg , voiceChannel ) ;
}
} else if ( command === 'skip' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing that I could skip for you.' ) ;
msg . channel . send ( 'Skipped :thumbsup:' )
serverQueue . connection . dispatcher . end ( 'Skipped' ) ;
return undefined ;
} else if ( command === 'stop' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing that I could stop for you.' ) ;
msg . channel . send ( 'Stopped the music! :stop_button:' )
serverQueue . songs = [ ] ;
serverQueue . connection . dispatcher . end ( 'Stopped!' ) ;
return undefined ;
} else if ( command === 'volume' ) {
if ( ! msg . member . voiceChannel ) return msg . channel . send ( ':x: You are not in a voice channel!' ) ;
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
if ( ! args [ 1 ] ) return msg . channel . send ( ` The current volume is: ** ${ serverQueue . volume } ** :speaker: ` ) ;
serverQueue . volume = args [ 1 ] ;
serverQueue . connection . dispatcher . setVolumeLogarithmic ( args [ 1 ] / 5 ) ;
return msg . channel . send ( ` I set the volume to: ** ${ args [ 1 ] } ** 🔊 ` ) ;
} else if ( command === 'np' ) {
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
return msg . channel . send ( ` :musical_note: Now playing: ** ${ serverQueue . songs [ 0 ] . title } ** ` ) ;
} else if ( command === 'queue' ) {
if ( ! serverQueue ) return msg . channel . send ( ':x: There is nothing playing.' ) ;
return msg . channel . send ( `
_ _ * * Song queue : * * _ _
$ { serverQueue . songs . map ( song => ` **-** ${ song . title } ` ) . join ( '\n' ) }
* * Now playing : * * $ { serverQueue . songs [ 0 ] . title } : musical _note :
` );
} else if ( command === 'pause' ) {
if ( serverQueue && serverQueue . playing ) {
serverQueue . playing = false ;
serverQueue . connection . dispatcher . pause ( ) ;
return msg . channel . send ( ':pause_button: Paused the music for you!' ) ;
}
return msg . channel . send ( ':x: There is nothing playing.' ) ;
} else if ( command === 'resume' ) {
if ( serverQueue && ! serverQueue . playing ) {
serverQueue . playing = true ;
serverQueue . connection . dispatcher . resume ( ) ;
return msg . channel . send ( ':play_pause: Resumed the music for you!' ) ;
}
return msg . channel . send ( ':x: There is nothing playing.' ) ;
2019-05-30 09:01:25 +00:00
}
2019-05-30 11:04:07 +00:00
return undefined ;
}
2019-05-30 09:01:25 +00:00
}
} ) ;
async function handleVideo ( video , msg , voiceChannel , playlist = false ) {
const serverQueue = queue . get ( msg . guild . id ) ;
console . log ( video ) ;
const song = {
id : video . id ,
title : Util . escapeMarkdown ( video . title ) ,
url : ` https://www.youtube.com/watch?v= ${ video . id } `
} ;
if ( ! serverQueue ) {
const queueConstruct = {
textChannel : msg . channel ,
voiceChannel : voiceChannel ,
connection : null ,
songs : [ ] ,
volume : 5 ,
playing : true
} ;
queue . set ( msg . guild . id , queueConstruct ) ;
queueConstruct . songs . push ( song ) ;
try {
var connection = await voiceChannel . join ( ) ;
queueConstruct . connection = connection ;
play ( msg . guild , queueConstruct . songs [ 0 ] ) ;
} catch ( error ) {
console . error ( ` :x: I could not join the voice channel: ${ error } ` ) ;
queue . delete ( msg . guild . id ) ;
return msg . channel . send ( ` :x: I could not join the voice channel: ${ error } ` ) ;
}
} else {
serverQueue . songs . push ( song ) ;
console . log ( serverQueue . songs ) ;
if ( playlist ) return undefined ;
else return msg . channel . send ( ` :white_check_mark: ** ${ song . title } ** has been added to the queue! ` ) ;
}
return undefined ;
}
function play ( guild , song ) {
const serverQueue = queue . get ( guild . id ) ;
if ( ! song ) {
serverQueue . voiceChannel . leave ( ) ;
queue . delete ( guild . id ) ;
return ;
}
console . log ( serverQueue . songs ) ;
const dispatcher = serverQueue . connection . playStream ( ytdl ( song . url , { quality : ` highestaudio ` , filter : 'audioonly' } ) )
. on ( 'end' , reason => {
if ( reason === 'Stream is not generating quickly enough.' ) console . log ( 'Song ended.' ) ;
else console . log ( reason ) ;
serverQueue . songs . shift ( ) ;
play ( guild , serverQueue . songs [ 0 ] ) ;
} )
. on ( 'error' , error => console . error ( error ) ) ;
dispatcher . setVolumeLogarithmic ( serverQueue . volume / 5 ) ;
serverQueue . textChannel . send ( ` :musical_note: Start playing: ** ${ song . title } ** ` ) ;
}
client . login ( process . env . BOT _TOKEN ) ;