mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-27 13:34:28 +00:00
Managed to get Play working
This commit is contained in:
parent
4c82a7bf1b
commit
ca0caecb85
7 changed files with 126 additions and 74 deletions
22
poetry.lock
generated
22
poetry.lock
generated
|
@ -268,6 +268,17 @@ version = "2.8.1"
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
six = ">=1.5"
|
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]]
|
[[package]]
|
||||||
category = "main"
|
category = "main"
|
||||||
description = "We have made you a wrapper you can't refuse"
|
description = "We have made you a wrapper you can't refuse"
|
||||||
|
@ -366,6 +377,10 @@ version = "^2.8.4"
|
||||||
optional = true
|
optional = true
|
||||||
version = "^1.3.0"
|
version = "^1.3.0"
|
||||||
|
|
||||||
|
[package.dependencies.python-multipart]
|
||||||
|
optional = true
|
||||||
|
version = "^0.0.5"
|
||||||
|
|
||||||
[package.dependencies.python_telegram_bot]
|
[package.dependencies.python_telegram_bot]
|
||||||
optional = true
|
optional = true
|
||||||
version = "^12.2.0"
|
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)"]
|
alchemy_hard = ["sqlalchemy (^1.3.10)", "psycopg2 (^2.8.4)"]
|
||||||
bard = ["ffmpeg_python (~0.2.0)", "youtube-dl"]
|
bard = ["ffmpeg_python (~0.2.0)", "youtube-dl"]
|
||||||
coloredlogs = ["coloredlogs (^10.0)"]
|
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)"]
|
discord = ["discord.py", "pynacl (^1.3.0)"]
|
||||||
herald = ["websockets (^8.1)"]
|
herald = ["websockets (^8.1)"]
|
||||||
sentry = ["sentry_sdk (~0.13.2)"]
|
sentry = ["sentry_sdk (~0.13.2)"]
|
||||||
telegram = ["python_telegram_bot (^12.2.0)"]
|
telegram = ["python_telegram_bot (^12.2.0)"]
|
||||||
|
|
||||||
[package.source]
|
[package.source]
|
||||||
reference = "f1803f2ffd5507827be1a430d2b09996decfc098"
|
reference = "8ff0731aa5bd167a59f342472bfe2d7e74daf1ca"
|
||||||
type = "git"
|
type = "git"
|
||||||
url = "https://github.com/Steffo99/royalnet/"
|
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.tar.gz", hash = "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c"},
|
||||||
{file = "python_dateutil-2.8.1-py2.py3-none-any.whl", hash = "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"},
|
{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 = [
|
python-telegram-bot = [
|
||||||
{file = "python-telegram-bot-12.2.0.tar.gz", hash = "sha256:346d42771c2b23384c59f5f41e05bd7e801a0ce118d8dcb95209bb73d5f694c5"},
|
{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"},
|
{file = "python_telegram_bot-12.2.0-py2.py3-none-any.whl", hash = "sha256:3beee89cba3bc3217566c96199f04776dd25f541ac8992da27fd247b2d208a14"},
|
||||||
|
|
|
@ -11,7 +11,7 @@ from .videochannel import VideochannelCommand
|
||||||
# from .trivia import TriviaCommand
|
# from .trivia import TriviaCommand
|
||||||
# from .matchmaking import MatchmakingCommand
|
# from .matchmaking import MatchmakingCommand
|
||||||
# from .pause import PauseCommand
|
# from .pause import PauseCommand
|
||||||
# from .play import PlayCommand
|
from .play import PlayCommand
|
||||||
# from .playmode import PlaymodeCommand
|
# from .playmode import PlaymodeCommand
|
||||||
# from .queue import QueueCommand
|
# from .queue import QueueCommand
|
||||||
# from .skip import SkipCommand
|
# from .skip import SkipCommand
|
||||||
|
@ -39,7 +39,7 @@ available_commands = [
|
||||||
# TriviaCommand,
|
# TriviaCommand,
|
||||||
# MatchmakingCommand,
|
# MatchmakingCommand,
|
||||||
# PauseCommand,
|
# PauseCommand,
|
||||||
# PlayCommand,
|
PlayCommand,
|
||||||
# PlaymodeCommand,
|
# PlaymodeCommand,
|
||||||
# QueueCommand,
|
# QueueCommand,
|
||||||
# SkipCommand,
|
# SkipCommand,
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import typing
|
|
||||||
import pickle
|
import pickle
|
||||||
import datetime
|
import base64
|
||||||
import discord
|
import discord
|
||||||
|
from typing import *
|
||||||
from royalnet.commands import *
|
from royalnet.commands import *
|
||||||
from royalnet.utils import asyncify
|
from royalnet.utils import *
|
||||||
from royalnet.audio import YtdlDiscord
|
|
||||||
from royalnet.bots import DiscordBot
|
|
||||||
|
|
||||||
|
|
||||||
class PlayCommand(Command):
|
class PlayCommand(Command):
|
||||||
|
@ -15,65 +13,41 @@ class PlayCommand(Command):
|
||||||
|
|
||||||
description: str = "Aggiunge un url alla coda della chat vocale."
|
description: str = "Aggiunge un url alla coda della chat vocale."
|
||||||
|
|
||||||
syntax = "[ [guild] ] {url}"
|
syntax = "{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)
|
|
||||||
|
|
||||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||||
guild_name, url = args.match(r"(?:\[(.+)])?\s*<?(.+)>?")
|
url = args.joined()
|
||||||
if not (url.startswith("http://") or url.startswith("https://")):
|
# 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"
|
# raise CommandError(f"Il comando [c]{self.interface.prefix}play[/c] funziona solo per riprodurre file da"
|
||||||
f" un URL.\n"
|
# f" un URL.\n"
|
||||||
f"Se vuoi cercare un video, usa [c]{self.interface.prefix}youtube[/c] o"
|
# f"Se vuoi cercare un video, come misura temporanea puoi usare "
|
||||||
f" [c]{self.interface.prefix}soundcloud[/c]!")
|
# f"[c]ytsearch:nomevideo[/c] o [c]scsearch:nomevideo[/c] come url.")
|
||||||
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"]:
|
|
||||||
if self.interface.name == "discord":
|
if self.interface.name == "discord":
|
||||||
# This is one of the unsafest things ever
|
message: discord.Message = data.message
|
||||||
embed = pickle.loads(eval(video["discord_embed_pickle"]))
|
guild: discord.Guild = message.guild
|
||||||
await data.message.channel.send(content="▶️ Aggiunto alla coda:", embed=embed)
|
guild_id: Optional[int] = guild.id
|
||||||
else:
|
else:
|
||||||
await data.reply(f"▶️ Aggiunto alla coda: [i]{video['title']}[/i]")
|
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":
|
||||||
|
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:
|
||||||
|
reply += numberemojiformat([a["title"] for a in added])
|
||||||
|
await data.reply(reply)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import typing
|
import typing
|
||||||
import random
|
import random
|
||||||
from royalnet.commands import *
|
from royalnet.commands import *
|
||||||
from royalnet.utils import safeformat
|
|
||||||
|
|
||||||
|
|
||||||
class SmecdsCommand(Command):
|
class SmecdsCommand(Command):
|
||||||
|
@ -62,8 +61,6 @@ class SmecdsCommand(Command):
|
||||||
"dello Slime God", "del salassato", "della salsa", "di Senjougahara", "di Sugar", "della Stampa",
|
"dello Slime God", "del salassato", "della salsa", "di Senjougahara", "di Sugar", "della Stampa",
|
||||||
"della Stampante"]
|
"della Stampante"]
|
||||||
|
|
||||||
_SMECDS = "🤔 Secondo me, è colpa {ds}."
|
|
||||||
|
|
||||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||||
ds = random.sample(self._DS_LIST, 1)[0]
|
ds = random.sample(self._DS_LIST, 1)[0]
|
||||||
await data.reply(safeformat(self._SMECDS, ds=ds))
|
await data.reply(f"🤔 Secondo me, è colpa {ds}.")
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
# Imports go here!
|
# Imports go here!
|
||||||
from .discord_cv import DiscordCvEvent
|
from .discord_cv import DiscordCvEvent
|
||||||
from .discord_summon import DiscordSummonEvent
|
from .discord_summon import DiscordSummonEvent
|
||||||
|
from .discord_play import DiscordPlayEvent
|
||||||
|
|
||||||
# Enter the commands of your Pack here!
|
# Enter the commands of your Pack here!
|
||||||
available_events = [
|
available_events = [
|
||||||
DiscordCvEvent,
|
DiscordCvEvent,
|
||||||
DiscordSummonEvent,
|
DiscordSummonEvent,
|
||||||
|
DiscordPlayEvent,
|
||||||
]
|
]
|
||||||
|
|
||||||
# noinspection PyUnreachableCode
|
# noinspection PyUnreachableCode
|
||||||
|
|
61
royalpack/events/discord_play.py
Normal file
61
royalpack/events/discord_play.py
Normal 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]
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ class DiscordSummonEvent(Event):
|
||||||
name = "discord_summon"
|
name = "discord_summon"
|
||||||
|
|
||||||
async def run(self, *,
|
async def run(self, *,
|
||||||
channel_name: Optional[str] = None,
|
channel_name: str = "",
|
||||||
channel_id: Optional[int] = None,
|
channel_id: Optional[int] = None,
|
||||||
guild_id: Optional[int] = None,
|
guild_id: Optional[int] = None,
|
||||||
user_id: Optional[int] = None,
|
user_id: Optional[int] = None,
|
||||||
|
@ -27,11 +27,11 @@ class DiscordSummonEvent(Event):
|
||||||
else:
|
else:
|
||||||
member = None
|
member = None
|
||||||
# From channel id
|
# From channel id
|
||||||
if channel_id:
|
if channel_id is not None:
|
||||||
client: discord.Client = self.serf.client
|
client: discord.Client = self.serf.client
|
||||||
channel = client.get_channel(channel_id)
|
channel = client.get_channel(channel_id)
|
||||||
# Find channel
|
# Find channel
|
||||||
elif channel_name is not None:
|
elif channel_name != "":
|
||||||
# Find accessible_to
|
# Find accessible_to
|
||||||
accessible_to = [self.serf.client.user]
|
accessible_to = [self.serf.client.user]
|
||||||
if member is not None:
|
if member is not None:
|
||||||
|
|
Loading…
Reference in a new issue