From 30b9ec4b5d448a4b4ff9a78dc4388d74be3d4d5b Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 9 Apr 2019 12:41:03 +0200 Subject: [PATCH 1/3] Start work on kv commands --- royalgames.py | 2 +- royalnet/commands/__init__.py | 5 +++- royalnet/commands/kv.py | 34 +++++++++++++++++++++++ royalnet/commands/kvactive.py | 24 ++++++++++++++++ royalnet/database/tables/__init__.py | 4 ++- royalnet/database/tables/activekvgroup.py | 18 ++++++++++++ royalnet/database/tables/keygroup.py | 13 +++++++++ royalnet/database/tables/keyvalue.py | 17 ++++++++++++ royalnet/utils/command.py | 1 + 9 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 royalnet/commands/kv.py create mode 100644 royalnet/commands/kvactive.py create mode 100644 royalnet/database/tables/activekvgroup.py create mode 100644 royalnet/database/tables/keygroup.py create mode 100644 royalnet/database/tables/keyvalue.py diff --git a/royalgames.py b/royalgames.py index 14a079a7..a0c11783 100644 --- a/royalgames.py +++ b/royalgames.py @@ -10,7 +10,7 @@ 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] 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..1b8ea12a 100644 --- a/royalnet/commands/__init__.py +++ b/royalnet/commands/__init__.py @@ -10,7 +10,10 @@ from .rage import RageCommand from .dateparser import DateparserCommand from .author import AuthorCommand from .reminder import ReminderCommand +from .kvactive import KvactiveCommand +from .kv import KvCommand __all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand", - "SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand"] + "SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand", + "KvactiveCommand", "KvCommand"] diff --git a/royalnet/commands/kv.py b/royalnet/commands/kv.py new file mode 100644 index 00000000..91fb7de3 --- /dev/null +++ b/royalnet/commands/kv.py @@ -0,0 +1,34 @@ +from ..database.tables import ActiveKvGroup, Royal, Keyvalue +from ..utils import Command, Call, asyncify + + +class KvCommand(Command): + + command_name = "kv" + command_description = "Visualizza o modifica un valore rv." + command_syntax = "(nomegruppo)" + + require_alchemy_tables = {ActiveKvGroup, Royal, Keyvalue} + + @classmethod + async def common(cls, call: Call): + key = call.args[0] + 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) + keyvalue = await asyncify(call.session.query(call.alchemy.Keyvalue).filter_by(group=active.group_name, 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 + if keyvalue is None: + keyvalue = call.alchemy.Keyvalue(group=active, 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..8981d109 --- /dev/null +++ b/royalnet/commands/kvactive.py @@ -0,0 +1,24 @@ +from ..database.tables import ActiveKvGroup, Royal +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} + + @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: + active = call.alchemy.ActiveKvGroup(royal=author, group=group_name) + call.session.add(active) + else: + active.group = group_name + await asyncify(call.session.commit) + await call.reply(f"✅ Hai attivato il gruppo [b]{group_name}[/b].") diff --git a/royalnet/database/tables/__init__.py b/royalnet/database/tables/__init__.py index dc48894b..709882c9 100644 --- a/royalnet/database/tables/__init__.py +++ b/royalnet/database/tables/__init__.py @@ -2,5 +2,7 @@ from .royals import Royal from .telegram import Telegram from .diario import Diario from .aliases import Alias +from .activekvgroup import ActiveKvGroup +from .keyvalue import Keyvalue -__all__ = ["Royal", "Telegram", "Diario", "Alias"] +__all__ = ["Royal", "Telegram", "Diario", "Alias", "ActiveKvGroup", "Keyvalue"] 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..f54c1177 --- /dev/null +++ b/royalnet/database/tables/keygroup.py @@ -0,0 +1,13 @@ +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..fd267dd9 --- /dev/null +++ b/royalnet/database/tables/keyvalue.py @@ -0,0 +1,17 @@ +from sqlalchemy import Column, \ + String, \ + ForeignKey + + +class Keyvalue: + __tablename__ = "keyvalues" + + group = Column(String, ForeignKey("keygroups.group_name"), primary_key=True) + key = Column(String, primary_key=True) + value = Column(String, nullable=False) + + def __repr__(self): + return f"" + + def __str__(self): + return f"{self.key}: [b]{self.value}[/b]" diff --git a/royalnet/utils/command.py b/royalnet/utils/command.py index 84a26f8e..323d8103 100644 --- a/royalnet/utils/command.py +++ b/royalnet/utils/command.py @@ -49,6 +49,7 @@ class CommandArgs(list): except IndexError: return None + class Command: """A generic command, called from any source.""" From 9a2d43aef30696cea20c0a23e31645918e9699e8 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 9 Apr 2019 17:00:14 +0200 Subject: [PATCH 2/3] Complete kv commands --- royalgames.py | 3 ++- royalnet/commands/__init__.py | 3 ++- royalnet/commands/kv.py | 18 +++++++------ royalnet/commands/kvactive.py | 14 +++++++--- royalnet/commands/kvroll.py | 39 ++++++++++++++++++++++++++++ royalnet/database/tables/__init__.py | 3 ++- royalnet/database/tables/keygroup.py | 1 - royalnet/database/tables/keyvalue.py | 8 ++++-- royalnet/utils/__init__.py | 3 ++- royalnet/utils/command.py | 6 ++--- royalnet/utils/plusformat.py | 4 +++ 11 files changed, 81 insertions(+), 21 deletions(-) create mode 100644 royalnet/commands/kvroll.py create mode 100644 royalnet/utils/plusformat.py diff --git a/royalgames.py b/royalgames.py index a0c11783..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, KvactiveCommand, KvCommand] + 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 1b8ea12a..33fdb22a 100644 --- a/royalnet/commands/__init__.py +++ b/royalnet/commands/__init__.py @@ -12,8 +12,9 @@ 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", - "KvactiveCommand", "KvCommand"] + "KvactiveCommand", "KvCommand", "KvrollCommand"] diff --git a/royalnet/commands/kv.py b/royalnet/commands/kv.py index 91fb7de3..e14d554a 100644 --- a/royalnet/commands/kv.py +++ b/royalnet/commands/kv.py @@ -1,22 +1,24 @@ -from ..database.tables import ActiveKvGroup, Royal, Keyvalue +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 rv." - command_syntax = "(nomegruppo)" + command_description = "Visualizza o modifica un valore kv." + command_syntax = "(chiave) [valore]" - require_alchemy_tables = {ActiveKvGroup, Royal, Keyvalue} + require_alchemy_tables = {ActiveKvGroup, Royal, Keyvalue, Keygroup} @classmethod async def common(cls, call: Call): - key = call.args[0] + 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) - keyvalue = await asyncify(call.session.query(call.alchemy.Keyvalue).filter_by(group=active.group_name, key=key).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: @@ -24,9 +26,9 @@ class KvCommand(Command): return await call.reply(f"ℹ️ Valore della chiave:\n{keyvalue}") else: - # Set + # Set/kv asdf 1000 if keyvalue is None: - keyvalue = call.alchemy.Keyvalue(group=active, key=key, value=value) + keyvalue = call.alchemy.Keyvalue(group=active.group, key=key, value=value) call.session.add(keyvalue) else: keyvalue.value = value diff --git a/royalnet/commands/kvactive.py b/royalnet/commands/kvactive.py index 8981d109..204b6887 100644 --- a/royalnet/commands/kvactive.py +++ b/royalnet/commands/kvactive.py @@ -1,4 +1,4 @@ -from ..database.tables import ActiveKvGroup, Royal +from ..database.tables import ActiveKvGroup, Royal, Keygroup from ..utils import Command, Call, asyncify @@ -16,9 +16,17 @@ class KvactiveCommand(Command): 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: - active = call.alchemy.ActiveKvGroup(royal=author, group=group_name) + 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: - active.group = group_name + 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 709882c9..0e5b8dd6 100644 --- a/royalnet/database/tables/__init__.py +++ b/royalnet/database/tables/__init__.py @@ -4,5 +4,6 @@ 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", "ActiveKvGroup", "Keyvalue"] +__all__ = ["Royal", "Telegram", "Diario", "Alias", "ActiveKvGroup", "Keyvalue", "Keygroup"] diff --git a/royalnet/database/tables/keygroup.py b/royalnet/database/tables/keygroup.py index f54c1177..ed5557ce 100644 --- a/royalnet/database/tables/keygroup.py +++ b/royalnet/database/tables/keygroup.py @@ -10,4 +10,3 @@ class Keygroup: def __repr__(self): return f"" - diff --git a/royalnet/database/tables/keyvalue.py b/royalnet/database/tables/keyvalue.py index fd267dd9..d09e63c8 100644 --- a/royalnet/database/tables/keyvalue.py +++ b/royalnet/database/tables/keyvalue.py @@ -1,17 +1,21 @@ from sqlalchemy import Column, \ String, \ ForeignKey +from sqlalchemy.orm import relationship +from .keygroup import Keygroup class Keyvalue: __tablename__ = "keyvalues" - group = Column(String, ForeignKey("keygroups.group_name"), primary_key=True) + 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"" + 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 323d8103..e8ff76ee 100644 --- a/royalnet/utils/command.py +++ b/royalnet/utils/command.py @@ -43,11 +43,11 @@ 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: 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) From 1c6ddad5ea0bf09134acdd99c6df96641801ffe4 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 9 Apr 2019 17:04:21 +0200 Subject: [PATCH 3/3] Bugfix --- royalnet/commands/kvactive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/royalnet/commands/kvactive.py b/royalnet/commands/kvactive.py index 204b6887..a9f7227b 100644 --- a/royalnet/commands/kvactive.py +++ b/royalnet/commands/kvactive.py @@ -8,7 +8,7 @@ class KvactiveCommand(Command): command_description = "Seleziona un gruppo di valori kv." command_syntax = "(nomegruppo)" - require_alchemy_tables = {ActiveKvGroup, Royal} + require_alchemy_tables = {ActiveKvGroup, Royal, Keygroup} @classmethod async def common(cls, call: Call):