From 5fe52d480d597f9e7207de23bd72a4a893e874da Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 26 Sep 2022 22:25:13 +0200 Subject: [PATCH 1/3] Improve embeds - Use url attribute to add link to title - Add video thumbnail as embed image --- src/bot.py | 15 ++++++++++++--- src/message.py | 13 +++++++++---- test/test_bot.py | 12 ++++++------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/bot.py b/src/bot.py index 55f1002..6098931 100644 --- a/src/bot.py +++ b/src/bot.py @@ -2,8 +2,9 @@ import asyncio import logging import os import sys -from dataclasses import dataclass +from dataclasses import dataclass, field from distutils.util import strtobool +import re import discord import youtube_dl @@ -25,6 +26,14 @@ class Song: title: str webpage_url: str audio_url: str + video_id: str = field(init=False) + image_url: str = field(init=False) + + def __post_init__(self): + video_url = self.webpage_url + if match := re.search(r'youtube\.com\/watch\?v=(?P[a-zA-Z0-9]+)', video_url): + self.video_id = match.group('video_id') + self.image_url = f'https://img.youtube.com/vi/{self.video_id}/hqdefault.jpg' class Music(commands.Cog): @@ -100,7 +109,7 @@ class Music(commands.Cog): self._next() self.logger.info('Now playing: %s (%s)', song.title, song.webpage_url) ctx.voice_client.play(audio, after=after) - embed = NowPlayingMessage(title=song.title, url=song.webpage_url) + embed = NowPlayingMessage(title=song.title, url=song.webpage_url, image_url=song.image_url) msg = await ctx.send(embed=embed) await self._add_skip_button(msg) # pylint: disable=broad-except @@ -142,7 +151,7 @@ class Music(commands.Cog): self.logger.info('Qeueing song: %s (%s)', song.title, song.webpage_url) await self._queue.put((ctx, song)) if ctx.voice_client.is_playing(): - embed = QueuedMessage(title=song.title, url=song.webpage_url) + embed = QueuedMessage(title=song.title, url=song.webpage_url, image_url=song.image_url) await ctx.send(embed=embed) def _skip(self, voice_client): diff --git a/src/message.py b/src/message.py index 87031df..a88a73b 100644 --- a/src/message.py +++ b/src/message.py @@ -13,6 +13,9 @@ class BotMessage(discord.Embed): **kwargs, title=title ) + image_url = kwargs.pop('image_url', None) + if image_url: + super().set_image(url=image_url) class ErrorMessage(BotMessage): @@ -31,18 +34,20 @@ class ErrorMessage(BotMessage): class NowPlayingMessage(BotMessage): - def __init__(self, title, url): + def __init__(self, title, url, image_url): super().__init__( title=f'Now playing: {title}', - description=url, + url=url, + image_url=image_url, color=discord.Color.green() ) class QueuedMessage(BotMessage): - def __init__(self, title, url): + def __init__(self, title, url, image_url): super().__init__( title=f'Queued: {title}', - description=url, + url=url, + image_url=image_url, color=discord.Color.blue() ) diff --git a/test/test_bot.py b/test/test_bot.py index 30ba2f7..85db058 100644 --- a/test/test_bot.py +++ b/test/test_bot.py @@ -21,8 +21,8 @@ async def test_bot_ensure_voice(mbot, ctx): await mbot.ensure_voice(ctx) -def mock_ytdl_extract_info(ytdl, url, title): - ytdl.extract_info.return_value = {'entries': [{'url': url, 'title': title}]} +def mock_ytdl_extract_info(ytdl, *, title, webpage_url, audio_url): + ytdl.extract_info.return_value = {'entries': [{'title': title, 'webpage_url': webpage_url, 'url': audio_url}]} def mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio): @@ -40,7 +40,7 @@ async def test_bot_playback(mbot, ctx): ctx.voice_client.is_playing.return_value = False url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ' title = 'In Flames - Deliver Us (Official Video)' - mock_ytdl_extract_info(ytdl, url, title) + mock_ytdl_extract_info(ytdl, title=title, webpage_url=url, audio_url=url) deliver_us_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio) query = 'in flames deliver us' # pylint: disable=too-many-function-args @@ -71,7 +71,7 @@ async def test_bot_playback(mbot, ctx): ctx.voice_client.is_playing.return_value = True url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg' title = 'Three Days Grace - Time of Dying (lyrics)' - mock_ytdl_extract_info(ytdl, url, title) + mock_ytdl_extract_info(ytdl, title=title, webpage_url=url, audio_url=url) time_of_dying_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio) # pylint: disable=too-many-function-args query = 'three days grace time of dying' @@ -111,7 +111,7 @@ async def test_bot_skip(mbot, ctx): ctx.voice_client.is_playing.return_value = False url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ' title = 'In Flames - Deliver Us (Official Video)' - mock_ytdl_extract_info(ytdl, url, title) + mock_ytdl_extract_info(ytdl, title=title, webpage_url=url, audio_url=url) deliver_us_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio) query = 'in flames deliver us' # pylint: disable=too-many-function-args @@ -125,7 +125,7 @@ async def test_bot_skip(mbot, ctx): ctx.voice_client.is_playing.return_value = True url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg' title = 'Three Days Grace - Time of Dying (lyrics)' - mock_ytdl_extract_info(ytdl, url, title) + mock_ytdl_extract_info(ytdl, title=title, webpage_url=url, audio_url=url) time_of_dying_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio) # pylint: disable=too-many-function-args query = 'three days grace time of dying' From eb9f74ede0edc71764aa2b717b92e1ca4f20fc7e Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 26 Sep 2022 22:33:23 +0200 Subject: [PATCH 2/3] Add pytest to vscode config --- .vscode/settings.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index e52f158..5a82275 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,8 @@ { "python.pythonPath": "venv/bin/python3.9", "python.testing.autoTestDiscoverOnSaveEnabled": true, - "pythonTestExplorer.testFramework": "pytest" + "pythonTestExplorer.testFramework": "pytest", + "python.testing.pytestArgs": ["test"], + "python.testing.unittestEnabled": false, + "python.testing.pytestEnabled": true } From 698ef7cf3cd3fed21b3c9d67a4158d2734d4e08b Mon Sep 17 00:00:00 2001 From: ekzyis Date: Mon, 26 Sep 2022 22:49:46 +0200 Subject: [PATCH 3/3] Move 'Now playing:' from embed to message content --- src/bot.py | 4 ++-- src/message.py | 8 ++++++-- test/test_bot.py | 8 ++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/bot.py b/src/bot.py index 6098931..2b9a781 100644 --- a/src/bot.py +++ b/src/bot.py @@ -110,7 +110,7 @@ class Music(commands.Cog): self.logger.info('Now playing: %s (%s)', song.title, song.webpage_url) ctx.voice_client.play(audio, after=after) embed = NowPlayingMessage(title=song.title, url=song.webpage_url, image_url=song.image_url) - msg = await ctx.send(embed=embed) + msg = await ctx.send(content=embed.content, embed=embed) await self._add_skip_button(msg) # pylint: disable=broad-except except Exception as err: @@ -152,7 +152,7 @@ class Music(commands.Cog): await self._queue.put((ctx, song)) if ctx.voice_client.is_playing(): embed = QueuedMessage(title=song.title, url=song.webpage_url, image_url=song.image_url) - await ctx.send(embed=embed) + await ctx.send(content=embed.content, embed=embed) def _skip(self, voice_client): """Skip to next song.""" diff --git a/src/message.py b/src/message.py index a88a73b..b7b621e 100644 --- a/src/message.py +++ b/src/message.py @@ -16,6 +16,8 @@ class BotMessage(discord.Embed): image_url = kwargs.pop('image_url', None) if image_url: super().set_image(url=image_url) + # Message content before embed + self.content = kwargs.pop('content', None) class ErrorMessage(BotMessage): @@ -36,7 +38,8 @@ class ErrorMessage(BotMessage): class NowPlayingMessage(BotMessage): def __init__(self, title, url, image_url): super().__init__( - title=f'Now playing: {title}', + content='Now playing:', + title=title, url=url, image_url=image_url, color=discord.Color.green() @@ -46,7 +49,8 @@ class NowPlayingMessage(BotMessage): class QueuedMessage(BotMessage): def __init__(self, title, url, image_url): super().__init__( - title=f'Queued: {title}', + content='Queued:', + title=title, url=url, image_url=image_url, color=discord.Color.blue() diff --git a/test/test_bot.py b/test/test_bot.py index 85db058..27db042 100644 --- a/test/test_bot.py +++ b/test/test_bot.py @@ -64,8 +64,10 @@ async def test_bot_playback(mbot, ctx): assert \ ctx.voice_client.play.call_args.args == (deliver_us_audio,), \ 'Did not playback correct audio' + content = ctx.send.call_args.kwargs['content'] + assert content == 'Now playing:', "Did not send 'Now playing:' message" embed = ctx.send.call_args.kwargs['embed'] - assert embed.title == f'Now playing: {title}', "Did not send 'Now playing:' message" + assert embed.title == title, "Did not send 'Now playing:' embed" # TEST: Following songs are put inside a queue ctx.voice_client.is_playing.return_value = True @@ -85,8 +87,10 @@ async def test_bot_playback(mbot, ctx): assert \ not ctx.voice_client.play.call_args.args == (time_of_dying_audio,), \ 'Did immediately playback audio instead of being queued' + content = ctx.send.call_args.kwargs['content'] + assert content == 'Queued:', "Did not send 'Queued:' message" embed = ctx.send.call_args.kwargs['embed'] - assert embed.title == f'Queued: {title}', "Did not send 'Queued:' message" + assert embed.title == title, "Did not send 'Queued:' embed" await asyncio.sleep(0) # Assert that there is still no playback because previous song is not finished yet assert \