diff --git a/src/request-bot.js b/src/request-bot.js index 861163d..9769cbc 100644 --- a/src/request-bot.js +++ b/src/request-bot.js @@ -36,7 +36,9 @@ const command = new SlashCommandBuilder() function isValidSendGbUrl(url) { return /^https:\/\/sendgb\.com\/[A-Za-z0-9]+$/.test(url); } - +function isValidDeezerUrl(url) { + return /^https:\/\/(www\.)?deezer\.com\/(en\/)?album\/\d+/.test(url); +} const rest = new REST({ version: "10" }).setToken(process.env.DISCORD_TOKEN); @@ -49,6 +51,26 @@ await rest.put( ); +async function getDeezerAlbum(url) { + const match = url.match(/album\/(\d+)/); + if (!match) return null; + + const albumId = match[1]; + const apiUrl = `https://api.deezer.com/album/${albumId}`; + const res = await fetch(apiUrl); + if (!res.ok) return null; + + const data = await res.json(); + return { + title: data.title, + artist: data.artist.name, + link: data.link, + cover: data.cover_medium, + releaseDate: data.release_date, + tracks: data.tracks?.data?.map(t => t.title).join(", ") || "No tracks info", + }; +} + async function getLastFmArtist(artist) { const url = "https://ws.audioscrobbler.com/2.0/?" + @@ -123,9 +145,7 @@ client.on("interactionCreate", async interaction => { if (interaction.guildId !== process.env.GUILD_ID) { return interaction.reply({ content: "❌ This command can only be used in the main server.", - flags: { - - } + ephemeral: true, }); } @@ -134,25 +154,70 @@ client.on("interactionCreate", async interaction => { const description = interaction.options.getString("description"); await interaction.deferReply({ ephemeral: true }); + if (!artistName && !url) { return interaction.editReply({ - content: "❌ You must provide either an artist name or a SendGB URL.", + content: "❌ You must provide either an artist name or a URL.", }); } + const channel = await client.channels.fetch(process.env.REQUEST_CHANNEL_ID); + if (url) { - if (!isValidSendGbUrl(url)) { - return interaction.editReply({ - content: "❌ Invalid SendGB URL format.", + if (isValidSendGbUrl(url)) { + if (!description) { + return interaction.editReply({ + content: "❌ A description is required when submitting a SendGB URL.", + }); + } + + await channel.send({ + embeds: [ + { + title: "📦 External Upload", + description, + fields: [ + { name: "Download", value: url }, + { name: "Requested by", value: `<@${interaction.user.id}>` }, + ], + }, + ], }); + + return interaction.editReply({ content: "✅ SendGB link submitted." }); } - if (!description) { - return interaction.editReply({ - content: "❌ A description is required when submitting a URL.", + if (isValidDeezerUrl(url)) { + const album = await getDeezerAlbum(url); + if (!album) { + return interaction.editReply({ + content: "❌ Could not fetch album info from Deezer.", + }); + } + + await channel.send({ + embeds: [ + { + title: album.title, + url: album.link, + description: `Artist: **${album.artist}**\nRelease Date: ${album.releaseDate}`, + thumbnail: { url: album.cover }, + fields: [ + { name: "Tracks", value: album.tracks }, + { name: "Requested by", value: `<@${interaction.user.id}>` }, + ], + }, + ], }); + + return interaction.editReply({ content: "✅ Deezer album info submitted." }); } + + return interaction.editReply({ + content: "❌ URL is not a valid SendGB or Deezer link.", + }); } + if (artistName) { if (await navidromeHasArtist(artistName)) { return interaction.editReply({ @@ -162,72 +227,30 @@ client.on("interactionCreate", async interaction => { const artist = await getLastFmArtist(artistName); if (!artist) { - return interaction.editReply({ - content: "❌ Artist not found on Last.fm.", - }); + return interaction.editReply({ content: "❌ Artist not found on Last.fm." }); } - const channel = await client.channels.fetch(process.env.REQUEST_CHANNEL_ID); - await channel.send({ embeds: [ { title: artist.name, url: artist.url, - description: - artist.bio?.summary?.replace(/<[^>]*>/g, "") ?? - "No description available.", + description: artist.bio?.summary?.replace(/<[^>]*>/g, "") ?? "No description available.", thumbnail: { - url: - artist.image?.find(i => i.size === "extralarge")?.["#text"] ?? - null, + url: artist.image?.find(i => i.size === "extralarge")?.["#text"] ?? null, }, fields: [ { name: "Listeners", value: artist.stats.listeners, inline: true }, { name: "Playcount", value: artist.stats.playcount, inline: true }, - { - name: "Tags", - value: - artist.tags?.tag?.map(t => t.name).join(", ") || "None", - }, - { - name: "Requested by", - value: `<@${interaction.user.id}>`, - }, + { name: "Tags", value: artist.tags?.tag?.map(t => t.name).join(", ") || "None" }, + { name: "Requested by", value: `<@${interaction.user.id}>` }, ], }, ], }); - return interaction.editReply({ - content: "✅ Artist request submitted.", - }); + return interaction.editReply({ content: "✅ Artist request submitted." }); } - - const channel = await client.channels.fetch(process.env.REQUEST_CHANNEL_ID); - - await channel.send({ - embeds: [ - { - title: "📦 External Upload", - description, - fields: [ - { - name: "Download", - value: url, - }, - { - name: "Requested by", - value: `<@${interaction.user.id}>`, - }, - ], - }, - ], - }); - - await interaction.editReply({ - content: "✅ Link submitted.", - }); }); /* --------------------------------- Ready -------------------------------- */