1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Bugfixes, improvements, experimental pt support

This commit is contained in:
Steffo 2019-12-17 20:11:05 +01:00
parent aa33e24a9d
commit 031f6e1d03
12 changed files with 132 additions and 188 deletions

3
.gitignore vendored
View file

@ -28,4 +28,5 @@ dist/
.idea/**/markdown-navigator.xml .idea/**/markdown-navigator.xml
.idea/**/markdown-exported-files.xml .idea/**/markdown-exported-files.xml
.idea/**/misc.xml .idea/**/misc.xml
.idea/**/*.iml .idea/**/discord.xml
.idea/**/*.iml

View file

@ -23,7 +23,7 @@ from .emojify import EmojifyCommand
from .leagueoflegends import LeagueoflegendsCommand from .leagueoflegends import LeagueoflegendsCommand
from .diarioquote import DiarioquoteCommand from .diarioquote import DiarioquoteCommand
# from .mp3 import Mp3Command # from .mp3 import Mp3Command
from .peertube import PeertubeCommand from .peertubeupdates import PeertubeUpdatesCommand
from .googlevideo import GooglevideoCommand from .googlevideo import GooglevideoCommand
from .yahoovideo import YahoovideoCommand from .yahoovideo import YahoovideoCommand
from .userinfo import UserinfoCommand from .userinfo import UserinfoCommand
@ -58,7 +58,7 @@ available_commands = [
LeagueoflegendsCommand, LeagueoflegendsCommand,
DiarioquoteCommand, DiarioquoteCommand,
# Mp3Command, # Mp3Command,
PeertubeCommand, PeertubeUpdatesCommand,
GooglevideoCommand, GooglevideoCommand,
YahoovideoCommand, YahoovideoCommand,
UserinfoCommand, UserinfoCommand,

View file

@ -10,7 +10,7 @@ class EatCommand(Command):
_FOODS = { _FOODS = {
"_default": "🍗 Hai mangiato {food}!\n[i]Ma non è successo nulla.[/i]", "_default": "🍗 Hai mangiato {food}!\n[i]Ma non è successo nulla.[/i]",
# Sezione nonna # Sezione nonna
"tutto": "👵🏻 Hai mangiato {food}. Si vede che hai gradito il pasto!\n[i]Tua nonna ti serve un'altra" "tutto": "👵🏻 Hai mangiato {food}. Si vede che hai gradito il pasto!\n[i]Tua nonna ti serve un'altra"
" porzione.[/i]", " porzione.[/i]",
@ -21,8 +21,8 @@ class EatCommand(Command):
"qualcosa di non cucinato dalla nonna": "👵🏻 Hai mangiato {food}!\n[i]Potresti essere appena stato " "qualcosa di non cucinato dalla nonna": "👵🏻 Hai mangiato {food}!\n[i]Potresti essere appena stato "
"diseredato...[/i]", "diseredato...[/i]",
"qualcosa di non preparato dalla nonna": "👵🏻 Hai mangiato {food}!\n[i]Potresti essere appena stato " "qualcosa di non preparato dalla nonna": "👵🏻 Hai mangiato {food}!\n[i]Potresti essere appena stato "
"diseredato...[/i]", "diseredato...[/i]",
# Sezione in cui mangi i membri Royal Games # Sezione in cui mangi i membri Royal Games
"balu": "🚹 Hai mangiato {food}.\n[i]Sa di snado.[/i]", "balu": "🚹 Hai mangiato {food}.\n[i]Sa di snado.[/i]",
"evilbalu": "🚹 Hai mangiato {food}.\n[i]Sa di snado.[/i]", "evilbalu": "🚹 Hai mangiato {food}.\n[i]Sa di snado.[/i]",
@ -37,14 +37,14 @@ class EatCommand(Command):
"max": "🚹 Hai mangiato {food}.\n[i]Sa di merda.[/i]", "max": "🚹 Hai mangiato {food}.\n[i]Sa di merda.[/i]",
"maxsensei": "🚹 Hai mangiato {food}.\n[i]Sa di merda.[/i]", "maxsensei": "🚹 Hai mangiato {food}.\n[i]Sa di merda.[/i]",
"steffo": "🚹 Hai mangiato {food}.\n[i]Sa di gelato e di Coca-Cola.[/i]", "steffo": "🚹 Hai mangiato {food}.\n[i]Sa di gelato e di Coca-Cola.[/i]",
#Sezione delle supercazzole # Sezione delle supercazzole
"antani": "❔ Hai mangiato {food}. \n[i]Con tarapia tapioco o scherziamo? No, mi permetta. Noi siamo in 4.\n" "antani": "❔ Hai mangiato {food}. \n[i]Con tarapia tapioco o scherziamo? No, mi permetta. Noi siamo in 4.\n"
"Come se fosse antani anche per lei soltanto in due, oppure in quattro anche scribàcchi confaldina?\n" "Come se fosse antani anche per lei soltanto in due, oppure in quattro anche scribàcchi confaldina?\n"
"Come antifurto, per esempio.[/i]" "Come antifurto, per esempio.[/i]",
"indice": "☝️ Hai mangiato l'{food}. \n[i]Ecco, lo alzi. Lo vede, lo vede che stuzzica?[/i]", "indice": "☝️ Hai mangiato l'{food}. \n[i]Ecco, lo alzi. Lo vede, lo vede che stuzzica?[/i]",
#sezione con piante e anmali # sezione con piante e anmali
"cactus": "🌵 Hai mangiato un {food}.\n[i]Gli hai tolto le spine prima, vero?[/i]", "cactus": "🌵 Hai mangiato un {food}.\n[i]Gli hai tolto le spine prima, vero?[/i]",
"tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n[i]Senti le tue ferite curarsi...[/i]", "tango": "🌳 Hai mangiato un {food}, e un albero insieme ad esso.\n[i]Senti le tue ferite curarsi...[/i]",
"gatto": "🐱 Vieni fermato prima di poter compiere questo gesto orribile.\n" "gatto": "🐱 Vieni fermato prima di poter compiere questo gesto orribile.\n"
@ -55,8 +55,8 @@ class EatCommand(Command):
"ragno": "🕸 Hai mangiato un {food}.\n[i]Ewww![/i]", "ragno": "🕸 Hai mangiato un {food}.\n[i]Ewww![/i]",
"crab": "🦀 Hai mangiato un {food}. {food} is gone!\n[i]Senti il tuo stomaco ballare.[/i]", "crab": "🦀 Hai mangiato un {food}. {food} is gone!\n[i]Senti il tuo stomaco ballare.[/i]",
"granchio": "🦀 Hai mangiato un {food}. {food} is gone!\n[i]Senti il tuo stomaco ballare.[/i]", "granchio": "🦀 Hai mangiato un {food}. {food} is gone!\n[i]Senti il tuo stomaco ballare.[/i]",
#Sezione con il cibo "normale" # Sezione con il cibo "normale"
"zucca": "🎃 Hai mangiato una {food}. Solo che era una lanterna di Halloween.\n[i]Inizi a fare luce al" "zucca": "🎃 Hai mangiato una {food}. Solo che era una lanterna di Halloween.\n[i]Inizi a fare luce al"
" buio.[/i]", " buio.[/i]",
"mela": "🍎 Hai mangiato una Mela, e hai fatto bene perché una mela al giorno toglie il medico di torno!\n" "mela": "🍎 Hai mangiato una Mela, e hai fatto bene perché una mela al giorno toglie il medico di torno!\n"
@ -80,8 +80,8 @@ class EatCommand(Command):
"gelato": "🍨 Mangiando del {food}, hai invocato Steffo.\n[i]Cedigli ora il tuo gelato.[/i]", "gelato": "🍨 Mangiando del {food}, hai invocato Steffo.\n[i]Cedigli ora il tuo gelato.[/i]",
"biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]", "biscotto": "🍪 Hai mangiato un {food} di contrabbando.\n[i]L'Inquisizione non lo saprà mai![/i]",
"biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]", "biscotti": "🍪 Hai mangiato tanti {food} di contrabbando.\n[i]Attento! L'Inquisizione è sulle tue tracce![/i]",
#Sezione delle bevande # Sezione delle bevande
"acqua": "💧 Hai bevuto un po' d'{food}.\n[i]Ti depura e ti fa fare tanta plin plin![/i}", "acqua": "💧 Hai bevuto un po' d'{food}.\n[i]Ti depura e ti fa fare tanta plin plin![/i}",
"cochina": "🥫 Hai bevuto una {food}. \n[i]Bella fresca.[/i]", "cochina": "🥫 Hai bevuto una {food}. \n[i]Bella fresca.[/i]",
"caffè": "☕️ Oh, no! Questo era il {food} della Peppina!\n[i]Ha provato col tritolo, salti in aria col" "caffè": "☕️ Oh, no! Questo era il {food} della Peppina!\n[i]Ha provato col tritolo, salti in aria col"
@ -97,7 +97,7 @@ class EatCommand(Command):
"birra": "🍺 Hai mangiato {food}.\n[i]Adesso sei un povero barbone alcolizzato.[/i]", "birra": "🍺 Hai mangiato {food}.\n[i]Adesso sei un povero barbone alcolizzato.[/i]",
"redbull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]", "redbull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]",
"red bull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]", "red bull": "🍾 Hai mangiato {food}.\n[i]Adesso puoi volare![/i]",
# Distribuzioni # Distribuzioni
"linux": "🐧 Hai mangiato {food}.\n[i]Senti systemd battere nel tuo cuore, adesso.[/i]", "linux": "🐧 Hai mangiato {food}.\n[i]Senti systemd battere nel tuo cuore, adesso.[/i]",
"arch": "🐧 Hai mangiato {food}, btw.\n[i]Ti senti più vicino a pacman, adesso.[/i]", "arch": "🐧 Hai mangiato {food}, btw.\n[i]Ti senti più vicino a pacman, adesso.[/i]",
@ -109,7 +109,7 @@ class EatCommand(Command):
"red hat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]", "red hat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]",
"redhat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]", "redhat": "🐧 Hai mangiato {food}.\n[i]La tua anima appartiene a IBM, ora.[/i]",
"linux from scratch": "🐧 Hai mangiato {food}.\n[i]Sei diventato un puzzle.[/i]", "linux from scratch": "🐧 Hai mangiato {food}.\n[i]Sei diventato un puzzle.[/i]",
# Altro # Altro
"demone": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]", "demone": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]",
"diavolo": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]", "diavolo": "👿 Hai mangiato un {food}. Non l'ha presa bene...\n[i]Hai terribili bruciori di stomaco.[/i]",
@ -137,7 +137,7 @@ class EatCommand(Command):
"niente": "⬜️ Non hai mangiato {food}.\n[i]Hai ancora più fame.[/i]", "niente": "⬜️ Non hai mangiato {food}.\n[i]Hai ancora più fame.[/i]",
"nulla": "⬜️ Non hai mangiato {food}.\n[i]Hai ancora più fame.[/i]", "nulla": "⬜️ Non hai mangiato {food}.\n[i]Hai ancora più fame.[/i]",
"torta": "⬜️ Non hai mangiato niente.\n[i]La {food} è una menzogna![/i]", "torta": "⬜️ Non hai mangiato niente.\n[i]La {food} è una menzogna![/i]",
"cake": "⬜️ Non hai mangiato niente.\n[i]The {food} is a lie![/i]", "cake": "⬜️ Non hai mangiato niente.\n[i]The {food} is a lie![/i]",
} }
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:

View file

@ -10,6 +10,7 @@ class GooglevideoCommand(PlayCommand):
syntax = "{ricerca}" syntax = "{ricerca}"
_URL_FORMAT = "gvsearch:{url}" async def get_url(self, args):
return f"gvsearch:{args.joined()}"
# Too bad gvsearch: always finds nothing. # Too bad gvsearch: always finds nothing.

View file

@ -1,75 +1,24 @@
import aiohttp from .play import PlayCommand
import asyncio
import datetime
import logging
import dateparser
from royalnet.commands import * from royalnet.commands import *
from royalnet.serf.telegram.escape import escape import aiohttp
import urllib.parse
log = logging.getLogger(__name__) class PeertubeCommand(PlayCommand):
class PeertubeCommand(Command):
name: str = "peertube" name: str = "peertube"
description: str = "Guarda quando è uscito l'ultimo video su RoyalTube." aliases = ["pt", "royaltube", "rt"]
_ready = asyncio.Event() description: str = "Cerca un video su RoyalTube e lo aggiunge alla coda della chat vocale."
_latest_date: datetime.datetime = None syntax = "{ricerca}"
def __init__(self, interface: CommandInterface): async def get_url(self, args):
super().__init__(interface) search = urllib.parse.quote(args.joined(require_at_least=1))
if self.interface.name == "telegram":
self.loop.create_task(self._ready_up())
self.loop.create_task(self._update())
async def _get_json(self):
log.debug("Getting jsonfeed")
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
async with session.get(self.config["Peertube"]["feed_url"]) as response: async with session.get(self.config["Peertube"]["instance_url"] +
log.debug("Parsing jsonfeed") f"/api/v1/search/videos?search={search}") as response:
j = await response.json() j = await response.json()
log.debug("Jsonfeed parsed successfully") if j["total"] < 1:
return j raise InvalidInputError("Nessun video trovato.")
return f'{self.config["Peertube"]["instance_url"]}/videos/watch/{j["data"][0]["uuid"]}'
async def _send(self, message):
client = self.interface.bot.client
await self.interface.bot.safe_api_call(client.send_message,
chat_id=self.config["Telegram"]["main_group_id"],
text=escape(message),
parse_mode="HTML",
disable_webpage_preview=True)
async def _ready_up(self):
j = await self._get_json()
if j["version"] != "https://jsonfeed.org/version/1":
raise ConfigurationError("url is not a jsonfeed")
videos = j["items"]
for video in reversed(videos):
date_modified = dateparser.parse(video["date_modified"])
if self._latest_date is None or date_modified > self._latest_date:
log.debug(f"Found newer video: {date_modified}")
self._latest_date = date_modified
self._ready.set()
async def _update(self):
await self._ready.wait()
while True:
j = await self._get_json()
videos = j["items"]
for video in reversed(videos):
date_modified = dateparser.parse(video["date_modified"])
if date_modified > self._latest_date:
log.debug(f"Found newer video: {date_modified}")
self._latest_date = date_modified
await self._send(f"🆕 Nuovo video su RoyalTube!\n"
f"[b]{video['title']}[/b]\n"
f"{video['url']}")
await asyncio.sleep(self.config["Peertube"]["feed_update_timeout"])
async def run(self, args: CommandArgs, data: CommandData) -> None:
if self.interface.name != "telegram":
raise UnsupportedError()
await data.reply(f" Ultimo video caricato il: [b]{self._latest_date.isoformat()}[/b]")

View file

@ -0,0 +1,78 @@
import aiohttp
import asyncio
import datetime
import logging
import dateparser
from royalnet.commands import *
from royalnet.serf.telegram.escape import escape
log = logging.getLogger(__name__)
class PeertubeUpdatesCommand(Command):
name: str = "peertubeupdates"
description: str = "Guarda quando è uscito l'ultimo video su PeerTube."
aliases = ["ptu"]
_ready = asyncio.Event()
_latest_date: datetime.datetime = None
def __init__(self, interface: CommandInterface):
super().__init__(interface)
if self.interface.name == "telegram":
self.loop.create_task(self._ready_up())
self.loop.create_task(self._update())
async def _get_json(self):
log.debug("Getting jsonfeed")
async with aiohttp.ClientSession() as session:
async with session.get(self.config["Peertube"]["instance_url"] +
"/feeds/videos.json?sort=-publishedAt&filter=local") as response:
log.debug("Parsing jsonfeed")
j = await response.json()
log.debug("Jsonfeed parsed successfully")
return j
async def _send(self, message):
client = self.interface.bot.client
await self.interface.bot.safe_api_call(client.send_message,
chat_id=self.config["Telegram"]["main_group_id"],
text=escape(message),
parse_mode="HTML",
disable_webpage_preview=True)
async def _ready_up(self):
j = await self._get_json()
if j["version"] != "https://jsonfeed.org/version/1":
raise ConfigurationError("url is not a jsonfeed")
videos = j["items"]
for video in reversed(videos):
date_modified = dateparser.parse(video["date_modified"])
if self._latest_date is None or date_modified > self._latest_date:
log.debug(f"Found newer video: {date_modified}")
self._latest_date = date_modified
self._ready.set()
async def _update(self):
await self._ready.wait()
while True:
j = await self._get_json()
videos = j["items"]
for video in reversed(videos):
date_modified = dateparser.parse(video["date_modified"])
if date_modified > self._latest_date:
log.debug(f"Found newer video: {date_modified}")
self._latest_date = date_modified
await self._send(f"🆕 Nuovo video su RoyalTube!\n"
f"[b]{video['title']}[/b]\n"
f"{video['url']}")
await asyncio.sleep(self.config["Peertube"]["feed_update_timeout"])
async def run(self, args: CommandArgs, data: CommandData) -> None:
if self.interface.name != "telegram":
raise UnsupportedError()
await data.reply(f" Ultimo video caricato il: [b]{self._latest_date.isoformat()}[/b]")

View file

@ -15,10 +15,10 @@ class PlayCommand(Command):
syntax = "{url}" syntax = "{url}"
_URL_FORMAT = "{url}" async def get_url(self, args: CommandArgs):
return args.joined()
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
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"
@ -27,11 +27,14 @@ class PlayCommand(Command):
if self.interface.name == "discord": if self.interface.name == "discord":
message: discord.Message = data.message message: discord.Message = data.message
guild: discord.Guild = message.guild guild: discord.Guild = message.guild
guild_id: Optional[int] = guild.id if guild is None:
guild_id = None
else:
guild_id: Optional[int] = guild.id
else: else:
guild_id = None guild_id = None
response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_play", response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_play",
url=self._URL_FORMAT.format(url=url), url=await self.get_url(args),
guild_id=guild_id) guild_id=guild_id)
too_long: List[Dict[str, Any]] = response["too_long"] too_long: List[Dict[str, Any]] = response["too_long"]
@ -56,4 +59,4 @@ class PlayCommand(Command):
await data.reply(reply) await data.reply(reply)
if len(added) + len(too_long) == 0: if len(added) + len(too_long) == 0:
raise ExternalError("Nessun video trovato.") raise ExternalError("Nessun video trovato.")

View file

@ -76,11 +76,11 @@ class ReminderCommand(Command):
else: else:
raise UnsupportedError("This command does not support the current interface.") raise UnsupportedError("This command does not support the current interface.")
creator = await data.get_author() creator = await data.get_author()
reminder = self.interface.alchemy.Reminder(creator=creator, reminder = self.interface.alchemy.get(Reminder)(creator=creator,
interface_name=self.interface.name, interface_name=self.interface.name,
interface_data=interface_data, interface_data=interface_data,
datetime=date, datetime=date,
message=reminder_text) message=reminder_text)
self.interface.loop.create_task(self._remind(reminder)) self.interface.loop.create_task(self._remind(reminder))
data.session.add(reminder) data.session.add(reminder)
await asyncify(data.session.commit) await asyncify(data.session.commit)

View file

@ -10,4 +10,5 @@ class SoundcloudCommand(PlayCommand):
syntax = "{ricerca}" syntax = "{ricerca}"
_URL_FORMAT = "scsearch:{url}" async def get_url(self, args):
return f"scsearch:{args.joined()}"

View file

@ -10,6 +10,7 @@ class YahoovideoCommand(PlayCommand):
syntax = "{ricerca}" syntax = "{ricerca}"
_URL_FORMAT = "yvsearch:{url}" async def get_url(self, args):
return f"yvsearch:{args.joined()}"
# Too bad yvsearch: always finds nothing. # Too bad yvsearch: always finds nothing.

View file

@ -10,4 +10,5 @@ class YoutubeCommand(PlayCommand):
syntax = "{ricerca}" syntax = "{ricerca}"
_URL_FORMAT = "ytsearch:{url}" async def get_url(self, args):
return f"ytsearch:{args.joined()}"

View file

@ -1,91 +0,0 @@
import typing
import discord
import asyncio
import datetime
from royalnet.commands import *
from royalnet.utils import asyncify
from royalnet.audio import YtdlDiscord
from royalnet.audio.playmodes import Playlist
from royalnet.bots import DiscordBot
class ZawarudoCommand(Command):
name: str = "zawarudo"
aliases = ["theworld", "world"]
description: str = "Ferma il tempo!"
syntax = "[ [guild] ] [1-9]"
@staticmethod
async def _legacy_zawarudo_handler(bot: "DiscordBot", guild_name: typing.Optional[str], time: int):
# 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",
"outtmpl": f"./downloads/{datetime.datetime.now().timestamp()}_%(title)s.%(ext)s"
}
# Start downloading
zw_start: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url,
"https://scaleway.steffo.eu/jojo/zawarudo_intro.mp3",
**ytdl_args)
zw_end: typing.List[YtdlDiscord] = await asyncify(YtdlDiscord.create_from_url,
"https://scaleway.steffo.eu/jojo/zawarudo_outro.mp3",
**ytdl_args)
old_playlist = bot.music_data[guild]
bot.music_data[guild].playmode = Playlist()
# Get voice client
vc: discord.VoiceClient = bot.client.find_voice_client_by_guild(guild)
channel: discord.VoiceChannel = vc.channel
affected: typing.List[typing.Union[discord.User, discord.Member]] = channel.members
await bot.add_to_music_data(zw_start, guild)
for member in affected:
if member.bot:
continue
await member.edit(mute=True)
await asyncio.sleep(time)
await bot.add_to_music_data(zw_end, guild)
for member in affected:
member: typing.Union[discord.User, discord.Member]
if member.bot:
continue
await member.edit(mute=False)
bot.music_data[guild] = old_playlist
await bot.advance_music_data(guild)
return {}
_event_name = "_legacy_zawarudo"
def __init__(self, interface: CommandInterface):
super().__init__(interface)
if interface.name == "discord":
interface.register_herald_action(self._event_name, self._legacy_zawarudo_handler)
async def run(self, args: CommandArgs, data: CommandData) -> None:
guild_name, time = args.match(r"(?:\[(.+)])?\s*(.+)?")
if time is None:
time = 5
else:
time = int(time)
if time < 1:
raise InvalidInputError("The World can't stop time for less than a second.")
if time > 10:
raise InvalidInputError("The World can stop time only for 10 seconds.")
await data.reply(f"🕒 ZA WARUDO! TOKI WO TOMARE!")
await self.interface.call_herald_action("discord", self._event_name, {
"guild_name": guild_name,
"time": time
})