Fixed some issues with incorrect songs being played in DJ mode.

This commit is contained in:
Jared Kick 2025-07-30 11:52:49 -04:00
parent a7f00f9e43
commit a8b5a59212
2 changed files with 30 additions and 20 deletions

View File

@ -88,28 +88,37 @@ class YTDLSource(discord.PCMVolumeTransformer):
loop = ctx.bot.loop if ctx else asyncio.get_event_loop() loop = ctx.bot.loop if ctx else asyncio.get_event_loop()
# If we got a YouTube link, get the video title for the song search # If we got a YouTube link, get the video title for the song search
if validators.url(search): logger.debug("Search parameter:", search)
if isinstance(search, dict):
search_term = search["title"]
artist_str = f"&artist={search["artist"]}"
elif isinstance(search, str) and validators.url(search):
with YoutubeDL() as ydl: with YoutubeDL() as ydl:
info = ydl.extract_info(search, download=False) info = ydl.extract_info(search, download=False)
search_term = info.get("title", "") search_term = info.get("title", "")
artist_str = ""
else: else:
search_term = search search_term = search
artist_str = ""
# Get song metadata # Get song metadata
logger.info(f"Searching LastFM for: '{search_term}'") logger.info(f"Searching LastFM for: '{search_term}'")
url = f"http://ws.audioscrobbler.com/2.0/?method=track.search&"\ url = f"http://ws.audioscrobbler.com/2.0/?method=track.search&"\
f"track={search_term}&api_key={LASTFM_API_KEY}&format=json" f"track={search_term}{artist_str}&api_key={LASTFM_API_KEY}&format=json"
response = requests.get(url) response = requests.get(url)
lastfm_data = response.json() lastfm_data = response.json()
# Let's get the first result, if any # Let's get the first result, if any
if lastfm_data['results']['trackmatches']['track']: if not lastfm_data['results']['trackmatches']['track']:
raise RuntimeError("LastFM returned no results")
track = lastfm_data['results']['trackmatches']['track'][0] track = lastfm_data['results']['trackmatches']['track'][0]
logger.debug("LastFM match: ", track)
artist = track['artist'] artist = track['artist']
song_title = track['name'] song_title = track['name']
# Adjust search term if we didn't get a URL # Adjust search term if we didn't get a URL
if not validators.url(search): if isinstance(search, dict) and not validators.url(search):
search = f"{song_title} {artist} official audio" search = f"{song_title} {artist} official audio"
logger.debug(f"Search string is not a URL; converting to {search}")
# Get YouTube video source # Get YouTube video source
logger.info(f"Getting YouTube video: {search_term}") logger.info(f"Getting YouTube video: {search_term}")
@ -428,26 +437,23 @@ class MusicPlayer:
"Queue is empty and DJ mode is on. Picking song at random" "Queue is empty and DJ mode is on. Picking song at random"
) )
try: try:
# TEST
user_ids = [m.id for m in self._channel.members] user_ids = [m.id for m in self._channel.members]
channel_ids = [c.id for c in self._channel.guild.channels] channel_ids = [c.id for c in self._channel.guild.channels]
song = self.bot.db.get_next_song(users=user_ids, channels=channel_ids) song = self.bot.db.get_next_song(users=user_ids, channels=channel_ids)
search = f"{song["artist"]} {song["title"]}"
source = await YTDLSource.create_source( source = await YTDLSource.create_source(
None, None,
search, song,
download=True, download=True,
) )
if not source: if not source:
raise RuntimeError("Could not get YouTube source.") raise RuntimeError("Could not get YouTube source.")
except Exception as e: except Exception as e:
# Something's wrong, turn off DJ mode to prevent infinite # # Something's wrong, turn off DJ mode to prevent infinite
# loop # # loop
self.dj_mode = False # self.dj_mode = False
print(e) logger.error(e)
await self._channel.send("Failed to get YouTube source.") # await self._channel.send(str(e))
# For the time being, we're going to use 'None' to signal to the # For the time being, we're going to use 'None' to signal to the
# player that it should go back around and check for a song again, # player that it should go back around and check for a song again,

View File

@ -415,7 +415,9 @@ class Database:
del activity_stats[None] del activity_stats[None]
return activity_stats return activity_stats
def get_next_song(self, users: list[int], channels: list[int], limit: int = 100, cutoff: datetime = datetime.now() - timedelta(hours=1)): def get_next_song(self, users: list[int], channels: list[int], limit: int = 100, cutoff: datetime = None):
_cutoff = datetime.now() - timedelta(hours=1) if not cutoff else cutoff
print("users:", users) print("users:", users)
print("channels:", channels) print("channels:", channels)
@ -466,7 +468,7 @@ class Database:
""" % ( """ % (
",".join(str(id) for id in user_ids), ",".join(str(id) for id in user_ids),
",".join(str(id) for id in channel_ids) ",".join(str(id) for id in channel_ids)
), (cutoff, limit)) ), (_cutoff, limit))
old_song_plays = cursor.fetchall() old_song_plays = cursor.fetchall()
# Compile results into cleaner list of dicts # Compile results into cleaner list of dicts
@ -490,7 +492,7 @@ class Database:
GROUP BY GROUP BY
song_title, song_title,
song_artist; song_artist;
""" % (",".join(str(id) for id in channel_ids)), (cutoff, )) """ % (",".join(str(id) for id in channel_ids)), (_cutoff, ))
recent_song_plays = cursor.fetchall() recent_song_plays = cursor.fetchall()
print("recent:", recent_song_plays) print("recent:", recent_song_plays)
@ -535,7 +537,9 @@ class Database:
"song title is the 'title' key and the artist is "\ "song title is the 'title' key and the artist is "\
"the 'artist' key. I want you to return a song "\ "the 'artist' key. I want you to return a song "\
"title and artist that you would recommend based "\ "title and artist that you would recommend based "\
"on the given songs. You should give me only a bare text "\ "on the given songs. Don't be afraid to branch out "\
"and vary songs; the same artist should not be "\
"repeated more than twice. You should give me only a bare text "\
"string formatted as a Python dict where the "\ "string formatted as a Python dict where the "\
"'title' key is the song title, and the 'artist' "\ "'title' key is the song title, and the 'artist' "\
"key is the song's artist. Don't add anything other "\ "key is the song's artist. Don't add anything other "\