from Exceptions.Exceptions import DownloadingError, InvalidInput, VulkanError from discord.ext.commands import Context from discord import Client from Controllers.AbstractController import AbstractController from Exceptions.Exceptions import ImpossibleMove, UnknownError from Controllers.ControllerResponse import ControllerResponse from Music.Downloader import Downloader from Music.Searcher import Searcher from Music.Song import Song from Parallelism.ProcessManager import ProcessManager from Parallelism.Commands import VCommands, VCommandsType class PlayController(AbstractController): def __init__(self, ctx: Context, bot: Client) -> None: super().__init__(ctx, bot) self.__searcher = Searcher() self.__down = Downloader() async def run(self, args: str) -> ControllerResponse: track = " ".join(args) requester = self.ctx.author.name if not self.__isUserConnected(): error = ImpossibleMove() embed = self.embeds.NO_CHANNEL() return ControllerResponse(self.ctx, embed, error) try: musics = await self.__searcher.search(track) if musics is None or len(musics) == 0: raise InvalidInput(self.messages.INVALID_INPUT, self.messages.ERROR_TITLE) for music in musics: song = Song(music, self.player.playlist, requester) self.player.playlist.add_song(song) quant = len(musics) songs_preload = self.player.playlist.getSongsToPreload() await self.__down.preload(songs_preload) if quant == 1: pos = len(self.player.playlist) song = self.__down.finish_one_song(song) if song.problematic: embed = self.embeds.SONG_PROBLEMATIC() error = DownloadingError() response = ControllerResponse(self.ctx, embed, error) elif not self.player.playing: embed = self.embeds.SONG_ADDED(song.title) response = ControllerResponse(self.ctx, embed) else: embed = self.embeds.SONG_ADDED_TWO(song.info, pos) response = ControllerResponse(self.ctx, embed) else: embed = self.embeds.SONGS_ADDED(quant) response = ControllerResponse(self.ctx, embed) # Get the process context for the current guild manager = ProcessManager(self.bot) processContext = manager.getPlayerContext(self.guild, self.ctx) # Add the downloaded song to the process playlist # All access to shared memory should be protect by acquire the Lock with processContext.getLock(): processContext.getPlaylist().add_song(song) # If process already started send a command to the player process by queue process = processContext.getProcess() queue = processContext.getQueue() if process.is_alive(): command = VCommands(VCommandsType.PLAY) queue.put(command) else: # Start the process process.start() return response except Exception as err: if isinstance(err, VulkanError): # If error was already processed print(f'DEVELOPER NOTE -> PlayController Error: {err.message}') error = err embed = self.embeds.CUSTOM_ERROR(error) else: print(f'DEVELOPER NOTE -> PlayController Error: {err}') error = UnknownError() embed = self.embeds.UNKNOWN_ERROR() return ControllerResponse(self.ctx, embed, error) def __isUserConnected(self) -> bool: if self.ctx.author.voice: return True else: return False