UNPKG

dellosmusic

Version:

Dellos Music Bot - Discord Music Bot

408 lines (365 loc) 13.6 kB
const { GatewayIntentBits, Collection, Client, MessageEmbed } = require("discord.js"); const { LavasfyClient } = require("lavasfy"); const { Manager } = require("erela.js"); const { Server } = require("socket.io"); const http = require("http"); const Jsoning = require("jsoning"); const fs = require("fs"); const path = require("path"); const Express = require("express"); const Logger = require("./Logger"); let prettyMilliseconds; (async () => { const prettyMsModule = await import("pretty-ms"); prettyMilliseconds = prettyMsModule.default; })(); const deezer = require("erela.js-deezer"); const apple = require("erela.js-apple"); const facebook = require("erela.js-facebook"); let d; //Class extending Stuff require("./EpicPlayer"); //idk why im doing but i wanna learn something new so... class DiscordMusicBot extends Client { constructor(props) { super(props); this.commands = new Collection(); this.connections = new Map(); this.CommandsRan = 0; this.SongsPlayed = 0; this.database = { //Saved at jsoning node_modules directory, DOCS: https://jsoning.js.org/ guild: new Jsoning("guild.json"), //Server Config }; this.logger = new Logger(path.join(__dirname, "..", "Logs.log")); try { //Config for testing this.botconfig = require("../dev-config"); } catch { //Config for production this.botconfig = require("../botconfig"); } if (this.botconfig.Token === "") return new TypeError( "The botconfig.js is not filled out. Please make sure nothing is blank, otherwise the bot will not work properly." ); this.LoadCommands(); this.LoadEvents(); //Web Stuff this.server = Express(); this.http = http.createServer(this.server); this.server.use("/", require("../api")); this.io = new Server(this.http); require("../api/socket")(this.io); //Utils this.ProgressBar = require("../util/ProgressBar"); this.Pagination = require("../util/pagination"); this.ParseHumanTime = (str) => { let Parsed; try { Parsed = require("../util/TimeString")(str); return Parsed; } catch { Parsed = false; return Parsed; } }; this.Ready = false; //idk where do i do it so i did it here ;-; this.ws.on("INTERACTION_CREATE", async (interaction) => { let GuildDB = await this.GetGuild(interaction.guild_id); //Initialize GuildDB if (!GuildDB) { await this.database.guild.set(interaction.guild_id, { prefix: this.botconfig.DefaultPrefix, DJ: null, }); GuildDB = await this.GetGuild(interaction.guild_id); } const command = interaction.data.name.toLowerCase(); const args = interaction.data.options; //Easy to send respnose so ;) interaction.guild = await this.guilds.fetch(interaction.guild_id); interaction.send = async (message) => { return await this.api .interactions(interaction.id, interaction.token) .callback.post({ data: { type: 4, data: typeof message == "string" ? { content: message } : message.type && message.type === "rich" ? { embeds: [message] } : message, }, }); }; let cmd = client.commands.get(command); if (cmd.SlashCommand && cmd.SlashCommand.run) cmd.SlashCommand.run(this, interaction, args, { GuildDB }); }); //because not worked lol ;-; const client = this; this.Lavasfy = new LavasfyClient( { clientID: this.botconfig.Spotify.ClientID, clientSecret: this.botconfig.Spotify.ClientSecret, playlistPageLoadLimit: 1, filterAudioOnlyResult: true, autoResolve: true, useSpotifyMetadata: true, }, [ { id: this.botconfig.Lavalink.id, host: this.botconfig.Lavalink.host, port: this.botconfig.Lavalink.port, password: this.botconfig.Lavalink.pass, secure: this.botconfig.Lavalink.secure, }, ] ); this.Manager = new Manager({ plugins: [new deezer(), new apple(), new facebook()], nodes: [ { identifier: this.botconfig.Lavalink.id, host: this.botconfig.Lavalink.host, port: this.botconfig.Lavalink.port, password: this.botconfig.Lavalink.pass, secure: this.botconfig.Lavalink.secure, retryAmount: this.botconfig.Lavalink.retryAmount, retryDelay: this.botconfig.Lavalink.retryDelay, }, ], send(id, payload) { const guild = client.guilds.cache.get(id); if (guild) guild.shard.send(payload); }, }) .on("nodeConnect", (node) => this.log(`Lavalink: Node ${node.options.identifier} connected`) ) .on("nodeError", (node, error) => this.log( `Lavalink: Node ${node.options.identifier} had an error: ${error.message}` ) ) .on("trackStart", async (player, track) => { this.SongsPlayed++; let TrackStartedEmbed = new MessageEmbed() .setAuthor(`Now playing ♪`, this.botconfig.IconURL) .setThumbnail(player.queue.current.displayThumbnail()) .setDescription(`[${track.title}](${track.uri})`) .addField("Requested by", `${track.requester}`, true) .setColor(this.botconfig.EmbedColor); // Check if the duration matches the duration of a livestream if (track.duration == 9223372036854776000) { d = "Live"; } else { d = prettyMilliseconds(track.duration, { colonNotation: true }); } TrackStartedEmbed.addField("Duration", `\`${d}\``, true); //.setFooter("Started playing at"); let NowPlaying = await client.channels.cache .get(player.textChannel) .send(TrackStartedEmbed); player.setNowplayingMessage(NowPlaying); }) .on("queueEnd", (player) => { let QueueEmbed = new MessageEmbed() .setAuthor("The queue has ended", this.botconfig.IconURL) .setColor(this.botconfig.EmbedColor); client.channels.cache.get(player.textChannel).send(QueueEmbed); player.destroy(); }) .on("playerMove", (player, currentChannel, newChannel) => { if (!newChannel) { //Channel deleted let QueueEmbed = new MessageEmbed() .setAuthor( "The voice channel has been deleted, and I had to stop playing.", this.botconfig.IconURL ) .setColor(this.botconfig.EmbedColor); client.channels.cache.get(player.textChannel).send(QueueEmbed); player.destroy(); } }); this.Lavasfy .on("searchResults", async (msg, query, tracks) => { let Pages = this.Pagination.createPages(tracks, msg.author); let PaginationEmbed = new MessageEmbed() .setAuthor(`Results for ${query}`, this.botconfig.IconURL) .setColor(this.botconfig.EmbedColor) .setFooter( "Page 1 of " + Pages.length + ` | ` + tracks.length + " Songs" ); Pages[0].forEach((track) => { PaginationEmbed.addField( `${Pages[0].indexOf(track) + 1}. ${track.title}`, `[${track.uri}](${track.uri})`, true ); }); msg.channel.send(PaginationEmbed).then(async (msgg) => { this.Pagination.createReactionEmbed( Pages, msgg, msg.author, PaginationEmbed, tracks ); }); }) .on("playlistResults", async (msg, query, playlists) => { let Pages = this.Pagination.createPages(playlists, msg.author); let PaginationEmbed = new MessageEmbed() .setAuthor(`Results for ${query}`, this.botconfig.IconURL) .setColor(this.botconfig.EmbedColor) .setFooter( "Page 1 of " + Pages.length + ` | ` + playlists.length + " Playlists" ); Pages[0].forEach((playlist) => { PaginationEmbed.addField( `${Pages[0].indexOf(playlist) + 1}. ${playlist.name}`, `[${playlist.uri}](${playlist.uri})`, true ); }); msg.channel.send(PaginationEmbed).then(async (msgg) => { this.Pagination.createReactionEmbed( Pages, msgg, msg.author, PaginationEmbed, playlists ); }); }) .on("albumResults", async (msg, query, albums) => { let Pages = this.Pagination.createPages(albums, msg.author); let PaginationEmbed = new MessageEmbed() .setAuthor(`Results for ${query}`, this.botconfig.IconURL) .setColor(this.botconfig.EmbedColor) .setFooter( "Page 1 of " + Pages.length + ` | ` + albums.length + " Albums" ); Pages[0].forEach((album) => { PaginationEmbed.addField( `${Pages[0].indexOf(album) + 1}. ${album.name}`, `[${album.uri}](${album.uri})`, true ); }); msg.channel.send(PaginationEmbed).then(async (msgg) => { this.Pagination.createReactionEmbed( Pages, msgg, msg.author, PaginationEmbed, albums ); }); }) .on("artistResults", async (msg, query, artists) => { let Pages = this.Pagination.createPages(artists, msg.author); let PaginationEmbed = new MessageEmbed() .setAuthor(`Results for ${query}`, this.botconfig.IconURL) .setColor(this.botconfig.EmbedColor) .setFooter( "Page 1 of " + Pages.length + ` | ` + artists.length + " Artists" ); Pages[0].forEach((artist) => { PaginationEmbed.addField( `${Pages[0].indexOf(artist) + 1}. ${artist.name}`, `[${artist.uri}](${artist.uri})`, true ); }); msg.channel.send(PaginationEmbed).then(async (msgg) => { this.Pagination.createReactionEmbed( Pages, msgg, msg.author, PaginationEmbed, artists ); }); }) .on("noResults", async (msg, query) => { let embed = new MessageEmbed() .setColor(this.botconfig.EmbedColor) .setAuthor("No results were found for " + query, this.botconfig.IconURL); msg.channel.send(embed); }) .on("loadTracks", async (player, tracks) => { let embed = new MessageEmbed() .setColor(this.botconfig.EmbedColor) .setAuthor("Added to Queue", this.botconfig.IconURL) .setThumbnail(player.queue.current.displayThumbnail()) .addField("Name", `[${tracks[0].title}](${tracks[0].uri})`, true) .addField("Duration", `\`${tracks[0].isStream ? "LIVE" : prettyMilliseconds(tracks[0].duration, { colonNotation: true })}\``, true) .addField("Position", player.queue.length, true) .addField("Estimated time until playing", this.ProgressBar(player)); if (player.queue.current.isStream) embed.addField("Current time", "LIVE", true); msg.channel.send(embed); }); //Load the songs which has been started before the bot was restarted this.database.guild.all().forEach(async (value) => { if (!value.track) return; let player = await this.Manager.join( { guild: value.guildID, channel: value.voiceChannelID, host: this.botconfig.Lavalink.host, }, { selfDeafen: this.botconfig.ServerDeafen, selfMute: false, } ); if (player.state !== "CONNECTED") return; player.set("autoplay", false); player.set("djmode", false); player.queue.add(value.track); player.stop(); }); } //Load Events async LoadEvents() { const eventFiles = fs .readdirSync(path.join(__dirname, "..", "events")) .filter((file) => file.endsWith(".js")); for (const file of eventFiles) { const event = require(path.join(__dirname, "..", "events", file)); const eventName = file.split(".")[0]; super.on(eventName, event.bind(null, this)); } } //Load Commands async LoadCommands() { const commandFolders = fs.readdirSync( path.join(__dirname, "..", "commands") ); for (const folder of commandFolders) { const commandFiles = fs .readdirSync(path.join(__dirname, "..", "commands", folder)) .filter((file) => file.endsWith(".js")); for (const file of commandFiles) { const command = require(path.join( __dirname, "..", "commands", folder, file )); this.commands.set(command.name, command); } } } log(text) { return this.logger.log(text); } } module.exports = DiscordMusicBot;