123 lines
5 KiB
Python
123 lines
5 KiB
Python
import discord
|
|
from discord.ext import commands
|
|
from discord import app_commands
|
|
import aiohttp
|
|
import re
|
|
|
|
class Lyrics(commands.Cog):
|
|
def __init__(self, bot):
|
|
self.bot = bot
|
|
|
|
@app_commands.command(name="lyrics", description="Get lyrics for a song")
|
|
@app_commands.describe(
|
|
artist="Name of the artist",
|
|
song="Title of the song",
|
|
language="Target language code (optional)"
|
|
)
|
|
@app_commands.choices(language=[
|
|
app_commands.Choice(name="Bulgarian", value="bg"),
|
|
app_commands.Choice(name="Czech", value="cs"),
|
|
app_commands.Choice(name="Danish", value="da"),
|
|
app_commands.Choice(name="German", value="de"),
|
|
app_commands.Choice(name="Greek", value="el"),
|
|
app_commands.Choice(name="English", value="en"),
|
|
app_commands.Choice(name="Spanish", value="es"),
|
|
app_commands.Choice(name="Estonian", value="et"),
|
|
app_commands.Choice(name="Finnish", value="fi"),
|
|
app_commands.Choice(name="French", value="fr"),
|
|
app_commands.Choice(name="Irish", value="ga"),
|
|
app_commands.Choice(name="Croatian", value="hr"),
|
|
app_commands.Choice(name="Hungarian", value="hu"),
|
|
app_commands.Choice(name="Italian", value="it"),
|
|
app_commands.Choice(name="Lithuanian", value="lt"),
|
|
app_commands.Choice(name="Latvian", value="lv"),
|
|
app_commands.Choice(name="Maltese", value="mt"),
|
|
app_commands.Choice(name="Dutch", value="nl"),
|
|
app_commands.Choice(name="Polish", value="pl"),
|
|
app_commands.Choice(name="Portuguese", value="pt"),
|
|
app_commands.Choice(name="Romanian", value="ro"),
|
|
app_commands.Choice(name="Slovak", value="sk"),
|
|
app_commands.Choice(name="Slovene", value="sl"),
|
|
app_commands.Choice(name="Swedish", value="sv"),
|
|
])
|
|
async def lyrics(self, interaction: discord.Interaction, artist: str = None, song: str = None, language: app_commands.Choice[str] = None):
|
|
await interaction.response.defer()
|
|
if not artist or not song:
|
|
member = interaction.guild.get_member(interaction.user.id)
|
|
if not member:
|
|
member = await interaction.guild.fetch_member(interaction.user.id)
|
|
act_artist, act_song = await self.get_artist_song_from_presence(member)
|
|
if act_artist and act_song:
|
|
artist = artist or act_artist
|
|
song = song or act_song
|
|
else:
|
|
await interaction.followup.send("No artist or song provided and couldn't find it from your current activity.")
|
|
return
|
|
|
|
lyrics = await self.fetch_lyrics(artist, song)
|
|
if not lyrics:
|
|
await interaction.followup.send(f"Could not find lyrics for **{artist} - {song}**")
|
|
return
|
|
|
|
if language:
|
|
translated = await self.translate_text(lyrics, language.value)
|
|
if translated:
|
|
lyrics = translated
|
|
|
|
if len(lyrics) > 1900:
|
|
lyrics = lyrics[:1900] + "\n\n[...lyrics truncated...]"
|
|
|
|
embed = discord.Embed(
|
|
title=f"{artist} - {song}",
|
|
description=lyrics,
|
|
color=discord.Color.blue()
|
|
)
|
|
embed.set_footer(text=f"Requested by {interaction.user}", icon_url=interaction.user.display_avatar.url)
|
|
await interaction.followup.send(embed=embed)
|
|
|
|
async def get_artist_song_from_presence(self, member: discord.Member):
|
|
for activity in member.activities:
|
|
if isinstance(activity, discord.Spotify):
|
|
return activity.artist, activity.title
|
|
return None, None
|
|
|
|
|
|
async def fetch_lyrics(self, artist, song):
|
|
artist_q = artist.replace(' ', '+').lower()
|
|
song_q = song.replace(' ', '+').lower()
|
|
|
|
url = f"https://lrclib.net/api/get?artist_name={artist_q}&track_name={song_q}"
|
|
print(url)
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
try:
|
|
async with session.get(url) as resp:
|
|
if resp.status != 200:
|
|
return None
|
|
data = await resp.json()
|
|
return data.get('plainLyrics')
|
|
except Exception:
|
|
return None
|
|
|
|
async def translate_text(self, text: str, target_lang: str) -> str | None:
|
|
translate_url = "https://translate.googleapis.com/translate_a/single"
|
|
params = {
|
|
"client": "gtx",
|
|
"sl": "auto",
|
|
"tl": target_lang,
|
|
"dt": "t",
|
|
"q": text
|
|
}
|
|
async with aiohttp.ClientSession() as session:
|
|
try:
|
|
async with session.get(translate_url, params=params) as resp:
|
|
if resp.status != 200:
|
|
return None
|
|
result = await resp.json()
|
|
translated_chunks = [item[0] for item in result[0] if item[0]]
|
|
return ''.join(translated_chunks)
|
|
except Exception:
|
|
return None
|
|
|
|
async def setup(bot):
|
|
await bot.add_cog(Lyrics(bot))
|