diff --git a/royalgames.py b/royalgames.py index 14a079a7..862eb27c 100644 --- a/royalgames.py +++ b/royalgames.py @@ -10,7 +10,8 @@ from royalnet.database.tables import Royal, Telegram loop = asyncio.get_event_loop() commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand, DebugCreateCommand, SyncCommand, - AuthorCommand, DiarioCommand, RageCommand, DateparserCommand, ReminderCommand] + AuthorCommand, DiarioCommand, RageCommand, DateparserCommand, ReminderCommand, KvactiveCommand, KvCommand, + KvrollCommand] master = RoyalnetServer("localhost", 1234, "sas") tg_bot = TelegramBot(os.environ["TG_AK"], "localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Telegram, "tg_id", error_command=ErrorHandlerCommand) diff --git a/royalnet/commands/__init__.py b/royalnet/commands/__init__.py index d9670135..33fdb22a 100644 --- a/royalnet/commands/__init__.py +++ b/royalnet/commands/__init__.py @@ -10,7 +10,11 @@ from .rage import RageCommand from .dateparser import DateparserCommand from .author import AuthorCommand from .reminder import ReminderCommand +from .kvactive import KvactiveCommand +from .kv import KvCommand +from .kvroll import KvrollCommand __all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand", - "SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand"] + "SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand", + "KvactiveCommand", "KvCommand", "KvrollCommand"] diff --git a/royalnet/commands/kv.py b/royalnet/commands/kv.py new file mode 100644 index 00000000..e14d554a --- /dev/null +++ b/royalnet/commands/kv.py @@ -0,0 +1,36 @@ +from ..database.tables import ActiveKvGroup, Royal, Keyvalue, Keygroup +from ..utils import Command, Call, asyncify + + +class KvCommand(Command): + + command_name = "kv" + command_description = "Visualizza o modifica un valore kv." + command_syntax = "(chiave) [valore]" + + require_alchemy_tables = {ActiveKvGroup, Royal, Keyvalue, Keygroup} + + @classmethod + async def common(cls, call: Call): + key = call.args[0].lower() + value = call.args.optional(1) + author = await call.get_author(error_if_none=True) + active = await asyncify(call.session.query(call.alchemy.ActiveKvGroup).filter_by(royal=author).one_or_none) + if active is None: + await call.reply("⚠️ Devi prima attivare un gruppo con il comando [c]kvactive[/c]!") + keyvalue = await asyncify(call.session.query(call.alchemy.Keyvalue).filter_by(group=active.group, key=key).one_or_none) + if value is None: + # Get + if keyvalue is None: + await call.reply("⚠️ La chiave specificata non esiste.") + return + await call.reply(f"ℹ️ Valore della chiave:\n{keyvalue}") + else: + # Set/kv asdf 1000 + if keyvalue is None: + keyvalue = call.alchemy.Keyvalue(group=active.group, key=key, value=value) + call.session.add(keyvalue) + else: + keyvalue.value = value + await asyncify(call.session.commit) + await call.reply(f"✅ Chiave aggiornata:\n{keyvalue}") diff --git a/royalnet/commands/kvactive.py b/royalnet/commands/kvactive.py new file mode 100644 index 00000000..a9f7227b --- /dev/null +++ b/royalnet/commands/kvactive.py @@ -0,0 +1,32 @@ +from ..database.tables import ActiveKvGroup, Royal, Keygroup +from ..utils import Command, Call, asyncify + + +class KvactiveCommand(Command): + + command_name = "kvactive" + command_description = "Seleziona un gruppo di valori kv." + command_syntax = "(nomegruppo)" + + require_alchemy_tables = {ActiveKvGroup, Royal, Keygroup} + + @classmethod + async def common(cls, call: Call): + group_name = call.args[0].lower() + author = await call.get_author(error_if_none=True) + active = await asyncify(call.session.query(call.alchemy.ActiveKvGroup).filter_by(royal=author).one_or_none) + if active is None: + group = await asyncify(call.session.query(call.alchemy.Keygroup).filter_by(group_name=group_name).one_or_none) + if group is None: + group = call.alchemy.Keygroup(group_name=group_name) + call.session.add(group) + active = call.alchemy.ActiveKvGroup(royal=author, group=group) + call.session.add(active) + else: + group = await asyncify(call.session.query(call.alchemy.Keygroup).filter_by(group_name=group_name).one_or_none) + if group is None: + group = call.alchemy.Keygroup(group_name=group_name) + call.session.add(group) + active.group = group + await asyncify(call.session.commit) + await call.reply(f"✅ Hai attivato il gruppo [b]{group_name}[/b].") diff --git a/royalnet/commands/kvroll.py b/royalnet/commands/kvroll.py new file mode 100644 index 00000000..9b95a31b --- /dev/null +++ b/royalnet/commands/kvroll.py @@ -0,0 +1,39 @@ +import random +from ..database.tables import ActiveKvGroup, Royal, Keygroup, Keyvalue +from ..utils import Command, Call, asyncify, plusformat + + +class KvrollCommand(Command): + + command_name = "kvroll" + command_description = "Lancia 1d20, poi aggiungici il valore della kv selezionata." + command_syntax = "(chiave) [modifier]" + + require_alchemy_tables = {ActiveKvGroup, Royal, Keyvalue, Keygroup} + + @classmethod + async def common(cls, call: Call): + key = call.args[0].lower() + normal_mod_str = call.args.optional(1, 0) + try: + normal_modifier = int(normal_mod_str) + except ValueError: + await call.reply("⚠️ Il modificatore specificato non è un numero.") + return + author = await call.get_author(error_if_none=True) + active = await asyncify(call.session.query(call.alchemy.ActiveKvGroup).filter_by(royal=author).one_or_none) + if active is None: + await call.reply("⚠️ Devi prima attivare un gruppo con il comando [c]kvactive[/c]!") + return + keyvalue = await asyncify(call.session.query(call.alchemy.Keyvalue).filter_by(group=active.group, key=key).one_or_none) + if keyvalue is None: + await call.reply("⚠️ La chiave specificata non esiste.") + return + try: + kv_modifier = int(keyvalue.value) + except ValueError: + await call.reply("⚠️ Il valore della chiave specificata non è un numero.") + return + roll = random.randrange(1, 21) + result = roll + kv_modifier + normal_modifier + await call.reply(f"🎲 {roll}{plusformat(kv_modifier)}{plusformat(normal_modifier)} = [b]{result}[/b]") diff --git a/royalnet/database/tables/__init__.py b/royalnet/database/tables/__init__.py index dc48894b..0e5b8dd6 100644 --- a/royalnet/database/tables/__init__.py +++ b/royalnet/database/tables/__init__.py @@ -2,5 +2,8 @@ from .royals import Royal from .telegram import Telegram from .diario import Diario from .aliases import Alias +from .activekvgroup import ActiveKvGroup +from .keyvalue import Keyvalue +from .keygroup import Keygroup -__all__ = ["Royal", "Telegram", "Diario", "Alias"] +__all__ = ["Royal", "Telegram", "Diario", "Alias", "ActiveKvGroup", "Keyvalue", "Keygroup"] diff --git a/royalnet/database/tables/activekvgroup.py b/royalnet/database/tables/activekvgroup.py new file mode 100644 index 00000000..1974c247 --- /dev/null +++ b/royalnet/database/tables/activekvgroup.py @@ -0,0 +1,18 @@ +from sqlalchemy import Column, \ + String, \ + Integer, \ + ForeignKey +from sqlalchemy.orm import relationship + + +class ActiveKvGroup: + __tablename__ = "activekvgroups" + + royal_id = Column(Integer, ForeignKey("royals.uid"), primary_key=True) + group_name = Column(String, ForeignKey("keygroups.group_name"), nullable=False) + + royal = relationship("Royal", backref="active_kv_group") + group = relationship("Keygroup", backref="users_with_this_active") + + def __repr__(self): + return f"" diff --git a/royalnet/database/tables/keygroup.py b/royalnet/database/tables/keygroup.py new file mode 100644 index 00000000..ed5557ce --- /dev/null +++ b/royalnet/database/tables/keygroup.py @@ -0,0 +1,12 @@ +from sqlalchemy import Column, \ + String, \ + ForeignKey + + +class Keygroup: + __tablename__ = "keygroups" + + group_name = Column(String, ForeignKey("keygroups.group_name"), primary_key=True) + + def __repr__(self): + return f"" diff --git a/royalnet/database/tables/keyvalue.py b/royalnet/database/tables/keyvalue.py new file mode 100644 index 00000000..d09e63c8 --- /dev/null +++ b/royalnet/database/tables/keyvalue.py @@ -0,0 +1,21 @@ +from sqlalchemy import Column, \ + String, \ + ForeignKey +from sqlalchemy.orm import relationship +from .keygroup import Keygroup + + +class Keyvalue: + __tablename__ = "keyvalues" + + group_name = Column(String, ForeignKey("keygroups.group_name"), primary_key=True) + key = Column(String, primary_key=True) + value = Column(String, nullable=False) + + group = relationship("Keygroup") + + def __repr__(self): + return f"" + + def __str__(self): + return f"{self.key}: [b]{self.value}[/b]" diff --git a/royalnet/utils/__init__.py b/royalnet/utils/__init__.py index 7060c955..65c2718c 100644 --- a/royalnet/utils/__init__.py +++ b/royalnet/utils/__init__.py @@ -4,6 +4,7 @@ from .command import Command, CommandArgs, InvalidInputError, UnsupportedError, from .safeformat import safeformat from .classdictjanitor import cdj from .sleepuntil import sleep_until +from .plusformat import plusformat __all__ = ["asyncify", "Call", "Command", "safeformat", "InvalidInputError", "UnsupportedError", "CommandArgs", - "cdj", "InvalidConfigError", "ExternalError", "sleep_until", "UnregisteredError"] + "cdj", "InvalidConfigError", "ExternalError", "sleep_until", "UnregisteredError", "plusformat"] diff --git a/royalnet/utils/command.py b/royalnet/utils/command.py index 84a26f8e..e8ff76ee 100644 --- a/royalnet/utils/command.py +++ b/royalnet/utils/command.py @@ -43,11 +43,12 @@ class CommandArgs(list): raise InvalidInputError("Pattern didn't match") return match - def optional(self, index: int) -> typing.Optional: + def optional(self, index: int, default=None) -> typing.Optional: try: return self[index] - except IndexError: - return None + except InvalidInputError: + return default + class Command: """A generic command, called from any source.""" diff --git a/royalnet/utils/plusformat.py b/royalnet/utils/plusformat.py new file mode 100644 index 00000000..ef5ba0b9 --- /dev/null +++ b/royalnet/utils/plusformat.py @@ -0,0 +1,4 @@ +def plusformat(i: int) -> str: + if i >= 0: + return f"+{i}" + return str(i)