Merge branch '36-show-youtube-thumbnail-in-now-playing-embed' into 'develop'
Resolve "Show youtube thumbnail in "Now playing:" embed" Closes #36 See merge request ekzyis/musicube!28
This commit is contained in:
commit
375a7c36cd
|
@ -1,5 +1,8 @@
|
||||||
{
|
{
|
||||||
"python.pythonPath": "venv/bin/python3.9",
|
"python.pythonPath": "venv/bin/python3.9",
|
||||||
"python.testing.autoTestDiscoverOnSaveEnabled": true,
|
"python.testing.autoTestDiscoverOnSaveEnabled": true,
|
||||||
"pythonTestExplorer.testFramework": "pytest"
|
"pythonTestExplorer.testFramework": "pytest",
|
||||||
|
"python.testing.pytestArgs": ["test"],
|
||||||
|
"python.testing.unittestEnabled": false,
|
||||||
|
"python.testing.pytestEnabled": true
|
||||||
}
|
}
|
||||||
|
|
19
src/bot.py
19
src/bot.py
|
@ -2,8 +2,9 @@ import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass, field
|
||||||
from distutils.util import strtobool
|
from distutils.util import strtobool
|
||||||
|
import re
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
import youtube_dl
|
import youtube_dl
|
||||||
|
@ -25,6 +26,14 @@ class Song:
|
||||||
title: str
|
title: str
|
||||||
webpage_url: str
|
webpage_url: str
|
||||||
audio_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<video_id>[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):
|
class Music(commands.Cog):
|
||||||
|
@ -100,8 +109,8 @@ class Music(commands.Cog):
|
||||||
self._next()
|
self._next()
|
||||||
self.logger.info('Now playing: %s (%s)', song.title, song.webpage_url)
|
self.logger.info('Now playing: %s (%s)', song.title, song.webpage_url)
|
||||||
ctx.voice_client.play(audio, after=after)
|
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)
|
msg = await ctx.send(content=embed.content, embed=embed)
|
||||||
await self._add_skip_button(msg)
|
await self._add_skip_button(msg)
|
||||||
# pylint: disable=broad-except
|
# pylint: disable=broad-except
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
@ -142,8 +151,8 @@ class Music(commands.Cog):
|
||||||
self.logger.info('Qeueing song: %s (%s)', song.title, song.webpage_url)
|
self.logger.info('Qeueing song: %s (%s)', song.title, song.webpage_url)
|
||||||
await self._queue.put((ctx, song))
|
await self._queue.put((ctx, song))
|
||||||
if ctx.voice_client.is_playing():
|
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)
|
await ctx.send(content=embed.content, embed=embed)
|
||||||
|
|
||||||
def _skip(self, voice_client):
|
def _skip(self, voice_client):
|
||||||
"""Skip to next song."""
|
"""Skip to next song."""
|
||||||
|
|
|
@ -13,6 +13,11 @@ class BotMessage(discord.Embed):
|
||||||
**kwargs,
|
**kwargs,
|
||||||
title=title
|
title=title
|
||||||
)
|
)
|
||||||
|
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):
|
class ErrorMessage(BotMessage):
|
||||||
|
@ -31,18 +36,22 @@ class ErrorMessage(BotMessage):
|
||||||
|
|
||||||
|
|
||||||
class NowPlayingMessage(BotMessage):
|
class NowPlayingMessage(BotMessage):
|
||||||
def __init__(self, title, url):
|
def __init__(self, title, url, image_url):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title=f'Now playing: {title}',
|
content='Now playing:',
|
||||||
description=url,
|
title=title,
|
||||||
|
url=url,
|
||||||
|
image_url=image_url,
|
||||||
color=discord.Color.green()
|
color=discord.Color.green()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class QueuedMessage(BotMessage):
|
class QueuedMessage(BotMessage):
|
||||||
def __init__(self, title, url):
|
def __init__(self, title, url, image_url):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
title=f'Queued: {title}',
|
content='Queued:',
|
||||||
description=url,
|
title=title,
|
||||||
|
url=url,
|
||||||
|
image_url=image_url,
|
||||||
color=discord.Color.blue()
|
color=discord.Color.blue()
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,8 +21,8 @@ async def test_bot_ensure_voice(mbot, ctx):
|
||||||
await mbot.ensure_voice(ctx)
|
await mbot.ensure_voice(ctx)
|
||||||
|
|
||||||
|
|
||||||
def mock_ytdl_extract_info(ytdl, url, title):
|
def mock_ytdl_extract_info(ytdl, *, title, webpage_url, audio_url):
|
||||||
ytdl.extract_info.return_value = {'entries': [{'url': url, 'title': title}]}
|
ytdl.extract_info.return_value = {'entries': [{'title': title, 'webpage_url': webpage_url, 'url': audio_url}]}
|
||||||
|
|
||||||
|
|
||||||
def mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio):
|
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
|
ctx.voice_client.is_playing.return_value = False
|
||||||
url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ'
|
url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ'
|
||||||
title = 'In Flames - Deliver Us (Official Video)'
|
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)
|
deliver_us_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio)
|
||||||
query = 'in flames deliver us'
|
query = 'in flames deliver us'
|
||||||
# pylint: disable=too-many-function-args
|
# pylint: disable=too-many-function-args
|
||||||
|
@ -64,14 +64,16 @@ async def test_bot_playback(mbot, ctx):
|
||||||
assert \
|
assert \
|
||||||
ctx.voice_client.play.call_args.args == (deliver_us_audio,), \
|
ctx.voice_client.play.call_args.args == (deliver_us_audio,), \
|
||||||
'Did not playback correct 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']
|
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
|
# TEST: Following songs are put inside a queue
|
||||||
ctx.voice_client.is_playing.return_value = True
|
ctx.voice_client.is_playing.return_value = True
|
||||||
url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg'
|
url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg'
|
||||||
title = 'Three Days Grace - Time of Dying (lyrics)'
|
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)
|
time_of_dying_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio)
|
||||||
# pylint: disable=too-many-function-args
|
# pylint: disable=too-many-function-args
|
||||||
query = 'three days grace time of dying'
|
query = 'three days grace time of dying'
|
||||||
|
@ -85,8 +87,10 @@ async def test_bot_playback(mbot, ctx):
|
||||||
assert \
|
assert \
|
||||||
not ctx.voice_client.play.call_args.args == (time_of_dying_audio,), \
|
not ctx.voice_client.play.call_args.args == (time_of_dying_audio,), \
|
||||||
'Did immediately playback audio instead of being queued'
|
'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']
|
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)
|
await asyncio.sleep(0)
|
||||||
# Assert that there is still no playback because previous song is not finished yet
|
# Assert that there is still no playback because previous song is not finished yet
|
||||||
assert \
|
assert \
|
||||||
|
@ -111,7 +115,7 @@ async def test_bot_skip(mbot, ctx):
|
||||||
ctx.voice_client.is_playing.return_value = False
|
ctx.voice_client.is_playing.return_value = False
|
||||||
url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ'
|
url = 'https://www.youtube.com/watch?v=Wr9LZ1hAFpQ'
|
||||||
title = 'In Flames - Deliver Us (Official Video)'
|
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)
|
deliver_us_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio)
|
||||||
query = 'in flames deliver us'
|
query = 'in flames deliver us'
|
||||||
# pylint: disable=too-many-function-args
|
# pylint: disable=too-many-function-args
|
||||||
|
@ -125,7 +129,7 @@ async def test_bot_skip(mbot, ctx):
|
||||||
ctx.voice_client.is_playing.return_value = True
|
ctx.voice_client.is_playing.return_value = True
|
||||||
url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg'
|
url = 'https://www.youtube.com/watch?v=pMDcYX2wRSg'
|
||||||
title = 'Three Days Grace - Time of Dying (lyrics)'
|
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)
|
time_of_dying_audio = mock_ffmpeg_pcm_audio(ffmpeg_pcm_audio)
|
||||||
# pylint: disable=too-many-function-args
|
# pylint: disable=too-many-function-args
|
||||||
query = 'three days grace time of dying'
|
query = 'three days grace time of dying'
|
||||||
|
|
Loading…
Reference in New Issue