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:
parent
6c8a93a33e
commit
89c1f6fe22
5 changed files with 74 additions and 14 deletions
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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.")
|
||||||
|
|
Loading…
Reference in a new issue