mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-27 13:34:28 +00:00
Working discord bot implementation! :O
This commit is contained in:
parent
c907422156
commit
49382b9bc1
14 changed files with 197 additions and 52 deletions
|
@ -18,6 +18,7 @@ tg_bot = TelegramBot(os.environ["TG_AK"], "localhost:1234", "sas", commands, os.
|
|||
ds_bot = DiscordBot(os.environ["DS_AK"], "localhost:1234", "sas", commands, os.environ["DB_PATH"], Royal, Discord, "discord_id", error_command=ErrorHandlerCommand)
|
||||
loop.create_task(master.run())
|
||||
loop.create_task(tg_bot.run())
|
||||
loop.create_task(ds_bot.run())
|
||||
print("Commands enabled:")
|
||||
print(tg_bot.generate_botfather_command_string())
|
||||
print("Starting loop...")
|
||||
|
|
|
@ -2,6 +2,7 @@ import discord
|
|||
import asyncio
|
||||
import typing
|
||||
import logging as _logging
|
||||
import sys
|
||||
from ..commands import NullCommand
|
||||
from ..utils import asyncify, Call, Command, UnregisteredError
|
||||
from ..network import RoyalnetLink, Message
|
||||
|
@ -16,10 +17,6 @@ async def todo(message: Message):
|
|||
|
||||
|
||||
class DiscordBot:
|
||||
# noinspection PyMethodParameters
|
||||
class DiscordClient(discord.Client):
|
||||
pass
|
||||
|
||||
def __init__(self,
|
||||
token: str,
|
||||
master_server_uri: str,
|
||||
|
@ -32,13 +29,14 @@ class DiscordBot:
|
|||
missing_command: typing.Type[Command] = NullCommand,
|
||||
error_command: typing.Type[Command] = NullCommand):
|
||||
self.token = token
|
||||
self.bot = self.DiscordClient()
|
||||
self.missing_command = missing_command
|
||||
self.error_command = error_command
|
||||
self.network: RoyalnetLink = RoyalnetLink(master_server_uri, master_server_secret, "discord", todo)
|
||||
# Generate commands
|
||||
self.commands = {}
|
||||
required_tables = set()
|
||||
for command in commands:
|
||||
self.commands[f"/{command.command_name}"] = command
|
||||
self.commands[f"!{command.command_name}"] = command
|
||||
required_tables = required_tables.union(command.require_alchemy_tables)
|
||||
# Generate the Alchemy database
|
||||
self.alchemy = Alchemy(database_uri, required_tables)
|
||||
|
@ -51,6 +49,7 @@ class DiscordBot:
|
|||
class DiscordCall(Call):
|
||||
interface_name = "discord"
|
||||
interface_obj = self
|
||||
interface_prefix = "!"
|
||||
alchemy = self.alchemy
|
||||
|
||||
async def reply(call, text: str):
|
||||
|
@ -85,6 +84,37 @@ class DiscordBot:
|
|||
|
||||
self.DiscordCall = DiscordCall
|
||||
|
||||
# noinspection PyMethodParameters
|
||||
class DiscordClient(discord.Client):
|
||||
async def on_message(cli, message: discord.Message):
|
||||
text = message.content
|
||||
# Skip non-text messages
|
||||
if not text:
|
||||
return
|
||||
# Find and clean parameters
|
||||
command_text, *parameters = text.split(" ")
|
||||
# Find the function
|
||||
try:
|
||||
selected_command = self.commands[command_text]
|
||||
except KeyError:
|
||||
# Skip inexistent commands
|
||||
selected_command = self.missing_command
|
||||
# Call the command
|
||||
try:
|
||||
return await self.DiscordCall(message.channel, selected_command, parameters, log,
|
||||
message=message).run()
|
||||
except Exception as exc:
|
||||
try:
|
||||
return await self.DiscordCall(message.channel, self.error_command, parameters, log,
|
||||
message=message,
|
||||
exception_info=sys.exc_info(),
|
||||
previous_command=selected_command).run()
|
||||
except Exception as exc2:
|
||||
log.error(f"Exception in error handler command: {exc2}")
|
||||
|
||||
self.DiscordClient = DiscordClient
|
||||
self.bot = self.DiscordClient()
|
||||
|
||||
async def run(self):
|
||||
await self.bot.login(self.token)
|
||||
await self.bot.connect()
|
||||
|
|
|
@ -51,6 +51,7 @@ class TelegramBot:
|
|||
class TelegramCall(Call):
|
||||
interface_name = "telegram"
|
||||
interface_obj = self
|
||||
interface_prefix = "/"
|
||||
alchemy = self.alchemy
|
||||
|
||||
async def reply(call, text: str):
|
||||
|
|
|
@ -11,10 +11,6 @@ class ErrorHandlerCommand(Command):
|
|||
|
||||
@classmethod
|
||||
async def common(cls, call: Call):
|
||||
raise UnsupportedError()
|
||||
|
||||
@classmethod
|
||||
async def telegram(cls, call: Call):
|
||||
try:
|
||||
e_type, e_value, e_tb = call.kwargs["exception_info"]
|
||||
except InvalidInputError:
|
||||
|
@ -22,7 +18,7 @@ class ErrorHandlerCommand(Command):
|
|||
return
|
||||
if e_type == InvalidInputError:
|
||||
command = call.kwargs["previous_command"]
|
||||
await call.reply(f"⚠️ Sintassi non valida.\nSintassi corretta: [c]/{command.command_name} {command.command_syntax}[/c]")
|
||||
await call.reply(f"⚠️ Sintassi non valida.\nSintassi corretta: [c]{call.interface_prefix}{command.command_name} {command.command_syntax}[/c]")
|
||||
return
|
||||
if e_type == UnregisteredError:
|
||||
await call.reply("⚠️ Devi essere registrato a Royalnet per usare questo comando!")
|
||||
|
|
|
@ -26,7 +26,7 @@ class Alchemy:
|
|||
except AttributeError:
|
||||
# Actually the intended result
|
||||
# TODO: here is the problem!
|
||||
self.__setattr__(name, type(name, (self.Base,), cdj(table)))
|
||||
self.__setattr__(name, type(name, (self.Base, table), {}))
|
||||
else:
|
||||
raise NameError(f"{name} is a reserved name and can't be used as a table name")
|
||||
self.Base.metadata.create_all()
|
||||
|
|
|
@ -3,16 +3,29 @@ from sqlalchemy import Column, \
|
|||
Integer, \
|
||||
ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from .royals import Royal
|
||||
from .keygroup import Keygroup
|
||||
|
||||
|
||||
class ActiveKvGroup:
|
||||
__tablename__ = "activekvgroups"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.uid"), primary_key=True)
|
||||
group_name = Column(String, ForeignKey("keygroups.group_name"), nullable=False)
|
||||
@declared_attr
|
||||
def royal_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"), primary_key=True)
|
||||
|
||||
royal = relationship("Royal", backref="active_kv_group")
|
||||
group = relationship("Keygroup", backref="users_with_this_active")
|
||||
@declared_attr
|
||||
def group_name(self):
|
||||
return Column(String, ForeignKey("keygroups.group_name"), nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def royal(self):
|
||||
return relationship("Royal", backref="active_kv_group")
|
||||
|
||||
@declared_attr
|
||||
def group(self):
|
||||
return relationship("Keygroup", backref="users_with_this_active")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ActiveKvGroup royal={self.royal} group={self.group_name}>"
|
||||
|
|
|
@ -3,16 +3,24 @@ from sqlalchemy import Column, \
|
|||
String, \
|
||||
ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from .royals import Royal
|
||||
|
||||
|
||||
class Alias:
|
||||
__tablename__ = "aliases"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.uid"))
|
||||
alias = Column(String, primary_key=True)
|
||||
@declared_attr
|
||||
def royal_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"))
|
||||
|
||||
royal = relationship("Royal", backref="aliases")
|
||||
@declared_attr
|
||||
def alias(self):
|
||||
return Column(String, primary_key=True)
|
||||
|
||||
@declared_attr
|
||||
def royal(self):
|
||||
return relationship("Royal", backref="aliases")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Alias {str(self)}>"
|
||||
|
|
|
@ -7,24 +7,56 @@ from sqlalchemy import Column, \
|
|||
ForeignKey, \
|
||||
String
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from .royals import Royal
|
||||
|
||||
|
||||
class Diario:
|
||||
__tablename__ = "diario"
|
||||
|
||||
diario_id = Column(Integer, primary_key=True)
|
||||
creator_id = Column(Integer, ForeignKey("royals.uid"), nullable=False)
|
||||
quoted_account_id = Column(Integer, ForeignKey("royals.uid"))
|
||||
quoted = Column(String)
|
||||
text = Column(Text)
|
||||
context = Column(Text)
|
||||
timestamp = Column(DateTime, nullable=False)
|
||||
media_url = Column(String)
|
||||
spoiler = Column(Boolean, default=False)
|
||||
@declared_attr
|
||||
def diario_id(self):
|
||||
return Column(Integer, primary_key=True)
|
||||
|
||||
creator = relationship("Royal", foreign_keys=creator_id, backref="diario_created")
|
||||
quoted_account = relationship("Royal", foreign_keys=quoted_account_id, backref="diario_quoted")
|
||||
@declared_attr
|
||||
def creator_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"), nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def quoted_account_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"))
|
||||
|
||||
@declared_attr
|
||||
def quoted(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def text(self):
|
||||
return Column(Text)
|
||||
|
||||
@declared_attr
|
||||
def context(self):
|
||||
return Column(Text)
|
||||
|
||||
@declared_attr
|
||||
def timestamp(self):
|
||||
return Column(DateTime, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def media_url(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def spoiler(self):
|
||||
return Column(Boolean, default=False)
|
||||
|
||||
@declared_attr
|
||||
def creator(self):
|
||||
return relationship("Royal", foreign_keys=self.creator_id, backref="diario_created")
|
||||
|
||||
@declared_attr
|
||||
def quoted_account(self):
|
||||
return relationship("Royal", foreign_keys=self.quoted_account_id, backref="diario_quoted")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Diario diario_id={self.diario_id} creator_id={self.creator_id} quoted_account_id={self.quoted_account_id} quoted={self.quoted} text={self.text} context={self.context} timestamp={self.timestamp} media_url={self.media_url} spoiler={self.spoiler}>"
|
||||
|
|
|
@ -4,19 +4,36 @@ from sqlalchemy import Column, \
|
|||
BigInteger, \
|
||||
ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from .royals import Royal
|
||||
|
||||
|
||||
class Discord:
|
||||
__tablename__ = "discord"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.uid"))
|
||||
discord_id = Column(BigInteger, primary_key=True)
|
||||
username = Column(String)
|
||||
discriminator = Column(String)
|
||||
avatar_hash = Column(String)
|
||||
@declared_attr
|
||||
def royal_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"))
|
||||
|
||||
royal = relationship("Royal", backref="discord")
|
||||
@declared_attr
|
||||
def discord_id(self):
|
||||
return Column(BigInteger, primary_key=True)
|
||||
|
||||
@declared_attr
|
||||
def username(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def discriminator(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def avatar_hash(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def royal(self):
|
||||
return relationship("Royal", backref="discord")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Discord {str(self)}>"
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
from sqlalchemy import Column, \
|
||||
String, \
|
||||
ForeignKey
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
|
||||
|
||||
class Keygroup:
|
||||
__tablename__ = "keygroups"
|
||||
|
||||
group_name = Column(String, ForeignKey("keygroups.group_name"), primary_key=True)
|
||||
@declared_attr
|
||||
def group_name(self):
|
||||
return Column(String, ForeignKey("keygroups.group_name"), primary_key=True)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Keygroup {self.group_name}>"
|
||||
|
|
|
@ -2,17 +2,28 @@ from sqlalchemy import Column, \
|
|||
String, \
|
||||
ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
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)
|
||||
@declared_attr
|
||||
def group_name(self):
|
||||
return Column(String, ForeignKey("keygroups.group_name"), primary_key=True)
|
||||
|
||||
group = relationship("Keygroup")
|
||||
@declared_attr
|
||||
def key(self):
|
||||
return Column(String, primary_key=True)
|
||||
|
||||
@declared_attr
|
||||
def value(self):
|
||||
return Column(String, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def group(self):
|
||||
return relationship("Keygroup")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Keyvalue group={self.group_name} key={self.key} value={self.value}>"
|
||||
|
|
|
@ -2,16 +2,31 @@ from sqlalchemy import Column, \
|
|||
Integer, \
|
||||
String, \
|
||||
LargeBinary
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
|
||||
|
||||
class Royal:
|
||||
__tablename__ = "royals"
|
||||
|
||||
uid = Column(Integer, unique=True, primary_key=True)
|
||||
username = Column(String, unique=True, nullable=False)
|
||||
password = Column(LargeBinary)
|
||||
role = Column(String, nullable=False)
|
||||
avatar = Column(LargeBinary)
|
||||
@declared_attr
|
||||
def uid(self):
|
||||
return Column(Integer, unique=True, primary_key=True)
|
||||
|
||||
@declared_attr
|
||||
def username(self):
|
||||
return Column(String, unique=True, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def password(self):
|
||||
return Column(LargeBinary)
|
||||
|
||||
@declared_attr
|
||||
def role(self):
|
||||
return Column(String, nullable=False)
|
||||
|
||||
@declared_attr
|
||||
def avatar(self):
|
||||
return Column(LargeBinary)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Royal {self.username}>"
|
||||
|
|
|
@ -5,19 +5,36 @@ from sqlalchemy import Column, \
|
|||
LargeBinary, \
|
||||
ForeignKey
|
||||
from sqlalchemy.orm import relationship
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
from .royals import Royal
|
||||
|
||||
|
||||
class Telegram:
|
||||
__tablename__ = "telegram"
|
||||
|
||||
royal_id = Column(Integer, ForeignKey("royals.uid"))
|
||||
tg_id = Column(BigInteger, primary_key=True)
|
||||
first_name = Column(String)
|
||||
last_name = Column(String)
|
||||
username = Column(String)
|
||||
@declared_attr
|
||||
def royal_id(self):
|
||||
return Column(Integer, ForeignKey("royals.uid"))
|
||||
|
||||
royal = relationship("Royal", backref="telegram")
|
||||
@declared_attr
|
||||
def tg_id(self):
|
||||
return Column(BigInteger, primary_key=True)
|
||||
|
||||
@declared_attr
|
||||
def first_name(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def last_name(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def username(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def royal(self):
|
||||
return relationship("Royal", backref="telegram")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Telegram {str(self)}>"
|
||||
|
|
|
@ -20,6 +20,7 @@ class Call:
|
|||
# These parameters / methods should be overridden
|
||||
interface_name = NotImplemented
|
||||
interface_obj = NotImplemented
|
||||
interface_prefix = NotImplemented
|
||||
alchemy: "Alchemy" = NotImplemented
|
||||
|
||||
async def reply(self, text: str):
|
||||
|
|
Loading…
Reference in a new issue