예제 #1
0
    async def preload_song(self, ctx: commands.Context) -> None:
        """
        Preload of the next song.
        :param ctx:
        :return:
        """
        try:
            if self.guilds[ctx.guild.id].song_queue.qsize() == 0:
                return
            i = 0
            for item in self.guilds[ctx.guild.id].song_queue.queue:
                item: Song
                if item.stream:
                    continue
                backup_title: str = str(item.title)
                if item.link is not None:
                    try:
                        type_of_source = Url.determine_source(item.link)
                        if type_of_source == Url.youtube_url:
                            youtube_dict = await self.parent.youtube.youtube_url(
                                item.link, ctx.guild.id)
                        elif type_of_source == Url.soundcloud_track:
                            youtube_dict = await self.parent.soundcloud.soundcloud_track(
                                item.link)
                        else:
                            continue
                    except BasicError:
                        self.parent.log(
                            logging_manager.debug_info(traceback.format_exc()))
                        continue
                    youtube_dict.user = item.user
                else:
                    if item.title:
                        continue
                    try:
                        youtube_dict = await self._search_song(ctx, item)
                    except BasicError:
                        continue
                    youtube_dict.user = item.user
                j: int = 0

                for _song in self.guilds[ctx.guild.id].song_queue.queue:
                    _song: Song
                    if _song.title != backup_title:
                        j += 1
                        continue
                    self.guilds[
                        ctx.guild.id].song_queue.queue[j] = Song.copy_song(
                            youtube_dict,
                            self.guilds[ctx.guild.id].song_queue.queue[j],
                        )
                    break
                break
            i += 1
        except IndexError:
            pass
        except AttributeError:
            traceback.print_exc()
예제 #2
0
 def test_song_copy(self):
     """
     Test Song Copy
     @return:
     """
     a = Song(title="Test1", image_url="fest1", duration=1)
     b = Song(image_url="kalb53")
     c = Song.copy_song(a, b)
     self.assertEqual(c.title, "Test1")
     self.assertEqual(c.image_url, "kalb53")
     self.assertEqual(c.duration, 1)
예제 #3
0
    async def preload_song(self, ctx):
        """
        Preload of the next song.
        :param ctx:
        :return:
        """
        try:
            if self.parent.guilds[ctx.guild.id].song_queue.qsize() > 0:
                i = 0
                for item in self.parent.guilds[ctx.guild.id].song_queue.queue:
                    item: Song
                    if item.stream is None:
                        backup_title: str = str(item.title)
                        if item.link is not None:
                            youtube_dict = await self.parent.youtube.youtube_url(
                                item.link, ctx.guild.id)
                            youtube_dict.user = item.user
                        else:
                            if item.title is not None:
                                youtube_dict = await self.parent.youtube.youtube_term(
                                    item)
                            else:
                                youtube_dict = await self.parent.youtube.youtube_term(
                                    item)
                            youtube_dict.user = item.user
                        j: int = 0

                        for _song in self.parent.guilds[
                                ctx.guild.id].song_queue.queue:
                            _song: Song
                            if _song.title == backup_title:
                                self.parent.guilds[
                                    ctx.guild.
                                    id].song_queue.queue[j] = Song.copy_song(
                                        youtube_dict,
                                        self.parent.guilds[
                                            ctx.guild.id].song_queue.queue[j],
                                    )
                                break
                            j -= -1
                        break
                    i += 1
        except IndexError:
            pass
        except AttributeError as e:
            traceback.print_exc()
예제 #4
0
    async def player(self, ctx, small_dict):
        if isinstance(small_dict, Error):
            error_message = small_dict.reason
            await self.parent.send_error_message(ctx, error_message)
            if error_message in (Errors.no_results_found, Errors.default):
                await self.parent.guilds[
                    ctx.guild.id].now_playing_message.message.delete()
                return

            small_dict = Song.copy_song(
                await self.parent.youtube.youtube_url(small_dict.link,
                                                      ctx.guild.id),
                small_dict,
            )

            if isinstance(small_dict, Error):
                self.parent.log.error(small_dict.reason)
                await self.parent.send_error_message(ctx, small_dict.reason)
                return

        try:
            self.parent.guilds[ctx.guild.id].now_playing = small_dict
            if self.parent.guilds[ctx.guild.id].voice_client is None:
                return
            volume = getattr(
                self.parent.guilds[ctx.guild.id],
                "volume",
                await self.parent.mongo.get_volume(ctx.guild.id),
            )
            if small_dict.codec == "opus":
                self.parent.log.debug("Using OPUS Audio.")
                # source = await FFmpegOpusAudioB.from_probe(
                #    small_dict.stream,
                #    volume=volume,
                # before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
                # commented, because of spamming messages of failed reconnects.
                # )
            else:
                # only used for backup soundcloud atm
                self.parent.log.debug("Using PCM Audio.")
                # source = PCMVolumeTransformerB(
                #   FFmpegPCMAudioB(
                #      small_dict.stream,
                #     before_options="-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5",
                # ),
                # volume=volume,
                # )
            try:
                small_dict.guild_id = ctx.guild.id
                self.parent.guilds[ctx.guild.id].voice_client.play(
                    small_dict
                    # source,
                    # after=lambda error: self.song_conclusion(ctx, error=error),
                )
                self.parent.guilds[ctx.guild.id].voice_client.set_after(
                    self.song_conclusion, ctx, error=None)
            except discord.ClientException:
                if ctx.guild.voice_client is None:
                    if (self.parent.guilds[ctx.guild.id].voice_channel
                            is not None):
                        self.parent.guilds[
                            ctx.guild.
                            id].voice_client = await self.parent.guilds[
                                ctx.guild.id
                            ].voice_channel.connect(timeout=10, reconnect=True)
                        small_dict.guild_id = ctx.guild.id
                        self.parent.guilds[ctx.guild.id].voice_client.play(
                            small_dict,
                            # after=lambda error: self.song_conclusion(
                            #    ctx, error=error
                            # ),
                        )
                        self.parent.guilds[
                            ctx.guild.id].voice_client.set_after(
                                self.song_conclusion, ctx, error=None)
            full, empty = await self.parent.mongo.get_chars(ctx.guild.id)
            self.parent.guilds[
                ctx.guild.id].now_playing_message = NowPlayingMessage(
                    ctx=ctx,
                    message=self.parent.guilds[
                        ctx.guild.id].now_playing_message.message,
                    song=self.parent.guilds[ctx.guild.id].now_playing,
                    full=full,
                    empty=empty,
                    discord_music=self.parent,
                    voice_client=self.parent.guilds[ctx.guild.id].voice_client,
                )
            await self.parent.guilds[ctx.guild.id].now_playing_message.send()

        except (Exception, discord.ClientException) as e:
            self.parent.log.debug(
                logging_manager.debug_info(traceback.format_exc(e)))
예제 #5
0
    async def pre_player(self, ctx, bypass=None):
        if (self.parent.guilds[ctx.guild.id].song_queue.qsize() > 0
                or bypass is not None):
            if bypass is None:
                small_dict = await self.parent.guilds[ctx.guild.id
                                                      ].song_queue.get()
            else:
                small_dict = bypass
            self.parent.guilds[
                ctx.guild.id].now_playing_message = NowPlayingMessage(
                    message=await
                    self.parent.send_embed_message(ctx=ctx,
                                                   message=" Loading ... ",
                                                   delete_after=None),
                    ctx=ctx,
                )
            if small_dict.stream is None:
                if small_dict.link is not None:
                    # url
                    _type = Url.determine_source(small_dict.link)
                    if _type == Url.youtube:
                        youtube_dict = Song.copy_song(
                            await self.parent.youtube.youtube_url(
                                small_dict.link, ctx.guild.id),
                            small_dict,
                        )
                    elif _type == Url.soundcloud:
                        youtube_dict = Song.copy_song(
                            await self.parent.soundcloud.soundcloud_track(
                                small_dict.link),
                            small_dict,
                        )
                    else:
                        self.parent.log.warning("Incompatible Song Type: " +
                                                _type)
                        return
                else:
                    if small_dict.title is None:
                        self.parent.log.warning(small_dict)
                    # term
                    youtube_dict = Song.copy_song(
                        await self.parent.youtube.youtube_term(small_dict),
                        small_dict,
                    )
                if isinstance(youtube_dict, Error):
                    if youtube_dict.reason != Errors.error_please_retry:
                        await self.parent.send_error_message(
                            ctx, youtube_dict.reason)
                        await self.parent.guilds[
                            ctx.guild.id].now_playing_message.message.delete()
                        await self.pre_player(ctx)
                        return
                    await self.parent.guilds[
                        ctx.guild.id].now_playing_message.message.delete()
                    await self.pre_player(ctx, bypass=small_dict)
                    return
                youtube_dict.user = small_dict.user
                youtube_dict.image_url = small_dict.image_url
                await self.player(ctx, youtube_dict)
                if hasattr(youtube_dict, "title"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_most_played(
                            youtube_dict.title))
                if hasattr(youtube_dict, "loadtime"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_response_time(
                            youtube_dict.loadtime))
            else:
                await self.player(ctx, small_dict)
                if hasattr(small_dict, "title"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_most_played(small_dict.title))
                if hasattr(small_dict, "loadtime"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_response_time(
                            small_dict.loadtime))

            asyncio.ensure_future(self.preload_song(ctx=ctx))
예제 #6
0
    async def pre_player(self, ctx: commands.Context, bypass=None) -> None:
        """
        Routine called before a song gets played.
        @param ctx:
        @param bypass:
        @return:
        """
        guild_id = ctx.guild.id
        if self.guilds[guild_id].song_queue.qsize() > 0 or bypass is not None:
            if bypass is None:
                small_dict = await self.guilds[ctx.guild.id].song_queue.get()
            else:
                small_dict = bypass
            if small_dict.stream is None:
                try:
                    if small_dict.link is not None:
                        # url
                        _type = Url.determine_source(small_dict.link)
                        if _type == Url.youtube:
                            youtube_dict = Song.copy_song(
                                await self.parent.youtube.youtube_url(
                                    small_dict.link, ctx.guild.id),
                                small_dict,
                            )
                        elif _type == Url.soundcloud:
                            youtube_dict = Song.copy_song(
                                await self.parent.soundcloud.soundcloud_track(
                                    small_dict.link),
                                small_dict,
                            )
                        else:
                            self.parent.log.warning(
                                f"Incompatible Song Type: {_type}")
                            return
                    else:
                        if small_dict.title is None:
                            self.parent.log.warning(small_dict)
                        # term
                        youtube_dict = Song.copy_song(
                            await self._search_song(ctx, small_dict),
                            small_dict)
                except NoResultsFound:
                    await self.parent.send_error_message(
                        ctx, Errors.no_results_found)
                    self.guilds[guild_id].unlock_queue()
                    await self.pre_player(ctx)
                    return
                except SongExtractionException:
                    await self.parent.send_error_message(
                        ctx, Errors.youtube_video_not_available)
                    self.guilds[guild_id].unlock_queue()
                    await self.pre_player(ctx)
                    return
                except (BasicError, asyncio.TimeoutError) as basic_error:
                    if str(basic_error) != Errors.error_please_retry:
                        await self.parent.send_error_message(
                            ctx, str(basic_error))
                        self.guilds[guild_id].unlock_queue()
                        await self.pre_player(ctx)
                        return
                    return await self.pre_player(ctx, bypass=small_dict)
                youtube_dict.user = small_dict.user
                youtube_dict.image_url = small_dict.image_url
                await self.player(ctx, youtube_dict)

                # add stats to website
                if hasattr(youtube_dict, "title"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_most_played(
                            youtube_dict.title))
                if hasattr(youtube_dict, "loadtime"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_response_time(
                            youtube_dict.loadtime))
            else:
                await self.player(ctx, small_dict)
                if hasattr(small_dict, "title"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_most_played(small_dict.title))
                if hasattr(small_dict, "loadtime"):
                    asyncio.ensure_future(
                        self.parent.mongo.append_response_time(
                            small_dict.loadtime))

            asyncio.ensure_future(self.preload_song(ctx=ctx))