1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Start moving some stuff around

This commit is contained in:
Steffo 2019-08-18 00:42:26 +03:00
parent 22b8cdf97f
commit e1c3270527
43 changed files with 125 additions and 188 deletions

View file

@ -1,3 +1,4 @@
from . import audio, bots, commands, database, network, utils, error, web, version from . import audio, bots, database, network, utils, error, web, version
from royalnet import commands
__all__ = ["audio", "bots", "commands", "database", "network", "utils", "error", "web", "version"] __all__ = ["audio", "bots", "commands", "database", "network", "utils", "error", "web", "version"]

View file

@ -1,9 +1,8 @@
import discord import discord
import asyncio
import typing import typing
import logging as _logging import logging as _logging
from .generic import GenericBot from .generic import GenericBot
from ..commands import NullCommand from royalnet.commands import NullCommand
from ..utils import asyncify, Call, Command, discord_escape from ..utils import asyncify, Call, Command, discord_escape
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError, RoyalnetResponseError from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError, RoyalnetResponseError
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError

View file

@ -3,7 +3,7 @@ import typing
import asyncio import asyncio
import logging import logging
from ..utils import Command, NetworkHandler, Call from ..utils import Command, NetworkHandler, Call
from ..commands import NullCommand from royalnet.commands import NullCommand
from ..network import RoyalnetLink, Request, Response, ResponseError, RoyalnetConfig from ..network import RoyalnetLink, Request, Response, ResponseError, RoyalnetConfig
from ..database import Alchemy, DatabaseConfig, relationshiplinkchain from ..database import Alchemy, DatabaseConfig, relationshiplinkchain

View file

@ -1,10 +1,9 @@
import telegram import telegram
import telegram.utils.request import telegram.utils.request
import asyncio
import typing import typing
import logging as _logging import logging as _logging
from .generic import GenericBot from .generic import GenericBot
from ..commands import NullCommand from royalnet.commands import NullCommand
from ..utils import asyncify, Call, Command, telegram_escape from ..utils import asyncify, Call, Command, telegram_escape
from ..error import UnregisteredError, InvalidConfigError, RoyalnetResponseError from ..error import UnregisteredError, InvalidConfigError, RoyalnetResponseError
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError

View file

@ -1,39 +1,4 @@
"""Commands that can be used in bots. from .commandinterface import CommandInterface
from .command import Command
These probably won't suit your needs, as they are tailored for the bots of the Royal Games gaming community, but they may be useful to develop new ones.""" __all__ = ["CommandInterface", "Command"]
from .null import NullCommand
from .ping import PingCommand
from .ship import ShipCommand
from .smecds import SmecdsCommand
from .ciaoruozi import CiaoruoziCommand
from .color import ColorCommand
from .sync import SyncCommand
from .diario import DiarioCommand
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
from .videoinfo import VideoinfoCommand
from .summon import SummonCommand
from .play import PlayCommand
from .skip import SkipCommand
from .playmode import PlaymodeCommand
from .videochannel import VideochannelCommand
from .missing import MissingCommand
from .cv import CvCommand
from .pause import PauseCommand
from .queue import QueueCommand
from .royalnetprofile import RoyalnetprofileCommand
from .id import IdCommand
from .dlmusic import DlmusicCommand
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand",
"SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand",
"KvactiveCommand", "KvCommand", "KvrollCommand", "VideoinfoCommand", "SummonCommand", "PlayCommand",
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand", "PauseCommand",
"QueueCommand", "RoyalnetprofileCommand", "IdCommand", "DlmusicCommand"]

View file

@ -0,0 +1,28 @@
import typing
from ..error import UnsupportedError
from .commandinterface import CommandInterface
class Command:
name: str = NotImplemented
"""The main name of the command.
To have ``/example`` on Telegram, the name should be ``example``."""
description: str = NotImplemented
"""A small description of the command, to be displayed when the command is being autocompleted."""
syntax: str = NotImplemented
"""The syntax of the command, to be displayed when a :py:exc:`royalnet.error.InvalidInputError` is raised,
in the format ``(required_arg) [optional_arg]``."""
require_alchemy_tables: typing.Set = set()
"""A set of :py:class:`royalnet.database` tables that must exist for this command to work."""
def __init__(self, interface: CommandInterface):
self.interface = interface
async def common(self) -> None:
raise UnsupportedError(f"Command {self.name} can't be called on {self.interface.name}.")
def __getattr__(self, item) -> typing.Callable:
return self.common

View file

@ -0,0 +1,44 @@
import typing
if typing.TYPE_CHECKING:
from ..database import Alchemy
from ..bots import GenericBot
class CommandInterface:
name: str = NotImplemented
prefix: str = NotImplemented
alchemy: "Alchemy" = NotImplemented
bot: "GenericBot" = NotImplemented
def __init__(self, alias: str):
self.session = self.alchemy.Session()
async def reply(self, text: str) -> None:
"""Send a text message to the channel where the call was made.
Parameters:
text: The text to be sent, possibly formatted in the weird undescribed markup that I'm using."""
raise NotImplementedError()
async def net_request(self, message, destination: str) -> dict:
"""Send data through a :py:class:`royalnet.network.RoyalnetLink` and wait for a :py:class:`royalnet.network.Reply`.
Parameters:
message: The data to be sent. Must be :py:mod:`pickle`-able.
destination: The destination of the request, either in UUID format or node name."""
raise NotImplementedError()
async def get_author(self, error_if_none: bool = False):
"""Try to find the identifier of the user that sent the message.
That probably means, the database row identifying the user.
Parameters:
error_if_none: Raise a :py:exc:`royalnet.error.UnregisteredError` if this is True and the call has no author.
Raises:
:py:exc:`royalnet.error.UnregisteredError` if ``error_if_none`` is set to True and no author is found."""
raise NotImplementedError()
def register_net_handler(self, message_type: str, network_handler: typing.Callable):
"""Register a new handler for messages received through Royalnet."""
raise NotImplementedError()

View file

@ -0,0 +1,40 @@
"""Commands that can be used in bots.
These probably won't suit your needs, as they are tailored for the bots of the Royal Games gaming community, but they
may be useful to develop new ones."""
from .null import NullCommand
from .ping import PingCommand
from .ship import ShipCommand
from .smecds import SmecdsCommand
from .ciaoruozi import CiaoruoziCommand
from .color import ColorCommand
from .sync import SyncCommand
from .diario import DiarioCommand
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
from .videoinfo import VideoinfoCommand
from .summon import SummonCommand
from .play import PlayCommand
from .skip import SkipCommand
from .playmode import PlaymodeCommand
from .videochannel import VideochannelCommand
from .missing import MissingCommand
from .cv import CvCommand
from .pause import PauseCommand
from .queue import QueueCommand
from .royalnetprofile import RoyalnetprofileCommand
from .id import IdCommand
from .dlmusic import DlmusicCommand
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand",
"SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand",
"KvactiveCommand", "KvCommand", "KvrollCommand", "VideoinfoCommand", "SummonCommand", "PlayCommand",
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand", "PauseCommand",
"QueueCommand", "RoyalnetprofileCommand", "IdCommand", "DlmusicCommand"]

View file

@ -6,8 +6,8 @@ import logging
from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig
from royalnet.commands import * from royalnet.commands import *
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from royalnet.commands.debug_create import DebugCreateCommand from royalnet.commands import DebugCreateCommand
from royalnet.commands.error_handler import ErrorHandlerCommand from royalnet.commands import ErrorHandlerCommand
from royalnet.network import RoyalnetServer, RoyalnetConfig from royalnet.network import RoyalnetServer, RoyalnetConfig
from royalnet.database import DatabaseConfig from royalnet.database import DatabaseConfig
from royalnet.database.tables import Royal, Telegram, Discord from royalnet.database.tables import Royal, Telegram, Discord

View file

@ -6,11 +6,9 @@ import logging
from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig
from royalnet.commands import * from royalnet.commands import *
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences
from royalnet.commands.debug_create import DebugCreateCommand from royalnet.commands import DebugCreateCommand
from royalnet.commands.error_handler import ErrorHandlerCommand from royalnet.commands import ErrorHandlerCommand
from royalnet.network import RoyalnetServer, RoyalnetConfig from royalnet.network import RoyalnetServer, RoyalnetConfig
from royalnet.database import DatabaseConfig
from royalnet.database.tables import Royal, Telegram, Discord
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()

View file

@ -2,8 +2,6 @@
from .asyncify import asyncify from .asyncify import asyncify
from .escaping import telegram_escape, discord_escape from .escaping import telegram_escape, discord_escape
from .call import Call
from .command import Command
from .commandargs import CommandArgs from .commandargs import CommandArgs
from .safeformat import safeformat from .safeformat import safeformat
from .classdictjanitor import cdj from .classdictjanitor import cdj
@ -11,6 +9,6 @@ from .sleepuntil import sleep_until
from .networkhandler import NetworkHandler from .networkhandler import NetworkHandler
from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat
__all__ = ["asyncify", "Call", "Command", "safeformat", "cdj", "sleep_until", "plusformat", "CommandArgs", __all__ = ["asyncify", "safeformat", "cdj", "sleep_until", "plusformat", "CommandArgs",
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat", "NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat",
"telegram_escape", "discord_escape"] "telegram_escape", "discord_escape"]

View file

@ -1,100 +0,0 @@
import typing
import asyncio
from .command import Command
from .commandargs import CommandArgs
if typing.TYPE_CHECKING:
from ..database import Alchemy
class Call:
"""A command call. An abstract class, sub-bots should create a new call class from this.
Attributes:
interface_name: The name of the interface that is calling the command. For example, ``telegram``, or ``discord``.
interface_obj: The main object of the interface that is calling the command. For example, the :py:class:`royalnet.bots.TelegramBot` object.
interface_prefix: The command prefix used by the interface. For example, ``/``, or ``!``.
alchemy: The :py:class:`royalnet.database.Alchemy` object associated to this interface. May be None if the interface is not connected to any database."""
# These parameters / methods should be overridden
interface_name = NotImplemented
interface_obj = NotImplemented
interface_prefix = NotImplemented
alchemy: "Alchemy" = NotImplemented
async def reply(self, text: str) -> None:
"""Send a text message to the channel where the call was made.
Parameters:
text: The text to be sent, possibly formatted in the weird undescribed markup that I'm using."""
raise NotImplementedError()
async def net_request(self, message, destination: str) -> dict:
"""Send data through a :py:class:`royalnet.network.RoyalnetLink` and wait for a :py:class:`royalnet.network.Reply`.
Parameters:
message: The data to be sent. Must be :py:mod:`pickle`-able.
destination: The destination of the request, either in UUID format or node name."""
raise NotImplementedError()
async def get_author(self, error_if_none=False):
"""Try to find the universal identifier of the user that sent the message.
That probably means, the database row identifying the user.
Parameters:
error_if_none: Raise a :py:exc:`royalnet.error.UnregisteredError` if this is True and the call has no author.
Raises:
:py:exc:`royalnet.error.UnregisteredError` if ``error_if_none`` is set to True and no author is found."""
raise NotImplementedError()
# These parameters / methods should be left alone
def __init__(self,
channel,
command: typing.Type[Command],
command_args: typing.List[str] = None,
loop: asyncio.AbstractEventLoop = None,
**kwargs):
"""Create the call.
Parameters:
channel: The channel object this call was sent in.
command: The command to be called.
command_args: The arguments to be passed to the command
kwargs: Additional optional keyword arguments that may be passed to the command, possibly specific to the bot.
"""
if command_args is None:
command_args = []
if loop is None:
self.loop = asyncio.get_event_loop()
else:
self.loop = loop
self.channel = channel
self.command = command
self.args = CommandArgs(command_args)
self.kwargs = kwargs
self.session = None
async def _session_init(self):
"""If the command requires database access, create a :py:class:`royalnet.database.Alchemy` session for this call, otherwise, do nothing."""
if not self.command.require_alchemy_tables:
return
self.session = await self.loop.run_in_executor(None, self.alchemy.Session)
async def session_end(self):
"""Close the previously created :py:class:`royalnet.database.Alchemy` session for this call (if it was created)."""
if not self.session:
return
self.session.close()
async def run(self):
"""Execute the called command, and return the command result."""
await self._session_init()
try:
coroutine = getattr(self.command, self.interface_name)
except AttributeError:
coroutine = self.command.common
try:
result = await coroutine(self)
finally:
await self.session_end()
return result

View file

@ -1,35 +0,0 @@
import typing
from ..error import UnsupportedError
if typing.TYPE_CHECKING:
from .call import Call
from ..utils import NetworkHandler
class Command:
"""The base class from which all commands should inherit."""
command_name: typing.Optional[str] = NotImplemented
"""The name of the command. To have ``/example`` on Telegram, the name should be ``example``. If the name is None or empty, the command won't be registered."""
command_description: str = NotImplemented
"""A small description of the command, to be displayed when the command is being autocompleted."""
command_syntax: str = NotImplemented
"""The syntax of the command, to be displayed when a :py:exc:`royalnet.error.InvalidInputError` is raised, in the format ``(required_arg) [optional_arg]``."""
require_alchemy_tables: typing.Set = set()
"""A set of :py:class:`royalnet.database` tables, that must exist for this command to work."""
network_handlers: typing.List[typing.Type["NetworkHandler"]] = []
"""A set of :py:class:`royalnet.utils.NetworkHandler`s that must exist for this command to work."""
@classmethod
async def common(cls, call: "Call"):
raise UnsupportedError()
@classmethod
def network_handler_dict(cls):
d = {}
for network_handler in cls.network_handlers:
d[network_handler.message_type] = network_handler
return d