Skip to content

Commit

Permalink
fix: make autoplay work with YouTube music radios (#140)
Browse files Browse the repository at this point in the history
* fix: autoplay doesn't function (temporary)

* feat): Autoplay Sources other than YouTube sources are supported.

* chore(requirements.txt): add  youtube-search-python and remove related & search

* style: conform to pep8

* Modify: Misuse of while loops and tasks

* style: conform to pep8

* Refactor(player.py): rename add_music variable to is_adding_music

* Refactor(player.py): Renames unnamed variables

* Refactor(utils.py): use snake_case to rename variable

* fix(lava/utils.py, requirements.txt): optimize get_recommended_tracks function and remove unnecessary dependencies

* feat(lava/classes/player.py): increase autoplay threshold to 30 and handle autoplay failure

* feat(locale/zh_TW.json): add error message for autoplay failure

---------

Co-authored-by: Nat1anWasTaken <nathan@nat1an.xyz>
  • Loading branch information
Mantouisyummy and Nat1anWasTaken authored Jun 14, 2024
1 parent c3cf14f commit 28d1fb8
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 26 deletions.
39 changes: 28 additions & 11 deletions lava/classes/player.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import asyncio
from asyncio import Task
from typing import TYPE_CHECKING, Optional, Union

import pylrc
Expand All @@ -10,6 +9,7 @@
from lavalink import DefaultPlayer, Node, parse_time
from pylrc.classes import Lyrics, LyricLine

from lava.embeds import ErrorEmbed
from lava.utils import get_recommended_tracks, get_image_size, find_lyrics_within_range

if TYPE_CHECKING:
Expand All @@ -27,6 +27,7 @@ def __init__(self, bot: "Bot", guild_id: int, node: Node):
self._guild: Optional[Guild] = None

self.autoplay: bool = False
self.is_adding_song: bool = False
self.show_lyrics: bool = True

self.last_update: int = 0
Expand All @@ -38,8 +39,6 @@ def __init__(self, bot: "Bot", guild_id: int, node: Node):

self._lyrics: Union[Lyrics[LyricLine], None] = None

self.timeout_task: Optional[Task] = None

@property
def lyrics(self) -> Union[Lyrics[LyricLine], None]:
if self._lyrics == MISSING:
Expand Down Expand Up @@ -74,17 +73,39 @@ async def check_autoplay(self) -> bool:
:return: True if tracks were added, False otherwise.
"""
if not self.autoplay or len(self.queue) >= 5:
if not self.autoplay or self.is_adding_song or len(self.queue) >= 30:
return False

self.is_adding_song = True

self.bot.logger.info(
"Queue is empty, adding recommended track for guild %s...", self.guild
)

recommendations = await get_recommended_tracks(self, self.current, 5 - len(self.queue))
recommendations = await get_recommended_tracks(self, self.current, 30 - len(self.queue))

if not recommendations:
self.is_adding_song = False
self.autoplay = False

if self.message:
message = await self.message.channel.send(
embed=ErrorEmbed(
self.bot.get_text(
'error.autoplay_failed', self.locale, '我找不到任何推薦的歌曲,所以我停止了自動播放'
),
)
)

await self.update_display(message, delay=5)

return False

for recommendation in recommendations:
self.add(requester=0, track=recommendation)

self.is_adding_song = False

async def toggle_autoplay(self):
"""
Toggle autoplay for the player.
Expand Down Expand Up @@ -258,9 +279,7 @@ async def update_display(self,
)

async def __generate_lyrics_embed(self) -> Embed:
"""
Generate the lyrics embed for the player.
"""
"""Generate the lyrics embed for the player."""
if self.lyrics is MISSING:
return Embed(
title=self.bot.get_text('display.lyrics.title', self.locale, '🎤 | 歌詞'),
Expand Down Expand Up @@ -433,9 +452,7 @@ def __generate_progress_bar(self, duration: Union[float, int], position: Union[f
f"{self.bot.get_icon('progress.end', 'ED|') if percentage != 1 else self.bot.get_icon('progress.end_point', 'EP')}"

async def is_current_artwork_wide(self) -> bool:
"""
Check if the current playing track's artwork is wide.
"""
"""Check if the current playing track's artwork is wide."""
if not self.current:
return False

Expand Down
31 changes: 18 additions & 13 deletions lava/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

import aiohttp
import imageio
import youtube_related
import youtube_search
from disnake import Interaction
from disnake.utils import get
from lavalink import AudioTrack
Expand Down Expand Up @@ -114,27 +112,34 @@ async def get_recommended_tracks(player: "LavaPlayer", track: AudioTrack, max_re
:param track: The seed tracks to get recommended tracks from.
:param max_results: The max amount of tracks to get.
"""
try:
results_from_youtube = await youtube_related.async_fetch(track.uri)
except ValueError: # The track is not a YouTube track
search_results = youtube_search.YoutubeSearch(f"{track.title} by {track.author}", 1).to_dict()
track = await player.bot.lavalink.decode_track(track.track) # Gets the original track. Usually from YouTube.

results_from_youtube = await youtube_related.async_fetch(
f"https://youtube.com/watch?v={search_results[0]['id']}"
)
if track.source_name != "youtube":
return []

results_from_yt = await player.node.get_tracks(
f"https://music.youtube.com/watch?v={track.identifier}8&list=RD{track.identifier}"
)

results: list[AudioTrack] = []

for result in results_from_youtube:
if result['id'] in [song.identifier for song in player.queue]: # Don't add duplicate songs
skip_first = True

for result_track in results_from_yt.tracks:
if skip_first:
skip_first = False
continue

if result_track.identifier in [t.identifier for t in results]: # Don't add duplicate songs
continue

if len(results) >= max_results:
break

track = (await player.node.get_tracks(f"https://youtube.com/watch?v={result['id']}")).tracks[0]
if result_track.identifier in [t.identifier for t in player.queue]:
continue

results.append(track)
results.append(result_track)

return results

Expand Down
1 change: 1 addition & 0 deletions locale/zh_TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
"display.footer": "如果你覺得音樂怪怪的,可以試著檢查看看效果器設定或是切換語音頻道地區",
"display.lyrics.title": "🎤 | 歌詞",
"display.lyrics.not_found": "*你得自己唱出這首歌的歌詞*",
"error.autoplay_failed": "我找不到任何推薦的歌曲,所以我停止了自動播放"
"display.control.pause": "暫停",
"display.control.resume": "繼續",
"display.control.previous": "重新開始",
Expand Down
2 changes: 0 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,5 @@ imageio==2.34.1
syncedlyrics==0.10.1
pylrc==0.1.2
colorlog
youtube-related
youtube-search
git+https://github.com/Nat1anWasTaken/Lavalink.py.git
git+https://github.com/Snipy7374/disnake-ext-paginator.git

0 comments on commit 28d1fb8

Please sign in to comment.