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

Do some more stuff

This commit is contained in:
Steffo 2019-04-01 12:33:20 +02:00
parent 472da17a7d
commit 7100193bd1
14 changed files with 110 additions and 25 deletions

17
royalgames.py Normal file
View file

@ -0,0 +1,17 @@
import os
import asyncio
from royalnet.bots import TelegramBot
from royalnet.commands import PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand
from royalnet.commands.debug_create import DebugCreateCommand
from royalnet.network import RoyalnetServer
loop = asyncio.get_event_loop()
commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand, DebugCreateCommand]
master = RoyalnetServer("localhost", 1234, "sas")
tg_bot = TelegramBot(os.environ["TG_AK"], "localhost:1234", "sas", commands, "sqlite://")
loop.create_task(master.run())
loop.create_task(tg_bot.run())
print("Starting loop...")
loop.run_forever()

View file

@ -34,10 +34,10 @@ class TelegramBot:
self.network: RoyalnetLink = RoyalnetLink(master_server_uri, master_server_secret, "telegram", todo) self.network: RoyalnetLink = RoyalnetLink(master_server_uri, master_server_secret, "telegram", todo)
# Generate commands # Generate commands
self.commands = {} self.commands = {}
required_tables = [] required_tables = set()
for command in commands: for command in commands:
self.commands[f"/{command.command_name}"] = command self.commands[f"/{command.command_name}"] = command
required_tables += command.require_alchemy_tables required_tables = required_tables.union(command.require_alchemy_tables)
# Generate the Alchemy database # Generate the Alchemy database
self.alchemy = Alchemy(database_uri, required_tables) self.alchemy = Alchemy(database_uri, required_tables)
@ -45,7 +45,7 @@ class TelegramBot:
class TelegramCall(Call): class TelegramCall(Call):
interface_name = "telegram" interface_name = "telegram"
interface_obj = self interface_obj = self
Session = self.alchemy.Session interface_alchemy = self.alchemy
async def reply(call, text: str): async def reply(call, text: str):
await asyncify(call.channel.send_message, text, parse_mode="HTML") await asyncify(call.channel.send_message, text, parse_mode="HTML")

View file

@ -2,5 +2,8 @@ from .null import NullCommand
from .ping import PingCommand from .ping import PingCommand
from .ship import ShipCommand from .ship import ShipCommand
from .smecds import SmecdsCommand from .smecds import SmecdsCommand
from .ciaoruozi import CiaoruoziCommand
from .color import ColorCommand
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand"]
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand"]

View file

@ -1,7 +1,7 @@
from ..utils import Command, CommandArgs, Call from ..utils import Command, CommandArgs, Call
class PingCommand(Command): class ColorCommand(Command):
command_name = "color" command_name = "color"
command_title = "Invia un colore in chat...?" command_title = "Invia un colore in chat...?"

View file

@ -0,0 +1,16 @@
from ..utils import Command, CommandArgs, Call
from ..database.tables import Royal
class DebugCreateCommand(Command):
command_name = "debug_create"
command_title = "Create a new Royalnet user account"
require_alchemy_tables = {Royal}
async def common(self, call: Call, args: CommandArgs):
royal = call.interface_alchemy.Royal(username=args[0], role="Member")
call.session.add(royal)
call.session.commit()
await call.reply(f"✅ Utente {royal} creato!")

View file

@ -1,4 +1,4 @@
from .alchemy import Alchemy from .alchemy import Alchemy
from .tables import Role, Royal from .tables import Royal
__all__ = ["Alchemy", "Role", "Royal"] __all__ = ["Alchemy", "Royal"]

View file

@ -4,13 +4,13 @@ from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from contextlib import contextmanager, asynccontextmanager from contextlib import contextmanager, asynccontextmanager
from ..utils import classdictjanitor from ..utils import cdj
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
class Alchemy: class Alchemy:
def __init__(self, database_uri: str = "sqlite://", tables: typing.Optional[typing.List] = None): def __init__(self, database_uri: str = "sqlite://", tables: typing.Optional[typing.Set] = None):
self.engine = create_engine(database_uri) self.engine = create_engine(database_uri)
self.Base = declarative_base(bind=self.engine) self.Base = declarative_base(bind=self.engine)
self.Session = sessionmaker(bind=self.engine) self.Session = sessionmaker(bind=self.engine)
@ -23,7 +23,7 @@ class Alchemy:
self.__getattribute__(name) self.__getattribute__(name)
except AttributeError: except AttributeError:
# Actually the intended result # Actually the intended result
self.__setattr__(name, type(name, (self.Base,), classdictjanitor(table))) self.__setattr__(name, type(name, (self.Base,), cdj(table)))
else: else:
raise NameError(f"{name} is a reserved name and can't be used as a table name") raise NameError(f"{name} is a reserved name and can't be used as a table name")
self.Base.metadata.create_all() self.Base.metadata.create_all()

View file

@ -1,3 +1,3 @@
from .royals import Role, Royal from .royals import Royal
__all__ = ["Role", "Royal"] __all__ = ["Royal"]

View file

@ -1,16 +1,9 @@
from enum import Enum
from sqlalchemy import Column, \ from sqlalchemy import Column, \
Integer, \ Integer, \
String, \ String, \
LargeBinary LargeBinary
class Role(Enum):
Guest = "Guest"
Member = "Member"
Admin = "Admin"
class Royal: class Royal:
__tablename__ = "royals" __tablename__ = "royals"
@ -18,3 +11,10 @@ class Royal:
username = Column(String, unique=True, nullable=False) username = Column(String, unique=True, nullable=False)
password = Column(LargeBinary) password = Column(LargeBinary)
role = Column(String, nullable=False) role = Column(String, nullable=False)
avatar = Column(LargeBinary)
def __repr__(self):
return f"<Royal {self.username}>"
def __str__(self):
return self.username

View file

@ -0,0 +1,28 @@
from sqlalchemy import Column, \
Integer, \
String, \
BigInteger, \
LargeBinary
class Telegram:
__tablename__ = "telegram"
royal_id = Column(Integer)
tg_id = Column(BigInteger, primary_key=True)
tg_first_name = Column(String)
tg_last_name = Column(String)
tg_username = Column(String)
tg_avatar = Column(LargeBinary)
def __repr__(self):
return f"<Telegram {str(self)}>"
def __str__(self):
if self.tg_username is not None:
return f"@{self.tg_username}"
elif self.tg_last_name is not None:
return f"{self.tg_first_name} {self.tg_last_name}"
else:
return self.tg_first_name

View file

@ -2,7 +2,7 @@ from .asyncify import asyncify
from .call import Call from .call import Call
from .command import Command, CommandArgs, InvalidInputError, UnsupportedError from .command import Command, CommandArgs, InvalidInputError, UnsupportedError
from .safeformat import safeformat from .safeformat import safeformat
from .classdictjanitor import classdictjanitor from .classdictjanitor import cdj
__all__ = ["asyncify", "Call", "Command", "safeformat", "InvalidInputError", "UnsupportedError", "CommandArgs", __all__ = ["asyncify", "Call", "Command", "safeformat", "InvalidInputError", "UnsupportedError", "CommandArgs",
"classdictjanitor"] "cdj"]

View file

@ -1,6 +1,11 @@
import typing import typing
import asyncio
from ..network.messages import Message from ..network.messages import Message
from .command import Command, CommandArgs from .command import Command, CommandArgs
from ..database import Alchemy
loop = asyncio.get_event_loop()
class Call: class Call:
@ -9,7 +14,7 @@ class Call:
# These parameters / methods should be overridden # These parameters / methods should be overridden
interface_name = NotImplemented interface_name = NotImplemented
interface_obj = NotImplemented interface_obj = NotImplemented
Session = NotImplemented interface_alchemy: Alchemy = NotImplemented
async def reply(self, text: str): async def reply(self, text: str):
"""Send a text message to the channel the call was made.""" """Send a text message to the channel the call was made."""
@ -26,10 +31,26 @@ class Call:
self.command = command self.command = command
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
self.session = None
async def session_init(self):
if not self.command.require_alchemy_tables:
return
self.session = await loop.run_in_executor(self.interface_alchemy.Session)
async def session_end(self):
if not self.session:
return
self.session.close()
async def run(self): async def run(self):
await self.session_init()
try: try:
coroutine = getattr(self.command, self.interface_name) coroutine = getattr(self.command, self.interface_name)
except AttributeError: except AttributeError:
coroutine = getattr(self.command, "common") coroutine = getattr(self.command, "common")
return await coroutine(self.command, self, CommandArgs(*self.args, **self.kwargs)) try:
result = await coroutine(self.command, self, CommandArgs(*self.args, **self.kwargs))
finally:
self.session.close()
return result

View file

@ -1,4 +1,4 @@
def classdictjanitor(class_) -> dict: def cdj(class_) -> dict:
"""Return the cleaned class attributes in a dict.""" """Return the cleaned class attributes in a dict."""
d = dict(class_.__dict__) d = dict(class_.__dict__)
del d["__module__"] del d["__module__"]

View file

@ -39,7 +39,7 @@ class Command:
command_name: str = NotImplemented command_name: str = NotImplemented
command_title: str = NotImplemented command_title: str = NotImplemented
require_alchemy_tables: typing.List = [] require_alchemy_tables: typing.Set = set()
async def common(self, call: "Call", args: CommandArgs): async def common(self, call: "Call", args: CommandArgs):
raise NotImplementedError() raise NotImplementedError()