diff --git a/README.md b/README.md index 9a275bd..469cebe 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ - [x] Music System - [x] Playlists System - [x] Premium System +- [x] Song Request System - [x] Custom Prefix - [x] Multi Language - [x] Custom Filters diff --git a/commands/Premium/Setup.js b/commands/Premium/Setup.js new file mode 100644 index 0000000..9062289 --- /dev/null +++ b/commands/Premium/Setup.js @@ -0,0 +1,68 @@ +const { EmbedBuilder, AttachmentBuilder, PermissionsBitField } = require('discord.js'); +const Setup = require("../../settings/models/Setup.js"); + +module.exports = { + config: { + name: "setup", + description: "Setup song request channel!", + accessableby: "Member", + category: "Premium", + }, + run: async (client, message, args, user, language, prefix) => { + if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return message.channel.send(`${client.i18n.get(language, "utilities", "lang_perm")}`); + try { + if (user && user.isPremium) { + await message.guild.channels.create({ + name: "song-request", + type: 0, // 0 = text, 2 = voice + topic: `${client.i18n.get(language, "setup", "setup_topic")}`, + parent_id: message.channel.parentId, + user_limit: 3, + rate_limit_per_user: 3, + }).then(async (channel) => { + + const attachment = new AttachmentBuilder("./settings/images/banner.png", { name: "setup.png" }); + + const queueMsg = `${client.i18n.get(language, "setup", "setup_queuemsg")}`; + + const playEmbed = new EmbedBuilder() + .setColor(client.color) + .setAuthor({ name: `${client.i18n.get(language, "setup", "setup_playembed_author")}` }) + .setImage(`${client.i18n.get(language, "setup", "setup_playembed_image")}`) + .setDescription(`${client.i18n.get(language, "setup", "setup_playembed_desc")}`) + .setFooter({ text: `${client.i18n.get(language, "setup", "setup_playembed_footer", { + prefix: client.prefix + })}` }); + + await channel.send({ files: [attachment] }); + await channel.send({ content: `${queueMsg}`, embeds: [playEmbed], components: [client.diSwitch] }).then(async (playmsg) => { + await Setup.findOneAndUpdate({ guild: message.guild.id }, { + guild: message.guild.id, + enable: true, + channel: channel.id, + playmsg: playmsg.id, + }); + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "setup", "setup_msg", { + channel: channel, + })}`) + .setColor(client.color); + + return message.channel.send({ embeds: [embed] }); + }) + }); + } else { + const embed = new EmbedBuilder() + .setAuthor({ name: `${client.i18n.get(language, "nopremium", "premium_author")}`, iconURL: client.user.displayAvatarURL() }) + .setDescription(`${client.i18n.get(language, "nopremium", "premium_desc")}`) + .setColor(client.color) + .setTimestamp() + + return message.channel.send({ content: " ", embeds: [embed] }); + } + } catch (err) { + console.log(err) + message.channel.send({ content: `${client.i18n.get(language, "nopremium", "premium_error")}` }) + } + } +}; \ No newline at end of file diff --git a/commands/Utilities/Control.js b/commands/Utilities/Control.js index f3c0360..f602542 100644 --- a/commands/Utilities/Control.js +++ b/commands/Utilities/Control.js @@ -1,5 +1,6 @@ -const { EmbedBuilder } = require('discord.js'); +const { EmbedBuilder, PermissionsBitField } = require('discord.js'); const GControl = require('../../settings/models/Control.js'); + module.exports = { config: { name: "control", @@ -10,43 +11,32 @@ module.exports = { accessableby: "Members" }, run: async (client, message, args, user, language, prefix) => { - if (!message.member.permissions.has('MANAGE_GUILD')) return message.channel.send(`${client.i18n.get(language, "utilities", "control_perm")}`); - if(!args[0]) return message.channel.send(`${client.i18n.get(language, "utilities", "control_arg")}`); - if(args[0] !== 'enable' && args[0] !== 'disable') return message.channel.send(`${client.i18n.get(language, "utilities", "control_invaild")}`); + if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return message.channel.send(`${client.i18n.get(language, "utilities", "control_perm")}`); + + const db = await GControl.findOne({ guild: message.guild.id }); + if (db.enable) { + db.enable = false; + db.save(); - const guildControl = await GControl.findOne({ guild: message.guild.id }); - if(!guildControl) { - const guildControl = new GControl({ - guild: message.guild.id, - playerControl: args[0] - }); - guildControl.save().then(() => { - const embed = new EmbedBuilder() + const embed = new EmbedBuilder() .setDescription(`${client.i18n.get(language, "utilities", "control_set", { - playerControl: args[0] + playerControl: "Disabled" })}`) .setColor(client.color) - message.channel.send({ embeds: [embed] }); - } - ).catch(() => { - message.channel.send(`${client.i18n.get(language, "utilities", "control_error")}`); - }); - } - else if(guildControl) { - guildControl.playerControl = args[0]; - guildControl.save().then(() => { - const embed = new EmbedBuilder() - .setDescription(`${client.i18n.get(language, "utilities", "control_change", { - playerControl: args[0] + message.channel.send({ embeds: [embed] }); + + } else { + db.enable = true; + db.save(); + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "utilities", "control_set", { + playerControl: "Enabled" })}`) .setColor(client.color) - - message.channel.send({ embeds: [embed] }); - } - ).catch(() => { - message.channel.send(`${client.i18n.get(language, "utilities", "control_error")}`); - }); + + message.channel.send({ embeds: [embed] }); } } } \ No newline at end of file diff --git a/commands/Utilities/Language.js b/commands/Utilities/Language.js index c673934..bff8a87 100644 --- a/commands/Utilities/Language.js +++ b/commands/Utilities/Language.js @@ -1,4 +1,4 @@ -const { EmbedBuilder } = require('discord.js'); +const { EmbedBuilder, PermissionsBitField } = require('discord.js'); const GLang = require('../../settings/models/Language.js'); module.exports = { @@ -11,9 +11,8 @@ module.exports = { accessableby: "Members" }, run: async (client, message, args, user, language, prefix) => { - - if (!message.member.permissions.has('MANAGE_GUILD')) return message.channel.send(`${client.i18n.get(language, "utilities", "lang_perm")}`); - if(!args[0]) return message.channel.send(`${client.i18n.get(language, "utilities", "lang_arg")}`); + if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return message.channel.send(`${client.i18n.get(language, "utilities", "lang_perm")}`); + if (!args[0]) return message.channel.send(`${client.i18n.get(language, "utilities", "lang_arg")}`); const languages = client.i18n.getLocales(); if (!languages.includes(args[0])) return message.channel.send(`${client.i18n.get(language, "utilities", "provide_lang", { languages: languages.join(', ') diff --git a/commands/Utilities/Prefix.js b/commands/Utilities/Prefix.js index d6572d5..04e2683 100644 --- a/commands/Utilities/Prefix.js +++ b/commands/Utilities/Prefix.js @@ -1,4 +1,4 @@ -const { EmbedBuilder } = require('discord.js'); +const { EmbedBuilder, PermissionsBitField } = require('discord.js'); const GPrefix = require('../../settings/models/Prefix.js'); module.exports = { @@ -11,8 +11,7 @@ module.exports = { accessableby: "Members" }, run: async (client, message, args, user, language, prefix) => { - - if (!message.member.permissions.has('MANAGE_GUILD')) return message.channel.send(`${client.i18n.get(language, "utilities", "prefix_perm")}`); + if (!message.member.permissions.has(PermissionsBitField.Flags.ManageGuild)) return message.channel.send(`${client.i18n.get(language, "utilities", "prefix_perm")}`); if(!args[0]) return message.channel.send(`${client.i18n.get(language, "utilities", "prefix_arg")}`); if(args[0].length > 10) return message.channel.send(`${client.i18n.get(language, "utilities", "prefix_length")}`); diff --git a/events/client/error.js b/events/client/error.js index 7dd0435..c340d15 100644 --- a/events/client/error.js +++ b/events/client/error.js @@ -1,5 +1,5 @@ const { white, red } = require('chalk'); -module.exports = async (client) => { - console.log(white('[') + red('WARN') + white('] ') + red('Errored ') + white(`${client.user.tag} (${client.user.id})`) + red(' ')); +module.exports = async (client, error) => { + console.log(white('[') + red('WARN') + white('] ') + red('Errored ') + white(`${client.user.tag} (${client.user.id}) | ${error}`) + red(' ')); }; diff --git a/events/guild/channelDelete.js b/events/guild/channelDelete.js new file mode 100644 index 0000000..9b9a313 --- /dev/null +++ b/events/guild/channelDelete.js @@ -0,0 +1,21 @@ +const Setup = require("../../settings/models/Setup.js"); + +module.exports = async (client, channel) => { + if (channel.type == 2) { + if (channel.members.has(client.user.id)) { + const player = client.manager.players.get(channel.guild.id); + if (!player) return; + if (channel.id === player.voiceChannel) { + player.destroy(); + } + } + } + + if (channel.type == 0) { + const db = await Setup.findOne({ guild: channel.guild.id }); + if (db.channel == channel.id) { + db.enable = false; + await db.save(); + } + } +}; \ No newline at end of file diff --git a/events/guild/interactionCreate.js b/events/guild/interactionCreate.js new file mode 100644 index 0000000..e609d7d --- /dev/null +++ b/events/guild/interactionCreate.js @@ -0,0 +1,155 @@ +const { EmbedBuilder } = require("discord.js"); +const GLang = require("../../settings/models/Language.js"); +const Setup = require("../../settings/models/Setup.js"); + +module.exports = async (client, interaction) => { + if (!interaction.guild || interaction.user.bot) return; + if (interaction.isButton()) { + const { customId, member } = interaction; + let voiceMember = interaction.guild.members.cache.get(member.id); + let channel = voiceMember.voice.channel; + + let player = await client.manager.get(interaction.guild.id); + if (!player) return; + + const playChannel = client.channels.cache.get(player.textChannel); + if (!playChannel) return; + + let guildModel = await GLang.findOne({ guild: playChannel.guild.id }); + if (!guildModel) { guildModel = await GLang.create({ + guild: playChannel.guild.id, + language: "en", + }); + } + + const { language } = guildModel; + + const db = await Setup.findOne({ guild: playChannel.guild.id }); + if (db.enable === false) return; + + // Here delete interaction.reply! + setTimeout(() => interaction.deleteReply(), 4000); + + switch (customId) { + case "sprevious": + { + if (!channel) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (interaction.guild.members.me.voice.channel && !interaction.guild.members.me.voice.channel.equals(channel)) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (!player || !player.queue.previous) { + return interaction.reply(`${client.i18n.get(language, "music", "previous_notfound")}`); + } else { + await player.queue.unshift(player.queue.previous); + await player.stop(); + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "music", "previous_msg")}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } + } + break; + + case "sskip": + { + if (!channel) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (interaction.guild.members.me.voice.channel && !interaction.guild.members.me.voice.channel.equals(channel)) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (!player) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_player")}`); + } else {} + if (player.queue.size == 0) { + await player.destroy(); + await client.UpdateMusic(player); + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "music", "skip_msg")}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } else { + await player.stop(); + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "music", "skip_msg")}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } + } + break; + + case "sstop": + { + if (!channel) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (interaction.guild.members.me.voice.channel && !interaction.guild.members.me.voice.channel.equals(channel)) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (!player) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_player")}`); + } else { + await player.destroy(); + await client.UpdateMusic(player); + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "player", "stop_msg")}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } + } + break; + + case "spause": + { + if (!channel) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (interaction.guild.members.me.voice.channel && !interaction.guild.members.me.voice.channel.equals(channel)) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (!player) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_player")}`); + } else { + await player.pause(!player.paused); + const uni = player.paused ? `${client.i18n.get(language, "player", "switch_pause")}` : `${client.i18n.get(language, "player", "switch_resume")}`; + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "player", "pause_msg", { + pause: uni, + })}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } + } + break; + + case "sloop": + { + if (!channel) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (interaction.guild.members.me.voice.channel && !interaction.guild.members.me.voice.channel.equals(channel)) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_voice")}`); + } else if (!player) { + return interaction.reply(`${client.i18n.get(language, "noplayer", "no_player")}`); + } else { + await player.setQueueRepeat(!player.queueRepeat); + const uni = player.queueRepeat ? `${client.i18n.get(language, "player", "switch_enable")}` : `${client.i18n.get(language, "player", "switch_disable")}`; + + const embed = new EmbedBuilder() + .setDescription(`${client.i18n.get(language, "player", "repeat_msg", { + loop: uni, + })}`) + .setColor(client.color); + + interaction.reply({ embeds: [embed] }); + } + } + break; + default: + break; + } + } +} \ No newline at end of file diff --git a/events/guild/messageCreate.js b/events/guild/messageCreate.js index bdaa635..18b5b8b 100644 --- a/events/guild/messageCreate.js +++ b/events/guild/messageCreate.js @@ -1,81 +1,167 @@ const { PermissionsBitField, EmbedBuilder } = require("discord.js"); const GPrefix = require('../../settings/models/Prefix.js'); const GLang = require('../../settings/models/Language.js'); +const Setup = require("../../settings/models/Setup.js"); const Premium = require('../../settings/models/Premium.js'); const chalk = require('chalk'); +const delay = require('delay'); module.exports = async (client, message) => { - if(message.author.bot || message.channel.type === "dm") return; + if(message.author.bot || message.channel.type === 1) return; - let PREFIX = client.prefix; - let LANGUAGE = client.i18n; - - const GuildPrefix = await GPrefix.findOne({ guild: message.guild.id }); - if(GuildPrefix && GuildPrefix.prefix) PREFIX = GuildPrefix.prefix; + /// Create database when not have! + await client.createSetup(message.guild.id); + await client.playerControl(message.guild.id); - let guildModel = await GLang.findOne({ guild: message.guild.id }); - if(guildModel && guildModel.language) LANGUAGE = guildModel.language; + /// Create new member! + let user = message.client.premiums.get(message.author.id); + if (!user) { + const findUser = await Premium.findOne({ Id: message.author.id }); + if (!findUser) { + const newUser = await Premium.create({ Id: message.author.id }); + message.client.premiums.set(message.author.id, newUser); + user = newUser + } + } - const prefix = PREFIX; - const language = LANGUAGE; + const database = await Setup.findOne({ guild: message.guild.id }); + /// REQUEST MODE! + if (database.enable) { + if (!message.guild || !message.guild.available) return; - const mention = new RegExp(`^<@!?${client.user.id}>( |)$`); + const channel = await message.guild.channels.cache.get(database.channel); + if (!channel) return; - if(message.content.match(mention)) { - const embed = new EmbedBuilder() - .setColor(client.color) - .setDescription(client.i18n.get(language, "message", "my_prefix", { - prefix: prefix || client.prefix, - }), - ); - message.channel.send({ embeds: [embed] }) - }; - const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); - const prefixRegex = new RegExp(`^(<@!?${client.user.id}>|${escapeRegex(prefix)})\\s*`); - if (!prefixRegex.test(message.content)) return; - const [ matchedPrefix ] = message.content.match(prefixRegex); - const args = message.content.slice(matchedPrefix.length).trim().split(/ +/g); - const cmd = args.shift().toLowerCase(); + if (database.channel != message.channel.id) return; - const command = client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd)); - if(!command) return; - if (!client.dev.includes(message.author.id) && client.dev.length > 0) { + const guildModel = await GLang.findOne({ guild: message.guild.id }); + if (!guildModel) { + guildModel = await GLang.create({ + guild: message.guild.id, + language: "en", + }); + } - message.channel.send(`${client.i18n.get(language, "message", "dev_only")}`); - console.log(chalk.bgRedBright(`[INFOMATION] ${message.author.tag} trying request the command from ${message.guild.name}`)); - return; - } + const { language } = guildModel; - console.log(chalk.magenta(`[COMMAND] ${command.config.name} used by ${message.author.tag} from ${message.guild.name}`)); + if (message.author.id === client.user.id) { + await delay(3000); + message.delete() + } - if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.SendMessages)) return await message.author.dmChannel.send(`${client.i18n.get(language, "message", "no_perms")}`); - if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.ViewChannel)) return; - if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.EmbedLinks)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); - if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.Speak)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); - if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.Connect)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); - - if (command) { - let user = message.client.premiums.get(message.author.id) - - if (!user) { - const findUser = await Premium.findOne({ Id: message.author.id }) - if (!findUser) { - const newUser = await Premium.create({ Id: message.author.id }) - message.client.premiums.set(message.author.id, newUser) - user = newUser - } else return - } + if (message.author.bot) return; + + const song = message.cleanContent; + await message.delete(); + + const voiceChannel = await message.member.voice.channel; + if (!voiceChannel) return message.channel.send(`${client.i18n.get(language, "noplayer", "no_voice")}`).then((msg) => { + setTimeout(() => { + msg.delete() + }, 4000); + }); + + const player = await client.manager.create({ + guild: message.guild.id, + voiceChannel: message.member.voice.channel.id, + textChannel: message.channel.id, + selfDeafen: true, + }); + + const state = player.state; + if (state != "CONNECTED") await player.connect(); + const res = await client.manager.search(song, message.author); + if(res.loadType != "NO_MATCHES") { + if(res.loadType == "TRACK_LOADED") { + player.queue.add(res.tracks[0]); + if(!player.playing) player.play(); + } else if(res.loadType == "PLAYLIST_LOADED") { + player.queue.add(res.tracks) + if(!player.playing) player.play(); + } else if(res.loadType == "SEARCH_RESULT") { + player.queue.add(res.tracks[0]); + if(!player.playing) player.play(); + } else if(res.loadType == "LOAD_FAILED") { + message.channel.send(`${client.i18n.get(language, "music", "play_fail")}`).then((msg) => { + setTimeout(() => { + msg.delete() + }, 4000); + }).catch((e) => {}); + player.destroy(); + } + } else { + message.channel.send(`${client.i18n.get(language, "music", "play_match")}`).then((msg) => { + setTimeout(() => { + msg.delete() + }, 4000); + }).catch((e) => {}); + player.destroy(); + } - try { - if (command.ownerOnly) { - if (message.author.id !== client.owner) { - return message.channel.send(`${client.i18n.get(language, "message", "owner_only")}`); + if (player) { + client.UpdateQueueMsg(player); + } + /// NORMAL MODE! + } else { + let PREFIX = client.prefix; + let LANGUAGE = client.i18n; + + const GuildPrefix = await GPrefix.findOne({ guild: message.guild.id }); + if(GuildPrefix && GuildPrefix.prefix) PREFIX = GuildPrefix.prefix; + + let guildModel = await GLang.findOne({ guild: message.guild.id }); + if(guildModel && guildModel.language) LANGUAGE = guildModel.language; + + const prefix = PREFIX; + const language = LANGUAGE; + + const mention = new RegExp(`^<@!?${client.user.id}>( |)$`); + + if(message.content.match(mention)) { + const embed = new EmbedBuilder() + .setColor(client.color) + .setDescription(client.i18n.get(language, "message", "my_prefix", { + prefix: prefix || client.prefix, + }), + ); + message.channel.send({ embeds: [embed] }) + }; + const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + const prefixRegex = new RegExp(`^(<@!?${client.user.id}>|${escapeRegex(prefix)})\\s*`); + if (!prefixRegex.test(message.content)) return; + const [ matchedPrefix ] = message.content.match(prefixRegex); + const args = message.content.slice(matchedPrefix.length).trim().split(/ +/g); + const cmd = args.shift().toLowerCase(); + + const command = client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd)); + if(!command) return; + if (!client.dev.includes(message.author.id) && client.dev.length > 0) { + + message.channel.send(`${client.i18n.get(language, "message", "dev_only")}`); + console.log(chalk.bgRedBright(`[INFOMATION] ${message.author.tag} trying request the command from ${message.guild.name}`)); + return; } + + console.log(chalk.magenta(`[COMMAND] ${command.config.name} used by ${message.author.tag} from ${message.guild.name}`)); + + if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.SendMessages)) return await message.author.dmChannel.send(`${client.i18n.get(language, "message", "no_perms")}`); + if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.ViewChannel)) return; + if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.EmbedLinks)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); + if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.Speak)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); + if(!message.guild.members.me.permissions.has(PermissionsBitField.Flags.Connect)) return await message.channel.send(`${client.i18n.get(language, "message", "no_perms")}`); + + if (command) { + try { + if (command.ownerOnly) { + if (message.author.id !== client.owner) { + return message.channel.send(`${client.i18n.get(language, "message", "owner_only")}`); + } + } + command.run(client, message, args, user, language, prefix); + } catch (error) { + console.log(error) + await message.channel.send(`${client.i18n.get(language, "message", "error")}`); + } + } } - command.run(client, message, args, user, language, prefix); - } catch (error) { - console.log(error) - await message.channel.send(`${client.i18n.get(language, "message", "error")}`); - } - } -} \ No newline at end of file + } \ No newline at end of file diff --git a/events/guild/voiceStateUpdate.js b/events/guild/voiceStateUpdate.js index 551bc13..0f9d377 100644 --- a/events/guild/voiceStateUpdate.js +++ b/events/guild/voiceStateUpdate.js @@ -7,7 +7,7 @@ module.exports = async (client, oldState, newState) => { if (!player) return; if (!newState.guild.members.cache.get(client.user.id).voice.channelId) player.destroy(); - if (newState.channelId && newState.channel.type == "GUILD_STAGE_VOICE" && newState.guild.members.me.voice.suppress) { + if (newState.channelId && newState.channel.type == 13 && newState.guild.members.me.voice.suppress) { if (newState.guild.members.me.permissions.has(PermissionsBitField.Flags.Speak) || (newState.channel && newState.channel.permissionsFor(nS.guild.members.me).has(PermissionsBitField.Flags.Speak))) { newState.guild.members.me.voice.setSuppressed(false); } @@ -19,13 +19,15 @@ module.exports = async (client, oldState, newState) => { if (player.twentyFourSeven) return; if (oldState.guild.members.cache.get(client.user.id).voice.channelId === oldState.channelId) { - if (oldState.guild.me.voice?.channel && oldState.guild.members.me.voice.channel.members.filter((m) => !m.user.bot).size === 0) { + if (oldState.guild.members.me.voice?.channel && oldState.guild.members.me.voice.channel.members.filter((m) => !m.user.bot).size === 0) { await delay(client.config.LEAVE_TIMEOUT); + const vcMembers = oldState.guild.members.me.voice.channel?.members.size; if (!vcMembers || vcMembers === 1) { - const newPlayer = client.manager?.players.get(newState.guild.id) - newPlayer ? player.destroy() : oldState.guild.members.me.voice.channel.leave(); + if(!player) return; + await player.destroy(); + await client.UpdateMusic(player); } } } diff --git a/events/player/playerMove.js b/events/player/playerMove.js index 2cb8624..e489147 100644 --- a/events/player/playerMove.js +++ b/events/player/playerMove.js @@ -16,9 +16,15 @@ module.exports = async (client, player, oldChannel, newChannel) => { const channel = guild.channels.cache.get(player.textChannel); if (!channel) return; - if(oldChannel === newChannel) return; - if(newChannel === null || !newChannel) { - if(!player) return; + /////////// Update Music Setup /////////// + + await client.UpdateMusic(player); + + ////////// End Update Music Setup ////////// + + if(oldChannel === newChannel) return; + if(newChannel === null || !newChannel) { + if(!player) return; return player.destroy(); } else { diff --git a/events/player/queueEnd.js b/events/player/queueEnd.js index 0dad150..2e3241b 100644 --- a/events/player/queueEnd.js +++ b/events/player/queueEnd.js @@ -1,5 +1,6 @@ const { EmbedBuilder } = require("discord.js"); const GLang = require("../../settings/models/Language.js"); +const Setup = require("../../settings/models/Setup.js"); module.exports = async (client, player) => { const channel = client.channels.cache.get(player.textChannel); @@ -19,10 +20,19 @@ module.exports = async (client, player) => { const { language } = guildModel; + /////////// Update Music Setup /////////// + + await client.UpdateMusic(player); + + const db = await Setup.findOne({ guild: channel.guild.id }); + if (db.enable) return player.destroy(); + + ////////// End Update Music Setup ////////// + const embed = new EmbedBuilder() .setColor(client.color) .setDescription(`${client.i18n.get(language, "player", "queue_end_desc")}`); await channel.send({ embeds: [embed] }); - return player.destroy(false); + return player.destroy(); } \ No newline at end of file diff --git a/events/player/trackError.js b/events/player/trackError.js index 9fda547..1549598 100644 --- a/events/player/trackError.js +++ b/events/player/trackError.js @@ -21,6 +21,12 @@ module.exports = async (client, player, track, payload) => { const { language } = guildModel; + /////////// Update Music Setup /////////// + + await client.UpdateMusic(player); + + ////////// End Update Music Setup ////////// + const embed = new EmbedBuilder() .setColor(client.color) .setDescription(`${client.i18n.get(language, "player", "error_desc")}`); diff --git a/events/player/trackStart.js b/events/player/trackStart.js index 9e8f452..79fd39b 100644 --- a/events/player/trackStart.js +++ b/events/player/trackStart.js @@ -2,14 +2,26 @@ const { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require(" const formatduration = require('../../structures/FormatDuration.js'); const GLang = require("../../settings/models/Language.js"); const GControl = require("../../settings/models/Control.js"); +const GSetup = require("../../settings/models/Setup.js"); module.exports = async (client, player, track, payload) => { - const GuildControl = await GControl.findOne({ guild: player.guild }); - try { - if (GuildControl.playerControl === 'enable'){ + if(!player) return; + + /////////// Update Music Setup /////////// + + await client.UpdateQueueMsg(player); + + /////////// Update Music Setup /////////// + const channel = client.channels.cache.get(player.textChannel); if (!channel) return; + const Control = await GControl.findOne({ guild: channel.guild.id }); + if (Control.enable) return; + + const Setup = await GSetup.findOne({ guild: channel.guild.id }); + if (Setup.enable) return; + let guildModel = await GLang.findOne({ guild: channel.guild.id, }); @@ -283,15 +295,4 @@ module.exports = async (client, player, track, payload) => { nplaying.edit({ embeds: [embeded], components: [] }) } }); - } else if(GuildControl.playerControl === 'disable'){ - null - } - } catch (err) { - const guildControl = new GControl({ guild: player.guild, playerControl: 'disable' }); - try { - guildControl.save() - } catch(err){ - console.log(err) - } - } } diff --git a/events/player/trackStuck.js b/events/player/trackStuck.js index 264ac44..6465f7a 100644 --- a/events/player/trackStuck.js +++ b/events/player/trackStuck.js @@ -18,6 +18,12 @@ module.exports = async (client, player, track, payload) => { const { language } = guildModel; + /////////// Update Music Setup /////////// + + await client.UpdateMusic(player); + + ////////// End Update Music Setup ////////// + const embed = new EmbedBuilder() .setColor(client.color) .setDescription(`${client.i18n.get(language, "player", "error_desc")}`); diff --git a/handlers/Player/loadPlayer.js b/handlers/Player/loadPlayer.js new file mode 100644 index 0000000..1d3deef --- /dev/null +++ b/handlers/Player/loadPlayer.js @@ -0,0 +1,13 @@ +const { readdirSync } = require("fs"); + +module.exports = async (client) => { + try { + readdirSync("./events/player/").forEach(file => { + const event = require(`../../events/player/${file}`); + let eventName = file.split(".")[0]; + client.manager.on(eventName, event.bind(null, client)); + }); + } catch (e) { + console.log(e); + } +}; diff --git a/handlers/Player/loadSetup.js b/handlers/Player/loadSetup.js new file mode 100644 index 0000000..66d435f --- /dev/null +++ b/handlers/Player/loadSetup.js @@ -0,0 +1,89 @@ +const { Client, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js"); +const Setup = require("../../settings/models/Setup.js"); +const Control = require("../../settings/models/Control.js"); + + /** + * + * @param {Client} client + */ + +module.exports = async (client) => { + + client.enSwitch = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setStyle(ButtonStyle.Success) + .setCustomId("spause") + .setEmoji("⏯"), + new ButtonBuilder() + .setStyle(ButtonStyle.Primary) + .setCustomId("sprevious") + .setEmoji("⬅"), + new ButtonBuilder() + .setStyle(ButtonStyle.Danger) + .setCustomId("sstop") + .setEmoji("⏹"), + new ButtonBuilder() + .setStyle(ButtonStyle.Primary) + .setCustomId("sskip") + .setEmoji("➡"), + new ButtonBuilder() + .setStyle(ButtonStyle.Success) + .setCustomId("sloop") + .setEmoji("🔄"), + ]); + + client.diSwitch = new ActionRowBuilder() + .addComponents([ + new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setCustomId("spause") + .setEmoji("⏯") + .setDisabled(true), + new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setCustomId("sprevious") + .setEmoji("⬅") + .setDisabled(true), + new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setCustomId("sstop") + .setEmoji("⏹") + .setDisabled(true), + new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setCustomId("sskip") + .setEmoji("➡") + .setDisabled(true), + new ButtonBuilder() + .setStyle(ButtonStyle.Secondary) + .setCustomId("sloop") + .setEmoji("🔄") + .setDisabled(true), + ]); + + client.createSetup = async function (guildId) { + const database = await Setup.findOne({ guild: guildId }); + if (!database) { + const newSetup = await new Setup({ + guild: guildId, + enable: false, + channel: "", + playmsg: "", + }); + await newSetup.save(); + } + } + + client.playerControl = async function (guildId) { + const database = await Control.findOne({ guild: guildId }); + if (!database) { + const newControl = await new Control({ + guild: guildId, + enable: false, + }); + await newControl.save(); + } + } + +}; \ No newline at end of file diff --git a/handlers/Player/loadUpdate.js b/handlers/Player/loadUpdate.js new file mode 100644 index 0000000..95bde90 --- /dev/null +++ b/handlers/Player/loadUpdate.js @@ -0,0 +1,115 @@ +const { Client, EmbedBuilder } = require("discord.js"); +const formatDuration = require("../../structures/FormatDuration.js"); +const { Player } = require("erela.js"); +const GLang = require("../../settings/models/Language.js"); +const Setup = require("../../settings/models/Setup.js"); + + /** + * + * @param {Client} client + */ +module.exports = async (client) => { + /** + * + * @param {Player} player + */ + client.UpdateQueueMsg = async function (player) { + let data = await Setup.findOne({ guild: player.guild }); + if (data.enable === false) return; + + let channel = await client.channels.cache.get(data.channel); + if (!channel) return; + + let playMsg = await channel.messages.fetch(data.playmsg, { cache: false, force: true }); + if (!playMsg) return; + + let guildModel = await GLang.findOne({ guild: player.guild }); + if (!guildModel) { guildModel = await GLang.create({ + guild: player.guild, + language: "en", + }); + } + + const { language } = guildModel; + + const songStrings = []; + const queuedSongs = player.queue.map((song, i) => `${client.i18n.get(language, "setup", "setup_content_queue", { + index: i + 1, + title: song.title, + duration: formatDuration(song.duration), + request: song.requester.tag, + })}`); + + await songStrings.push(...queuedSongs); + + const Str = songStrings.slice(0, 10).join('\n'); + + let cSong = player.queue.current; + let qDuration = `${formatDuration(player.queue.duration)}`; + + let embed = new EmbedBuilder() + .setAuthor({ name: `${client.i18n.get(language, "setup", "setup_author")}`, iconURL: `${client.i18n.get(language, "setup", "setup_author_icon")}` }) + .setDescription(`${client.i18n.get(language, "setup", "setup_desc", { + title: cSong.title, + url: cSong.uri, + duration: formatDuration(cSong.duration), + request: cSong.requester, + })}`) // [${cSong.title}](${cSong.uri}) \`[${formatDuration(cSong.duration)}]\` • ${cSong.requester} + .setColor(client.color) + .setImage(`https://img.youtube.com/vi/${cSong.identifier}/sddefault.jpg`) + .setFooter({ text: `${client.i18n.get(language, "setup", "setup_footer", { + songs: player.queue.length, + volume: player.volume, + duration: qDuration, + })}` }) //${player.queue.length} • Song's in Queue | Volume • ${player.volume}% | ${qDuration} • Total Duration + + return await playMsg.edit({ + content: `${client.i18n.get(language, "setup", "setup_content")}\n${Str == '' ? `${client.i18n.get(language, "setup", "setup_content_empty")}` : '\n' + Str}`, + embeds: [embed], + components: [client.enSwitch] + }).catch((e) => {}); + }; + + /** + * + * @param {Player} player + */ + client.UpdateMusic = async function (player) { + let data = await Setup.findOne({ guild: player.guild }); + if (data.enable === false) return; + + let channel = await client.channels.cache.get(data.channel); + if (!channel) return; + + let playMsg = await channel.messages.fetch(data.playmsg, { cache: true, force: true }); + if (!playMsg) return; + + let guildModel = await GLang.findOne({ guild: player.guild }); + if (!guildModel) { guildModel = await GLang.create({ + guild: player.guild, + language: "en", + }); + } + + const { language } = guildModel; + + const queueMsg = `${client.i18n.get(language, "setup", "setup_queuemsg")}`; + + const playEmbed = new EmbedBuilder() + .setColor(client.color) + .setAuthor({ name: `${client.i18n.get(language, "setup", "setup_playembed_author")}` }) + .setImage(`${client.i18n.get(language, "setup", "setup_playembed_image")}`) + .setDescription(`${client.i18n.get(language, "setup", "setup_playembed_desc", { + clientId: client.user.id, + })}`) + .setFooter({ text: `${client.i18n.get(language, "setup", "setup_playembed_footer", { + prefix: client.prefix, + })}` }); + + return await playMsg.edit({ + content: `${queueMsg}`, + embeds: [playEmbed], + components: [client.diSwitch] + }).catch((e) => {}); + }; +}; \ No newline at end of file diff --git a/handlers/loadDatabase.js b/handlers/loadDatabase.js index a03fd40..d4005d6 100644 --- a/handlers/loadDatabase.js +++ b/handlers/loadDatabase.js @@ -6,7 +6,7 @@ module.exports = async () => { try { await mongoose.connect(MONGO_URI, { useNewUrlParser: true, - useUnifiedTopology: true, + useUnifiedTopology: true }); console.log(white('[') + green('INFO') + white('] ') + green('Database ') + white('Events') + green(' Loaded!')); } catch (error) { diff --git a/handlers/loadPlayer.js b/handlers/loadPlayer.js index 6a48ab0..209e1ff 100644 --- a/handlers/loadPlayer.js +++ b/handlers/loadPlayer.js @@ -1,15 +1,8 @@ const { white, green } = require("chalk"); -const { readdirSync } = require("fs"); -module.exports = async (client) => { - try { - readdirSync("./events/player/").forEach(file => { - const event = require(`../events/player/${file}`); - let eventName = file.split(".")[0]; - client.manager.on(eventName, event.bind(null, client)); - }); - } catch (e) { - console.log(e); - } +module.exports = (client) => { + require("./Player/loadPlayer.js")(client); + require("./Player/loadSetup.js")(client); + require("./Player/loadUpdate.js")(client); console.log(white('[') + green('INFO') + white('] ') + green('Player ') + white('Events') + green(' Loaded!')); -}; +}; \ No newline at end of file diff --git a/languages/en/setup.yaml b/languages/en/setup.yaml new file mode 100644 index 0000000..57db41f --- /dev/null +++ b/languages/en/setup.yaml @@ -0,0 +1,23 @@ +##### Setup command ##### +setup_topic: "⏯ *Pause/Resume the song.*\n⬅ *Previous the song.*\n⏹ *Stop the song.*\n➡ *Skip the song.*\n🔁 *Loop/Unloop the song.*" +setup_msg: "*`Succesfully Setup Music System in`* %{channel}\n```Warning: I disable all commands for perfermance! if you want to use normal please delete song-request channel```" +setup_enable: "*`Already have setup channel song request can't use this command.`*" + +##### Setup Handler ##### +setup_queuemsg: "**__Queue list:__**\nJoin a voice channel and queue songs by name or url in here." + +setup_playembed_author: "No song playing currently." +setup_playembed_image: "https://images2.alphacoders.com/110/thumb-1920-1109233.jpg" +setup_playembed_desc: ">>> [Invite](https://discord.com/api/oauth2/authorize?client_id=%{clientId}&permissions=2184310032&scope=bot%20applications.commands) | [Support](https://discord.gg/SNG3dh3MbR) | [Website](https://adivise.github.io/Stylish/)" +setup_playembed_footer: "Prefix is: %{prefix}" + +##### Setup Update Handler ##### + +setup_author: "Starting playing..." +setup_author_icon: "https://cdn.discordapp.com/emojis/741605543046807626.gif" +setup_desc: "[%{title}](%{url}) `[%{duration}]` • %{request}" +setup_footer: "%{songs} • Song's in Queue | Volume • %{volume}% | %{duration} • Total Duration" + +setup_content: "**__Queue list:__**" +setup_content_queue: "*`%{index} • %{title} • [%{duration}]`* • %{request}" +setup_content_empty: "Join a voice channel and queue songs by name or url in here." \ No newline at end of file diff --git a/languages/en/utilities.yaml b/languages/en/utilities.yaml index 86f68dd..0a89409 100644 --- a/languages/en/utilities.yaml +++ b/languages/en/utilities.yaml @@ -26,8 +26,4 @@ help_timeout: "```Help Menu is time out please try %{prefix}help to see again.`` ##### Player Control Toggle command ##### control_perm: "You need the `MANAGE_GUILD` permission to use this command." -control_arg: "**Please specify a mode! `(enable or disable)`**" -control_invalid: "**The mode can't be another word! Only enable or disable**" -control_set: "`🔧` | *Player control mode has been set to:* `%{playerControl}`" -control_change: "`🔧` | *Player control mode has been change to:* `%{playerControl}`" -control_error: "An error occured while setting the player control mode!" \ No newline at end of file +control_set: "`🔧` | *Player control is:* `%{playerControl}`" \ No newline at end of file diff --git a/languages/th/setup.yaml b/languages/th/setup.yaml new file mode 100644 index 0000000..06e6f89 --- /dev/null +++ b/languages/th/setup.yaml @@ -0,0 +1,24 @@ +##### Setup command ##### +setup_topic: "⏯ *หยุดชั่วคราว/ดำเนินการต่อ ของเพลง*\n⬅ *กลับไปเพลงก่อนหน้า*\n⏹ *ปิดเพลง/เอาบอทออกจากห้อง*\n➡ *ข้ามไปเพลงต่อไป*\n🔁 *เล่นเพลงซ้ำ/ยกเลิกเล่นเพลงซ้ำ*" +setup_msg: "*`สร้างระบบ แชทเพลง สำเร็จ`* %{channel}\n```คำเตือน: ห้ามลบอะไรก็ตามแต่ที่บอทได้ส่งทิ้งไว้! (เพื่อให้บอทยังทำงานได้! ถ้าลบไปแล้วให้สร้างใหม่)```" +setup_deleted: "*`ลบระบบ แชทเพลง ออกจากฐานข้อมูลสำเร็จ`* (อย่าลืมลบห้องด้วย)" +setup_enable: "มีระบบ แชทเพลง อยู่ไม่สามารถใช้งาน คำสั่งนี้ได้" + +##### Setup Handler ##### +setup_queuemsg: "**__คิวทั้งหมด:__**\nเข้าห้องพูดคุยแล้วเพิ่มเพลงโดย ใช้ชื่อหรือลิ้งเพลง ในห้องนี้" + +setup_playembed_author: "ไม่มีเพลง เล่นอยู่ ในปัจจุบัน" +setup_playembed_image: "https://images2.alphacoders.com/110/thumb-1920-1109233.jpg" +setup_playembed_desc: ">>> [Invite](https://discord.com/api/oauth2/authorize?client_id=%{clientId}&permissions=2184310032&scope=bot%20applications.commands) | [Support](https://discord.gg/SNG3dh3MbR) | [Website](https://adivise.github.io/Stylish/)" +setup_playembed_footer: "Prefix is: %{prefix}" + +##### Setup Update Handler ##### + +setup_author: "กำลังเล่น เพลง..." +setup_author_icon: "https://cdn.discordapp.com/emojis/741605543046807626.gif" +setup_desc: "[%{title}](%{url}) `[%{duration}]` • %{request}" +setup_footer: "%{songs} • เพลงในคิว | ระดับเสียง • %{volume}% | ระยะเวลาทั้งหมด • %{duration}" + +setup_content: "**__คิวทั้งหมด:__**" +setup_content_queue: "*`%{index} • %{title} • [%{duration}]`* • %{request}" +setup_content_empty: "เข้าห้องพูดคุยแล้วเพิ่มเพลงโดย ใช้ชื่อหรือลิ้งเพลง ในห้องนี้" \ No newline at end of file diff --git a/languages/th/utilities.yaml b/languages/th/utilities.yaml index 68255a7..469879c 100644 --- a/languages/th/utilities.yaml +++ b/languages/th/utilities.yaml @@ -22,4 +22,8 @@ restart_msg: "`🤖` | *บอทได้ถูก:* `ปิดตัวลง help_desc: "โปรดเลือกเมนูหมวดหมู่!" help_category_desc: "เลือก %{category} เพื่อดูคำสั่งทั้งหมด" help_category: "%{category}" -help_timeout: "```เมนูช่วย เหลือหมดเวลาแล้ว พิมพ์ %{prefix}help เพื่อดูอีกครั้ง```" \ No newline at end of file +help_timeout: "```เมนูช่วย เหลือหมดเวลาแล้ว พิมพ์ %{prefix}help เพื่อดูอีกครั้ง```" + +##### Player Control Toggle command ##### +control_perm: "คุณต้องมีความสามารถ `MANAGE_GUILD` เพื่อใช้คำสั่ง" +control_set: "`🔧` | *Player control is:* `%{playerControl}`" \ No newline at end of file diff --git a/settings/images/banner.png b/settings/images/banner.png new file mode 100644 index 0000000..7e63b54 Binary files /dev/null and b/settings/images/banner.png differ diff --git a/settings/models/Control.js b/settings/models/Control.js index 429a2c0..3607310 100644 --- a/settings/models/Control.js +++ b/settings/models/Control.js @@ -1,16 +1,8 @@ const mongoose = require('mongoose'); const CreateControl = mongoose.Schema({ - guild: { - type: String, - required: true, - unique: true, - }, - playerControl: { - type: String, - default: "enable", - required: true, - } + guild: String, + enable: Boolean }); module.exports = mongoose.model('Control', CreateControl); \ No newline at end of file diff --git a/settings/models/Setup.js b/settings/models/Setup.js new file mode 100644 index 0000000..34355f5 --- /dev/null +++ b/settings/models/Setup.js @@ -0,0 +1,11 @@ +const mongoose = require('mongoose'); + +const CreateSetup = mongoose.Schema({ + guild: String, + enable: Boolean, + channel: String, + playmsg: String, + queuemsg: String, +}); + +module.exports = mongoose.model('Setup', CreateSetup); \ No newline at end of file