mirror of
https://github.com/RafaelSolVargas/Vulkan.git
synced 2025-10-29 16:57:23 +00:00
Fixing erros due to processing
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
import asyncio
|
||||
from typing import List
|
||||
from Config.Configs import Configs
|
||||
from yt_dlp import YoutubeDL
|
||||
from yt_dlp import YoutubeDL, DownloadError
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from Music.Song import Song
|
||||
from Utils.Utils import Utils, run_async
|
||||
from Config.Exceptions import DownloadingError
|
||||
|
||||
|
||||
class Downloader:
|
||||
@@ -40,16 +41,20 @@ class Downloader:
|
||||
self.__playlist_keys = ['entries']
|
||||
|
||||
def finish_one_song(self, song: Song) -> Song:
|
||||
if song.identifier is None:
|
||||
return None
|
||||
try:
|
||||
if song.identifier is None:
|
||||
return None
|
||||
|
||||
if Utils.is_url(song.identifier):
|
||||
song_info = self.__download_url(song.identifier)
|
||||
else:
|
||||
song_info = self.__download_title(song.identifier)
|
||||
if Utils.is_url(song.identifier):
|
||||
song_info = self.__download_url(song.identifier)
|
||||
else:
|
||||
song_info = self.__download_title(song.identifier)
|
||||
|
||||
song.finish_down(song_info)
|
||||
return song
|
||||
song.finish_down(song_info)
|
||||
return song
|
||||
# Convert yt_dlp error to my own error
|
||||
except DownloadError:
|
||||
raise DownloadingError()
|
||||
|
||||
async def preload(self, songs: List[Song]) -> None:
|
||||
for song in songs:
|
||||
@@ -81,8 +86,11 @@ class Downloader:
|
||||
else: # Failed to extract the songs
|
||||
print(f'DEVELOPER NOTE -> Failed to Extract URL {url}')
|
||||
return []
|
||||
# Convert the yt_dlp download error to own error
|
||||
except DownloadError:
|
||||
raise DownloadingError()
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Error Extracting Music: {e}')
|
||||
print(f'DEVELOPER NOTE -> Error Extracting Music: {e}, {type(e)}')
|
||||
raise e
|
||||
else:
|
||||
return []
|
||||
|
||||
116
Music/Player.py
116
Music/Player.py
@@ -1,116 +0,0 @@
|
||||
import asyncio
|
||||
from discord.ext import commands
|
||||
from discord import Client, Guild, FFmpegPCMAudio
|
||||
from discord.ext.commands import Context
|
||||
from Music.Downloader import Downloader
|
||||
from Music.Playlist import Playlist
|
||||
from Music.Song import Song
|
||||
from Utils.Utils import Timer
|
||||
|
||||
|
||||
class Player(commands.Cog):
|
||||
def __init__(self, bot: Client, guild: Guild):
|
||||
self.__down: Downloader = Downloader()
|
||||
self.__playlist: Playlist = Playlist()
|
||||
self.__bot: Client = bot
|
||||
self.__guild: Guild = guild
|
||||
|
||||
self.__timer = Timer(self.__timeout_handler)
|
||||
self.__playing = False
|
||||
|
||||
# Flag to control if the player should stop totally the playing
|
||||
self.__force_stop = False
|
||||
self.FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
|
||||
'options': '-vn'}
|
||||
|
||||
@property
|
||||
def playing(self) -> bool:
|
||||
return self.__playing
|
||||
|
||||
@property
|
||||
def playlist(self) -> Playlist:
|
||||
return self.__playlist
|
||||
|
||||
async def play(self, ctx: Context) -> str:
|
||||
if not self.__playing:
|
||||
first_song = self.__playlist.next_song()
|
||||
await self.__play_music(ctx, first_song)
|
||||
|
||||
async def play_prev(self, ctx: Context) -> None:
|
||||
song = self.__playlist.prev_song()
|
||||
if song is not None:
|
||||
if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused():
|
||||
# Will forbidden next_song to execute after stopping current player
|
||||
self.__force_stop = True
|
||||
self.__guild.voice_client.stop()
|
||||
self.__playing = False
|
||||
|
||||
await self.__play_music(ctx, song)
|
||||
|
||||
async def force_stop(self) -> None:
|
||||
try:
|
||||
if self.__guild.voice_client is None:
|
||||
return
|
||||
|
||||
self.__guild.voice_client.stop()
|
||||
await self.__guild.voice_client.disconnect()
|
||||
self.__playlist.clear()
|
||||
self.__playlist.loop_off()
|
||||
except Exception as e:
|
||||
print(f'DEVELOPER NOTE -> Force Stop Error: {e}')
|
||||
|
||||
def __play_next(self, error, ctx: Context) -> None:
|
||||
if self.__force_stop: # If it's forced to stop player
|
||||
self.__force_stop = False
|
||||
return None
|
||||
|
||||
song = self.__playlist.next_song()
|
||||
|
||||
if song is not None:
|
||||
coro = self.__play_music(ctx, song)
|
||||
self.__bot.loop.create_task(coro)
|
||||
else:
|
||||
self.__playing = False
|
||||
|
||||
async def __play_music(self, ctx: Context, song: Song) -> None:
|
||||
try:
|
||||
source = await self.__ensure_source(song)
|
||||
if source is None:
|
||||
self.__play_next(None, ctx)
|
||||
|
||||
self.__playing = True
|
||||
|
||||
player = FFmpegPCMAudio(song.source, **self.FFMPEG_OPTIONS)
|
||||
voice = self.__guild.voice_client
|
||||
voice.play(player, after=lambda e: self.__play_next(e, ctx))
|
||||
|
||||
self.__timer.cancel()
|
||||
self.__timer = Timer(self.__timeout_handler)
|
||||
|
||||
await ctx.invoke(self.__bot.get_command('np'))
|
||||
|
||||
songs = self.__playlist.getSongsToPreload()
|
||||
asyncio.create_task(self.__down.preload(songs))
|
||||
except:
|
||||
self.__play_next(None, ctx)
|
||||
|
||||
async def __timeout_handler(self) -> None:
|
||||
if self.__guild.voice_client is None:
|
||||
return
|
||||
|
||||
if self.__guild.voice_client.is_playing() or self.__guild.voice_client.is_paused():
|
||||
self.__timer = Timer(self.__timeout_handler)
|
||||
|
||||
elif self.__guild.voice_client.is_connected():
|
||||
self.__playlist.clear()
|
||||
self.__playlist.loop_off()
|
||||
await self.__guild.voice_client.disconnect()
|
||||
|
||||
async def __ensure_source(self, song: Song) -> str:
|
||||
while True:
|
||||
await asyncio.sleep(0.1)
|
||||
if song.source is not None: # If song got downloaded
|
||||
return song.source
|
||||
|
||||
if song.problematic: # If song got any error
|
||||
return None
|
||||
@@ -44,6 +44,9 @@ class Playlist:
|
||||
def getCurrentSong(self) -> Song:
|
||||
return self.__current
|
||||
|
||||
def setCurrentSong(self, song: Song) -> Song:
|
||||
self.__current = song
|
||||
|
||||
def getSongsToPreload(self) -> List[Song]:
|
||||
return list(self.__queue)[:self.__configs.MAX_PRELOAD_SONGS]
|
||||
|
||||
@@ -73,6 +76,7 @@ class Playlist:
|
||||
|
||||
# Get the new song
|
||||
if len(self.__queue) == 0:
|
||||
self.__current = None
|
||||
return None
|
||||
|
||||
self.__current = self.__queue.popleft()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from Config.Exceptions import DeezerError, InvalidInput, SpotifyError, YoutubeError
|
||||
from Config.Exceptions import DeezerError, InvalidInput, SpotifyError, VulkanError, YoutubeError
|
||||
from Music.Downloader import Downloader
|
||||
from Music.Types import Provider
|
||||
from Music.SpotifySearcher import SpotifySearch
|
||||
@@ -25,7 +25,10 @@ class Searcher():
|
||||
track = self.__cleanYoutubeInput(track)
|
||||
musics = await self.__down.extract_info(track)
|
||||
return musics
|
||||
except:
|
||||
except VulkanError as error:
|
||||
raise error
|
||||
except Exception as error:
|
||||
print(f'[Error in Searcher] -> {error}, {type(error)}')
|
||||
raise YoutubeError(self.__messages.YOUTUBE_NOT_FOUND, self.__messages.GENERIC_TITLE)
|
||||
|
||||
elif provider == Provider.Spotify:
|
||||
|
||||
@@ -23,6 +23,7 @@ class Song:
|
||||
else:
|
||||
print(f'DEVELOPER NOTE -> {key} not found in info of music: {self.identifier}')
|
||||
self.destroy()
|
||||
return
|
||||
|
||||
for key in self.__useful_keys:
|
||||
if key in info.keys():
|
||||
|
||||
Reference in New Issue
Block a user