Ruby-Cogs/lastfm/nowplaying.py
2025-03-26 10:59:44 -04:00

159 lines
6.3 KiB
Python

import asyncio
from typing import Optional
import discord
from redbot.core.utils.chat_formatting import escape
from redbot.core.utils.menus import DEFAULT_CONTROLS, menu
from .abc import MixinMeta
from .exceptions import *
from .fmmixin import FMMixin
command_fm = FMMixin.command_fm
command_fm_server = FMMixin.command_fm_server
class NowPlayingMixin(MixinMeta):
"""NowPlaying Commands"""
@command_fm.command(name="nowplaying", aliases=["np"])
async def command_nowplaying(self, ctx, user: Optional[discord.Member] = None):
"""Currently playing song or most recent song."""
user = user or ctx.author
async with ctx.typing():
conf = await self.config.user(user).all()
self.check_if_logged_in(conf, user == ctx.author)
data = await self.api_request(
ctx,
{
"user": conf["lastfm_username"],
"method": "user.getrecenttracks",
"limit": 1,
},
)
user_attr = data["recenttracks"]["@attr"]
tracks = data["recenttracks"]["track"]
if not tracks:
return await ctx.send("You have not listened to anything yet!")
try:
artist = tracks[0]["artist"]["#text"]
album = tracks[0]["album"]["#text"]
track = tracks[0]["name"]
image_url = tracks[0]["image"][-1]["#text"]
url = tracks[0]["url"]
except KeyError:
artist = tracks["artist"]["#text"]
album = tracks["album"]["#text"]
track = tracks["name"]
image_url = tracks["image"][-1]["#text"]
url = tracks["url"]
content = discord.Embed(color=await self.bot.get_embed_color(ctx.channel), url=url)
content.description = f"**{escape(album, formatting=True)}**" if album else ""
content.title = (
f"**{escape(artist, formatting=True)}** — ***{escape(track, formatting=True)} ***"
)
content.set_thumbnail(url=image_url)
# tags and playcount
trackdata = await self.api_request(
ctx,
{
"user": conf["lastfm_username"],
"method": "track.getInfo",
"artist": artist,
"track": track,
},
)
if trackdata is not None:
loved = trackdata["track"].get("userloved", "0") == "1"
if loved:
content.title += " :heart:"
tags = []
try:
trackdata = trackdata["track"]
playcount = int(trackdata["userplaycount"])
if playcount > 0:
content.description += f"\n> {playcount} {self.format_plays(playcount)}"
if isinstance(trackdata["toptags"], dict):
for tag in trackdata["toptags"]["tag"]:
if "name" in tag:
tags.append(tag["name"])
else:
tags.append(tag)
if tags:
content.set_footer(text=", ".join(tags))
except KeyError:
pass
# play state
state = "— Most recent track"
try:
if "@attr" in tracks[0]:
if "nowplaying" in tracks[0]["@attr"]:
state = "— Now Playing"
except KeyError:
if "@attr" in tracks:
if "nowplaying" in tracks["@attr"]:
state = "— Now Playing"
content.set_author(
name=f"{user_attr['user']} {state}",
icon_url=user.display_avatar.url,
)
if state == "— Most recent track":
msg = "You aren't currently listening to anything, here is the most recent song found."
else:
msg = None
await ctx.send(msg if msg is not None else None, embed=content)
@command_fm_server.command(name="nowplaying", aliases=["np"])
async def command_servernp(self, ctx):
"""What people on this server are listening to at the moment."""
listeners = []
tasks = []
async with ctx.typing():
userlist = await self.config.all_users()
guildusers = [x.id for x in ctx.guild.members]
userslist = [user for user in userlist if user in guildusers]
for user in userslist:
lastfm_username = userlist[user]["lastfm_username"]
if lastfm_username is None:
continue
member = ctx.guild.get_member(user)
if member is None:
continue
tasks.append(self.get_current_track(ctx, lastfm_username, member, True))
total_linked = len(tasks)
if tasks:
data = await asyncio.gather(*tasks)
data = [i for i in data if i]
for name, artist, album, image, ref in data:
if name is not None:
listeners.append((name, artist, ref))
else:
return await ctx.send("Nobody on this server has connected their last.fm account yet!")
if not listeners:
return await ctx.send("Nobody on this server is listening to anything at the moment!")
total_listening = len(listeners)
rows = []
for name, artist, member in listeners:
rows.append(f"{member.mention} **{artist}** — ***{name}***")
content = discord.Embed(color=await ctx.embed_color())
content.set_author(
name=f"What is {ctx.guild.name} listening to?",
icon_url=ctx.guild.icon.url if ctx.guild.icon else None,
)
content.set_footer(text=f"{total_listening} / {total_linked} Members")
pages = await self.create_pages(content, rows)
if len(pages) > 1:
await menu(ctx, pages, DEFAULT_CONTROLS)
else:
await ctx.send(embed=pages[0])