From 35dc8e42a045f6c0bc066fadd13f5d59448ab5ea Mon Sep 17 00:00:00 2001 From: SileNce5k Date: Wed, 30 Apr 2025 19:48:33 +0200 Subject: [PATCH] temp --- commands/misc/fm.js | 27 +++++++- util/lastfm/getTopAlbums.js | 119 +++++++++++++++++++++++++++++++++++ util/lastfm/getTopArtists.js | 118 ++++++++++++++++++++++++++++++++++ util/lastfm/roast.js | 37 +++++++++++ 4 files changed, 300 insertions(+), 1 deletion(-) create mode 100644 util/lastfm/getTopAlbums.js create mode 100644 util/lastfm/getTopArtists.js create mode 100644 util/lastfm/roast.js diff --git a/commands/misc/fm.js b/commands/misc/fm.js index 615630c..41d769e 100644 --- a/commands/misc/fm.js +++ b/commands/misc/fm.js @@ -4,6 +4,11 @@ const getCurrentCover = require("../../util/lastfm/getCurrentCover"); const getTopTracks = require("../../util/lastfm/getTopTracks"); const help = require("../info/help"); const parseMention = require("../../util/parseMention"); +const roast = require("../../util/lastfm/roast"); +const getTopArtists = require("../../util/lastfm/getTopArtists"); +const getTopAlbums = require("../../util/lastfm/getTopAlbums"); +const {EmbedBuilder} = require('discord.js'); +const getNickname = require('../../util/getNickname'); module.exports = { name: 'fm', description: 'Last fm commands. See `help fm` for more info.', @@ -13,6 +18,7 @@ module.exports = { "Get current scrobble: `fm`", "Get top tracks: `fmtt`", "Get album cover for current scrobble: `fmcover`", + "Get a roast from an LLM using your top artists and albums: `fmroast`" ], async execute({ message, args, prefix, client }) { let sendText = {text: "Something went wrong.", embed: null}; @@ -31,6 +37,25 @@ module.exports = { case "cover": sendText = await getCurrentCover(message.author.id, message.guild); break; + case "roast": + let topArtists = await getTopArtists(message.author.id, ["yearly"], message.guild, true); + let topAlbums = await getTopAlbums(message.author.id, ["yearly"], message.guild, true); + let result = await roast(topArtists, topAlbums); + + let parse = parseMention(message.author.id, message.guild) + let user = message.guild.members.cache.get(parse); + let nickname = getNickname(user, message.guild) + if (nickname == null) { + nickname = user.user.username; + } + const possesive = nickname.at(nickname.length - 1) === "s" ? "'" : "'s" + const embed = new EmbedBuilder() + .setAuthor({name: `${nickname}${possesive} AI roast`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })}) + .setColor(15780145) + embed.addFields({ + name: ` `, value: `${result}` + },) + break; default: sendText.text = `${args[0]} is not a valid subcommand.\nSee \`${prefix}help fm\` for more info.`; break; @@ -51,4 +76,4 @@ module.exports = { message.channel.send(sendText.text.replaceAll("", prefix)); } } -}; \ No newline at end of file +}; \ No newline at end of file diff --git a/util/lastfm/getTopAlbums.js b/util/lastfm/getTopAlbums.js new file mode 100644 index 0000000..049393d --- /dev/null +++ b/util/lastfm/getTopAlbums.js @@ -0,0 +1,119 @@ +// http://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=username&api_key=YOUR_API_KEY&format=json + +const getFmUsername = require("./getFmUsername"); +const {EmbedBuilder} = require('discord.js'); +const getNickname = require('../getNickname') +const parseMention = require('../parseMention') + +module.exports = async function (userID, option, guild, compatibility=false) { + let lastfmUsername = await getFmUsername(userID) + let parse = parseMention(userID, guild) + let user = guild.members.cache.get(parse); + let nickname = getNickname(user, guild) + if (nickname == null) { + nickname = user.user.username; + } + let albums = []; + const options = { + "weekly": "7day", + "week": "7day", + "w": "7day", + + "monthly": "1month", + "month": "1month", + "m": "1month", + + "quarterly": "3month", + "q": "3month", + + "halfyear": "6month", + "hy": "6month", + "h": "6month", + + "yearly": "12month", + "year": "12month", + "y": "12month", + + "alltime": "overall", + "a": "overall", + "at": "overall", + "all": "overall", + + undefined: "7day" + }; + + if(option.length === 0){ + option[0] = "weekly" + } + + option[0] = options[option[0]]; + if(option[0] === undefined) + option[0] = options[option[0]]; + + let duration = ""; + switch (option[0]){ + case "overall": + duration = "all time"; + break; + case "7day": + duration = "weekly"; + break; + case "1month": + duration = "monthly"; + break; + case "3month": + duration = "quarterly"; + break; + case "6month": + duration = "half year"; + break; + case "12month": + duration = "yearly"; + break; + } + let sendText = { text: "", embed: null } + if(lastfmUsername != undefined){ + albums = await new Promise ((resolve, reject) => { + fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopalbums&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`) + .then(response => response.json()) + .then(data => { + for(let i = 0; i < 10; i++){ + let album = {} + let currentAlbum = data.topalbums.album[i]; + album.artist = currentAlbum.artist.name; + album.name = currentAlbum.name; + album.playcount = currentAlbum.playcount; + albums.push(album); + } + resolve(albums); + }) + .catch(error => { + console.error(error); + reject(error); + }); + }); + } + // const embed = new EmbedBuilder() + // .setAuthor({name: `Top ${duration} albums for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })}) + // .setThumbnail(albums[0].cover) + // .setColor(15780145) + // let tracksInfo = ""; + // for(let i = 0; i < albums.length; i++){ + // let pluralCharacter = albums[i].playcount > 1 ? 's' : ''; + // let track = `${i}. **${albums[i].artist}** - ${albums[i].song} - *${albums[i].playcount} play${pluralCharacter}*`; + // if(i < albums.length - 1){ + // tracksInfo += `${track}\n`; + // }else{ + // tracksInfo += `${track}`; + // } + // } + // embed.addFields({ + // name: ` `, value: `${tracksInfo}` + // },) + // sendText.embed = embed; + // if(compatibility) + return albums; + // else + // return sendText; + +} \ No newline at end of file diff --git a/util/lastfm/getTopArtists.js b/util/lastfm/getTopArtists.js new file mode 100644 index 0000000..2318180 --- /dev/null +++ b/util/lastfm/getTopArtists.js @@ -0,0 +1,118 @@ +// http://ws.audioscrobbler.com/2.0/?method=user.gettoptracks&user=username&api_key=YOUR_API_KEY&format=json + +const getFmUsername = require("./getFmUsername"); +const {EmbedBuilder} = require('discord.js'); +const getNickname = require('../getNickname') +const parseMention = require('../parseMention') + +module.exports = async function (userID, option, guild, compatibility=false) { + let lastfmUsername = await getFmUsername(userID) + let parse = parseMention(userID, guild) + let user = guild.members.cache.get(parse); + let nickname = getNickname(user, guild) + if (nickname == null) { + nickname = user.user.username; + } + let artists = []; + const options = { + "weekly": "7day", + "week": "7day", + "w": "7day", + + "monthly": "1month", + "month": "1month", + "m": "1month", + + "quarterly": "3month", + "q": "3month", + + "halfyear": "6month", + "hy": "6month", + "h": "6month", + + "yearly": "12month", + "year": "12month", + "y": "12month", + + "alltime": "overall", + "a": "overall", + "at": "overall", + "all": "overall", + + undefined: "7day" + }; + + if(option.length === 0){ + option[0] = "weekly" + } + + option[0] = options[option[0]]; + if(option[0] === undefined) + option[0] = options[option[0]]; + + let duration = ""; + switch (option[0]){ + case "overall": + duration = "all time"; + break; + case "7day": + duration = "weekly"; + break; + case "1month": + duration = "monthly"; + break; + case "3month": + duration = "quarterly"; + break; + case "6month": + duration = "half year"; + break; + case "12month": + duration = "yearly"; + break; + } + let sendText = { text: "", embed: null } + if(lastfmUsername != undefined){ + artists = await new Promise ((resolve, reject) => { + fetch(`https://ws.audioscrobbler.com/2.0/?method=user.gettopartists&user=${lastfmUsername}&period=${option[0]}&api_key=${process.env.LAST_FM_API_KEY}&format=json`) + .then(response => response.json()) + .then(data => { + for(let i = 0; i < 10; i++){ + let artist = {} + let currentArtist = data.topartists.artist[i]; + artist.name = currentArtist.name; + artist.playcount = currentArtist.playcount; + artists.push(artist); + } + resolve(artists); + }) + .catch(error => { + console.error(error); + reject(error); + }); + }); + } + // const embed = new EmbedBuilder() + // .setAuthor({name: `Top ${duration} tracks for ${nickname}`, iconURL: user.user.avatarURL({ dynamic: true, size: 4096 })}) + // .setThumbnail(tracks[0].cover) + // .setColor(15780145) + // let tracksInfo = ""; + // for(let i = 0; i < tracks.length; i++){ + // let pluralCharacter = tracks[i].playcount > 1 ? 's' : ''; + // let track = `${i}. **${tracks[i].artist}** - ${tracks[i].song} - *${tracks[i].playcount} play${pluralCharacter}*`; + // if(i < tracks.length - 1){ + // tracksInfo += `${track}\n`; + // }else{ + // tracksInfo += `${track}`; + // } + // } + // embed.addFields({ + // name: ` `, value: `${tracksInfo}` + // },) + // sendText.embed = embed; + // if(compatibility) + return artists; + // else + // return sendText; + +} \ No newline at end of file diff --git a/util/lastfm/roast.js b/util/lastfm/roast.js new file mode 100644 index 0000000..33efaaf --- /dev/null +++ b/util/lastfm/roast.js @@ -0,0 +1,37 @@ +require("dotenv").config(); +module.exports = async function(topArtists, topAlbums) { + let prompt = "Roast the top 10 artists albums the user has listened to most for the last 365 days. Go as hard as possible and be mean like a music elitist. Create 3 paragraphs, and a short sentence as a summary at the end.\n" + + prompt += "Top artists and their playcounts:\n" + topArtists.forEach(topArtist => { + prompt += `${topArtist.name} (${topArtist.playcount})\n` + }); + + prompt += "Top albums and their playcounts:\n" + topAlbums.forEach(topAlbum => { + prompt += `${topAlbum.artist} - ${topAlbum.name} (${topAlbum.playcount})\n` + }) + let answer = ""; + await fetch(`https://openrouter.ai/api/v1/chat/completions`, { + method: `POST`, + headers: { + "Authorization": `Bearer ${process.env.OPENROUTER_API_KEY}`, + "Content-Type": `application/json` + }, + body: JSON.stringify({ + "model": `deepseek/deepseek-chat-v3-0324:free`, + "messages": [ + { + "role": `system`, + "content": prompt + } + ], + "max_tokens": 400 + }) + }).then(response => response.json()).then(data => { + answer = data.choices[0].message.content; + }).catch(error => { + console.error(error); + }); + return {embed: null, text: answer}; +} \ No newline at end of file