From 2a7dca38f2f68787e81f4468c7312e6709b8ac4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christer=20War=C3=A9n?= Date: Tue, 28 Nov 2023 22:54:22 +0200 Subject: [PATCH] Add RadioPlay playlist support --- src/client/classes/Stations.ts | 3 +- src/client/commands/list.ts | 25 +++++-- src/client/commands/maintenance.ts | 12 ++-- src/client/commands/play.ts | 6 +- src/client/funcs/listStations.ts | 14 +++- src/client/funcs/play.ts | 109 ++++++++++++++++++----------- 6 files changed, 114 insertions(+), 55 deletions(-) diff --git a/src/client/classes/Stations.ts b/src/client/classes/Stations.ts index 225a2eb..c3f2fb5 100644 --- a/src/client/classes/Stations.ts +++ b/src/client/classes/Stations.ts @@ -8,9 +8,10 @@ export interface station { [key: string]: string }, playlist?: { - type: "supla" | "yle", + type: "radioplay" | "supla" | "yle", address: string | string } + track?: string; } export default class Stations extends Array { diff --git a/src/client/commands/list.ts b/src/client/commands/list.ts index 563d418..f2a0c3d 100644 --- a/src/client/commands/list.ts +++ b/src/client/commands/list.ts @@ -1,10 +1,13 @@ -import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; +import { ApplicationCommandOptionType, ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; import { station } from "../classes/Stations"; export default { name: 'list', - description: 'List radio stations', + description: 'List stations', + options: [ + { type: ApplicationCommandOptionType.String, name: "query", description: "Select list", choices: [{"name": "1", "value": "1"},{"name": "2", "value": "2"}], required: false} + ], category: 'radio', execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { @@ -15,6 +18,20 @@ export default { }); } + if(!interaction.guild) return; + + let query: string | null = null; + + if(interaction.isChatInputCommand()){ + query = interaction.options?.getString("query"); + } + + if(interaction.isStringSelectMenu()){ + query = interaction.values?.[0]; + } + + if(!query) query = "1"; + if(!client.stations) { return interaction.reply({ content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, { @@ -24,10 +41,10 @@ export default { }); } - const radio = client.radio?.get(interaction.guild?.id); + const radio = client.radio?.get(interaction.guild.id); if(radio && !client.config.maintenanceMode){ - client.funcs.listStations(client, interaction); + client.funcs.listStations(client, interaction, query); } else { let stations = `${client.stations.map((s: station) => `**#** ${s.name}`).join('\n')}` const hashs = stations.split('**#**').length; diff --git a/src/client/commands/maintenance.ts b/src/client/commands/maintenance.ts index e255915..1c928e6 100644 --- a/src/client/commands/maintenance.ts +++ b/src/client/commands/maintenance.ts @@ -183,7 +183,7 @@ export default { client.user?.setStatus('idle'); client.radio?.save(client); - setInterval(() => { + let timer : NodeJS.Timeout = setInterval(() => { if(client.radio?.size == 0 && client.config.streamerMode == "manual" && client.config.maintenanceMode){ client.streamer?.leave(client); client.streamer = new Streamer(); @@ -195,9 +195,9 @@ export default { } if(!client.config.maintenanceMode){ - clearInterval(undefined); + clearInterval(timer); } - }, 500); + }, 1000); break; case "11": @@ -207,7 +207,7 @@ export default { client.user?.setStatus('idle'); client.radio?.save(client); - setInterval(() => { + let timer2 : NodeJS.Timeout = setInterval(() => { if(client.radio?.size == 0 && client.config.streamerMode == "auto" && client.config.maintenanceMode){ client.streamer?.leave(client); client.streamer = new Streamer(); @@ -219,9 +219,9 @@ export default { } if(!client.config.maintenanceMode){ - clearInterval(undefined); + clearInterval(timer2); } - }, 500); + }, 1000); break; default: diff --git a/src/client/commands/play.ts b/src/client/commands/play.ts index e9bb0cc..3b4545e 100644 --- a/src/client/commands/play.ts +++ b/src/client/commands/play.ts @@ -13,6 +13,8 @@ export default { category: "radio", async execute(interaction: ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) { + if(!interaction.guild) return; + if(client.config.maintenanceMode){ return interaction.reply({ content: client.messages.emojis["error"] + client.messages.maintenance, @@ -40,10 +42,10 @@ export default { } if(!query){ - return client.funcs.listStations(client, interaction); + return client.funcs.listStations(client, interaction, "1"); } - const radio = client.radio?.get(interaction.guild?.id); + const radio = client.radio?.get(interaction.guild.id); if(!(interaction.member instanceof GuildMember)) return; const voiceChannel = interaction.member?.voice.channel; diff --git a/src/client/funcs/listStations.ts b/src/client/funcs/listStations.ts index 96349a6..3b443c2 100644 --- a/src/client/funcs/listStations.ts +++ b/src/client/funcs/listStations.ts @@ -1,11 +1,12 @@ import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, SelectMenuComponentOptionData, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js"; import RadioClient from "../../Client"; -export default function listStations(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction){ +export default function listStations(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, offset: string){ if(!client.stations) return; let options : SelectMenuComponentOptionData[] = new Array(); + for (const station of client.stations){ options.push({ label: station.name, @@ -14,6 +15,17 @@ export default function listStations(client: RadioClient, interaction: ButtonInt }); } + switch(offset){ + case "1": + options = options.slice(0,Math.round(options.length/2)); + break; + case "2": + options = options.slice(Math.round(options.length/2),options.length-1); + break; + default: + options = options.slice(0,Math.round(options.length/2)); + } + const menu = new ActionRowBuilder() .addComponents( new StringSelectMenuBuilder() diff --git a/src/client/funcs/play.ts b/src/client/funcs/play.ts index fc773db..a0864b9 100644 --- a/src/client/funcs/play.ts +++ b/src/client/funcs/play.ts @@ -6,30 +6,43 @@ export default async function play(client: RadioClient, interaction: ChatInputCo if(!guild) return; const radio = client.radio?.get(guild.id); + if(!radio) return; const audioPlayer = client.streamer?.listen(station); - radio.connection.subscribe(audioPlayer); + if(!audioPlayer) return; + radio.connection?.subscribe(audioPlayer); client.funcs.logger('Radio', guild.id + " / " + "Play" + " / " + radio.station.name); - try { - if(radio.station?.playlist?.type == "supla" || radio.station?.playlist?.type == "yle"){ + if(radio.station.playlist){ + if(radio.station.playlist.type == "radioplay" || radio.station.playlist.type == "supla" || radio.station.playlist.type == "yle"){ let playlist: any = await fetch(radio.station.playlist.address) .then((response: Response) => response.json()) .catch(error => { }); - switch(radio.station?.playlist.type){ - case "supla": - radio.station.track = "__" + playlist.items[0]?.artist + "__" + "\n" + playlist.items[0]?.song; - break; - case "yle": - radio.station.track = "-"; - break; - default: - radio.station.track = "-"; + radio.station.track = "-"; + + if(playlist){ + switch(radio.station.playlist.type){ + case "radioplay": + if(playlist[0] && playlist[0].stationNowPlaying && playlist[0].stationNowPlaying.nowPlayingArtist && playlist[0].stationNowPlaying.nowPlayingTrack){ + radio.station.track = "__" + playlist[0].stationNowPlaying.nowPlayingArtist + "__" + "\n" + playlist[0].stationNowPlaying.nowPlayingTrack; + } + break; + case "supla": + if(playlist.items && playlist.items[0] && playlist.items[0].artist && playlist.items[0].song){ + radio.station.track = "__" + playlist.items[0].artist + "__" + "\n" + playlist.items[0].song; + } + break; + case "yle": + if(playlist.data && playlist.data.performer && playlist.data.title){ + radio.station.track = "__" + playlist.data.performer + "__" + "\n" + playlist.data.title; + } + break; + default: + radio.station.track = "-"; + } } } - } catch(TypeError) { - } const embed = new EmbedBuilder() @@ -95,47 +108,61 @@ export default async function play(client: RadioClient, interaction: ChatInputCo ); if(!radio.message){ - radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }); + radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }) ?? null; } else { - if(radio.textChannel.id == radio.message.channel.id){ + if(radio.textChannel?.id == radio.message.channel.id){ radio.message.edit({ embeds: [embed], components: [buttons] }); } else { radio.message?.delete(); - radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }); + radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }) ?? null; } } - setInterval(async function(){ - const radio = client.radio?.get(guild.id); - let changed = false; + const oldRadio = {...radio}; - try { - if(radio.station?.playlist?.type == "supla" || radio.station?.playlist?.type == "yle"){ + let timer : NodeJS.Timeout = setInterval(async function(){ + const radio = client.radio?.get(guild.id); + + if(!radio || !oldRadio || radio.station.name != oldRadio.station.name) { + return clearInterval(timer); + } + + if(radio.station.playlist){ + if(radio.station.playlist.type == "radioplay" || radio.station.playlist.type == "supla" || radio.station.playlist.type == "yle"){ let playlist: any = await fetch(radio.station.playlist.address) .then((response: Response) => response.json()) .catch(error => { }); - switch(radio.station?.playlist.type){ - case "supla": - if(radio.station.track != "__" + playlist.items[0]?.artist + "__" + "\n" + playlist.items[0].song){ - radio.station.track = "__" + playlist.items[0].artist + "__" + "\n" + playlist.items[0].song; - } - break; - case "yle": - radio.station.track = "-"; - break; - default: - radio.station.track = "-"; + radio.station.track = "-"; + + if(playlist){ + switch(radio.station.playlist?.type){ + case "radioplay": + if(playlist[0] && playlist[0].stationNowPlaying && playlist[0].stationNowPlaying.nowPlayingArtist && playlist[0].stationNowPlaying.nowPlayingTrack){ + radio.station.track = "__" + playlist[0].stationNowPlaying.nowPlayingArtist + "__" + "\n" + playlist[0].stationNowPlaying.nowPlayingTrack; + } + break; + case "supla": + if(playlist.items && playlist.items[0] && playlist.items[0].artist && playlist.items[0].song){ + radio.station.track = "__" + playlist.items[0].artist + "__" + "\n" + playlist.items[0].song; + } + break; + case "yle": + if(playlist.data && playlist.data.performer && playlist.data.title){ + radio.station.track = "__" + playlist.data.performer + "__" + "\n" + playlist.data.title; + } + break; + default: + radio.station.track = "-"; + } } } - } catch(TypeError) { - } let date = new Date(); radio.currentTime = date.getTime(); - radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime); + radio.playTime = radio.currentTime - radio.startTime; const completed = (radio.playTime); const embed = new EmbedBuilder() @@ -169,16 +196,16 @@ export default async function play(client: RadioClient, interaction: ChatInputCo if(!radio.message){ - radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }); + radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }) ?? null; } else { - if(radio.textChannel.id == radio.message.channel.id){ - radio.message.edit({ embeds: [embed], components: [buttons] }); + if(radio.textChannel?.id == radio.message.channel.id){ + radio.message?.edit({ embeds: [embed], components: [buttons] }); } else { radio.message?.delete(); - radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }); + radio.message = await radio.textChannel?.send({ embeds: [embed], components: [buttons] }) ?? null; } } - },15000); + },2500); interaction?.reply({ content: client.messages.emojis["play"] + client.messages.replace(client.messages.play, {