1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

Start porting to 5.11 (sigh)

This commit is contained in:
Steffo 2020-08-20 03:20:53 +02:00
parent c1145550dd
commit 3f1c8a57d3
30 changed files with 746 additions and 1045 deletions

779
poetry.lock generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
[tool.poetry] [tool.poetry]
name = "royalpack" name = "royalpack"
version = "5.13.9" version = "5.14.0"
description = "A Royalnet command pack for the Royal Games community" description = "A Royalnet command pack for the Royal Games community"
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"] authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
license = "AGPL-3.0+" license = "AGPL-3.0+"
@ -28,13 +28,12 @@
itsdangerous = "^1.1.0" itsdangerous = "^1.1.0"
[tool.poetry.dependencies.royalnet] [tool.poetry.dependencies.royalnet]
version = "~5.10.4" version = "~5.11.0"
# Maybe... there is a way to make these selectable? # Maybe... there is a way to make these selectable?
extras = [ extras = [
"telegram", "telegram",
"discord", "discord",
"alchemy_easy", "alchemy_easy",
"bard",
"constellation", "constellation",
"sentry", "sentry",
"herald", "herald",

View file

@ -23,7 +23,6 @@ from .leagueoflegends import LeagueoflegendsCommand
from .magickfiorygi import MagickfiorygiCommand from .magickfiorygi import MagickfiorygiCommand
from .magicktreasure import MagicktreasureCommand from .magicktreasure import MagicktreasureCommand
from .matchmaking import MatchmakingCommand from .matchmaking import MatchmakingCommand
from .peertubeupdates import PeertubeUpdatesCommand
from .ping import PingCommand from .ping import PingCommand
from .pmots import PmotsCommand from .pmots import PmotsCommand
from .dog import DogCommand from .dog import DogCommand
@ -37,7 +36,6 @@ from .steammatch import SteammatchCommand
from .steampowered import SteampoweredCommand from .steampowered import SteampoweredCommand
from .treasure import TreasureCommand from .treasure import TreasureCommand
from .trivia import TriviaCommand from .trivia import TriviaCommand
from .userinfo import UserinfoCommand
from .osu import OsuCommand from .osu import OsuCommand
# Enter the commands of your Pack here! # Enter the commands of your Pack here!
@ -66,7 +64,6 @@ available_commands = [
MagickfiorygiCommand, MagickfiorygiCommand,
MagicktreasureCommand, MagicktreasureCommand,
MatchmakingCommand, MatchmakingCommand,
PeertubeUpdatesCommand,
PingCommand, PingCommand,
PmotsCommand, PmotsCommand,
DogCommand, DogCommand,
@ -80,7 +77,6 @@ available_commands = [
SteampoweredCommand, SteampoweredCommand,
TreasureCommand, TreasureCommand,
TriviaCommand, TriviaCommand,
UserinfoCommand,
OsuCommand, OsuCommand,
] ]

View file

@ -14,34 +14,34 @@ log = logging.getLogger(__name__)
class LinkerCommand(rc.Command, metaclass=abc.ABCMeta): class LinkerCommand(rc.Command, metaclass=abc.ABCMeta):
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
self.updater_task = None self.updater_task = None
if self.enabled(): if self.enabled():
self.updater_task = self.loop.create_task(self.run_updater()) self.updater_task = self.loop.create_task(self.run_updater())
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
author = await data.get_author(error_if_none=True) author = await data.get_author(error_if_none=True)
async with data.session_acm() as session:
if len(args) == 0: if len(args) == 0:
message = [] message = []
for obj in await self.get_updatables_of_user(session=data.session, user=author): for obj in await self.get_updatables_of_user(session=session, user=author):
async def change(attribute: str, value: Any): async def change(attribute: str, value: Any):
"""A shortcut for self.__change.""" """A shortcut for self.__change."""
await self._change(session=data.session, await self._change(session=session,
obj=obj, obj=obj,
attribute=attribute, attribute=attribute,
new=value) new=value)
await self.update(session=data.session, obj=obj, change=change) await self.update(session=session, obj=obj, change=change)
message.append(self.describe(obj)) message.append(self.describe(obj))
if len(message) == 0: if len(message) == 0:
raise rc.UserError("Nessun account connesso.") raise rc.UserError("Nessun account connesso.")
await data.session_commit() await ru.asyncify(session.commit)
await data.reply("\n".join(message)) await data.reply("\n".join(message))
else: else:
created = await self.create(session=data.session, user=author, args=args, data=data) created = await self.create(session=session, user=author, args=args, data=data)
await data.session_commit() await ru.asyncify(session.commit)
if created is not None: if created is not None:
message = ["🔗 Account collegato!", "", self.describe(created)] message = ["🔗 Account collegato!", "", self.describe(created)]
await data.reply("\n".join(message)) await data.reply("\n".join(message))
@ -143,7 +143,7 @@ class LinkerCommand(rc.Command, metaclass=abc.ABCMeta):
def enabled(self) -> bool: def enabled(self) -> bool:
"""Whether the updater is enabled or not.""" """Whether the updater is enabled or not."""
return self.config[self.name]["updater"]["enabled"] and self.interface.name == "telegram" return self.config[self.name]["updater"]["enabled"] and isinstance(self.serf, rst.TelegramSerf)
def period(self) -> int: def period(self) -> int:
"""The time between two updater cycles.""" """The time between two updater cycles."""

View file

@ -1,15 +1,16 @@
from typing import * from typing import *
import telegram import telegram
from royalnet.commands import * import royalnet.commands as rc
import royalnet.serf.telegram as rst
class CiaoruoziCommand(Command): class CiaoruoziCommand(rc.Command):
name: str = "ciaoruozi" name: str = "ciaoruozi"
description: str = "Saluta Ruozi, un leggendario essere che è tornato in Royal Games." description: str = "Saluta Ruozi, un leggendario essere che è tornato in Royal Games."
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
if self.interface.name == "telegram": if isinstance(self.serf, rst.TelegramSerf):
user: telegram.User = data.message.from_user user: telegram.User = data.message.from_user
# Se sei Ruozi, salutati da solo! # Se sei Ruozi, salutati da solo!
if user.id == 112437036: if user.id == 112437036:

View file

@ -9,9 +9,6 @@ class CvCommand(Command):
syntax: str = "[a][o][n][d][h]" syntax: str = "[a][o][n][d][h]"
def __init__(self, interface: CommandInterface):
super().__init__(interface)
def _render_member(self, def _render_member(self,
member, member,
display_nick: bool, display_nick: bool,
@ -92,7 +89,7 @@ class CvCommand(Command):
return f"{status}{voice} {name}{activity}\n" return f"{status}{voice} {name}{activity}\n"
async def run(self, args: CommandArgs, data: CommandData) -> None: async def run(self, args: CommandArgs, data: CommandData) -> None:
response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") response: Dict[str, Any] = await self.serf.call_herald_event("discord", "discord_cv")
flags = args.optional(0, default="") flags = args.optional(0, default="")
display_nicks = "n" in flags display_nicks = "n" in flags

View file

@ -4,6 +4,7 @@ import asyncio
import datetime import datetime
import royalnet.commands as rc import royalnet.commands as rc
import royalnet.utils as ru import royalnet.utils as ru
import royalnet.serf.discord as rsd
from ..tables import Cvstats from ..tables import Cvstats
@ -18,14 +19,14 @@ class CvstatsCommand(rc.Command):
syntax: str = "" syntax: str = ""
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf=serf, config=config)
if self.interface.name == "discord": if isinstance(self.serf, rsd.DiscordSerf):
self.loop.create_task(self._updater(1800)) self.loop.create_task(self._updater(1800))
def _is_ryg_member(self, member: dict): def _is_ryg_member(self, member: dict):
for role in member["roles"]: for role in member["roles"]:
if role["id"] == self.interface.config["Cv"]["displayed_role_id"]: if role["id"] == self.config["Cv"]["displayed_role_id"]:
return True return True
return False return False
@ -33,7 +34,7 @@ class CvstatsCommand(rc.Command):
log.info(f"Gathering Cvstats...") log.info(f"Gathering Cvstats...")
while True: while True:
try: try:
response: Dict[str, Any] = await self.interface.call_herald_event("discord", "discord_cv") response: Dict[str, Any] = await self.serf.call_herald_event("discord", "discord_cv")
except rc.ConfigurationError: except rc.ConfigurationError:
await asyncio.sleep(10) await asyncio.sleep(10)
continue continue
@ -118,7 +119,8 @@ class CvstatsCommand(rc.Command):
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
CvstatsT = self.alchemy.get(Cvstats) CvstatsT = self.alchemy.get(Cvstats)
cvstats = data.session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).first() async with data.session_acm() as session:
cvstats = session.query(CvstatsT).order_by(CvstatsT.timestamp.desc()).first()
message = [ message = [
f" [b]Statistiche[/b]", f" [b]Statistiche[/b]",

View file

@ -6,6 +6,7 @@ import aiohttp
import royalnet.commands as rc import royalnet.commands as rc
import royalnet.utils as ru import royalnet.utils as ru
import royalnet.backpack.tables as rbt import royalnet.backpack.tables as rbt
import royalnet.serf.telegram as rst
from ..tables import * from ..tables import *
@ -38,7 +39,8 @@ class DiarioCommand(rc.Command):
syntax = "[!] \"{testo}\" --[autore], [contesto]" syntax = "[!] \"{testo}\" --[autore], [contesto]"
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
if self.interface.name == "telegram": async with data.session_acm() as session:
if isinstance(self.serf, rst.TelegramSerf):
message: telegram.Message = data.message message: telegram.Message = data.message
reply: telegram.Message = message.reply_to_message reply: telegram.Message = message.reply_to_message
creator = await data.get_author() creator = await data.get_author()
@ -65,7 +67,7 @@ class DiarioCommand(rc.Command):
if photosizes: if photosizes:
# Text is a caption # Text is a caption
text = reply.caption text = reply.caption
media_url = await to_imgur(self.interface.config["Imgur"]["token"], media_url = await to_imgur(self.config["Imgur"]["token"],
photosizes, text if text is not None else "") photosizes, text if text is not None else "")
else: else:
media_url = None media_url = None
@ -73,7 +75,7 @@ class DiarioCommand(rc.Command):
if not (text or media_url): if not (text or media_url):
raise rc.InvalidInputError("Il messaggio a cui hai risposto non contiene testo o immagini.") raise rc.InvalidInputError("Il messaggio a cui hai risposto non contiene testo o immagini.")
# Find the Royalnet account associated with the sender # Find the Royalnet account associated with the sender
quoted_tg = await ru.asyncify(data.session.query(self.alchemy.get(rbt.Telegram)) quoted_tg = await ru.asyncify(session.query(self.alchemy.get(rbt.Telegram))
.filter_by(tg_id=reply.from_user.id) .filter_by(tg_id=reply.from_user.id)
.one_or_none) .one_or_none)
quoted_account = quoted_tg.user if quoted_tg is not None else None quoted_account = quoted_tg.user if quoted_tg is not None else None
@ -93,7 +95,7 @@ class DiarioCommand(rc.Command):
# Check if there's an image associated with the reply # Check if there's an image associated with the reply
photosizes: Optional[List[telegram.PhotoSize]] = message.photo photosizes: Optional[List[telegram.PhotoSize]] = message.photo
if photosizes: if photosizes:
media_url = await to_imgur(self.interface.config["Imgur"]["token"], media_url = await to_imgur(self.config["Imgur"]["token"],
photosizes, raw_text if raw_text is not None else "") photosizes, raw_text if raw_text is not None else "")
else: else:
media_url = None media_url = None
@ -123,7 +125,7 @@ class DiarioCommand(rc.Command):
# Find if there's a Royalnet account associated with the quoted name # Find if there's a Royalnet account associated with the quoted name
if quoted is not None: if quoted is not None:
quoted_alias = await ru.asyncify( quoted_alias = await ru.asyncify(
data.session.query(self.alchemy.get(rbt.Alias)) session.query(self.alchemy.get(rbt.Alias))
.filter_by(alias=quoted.lower()).one_or_none .filter_by(alias=quoted.lower()).one_or_none
) )
else: else:
@ -147,8 +149,8 @@ class DiarioCommand(rc.Command):
timestamp=timestamp, timestamp=timestamp,
media_url=media_url, media_url=media_url,
spoiler=spoiler) spoiler=spoiler)
data.session.add(diario) session.add(diario)
await ru.asyncify(data.session.commit) await ru.asyncify(session.commit)
await data.reply(f"{str(diario)}") await data.reply(f"{str(diario)}")
else: else:
# Find the creator of the quotes # Find the creator of the quotes
@ -181,19 +183,15 @@ class DiarioCommand(rc.Command):
context = None context = None
# Find if there's a Royalnet account associated with the quoted name # Find if there's a Royalnet account associated with the quoted name
if quoted is not None: if quoted is not None:
quoted_alias = await ru.asyncify( quoted_account = await rbt.User.find(self.alchemy, session, quoted)
data.session.query(self.alchemy.get(rbt.Alias))
.filter_by(alias=quoted.lower())
.one_or_none
)
else: else:
quoted_alias = None quoted_account = None
quoted_account = quoted_alias.user if quoted_alias is not None else None if quoted_account is None:
if quoted_alias is not None and quoted_account is None:
raise rc.UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n" raise rc.UserError("Il nome dell'autore è ambiguo, quindi la riga non è stata aggiunta.\n"
"Per piacere, ripeti il comando con un nome più specifico!") "Per piacere, ripeti il comando con un nome più specifico!")
# Create the diario quote # Create the diario quote
diario = self.alchemy.Diario(creator=creator, DiarioT = self.alchemy.get(Diario)
diario = DiarioT(creator=creator,
quoted_account=quoted_account, quoted_account=quoted_account,
quoted=quoted, quoted=quoted,
text=text, text=text,
@ -201,6 +199,6 @@ class DiarioCommand(rc.Command):
timestamp=timestamp, timestamp=timestamp,
media_url=None, media_url=None,
spoiler=spoiler) spoiler=spoiler)
data.session.add(diario) session.add(diario)
await ru.asyncify(data.session.commit) await ru.asyncify(session.commit)
await data.reply(f"{str(diario)}") await data.reply(f"{str(diario)}")

View file

@ -19,7 +19,8 @@ class DiarioquoteCommand(rc.Command):
entry_id = int(args[0].lstrip("#")) entry_id = int(args[0].lstrip("#"))
except ValueError: except ValueError:
raise rc.CommandError("L'id che hai specificato non è valido.") raise rc.CommandError("L'id che hai specificato non è valido.")
entry: Diario = await ru.asyncify(data.session.query(self.alchemy.get(Diario)).get, entry_id) async with data.session_acm() as session:
entry: Diario = await ru.asyncify(session.query(self.alchemy.get(Diario)).get, entry_id)
if entry is None: if entry is None:
raise rc.CommandError("Nessuna riga con quell'id trovata.") raise rc.CommandError("Nessuna riga con quell'id trovata.")
await data.reply(f" {entry}") await data.reply(f" {entry}")

View file

@ -16,13 +16,10 @@ class DiarioshuffleCommand(rc.Command):
syntax = "" syntax = ""
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
async with data.session_acm() as session:
DiarioT = self.alchemy.get(Diario) DiarioT = self.alchemy.get(Diario)
entry: List[Diario] = await ru.asyncify( entry: List[Diario] = await ru.asyncify(
data.session session.query(DiarioT).order_by(func.random()).limit(1).one_or_none
.query(DiarioT)
.order_by(func.random())
.limit(1)
.one_or_none
) )
if entry is None: if entry is None:
raise rc.CommandError("Nessuna riga del diario trovata.") raise rc.CommandError("Nessuna riga del diario trovata.")

View file

@ -20,7 +20,8 @@ class GivefiorygiCommand(rc.Command):
if user_arg is None: if user_arg is None:
raise rc.InvalidInputError("Non hai specificato un destinatario!") raise rc.InvalidInputError("Non hai specificato un destinatario!")
user = await rbt.User.find(self.alchemy, data.session, user_arg) async with data.session_acm() as session:
user = await rbt.User.find(self.alchemy, session, user_arg)
if user is None: if user is None:
raise rc.InvalidInputError("L'utente specificato non esiste!") raise rc.InvalidInputError("L'utente specificato non esiste!")
if user.uid == author.uid: if user.uid == author.uid:

View file

@ -13,14 +13,14 @@ class GivetreasureCommand(MagicktreasureCommand):
syntax: str = "{codice} {valore}" syntax: str = "{codice} {valore}"
async def _permission_check(self, author, code, value, data): async def _permission_check(self, author, code, value, data, session):
if author.fiorygi.fiorygi < value: if author.fiorygi.fiorygi < value:
raise rc.UserError("Non hai abbastanza fiorygi per creare questo Treasure.") raise rc.UserError("Non hai abbastanza fiorygi per creare questo Treasure.")
async def _create_treasure(self, author, code, value, data): async def _create_treasure(self, author, code, value, data, session):
TreasureT = self.alchemy.get(Treasure) TreasureT = self.alchemy.get(Treasure)
treasure = await ru.asyncify(data.session.query(TreasureT).get, code) treasure = await ru.asyncify(session.query(TreasureT).get, code)
if treasure is not None: if treasure is not None:
raise rc.UserError("Esiste già un Treasure con quel codice.") raise rc.UserError("Esiste già un Treasure con quel codice.")

View file

@ -17,19 +17,19 @@ class HelpCommand(rc.Command):
] ]
for command in sorted(list(set(self.serf.commands.values())), key=lambda c: c.name): for command in sorted(list(set(self.serf.commands.values())), key=lambda c: c.name):
message.append(f"- [c]{self.interface.prefix}{command.name}[/c]") message.append(f"- [c]{self.serf.prefix}{command.name}[/c]")
await data.reply("\n".join(message)) await data.reply("\n".join(message))
else: else:
name: str = args[0].lstrip(self.interface.prefix) name: str = args[0].lstrip(self.serf.prefix)
try: try:
command: rc.Command = self.serf.commands[f"{self.interface.prefix}{name}"] command: rc.Command = self.serf.commands[f"{self.serf.prefix}{name}"]
except KeyError: except KeyError:
raise rc.InvalidInputError("Il comando richiesto non esiste.") raise rc.InvalidInputError("Il comando richiesto non esiste.")
message = [ message = [
f" [c]{self.interface.prefix}{command.name} {command.syntax}[/c]", f" [c]{self.serf.prefix}{command.name} {command.syntax}[/c]",
"", "",
f"{command.description}" f"{command.description}"
] ]

View file

@ -29,8 +29,8 @@ class LeagueoflegendsCommand(LinkerCommand):
"rank_flexq": "Flex", "rank_flexq": "Flex",
} }
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
self._lolwatcher: Optional[riotwatcher.RiotWatcher] = None self._lolwatcher: Optional[riotwatcher.RiotWatcher] = None
self._tftwatcher: Optional[riotwatcher.RiotWatcher] = None self._tftwatcher: Optional[riotwatcher.RiotWatcher] = None
if self.enabled(): if self.enabled():

View file

@ -23,7 +23,8 @@ class MagickfiorygiCommand(rc.Command):
if user_arg is None: if user_arg is None:
raise rc.InvalidInputError("Non hai specificato un destinatario!") raise rc.InvalidInputError("Non hai specificato un destinatario!")
user = await rbt.User.find(self.alchemy, data.session, user_arg) async with data.session_acm() as session:
user = await rbt.User.find(self.alchemy, session, user_arg)
if user is None: if user is None:
raise rc.InvalidInputError("L'utente specificato non esiste!") raise rc.InvalidInputError("L'utente specificato non esiste!")

View file

@ -12,15 +12,15 @@ class MagicktreasureCommand(rc.Command):
syntax: str = "{codice} {valore}" syntax: str = "{codice} {valore}"
async def _permission_check(self, author, code, value, data): async def _permission_check(self, author, code, value, data, session):
if "banker" not in author.roles: if "banker" not in author.roles:
raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.") raise rc.UserError("Non hai permessi sufficienti per eseguire questo comando.")
return author return author
async def _create_treasure(self, author, code, value, data): async def _create_treasure(self, author, code, value, data, session):
TreasureT = self.alchemy.get(Treasure) TreasureT = self.alchemy.get(Treasure)
treasure = await ru.asyncify(data.session.query(TreasureT).get, code) treasure = await ru.asyncify(session.query(TreasureT).get, code)
if treasure is not None: if treasure is not None:
raise rc.UserError("Esiste già un Treasure con quel codice.") raise rc.UserError("Esiste già un Treasure con quel codice.")
@ -44,10 +44,10 @@ class MagicktreasureCommand(rc.Command):
if value < 0: if value < 0:
raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.") raise rc.InvalidInputError("Il valore deve essere maggiore o uguale a 0.")
await self._permission_check(author, code, value, data) async with data.session_acm() as session:
treasure = await self._create_treasure(author, code, value, data) await self._permission_check(author, code, value, data, session)
treasure = await self._create_treasure(author, code, value, data, session)
data.session.add(treasure) session.add(treasure)
await data.session_commit() await ru.asyncify(session.commit)
await data.reply("✅ Treasure creato!") await data.reply("✅ Treasure creato!")

View file

@ -3,7 +3,9 @@ import datetime
import re import re
import dateparser import dateparser
import typing import typing
import royalnet.utils as ru
import royalnet.commands as rc import royalnet.commands as rc
import royalnet.serf.telegram as rst
from ..tables import MMEvent from ..tables import MMEvent
from ..utils import MMTask from ..utils import MMTask
@ -18,20 +20,20 @@ class MatchmakingCommand(rc.Command):
aliases = ["mm", "lfg"] aliases = ["mm", "lfg"]
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
# Find all active MMEvents and run the tasks for them # Find all active MMEvents and run the tasks for them
session = self.alchemy.Session() session = self.alchemy.Session()
# Create a new MMEvent and run it # Create a new MMEvent and run it
if self.interface.name == "telegram": if isinstance(self.serf, rst.TelegramSerf):
MMEventT = self.alchemy.get(MMEvent) MMEventT = self.alchemy.get(MMEvent)
active_mmevents = ( active_mmevents = (
session session
.query(MMEventT) .query(MMEventT)
.filter( .filter(
MMEventT.interface == self.interface.name, MMEventT.interface == self.serf.interface_name,
MMEventT.interrupted == False MMEventT.interrupted == False
) )
.all() .all()
@ -74,13 +76,14 @@ class MatchmakingCommand(rc.Command):
dt, title, description = self._parse_args(args) dt, title, description = self._parse_args(args)
# Add the MMEvent to the database # Add the MMEvent to the database
async with data.session_acm() as session:
mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author, mmevent: MMEvent = self.alchemy.get(MMEvent)(creator=author,
datetime=dt, datetime=dt,
title=title, title=title,
description=description, description=description,
interface=self.interface.name) interface=self.serf.interface_name)
data.session.add(mmevent) session.add(mmevent)
await data.session_commit() await ru.asyncify(session.commit)
# Create and run a task for the newly created MMEvent # Create and run a task for the newly created MMEvent
task = MMTask(mmevent.mmid, command=self) task = MMTask(mmevent.mmid, command=self)

View file

@ -7,7 +7,6 @@ import royalnet.commands as rc
import royalnet.utils as ru import royalnet.utils as ru
from .abstract.linker import LinkerCommand from .abstract.linker import LinkerCommand
from ..types import Updatable
from ..tables import Osu from ..tables import Osu
from ..stars.api_auth_login_osu import ApiAuthLoginOsuStar from ..stars.api_auth_login_osu import ApiAuthLoginOsuStar

View file

@ -1,81 +0,0 @@
from typing import *
import aiohttp
import asyncio
import datetime
import logging
import dateparser
import royalnet.commands as rc
import royalnet.serf.telegram as rst
log = logging.getLogger(__name__)
class PeertubeUpdatesCommand(rc.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: rc.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")
if response.status != 200:
raise rc.ExternalError("Peertube is unavailable")
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=rst.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 rc.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: rc.CommandArgs, data: rc.CommandData) -> None:
if self.interface.name != "telegram":
raise rc.UnsupportedError()
await data.reply(f" Ultimo video caricato il: [b]{self._latest_date.isoformat()}[/b]")

View file

@ -12,7 +12,7 @@ class PingCommand(rc.Command):
syntax: str = "" syntax: str = ""
_targets = ["telegram", "discord", "matrix", "constellation"] _targets = ["telegram", "discord", "constellation"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
await data.reply("📶 Ping...") await data.reply("📶 Ping...")
@ -21,7 +21,7 @@ class PingCommand(rc.Command):
start = datetime.datetime.now() start = datetime.datetime.now()
for target in self._targets: for target in self._targets:
tasks[target] = self.loop.create_task(self.interface.call_herald_event(target, "pong")) tasks[target] = self.loop.create_task(self.serf.call_herald_event(target, "pong"))
await asyncio.sleep(10) await asyncio.sleep(10)

View file

@ -7,8 +7,8 @@ import discord
from sqlalchemy import and_ from sqlalchemy import and_
import royalnet.commands as rc import royalnet.commands as rc
import royalnet.utils as ru import royalnet.utils as ru
from royalnet.serf.telegram import escape as telegram_escape import royalnet.serf.telegram as rst
from royalnet.serf.discord import escape as discord_escape import royalnet.serf.discord as rsd
from ..tables import Reminder from ..tables import Reminder
@ -22,34 +22,35 @@ class ReminderCommand(rc.Command):
syntax: str = "[ {data} ] {messaggio}" syntax: str = "[ {data} ] {messaggio}"
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
session = interface.alchemy.Session()
session = self.alchemy.Session()
reminders = ( reminders = (
session.query(interface.alchemy.get(Reminder)) session.query(self.alchemy.get(Reminder))
.filter(and_( .filter(and_(
interface.alchemy.get(Reminder).datetime >= datetime.datetime.now(), self.alchemy.get(Reminder).datetime >= datetime.datetime.now(),
interface.alchemy.get(Reminder).interface_name == interface.name)) self.alchemy.get(Reminder).interface_name == self.serf.interface_name))
.all() .all()
) )
for reminder in reminders: for reminder in reminders:
interface.loop.create_task(self._remind(reminder)) self.loop.create_task(self._remind(reminder))
async def _remind(self, reminder): async def _remind(self, reminder):
await ru.sleep_until(reminder.datetime) await ru.sleep_until(reminder.datetime)
if self.interface.name == "telegram": if isinstance(self.serf, rst.TelegramSerf):
chat_id: int = pickle.loads(reminder.interface_data) chat_id: int = pickle.loads(reminder.interface_data)
client: telegram.Bot = self.serf.client client: telegram.Bot = self.serf.client
await self.serf.api_call(client.send_message, await self.serf.api_call(client.send_message,
chat_id=chat_id, chat_id=chat_id,
text=telegram_escape(f"❗️ {reminder.message}"), text=rst.escape(f"❗️ {reminder.message}"),
parse_mode="HTML", parse_mode="HTML",
disable_web_page_preview=True) disable_web_page_preview=True)
elif self.interface.name == "discord": elif isinstance(self.serf, rsd.DiscordSerf):
channel_id: int = pickle.loads(reminder.interface_data) channel_id: int = pickle.loads(reminder.interface_data)
client: discord.Client = self.serf.client client: discord.Client = self.serf.client
channel = client.get_channel(channel_id) channel = client.get_channel(channel_id)
await channel.send(discord_escape(f"❗️ {reminder.message}")) await channel.send(rsd.escape(f"❗️ {reminder.message}"))
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
try: try:
@ -70,18 +71,19 @@ class ReminderCommand(rc.Command):
await data.reply("⚠️ La data che hai specificato è nel passato.") await data.reply("⚠️ La data che hai specificato è nel passato.")
return return
await data.reply(f"✅ Promemoria impostato per [b]{date.strftime('%Y-%m-%d %H:%M:%S')}[/b]") await data.reply(f"✅ Promemoria impostato per [b]{date.strftime('%Y-%m-%d %H:%M:%S')}[/b]")
if self.interface.name == "telegram": if isinstance(self.serf, rst.TelegramSerf):
interface_data = pickle.dumps(data.message.chat.id) interface_data = pickle.dumps(data.message.chat.id)
elif self.interface.name == "discord": elif isinstance(self.serf, rsd.DiscordSerf):
interface_data = pickle.dumps(data.message.channel.id) interface_data = pickle.dumps(data.message.channel.id)
else: else:
raise rc.UnsupportedError("This command does not support the current interface.") raise rc.UnsupportedError("This command does not support the current interface.")
creator = await data.get_author() creator = await data.get_author()
reminder = self.interface.alchemy.get(Reminder)(creator=creator, async with data.session_acm() as session:
interface_name=self.interface.name, reminder = self.alchemy.get(Reminder)(creator=creator,
interface_name=self.serf.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.loop.create_task(self._remind(reminder))
data.session.add(reminder) session.add(reminder)
await ru.asyncify(data.session.commit) await ru.asyncify(session.commit)

View file

@ -16,9 +16,6 @@ class RoyalpackCommand(rc.Command):
return pkg_resources.get_distribution("royalpack").version return pkg_resources.get_distribution("royalpack").version
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
if __debug__:
message = f" Royalpack [url=https://github.com/Steffo99/royalpack/]Unreleased[/url]\n"
else:
message = f" Royalpack [url=https://github.com/Steffo99/royalpack/releases/tag/{self.royalpack_version}]{self.royalpack_version}[/url]\n" message = f" Royalpack [url=https://github.com/Steffo99/royalpack/releases/tag/{self.royalpack_version}]{self.royalpack_version}[/url]\n"
if "69" in self.royalpack_version: if "69" in self.royalpack_version:
message += "(Nice.)" message += "(Nice.)"

View file

@ -53,8 +53,8 @@ class SteammatchCommand(rc.Command):
syntax: str = "{royalnet_username}+" syntax: str = "{royalnet_username}+"
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
self._api = steam.webapi.WebAPI(self.config["steampowered"]["token"]) self._api = steam.webapi.WebAPI(self.config["steampowered"]["token"])
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
@ -64,7 +64,8 @@ class SteammatchCommand(rc.Command):
users.append(author) users.append(author)
for arg in args: for arg in args:
user = await rbt.User.find(self.alchemy, data.session, arg) async with data.session_acm() as session:
user = await rbt.User.find(self.alchemy, session, arg)
users.append(user) users.append(user)
if len(users) < 2: if len(users) < 2:

View file

@ -22,8 +22,8 @@ class SteampoweredCommand(LinkerCommand):
syntax: str = "{url_profilo}" syntax: str = "{url_profilo}"
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
self._api = steam.webapi.WebAPI(self.token()) self._api = steam.webapi.WebAPI(self.token())
def token(self): def token(self):

View file

@ -16,16 +16,17 @@ class TreasureCommand(rc.Command):
author = await data.get_author(error_if_none=True) author = await data.get_author(error_if_none=True)
code = args[0].lower() code = args[0].lower()
async with data.session_acm() as session:
TreasureT = self.alchemy.get(Treasure) TreasureT = self.alchemy.get(Treasure)
treasure = await ru.asyncify(data.session.query(TreasureT).get, code) treasure = await ru.asyncify(session.query(TreasureT).get, code)
if treasure is None: if treasure is None:
raise rc.UserError("Non esiste nessun Treasure con quel codice.") raise rc.UserError("Non esiste nessun Treasure con quel codice.")
if treasure.redeemed_by is not None: if treasure.redeemed_by is not None:
raise rc.UserError(f"Quel tesoro è già stato riscattato da {treasure.redeemed_by}.") raise rc.UserError(f"Quel tesoro è già stato riscattato da {treasure.redeemed_by}.")
treasure.redeemed_by = author treasure.redeemed_by = author
await data.session_commit() await ru.asyncify(session.commit)
await FiorygiTransaction.spawn_fiorygi(data, await FiorygiTransaction.spawn_fiorygi(data,
author, author,
treasure.value, treasure.value,

View file

@ -31,20 +31,21 @@ class TriviaCommand(rc.Command):
# _question_lock: bool = False # _question_lock: bool = False
def __init__(self, interface: rc.CommandInterface): def __init__(self, serf, config):
super().__init__(interface) super().__init__(serf, config)
self._answerers: Dict[uuid.UUID, Dict[str, bool]] = {} self._answerers: Dict[uuid.UUID, Dict[str, bool]] = {}
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
arg = args.optional(0) arg = args.optional(0)
async with data.session_acm() as session:
if arg == "credits": if arg == "credits":
await data.reply(f" [c]{self.interface.prefix}{self.name}[/c] di [i]Steffo[/i]\n" await data.reply(f" [c]{self.serf.prefix}{self.name}[/c] di [i]Steffo[/i]\n"
f"\n" f"\n"
f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i]," f"Tutte le domande vengono dall'[b]Open Trivia Database[/b] di [i]Pixeltail Games[/i],"
f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].") f" creatori di Tower Unite, e sono rilasciate sotto la licenza [b]CC BY-SA 4.0[/b].")
return return
elif arg == "scores": elif arg == "scores":
trivia_scores = await ru.asyncify(data.session.query(self.alchemy.get(TriviaScore)).all) trivia_scores = await ru.asyncify(session.query(self.alchemy.get(TriviaScore)).all)
strings = ["🏆 [b]Trivia Leaderboards[/b]\n"] strings = ["🏆 [b]Trivia Leaderboards[/b]\n"]
for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)): for index, ts in enumerate(sorted(trivia_scores, key=lambda ts: -ts.score)):
if index > 3: if index > 3:
@ -57,8 +58,8 @@ class TriviaCommand(rc.Command):
# raise rc.CommandError("C'è già un'altra domanda attiva!") # raise rc.CommandError("C'è già un'altra domanda attiva!")
# self._question_lock = True # self._question_lock = True
# Fetch the question # Fetch the question
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as ws:
async with session.get("https://opentdb.com/api.php?amount=1") as response: async with ws.get("https://opentdb.com/api.php?amount=1") as response:
j = await response.json() j = await response.json()
# Parse the question # Parse the question
if j["response_code"] != 0: if j["response_code"] != 0:
@ -112,13 +113,11 @@ class TriviaCommand(rc.Command):
keyboard: List[rc.KeyboardKey] = [] keyboard: List[rc.KeyboardKey] = []
for index, answer in enumerate(answers): for index, answer in enumerate(answers):
if index == correct_index: if index == correct_index:
keyboard.append(rc.KeyboardKey(interface=self.interface, keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
short=self._letter_emojis[index],
text=answers[index], text=answers[index],
callback=correct)) callback=correct))
else: else:
keyboard.append(rc.KeyboardKey(interface=self.interface, keyboard.append(rc.KeyboardKey(short=self._letter_emojis[index],
short=self._letter_emojis[index],
text=answers[index], text=answers[index],
callback=wrong)) callback=wrong))
async with data.keyboard(text=text, keys=keyboard): async with data.keyboard(text=text, keys=keyboard):
@ -126,11 +125,11 @@ class TriviaCommand(rc.Command):
results = f"❗️ Tempo scaduto!\n" \ results = f"❗️ Tempo scaduto!\n" \
f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n" f"La risposta corretta era [b]{answers[correct_index]}[/b]!\n\n"
for answerer_id in self._answerers[question_id]: for answerer_id in self._answerers[question_id]:
answerer = data.session.query(self.alchemy.get(rbt.users.User)).get(answerer_id) answerer = session.query(self.alchemy.get(rbt.users.User)).get(answerer_id)
if answerer.trivia_score is None: if answerer.trivia_score is None:
ts = self.interface.alchemy.get(TriviaScore)(user=answerer) ts = self.alchemy.get(TriviaScore)(user=answerer)
data.session.add(ts) session.add(ts)
await ru.asyncify(data.session.commit) await ru.asyncify(session.commit)
previous_score = answerer.trivia_score.score previous_score = answerer.trivia_score.score
if self._answerers[question_id][answerer_id]: if self._answerers[question_id][answerer_id]:
results += self._correct_emoji results += self._correct_emoji
@ -143,5 +142,5 @@ class TriviaCommand(rc.Command):
results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n" results += f" {answerer}: [b]{current_score:.0f}p[/b] ({score_difference:+.0f}p)\n"
await data.reply(results) await data.reply(results)
del self._answerers[question_id] del self._answerers[question_id]
await ru.asyncify(data.session.commit) await ru.asyncify(session.commit)
# self._question_lock = False # self._question_lock = False

View file

@ -1,74 +0,0 @@
from typing import *
import royalnet.commands as rc
import royalnet.backpack.tables as rbt
class UserinfoCommand(rc.Command):
name: str = "userinfo"
aliases = ["uinfo", "ui", "useri"]
description: str = "Visualizza informazioni su un utente."
syntax = "[username]"
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
username = args.optional(0)
if username is None:
user: rbt.User = await data.get_author(error_if_none=True)
else:
found: Optional[rbt.User] = await rbt.User.find(self.alchemy, data.session, username)
if not found:
raise rc.InvalidInputError("Utente non trovato.")
else:
user = found
r = [
f" [url=https://ryg.steffo.eu/#/user/{user.uid}]{user.username}[/url]",
f"{', '.join(user.roles)}",
]
if user.email:
r.append(f"{user.email}")
r.append("")
# Bios are a bit too long
# if user.bio:
# r.append(f"{user.bio}")
for account in user.telegram:
r.append(f"{account}")
for account in user.discord:
r.append(f"{account}")
for account in user.steam:
r.append(f"{account}")
if account.dota is not None:
r.append(f"{account.dota}")
if account.brawlhalla is not None:
r.append(f"{account.brawlhalla}")
for account in user.leagueoflegends:
r.append(f"{account}")
r.append("")
r.append(f"Ha creato [b]{len(user.diario_created)}[/b] righe di "
f"[url=https://ryg.steffo.eu/#/diario]Diario[/url], e vi compare in"
f" [b]{len(user.diario_quoted)}[/b] righe.")
r.append("")
if user.trivia_score:
r.append(f"Ha [b]{user.trivia_score.score:.0f}[/b] punti Trivia, avendo risposto correttamente a"
f" [b]{user.trivia_score.correct_answers}[/b] domande su"
f" [b]{user.trivia_score.total_answers}[/b].")
r.append("")
if user.fiorygi:
r.append(f"Ha [b]{user.fiorygi}[/b].")
r.append("")
await data.reply("\n".join(r))

View file

@ -4,6 +4,7 @@ import datetime
from sqlalchemy import * from sqlalchemy import *
from sqlalchemy.orm import * from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.ext.declarative import declared_attr
import royalnet.utils as ru
from .fiorygi import Fiorygi from .fiorygi import Fiorygi
@ -48,22 +49,24 @@ class FiorygiTransaction:
@classmethod @classmethod
async def spawn_fiorygi(cls, data: "CommandData", user, qty: int, reason: str): async def spawn_fiorygi(cls, data: "CommandData", user, qty: int, reason: str):
if user.fiorygi is None: if user.fiorygi is None:
data.session.add(data._interface.alchemy.get(Fiorygi)( async with data.session_acm() as session:
session.add(data.alchemy.get(Fiorygi)(
user_id=user.uid, user_id=user.uid,
fiorygi=0 fiorygi=0
)) ))
await data.session_commit() await ru.asyncify(session.commit)
transaction = data._interface.alchemy.get(FiorygiTransaction)( async with data.session_acm() as session:
transaction = data.alchemy.get(FiorygiTransaction)(
user_id=user.uid, user_id=user.uid,
change=qty, change=qty,
reason=reason, reason=reason,
timestamp=datetime.datetime.now() timestamp=datetime.datetime.now()
) )
data.session.add(transaction) session.add(transaction)
user.fiorygi.fiorygi += qty user.fiorygi.fiorygi += qty
await data.session_commit() await ru.asyncify(session.commit)
if len(user.telegram) > 0: if len(user.telegram) > 0:
user_str = user.telegram[0].mention() user_str = user.telegram[0].mention()
@ -77,6 +80,7 @@ class FiorygiTransaction:
else: else:
msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]." msg = f"💸 [b]{user_str}[/b] ha perso [b]{-qty}[/b] fioryg{'i' if qty != -1 else ''} per [i]{reason}[/i]."
await data._interface.call_herald_event("telegram", "telegram_message", await data.command.serf.call_herald_event(
chat_id=data._interface.config["Telegram"]["main_group_id"], "telegram", "telegram_message",
chat_id=data.command.config["Telegram"]["main_group_id"],
text=msg) text=msg)