1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

Play command improvements

This commit is contained in:
Steffo 2019-04-23 15:48:05 +02:00
parent 6c8a93a33e
commit 89c1f6fe22
5 changed files with 74 additions and 14 deletions

View file

@ -10,10 +10,15 @@ class RoyalPCMAudio(AudioSource):
self._file = open(self.rpf.audio_filename, "rb") self._file = open(self.rpf.audio_filename, "rb")
@staticmethod @staticmethod
def create_from_url(url) -> typing.List["RoyalPCMAudio"]: def create_from_url(url: str) -> typing.List["RoyalPCMAudio"]:
rpf_list = RoyalPCMFile.create_from_url(url) rpf_list = RoyalPCMFile.create_from_url(url)
return [RoyalPCMAudio(rpf) for rpf in rpf_list] return [RoyalPCMAudio(rpf) for rpf in rpf_list]
@staticmethod
def create_from_ytsearch(search: str, amount: int = 1) -> typing.List["RoyalPCMAudio"]:
rpf_list = RoyalPCMFile.create_from_ytsearch(search, amount)
return [RoyalPCMAudio(rpf) for rpf in rpf_list]
def is_opus(self): def is_opus(self):
return False return False

View file

@ -48,7 +48,14 @@ class RoyalPCMFile(YtdlFile):
@staticmethod @staticmethod
def create_from_url(url, **ytdl_args) -> typing.List["RoyalPCMFile"]: def create_from_url(url, **ytdl_args) -> typing.List["RoyalPCMFile"]:
info_list = YtdlInfo.create_from_url(url) info_list = YtdlInfo.create_from_url(url)
return [RoyalPCMFile(info) for info in info_list] return [RoyalPCMFile(info, **ytdl_args) for info in info_list]
@staticmethod
def create_from_ytsearch(search: str, amount: int = 1, **ytdl_args) -> typing.List["RoyalPCMFile"]:
"""Search a string on YouTube and download the first amount videos found."""
url = f"ytsearch{amount}:{search}"
info_list = YtdlInfo.create_from_url(url)
return [RoyalPCMFile(info, **ytdl_args) for info in info_list]
@property @property
def _ytdl_filename(self): def _ytdl_filename(self):

View file

@ -53,7 +53,9 @@ class DiscordBot(GenericBot):
.replace("[u]", "__") \ .replace("[u]", "__") \
.replace("[/u]", "__") \ .replace("[/u]", "__") \
.replace("[c]", "`") \ .replace("[c]", "`") \
.replace("[/c]", "`") .replace("[/c]", "`") \
.replace("[p]", "```") \
.replace("[/p]", "```")
await call.channel.send(escaped_text) await call.channel.send(escaped_text)
async def net_request(call, message: Message, destination: str): async def net_request(call, message: Message, destination: str):
@ -203,11 +205,9 @@ class DiscordBot(GenericBot):
await self.client.connect() await self.client.connect()
# TODO: how to stop? # TODO: how to stop?
async def add_to_music_data(self, url: str, guild: discord.Guild): async def add_to_music_data(self, audio_sources: typing.List[discord.AudioSource], guild: discord.Guild):
"""Add a file to the corresponding music_data object.""" """Add a file to the corresponding music_data object."""
log.debug(f"Adding {url} to music_data of {guild}")
guild_music_data = self.music_data[guild] guild_music_data = self.music_data[guild]
audio_sources = await asyncify(RoyalPCMAudio.create_from_url, url)
for audio_source in audio_sources: for audio_source in audio_sources:
log.debug(f"Adding {audio_source} to music_data") log.debug(f"Adding {audio_source} to music_data")
guild_music_data.add(audio_source) guild_music_data.add(audio_source)

View file

@ -48,7 +48,9 @@ class TelegramBot(GenericBot):
.replace("[u]", "<b>") \ .replace("[u]", "<b>") \
.replace("[/u]", "</b>") \ .replace("[/u]", "</b>") \
.replace("[c]", "<code>") \ .replace("[c]", "<code>") \
.replace("[/c]", "</code>") .replace("[/c]", "</code>") \
.replace("[p]", "<pre>") \
.replace("[/p]", "</pre>")
await asyncify(call.channel.send_message, escaped_text, parse_mode="HTML") await asyncify(call.channel.send_message, escaped_text, parse_mode="HTML")
async def net_request(call, message: Message, destination: str): async def net_request(call, message: Message, destination: str):

View file

@ -1,8 +1,11 @@
import typing import typing
import asyncio import asyncio
from ..utils import Command, Call, NetworkHandler import youtube_dl
from ..network import Message, RequestSuccessful import ffmpeg
from ..utils import Command, Call, NetworkHandler, asyncify
from ..network import Message, RequestSuccessful, RequestError
from ..error import TooManyFoundError, NoneFoundError from ..error import TooManyFoundError, NoneFoundError
from ..audio import RoyalPCMAudio, YtdlInfo
if typing.TYPE_CHECKING: if typing.TYPE_CHECKING:
from ..bots import DiscordBot from ..bots import DiscordBot
@ -16,6 +19,11 @@ class PlayMessage(Message):
self.guild_name: typing.Optional[str] = guild_name self.guild_name: typing.Optional[str] = guild_name
class PlaySuccessful(RequestSuccessful):
def __init__(self, info_list: typing.List[YtdlInfo]):
self.info_list: typing.List[YtdlInfo] = info_list
class PlayNH(NetworkHandler): class PlayNH(NetworkHandler):
message_type = PlayMessage message_type = PlayMessage
@ -36,9 +44,12 @@ class PlayNH(NetworkHandler):
# TODO: change Exception # TODO: change Exception
raise Exception("No music_data for this guild") raise Exception("No music_data for this guild")
# Start downloading # Start downloading
# noinspection PyAsyncCall try:
loop.create_task(bot.add_to_music_data(message.url, guild)) audio_sources: typing.List[RoyalPCMAudio] = await asyncify(RoyalPCMAudio.create_from_url, message.url)
return RequestSuccessful() except youtube_dl.utils.DownloadError:
audio_sources = await asyncify(RoyalPCMAudio.create_from_ytsearch, message.url)
await bot.add_to_music_data(audio_sources, guild)
return PlaySuccessful(info_list=[source.rpf.info for source in audio_sources])
class PlayCommand(Command): class PlayCommand(Command):
@ -51,5 +62,40 @@ class PlayCommand(Command):
@classmethod @classmethod
async def common(cls, call: Call): async def common(cls, call: Call):
guild, url = call.args.match(r"(?:\[(.+)])?\s*(.+)") guild, url = call.args.match(r"(?:\[(.+)])?\s*(.+)")
await call.net_request(PlayMessage(url, guild), "discord") response: typing.Union[RequestError, PlaySuccessful] = await call.net_request(PlayMessage(url, guild), "discord")
await call.reply(f"✅ Richiesta la riproduzione di [c]{url}[/c].") if isinstance(response, RequestError):
# RoyalPCMFile errors
if isinstance(response.exc, FileExistsError):
await call.reply(f"❌ Scaricare [c]{url}[/c] significherebbe sovrascrivere un file già esistente.\nQuesto è un bug, e non dovrebbe mai succedere. Se è appena successo, segnalate il problema a https://github.com/Steffo99/royalnet/issues.\n[p]{response.exc}[/p]")
return
# ffmpeg errors
if isinstance(response.exc, ffmpeg.Error):
await call.reply(f"⚠️ Errore durante la conversione a PCM di [c]{url}[/c]:\n[p]{response.exc}[/p]")
return
# youtube_dl errors
if isinstance(response.exc, youtube_dl.utils.ContentTooShortError):
await call.reply(f"⚠️ Mentre era in corso il download di [c]{url}[/c], la connessione è stata interrotta, quindi la riproduzione è stata annullata.\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.UnavailableVideoError):
await call.reply(f"⚠️ Non è disponibile nessun audio su [c]{url}[/c].\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.SameFileError):
await call.reply(f"❌ Scaricare [c]{url}[/c] significherebbe scaricare due file diversi sullo stesso nome.\nQuesto è un bug, e non dovrebbe mai succedere. Se è appena successo, segnalate il problema a https://github.com/Steffo99/royalnet/issues.\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.GeoRestrictedError):
await call.reply(f"⚠️ [c]{url}[/c] non può essere visualizzato nel paese in cui si trova il bot e non può essere scaricato.\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.UnsupportedError):
await call.reply(f"⚠️ [c]{url}[/c] non è supportato da YoutubeDL e non può essere scaricato.\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.ExtractorError):
await call.reply(f"⚠️ Errore nella ricerca di info per [c]{url}[/c]:\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.DownloadError):
await call.reply(f"⚠️ Errore nel download di [c]{url}[/c]:\n[p]{response.exc}[/p]")
return
if isinstance(response.exc, youtube_dl.utils.YoutubeDLError):
await call.reply(f"⚠️ Errore di youtube_dl per [c]{url}[/c]:\n[p]{response.exc}[/p]")
return
for info in response.info_list:
await call.reply(f"⬇️ Download di [i]{info.title}[/i] completato.")