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:
parent
22b8cdf97f
commit
e1c3270527
43 changed files with 125 additions and 188 deletions
|
@ -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"]
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import discord
|
||||
import asyncio
|
||||
import typing
|
||||
import logging as _logging
|
||||
from .generic import GenericBot
|
||||
from ..commands import NullCommand
|
||||
from royalnet.commands import NullCommand
|
||||
from ..utils import asyncify, Call, Command, discord_escape
|
||||
from ..error import UnregisteredError, NoneFoundError, TooManyFoundError, InvalidConfigError, RoyalnetResponseError
|
||||
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
||||
|
|
|
@ -3,7 +3,7 @@ import typing
|
|||
import asyncio
|
||||
import logging
|
||||
from ..utils import Command, NetworkHandler, Call
|
||||
from ..commands import NullCommand
|
||||
from royalnet.commands import NullCommand
|
||||
from ..network import RoyalnetLink, Request, Response, ResponseError, RoyalnetConfig
|
||||
from ..database import Alchemy, DatabaseConfig, relationshiplinkchain
|
||||
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import telegram
|
||||
import telegram.utils.request
|
||||
import asyncio
|
||||
import typing
|
||||
import logging as _logging
|
||||
from .generic import GenericBot
|
||||
from ..commands import NullCommand
|
||||
from royalnet.commands import NullCommand
|
||||
from ..utils import asyncify, Call, Command, telegram_escape
|
||||
from ..error import UnregisteredError, InvalidConfigError, RoyalnetResponseError
|
||||
from ..network import RoyalnetConfig, Request, ResponseSuccess, ResponseError
|
||||
|
|
|
@ -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."""
|
||||
|
||||
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"]
|
||||
__all__ = ["CommandInterface", "Command"]
|
||||
|
|
28
royalnet/commands/command.py
Normal file
28
royalnet/commands/command.py
Normal 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
|
44
royalnet/commands/commandinterface.py
Normal file
44
royalnet/commands/commandinterface.py
Normal 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()
|
40
royalnet/commands/royalgames/__init__.py
Normal file
40
royalnet/commands/royalgames/__init__.py
Normal 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"]
|
|
@ -6,8 +6,8 @@ import logging
|
|||
from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig
|
||||
from royalnet.commands import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from royalnet.commands.debug_create import DebugCreateCommand
|
||||
from royalnet.commands.error_handler import ErrorHandlerCommand
|
||||
from royalnet.commands import DebugCreateCommand
|
||||
from royalnet.commands import ErrorHandlerCommand
|
||||
from royalnet.network import RoyalnetServer, RoyalnetConfig
|
||||
from royalnet.database import DatabaseConfig
|
||||
from royalnet.database.tables import Royal, Telegram, Discord
|
||||
|
|
|
@ -6,11 +6,9 @@ import logging
|
|||
from royalnet.bots import DiscordBot, DiscordConfig, TelegramBot, TelegramConfig
|
||||
from royalnet.commands import *
|
||||
# noinspection PyUnresolvedReferences
|
||||
from royalnet.commands.debug_create import DebugCreateCommand
|
||||
from royalnet.commands.error_handler import ErrorHandlerCommand
|
||||
from royalnet.commands import DebugCreateCommand
|
||||
from royalnet.commands import ErrorHandlerCommand
|
||||
from royalnet.network import RoyalnetServer, RoyalnetConfig
|
||||
from royalnet.database import DatabaseConfig
|
||||
from royalnet.database.tables import Royal, Telegram, Discord
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
from .asyncify import asyncify
|
||||
from .escaping import telegram_escape, discord_escape
|
||||
from .call import Call
|
||||
from .command import Command
|
||||
from .commandargs import CommandArgs
|
||||
from .safeformat import safeformat
|
||||
from .classdictjanitor import cdj
|
||||
|
@ -11,6 +9,6 @@ from .sleepuntil import sleep_until
|
|||
from .networkhandler import NetworkHandler
|
||||
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",
|
||||
"telegram_escape", "discord_escape"]
|
||||
|
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in a new issue