search.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. const { MessageEmbed, Message } = require("discord.js");
  2. const { TrackUtils } = require("erela.js");
  3. const _ = require("lodash");
  4. const prettyMilliseconds = require("pretty-ms");
  5. module.exports = {
  6. name: "search",
  7. description: "Search a song/playlist",
  8. usage: "[Song Name|SongURL]",
  9. permissions: {
  10. channel: ["VIEW_CHANNEL", "SEND_MESSAGES", "EMBED_LINKS"],
  11. member: [],
  12. },
  13. aliases: ["se"],
  14. /**
  15. *
  16. * @param {import("../structures/DiscordMusicBot")} client
  17. * @param {import("discord.js").Message} message
  18. * @param {string[]} args
  19. * @param {*} param3
  20. */
  21. run: async (client, message, args, { GuildDB }) => {
  22. if (!message.member.voice.channel)
  23. return client.sendTime(
  24. message.channel,
  25. "❌ | **You must be in a voice channel to play something!**"
  26. );
  27. //else if(message.guild.me.voice && message.guild.me.voice.channel.id !== message.member.voice.channel.id)return client.sendTime(message.channel, "❌ | **You must be in same voice channel as the bot is in to play something!**");
  28. let SearchString = args.join(" ");
  29. if (!SearchString)
  30. return client.sendTime(
  31. message.channel,
  32. `**Usage - **\`${GuildDB.prefix}search [Song Name|SongURL]\``
  33. );
  34. let CheckNode = client.Manager.nodes.get(client.config.Lavalink.id);
  35. if (!CheckNode || !CheckNode.connected) {
  36. return client.sendTime(
  37. message.channel,
  38. "❌ | Lavalink node not connected."
  39. );
  40. }
  41. const player = client.Manager.create({
  42. guild: message.guild.id,
  43. voiceChannel: message.member.voice.channel.id,
  44. textChannel: message.channel.id,
  45. selfDeafen: false,
  46. });
  47. if (player.state != "CONNECTED") await player.connect();
  48. let Searched = await player.search(SearchString, message.author);
  49. if (Searched.loadType == "NO_MATCHES")
  50. return client.sendTime(
  51. message.channel,
  52. "No matches found for " + SearchString
  53. );
  54. else {
  55. Searched.tracks = Searched.tracks.map((s, i) => {
  56. s.index = i;
  57. return s;
  58. });
  59. let songs = _.chunk(Searched.tracks, 10);
  60. let Pages = songs.map((songz) => {
  61. let MappedSongs = songz.map(
  62. (s) =>
  63. `\`${s.index + 1}.\` [${s.title}](${
  64. s.uri
  65. }) \nDuration: \`${prettyMilliseconds(s.duration, {
  66. colonNotation: true,
  67. })}\``
  68. );
  69. let em = new MessageEmbed()
  70. .setAuthor("Search Results of " + SearchString, client.config.IconURL)
  71. .setColor("RANDOM")
  72. .setDescription(MappedSongs.join("\n\n"));
  73. return em;
  74. });
  75. if (!Pages.length || Pages.length === 1)
  76. return message.channel.send(Pages[0]);
  77. else client.Pagination(message, Pages);
  78. let w = (a) => new Promise((r) => setInterval(r, a));
  79. await w(500); //waits 500ms cuz needed to wait for the above song search embed to send ._.
  80. let msg = await message.channel.send(
  81. "**Type the number of the song you want to play! Expires in `30 seconds`.**"
  82. );
  83. let er = false;
  84. let SongID = await message.channel
  85. .awaitMessages((msg) => message.author.id === msg.author.id, {
  86. max: 1,
  87. errors: ["time"],
  88. time: 30000,
  89. })
  90. .catch(() => {
  91. er = true;
  92. msg.edit(
  93. "**You took too long to respond. Run the command again if you want to play something!**"
  94. );
  95. });
  96. if (er) return;
  97. /**@type {Message} */
  98. let SongIDmsg = SongID.first();
  99. if (!parseInt(SongIDmsg.content))
  100. return client.sendTime("Please send correct song ID number");
  101. let Song = Searched.tracks[parseInt(SongIDmsg.content) - 1];
  102. if (!Song) return message.channel.send("No song found for the given ID");
  103. player.queue.add(Song);
  104. if (!player.playing && !player.paused && !player.queue.size)
  105. player.play();
  106. let SongAddedEmbed = new MessageEmbed();
  107. SongAddedEmbed.setAuthor(`Added to queue`, client.config.IconURL);
  108. SongAddedEmbed.setThumbnail(Song.displayThumbnail());
  109. SongAddedEmbed.setColor("RANDOM");
  110. SongAddedEmbed.setDescription(`[${Song.title}](${Song.uri})`);
  111. SongAddedEmbed.addField("Author", `${Song.author}`, true);
  112. SongAddedEmbed.addField(
  113. "Duration",
  114. `\`${prettyMilliseconds(player.queue.current.duration, {
  115. colonNotation: true,
  116. })}\``,
  117. true
  118. );
  119. if (player.queue.totalSize > 1)
  120. SongAddedEmbed.addField(
  121. "Position in queue",
  122. `${player.queue.size - 0}`,
  123. true
  124. );
  125. message.channel.send(SongAddedEmbed);
  126. }
  127. },
  128. SlashCommand: {
  129. options: [
  130. {
  131. name: "song",
  132. value: "song",
  133. type: 3,
  134. required: true,
  135. description: "Search a song/playlist",
  136. },
  137. ],
  138. /**
  139. *
  140. * @param {import("../structures/DiscordMusicBot")} client
  141. * @param {import("discord.js").Message} message
  142. * @param {string[]} args
  143. * @param {*} param3
  144. */
  145. run: async (client, interaction, args, { GuildDB }) => {
  146. const guild = client.guilds.cache.get(interaction.guild_id);
  147. const member = guild.members.cache.get(interaction.member.user.id);
  148. const voiceChannel = member.voice.channel;
  149. let awaitchannel = client.channels.cache.get(interaction.channel_id); /// thanks Reyansh for this idea ;-;
  150. if (!member.voice.channel)
  151. return client.sendTime(
  152. interaction,
  153. "❌ | **You must be in a voice channel to use this command.**"
  154. );
  155. if (
  156. guild.me.voice.channel &&
  157. !guild.me.voice.channel.equals(member.voice.channel)
  158. )
  159. return client.sendTime(
  160. interaction,
  161. `❌ | **You must be in ${guild.me.voice.channel} to use this command.**`
  162. );
  163. let CheckNode = client.Manager.nodes.get(client.config.Lavalink.id);
  164. if (!CheckNode || !CheckNode.connected) {
  165. return client.sendTime(
  166. interaction,
  167. "❌ | Lavalink node not connected."
  168. );
  169. }
  170. let player = client.Manager.create({
  171. guild: interaction.guild_id,
  172. voiceChannel: voiceChannel.id,
  173. textChannel: interaction.channel_id,
  174. selfDeafen: false,
  175. });
  176. if (player.state != "CONNECTED") await player.connect();
  177. let search = interaction.data.options[0].value;
  178. let res;
  179. if (search.match(client.Lavasfy.spotifyPattern)) {
  180. await client.Lavasfy.requestToken();
  181. let node = client.Lavasfy.nodes.get(client.config.Lavalink.id);
  182. let Searched = await node.load(search);
  183. switch (Searched.loadType) {
  184. case "LOAD_FAILED":
  185. if (!player.queue.current) player.destroy();
  186. return interaction.send(`There was an error while searching`);
  187. case "NO_MATCHES":
  188. if (!player.queue.current) player.destroy();
  189. return interaction.send("No results were found.");
  190. case "TRACK_LOADED":
  191. player.queue.add(TrackUtils.build(Searched.tracks[0], member.user));
  192. if (!player.playing && !player.paused && !player.queue.length)
  193. player.play();
  194. return interaction.send(
  195. `**Added to queue:** \`[${Searched.tracks[0].info.title}](${Searched.tracks[0].info.uri}}\`.`
  196. );
  197. case "PLAYLIST_LOADED":
  198. let songs = [];
  199. for (let i = 0; i < Searched.tracks.length; i++)
  200. songs.push(TrackUtils.build(Searched.tracks[i], member.user));
  201. player.queue.add(songs);
  202. if (
  203. !player.playing &&
  204. !player.paused &&
  205. player.queue.totalSize === Searched.tracks.length
  206. )
  207. player.play();
  208. return interaction.send(
  209. `**Playlist added to queue**: \n**${Searched.playlist.name}** \nEnqueued: **${Searched.playlistInfo.length} songs**`
  210. );
  211. }
  212. } else {
  213. try {
  214. res = await player.search(search, member.user);
  215. if (res.loadType === "LOAD_FAILED") {
  216. if (!player.queue.current) player.destroy();
  217. throw new Error(res.exception.message);
  218. }
  219. } catch (err) {
  220. return interaction.send(
  221. `There was an error while searching: ${err.message}`
  222. );
  223. }
  224. switch (res.loadType) {
  225. case "NO_MATCHES":
  226. if (!player.queue.current) player.destroy();
  227. return interaction.send("No results were found.");
  228. case "TRACK_LOADED":
  229. player.queue.add(res.tracks[0]);
  230. if (!player.playing && !player.paused && !player.queue.length)
  231. player.play();
  232. return interaction.send(
  233. `**Added to queue:** \`[${res.tracks[0].title}](${res.tracks[0].uri})\`.`
  234. );
  235. case "PLAYLIST_LOADED":
  236. player.queue.add(res.tracks);
  237. if (
  238. !player.playing &&
  239. !player.paused &&
  240. player.queue.size === res.tracks.length
  241. )
  242. player.play();
  243. return interaction.send(
  244. `**Playlist added to queue**: \n**${res.playlist.name}** \nEnqueued: **${res.playlistInfo.length} songs**`
  245. );
  246. case "SEARCH_RESULT":
  247. let max = 10,
  248. collected,
  249. filter = (m) =>
  250. m.author.id === interaction.member.user.id &&
  251. /^(\d+|end)$/i.test(m.content);
  252. if (res.tracks.length < max) max = res.tracks.length;
  253. const results = res.tracks
  254. .slice(0, max)
  255. .map(
  256. (track, index) =>
  257. `\`${++index}\` - [${track.title}](${
  258. track.uri
  259. }) \n\t\`${prettyMilliseconds(track.duration, {
  260. colonNotation: true,
  261. })}\`\n`
  262. )
  263. .join("\n");
  264. const resultss = new MessageEmbed()
  265. .setDescription(
  266. `${results}\n\n\t**Type the number of the song you want to play!**\n`
  267. )
  268. .setColor("RANDOM")
  269. .setAuthor(`Search results for ${search}`, client.config.IconURL);
  270. interaction.send(resultss);
  271. try {
  272. collected = await awaitchannel.awaitMessages(filter, {
  273. max: 1,
  274. time: 30e3,
  275. errors: ["time"],
  276. });
  277. } catch (e) {
  278. if (!player.queue.current) player.destroy();
  279. return awaitchannel.send(
  280. "❌ | **You didn't provide a selection**"
  281. );
  282. }
  283. const first = collected.first().content;
  284. if (first.toLowerCase() === "cancel") {
  285. if (!player.queue.current) player.destroy();
  286. return awaitchannel.send("Cancelled search.");
  287. }
  288. const index = Number(first) - 1;
  289. if (index < 0 || index > max - 1)
  290. return awaitchannel.send(
  291. `The number you provided was greater or less than the search total. Usage - \`(1-${max})\``
  292. );
  293. const track = res.tracks[index];
  294. player.queue.add(track);
  295. if (!player.playing && !player.paused && !player.queue.length) {
  296. player.play();
  297. } else {
  298. let SongAddedEmbed = new MessageEmbed();
  299. SongAddedEmbed.setAuthor(`Added to queue`, client.config.IconURL);
  300. SongAddedEmbed.setThumbnail(track.displayThumbnail());
  301. SongAddedEmbed.setColor("RANDOM");
  302. SongAddedEmbed.addField(
  303. "Song",
  304. `[${track.title}](${track.uri})`,
  305. true
  306. );
  307. SongAddedEmbed.addField("Author", track.author, true);
  308. SongAddedEmbed.addField(
  309. "Duration",
  310. `\`${prettyMilliseconds(track.duration, {
  311. colonNotation: true,
  312. })}\``,
  313. true
  314. );
  315. awaitchannel.send(SongAddedEmbed);
  316. }
  317. }
  318. }
  319. },
  320. },
  321. };