gaber-elsayed

Music Code

Feb 1st, 2020
512
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.22 KB | None | 0 0
  1. const Discord = require('discord.js');
  2. const botSettings = require("./config.json");
  3. const axios = require("axios");
  4. const yt = require("ytdl-core");
  5. const YouTube = require("simple-youtube-api");
  6. const fs = require("fs");
  7. const getYTID = require("get-youtube-id");
  8. const fetchVideoInfo = require("youtube-info");
  9. const prefix = botSettings.prefix;
  10. const ytApiKey = botSettings.ytApiKey;
  11. const youtube = new YouTube(ytApiKey);
  12.  
  13. const bot = new Discord.Client({
  14. disableEveryone: true
  15. });
  16.  
  17. let commandsList = fs.readFileSync('commands.md', 'utf8');
  18.  
  19. /* MUSIC VARIABLES */
  20. let queue = []; // Songs queue
  21. let songsQueue = []; // Song names stored for queue command
  22. let isPlaying = false; // Is music playing
  23. let dispatcher = null;
  24. let voiceChannel = null;
  25. let skipRequest = 0; // Stores the number of skip requests
  26. let skippers = []; // Usernames of people who voted to skip the song
  27. let ytResultList = []; // Video names results from yt command
  28. let ytResultAdd = []; // For storing !add command choice
  29. /* MUSIC VARIABLES END */
  30. let re = /^(?:[1-5]|0[1-5]|10)$/; // RegEx for allowing only 1-5 while selecting song from yt results
  31. let regVol = /^(?:([1][0-9][0-9])|200|([1-9][0-9])|([0-9]))$/; // RegEx for volume control
  32. let youtubeSearched = false; // If youtube has been searched (for !add command)
  33. let selectUser; // Selecting user from guild
  34.  
  35. bot.on("ready", async () => {
  36. console.log(`Bot is ready! ${bot.user.username}`);
  37.  
  38. /*try {
  39. let link = await bot.generateInvite(["ADMINISTRATOR"]);
  40. console.log(link);
  41. } catch (e) {
  42. console.log(e.stack);
  43. }*/
  44.  
  45. });
  46.  
  47. bot.on("message", async message => {
  48. if (message.author.bot) return;
  49. if (message.channel.type === "dm") return;
  50.  
  51. let messageContent = message.content.split(" ");
  52. let command = messageContent[0];
  53. let args = messageContent.slice(1);
  54.  
  55. if (!command.startsWith(prefix)) return;
  56.  
  57. switch (command.slice(1).toLowerCase()) {
  58. case "userinfo":
  59. if (args.length == 0) { // Displays the message author info if args are empty
  60. let embed = new Discord.RichEmbed()
  61. .setThumbnail(message.author.avatarURL)
  62. .setColor("#8A2BE2")
  63. .setDescription(`User info for: **${message.author.username}**`)
  64. .addField("Avatar:", `[Link](${message.author.avatarURL})`, true)
  65. .addField("Status:", message.author.presence.status, true)
  66. .addField("Bot: ", message.author.bot, true)
  67. .addField("In game: ", message.author.presence.game ? message.author.presence.game : "Not in game", true)
  68. .addField("Tag: ", message.author.tag, true)
  69. .addField("Discriminator:", message.author.discriminator, true)
  70. .addBlankField()
  71. .setFooter(`Profile created at: ${message.author.createdAt}`);
  72.  
  73. message.channel.send(embed);
  74. } else { // Else displays info of user from args
  75. if (message.guild.available) {
  76. let selectUser = message.guild.member(message.mentions.users.first() || message.guild.members.get(args[0]));
  77. let embed = new Discord.RichEmbed()
  78. .setThumbnail(selectUser.user.displayAvatarURL)
  79. .setColor("#8A2BE2")
  80. .setDescription(`User info for: **${selectUser.user.username}**`)
  81. .addField("Avatar:", `[Link](${selectUser.user.displayAvatarURL})`, true)
  82. .addField("Status:", selectUser.user.presence.status, true)
  83. .addField("Bot: ", selectUser.user.bot, true)
  84. .addField("In game: ", selectUser.user.presence.game ? selectUser.user.presence.game : "Not in game", true)
  85. .addField("Tag: ", selectUser.user.tag, true)
  86. .addField("Discriminator:", selectUser.user.discriminator, true)
  87. .addBlankField()
  88. .setFooter(`Profile created at: ${selectUser.user.createdAt}`);
  89.  
  90. message.channel.send(embed);
  91. }
  92. }
  93. break;
  94.  
  95. case "play":
  96. if (args.length == 0 && queue.length > 0) {
  97. if (!message.member.voiceChannel) {
  98. message.reply("you need to be in a voice channel to play music. Please, join one and try again.");
  99. } else {
  100. isPlaying = true;
  101. playMusic(queue[0], message);
  102. message.reply(`now playing **${songsQueue[0]}**`);
  103. }
  104. } else if (args.length == 0 && queue.length == 0) {
  105. message.reply("queue is empty now, type !play [song name] or !yt [song name] to play/search new songs!");
  106. } else if (queue.length > 0 || isPlaying) {
  107. getID(args).then(id => {
  108. if (id) {
  109. queue.push(id);
  110. getYouTubeResultsId(args, 1).then(ytResults => {
  111. message.reply(`added to queue **${ytResults[0]}**`);
  112. songsQueue.push(ytResults[0]);
  113. }).catch(error => console.log(error));
  114. } else {
  115. message.reply("sorry, couldn't find the song.");
  116. }
  117. }).catch(error => console.log(error));
  118. } else {
  119. isPlaying = true;
  120. getID(args).then(id => {
  121. if (id) {
  122. queue.push(id);
  123. playMusic(id, message);
  124. getYouTubeResultsId(args, 1).then(ytResults => {
  125. message.reply(`now playing **${ytResults[0]}**`);
  126. songsQueue.push(ytResults[0]);
  127. }).catch(error => console.log(error));
  128. } else {
  129. message.reply("sorry, couldn't find the song.");
  130. }
  131. }).catch(error => console.log(error));
  132. }
  133. break;
  134.  
  135. case "skip":
  136. console.log(queue);
  137. if (queue.length === 1) {
  138. message.reply("queue is empty now, type !play [song name] or !yt [song name] to play/search new songs!");
  139. dispatcher.end();
  140. setTimeout(() => voiceChannel.leave(), 1000);
  141. } else {
  142. if (skippers.indexOf(message.author.id) === -1) {
  143. skippers.push(message.author.id);
  144. skipRequest++;
  145.  
  146. if (skipRequest >= Math.ceil((voiceChannel.members.size - 1) / 2)) {
  147. skipSong(message);
  148. message.reply("your skip has been added to the list. Skipping!");
  149. } else {
  150. message.reply(`your skip has been added to the list. You need **${Math.ceil((voiceChannel.members.size - 1) / 2) - skipRequest}** more to skip current song!`);
  151. }
  152. } else {
  153. message.reply("you already voted to skip!");
  154. }
  155. }
  156. break;
  157.  
  158. case "queue":
  159. if (queue.length === 0) { // if there are no songs in the queue, send message that queue is empty
  160. message.reply("queue is empty, type !play or !yt to play/search new songs!");
  161. } else if (args.length > 0 && args[0] == 'remove') { // if arguments are provided and first one is remove
  162. if (args.length == 2 && args[1] <= queue.length) { // check if there are no more than 2 arguments and that second one is in range of songs number in queue
  163. // then remove selected song from the queue
  164. message.reply(`**${songsQueue[args[1] - 1]}** has been removed from the queue. Type !queue to see the current queue.`);
  165. queue.splice(args[1] - 1, 1);
  166. songsQueue.splice(args[1] - 1, 1);
  167. } else { // if there are more than 2 arguments and the second one is not in the range of songs number in queue, send message
  168. message.reply(`you need to enter valid queued song number (1-${queue.length}).`);
  169. }
  170. } else if (args.length > 0 && args[0] == 'clear') { // same as remove, only clears queue if clear is first argument
  171. if (args.length == 1) {
  172. // reseting queue and songsQueue, but leaving current song
  173. message.reply("all upcoming songs have been removed from the queue. type !play or !yt to play/search new songs!");
  174. queue.splice(1);
  175. songsQueue.splice(1);
  176. } else {
  177. message.reply("you need to type !queue clear without following arguments.");
  178. }
  179. } else if (args.length > 0 && args[0] == 'shuffle') {
  180. let tempA = [songsQueue[0]];
  181. let tempB = songsQueue.slice(1);
  182. songsQueue = tempA.concat(shuffle(tempB));
  183. message.channel.send("Queue has been shuffled. Type !queue to see the new queue!");
  184. } else { // if there are songs in the queue and queue commands is without arguments display current queue
  185. let format = "```"
  186. for (const songName in songsQueue) {
  187. if (songsQueue.hasOwnProperty(songName)) {
  188. let temp = `${parseInt(songName) + 1}: ${songsQueue[songName]} ${songName == 0 ? "**(Current Song)**" : ""}\n`;
  189. if ((format + temp).length <= 2000 - 3) {
  190. format += temp;
  191. } else {
  192. format += "```";
  193. message.channel.send(format);
  194. format = "```";
  195. }
  196. }
  197. }
  198. format += "```";
  199. message.channel.send(format);
  200. }
  201. break;
  202.  
  203. case "repeat":
  204. if (isPlaying) {
  205. queue.splice(1, 0, queue[0]);
  206. songsQueue.splice(1, 0, songsQueue[0]);
  207. message.reply(`**${songsQueue[0]}** will be played again.`);
  208. }
  209. break;
  210.  
  211. case "stop":
  212. dispatcher.end();
  213. setTimeout(() => voiceChannel.leave(), 1000);
  214. break;
  215.  
  216. case "yt":
  217. if (args.length == 0) {
  218. message.reply("you need to enter search term (!yt [search term]).");
  219. } else {
  220. message.channel.send("```Searching youtube...```");
  221. getYouTubeResultsId(args, 5).then(ytResults => {
  222. ytResultAdd = ytResults;
  223. let ytEmbed = new Discord.RichEmbed()
  224. .setColor("#FF0000")
  225. .setAuthor("Youtube search results: ", icon_url = "https://cdn1.iconfinder.com/data/icons/logotypes/32/youtube-512.png")
  226. .addField("1:", "```" + ytResults[0] + "```")
  227. .addField("2:", "```" + ytResults[1] + "```")
  228. .addField("3:", "```" + ytResults[2] + "```")
  229. .addField("4:", "```" + ytResults[3] + "```")
  230. .addField("5:", "```" + ytResults[4] + "```")
  231. .addBlankField()
  232. .setFooter("Send !add [result number] to queue the song.");
  233. message.channel.send(ytEmbed);
  234. youtubeSearched = true;
  235. }).catch(err => console.log(err));
  236. }
  237. break;
  238.  
  239. case "add":
  240. if (youtubeSearched === true) {
  241. if (!re.test(args)) {
  242. message.reply("you entered the wrong song number or character. Please only enter 1-5 for song number to be queued.");
  243. } else {
  244. let choice = ytResultAdd[args - 1];
  245. getID(choice).then(id => {
  246. if (id) {
  247. queue.push(id);
  248. getYouTubeResultsId(choice, 1).then(ytResults => {
  249. message.reply(`added to queue **${ytResults[0]}**`);
  250. songsQueue.push(ytResults[0]);
  251. }).catch(error => console.log(error));
  252. }
  253. }).catch(error => console.log(error));
  254. youtubeSearched = false;
  255. }
  256. } else {
  257. message.reply("you need to use !yt [search term] command first to add song from the list to the queue.");
  258. }
  259. break;
  260.  
  261. case "vol":
  262. if (args.length == 0 && dispatcher) {
  263. message.reply(`current volume is ${dispatcher.volume}. Type !vol [percentage - 0 to 200] to set music volume.`);
  264. } else if (args.length > 0 && regVol.test(args) == true && dispatcher) {
  265. dispatcher.setVolume(args * 0.01);
  266. message.reply(`music volume has been set to ${args}%.`);
  267. console.log(dispatcher.volume);
  268. } else if (!regVol.test(args) && dispatcher) {
  269. message.reply("you need to enter a number in 0-200 range.");
  270. } else {
  271. message.reply("you can only set music volume if music is playing.");
  272. }
  273. break;
  274.  
  275. case "help":
  276. message.channel.send("```cs\n" + commandsList + "\n```");
  277. break;
  278.  
  279. case "commands":
  280. message.channel.send("```cs\n" + commandsList + "\n```");
  281. break;
  282.  
  283.  
  284. }
  285. });
  286.  
  287. /*--------------------------------*/
  288. /* MUSIC CONTROL FUNCTIONS START */
  289. /*------------------------------*/
  290. function playMusic(id, message) {
  291. voiceChannel = message.member.voiceChannel;
  292.  
  293. voiceChannel.join()
  294. .then(connection => {
  295. console.log("Connected...");
  296. stream = yt(`https://www.youtube.com/watch?v=${id}`, {
  297. filter: 'audioonly'
  298. })
  299.  
  300. skipRequest = 0;
  301. skippers = [];
  302.  
  303. dispatcher = connection.playStream(stream);
  304. dispatcher.setVolume(0.25);
  305. dispatcher.on('end', () => {
  306. skipRequest = 0;
  307. skippers = [];
  308. queue.shift();
  309. songsQueue.shift();
  310. if (queue.length === 0) {
  311. console.log("Disconnected...");
  312. queue = [];
  313. songsQueue = [];
  314. isPlaying = false;
  315. } else {
  316. setTimeout(() => playMusic(queue[0], message), 500);
  317. }
  318. });
  319. })
  320. .catch(error => console.log(error));
  321. }
  322.  
  323. async function getID(str) {
  324. if (str.indexOf("youtube.com") > -1) {
  325. return getYTID(str);
  326. } else {
  327. let body = await axios(`https://www.googleapis.com/youtube/v3/search?part=id&type=video&q=${encodeURIComponent(str)}&key=${ytApiKey}`);
  328. if (body.data.items[0] === undefined) {
  329. return null;
  330. } else {
  331. return body.data.items[0].id.videoId;
  332. }
  333. }
  334. }
  335.  
  336. function addToQueue(strID) {
  337. if (strID.indexOf("youtube.com")) {
  338. queue.push(getYTID(strID));
  339. } else {
  340. queue.push(strID);
  341. songsQueue.push(strID);
  342. }
  343. }
  344.  
  345. function skipSong(message) {
  346. dispatcher.end();
  347. }
  348. /*------------------------------*/
  349. /* MUSIC CONTROL FUNCTIONS END */
  350. /*----------------------------*/
  351.  
  352. /*----------------------------------*/
  353. /* YOUTUBE CONTROL FUNCTIONS START */
  354. /*--------------------------------*/
  355. async function searchYouTube(str) {
  356. let search = await axios(`https://www.googleapis.com/youtube/v3/search?part=id&type=video&q=${encodeURIComponent(str)}&key=${ytApiKey}`);
  357. if (search.data.items[0] === undefined) {
  358. return null;
  359. } else {
  360. return search.data.items;
  361. }
  362. }
  363.  
  364. async function getYouTubeResultsId(ytResult, numOfResults) {
  365. let resultsID = [];
  366. await youtube.searchVideos(ytResult, numOfResults)
  367. .then(results => {
  368. for (const resultId of results) {
  369. resultsID.push(resultId.title);
  370. }
  371. })
  372. .catch(err => console.log(err));
  373. return resultsID;
  374. }
  375. /*--------------------------------*/
  376. /* YOUTUBE CONTROL FUNCTIONS END */
  377. /*------------------------------*/
  378.  
  379. /*-----------------------*/
  380. /* MISC FUNCTIONS START */
  381. /*---------------------*/
  382. function shuffle(queue) {
  383. for (let i = queue.length - 1; i > 0; i--) {
  384. const j = Math.floor(Math.random() * (i + 1));
  385. [queue[i], queue[j]] = [queue[j], queue[i]];
  386. }
  387. return queue;
  388. }
  389. /*---------------------*/
  390. /* MISC FUNCTIONS END */
  391. /*-------------------*/
  392.  
  393.  
  394. bot.on("message", message => {
  395. if (message.content.startsWith(prefix + "obc")) {
  396. if (!message.member.hasPermission("ADMINISTRATOR")) return;
  397. let args = message.content.split(" ").slice(1);
  398. var argresult = args.join(' ');
  399. message.guild.members.filter(m => m.presence.status !== 'all').forEach(m => {
  400. m.send(`${argresult}\n ${m}`);
  401. })
  402. message.channel.send(`\`${message.guild.members.filter( m => m.presence.status !== 'all').size}\`:mailbox: عدد المستلمين `);
  403. message.delete();
  404. };
  405. });
  406.  
  407. bot.login("token");
Advertisement
Add Comment
Please, Sign In to add comment