1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-12-03 16:24:20 +00:00

Managed to get Play working

This commit is contained in:
Steffo 2019-12-01 23:53:47 +01:00
parent 4c82a7bf1b
commit ca0caecb85
7 changed files with 126 additions and 74 deletions

22
poetry.lock generated
View file

@ -268,6 +268,17 @@ version = "2.8.1"
[package.dependencies]
six = ">=1.5"
[[package]]
category = "main"
description = "A streaming multipart parser for Python"
name = "python-multipart"
optional = false
python-versions = "*"
version = "0.0.5"
[package.dependencies]
six = ">=1.4.0"
[[package]]
category = "main"
description = "We have made you a wrapper you can't refuse"
@ -366,6 +377,10 @@ version = "^2.8.4"
optional = true
version = "^1.3.0"
[package.dependencies.python-multipart]
optional = true
version = "^0.0.5"
[package.dependencies.python_telegram_bot]
optional = true
version = "^12.2.0"
@ -399,14 +414,14 @@ alchemy_easy = ["sqlalchemy (^1.3.10)", "psycopg2_binary (^2.8.4)"]
alchemy_hard = ["sqlalchemy (^1.3.10)", "psycopg2 (^2.8.4)"]
bard = ["ffmpeg_python (~0.2.0)", "youtube-dl"]
coloredlogs = ["coloredlogs (^10.0)"]
constellation = ["starlette (^0.12.13)", "uvicorn (^0.10.7)"]
constellation = ["starlette (^0.12.13)", "uvicorn (^0.10.7)", "python-multipart (^0.0.5)"]
discord = ["discord.py", "pynacl (^1.3.0)"]
herald = ["websockets (^8.1)"]
sentry = ["sentry_sdk (~0.13.2)"]
telegram = ["python_telegram_bot (^12.2.0)"]
[package.source]
reference = "f1803f2ffd5507827be1a430d2b09996decfc098"
reference = "8ff0731aa5bd167a59f342472bfe2d7e74daf1ca"
type = "git"
url = "https://github.com/Steffo99/royalnet/"
@ -787,6 +802,9 @@ python-dateutil = [
{file = "python-dateutil-2.8.1.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
]
python-multipart = [
{file = "python-multipart-0.0.5.tar.gz", hash = "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43"},
]
python-telegram-bot = [
{file = "python-telegram-bot-12.2.0.tar.gz", hash = "sha256:346d42771c2b23384c59f5f41e05bd7e801a0ce118d8dcb95209bb73d5f694c5"},
{file = "python_telegram_bot-12.2.0-py2.py3-none-any.whl", hash = "sha256:3beee89cba3bc3217566c96199f04776dd25f541ac8992da27fd247b2d208a14"},

View file

@ -11,7 +11,7 @@ from .videochannel import VideochannelCommand
# from .trivia import TriviaCommand
# from .matchmaking import MatchmakingCommand
# from .pause import PauseCommand
# from .play import PlayCommand
from .play import PlayCommand
# from .playmode import PlaymodeCommand
# from .queue import QueueCommand
# from .skip import SkipCommand
@ -39,7 +39,7 @@ available_commands = [
# TriviaCommand,
# MatchmakingCommand,
# PauseCommand,
# PlayCommand,
PlayCommand,
# PlaymodeCommand,
# QueueCommand,
# SkipCommand,

View file

@ -1,11 +1,9 @@
import typing
import pickle
import datetime
import base64
import discord
from typing import *
from royalnet.commands import *
from royalnet.utils import asyncify
from royalnet.audio import YtdlDiscord
from royalnet.bots import DiscordBot
from royalnet.utils import *
class PlayCommand(Command):
@ -15,65 +13,41 @@ class PlayCommand(Command):
description: str = "Aggiunge un url alla coda della chat vocale."
syntax = "[ [guild] ] {url}"
@staticmethod
async def _legacy_play_handler(bot: "DiscordBot", guild_name: typing.Optional[str], url: str):
"""Handle a play Royalnet request. That is, add audio to a PlayMode."""
# Find the matching guild
if guild_name:
guilds: typing.List[discord.Guild] = bot.client.find_guild_by_name(guild_name)
else:
guilds = bot.client.guilds
if len(guilds) == 0:
raise CommandError("Server non trovato.")
if len(guilds) > 1:
raise CommandError("Il nome del server è ambiguo.")
guild = list(bot.client.guilds)[0]
# Ensure the guild has a PlayMode before adding the file to it
if not bot.music_data.get(guild):
raise CommandError("Il bot non è in nessun canale vocale.")
# Create url
ytdl_args = {
"format": "bestaudio/best",
"outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s"
}
# Start downloading
dfiles: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url, url, **ytdl_args)
await bot.add_to_music_data(dfiles, guild)
# Create response dictionary
response = {
"videos": [{
"title": dfile.info.title,
"discord_embed_pickle": str(pickle.dumps(dfile.info.to_discord_embed()))
} for dfile in dfiles]
}
return response
_event_name = "_legacy_play"
def __init__(self, interface: CommandInterface):
super().__init__(interface)
if interface.name == "discord":
interface.register_herald_action(self._event_name, self._legacy_play_handler)
syntax = "{url}"
async def run(self, args: CommandArgs, data: CommandData) -> None:
guild_name, url = args.match(r"(?:\[(.+)])?\s*<?(.+)>?")
if not (url.startswith("http://") or url.startswith("https://")):
raise CommandError(f"Il comando [c]{self.interface.prefix}play[/c] funziona solo per riprodurre file da"
f" un URL.\n"
f"Se vuoi cercare un video, usa [c]{self.interface.prefix}youtube[/c] o"
f" [c]{self.interface.prefix}soundcloud[/c]!")
response: dict = await self.interface.call_herald_action("discord", self._event_name, {
"guild_name": guild_name,
"url": url
})
if len(response["videos"]) == 0:
raise CommandError(f"Nessun file trovato.")
for video in response["videos"]:
url = args.joined()
# if not (url.startswith("http://") or url.startswith("https://")):
# raise CommandError(f"Il comando [c]{self.interface.prefix}play[/c] funziona solo per riprodurre file da"
# f" un URL.\n"
# f"Se vuoi cercare un video, come misura temporanea puoi usare "
# f"[c]ytsearch:nomevideo[/c] o [c]scsearch:nomevideo[/c] come url.")
if self.interface.name == "discord":
message: discord.Message = data.message
guild: discord.Guild = message.guild
guild_id: Optional[int] = guild.id
else:
guild_id = None
response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_play",
url=url, guild_id=guild_id)
too_long: List[Dict[str, Any]] = response["too_long"]
if len(too_long) > 0:
await data.reply(f"{len(too_long)} file non {'è' if len(too_long) == 1 else 'sono'}"
f" stat{'o' if len(too_long) == 1 else 'i'} scaricat{'o' if len(too_long) == 1 else 'i'}"
f" perchè durava{'' if len(too_long) == 1 else 'no'}"
f" più di [c]{self.config['Play']['max_song_duration']}[/c] secondi.")
added: List[Dict[str, Any]] = response["added"]
if len(added) > 0:
reply = f"▶️ Aggiunt{'o' if len(added) == 1 else 'i'} {len(added)} file alla coda:\n"
if self.interface.name == "discord":
# This is one of the unsafest things ever
embed = pickle.loads(eval(video["discord_embed_pickle"]))
await data.message.channel.send(content="▶️ Aggiunto alla coda:", embed=embed)
await data.reply(reply)
for item in added:
embed = pickle.loads(base64.b64decode(bytes(item["stringified_base64_pickled_discord_embed"],
encoding="ascii")))
# noinspection PyUnboundLocalVariable
await message.channel.send(embed=embed)
else:
await data.reply(f"▶️ Aggiunto alla coda: [i]{video['title']}[/i]")
reply += numberemojiformat([a["title"] for a in added])
await data.reply(reply)

View file

@ -1,7 +1,6 @@
import typing
import random
from royalnet.commands import *
from royalnet.utils import safeformat
class SmecdsCommand(Command):
@ -62,8 +61,6 @@ class SmecdsCommand(Command):
"dello Slime God", "del salassato", "della salsa", "di Senjougahara", "di Sugar", "della Stampa",
"della Stampante"]
_SMECDS = "🤔 Secondo me, è colpa {ds}."
async def run(self, args: CommandArgs, data: CommandData) -> None:
ds = random.sample(self._DS_LIST, 1)[0]
await data.reply(safeformat(self._SMECDS, ds=ds))
await data.reply(f"🤔 Secondo me, è colpa {ds}.")

View file

@ -1,11 +1,13 @@
# Imports go here!
from .discord_cv import DiscordCvEvent
from .discord_summon import DiscordSummonEvent
from .discord_play import DiscordPlayEvent
# Enter the commands of your Pack here!
available_events = [
DiscordCvEvent,
DiscordSummonEvent,
DiscordPlayEvent,
]
# noinspection PyUnreachableCode

View file

@ -0,0 +1,61 @@
import discord
import pickle
import base64
import datetime
from typing import *
from royalnet.commands import *
from royalnet.serf.discord import *
from royalnet.bard import *
class DiscordPlayEvent(Event):
name = "discord_play"
async def run(self,
url: str,
guild_id: Optional[int] = None,
**kwargs) -> dict:
if not isinstance(self.serf, DiscordSerf):
raise UnsupportedError()
client: discord.Client = self.serf.client
if len(self.serf.voice_players) == 1:
voice_player: VoicePlayer = self.serf.voice_players[0]
else:
if guild_id is None:
# TODO: trovare un modo per riprodurre canzoni su più server da Telegram
raise InvalidInputError("Non so in che Server riprodurre questo file...\n"
"Invia il comando su Discord, per favore!")
guild: discord.Guild = client.get_guild(guild_id)
if guild is None:
raise InvalidInputError("Impossibile trovare il Server specificato.")
voice_player: VoicePlayer = self.serf.find_voice_player(guild)
if voice_player is None:
raise UserError("Il bot non è in nessun canale vocale.\n"
"Evocalo prima con [c]summon[/c]!")
ytds = await YtdlDiscord.from_url(url)
added: List[YtdlDiscord] = []
too_long: List[YtdlDiscord] = []
if isinstance(voice_player.playing, PlayableYTDQueue):
for ytd in ytds:
if ytd.info.duration >= datetime.timedelta(seconds=self.config["Play"]["max_song_duration"]):
too_long.append(ytd)
continue
await ytd.convert_to_pcm()
added.append(ytd)
voice_player.playing.contents.append(ytd)
if not voice_player.voice_client.is_playing():
await voice_player.start()
else:
raise CommandError(f"Non so come aggiungere musica a [c]{voice_player.playing.__class__.__qualname__}[/c]!")
return {
"added": [{
"title": ytd.info.title,
"stringified_base64_pickled_discord_embed": str(base64.b64encode(pickle.dumps(ytd.embed())),
encoding="ascii")
} for ytd in added],
"too_long": [{
"title": ytd.info.title,
"stringified_base64_pickled_discord_embed": str(base64.b64encode(pickle.dumps(ytd.embed())),
encoding="ascii")
} for ytd in too_long]
}

View file

@ -9,7 +9,7 @@ class DiscordSummonEvent(Event):
name = "discord_summon"
async def run(self, *,
channel_name: Optional[str] = None,
channel_name: str = "",
channel_id: Optional[int] = None,
guild_id: Optional[int] = None,
user_id: Optional[int] = None,
@ -27,11 +27,11 @@ class DiscordSummonEvent(Event):
else:
member = None
# From channel id
if channel_id:
if channel_id is not None:
client: discord.Client = self.serf.client
channel = client.get_channel(channel_id)
# Find channel
elif channel_name is not None:
elif channel_name != "":
# Find accessible_to
accessible_to = [self.serf.client.user]
if member is not None: