Ejemplo n.º 1
0
Archivo: music.py Proyecto: vzymox/Life
    async def volume(self, ctx: context.Context, volume: int = None) -> None:
        """
        Changes the volume of the player.

        `volume`: The volume to change too, between 0 and 100.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if not volume and volume != 0:
            await ctx.send(
                f'The players volume is `{ctx.voice_client.volume}%`.')
            return

        if volume < 0 or volume > 100 and ctx.author.id not in self.bot.config.owner_ids:
            raise exceptions.VoiceError(
                f'That was not a valid volume, Please choose a value between `0` and and `100`.'
            )

        await ctx.voice_client.set_volume(volume=volume)
        await ctx.send(
            f'The players volume is now `{ctx.voice_client.volume}%`.')
Ejemplo n.º 2
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_remove(self, ctx: context.Context, entry: int = 0) -> None:
        """
        Removes a track from the queue.

        `entry`: The position of the track you want to remove.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if ctx.voice_client.queue.is_empty:
            raise exceptions.VoiceError('The players queue is empty.')

        if entry <= 0 or entry > len(ctx.voice_client.queue):
            raise exceptions.VoiceError(
                f'That was not a valid track entry. Choose a number between `1` and `{len(ctx.voice_client.queue)}` '
            )

        item = await ctx.voice_client.queue.get(position=entry - 1,
                                                put_history=False)
        await ctx.send(f'Removed `{item.title}` from the queue.')
Ejemplo n.º 3
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_sort(self,
                         ctx: context.Context,
                         method: Literal['title', 'length', 'author'],
                         reverse: bool = False) -> None:
        """
        Sorts the queue.

        `method`: The method to sort the queue with. Can be `title`, `length` or `author`.
        `reverse`: Whether or not to reverse the sort, as in `5, 3, 2, 4, 1` -> `5, 4, 3, 2, 1` instead of `5, 3, 2, 4, 1` -> `1, 2, 3, 4, 5`.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if ctx.voice_client.queue.is_empty:
            raise exceptions.VoiceError('The players queue is empty.')

        if method == 'title':
            ctx.voice_client.queue._queue.sort(key=lambda track: track.title,
                                               reverse=reverse)
        elif method == 'author':
            ctx.voice_client.queue._queue.sort(key=lambda track: track.author,
                                               reverse=reverse)
        elif method == 'length':
            ctx.voice_client.queue._queue.sort(key=lambda track: track.length,
                                               reverse=reverse)

        await ctx.send(f'The queue has been sorted with method `{method}`.')
Ejemplo n.º 4
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_history(self, ctx: context.Context) -> None:
        """
        Displays the queue history.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        history = list(ctx.voice_client.queue.history)
        if not history:
            raise exceptions.VoiceError('The queue history is empty.')

        time = self.bot.utils.format_seconds(
            seconds=round(sum(track.length for track in history)) / 1000,
            friendly=True)
        header = f'Showing `{min([10, len(history)])}` out of `{len(history)}` track(s) in the queues history. Total queue history time is `{time}`.\n\n'

        entries = [
            f'`{index + 1}.` [{str(track.title)}]({track.uri}) | {self.bot.utils.format_seconds(seconds=round(track.length) / 1000)} | {track.requester.mention}'
            for index, track in enumerate(history)
        ]

        await ctx.paginate_embed(entries=entries,
                                 per_page=10,
                                 title='Queue history:',
                                 header=header)
Ejemplo n.º 5
0
Archivo: music.py Proyecto: vzymox/Life
    async def now_playing(self, ctx: context.Context) -> None:
        """
        Displays the player controller.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        if not ctx.voice_client.is_playing:
            raise exceptions.VoiceError(f'There are no tracks playing.')

        await ctx.voice_client.invoke_controller()
Ejemplo n.º 6
0
Archivo: music.py Proyecto: vzymox/Life
    async def skip(self, ctx: context.Context, amount: int = 1) -> None:
        """
        Skips an amount of tracks.

        `amount`: The amount of tracks to skip. Defaults to 1
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if not ctx.voice_client.is_playing:
            raise exceptions.VoiceError(f'There are no tracks playing.')

        if ctx.voice_client.current.requester.id != ctx.author.id:
            amount = 1

            if ctx.author not in ctx.voice_client.listeners:
                raise exceptions.VoiceError(
                    'You can not vote to skip as you are currently deafened or server deafened.'
                )

            if ctx.author.id in ctx.voice_client.skip_requests:
                ctx.voice_client.skip_requests.remove(ctx.author.id)
                raise exceptions.VoiceError(f'Removed your vote to skip.')
            else:
                ctx.voice_client.skip_requests.append(ctx.author.id)
                await ctx.send('Added your vote to skip.')

            skips_needed = (len(ctx.voice_client.listeners) // 2) + 1
            if len(ctx.voice_client.skip_requests) < skips_needed:
                raise exceptions.VoiceError(
                    f'Currently on `{len(ctx.voice_client.skip_requests)}` out of `{skips_needed}` votes needed to skip.'
                )

        if amount != 1:

            if amount <= 0 or amount > len(ctx.voice_client.queue) + 1:
                raise exceptions.VoiceError(
                    f'There are not enough tracks in the queue to skip that many. Choose a number between `1` and `{len(ctx.voice_client.queue) + 1}`.'
                )

            for index, track in enumerate(ctx.voice_client.queue[:amount - 1]):
                if track.requester.id != ctx.author.id:
                    raise exceptions.VoiceError(
                        f'You only skipped `{index + 1}` out of the next `{amount}` tracks because you were not the requester of all them.'
                    )

                ctx.voice_client.queue.get()

        await ctx.voice_client.stop()
        await ctx.send(
            f'Skipped `{amount}` {"track." if amount == 1 else "tracks."}')
Ejemplo n.º 7
0
Archivo: music.py Proyecto: vzymox/Life
    async def play(self, ctx: context.Context, *, query: str) -> None:
        """
        Plays or queues a track with the given search.

        `query`: The search term to find tracks for. You can prepend this query with soundcloud to search for tracks on soundcloud.

        This command supports youtube/soundcloud searching or youtube, soundcloud, spotify, bandcamp, beam, twitch, and vimeo links.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            await ctx.invoke(self.join)

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        async with ctx.channel.typing():

            search = await ctx.voice_client.search(query=query, ctx=ctx)

            if search.source == 'HTTP' and ctx.author.id not in self.bot.config.owner_ids:
                raise exceptions.VoiceError(
                    'You are unable to play HTTP links.')

            if search.source == 'spotify':

                message = f'Added the Spotify {search.search_type} `{search.search_result.name}` to the queue.'
                if search.search_type in ('album', 'playlist'):
                    message = f'{message[:-1]} with a total of `{len(search.tracks)}` tracks.'

                tracks = search.tracks

            else:

                if search.search_type == 'track':
                    message = f'Added the {search.source} {search.search_type} `{search.tracks[0].title}` to the queue.'
                    tracks = [search.tracks[0]]
                elif search.search_type == 'playlist':
                    message = f'Added the {search.source} {search.search_type} `{search.search_result.name}` to the queue with a total of **{len(search.tracks)}** track(s)'
                    tracks = search.tracks

            ctx.voice_client.queue.put(items=tracks)
            await ctx.send(message)
Ejemplo n.º 8
0
Archivo: music.py Proyecto: vzymox/Life
    async def leave(self, ctx: context.Context) -> None:
        """
        Leaves the voice channel.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        await ctx.send(f'Left the voice channel `{ctx.voice_client.channel}`.')
        await ctx.voice_client.stop()
        await ctx.voice_client.disconnect()
Ejemplo n.º 9
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_loop_current(self, ctx: context.Context) -> None:
        """
        Loops the current track.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        ctx.voice_client.queue.set_looping(
            looping=not ctx.voice_client.queue.is_looping, current=True)
        await ctx.send(
            f'I will {"start" if ctx.voice_client.queue.is_looping else "stop"} looping the current track.'
        )
Ejemplo n.º 10
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_reverse(self, ctx: context.Context) -> None:
        """
        Reverses the queue.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if ctx.voice_client.queue.is_empty:
            raise exceptions.VoiceError('The players queue is empty.')

        ctx.voice_client.queue.reverse()
        await ctx.send(f'The queue has been reversed.')
Ejemplo n.º 11
0
Archivo: music.py Proyecto: vzymox/Life
    async def join(self, ctx: context.Context) -> None:
        """
        Joins your voice channel.
        """

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel:
            raise exceptions.VoiceError(
                'You must be in a voice channel to use this command.')

        if ctx.voice_client and ctx.voice_client.is_connected:
            raise exceptions.VoiceError('I am already in a voice channel.')

        if ctx.voice_client:
            await ctx.voice_client.reconnect(channel=channel)
        else:
            await self.slate.create_player(channel=channel, cls=Player)

        ctx.voice_client.text_channel = ctx.channel
        await ctx.send(f'Joined the voice channel `{channel}`.')
Ejemplo n.º 12
0
Archivo: music.py Proyecto: vzymox/Life
    async def unpause(self, ctx: context.Context) -> None:
        """
        Resumes the player.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if ctx.voice_client.is_paused is False:
            raise exceptions.VoiceError('The player is not paused.')

        await ctx.voice_client.set_pause(pause=False)
        await ctx.send(f'The player is now resumed.')
Ejemplo n.º 13
0
Archivo: music.py Proyecto: vzymox/Life
    async def destroy(self, ctx: context.Context) -> None:
        """
        Completely destroys the guilds player.
        """

        if not ctx.voice_client:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        await ctx.send(f'Destroyed this guilds player.')
        await ctx.voice_client.destroy()
Ejemplo n.º 14
0
    def sort(self, method: str = 'title', reverse: bool = False) -> None:

        if method == 'title':
            self.queue.sort(key=lambda track: track.title, reverse=reverse)
        elif method == 'author':
            self.queue.sort(key=lambda track: track.author, reverse=reverse)
        elif method == 'length':
            self.queue.sort(key=lambda track: track.length, reverse=reverse)
        else:
            raise exceptions.VoiceError('That was not a valid queue sort operation. Please choose either `title`, `length` or `author`')

        self.player.dispatch_event(data={'type': 'PlayerQueueUpdate', 'player': self.player})
Ejemplo n.º 15
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_history_clear(self, ctx: context.Context) -> None:
        """
        Clears the queue history.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        history = list(ctx.voice_client.queue.history)
        if not history:
            raise exceptions.VoiceError('The queue history is empty.')

        ctx.voice_client.queue.clear_history()
        await ctx.send(f'The queue history has been cleared.')
Ejemplo n.º 16
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_move(self,
                         ctx: context.Context,
                         entry_1: int = 0,
                         entry_2: int = 0) -> None:
        """
        Move a track in the queue to a different position.

        `entry_1`: The position of the track you want to move from.
        `entry_2`: The position of the track you want to move too.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if ctx.voice_client.queue.is_empty:
            raise exceptions.VoiceError('The players queue is empty.')

        if entry_1 <= 0 or entry_1 > len(ctx.voice_client.queue):
            raise exceptions.VoiceError(
                f'That was not a valid track entry to move from. Choose a number between `1` and `{len(ctx.voice_client.queue)}` '
            )

        if entry_2 <= 0 or entry_2 > len(ctx.voice_client.queue):
            raise exceptions.VoiceError(
                f'That was not a valid track entry to move too. Choose a number between `1` and `{len(ctx.voice_client.queue)}` '
            )

        track = ctx.voice_client.queue.get(position=entry_1 - 1,
                                           put_history=False)
        ctx.voice_client.queue.put(items=track, position=entry_2 - 1)
        await ctx.send(
            f'Moved `{track.title}` from position `{entry_1}` to position `{entry_2}`.'
        )
Ejemplo n.º 17
0
Archivo: music.py Proyecto: vzymox/Life
    async def seek(self, ctx: context.Context, seconds: int = None) -> None:
        """
        Changes the position of the player.

        `position`: The position to seek too, in seconds.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')

        channel = getattr(ctx.author.voice, 'channel', None)
        if not channel or channel.id != ctx.voice_client.channel.id:
            raise exceptions.VoiceError(
                f'You must be connected to the same voice channel as me to use this command.'
            )

        if not ctx.voice_client.is_playing:
            raise exceptions.VoiceError(f'There are no tracks playing.')

        if not ctx.voice_client.current.is_seekable:
            raise exceptions.VoiceError('The current track is not seekable.')

        if not seconds and seconds != 0:
            await ctx.send(
                f'The players position is `{self.bot.utils.format_seconds(seconds=ctx.voice_client.position / 1000)}`'
            )
            return

        milliseconds = seconds * 1000
        if milliseconds < 0 or milliseconds > ctx.voice_client.current.length:
            raise exceptions.VoiceError(
                f'That was not a valid position. Please choose a value between `0` and `{round(ctx.voice_client.current.length / 1000)}`.'
            )

        await ctx.voice_client.set_position(position=milliseconds)
        await ctx.send(
            f'The players position is now `{self.bot.utils.format_seconds(seconds=milliseconds / 1000)}`.'
        )
Ejemplo n.º 18
0
Archivo: music.py Proyecto: vzymox/Life
    async def queue_detailed(self, ctx: context.Context) -> None:
        """
        Displays detailed information about the queue.
        """

        if not ctx.voice_client or not ctx.voice_client.is_connected:
            raise exceptions.VoiceError(
                'I am not connected to any voice channels.')
        if ctx.voice_client.queue.is_empty:
            raise exceptions.VoiceError('The players queue is empty.')

        entries = []
        for index, track in enumerate(ctx.voice_client.queue):
            embed = discord.Embed(colour=ctx.colour)
            embed.set_image(url=track.thumbnail)
            embed.description = f'Showing detailed information about track `{index + 1}` out of `{len(ctx.voice_client.queue)}` in the queue.\n\n' \
                                f'[{track.title}]({track.uri})\n\n`Author:` {track.author}\n`Source:` {track.source}\n' \
                                f'`Length:` {self.bot.utils.format_seconds(seconds=round(track.length) / 1000, friendly=True)}\n' \
                                f'`Live:` {track.is_stream}\n`Seekable:` {track.is_seekable}\n`Requester:` {track.requester.mention}'
            entries.append(embed)

        await ctx.paginate_embeds(entries=entries)
Ejemplo n.º 19
0
    async def search(self, query: str,
                     ctx: context.Context) -> objects.SearchResult:

        search_result = None
        search_tracks = None

        spotify_url_check = self.spotify_url_regex.match(query)
        if spotify_url_check is not None:

            source = 'spotify'

            spotify_client: spotify.Client = self.bot.cogs["Music"].spotify
            spotify_http_client: spotify.HTTPClient = self.bot.cogs[
                "Music"].spotify_http

            search_type = spotify_url_check.group('type')
            spotify_id = spotify_url_check.group('id')

            try:
                if search_type == 'album':
                    search_result = await spotify_client.get_album(
                        spotify_id=spotify_id)
                    search_tracks = await search_result.get_all_tracks()
                elif search_type == 'playlist':
                    search_result = spotify.Playlist(
                        client=spotify_client,
                        data=await
                        spotify_http_client.get_playlist(spotify_id))
                    search_tracks = await search_result.get_all_tracks()
                elif search_type == 'track':
                    search_result = await spotify_client.get_track(
                        spotify_id=spotify_id)
                    search_tracks = [search_result]

            except spotify.NotFound or HTTPException:
                raise exceptions.VoiceError(
                    f'No results were found for your Spotify link.')
            if not search_tracks:
                raise exceptions.VoiceError(
                    f'No results were found for your Spotify link.')

            tracks = [
                slate.Track(
                    track_id='',
                    ctx=ctx,
                    track_info={
                        'title':
                        track.name or 'Unknown',
                        'author':
                        ', '.join(artist.name
                                  for artist in track.artists) or 'Unknown',
                        'length':
                        track.duration or 0,
                        'identifier':
                        track.id or 'Unknown',
                        'uri':
                        track.url or 'spotify',
                        'isStream':
                        False,
                        'isSeekable':
                        False,
                        'position':
                        0,
                        'thumbnail':
                        track.images[0].url if track.images else None
                    },
                ) for track in search_tracks
            ]

        else:

            url = yarl.URL(query)
            if not url.host or not url.scheme:
                if query.startswith('soundcloud'):
                    query = f'scsearch:{query[11:]}'
                else:
                    query = f'ytsearch:{query}'

            try:
                search_result = await self.node.search(query=query, ctx=ctx)
            except slate.TrackLoadError as error:
                raise exceptions.VoiceError(
                    f'`{error.status_code}` error code while searching for results. For support use `{self.bot.config.prefix}support`.'
                )
            except slate.TrackLoadFailed as error:
                raise exceptions.VoiceError(
                    f'`{error.severity}` error while searching for results. For support use `{self.bot.config.prefix}support`.\nReason: `{error.message}`'
                )

            if not search_result:
                raise exceptions.VoiceError(
                    f'No results were found for your search.')

            if isinstance(search_result, slate.Playlist):
                source = 'youtube'
                search_type = 'playlist'
                tracks = search_result.tracks
            else:
                source = search_result[0].source
                search_type = 'track'
                tracks = search_result

        return objects.SearchResult(source=source,
                                    search_type=search_type,
                                    search_result=search_result,
                                    tracks=tracks)
Ejemplo n.º 20
0
Archivo: music.py Proyecto: vzymox/Life
    async def lyrics(self,
                     ctx: context.Context,
                     *,
                     query: str = 'spotify') -> None:

        if query == 'spotify':

            spotify_activity = discord.utils.find(
                lambda activity: isinstance(activity, discord.Spotify),
                ctx.author.activities)
            if not spotify_activity:
                raise exceptions.VoiceError(
                    'I was unable to detect a Spotify status on your account.')

            query = f'{spotify_activity.title} - {spotify_activity.album} - {spotify_activity.artist}'

        elif query == 'player':

            if not ctx.voice_client or not ctx.voice_client.is_connected:
                raise exceptions.VoiceError(
                    'I am not connected to any voice channels.')
            if not ctx.voice_client.is_playing:
                raise exceptions.VoiceError(f'There are no tracks playing.')

            query = f'{ctx.voice_client.current.title} - {ctx.voice_client.current.requester}'

        try:
            results = await self.ksoft.music.lyrics(query=query, limit=20)
        except ksoftapi.NoResults:
            raise exceptions.ArgumentError(
                f'No results were found for the query `{query}`.')
        except ksoftapi.APIError:
            raise exceptions.VoiceError(
                'The API used to fetch lyrics is currently down/broken.')

        paginator = await ctx.paginate_embed(
            entries=[
                f'`{index + 1}.` {result.name} - {result.artist}'
                for index, result in enumerate(results)
            ],
            per_page=10,
            header=
            f'**__Please choose the number of the track you would like lyrics for:__**\n`Query`: {query}\n\n'
        )

        try:
            response = await self.bot.wait_for(
                'message',
                check=lambda msg: msg.author == ctx.author and msg.channel ==
                ctx.channel,
                timeout=30.0)
        except asyncio.TimeoutError:
            raise exceptions.ArgumentError('You took too long to respond.')

        response = await commands.clean_content().convert(
            ctx=ctx, argument=response.content)
        try:
            response = int(response) - 1
        except ValueError:
            raise exceptions.ArgumentError('That was not a valid number.')
        if response < 0 or response >= len(results):
            raise exceptions.ArgumentError(
                'That was not one of the available lyrics.')

        await paginator.stop()
        result = results[response]

        entries = []
        for line in result.lyrics.split('\n'):

            if not entries:
                entries.append(line)
                continue

            last_entry = entries[-1]
            if len(last_entry) >= 1000 or len(last_entry) + len(line) >= 1000:
                entries.append(line)
                continue

            entries[-1] += f'\n{line}'

        await ctx.paginate_embed(
            entries=entries,
            header=f'Lyrics for `{result.name}` by `{result.artist}`:\n\n',
            embed_add_footer='Lyrics provided by KSoft.Si API.',
            per_page=1)