-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Live Radio stations and Youtube url to mp3 #352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
const { EmbedBuilder } = require('discord.js'); | ||
const { Translate } = require('../process_tools'); | ||
const { stopRadio } = require('../utils/radioPlayer'); | ||
|
||
module.exports = async ({ client, inter }) => { | ||
try { | ||
// Only allow the requester or admins to stop the radio | ||
if (inter.member.permissions.has('ADMINISTRATOR') || inter.message.interaction.user.id === inter.user.id) { | ||
const result = stopRadio(inter.guild.id); | ||
|
||
const embed = new EmbedBuilder() | ||
.setColor('#2f3136') | ||
.setAuthor({ name: await Translate(result ? | ||
`Radio playback has been stopped. <✅>` : | ||
`No active radio to stop. <❌>`) | ||
}); | ||
|
||
return inter.update({ embeds: [embed], components: [] }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This causes an "InteractionAlreadyReplied" error |
||
} else { | ||
return inter.reply({ | ||
content: await Translate(`Only the person who started the radio or an administrator can stop it.`), | ||
ephemeral: true | ||
}); | ||
} | ||
} catch (error) { | ||
console.error('Error in radio_stop button handler:', error); | ||
|
||
// Try to provide some feedback even if there's an error | ||
try { | ||
return inter.reply({ | ||
content: await Translate(`There was an error stopping the radio. Please try again.`), | ||
ephemeral: true | ||
}).catch(console.error); | ||
} catch (replyError) { | ||
console.error('Failed to send error message:', replyError); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
const { EmbedBuilder } = require('discord.js'); | ||
const { Translate } = require('../process_tools'); | ||
|
||
module.exports = async ({ client, inter }) => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused |
||
try { | ||
// Get the active connections from the YouTube command | ||
const activeConnections = require('../commands/music/youtube').activeConnections; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Connections should be fetched from |
||
|
||
// Only allow the requester or admins to stop the YouTube player | ||
if (inter.member.permissions.has('ADMINISTRATOR') || inter.message.interaction.user.id === inter.user.id) { | ||
let result = false; | ||
|
||
// Check if there's an active connection for this guild | ||
if (activeConnections && activeConnections.has(inter.guild.id)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use optional chaining ( |
||
const connection = activeConnections.get(inter.guild.id); | ||
connection.destroy(); | ||
activeConnections.delete(inter.guild.id); | ||
result = true; | ||
} | ||
|
||
const embed = new EmbedBuilder() | ||
.setColor('#FF0000') | ||
.setAuthor({ name: await Translate(result ? | ||
`YouTube playback has been stopped. <✅>` : | ||
`No active YouTube player to stop. <❌>`) | ||
}); | ||
|
||
// Use try-catch to handle potential "already replied" errors | ||
try { | ||
// Try to update the message first | ||
await inter.update({ embeds: [embed], components: [] }); | ||
} catch (updateError) { | ||
console.log('Could not update interaction, trying to reply instead:', updateError.message); | ||
|
||
// If update fails, try to reply | ||
try { | ||
await inter.reply({ embeds: [embed], ephemeral: true }); | ||
} catch (replyError) { | ||
console.error('Failed to reply to interaction:', replyError.message); | ||
} | ||
} | ||
} else { | ||
// For unauthorized users, use deferReply + editReply pattern which is more reliable | ||
try { | ||
await inter.deferReply({ ephemeral: true }); | ||
await inter.editReply({ | ||
content: await Translate(`Only the person who started the YouTube player or an administrator can stop it.`) | ||
}); | ||
} catch (error) { | ||
console.error('Failed to respond to unauthorized user:', error.message); | ||
} | ||
} | ||
} catch (error) { | ||
console.error('Error in youtube_stop button handler:', error); | ||
|
||
// Try to provide some feedback even if there's an error | ||
try { | ||
// Use deferReply + editReply pattern which is more reliable | ||
await inter.deferReply({ ephemeral: true }).catch(console.error); | ||
await inter.editReply({ | ||
content: await Translate(`There was an error stopping the YouTube player. Please try again.`) | ||
}).catch(console.error); | ||
} catch (replyError) { | ||
console.error('Failed to send error message:', replyError); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
const { ApplicationCommandOptionType, EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js'); | ||
const { Translate } = require('../../process_tools'); | ||
const radioStations = require('../../radioStations'); | ||
const { playRadioStation, stopRadio } = require('../../utils/radioPlayer'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unused |
||
|
||
module.exports = { | ||
name: 'radio', | ||
description: ('Play a live radio station'), | ||
voiceChannel: true, | ||
options: [ | ||
{ | ||
name: 'station', | ||
description: ('The radio station you want to listen to'), | ||
type: ApplicationCommandOptionType.String, | ||
required: true, | ||
choices: radioStations.map(station => ({ | ||
name: station.name, | ||
value: station.name | ||
})) | ||
}, | ||
{ | ||
name: 'quality', | ||
description: ('Audio quality (higher uses more bandwidth)'), | ||
type: ApplicationCommandOptionType.String, | ||
required: false, | ||
choices: [ | ||
{ name: 'Low', value: 'low' }, | ||
{ name: 'Medium', value: 'medium' }, | ||
{ name: 'High', value: 'high' } | ||
] | ||
} | ||
], | ||
|
||
async execute({ inter, client }) { | ||
const stationName = inter.options.getString('station'); | ||
const qualityOption = inter.options.getString('quality') || 'high'; | ||
|
||
const defaultEmbed = new EmbedBuilder().setColor('#2f3136'); | ||
|
||
// Set quality based on user selection | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why base quality off of volume ? Aren't these 2 different things ? |
||
let volumeLevel = client.config.opt.volume; | ||
|
||
switch(qualityOption) { | ||
case 'low': | ||
volumeLevel = Math.min(client.config.opt.volume, 70); | ||
break; | ||
case 'medium': | ||
volumeLevel = Math.min(client.config.opt.volume, 80); | ||
break; | ||
case 'high': | ||
volumeLevel = client.config.opt.volume; | ||
break; | ||
} | ||
|
||
try { | ||
// Find the selected radio station | ||
const station = radioStations.find(s => s.name === stationName); | ||
|
||
if (!station) { | ||
defaultEmbed.setAuthor({ name: await Translate(`Radio station not found. Try again? <❌>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed], ephemeral: false }); | ||
} | ||
|
||
// Tell user we're connecting to the radio station | ||
defaultEmbed.setAuthor({ name: await Translate(`Connecting to ${station.name} radio... <📻>`) }); | ||
await inter.editReply({ embeds: [defaultEmbed], ephemeral: false }); | ||
|
||
// Use our custom radio player instead of discord-player | ||
try { | ||
const result = await playRadioStation({ | ||
voiceChannel: inter.member.voice.channel, | ||
interaction: inter, | ||
station: station, | ||
volume: volumeLevel, | ||
client: client | ||
}); | ||
|
||
if (result.success) { | ||
// Create a stop button that uses the button handler system | ||
const stopButton = new ButtonBuilder() | ||
.setCustomId('radio_stop') | ||
.setLabel('Stop Radio') | ||
.setStyle(ButtonStyle.Danger) | ||
.setEmoji('⏹️'); | ||
|
||
const row = new ActionRowBuilder().addComponents(stopButton); | ||
|
||
// Send a non-ephemeral message with the button | ||
await inter.editReply({ | ||
embeds: [result.embed], | ||
components: [row], | ||
ephemeral: false | ||
}); | ||
|
||
return; | ||
} else { | ||
defaultEmbed.setAuthor({ name: await Translate(`Error playing radio station. Try another station? <❌>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed], ephemeral: false }); | ||
} | ||
} catch (error) { | ||
console.log(`Radio play error: ${error}`); | ||
defaultEmbed.setAuthor({ name: await Translate(`Error playing radio station. Try another station? <❌>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed], ephemeral: false }); | ||
} | ||
} catch (error) { | ||
console.log(`Radio command error: ${error}`); | ||
defaultEmbed.setAuthor({ name: await Translate(`I can't join the voice channel... try again? <❌>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed], ephemeral: false }); | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
const { EmbedBuilder } = require('discord.js'); | ||
const { Translate } = require('../../process_tools'); | ||
const { stopRadio, activeRadioConnections } = require('../../utils/radioPlayer'); | ||
|
||
module.exports = { | ||
name: 'radiostop', | ||
description:("Stop the radio playback"), | ||
voiceChannel: true, | ||
|
||
async execute({ inter }) { | ||
const defaultEmbed = new EmbedBuilder().setColor('#2f3136'); | ||
|
||
// Check if there's a radio playing in this guild | ||
if (activeRadioConnections.has(inter.guild.id)) { | ||
const stopped = stopRadio(inter.guild.id); | ||
|
||
if (stopped) { | ||
defaultEmbed.setAuthor({ name: await Translate(`Radio playback has been stopped. <✅>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed] }); | ||
} | ||
} | ||
|
||
defaultEmbed.setAuthor({ name: await Translate(`No radio is currently playing. <❌>`) }); | ||
return inter.editReply({ embeds: [defaultEmbed] }); | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused
client
parameter