mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-12-17 23:24:20 +00:00
Create queue command
This commit is contained in:
parent
a512da0058
commit
956cdb5ac0
7 changed files with 116 additions and 5 deletions
|
@ -47,6 +47,18 @@ class PlayMode:
|
||||||
"""Delete all :py:class:`royalnet.audio.RoyalPCMAudio` contained inside this PlayMode."""
|
"""Delete all :py:class:`royalnet.audio.RoyalPCMAudio` contained inside this PlayMode."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
|
||||||
|
"""Display all the videos in the PlayMode as a list, if possible.
|
||||||
|
|
||||||
|
To be used with `queue` commands, for example.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
NotImplementedError: If a preview can't be generated.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A list of videos contained in the queue."""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class Playlist(PlayMode):
|
class Playlist(PlayMode):
|
||||||
"""A video list. :py:class:`royalnet.audio.RoyalPCMAudio` played are removed from the list."""
|
"""A video list. :py:class:`royalnet.audio.RoyalPCMAudio` played are removed from the list."""
|
||||||
|
@ -85,6 +97,9 @@ class Playlist(PlayMode):
|
||||||
while self.list:
|
while self.list:
|
||||||
self.list.pop(0).delete()
|
self.list.pop(0).delete()
|
||||||
|
|
||||||
|
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
|
||||||
|
return self.list
|
||||||
|
|
||||||
|
|
||||||
class Pool(PlayMode):
|
class Pool(PlayMode):
|
||||||
"""A :py:class:`royalnet.audio.RoyalPCMAudio` pool. :py:class:`royalnet.audio.RoyalPCMAudio` are selected in random order and are not repeated until every song has been played at least once."""
|
"""A :py:class:`royalnet.audio.RoyalPCMAudio` pool. :py:class:`royalnet.audio.RoyalPCMAudio` are selected in random order and are not repeated until every song has been played at least once."""
|
||||||
|
@ -126,3 +141,8 @@ class Pool(PlayMode):
|
||||||
item.delete()
|
item.delete()
|
||||||
self.pool = None
|
self.pool = None
|
||||||
self._pool_copy = None
|
self._pool_copy = None
|
||||||
|
|
||||||
|
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
|
||||||
|
preview_pool = self.pool.copy()
|
||||||
|
random.shuffle(preview_pool)
|
||||||
|
return preview_pool
|
|
@ -26,9 +26,11 @@ from .videochannel import VideochannelCommand
|
||||||
from .missing import MissingCommand
|
from .missing import MissingCommand
|
||||||
from .cv import CvCommand
|
from .cv import CvCommand
|
||||||
from .pause import PauseCommand
|
from .pause import PauseCommand
|
||||||
|
from .queue import QueueCommand
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand",
|
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand",
|
||||||
"SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand",
|
"SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand",
|
||||||
"KvactiveCommand", "KvCommand", "KvrollCommand", "VideoinfoCommand", "SummonCommand", "PlayCommand",
|
"KvactiveCommand", "KvCommand", "KvrollCommand", "VideoinfoCommand", "SummonCommand", "PlayCommand",
|
||||||
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand", "PauseCommand"]
|
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand", "PauseCommand",
|
||||||
|
"QueueCommand"]
|
||||||
|
|
|
@ -10,6 +10,7 @@ if typing.TYPE_CHECKING:
|
||||||
class PauseNH(NetworkHandler):
|
class PauseNH(NetworkHandler):
|
||||||
message_type = "music_pause"
|
message_type = "music_pause"
|
||||||
|
|
||||||
|
# noinspection PyProtectedMember
|
||||||
@classmethod
|
@classmethod
|
||||||
async def discord(cls, bot: "DiscordBot", data: dict):
|
async def discord(cls, bot: "DiscordBot", data: dict):
|
||||||
# Find the matching guild
|
# Find the matching guild
|
||||||
|
@ -23,7 +24,7 @@ class PauseNH(NetworkHandler):
|
||||||
guild = list(bot.music_data)[0]
|
guild = list(bot.music_data)[0]
|
||||||
# Set the currently playing source as ended
|
# Set the currently playing source as ended
|
||||||
voice_client: discord.VoiceClient = bot.client.find_voice_client_by_guild(guild)
|
voice_client: discord.VoiceClient = bot.client.find_voice_client_by_guild(guild)
|
||||||
if not voice_client.is_playing():
|
if not (voice_client.is_playing() or voice_client.is_paused()):
|
||||||
raise NoneFoundError("Nothing to pause")
|
raise NoneFoundError("Nothing to pause")
|
||||||
# Toggle pause
|
# Toggle pause
|
||||||
resume = voice_client._player.is_paused()
|
resume = voice_client._player.is_paused()
|
||||||
|
|
76
royalnet/commands/queue.py
Normal file
76
royalnet/commands/queue.py
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import typing
|
||||||
|
import pickle
|
||||||
|
from ..network import Request, ResponseSuccess
|
||||||
|
from ..utils import Command, Call, NetworkHandler, numberemojiformat
|
||||||
|
from ..error import TooManyFoundError, NoneFoundError
|
||||||
|
if typing.TYPE_CHECKING:
|
||||||
|
from ..bots import DiscordBot
|
||||||
|
|
||||||
|
|
||||||
|
class QueueNH(NetworkHandler):
|
||||||
|
message_type = "music_queue"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def discord(cls, bot: "DiscordBot", data: dict):
|
||||||
|
# Find the matching guild
|
||||||
|
if data["guild_name"]:
|
||||||
|
guild = bot.client.find_guild_by_name(data["guild_name"])
|
||||||
|
else:
|
||||||
|
if len(bot.music_data) == 0:
|
||||||
|
raise NoneFoundError("No voice clients active")
|
||||||
|
if len(bot.music_data) > 1:
|
||||||
|
raise TooManyFoundError("Multiple guilds found")
|
||||||
|
guild = list(bot.music_data)[0]
|
||||||
|
# Check if the guild has a PlayMode
|
||||||
|
playmode = bot.music_data.get(guild)
|
||||||
|
if not playmode:
|
||||||
|
return ResponseSuccess({
|
||||||
|
"type": None
|
||||||
|
})
|
||||||
|
try:
|
||||||
|
queue = playmode.queue_preview()
|
||||||
|
except NotImplementedError:
|
||||||
|
return ResponseSuccess({
|
||||||
|
"type": playmode.__class__.__name__
|
||||||
|
})
|
||||||
|
return ResponseSuccess({
|
||||||
|
"type": playmode.__class__.__name__,
|
||||||
|
"queue":
|
||||||
|
{
|
||||||
|
"strings": [str(element.rpf.info) for element in queue],
|
||||||
|
"pickled_embeds": str(pickle.dumps([element.rpf.info.to_discord_embed() for element in queue]))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class QueueCommand(Command):
|
||||||
|
|
||||||
|
command_name = "queue"
|
||||||
|
command_description = "Visualizza un'anteprima della coda di riproduzione attuale."
|
||||||
|
command_syntax = "[ [guild] ]"
|
||||||
|
|
||||||
|
network_handlers = [QueueNH]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def common(cls, call: Call):
|
||||||
|
guild, = call.args.match(r"(?:\[(.+)])?")
|
||||||
|
data = await call.net_request(Request("music_queue", {"guild_name": guild}), "discord")
|
||||||
|
if data["type"] is None:
|
||||||
|
await call.reply("ℹ️ Non c'è nessuna coda di riproduzione attiva al momento.")
|
||||||
|
return
|
||||||
|
elif "queue" not in data:
|
||||||
|
await call.reply(f"ℹ️ La coda di riproduzione attuale ([c]{data['type']}[/c]) non permette l'anteprima.")
|
||||||
|
return
|
||||||
|
if data["type"] == "Playlist":
|
||||||
|
message = f"ℹ️ Questa [c]Playlist[/c] contiene {len(data['queue'])} elementi, e i prossimi saranno:\n"
|
||||||
|
elif data["type"] == "Pool":
|
||||||
|
message = f"ℹ️ Questo [c]Pool[/c] contiene {len(data['queue'])} elementi, tra cui:\n"
|
||||||
|
else:
|
||||||
|
message = f"ℹ️ Il PlayMode attuale, [c]{data['type']}[/c], contiene {len(data['queue'])} elementi:\n"
|
||||||
|
if call.interface_name == "discord":
|
||||||
|
await call.reply(message)
|
||||||
|
for embed in pickle.loads(eval(data["queue"]["pickled_embeds"]))[:5]:
|
||||||
|
await call.channel.send(embed=embed)
|
||||||
|
else:
|
||||||
|
message += numberemojiformat(data["queue"]["strings"])
|
||||||
|
await call.reply(message)
|
|
@ -20,7 +20,7 @@ log.setLevel(logging.WARNING)
|
||||||
commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand, DebugCreateCommand, SyncCommand,
|
commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand, DebugCreateCommand, SyncCommand,
|
||||||
AuthorCommand, DiarioCommand, RageCommand, DateparserCommand, ReminderCommand, KvactiveCommand, KvCommand,
|
AuthorCommand, DiarioCommand, RageCommand, DateparserCommand, ReminderCommand, KvactiveCommand, KvCommand,
|
||||||
KvrollCommand, VideoinfoCommand, SummonCommand, PlayCommand, SkipCommand, PlaymodeCommand,
|
KvrollCommand, VideoinfoCommand, SummonCommand, PlayCommand, SkipCommand, PlaymodeCommand,
|
||||||
VideochannelCommand, CvCommand, PauseCommand]
|
VideochannelCommand, CvCommand, PauseCommand, QueueCommand]
|
||||||
|
|
||||||
address, port = "127.0.0.1", 1234
|
address, port = "127.0.0.1", 1234
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ from .safeformat import safeformat
|
||||||
from .classdictjanitor import cdj
|
from .classdictjanitor import cdj
|
||||||
from .sleepuntil import sleep_until
|
from .sleepuntil import sleep_until
|
||||||
from .networkhandler import NetworkHandler
|
from .networkhandler import NetworkHandler
|
||||||
from .formatters import andformat, plusformat, fileformat, ytdldateformat
|
from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat
|
||||||
|
|
||||||
__all__ = ["asyncify", "Call", "Command", "safeformat", "cdj", "sleep_until", "plusformat", "CommandArgs",
|
__all__ = ["asyncify", "Call", "Command", "safeformat", "cdj", "sleep_until", "plusformat", "CommandArgs",
|
||||||
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat"]
|
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat"]
|
||||||
|
|
|
@ -58,3 +58,15 @@ def ytdldateformat(string: typing.Optional[str], separator: str = "-") -> str:
|
||||||
if string is None:
|
if string is None:
|
||||||
return ""
|
return ""
|
||||||
return f"{string[0:4]}{separator}{string[4:6]}{separator}{string[6:8]}"
|
return f"{string[0:4]}{separator}{string[4:6]}{separator}{string[6:8]}"
|
||||||
|
|
||||||
|
|
||||||
|
def numberemojiformat(l: typing.List[str]) -> str:
|
||||||
|
number_emojis = ["1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣", "🔟"]
|
||||||
|
extra_emoji = "*️⃣"
|
||||||
|
result = ""
|
||||||
|
for index, element in enumerate(l):
|
||||||
|
try:
|
||||||
|
result += f"{number_emojis[index]} {element}\n"
|
||||||
|
except IndexError:
|
||||||
|
result += f"{extra_emoji} {element}\n"
|
||||||
|
return result
|
||||||
|
|
Loading…
Reference in a new issue