1
Fork 0
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:
Steffo 2019-04-12 00:55:35 +02:00
parent c907422156
commit 49382b9bc1
14 changed files with 197 additions and 52 deletions

View file

@ -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...")

View file

@ -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()

View file

@ -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):

View file

@ -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!")

View file

@ -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()

View file

@ -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}>"

View file

@ -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)}>"

View file

@ -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}>"

View file

@ -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)}>"

View file

@ -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}>"

View file

@ -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}>"

View file

@ -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}>"

View file

@ -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)}>"

View file

@ -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):