diff --git a/package-lock.json b/package-lock.json index 079efd4..0eafcbb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "eximiabots-radiox", - "version": "0.3.3", + "version": "0.3.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "eximiabots-radiox", - "version": "0.3.3", + "version": "0.3.4", "license": "MIT", "dependencies": { "@discordjs/builders": "^0.6.0", @@ -1228,9 +1228,9 @@ } }, "node_modules/deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "node_modules/defer-to-connect": { @@ -4788,9 +4788,9 @@ "dev": true }, "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, "defer-to-connect": { diff --git a/package.json b/package.json index f37e0b7..27aee2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eximiabots-radiox", - "version": "0.3.3", + "version": "0.3.4", "description": "Internet Radio to your Discord guild", "main": "index.js", "scripts": { diff --git a/src/Client.ts b/src/Client.ts index a991ab7..f1ebe9d 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -39,6 +39,9 @@ class RadioClient extends Client { this.funcs.statisticsUpdate = require("./client/funcs/statisticsUpdate.js"); this.funcs.saveState = require("./client/funcs/saveState.js"); this.funcs.loadState = require("./client/funcs/loadState.js"); + this.funcs.searchStation = require("./client/funcs/searchStation.js"); + this.funcs.play = require("./client/funcs/play.js"); + this.funcs.listStations = require("./client/funcs/listStations.js"); console.log('RadioX ' + this.config.version); console.log('Internet Radio to your Discord guild'); diff --git a/src/client/commands.js b/src/client/commands.js index 078a8ee..a1a8a14 100644 --- a/src/client/commands.js +++ b/src/client/commands.js @@ -44,16 +44,17 @@ module.exports = { try { await rest.put( Routes.applicationGuildCommands(client.user.id, guild.id), - { body: commands }, + { body: commands } ); + client.funcs.logger('Slash Commands', 'Guild Applications – Successful' + "\n" + guild.id + " / " + guild.name); } catch (DiscordAPIError) { - + client.funcs.logger('Slash Commands', 'Guild Applications – Failed' + "\n" + guild.id + " / " + guild.name); } }); } else { await rest.put( Routes.applicationCommands(client.user.id), - { body: commands }, + { body: commands } ); } diff --git a/src/client/commands/bug.js b/src/client/commands/bug.js index 11a19c0..a87a638 100644 --- a/src/client/commands/bug.js +++ b/src/client/commands/bug.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'bug', - alias: 'none', - usage: '', description: 'Report a bug', permission: 'none', category: 'info', - async execute(interaction, client, Discord, command) { + async execute(interaction, client) { let message = {}; message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username); diff --git a/src/client/commands/help.js b/src/client/commands/help.js index 016b267..2b7da61 100644 --- a/src/client/commands/help.js +++ b/src/client/commands/help.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'help', - alias: 'h', - usage: '', description: 'Get help using bot', permission: 'none', category: 'info', - execute(interaction, client, Discord, command) { + execute(interaction, client) { let message = {}; const categories = []; diff --git a/src/client/commands/invite.js b/src/client/commands/invite.js index aa65a41..38db87a 100644 --- a/src/client/commands/invite.js +++ b/src/client/commands/invite.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'invite', - alias: 'i', - usage: '', description: 'Invite Bot', permission: 'none', category: 'info', - execute(interaction, client, Discord, command) { + execute(interaction, client) { let message = {}; message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username); const embed = new Discord.MessageEmbed() diff --git a/src/client/commands/list.js b/src/client/commands/list.js index 0caa10b..b0ce3fd 100644 --- a/src/client/commands/list.js +++ b/src/client/commands/list.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'list', - alias: 'l', - usage: '', description: 'List radio stations', permission: 'none', category: 'radio', - execute(interaction, client, Discord, command) { + execute(interaction, client) { let message = {}; if(!client.stations) { message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); @@ -15,49 +15,7 @@ module.exports = { const radio = client.radio.get(interaction.guild.id); if(radio){ - let menu = []; - - let stations = new Array(); - - let options = new Array(); - options[1] = new Array(); - options[2] = new Array(); - - stations[1] = client.stations.slice(0,24).forEach(station => { - station = { - label: station.name, - description: station.owner, - value: station.name - }; - options[1].push(station); - }); - - stations[2] = client.stations.slice(25).forEach(station => { - station = { - label: station.name, - description: station.owner, - value: station.name - }; - options[2].push(station); - }); - - menu = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageSelectMenu() - .setCustomId('play') - .setPlaceholder('Change station') - .addOptions(options[1]) - .addOptions(options[2]) - ); - - stations = null; - options = null; - - interaction.reply({ - content: '**Select station:**', - components: [menu], - ephemeral: true - }); + client.funcs.listStations(client, interaction); } else { let stations = `${client.stations.map(s => `**#** ${s.name}`).join('\n')}` const hashs = stations.split('**#**').length; diff --git a/src/client/commands/maintenance.js b/src/client/commands/maintenance.js index 08a52fc..9913f4d 100644 --- a/src/client/commands/maintenance.js +++ b/src/client/commands/maintenance.js @@ -1,52 +1,62 @@ +import Discord from "discord.js"; + module.exports = { name: 'maintenance', - alias: 'm', - usage: '', description: 'Bot Maintenance', permission: 'none', category: 'info', - execute(interaction, client, Discord, command) { + execute(interaction, client) { let message = {}; if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply(client.messageEmojis["error"] + client.messages.notAllowed); - if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); - return interaction.reply(client.messageEmojis["error"] + message.errorToGetPlaylist); - } - - let currentRadios = client.radio.keys(); - let radio = currentRadios.next(); - let stoppedRadios = ""; + if(client.config.version.includes("-dev")){ + interaction.reply({ + content: "Maintenance Initiated", + ephemeral: true + }); - client.user.setStatus('dnd'); - - while (!radio.done) { - let currentRadio = client.radio.get(radio.value); - currentRadio.guild = client.datastore.getEntry(radio.value).guild; - - if(currentRadio){ - client.funcs.statisticsUpdate(client, currentRadio.guild, currentRadio); - currentRadio.connection?.destroy(); - currentRadio.audioPlayer?.stop(); - currentRadio.message?.delete(); - client.radio.delete(radio.value); - stoppedRadios += "-" + radio.value + ": " + currentRadio.guild.name + "\n"; + process.emit('SIGINT'); + } else { + if(!client.stations) { + message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); + return interaction.reply(client.messageEmojis["error"] + message.errorToGetPlaylist); } - radio = currentRadios.next(); + + let currentRadios = client.radio.keys(); + let radio = currentRadios.next(); + let stoppedRadios = ""; + + client.user.setStatus('dnd'); + + while (!radio.done) { + let currentRadio = client.radio.get(radio.value); + currentRadio.guild = client.datastore.getEntry(radio.value).guild; + + if(currentRadio){ + client.funcs.statisticsUpdate(client, currentRadio.guild, currentRadio); + currentRadio.connection?.destroy(); + currentRadio.audioPlayer?.stop(); + currentRadio.message?.delete(); + client.radio.delete(radio.value); + stoppedRadios += "-" + radio.value + ": " + currentRadio.guild.name + "\n"; + } + radio = currentRadios.next(); + } + + const embed = new Discord.MessageEmbed() + .setTitle(client.messages.maintenanceTitle) + .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["maintenance"].replace(/[^0-9]+/g, '')) + .setColor(client.config.embedColor) + .setDescription("Stopped all radios" + "\n" + stoppedRadios) + .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') + .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); + + interaction.reply({ + embeds: [embed], + ephemeral: true + }); } - const embed = new Discord.MessageEmbed() - .setTitle(client.messages.maintenanceTitle) - .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["maintenance"].replace(/[^0-9]+/g, '')) - .setColor(client.config.embedColor) - .setDescription("Stopped all radios" + "\n" + stoppedRadios) - .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') - .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); - - interaction.reply({ - embeds: [embed], - ephemeral: true - }); } }; \ No newline at end of file diff --git a/src/client/commands/next.js b/src/client/commands/next.js new file mode 100644 index 0000000..56747d3 --- /dev/null +++ b/src/client/commands/next.js @@ -0,0 +1,35 @@ +module.exports = { + name: 'next', + description: 'Next Station', + permission: 'none', + category: 'radio', + async execute(interaction, client, command) { + if (client.funcs.check(client, interaction, command)) { + const radio = client.radio.get(interaction.guild.id); + + let index = client.stations.findIndex(station => station.name == radio.station.name) + 1; + if(index == client.stations.length) index = 0; + + let station = client.stations[index]; + + if(!station) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.noSearchResults, + ephemeral: true + }); + + interaction.deferUpdate(); + + let url = station.stream[station.stream.default]; + + client.funcs.statisticsUpdate(client, interaction.guild, radio); + radio.audioPlayer.stop(); + + let date = new Date(); + radio.station = station; + radio.textChannel = interaction.channel; + radio.startTime = date.getTime(); + client.funcs.play(null, interaction.guild, client, url); + + } + } +} \ No newline at end of file diff --git a/src/client/commands/nowplaying.js b/src/client/commands/nowplaying.js index 7a59e38..e6b2e62 100644 --- a/src/client/commands/nowplaying.js +++ b/src/client/commands/nowplaying.js @@ -1,45 +1,36 @@ +import Discord from "discord.js"; + module.exports = { name: 'nowplaying', - alias: 'np', - usage: '', description: 'Current Radio Station', permission: 'none', category: 'radio', - async execute(interaction, client, Discord, command) { - let message = {}; - const radio = client.radio.get(interaction.guild.id); - if (!radio) return interaction.reply({ - content: 'There is nothing playing.', - ephemeral: true - }); - if(!client.stations) { - message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); - return interaction.reply({ - content: client.messageEmojis["error"] + message.errorToGetPlaylist, + async execute(interaction, client, command) { + if (client.funcs.check(client, interaction, command)) { + let message = {}; + const radio = client.radio.get(interaction.guild.id); + + let date = new Date(); + radio.currentTime = date.getTime(); + radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime); + const completed = (radio.playTime); + + message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); + message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.owner); + message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", client.funcs.msToTime(completed)); + + const embed = new Discord.MessageEmbed() + .setTitle(client.messages.nowplayingTitle) + .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) + .setColor(client.config.embedColor) + .setDescription(message.nowplayingDescription) + .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') + .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); + + interaction.reply({ + embeds: [embed], ephemeral: true }); } - - let date = new Date(); - radio.currentTime = date.getTime(); - radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime); - const completed = (radio.playTime); - - message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); - message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.owner); - message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", client.funcs.msToTime(completed)); - - const embed = new Discord.MessageEmbed() - .setTitle(client.messages.nowplayingTitle) - .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor) - .setDescription(message.nowplayingDescription) - .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') - .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); - - interaction.reply({ - embeds: [embed], - ephemeral: true - }); } }; \ No newline at end of file diff --git a/src/client/commands/play.js b/src/client/commands/play.js index b022bbf..d8960fe 100644 --- a/src/client/commands/play.js +++ b/src/client/commands/play.js @@ -1,13 +1,11 @@ const { createAudioPlayer, - createAudioResource, getVoiceConnection, joinVoiceChannel } = require("@discordjs/voice"); module.exports = { name: "play", - alias: "p", usage: "", description: "Play radio", options: [ @@ -15,7 +13,7 @@ module.exports = { ], permission: "none", category: "radio", - async execute(interaction, client, Discord, command) { + async execute(interaction, client) { let message = {}; let query = interaction.options?.getString("query") ?? interaction.values?.[0]; if(!query){ @@ -24,47 +22,7 @@ module.exports = { return interaction.reply(client.messageEmojis["error"] + message.errorToGetPlaylist); } - let stations = new Array(); - - let options = new Array(); - options[1] = new Array(); - options[2] = new Array(); - - stations[1] = client.stations.slice(0,24).forEach(station => { - station = { - label: station.name, - description: station.owner, - value: station.name - }; - options[1].push(station); - }); - - stations[2] = client.stations.slice(25).forEach(station => { - station = { - label: station.name, - description: station.owner, - value: station.name - }; - options[2].push(station); - }); - - const menu = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageSelectMenu() - .setCustomId('play') - .setPlaceholder('Nothing selected') - .addOptions(options[1]) - .addOptions(options[2]) - ); - - stations = null; - options = null; - - return interaction.reply({ - content: '**Select station:**', - components: [menu], - ephemeral: true - }); + client.funcs.listStations(client, interaction); } let url = query ? query.replace(/<(.+)>/g, "$1") : ""; const radio = client.radio.get(interaction.guild.id); @@ -123,7 +81,7 @@ module.exports = { content: client.messageEmojis["error"] + client.messages.tooShortSearch, ephemeral: true }); - const sstation = await searchStation(query, client); + const sstation = await client.funcs.searchStation(query, client); if (!sstation) return interaction.reply({ content: client.messageEmojis["error"] + client.messages.noSearchResults, @@ -141,7 +99,7 @@ module.exports = { radio.station = station; radio.textChannel = interaction.channel; radio.startTime = date.getTime(); - play(interaction, interaction.guild, client, url, Discord); + client.funcs.play(interaction, interaction.guild, client, url); return; } @@ -167,7 +125,7 @@ module.exports = { construct.connection = connection; let date = new Date(); construct.startTime = date.getTime(); - play(interaction, interaction.guild, client, url, Discord); + client.funcs.play(interaction, interaction.guild, client, url); client.datastore.checkEntry(interaction.guild.id); construct.currentGuild = client.datastore.getEntry(interaction.guild.id); @@ -184,158 +142,4 @@ module.exports = { return interaction.reply(client.messageEmojis["error"] + `An error occured: ${error}`); } } -}; - -async function play(interaction, guild, client, url, Discord) { - let message = {}; - const radio = client.radio.get(guild.id); - const resource = createAudioResource(url); - radio.connection.subscribe(radio.audioPlayer); - radio.audioPlayer.play(resource); - resource.playStream - .on("readable", () => { - client.funcs.logger('Radio', 'Stream started' + " / " + guild.id + " / " + radio.station.name); - }) - .on("finish", () => { - client.funcs.logger('Radio', 'Stream finished' + " / " + guild.id); - client.funcs.statisticsUpdate(client, guild, radio); - radio.connection?.destroy(); - radio.audioPlayer?.stop(); - client.radio.delete(guild.id); - return; - }) - .on("error", error => { - client.funcs.logger('Radio', 'Stream errored'); - console.error(error); - radio.connection?.destroy(); - radio.audioPlayer?.stop(); - client.radio.delete(guild.id); - return interaction.reply(client.messages.errorPlaying); - }); - - message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); - message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.owner); - message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("Owner: ", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - - const embed = new Discord.MessageEmbed() - .setTitle(client.user.username) - .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor) - .addField(client.messages.nowplayingTitle, message.nowplayingDescription, true) - .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') - .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); - - const buttons = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setCustomId('list') - .setEmoji(client.messageEmojis["list"]) - .setStyle('SECONDARY') - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('prev') - .setEmoji(client.messageEmojis["prev"]) - .setStyle('SECONDARY') - .setDisabled(true) - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('stop') - .setEmoji(client.messageEmojis["stop"]) - .setStyle('SECONDARY') - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('next') - .setEmoji(client.messageEmojis["next"]) - .setStyle('SECONDARY') - .setDisabled(true) - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('statistics') - .setEmoji(client.messageEmojis["statistics"]) - .setStyle('SECONDARY') - ); - - if(!radio.message){ - radio.message = await radio.textChannel.send({ embeds: [embed], components: [buttons] }); - } else { - radio.message.edit({ embeds: [embed], components: [buttons] }); - } - - message.play = client.messages.play.replace("%radio.station.name%", radio.station.name); - - interaction.reply({ - content: client.messageEmojis["play"] + message.play, - ephemeral: true - }); - -} - -function searchStation(key, client) { - if (client.stations === null) return false; - let foundStations = []; - if (!key) return false; - if (key == "radio") return false; - - client.stations - .filter( - x => x.name.toUpperCase().includes(key.toUpperCase()) || x === key - ) - .forEach(x => - foundStations.push({ station: x, name: x.name, probability: 100 }) - ); - - if (key.startsWith("radio ")) key = key.slice(6); - const probabilityIncrement = 100 / key.split(" ").length / 2; - for (let i = 0; i < key.split(" ").length; i++) { - client.stations - .filter( - x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key - ) - .forEach(x => - foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }) - ); - } - if (foundStations.length === 0) return false; - for (let i = 0; i < foundStations.length; i++) { - for (let j = 0; j < foundStations.length; j++) { - if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1); - } - } - for (let i = 0; i < foundStations.length; i++) { - if (foundStations[i].name.length > key.length) { - foundStations[i].probability -= - (foundStations[i].name.split(" ").length - key.split(" ").length) * - (probabilityIncrement * 0.5); - } else if (foundStations[i].name.length === key.length) { - foundStations[i].probability += probabilityIncrement * 0.9; - } - - for (let j = 0; j < key.split(" ").length; j++) { - if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) { - foundStations[i].probability -= probabilityIncrement * 0.5; - } - } - } - let highestProbabilityStation; - for (let i = 0; i < foundStations.length; i++) { - if ( - !highestProbabilityStation || - highestProbabilityStation.probability < foundStations[i].probability - ) - highestProbabilityStation = foundStations[i]; - if ( - highestProbabilityStation && - highestProbabilityStation.probability === foundStations[i].probability - ) { - highestProbabilityStation = foundStations[i].station; - } - } - return highestProbabilityStation; -} +}; \ No newline at end of file diff --git a/src/client/commands/prev.js b/src/client/commands/prev.js new file mode 100644 index 0000000..eb7e572 --- /dev/null +++ b/src/client/commands/prev.js @@ -0,0 +1,35 @@ +module.exports = { + name: 'prev', + description: 'Previous Station', + permission: 'none', + category: 'radio', + async execute(interaction, client, command) { + if (client.funcs.check(client, interaction, command)) { + const radio = client.radio.get(interaction.guild.id); + + let index = client.stations.findIndex(station => station.name == radio.station.name) - 1; + if(index == -1) index = client.stations.length - 1; + + let station = client.stations[index]; + + if(!station) return interaction.reply({ + content: client.messageEmojis["error"] + client.messages.noSearchResults, + ephemeral: true + }); + + interaction.deferUpdate(); + + let url = station.stream[station.stream.default]; + + client.funcs.statisticsUpdate(client, interaction.guild, radio); + radio.audioPlayer.stop(); + + let date = new Date(); + radio.station = station; + radio.textChannel = interaction.channel; + radio.startTime = date.getTime(); + client.funcs.play(null, interaction.guild, client, url); + + } + } +} \ No newline at end of file diff --git a/src/client/commands/statistics.js b/src/client/commands/statistics.js index dcd81a5..b96ef04 100644 --- a/src/client/commands/statistics.js +++ b/src/client/commands/statistics.js @@ -1,14 +1,15 @@ +import Discord from "discord.js"; + module.exports = { name: 'statistics', - alias: 'stats', - usage: '', description: 'Show statistics', permission: 'none', category: 'info', - execute(interaction, client, Discord, command) { + execute(interaction, client) { let message = {}; let stations = client.stations; let currentGuild = client.datastore.getEntry(interaction.guild.id); + let global = client.datastore.getEntry("global"); let statistics = ""; if(!client.stations) { @@ -21,9 +22,13 @@ module.exports = { } else { Object.keys(stations).forEach(function(station) { if(currentGuild.statistics[stations[station].name] && currentGuild.statistics[stations[station].name].time && parseInt(currentGuild.statistics[stations[station].name].time) > 0 && currentGuild.statistics[stations[station].name].used && parseInt(currentGuild.statistics[stations[station].name].used) > 0){ - statistics += `**${parseInt(station) + 1}** ` + stations[station].name + " \n"; - statistics += "Time: " + client.funcs.msToTime(currentGuild.statistics[stations[station].name].time) + "\n"; - statistics += "Used: " + currentGuild.statistics[stations[station].name].used + "\n"; + statistics += `**${parseInt(station) + 1}. ` + stations[station].name + "** \n"; + if(global && global.statistics[stations[station].name] && global.statistics[stations[station].name].time && parseInt(global.statistics[stations[station].name].time) > 0 && global.statistics[stations[station].name].used && parseInt(global.statistics[stations[station].name].used) > 0){ + statistics += "Guild – Time: " + client.funcs.msToTime(currentGuild.statistics[stations[station].name].time) + " (" + ((currentGuild.statistics[stations[station].name].time / global.statistics[stations[station].name].time) * 100) + "%" + ")" + " / " + "Used: " + currentGuild.statistics[stations[station].name].used + " (" + ((currentGuild.statistics[stations[station].name].used / global.statistics[stations[station].name].used) * 100) + "%" + ")" + "\n"; + statistics += "Global – Time: " + client.funcs.msToTime(global.statistics[stations[station].name].time) + " / " + "Used: " + global.statistics[stations[station].name].used + "\n\n"; + } else { + statistics += "Time: " + client.funcs.msToTime(currentGuild.statistics[stations[station].name].time) + " / " + "Used: " + currentGuild.statistics[stations[station].name].used + "\n\n"; + } } }); } diff --git a/src/client/commands/status.js b/src/client/commands/status.js index 6d9cf63..6a3ce7b 100644 --- a/src/client/commands/status.js +++ b/src/client/commands/status.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'status', - alias: 'st', - usage: '', description: 'Bot Status', permission: 'none', category: 'info', - async execute(interaction, client, Discord, command) { + async execute(interaction, client) { let message = {}; message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username); diff --git a/src/client/commands/stop.js b/src/client/commands/stop.js index 19d4c56..9c53249 100644 --- a/src/client/commands/stop.js +++ b/src/client/commands/stop.js @@ -1,11 +1,11 @@ +import Discord from "discord.js"; + module.exports = { name: 'stop', description: 'Stop radio', - alias: 's', - usage: '', permission: 'none', category: 'radio', - async execute(interaction, client, Discord, command) { + async execute(interaction, client, command) { const radio = client.radio.get(interaction.guild.id); if (client.funcs.check(client, interaction, command)) { client.funcs.statisticsUpdate(client, interaction.guild, radio); diff --git a/src/client/events/SIGINT.js b/src/client/events/SIGINT.js index 59495c7..52ed167 100644 --- a/src/client/events/SIGINT.js +++ b/src/client/events/SIGINT.js @@ -35,7 +35,7 @@ module.exports = { radio = currentRadios.next(); } - const rest = new REST({ version: '9' }).setToken(token); + /*const rest = new REST({ version: '9' }).setToken(token); if(version.includes("-dev")){ await rest.put( Routes.applicationCommands(client.user.id), @@ -47,13 +47,13 @@ module.exports = { try { await rest.put( Routes.applicationGuildCommands(client.user.id, guild.id), - { body: [] }, + { body: [] } ); } catch (DiscordAPIError) { } }); - } + }*/ setInterval(() => { if(radio.done){ diff --git a/src/client/events/interactionCreate.js b/src/client/events/interactionCreate.js index 67d2666..64e06b9 100644 --- a/src/client/events/interactionCreate.js +++ b/src/client/events/interactionCreate.js @@ -1,11 +1,9 @@ -import Discord from "discord.js"; - module.exports = { name: 'interactionCreate', async execute(client, interaction) { const permissions = interaction.channel.permissionsFor(interaction.client.user); - if (!permissions.has('EMBED_LINKS')) return interaction.send(client.messages.noPermsEmbed); + if (!permissions.has('EMBED_LINKS')) return interaction.reply(client.messages.noPermsEmbed); if(interaction.isCommand()){ const commandName = interaction.commandName; @@ -13,7 +11,7 @@ module.exports = { if (!command) return; try { - command.execute(interaction, client, Discord, command); + command.execute(interaction, client); } catch (error) { interaction.reply({ content: client.messages.runningCommandFailed, @@ -27,7 +25,7 @@ module.exports = { if (!command) return; try { - command.execute(interaction, client, Discord, command); + command.execute(interaction, client, command); } catch (error) { interaction.reply({ content: client.messages.runningCommandFailed, diff --git a/src/client/events/messageCreate.js b/src/client/events/messageCreate.js index ecc09aa..ccd314f 100644 --- a/src/client/events/messageCreate.js +++ b/src/client/events/messageCreate.js @@ -22,7 +22,7 @@ module.exports = { if (!args[0]) return; const commandName = args[0].toLowerCase(); if (commandName === 'none') return; - const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)) || client.commandAliases.get(commandName); + const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName)); if (!command && message.content !== `${prefix}`) return; const permissions = message.channel.permissionsFor(message.client.user); if (!permissions.has('EMBED_LINKS')) return message.channel.send(client.messages.noPermsEmbed); diff --git a/src/client/funcs/check.js b/src/client/funcs/check.js index e7987ed..38fe48a 100644 --- a/src/client/funcs/check.js +++ b/src/client/funcs/check.js @@ -2,6 +2,14 @@ module.exports = function (client, interaction, command) { let message = {}; const radio = client.radio.get(interaction.guild.id); const permissions = interaction.channel.permissionsFor(interaction.user); + if(!client.stations) { + message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild); + interaction.reply({ + content: client.messageEmojis["error"] + message.errorToGetPlaylist, + ephemeral: true + }); + return false; + } if (!radio) { interaction.reply({ content: client.messageEmojis["error"] + client.messages.notPlaying, diff --git a/src/client/funcs/listStations.js b/src/client/funcs/listStations.js new file mode 100644 index 0000000..f410032 --- /dev/null +++ b/src/client/funcs/listStations.js @@ -0,0 +1,45 @@ +import Discord from "discord.js"; + +module.exports = function (client, interaction){ + let stations = new Array(); + + let options = new Array(); + options[1] = new Array(); + options[2] = new Array(); + + stations[1] = client.stations.slice(0,24).forEach(station => { + station = { + label: station.name, + description: station.owner, + value: station.name + }; + options[1].push(station); + }); + + stations[2] = client.stations.slice(25).forEach(station => { + station = { + label: station.name, + description: station.owner, + value: station.name + }; + options[2].push(station); + }); + + const menu = new Discord.MessageActionRow() + .addComponents( + new Discord.MessageSelectMenu() + .setCustomId('play') + .setPlaceholder('Nothing selected') + .addOptions(options[1]) + .addOptions(options[2]) + ); + + stations = null; + options = null; + + return interaction.reply({ + content: '**Select station:**', + components: [menu], + ephemeral: true + }); +} \ No newline at end of file diff --git a/src/client/funcs/play.js b/src/client/funcs/play.js new file mode 100644 index 0000000..24addeb --- /dev/null +++ b/src/client/funcs/play.js @@ -0,0 +1,93 @@ +import Discord from "discord.js"; +const { + createAudioResource +} = require("@discordjs/voice"); + +module.exports = async function play(interaction, guild, client, url) { + let message = {}; + const radio = client.radio.get(guild.id); + const resource = createAudioResource(url); + radio.connection.subscribe(radio.audioPlayer); + radio.audioPlayer.play(resource); + resource.playStream + .on("readable", () => { + client.funcs.logger('Radio', 'Stream started' + " / " + guild.id + " / " + radio.station.name); + }) + .on("finish", () => { + client.funcs.logger('Radio', 'Stream finished' + " / " + guild.id); + client.funcs.statisticsUpdate(client, guild, radio); + radio.connection?.destroy(); + radio.audioPlayer?.stop(); + client.radio.delete(guild.id); + return; + }) + .on("error", error => { + client.funcs.logger('Radio', 'Stream errored'); + console.error(error); + radio.connection?.destroy(); + radio.audioPlayer?.stop(); + client.radio.delete(guild.id); + return interaction.reply(client.messages.errorPlaying); + }); + + message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); + message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.owner); + message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", ""); + message.nowplayingDescription = message.nowplayingDescription.replace("Owner: ", ""); + message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); + message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); + + const embed = new Discord.MessageEmbed() + .setTitle(client.user.username) + .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) + .setColor(client.config.embedColor) + .addField(client.messages.nowplayingTitle, message.nowplayingDescription, true) + .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') + .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); + + const buttons = new Discord.MessageActionRow() + .addComponents( + new Discord.MessageButton() + .setCustomId('list') + .setEmoji(client.messageEmojis["list"]) + .setStyle('SECONDARY') + ) + .addComponents( + new Discord.MessageButton() + .setCustomId('prev') + .setEmoji(client.messageEmojis["prev"]) + .setStyle('SECONDARY') + ) + .addComponents( + new Discord.MessageButton() + .setCustomId('stop') + .setEmoji(client.messageEmojis["stop"]) + .setStyle('SECONDARY') + ) + .addComponents( + new Discord.MessageButton() + .setCustomId('next') + .setEmoji(client.messageEmojis["next"]) + .setStyle('SECONDARY') + ) + .addComponents( + new Discord.MessageButton() + .setCustomId('statistics') + .setEmoji(client.messageEmojis["statistics"]) + .setStyle('SECONDARY') + ); + + if(!radio.message){ + radio.message = await radio.textChannel.send({ embeds: [embed], components: [buttons] }); + } else { + radio.message.edit({ embeds: [embed], components: [buttons] }); + } + + message.play = client.messages.play.replace("%radio.station.name%", radio.station.name); + + interaction?.reply({ + content: client.messageEmojis["play"] + message.play, + ephemeral: true + }); + +} \ No newline at end of file diff --git a/src/client/funcs/searchStation.js b/src/client/funcs/searchStation.js new file mode 100644 index 0000000..f443fd0 --- /dev/null +++ b/src/client/funcs/searchStation.js @@ -0,0 +1,62 @@ +module.exports = function searchStation(key, client) { + if (client.stations === null) return false; + let foundStations = []; + if (!key) return false; + if (key == "radio") return false; + + client.stations + .filter( + x => x.name.toUpperCase().includes(key.toUpperCase()) || x === key + ) + .forEach(x => + foundStations.push({ station: x, name: x.name, probability: 100 }) + ); + + if (key.startsWith("radio ")) key = key.slice(6); + const probabilityIncrement = 100 / key.split(" ").length / 2; + for (let i = 0; i < key.split(" ").length; i++) { + client.stations + .filter( + x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key + ) + .forEach(x => + foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }) + ); + } + if (foundStations.length === 0) return false; + for (let i = 0; i < foundStations.length; i++) { + for (let j = 0; j < foundStations.length; j++) { + if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1); + } + } + for (let i = 0; i < foundStations.length; i++) { + if (foundStations[i].name.length > key.length) { + foundStations[i].probability -= + (foundStations[i].name.split(" ").length - key.split(" ").length) * + (probabilityIncrement * 0.5); + } else if (foundStations[i].name.length === key.length) { + foundStations[i].probability += probabilityIncrement * 0.9; + } + + for (let j = 0; j < key.split(" ").length; j++) { + if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) { + foundStations[i].probability -= probabilityIncrement * 0.5; + } + } + } + let highestProbabilityStation; + for (let i = 0; i < foundStations.length; i++) { + if ( + !highestProbabilityStation || + highestProbabilityStation.probability < foundStations[i].probability + ) + highestProbabilityStation = foundStations[i]; + if ( + highestProbabilityStation && + highestProbabilityStation.probability === foundStations[i].probability + ) { + highestProbabilityStation = foundStations[i].station; + } + } + return highestProbabilityStation; +} \ No newline at end of file diff --git a/src/client/restoreradio.js b/src/client/restoreradio.js index 45ff10f..4916bbc 100644 --- a/src/client/restoreradio.js +++ b/src/client/restoreradio.js @@ -1,7 +1,6 @@ import Discord from "discord.js"; const { createAudioPlayer, - createAudioResource, getVoiceConnection, joinVoiceChannel } = require("@discordjs/voice"); @@ -15,7 +14,7 @@ module.exports = { if(!state) return; if(!state.station || !state.channels.voice || !state.channels.text) return; - const sstation = await searchStation(state.station.name, client); + const sstation = await client.funcs.searchStation(state.station.name, client); let url = sstation.stream[sstation.stream.default]; let station = sstation; @@ -43,7 +42,7 @@ module.exports = { let date = new Date(); construct.startTime = date.getTime(); - play(null, guild, client, url, Discord); + client.funcs.play(null, guild, client, url, Discord); client.datastore.checkEntry(guild.id); construct.datastore = client.datastore.getEntry(guild.id); @@ -59,152 +58,4 @@ module.exports = { } }); } -} - -async function play(interaction, guild, client, url, Discord) { - let message = {}; - const radio = client.radio.get(guild.id); - const resource = createAudioResource(url); - radio.connection.subscribe(radio.audioPlayer); - radio.audioPlayer.play(resource); - resource.playStream - .on("readable", () => { - client.funcs.logger('Radio', 'Stream started' + " / " + guild.id + " / " + radio.station.name); - }) - .on("finish", () => { - client.funcs.logger('Radio', 'Stream finished' + " / " + guild.id); - client.funcs.statisticsUpdate(client, guild, radio); - radio.connection?.destroy(); - radio.audioPlayer?.stop(); - client.radio.delete(guild.id); - return; - }) - .on("error", error => { - client.funcs.logger('Radio', 'Stream errored'); - console.error(error); - radio.connection?.destroy(); - radio.audioPlayer?.stop(); - client.radio.delete(guild.id); - }); - - message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name); - message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.owner); - message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("Owner: ", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - message.nowplayingDescription = message.nowplayingDescription.replace("**", ""); - - const embed = new Discord.MessageEmbed() - .setTitle(client.user.username) - .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, ''))) - .setColor(client.config.embedColor) - .addField(client.messages.nowplayingTitle, message.nowplayingDescription, true) - .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png') - .setFooter(client.messages.footerText, "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')); - - const buttons = new Discord.MessageActionRow() - .addComponents( - new Discord.MessageButton() - .setCustomId('list') - .setEmoji(client.messageEmojis["list"]) - .setStyle('SECONDARY') - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('prev') - .setEmoji(client.messageEmojis["prev"]) - .setStyle('SECONDARY') - .setDisabled(true) - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('stop') - .setEmoji(client.messageEmojis["stop"]) - .setStyle('SECONDARY') - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('next') - .setEmoji(client.messageEmojis["next"]) - .setStyle('SECONDARY') - .setDisabled(true) - ) - .addComponents( - new Discord.MessageButton() - .setCustomId('statistics') - .setEmoji(client.messageEmojis["statistics"]) - .setStyle('SECONDARY') - ); - - if(!radio.message){ - radio.message = await radio.textChannel.send({ embeds: [embed], components: [buttons] }); - } else { - radio.message.edit({ embeds: [embed], components: [buttons] }); - } - - message.play = client.messages.play.replace("%radio.station.name%", radio.station.name); - -} - -function searchStation(key, client) { - if (client.stations === null) return false; - let foundStations = []; - if (!key) return false; - if (key == "radio") return false; - - client.stations - .filter( - x => x.name.toUpperCase().includes(key.toUpperCase()) || x === key - ) - .forEach(x => - foundStations.push({ station: x, name: x.name, probability: 100 }) - ); - - if (key.startsWith("radio ")) key = key.slice(6); - const probabilityIncrement = 100 / key.split(" ").length / 2; - for (let i = 0; i < key.split(" ").length; i++) { - client.stations - .filter( - x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key - ) - .forEach(x => - foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }) - ); - } - if (foundStations.length === 0) return false; - for (let i = 0; i < foundStations.length; i++) { - for (let j = 0; j < foundStations.length; j++) { - if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1); - } - } - for (let i = 0; i < foundStations.length; i++) { - if (foundStations[i].name.length > key.length) { - foundStations[i].probability -= - (foundStations[i].name.split(" ").length - key.split(" ").length) * - (probabilityIncrement * 0.5); - } else if (foundStations[i].name.length === key.length) { - foundStations[i].probability += probabilityIncrement * 0.9; - } - - for (let j = 0; j < key.split(" ").length; j++) { - if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) { - foundStations[i].probability -= probabilityIncrement * 0.5; - } - } - } - let highestProbabilityStation; - for (let i = 0; i < foundStations.length; i++) { - if ( - !highestProbabilityStation || - highestProbabilityStation.probability < foundStations[i].probability - ) - highestProbabilityStation = foundStations[i]; - if ( - highestProbabilityStation && - highestProbabilityStation.probability === foundStations[i].probability - ) { - highestProbabilityStation = foundStations[i].station; - } - } - return highestProbabilityStation; } \ No newline at end of file