diff --git a/docs/doctrees/apireference.doctree b/docs/doctrees/apireference.doctree index 46fb5e7e..8c7e5075 100644 Binary files a/docs/doctrees/apireference.doctree and b/docs/doctrees/apireference.doctree differ diff --git a/docs/doctrees/environment.pickle b/docs/doctrees/environment.pickle index 308b3e3d..a7f9c07b 100644 Binary files a/docs/doctrees/environment.pickle and b/docs/doctrees/environment.pickle differ diff --git a/docs/html/_sources/apireference.rst.txt b/docs/html/_sources/apireference.rst.txt index 78f973f2..a8b13455 100644 --- a/docs/html/_sources/apireference.rst.txt +++ b/docs/html/_sources/apireference.rst.txt @@ -5,66 +5,7 @@ These pages were automatically generated from docstrings in code. They might be outdated, or incomplete. -Audio ------------------------------------- - -.. automodule:: royalnet.audio - :members: - :undoc-members: - :private-members: - -Bots ------------------------------------- - -.. automodule:: royalnet.bots - :members: - :undoc-members: - :private-members: - -Commands ------------------------------------- - -.. automodule:: royalnet.commands - :members: - :undoc-members: - :private-members: - -Database ------------------------------------- - -.. automodule:: royalnet.database - :members: - :undoc-members: - :private-members: - -Network ------------------------------------- - -.. automodule:: royalnet.network - :members: - :undoc-members: - :private-members: - -Utils ------------------------------------- - -.. automodule:: royalnet.utils - :members: - :undoc-members: - :private-members: - -Web ------------------------------------- - -.. automodule:: royalnet.web - :members: - :undoc-members: - :private-members: - -Error ------------------------------------- - -.. automodule:: royalnet.error +.. automodule:: royalnet :members: :undoc-members: :private-members: diff --git a/docs/html/_static/jquery-3.4.1.js b/docs/html/_static/jquery-3.4.1.js index 1b8f13f9..773ad95c 100644 --- a/docs/html/_static/jquery-3.4.1.js +++ b/docs/html/_static/jquery-3.4.1.js @@ -5170,7 +5170,7 @@ jQuery.event = { } } - // Remove common event handler if we removed something and no more handlers exist + // Remove generic event handler if we removed something and no more handlers exist // (avoids potential for endless recursion during removal of special event handlers) if ( origCount && !handlers.length ) { if ( !special.teardown || diff --git a/docs/html/apireference.html b/docs/html/apireference.html index fa397e6a..66d957d9 100644 --- a/docs/html/apireference.html +++ b/docs/html/apireference.html @@ -83,17 +83,7 @@ @@ -162,1231 +152,6 @@

API Reference

These pages were automatically generated from docstrings in code.

They might be outdated, or incomplete.

-
-

Audio

-

Video and audio downloading related classes, mainly used for Discord voice bots.

-
-
-class royalnet.audio.YtdlInfo(info: Dict[str, Any])
-

A wrapper around youtube_dl extracted info.

-
-
-__init__(info: Dict[str, Any])
-

Create a YtdlInfo from the dict returned by the youtube_dl.YoutubeDL.extract_info() function.

-
-

Warning

-

Does not download the info, for that use royalnet.audio.YtdlInfo.retrieve_for_url().

-
-
- -
-
-_default_ytdl_args = {'ignoreerrors': True, 'no_warnings': True, 'noplaylist': True, 'outtmpl': '%(title)s-%(id)s.%(ext)s', 'quiet': True}
-
- -
-
-classmethod retrieve_for_url(url, **ytdl_args) → List[royalnet.audio.ytdlinfo.YtdlInfo]
-

Fetch the info for an url through YoutubeDL.

-
-
Returns
-

A list containing the infos for the requested videos.

-
-
-
- -
-
-to_discord_embed() → discord.embeds.Embed
-

Return this info as a discord.Embed.

-
- -
- -
-
-class royalnet.audio.YtdlFile(url: str, info: Optional[royalnet.audio.ytdlinfo.YtdlInfo] = None, filename: Optional[str] = None)
-

Information about a youtube-dl downloaded file.

-
-
-_default_ytdl_args = {'ignoreerrors': True, 'no_warnings': True, 'noplaylist': True, 'outtmpl': '%(epoch)s-%(title)s-%(id)s.%(ext)s', 'quiet': True}
-
- -
-
-delete()
-
- -
-
-download_file(**ytdl_args) → None
-
- -
-
-classmethod download_from_url(url: str, **ytdl_args) → List[royalnet.audio.ytdlfile.YtdlFile]
-
- -
-
-has_info() → bool
-
- -
-
-is_downloaded() → bool
-
- -
-
-open()
-
- -
-
-update_info(**ytdl_args) → None
-
- -
- -
-
-class royalnet.audio.FileAudioSource(file)
-

A discord.AudioSource that uses a io.BufferedIOBase as an input instead of memory.

-

The stream should be in the usual PCM encoding.

-
-

Warning

-

This AudioSource will consume (and close) the passed stream.

-
-
-
-is_opus()
-

This audio file isn’t Opus-encoded, but PCM-encoded.

-
-
Returns
-

False.

-
-
-
- -
-
-read()
-

Reads 20ms worth of audio.

-

If the audio is complete, then returning an empty bytes-like object to signal this is the way to do so.

-
- -
- -
-
-class royalnet.audio.YtdlDiscord(ytdl_file: royalnet.audio.ytdlfile.YtdlFile)
-
-
-convert_to_pcm() → None
-
- -
-
-classmethod create_from_url(url, **ytdl_args) → List[royalnet.audio.ytdldiscord.YtdlDiscord]
-
- -
-
-delete() → None
-
- -
-
-property info
-
- -
-
-pcm_available()
-
- -
-
-ready_up()
-
- -
-
-spawn_audiosource() → royalnet.audio.fileaudiosource.FileAudioSource
-
- -
- -
-
-class royalnet.audio.YtdlMp3(ytdl_file: royalnet.audio.ytdlfile.YtdlFile)
-
-
-convert_to_mp3() → None
-
- -
-
-classmethod create_and_ready_from_url(url, **ytdl_args) → List[royalnet.audio.ytdlmp3.YtdlMp3]
-
- -
-
-classmethod create_from_url(url, **ytdl_args) → List[royalnet.audio.ytdlmp3.YtdlMp3]
-
- -
-
-delete() → None
-
- -
-
-property info
-
- -
-
-pcm_available()
-
- -
-
-ready_up()
-
- -
- -
-
-

Bots

-

Various bot interfaces, and a generic class to create new ones.

-
-
-class royalnet.bots.TelegramBot(*, network_config: Optional[royalnet.network.networkconfig.NetworkConfig] = None, database_config: Optional[royalnet.database.databaseconfig.DatabaseConfig] = None, commands: List[Type[royalnet.commands.command.Command]] = None, sentry_dsn: Optional[str] = None, loop: asyncio.events.AbstractEventLoop = None, secrets_name: str = '__default__')
-

A bot that connects to Telegram.

-
-
-_data_factory() → Type[royalnet.commands.commanddata.CommandData]
-
- -
-
-async _handle_callback_query(update: telegram.update.Update)
-
- -
-
-async _handle_message(update: telegram.update.Update)
-
- -
-
-async _handle_update(update: telegram.update.Update)
-
- -
-
-_init_client()
-

Create the telegram.Bot, and set the starting offset.

-
- -
-
-_initialize()
-
- -
-
-_interface_factory() → Type[royalnet.commands.commandinterface.CommandInterface]
-
- -
-
-interface_name = 'telegram'
-
- -
-
-async run()
-

A blocking coroutine that should make the bot start listening to commands and requests.

-
- -
-
-static safe_api_call(f: Callable, *args, **kwargs) → Optional
-
- -
- -
-
-class royalnet.bots.DiscordBot(*, network_config: Optional[royalnet.network.networkconfig.NetworkConfig] = None, database_config: Optional[royalnet.database.databaseconfig.DatabaseConfig] = None, commands: List[Type[royalnet.commands.command.Command]] = None, sentry_dsn: Optional[str] = None, loop: asyncio.events.AbstractEventLoop = None, secrets_name: str = '__default__')
-

A bot that connects to Discord.

-
-
-_bot_factory() → Type[discord.client.Client]
-

Create a custom DiscordClient class inheriting from discord.Client.

-
- -
-
-_data_factory() → Type[royalnet.commands.commanddata.CommandData]
-
- -
-
-_init_client()
-

Create an instance of the DiscordClient class created in royalnet.bots.DiscordBot._bot_factory().

-
- -
-
-_init_voice()
-

Initialize the variables needed for the connection to voice chat.

-
- -
-
-_initialize()
-
- -
-
-_interface_factory() → Type[royalnet.commands.commandinterface.CommandInterface]
-
- -
-
-async add_to_music_data(dfiles: List[royalnet.audio.ytdldiscord.YtdlDiscord], guild: discord.guild.Guild)
-

Add a list of royalnet.audio.YtdlDiscord to the corresponding music_data object.

-
- -
-
-async advance_music_data(guild: discord.guild.Guild)
-

Try to play the next song, while it exists. Otherwise, just return.

-
- -
-
-interface_name = 'discord'
-
- -
-
-async run()
-

Login to Discord, then run the bot.

-
- -
-
-async update_activity_with_source_title()
-

Change the bot’s presence (using discord.Client.change_presence()) to match the current listening status.

-

If multiple guilds are using the bot, the bot will always have an empty presence.

-
- -
- -
-
-class royalnet.bots.GenericBot(*, network_config: Optional[royalnet.network.networkconfig.NetworkConfig] = None, database_config: Optional[royalnet.database.databaseconfig.DatabaseConfig] = None, commands: List[Type[royalnet.commands.command.Command]] = None, sentry_dsn: Optional[str] = None, loop: asyncio.events.AbstractEventLoop = None, secrets_name: str = '__default__')
-

A generic bot class, to be used as base for the other more specific classes, such as -royalnet.bots.TelegramBot and royalnet.bots.DiscordBot.

-
-
-_data_factory() → Type[royalnet.commands.commanddata.CommandData]
-
- -
-
-_init_commands() → None
-

Generate the commands dictionary required to handle incoming messages, and the network_handlers -dictionary required to handle incoming requests.

-
- -
-
-_init_database()
-

Create an royalnet.database.Alchemy with the tables required by the commands. Then, -find the chain that links the master_table to the identity_table.

-
- -
-
-_init_loop()
-
- -
-
-_init_network()
-

Create a royalnet.network.NetworkLink, and run it as a asyncio.Task.

-
- -
-
-_init_sentry()
-
- -
-
-_initialize()
-
- -
-
-_interface_factory() → Type[royalnet.commands.commandinterface.CommandInterface]
-
- -
-
-async _network_handler(request_dict: dict) → dict
-

Handle a single dict received from the royalnet.network.NetworkLink.

-
-
Returns
-

Another dict, formatted as a royalnet.network.Response.

-
-
-
- -
-
-get_secret(username: str)
-
- -
-
-interface_name = NotImplemented
-
- -
-
-run()
-

A blocking coroutine that should make the bot start listening to commands and requests.

-
- -
-
-run_blocking(verbose=False)
-
- -
-
-set_secret(username: str, password: str)
-
- -
- -
-
-

Commands

-
-
-class royalnet.commands.CommandInterface
-
-
-alchemy = NotImplemented
-
- -
-
-bot = NotImplemented
-
- -
-
-loop = NotImplemented
-
- -
-
-name = NotImplemented
-
- -
-
-async net_request(message, destination: str) → dict
-

Send data through a royalnet.network.NetworkLink and wait for a -royalnet.network.Reply.

-
-
Parameters
-
    -
  • message – The data to be sent. Must be pickle-able.

  • -
  • destination – The destination of the request, either in UUID format or node name.

  • -
-
-
-
- -
-
-prefix = NotImplemented
-
- -
-
-register_keyboard_key(key_name: str, callback: Callable)
-
- -
-
-register_net_handler(message_type: str, network_handler: Callable)
-

Register a new handler for messages received through Royalnet.

-
- -
-
-unregister_keyboard_key(key_name: str)
-
- -
-
-unregister_net_handler(message_type: str)
-

Remove a Royalnet handler.

-
- -
- -
-
-class royalnet.commands.Command(interface: royalnet.commands.commandinterface.CommandInterface)
-
-
-aliases = NotImplemented
-

A list of possible aliases for a command. -To have /e as alias for /example, one should set aliases to ["e"].

-
- -
-
-description = NotImplemented
-

A small description of the command, to be displayed when the command is being autocompleted.

-
- -
-
-name = NotImplemented
-

The main name of the command. -To have /example on Telegram, the name should be example.

-
- -
-
-require_alchemy_tables = {}
-

A set of royalnet.database tables that must exist for this command to work.

-
- -
-
-async run(args: royalnet.commands.commandargs.CommandArgs, data: royalnet.commands.commanddata.CommandData) → None
-
- -
-
-syntax = ''
-

The syntax of the command, to be displayed when a royalnet.error.InvalidInputError is raised, -in the format (required_arg) [optional_arg].

-
- -
- -
-
-class royalnet.commands.CommandData
-
-
-async delete_invoking(error_if_unavailable=False) → None
-

Delete the invoking message, if supported by the interface.

-

The invoking message is the message send by the user that contains the command.

-
-
Parameters
-

error_if_unavailable – if True, raise an exception if the message cannot been deleted.

-
-
-
- -
-
-async get_author(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 an exception if this is True and the call has no author.

-
-
-
- -
-
-async keyboard(text: str, keyboard: Dict[str, Callable]) → None
-

Send a keyboard having the keys of the dict as keys and calling the correspondent values on a press.

-

The function should be passed the CommandData instance as a argument.

-
- -
-
-async reply(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.

-
-
-
- -
- -
-
-class royalnet.commands.CommandArgs
-

An interface to access the arguments of a command with ease.

-
-
-__getitem__(item)
-

Arguments can be accessed with an array notation, such as args[0].

-
-
Raises
-

royalnet.error.InvalidInputError – if the requested argument does not exist.

-
-
-
- -
-
-joined(*, require_at_least=0) → str
-

Get the arguments as a space-joined string.

-
-
Parameters
-

require_at_least – the minimum amount of arguments required, will raise royalnet.error.InvalidInputError if the requirement is not fullfilled.

-
-
Raises
-

royalnet.error.InvalidInputError – if there are less than require_at_least arguments.

-
-
Returns
-

The space-joined string.

-
-
-
- -
-
-match(pattern: Union[str, Pattern], *flags) → Sequence[AnyStr]
-

Match the royalnet.utils.commandargs.joined() to a regex pattern.

-
-
Parameters
-

pattern – The regex pattern to be passed to re.match().

-
-
Raises
-

royalnet.error.InvalidInputError – if the pattern doesn’t match.

-
-
Returns
-

The matched groups, as returned by re.Match.groups().

-
-
-
- -
-
-optional(index: int, default=None)
-

Get the argument at a specific index, but don’t raise an error if nothing is found, instead returning the default value.

-
-
Parameters
-
    -
  • index – The index of the argument you want to retrieve.

  • -
  • default – The value returned if the argument is missing.

  • -
-
-
Returns
-

Either the argument or the default value, defaulting to None.

-
-
-
- -
- -
-
-exception royalnet.commands.CommandError(message='')
-

Something went wrong during the execution of this command.

-

Display an error message to the user, explaining what went wrong.

-
- -
-
-exception royalnet.commands.InvalidInputError(message='')
-

The command has received invalid input and cannot complete.

-

Display an error message to the user, along with the correct syntax for the command.

-
- -
-
-exception royalnet.commands.UnsupportedError(message='')
-

A requested feature is not available on this interface.

-

Display an error message to the user, telling them to use another interface.

-
- -
-
-exception royalnet.commands.KeyboardExpiredError(message='')
-

A special type of exception that can be raised in keyboard handlers to mark a specific keyboard as expired.

-
- -
-
-

Database

-

Relational database classes and methods.

-
-
-class royalnet.database.Alchemy(database_uri: str, tables: Set)
-

A wrapper around SQLAlchemy declarative that allows to use multiple databases at once while maintaining a single table-class for both of them.

-
-
-__init__(database_uri: str, tables: Set)
-

Create a new Alchemy object.

-
-
Parameters
-
-
-
-
- -
-
-_create_tables(tables: Set)
-
- -
-
-session_acm()
-

Use Alchemy as a asyncronous context manager (to be used in async with statements).

-
- -
-
-session_cm()
-

Use Alchemy as a context manager (to be used in with statements).

-
- -
- -
-
-royalnet.database.relationshiplinkchain(starting_class, ending_class) → Optional[tuple]
-

Find the path to follow to get from the starting table to the ending table.

-
- -
-
-class royalnet.database.DatabaseConfig(database_uri: str, master_table: Type, identity_table: Type, identity_column_name: str)
-

The configuration to be used for the royalnet.database.Alchemy component of royalnet.bots.GenericBot.

-
- -
-
-

Network

-

Royalnet (websocket) related classes.

-
- -
-
-async connect()
-

Connect to the royalnet.network.NetworkServer at self.master_uri.

-
- -
-
-async identify() → None
-
- -
-
-async receive() → royalnet.network.package.Package
-

Recieve a Package from the royalnet.network.NetworkServer.

-
-
Raises
-

royalnet.network.royalnetlink.ConnectionClosedError

-
-
-
- -
-
-async request(message, destination)
-
- -
-
-async run()
-

Blockingly run the Link.

-
- -
-
-async send(package: royalnet.network.package.Package)
-
- -
- -
-
-exception royalnet.network.NetworkError(error_data: dict, *args)
-
- -
-
-exception royalnet.network.NotConnectedError
-

The royalnet.network.NetworkLink is not connected to a royalnet.network.NetworkServer.

-
- -
-
-exception royalnet.network.NotIdentifiedError
-

The royalnet.network.NetworkLink has not identified yet to a royalnet.network.NetworkServer.

-
- -
-
-class royalnet.network.Package(data: dict, *, source: str, destination: str, source_conv_id: Optional[str] = None, destination_conv_id: Optional[str] = None)
-

A Royalnet package, the data type with which a royalnet.network.NetworkLink communicates with a royalnet.network.NetworkServer or another link. -Contains info about the source and the destination.

-
-
-__init__(data: dict, *, source: str, destination: str, source_conv_id: Optional[str] = None, destination_conv_id: Optional[str] = None)
-

Create a Package.

-
-
Parameters
-
    -
  • data – The data that should be sent. Usually a royalnet.network.Message.

  • -
  • source – The nid of the node that created this Package.

  • -
  • destination – The link_type of the destination node, or alternatively, the nid of the node. Can also be the NULL value to send the message to nobody.

  • -
  • source_conv_id – The conversation id of the node that created this package. Akin to the sequence number on IP packets.

  • -
  • destination_conv_id – The conversation id of the node that this Package is a reply to.

  • -
-
-
-
- -
-
-static from_dict(d) → royalnet.network.package.Package
-

Create a Package from a dictionary.

-
- -
-
-static from_json_bytes(b: bytes) → royalnet.network.package.Package
-

Create a Package from UTF8-encoded JSON bytes.

-
- -
-
-static from_json_string(string: str) → royalnet.network.package.Package
-

Create a Package from a JSON string.

-
- -
-
-reply(data) → royalnet.network.package.Package
-

Reply to this Package with another Package.

-
-
Parameters
-

data – The data that should be sent. Usually a royalnet.network.Message.

-
-
Returns
-

The reply Package.

-
-
-
- -
-
-to_dict() → dict
-

Convert the Package into a dictionary.

-
- -
-
-to_json_bytes() → bytes
-

Convert the Package into UTF8-encoded JSON bytes.

-
- -
-
-to_json_string() → str
-

Convert the Package into a JSON string.

-
- -
- -
-
-class royalnet.network.NetworkServer(address: str, port: int, required_secret: str, *, loop: asyncio.events.AbstractEventLoop = None)
-
-
-find_client(*, nid: str = None, link_type: str = None) → List[royalnet.network.networkserver.ConnectedClient]
-
- -
-
-find_destination(package: royalnet.network.package.Package) → List[royalnet.network.networkserver.ConnectedClient]
-

Find a list of destinations for the package.

-
-
Parameters
-

package – The package to find the destination of.

-
-
Returns
-

A list of ConnectedClients to send the package to.

-
-
-
- -
-
-async listener(websocket: websockets.server.WebSocketServerProtocol, path)
-
- -
-
-async route_package(package: royalnet.network.package.Package) → None
-

Executed every time a package is received and must be routed somewhere.

-
- -
-
-run_blocking(verbose=False)
-
- -
-
-serve()
-
- -
- -
-
-class royalnet.network.NetworkConfig(master_uri: str, master_secret: str)
-
- -
-
-exception royalnet.network.ConnectionClosedError
-

The royalnet.network.NetworkLink’s connection was closed unexpectedly. The link can’t be used anymore.

-
- -
-
-class royalnet.network.Request(handler: str, data: dict)
-

A request sent from a royalnet.network.NetworkLink to another.

-

It contains the name of the requested handler, in addition to the data.

-
-
-static from_dict(d: dict)
-
- -
-
-to_dict()
-
- -
- -
-
-class royalnet.network.Response
-

A base class to be inherited by all other response types.

-
-
-classmethod from_dict(d: dict) → royalnet.network.response.Response
-

Recreate the response from a received dict.

-
- -
-
-raise_on_error()
-

Raise an Exception if the Response is an error, do nothing otherwise.

-
- -
-
-to_dict() → dict
-

Prepare the Response to be sent by converting it to a JSONable dict.

-
- -
- -
-
-class royalnet.network.ResponseSuccess(data: Optional[dict] = None)
-

A response to a successful royalnet.network.Request.

-
-
-raise_on_error()
-

Raise an Exception if the Response is an error, do nothing otherwise.

-
- -
- -
-
-class royalnet.network.ResponseError(name: str, description: str, extra_info: Optional[dict] = None)
-

A response to a invalid royalnet.network.Request.

-
-
-raise_on_error()
-

Raise an Exception if the Response is an error, do nothing otherwise.

-
- -
- -
-
-

Utils

-

Miscellaneous useful functions and classes.

-
-
-async royalnet.utils.asyncify(function: Callable, *args, **kwargs)
-

Convert a function into a coroutine.

-
-

Warning

-

The coroutine cannot be cancelled, and any attempts to do so will result in unexpected outputs.

-
-
- -
-
-royalnet.utils.safeformat(string: str, **words: str) → str
-

str.format() something, but ignore missing keys instead of raising an error.

-
-
Parameters
-
    -
  • string – The base string to be formatted.

  • -
  • words – The words to format the string with.

  • -
-
-
Returns
-

The formatted string.

-
-
-
- -
-
-royalnet.utils.cdj(class_: Any) → dict
-

Return a dict of the class attributes without the __module__, __dict__, __weakref__ and __doc__ keys, to be used while generating dynamically SQLAlchemy declarative table classes.

-
-
Parameters
-

class_ – The object that you want to dict-ify.

-
-
Returns
-

The class dict.

-
-
-
-

Warning

-

You can’t dict-ify classes with __slots__!

-
-
- -
-
-async royalnet.utils.sleep_until(dt: datetime.datetime) → None
-

Block the call until the specified datetime.

-
-

Warning

-

Accurate only to seconds.

-
-
- -
-
-royalnet.utils.plusformat(i: int) → str
-

Convert an int to a str, prepending a + if it’s greater than 0.

-
-
Parameters
-

i – the int to convert.

-
-
Returns
-

The resulting str.

-
-
-
- -
-
-class royalnet.utils.NetworkHandler
-

The NetworkHandler functions are called when a specific Message type is received.

-
-
-message_type = NotImplemented
-
- -
- -
-
-royalnet.utils.andformat(l: List[str], middle=', ', final=' and ') → str
-

Convert a list to a str by adding final between the last two elements and middle between the others.

-
-
Parameters
-
    -
  • l – the input list.

  • -
  • middle – the str to be added between the middle elements.

  • -
  • final – the str to be added between the last two elements.

  • -
-
-
Returns
-

The resulting str.

-
-
-
- -
-
-royalnet.utils.plusformat(i: int) → str
-

Convert an int to a str, prepending a + if it’s greater than 0.

-
-
Parameters
-

i – the int to convert.

-
-
Returns
-

The resulting str.

-
-
-
- -
-
-royalnet.utils.fileformat(string: str) → str
-

Ensure a string can be used as a filename by replacing all non-word characters with underscores.

-
-
Parameters
-

string – the input string.

-
-
Returns
-

A valid filename string.

-
-
-
- -
-
-royalnet.utils.ytdldateformat(string: Optional[str], separator: str = '-') → str
-

Convert the weird date string returned by youtube-dl into the YYYY-MM-DD format.

-
-
Parameters
-
    -
  • string – the input string, in the YYYYMMDD format.

  • -
  • separator – the string to add between the years, the months and the days. Defaults to -.

  • -
-
-
Returns
-

The resulting string, in the format YYYY-MM-DD format.

-
-
-
- -
-
-royalnet.utils.numberemojiformat(l: List[str]) → str
-
- -
-
-royalnet.utils.telegram_escape(string: str) → str
-

Escape a string to be sent through Telegram, and format it using RoyalCode.

-
-

Warning

-

Currently escapes everything, even items in code blocks.

-
-
- -
-
-royalnet.utils.discord_escape(string: str) → str
-

Escape a string to be sent through Discord, and format it using RoyalCode.

-
-

Warning

-

Currently escapes everything, even items in code blocks.

-
-
- -
-
-royalnet.utils.splitstring(s: str, max: int) → List[str]
-
- -
-
-royalnet.utils.parse_5etools_entry(entry) → str
-
- -
-
-royalnet.utils.ordinalformat(number: int)
-
- -
-
-

Web

-
-
-royalnet.web.create_app(config_obj: Type, blueprints: List[royalnet.web.royalprint.Royalprint])
-

Create a flask.Flask application object.

-

Gets the app.secret_key from the SECRET_KEY envvar.

-

Also requires a DB_PATH key in config_obj to initialize the database connection.

-
-

Warning

-

The code for this class was written at 1 AM, and I have no clue of how and why it works or even if it really does work. -Use with caution?

-
-
-
Parameters
-
    -
  • config_obj – The object to be passed to flask.Flask.config.from_object().

  • -
  • blueprints – A list of blueprints to be registered to the application.

  • -
-
-
Returns
-

The created flask.Flask.

-
-
-
- -
-
-class royalnet.web.Royalprint(name, import_name, static_folder=None, static_url_path=None, template_folder=None, url_prefix=None, subdomain=None, url_defaults=None, root_path=None, required_tables: Optional[set] = None)
-

An edited flask.Blueprint containing an additional required_tables parameter.

-
- -
-
-

Error

-
-
-exception royalnet.error.RoyalnetRequestError(error: ResponseError)
-

An error was raised while handling the Royalnet request.

-

This exception contains the royalnet.network.ResponseError that was returned by the other Link.

-
-
-property args
-
- -
- -
-
-exception royalnet.error.RoyalnetResponseError
-

The royalnet.network.Response that was received is invalid.

-
- -
diff --git a/docs/html/creatingacommand.html b/docs/html/creatingacommand.html index 3c2157dd..d36dfdb3 100644 --- a/docs/html/creatingacommand.html +++ b/docs/html/creatingacommand.html @@ -199,7 +199,7 @@ It’s the name your command will be called with: for example, the “spaghetti Try to keep the name as short as possible, while staying specific enough so no other command will have the same name.

Next, create a new Python file with the name you have thought of. The previously mentioned “spaghetti” command should have a file called spaghetti.py.

-

Then, in the first row of the file, import the Command class from royalnet, and create a new class inheriting from it:

+

Then, in the first row of the file, import the Command class from royalnet, and create a new class inheriting from it:

from royalnet.commands import Command
 
 class SpaghettiCommand(Command):
@@ -215,8 +215,8 @@ The previously mentioned “spaghetti” command should have a file called description = "Send a spaghetti emoji in the chat."
 
-

Now override the Command.run() method, adding the code you want the bot to run when the command is called.

-

To send a message in the chat the command was called in, you can use the CommandData.reply() method:

+

Now override the Command.run() method, adding the code you want the bot to run when the command is called.

+

To send a message in the chat the command was called in, you can use the CommandData.reply() method:

from royalnet.commands import Command
 
 class SpaghettiCommand(Command):
@@ -234,7 +234,7 @@ The previously mentioned “spaghetti” command should have a file called Command arguments
 

A command can have some arguments passed by the user: for example, on Telegram an user may type /spaghetti carbonara al-dente to pass the str “carbonara al-dente” to the command code.

-

These arguments can be accessed in multiple ways through the args parameter passed to the Command.run() +

These arguments can be accessed in multiple ways through the args parameter passed to the Command.run() method.

If you want your command to use arguments, override the syntax class attribute with a brief description of the syntax of your command, possibly using (round parentheses) for required arguments and [square brackets] for optional @@ -271,7 +271,7 @@ ones.

Optional access

-

If you don’t want arguments to be required, you can access them through the CommandArgs.optional() method: it +

If you don’t want arguments to be required, you can access them through the CommandArgs.optional() method: it will return None if the argument wasn’t passed, making it optional.

args.optional(0)
 # "carbonara"
@@ -291,12 +291,12 @@ will return 
 

Full string

-

If you want the full argument string, you can use the CommandArgs.joined() method.

+

If you want the full argument string, you can use the CommandArgs.joined() method.

args.joined()
 # "carbonara al-dente"
 
-

You can specify a minimum number of arguments too, so that an InvalidInputError will be +

You can specify a minimum number of arguments too, so that an InvalidInputError will be raised if not enough arguments are present:

args.joined(require_at_least=3)
 # InvalidInputError() is raised
@@ -306,8 +306,8 @@ raised if not enough arguments are present:

Regular expressions

For more complex commands, you may want to get arguments through regular expressions.

-

You can then use the CommandArgs.match() method, which tries to match a pattern to the command argument string, -which returns a tuple of the matched groups and raises an InvalidInputError if there is no match.

+

You can then use the CommandArgs.match() method, which tries to match a pattern to the command argument string, +which returns a tuple of the matched groups and raises an InvalidInputError if there is no match.

To match a pattern, re.match() is used, meaning that Python will try to match only at the beginning of the string.

args.match(r"(carb\w+)")
 # ("carbonara",)
@@ -326,18 +326,18 @@ which returns a tuple of the matched groups and raises an 
 

Raising errors

-

If you want to display an error message to the user, you can raise a CommandError using the error message as argument:

+

If you want to display an error message to the user, you can raise a CommandError using the error message as argument:

if not kitchen.is_open():
     raise CommandError("The kitchen is closed. Come back later!")
 
-

You can also manually raise InvalidInputError to redisplay the command syntax, along with your error message:

+

You can also manually raise InvalidInputError to redisplay the command syntax, along with your error message:

if args[0] not in allowed_pasta:
     raise InvalidInputError("The specified pasta type is invalid.")
 

If you need a Royalnet feature that’s not available on the current interface, you can raise an -UnsupportedError with a brief description of what’s missing:

+UnsupportedError with a brief description of what’s missing:

if interface.name != "telegram":
     raise UnsupportedError("This command can only be run on Telegram interfaces.")
 
@@ -346,7 +346,7 @@ which returns a tuple of the matched groups and raises an

Running code at the initialization of the bot

You can run code while the bot is starting by overriding the Command.__init__() function.

-

You should keep the super().__init__(interface) call at the start of it, so that the Command instance is +

You should keep the super().__init__(interface) call at the start of it, so that the Command instance is initialized properly, then add your code after it.

You can add fields to the command to keep shared data between multiple command calls (but not bot restarts): it may be useful for fetching external static data and keeping it until the bot is restarted, or to store references to all the @@ -377,7 +377,7 @@ be useful for fetching external static data and keeping it until the bot is rest

Coroutines and slow operations

You may have noticed that in the previous examples we used await data.reply("🍝") instead of just data.reply("🍝").

-

This is because CommandData.reply() isn’t a simple method: it is a coroutine, a special kind of function that +

This is because CommandData.reply() isn’t a simple method: it is a coroutine, a special kind of function that can be executed separately from the rest of the code, allowing the bot to do other things in the meantime.

By adding the await keyword before the data.reply("🍝"), we tell the bot that it can do other things, like receiving new messages, while the message is being sent.

@@ -389,7 +389,7 @@ are finished and may cause bugs in other parts of the code!

...
-

If the slow function you want does not cause any side effect, you can wrap it with the royalnet.utils.asyncify() +

If the slow function you want does not cause any side effect, you can wrap it with the royalnet.utils.asyncify() function:

async def run(self, args, data):
     # If the called function has no side effect, you can do this!
@@ -404,7 +404,7 @@ a coroutine that does the same exact thing.

Delete the invoking message

The invoking message of a command is the message that the user sent that the bot recognized as a command; for example, the message /spaghetti carbonara is the invoking message for the spaghetti command run.

-

You can have the bot delete the invoking message for a command by calling the CommandData.delete_invoking +

You can have the bot delete the invoking message for a command by calling the CommandData.delete_invoking method:

async def run(self, args, data):
     await data.delete_invoking()
@@ -427,13 +427,13 @@ to True:

Using the database

Bots can be connected to a PostgreSQL database through a special SQLAlchemy interface called -royalnet.database.Alchemy.

+royalnet.database.Alchemy.

If the connection is established, the self.interface.alchemy and self.interface.session fields will be available for use in commands.

-

self.interface.alchemy is an instance of royalnet.database.Alchemy, which contains the +

self.interface.alchemy is an instance of royalnet.database.Alchemy, which contains the sqlalchemy.engine.Engine, metadata and tables, while self.interface.session is a sqlalchemy.orm.session.Session, and can be interacted in the same way as one.

-

If you want to use royalnet.database.Alchemy in your command, you should override the +

If you want to use royalnet.database.Alchemy in your command, you should override the require_alchemy_tables field with the set of Alchemy tables you need.

from royalnet.commands import Command
 from royalnet.database.tables import Royal
@@ -453,7 +453,7 @@ available for use in commands.

Querying the database

You can sqlalchemy.orm.query.Query the database using the SQLAlchemy ORM.

-

The SQLAlchemy tables can be found inside royalnet.database.Alchemy with the same name they were created +

The SQLAlchemy tables can be found inside royalnet.database.Alchemy with the same name they were created from, if they were specified in require_alchemy_tables.

RoyalTable = self.interface.alchemy.Royal
 query = self.interface.session.query(RoyalTable)
@@ -487,7 +487,7 @@ from, if they were specified in You can fetch the query results with the sqlalchemy.orm.query.Query.all(),
 sqlalchemy.orm.query.Query.first(), sqlalchemy.orm.query.Query.one() and
 sqlalchemy.orm.query.Query.one_or_none() methods.

-

Remember to use royalnet.utils.asyncify() when fetching results, as it may take a while!

+

Remember to use royalnet.utils.asyncify() when fetching results, as it may take a while!

Use sqlalchemy.orm.query.Query.all() if you want a list of all results:

results: list = await asyncify(query.all)
 
diff --git a/docs/html/genindex.html b/docs/html/genindex.html index 8574095f..44576c20 100644 --- a/docs/html/genindex.html +++ b/docs/html/genindex.html @@ -150,585 +150,8 @@

Index

- _ - | A - | B - | C - | D - | F - | G - | H - | I - | J - | K - | L - | M - | N - | O - | P - | R - | S - | T - | U - | Y
-

_

- - - -
- -

A

- - - -
- -

B

- - -
- -

C

- - - -
- -

D

- - - -
- -

F

- - - -
- -

G

- - - -
- -

H

- - -
- -

I

- - - -
- -

J

- - -
- -

K

- - - -
- -

L

- - - -
- -

M

- - - -
- -

N

- - - -
- -

O

- - - -
- -

P

- - - -
- -

R

- - - -
- -

S

- - - -
- -

T

- - - -
- -

U

- - - -
- -

Y

- - - -
-
diff --git a/docs/html/index.html b/docs/html/index.html index b5c0ea49..1bb04ae0 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -182,17 +182,7 @@
  • Comunicating via Royalnet
  • -
  • API Reference -
  • +
  • API Reference
  • You’ll then be asked for a network password.

    -

    This password is used to connect to the rest of the royalnet.network, or, if you’re hosting a local Network, +

    This password is used to connect to the rest of the royalnet.network, or, if you’re hosting a local Network, it will be the necessary password to connect to it:

    Network password []: cosafaunapesuunafoglia
     
    diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js index f72c9203..7ae9ac73 100644 --- a/docs/html/searchindex.js +++ b/docs/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["apireference","creatingacommand","index","runningroyalnet"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["apireference.rst","creatingacommand.rst","index.rst","runningroyalnet.rst"],objects:{"royalnet.audio":{FileAudioSource:[0,1,1,""],YtdlDiscord:[0,1,1,""],YtdlFile:[0,1,1,""],YtdlInfo:[0,1,1,""],YtdlMp3:[0,1,1,""]},"royalnet.audio.FileAudioSource":{is_opus:[0,2,1,""],read:[0,2,1,""]},"royalnet.audio.YtdlDiscord":{"delete":[0,2,1,""],convert_to_pcm:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""],spawn_audiosource:[0,2,1,""]},"royalnet.audio.YtdlFile":{"delete":[0,2,1,""],_default_ytdl_args:[0,3,1,""],download_file:[0,2,1,""],download_from_url:[0,2,1,""],has_info:[0,2,1,""],is_downloaded:[0,2,1,""],open:[0,2,1,""],update_info:[0,2,1,""]},"royalnet.audio.YtdlInfo":{__init__:[0,2,1,""],_default_ytdl_args:[0,3,1,""],retrieve_for_url:[0,2,1,""],to_discord_embed:[0,2,1,""]},"royalnet.audio.YtdlMp3":{"delete":[0,2,1,""],convert_to_mp3:[0,2,1,""],create_and_ready_from_url:[0,2,1,""],create_from_url:[0,2,1,""],info:[0,2,1,""],pcm_available:[0,2,1,""],ready_up:[0,2,1,""]},"royalnet.bots":{DiscordBot:[0,1,1,""],GenericBot:[0,1,1,""],TelegramBot:[0,1,1,""]},"royalnet.bots.DiscordBot":{_bot_factory:[0,2,1,""],_data_factory:[0,2,1,""],_init_client:[0,2,1,""],_init_voice:[0,2,1,""],_initialize:[0,2,1,""],_interface_factory:[0,2,1,""],add_to_music_data:[0,2,1,""],advance_music_data:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""],update_activity_with_source_title:[0,2,1,""]},"royalnet.bots.GenericBot":{_data_factory:[0,2,1,""],_init_commands:[0,2,1,""],_init_database:[0,2,1,""],_init_loop:[0,2,1,""],_init_network:[0,2,1,""],_init_sentry:[0,2,1,""],_initialize:[0,2,1,""],_interface_factory:[0,2,1,""],_network_handler:[0,2,1,""],get_secret:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""],run_blocking:[0,2,1,""],set_secret:[0,2,1,""]},"royalnet.bots.TelegramBot":{_data_factory:[0,2,1,""],_handle_callback_query:[0,2,1,""],_handle_message:[0,2,1,""],_handle_update:[0,2,1,""],_init_client:[0,2,1,""],_initialize:[0,2,1,""],_interface_factory:[0,2,1,""],interface_name:[0,3,1,""],run:[0,2,1,""],safe_api_call:[0,2,1,""]},"royalnet.commands":{Command:[0,1,1,""],CommandArgs:[0,1,1,""],CommandData:[0,1,1,""],CommandError:[0,4,1,""],CommandInterface:[0,1,1,""],InvalidInputError:[0,4,1,""],KeyboardExpiredError:[0,4,1,""],UnsupportedError:[0,4,1,""]},"royalnet.commands.Command":{aliases:[0,3,1,""],description:[0,3,1,""],name:[0,3,1,""],require_alchemy_tables:[0,3,1,""],run:[0,2,1,""],syntax:[0,3,1,""]},"royalnet.commands.CommandArgs":{__getitem__:[0,2,1,""],joined:[0,2,1,""],match:[0,2,1,""],optional:[0,2,1,""]},"royalnet.commands.CommandData":{delete_invoking:[0,2,1,""],get_author:[0,2,1,""],keyboard:[0,2,1,""],reply:[0,2,1,""]},"royalnet.commands.CommandInterface":{alchemy:[0,3,1,""],bot:[0,3,1,""],loop:[0,3,1,""],name:[0,3,1,""],net_request:[0,2,1,""],prefix:[0,3,1,""],register_keyboard_key:[0,2,1,""],register_net_handler:[0,2,1,""],unregister_keyboard_key:[0,2,1,""],unregister_net_handler:[0,2,1,""]},"royalnet.database":{Alchemy:[0,1,1,""],DatabaseConfig:[0,1,1,""],relationshiplinkchain:[0,5,1,""]},"royalnet.database.Alchemy":{__init__:[0,2,1,""],_create_tables:[0,2,1,""],session_acm:[0,2,1,""],session_cm:[0,2,1,""]},"royalnet.error":{RoyalnetRequestError:[0,4,1,""],RoyalnetResponseError:[0,4,1,""]},"royalnet.error.RoyalnetRequestError":{args:[0,2,1,""]},"royalnet.network":{ConnectionClosedError:[0,4,1,""],NetworkConfig:[0,1,1,""],NetworkError:[0,4,1,""],NetworkLink:[0,1,1,""],NetworkServer:[0,1,1,""],NotConnectedError:[0,4,1,""],NotIdentifiedError:[0,4,1,""],Package:[0,1,1,""],Request:[0,1,1,""],Response:[0,1,1,""],ResponseError:[0,1,1,""],ResponseSuccess:[0,1,1,""]},"royalnet.network.NetworkLink":{connect:[0,2,1,""],identify:[0,2,1,""],receive:[0,2,1,""],request:[0,2,1,""],run:[0,2,1,""],send:[0,2,1,""]},"royalnet.network.NetworkServer":{find_client:[0,2,1,""],find_destination:[0,2,1,""],listener:[0,2,1,""],route_package:[0,2,1,""],run_blocking:[0,2,1,""],serve:[0,2,1,""]},"royalnet.network.Package":{__init__:[0,2,1,""],from_dict:[0,2,1,""],from_json_bytes:[0,2,1,""],from_json_string:[0,2,1,""],reply:[0,2,1,""],to_dict:[0,2,1,""],to_json_bytes:[0,2,1,""],to_json_string:[0,2,1,""]},"royalnet.network.Request":{from_dict:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.Response":{from_dict:[0,2,1,""],raise_on_error:[0,2,1,""],to_dict:[0,2,1,""]},"royalnet.network.ResponseError":{raise_on_error:[0,2,1,""]},"royalnet.network.ResponseSuccess":{raise_on_error:[0,2,1,""]},"royalnet.utils":{NetworkHandler:[0,1,1,""],andformat:[0,5,1,""],asyncify:[0,5,1,""],cdj:[0,5,1,""],discord_escape:[0,5,1,""],fileformat:[0,5,1,""],numberemojiformat:[0,5,1,""],ordinalformat:[0,5,1,""],parse_5etools_entry:[0,5,1,""],plusformat:[0,5,1,""],safeformat:[0,5,1,""],sleep_until:[0,5,1,""],splitstring:[0,5,1,""],telegram_escape:[0,5,1,""],ytdldateformat:[0,5,1,""]},"royalnet.utils.NetworkHandler":{message_type:[0,3,1,""]},"royalnet.web":{Royalprint:[0,1,1,""],create_app:[0,5,1,""]},royalnet:{audio:[0,0,0,"-"],bots:[0,0,0,"-"],commands:[0,0,0,"-"],database:[0,0,0,"-"],error:[0,0,0,"-"],network:[0,0,0,"-"],utils:[0,0,0,"-"],web:[0,0,0,"-"]}},objnames:{"0":["py","module","Python module"],"1":["py","class","Python class"],"2":["py","method","Python method"],"3":["py","attribute","Python attribute"],"4":["py","exception","Python exception"],"5":["py","function","Python function"]},objtypes:{"0":"py:module","1":"py:class","2":"py:method","3":"py:attribute","4":"py:exception","5":"py:function"},terms:{"20m":0,"byte":0,"class":[0,1],"default":[0,1],"final":0,"function":[0,1],"import":1,"int":0,"new":[0,2,3],"null":0,"return":[0,1],"short":1,"static":[0,1],"super":1,"true":[0,1],"try":[0,1],"while":[0,1],Adding:2,And:1,For:1,Not:1,That:0,The:[0,1,2],Then:[0,1,3],These:[0,1],Use:[0,1],Using:2,__default__:[0,3],__dict__:0,__doc__:0,__getitem__:0,__init__:[0,1],__module__:0,__slots__:0,__weakref__:0,_bot_factori:0,_create_t:0,_data_factori:0,_default_ytdl_arg:0,_handle_callback_queri:0,_handle_messag:0,_handle_upd:0,_init_cli:0,_init_command:0,_init_databas:0,_init_loop:0,_init_network:0,_init_sentri:0,_init_voic:0,_initi:0,_interface_factori:0,_network_handl:0,aaaaaa:3,aaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:3,abl:[0,3],about:[0,1],abstracteventloop:0,access:[0,2],accur:0,add:[0,1],add_to_music_data:0,added:[0,1],adding:[0,1],addit:0,addition:1,address:0,advance_music_data:0,after:[1,3],akin:0,alchemi:[0,2],alia:0,alias:0,all:[0,1,3],allow:[0,1],allowed_pasta:1,along:[0,1],alreadi:[1,3],also:[0,1],altern:0,alwai:[0,1],amount:0,andformat:0,ani:[0,1],anonym:3,anoth:0,anymor:0,anystr:0,api:[2,3],app:0,append:1,applic:[0,3],arg:[0,1],argument:[0,2],around:0,arrai:0,ascend:1,ask:3,associ:3,async:[0,1],asyncifi:[0,1],asyncio:[0,1],asyncron:0,attempt:0,attribut:[0,1],audio:2,audiosourc:0,author:[0,3],autocomplet:0,automat:0,avail:[0,1,3],avoid:1,await:1,back:1,banana:1,base:0,becaus:1,been:0,befor:1,begin:1,being:[0,1],between:[0,1],block:0,blockingli:0,blueprint:0,bool:0,bot:2,botfath:3,both:0,bracket:1,brief:1,bufferediobas:0,bug:1,call:[0,1],callabl:0,callback:0,can:[0,1,3],cancel:0,cannot:0,carb:1,carbonara:1,caus:1,caution:0,cdj:0,certain:1,chain:0,chang:[0,1],change_pres:0,channel:0,charact:0,chat:[0,1],check:0,class_:0,classmethod:0,client:0,close:[0,1],clue:0,code:[0,2],column:1,come:1,command:2,commandarg:[0,1],commanddata:[0,1],commanderror:[0,1],commandinterfac:0,commun:0,comparis:1,complet:0,complex:1,compon:0,comun:2,config:0,config_obj:0,configur:[0,3],connect:[0,1,3],connectedcli:0,connectionclosederror:0,consid:1,consum:0,contain:[0,1],context:0,convers:0,convert:0,convert_to_mp3:0,convert_to_pcm:0,core:0,coroutin:[0,2],correct:0,correspond:0,cosafaunapesuunafoglia:3,could:1,creat:[0,2,3],create_and_ready_from_url:0,create_app:0,create_from_url:0,current:[0,1],custom:0,daemon:3,dai:0,data:[0,1],databas:2,database_config:0,database_uri:0,databaseconfig:0,date:0,datetim:0,db_path:0,declar:0,def:1,delet:[0,2],delete_invok:[0,1],dent:1,desc:1,descend:1,describ:0,descript:[0,1],desir:3,desktop:3,destin:0,destination_conv_id:0,detail:0,develop:3,dfile:0,dict:0,dictionari:0,differ:1,direct:2,directli:1,discord:[0,3],discord_escap:0,discordbot:0,discordcli:0,displai:[0,1],doc:0,docstr:0,document:[1,2],doe:[0,1],doesn:0,don:[0,1],done:1,download:[0,3],download_1_terabyte_of_spaghetti:1,download_fil:0,download_from_url:0,dsn:3,dure:0,dynam:0,eas:0,edit:0,effect:1,either:0,element:[0,1],els:[1,3],emb:0,emoji:1,empti:0,encod:0,end:0,ending_class:0,engin:[0,1],enough:1,ensur:0,enter:3,entri:0,envvar:0,epoch:0,error:2,error_data:0,error_if_non:0,error_if_unavail:[0,1],escap:0,establish:1,even:0,event:0,everi:[0,1],everyth:0,exact:1,exampl:[0,1],except:[0,1],execut:[0,1],exist:[0,1],expect:1,expir:0,explain:0,express:2,ext:0,extern:1,extra_info:0,extract:0,extract_info:0,fals:0,featur:[0,1],fetch:[0,2],field:1,file:[0,1],fileaudiosourc:0,fileformat:0,filenam:0,filter:2,find:0,find_client:0,find_destin:0,finish:1,first:[1,3],flag:0,flask:0,follow:0,format:0,found:[0,1],from:[0,1,3],from_dict:0,from_json_byt:0,from_json_str:0,from_object:0,full:2,fullfil:0,gener:0,genericbot:0,get:[0,1,3],get_author:0,get_secret:0,github:2,greater:[0,1],group:[0,1,3],guild:0,handl:0,handler:0,has:[0,1],has_info:0,have:[0,1,3],headless:3,help:3,here:1,host:3,how:0,html:0,http:0,identifi:0,identity_column_nam:0,identity_t:0,ifi:0,ignor:[0,1,3],ignoreerror:0,imag:1,imgur:3,import_nam:0,incom:0,incomplet:0,index:[0,2],info:0,inform:0,inherit:[0,1],initi:[0,2],input:0,insid:1,instal:3,instanc:[0,1,3],instead:[0,1],interact:1,interfac:[0,1],interface_nam:0,interpret:3,invalid:[0,1],invalidinputerror:[0,1],invok:[0,2],is_download:0,is_open:1,is_opu:0,isn:[0,1],itali:1,item:0,join:[0,1],json:0,jsonabl:0,just:[0,1,3],keep:1,kei:[0,3],key_nam:0,keyboard:0,keyboardexpirederror:0,keyr:2,keyword:1,kind:1,kitchen:1,kwarg:0,last:0,later:1,launch:3,less:0,like:[0,1],link:0,link_typ:0,linux:3,list:[0,1],listen:0,local:3,login:0,look:1,loop:0,made:0,mai:1,main:[0,3],mainli:0,maintain:0,make:[0,1],manag:0,manual:[1,3],mark:0,markup:0,master_secret:0,master_t:0,master_uri:0,match:[0,1],max:0,mean:[0,1],meantim:1,member:1,memori:0,mention:1,messag:[0,2],message_typ:0,metadata:1,method:[0,1],middl:0,might:0,minimum:[0,1],miscellan:0,miss:[0,1],month:0,more:[0,2],multipl:[0,1],music_data:0,must:0,name:[0,1,3],necessari:3,need:[0,1,3],net_request:0,network:[2,3],network_config:0,network_handl:0,networkconfig:0,networkerror:0,networkhandl:0,networklink:0,networkserv:0,next:[0,1,3],nid:0,no_warn:0,nobodi:0,node:0,non:0,none:[0,1],noplaylist:0,normal:1,notat:0,notconnectederror:0,noth:[0,1],notic:1,notidentifiederror:0,notimpl:0,now:[1,3],number:[0,1],numberemojiformat:0,object:[0,1],offset:0,onc:[0,1],one:[0,1,3],one_or_non:1,ones:[0,1],onli:[0,1],open:0,oper:2,option:[0,2,3],optional_arg:0,opu:0,order:2,order_bi:1,ordinalformat:0,org:0,orm:1,other:[0,1],otherwis:[0,1],outdat:0,output:0,outtmpl:0,overrid:1,packag:[0,3],packet:0,page:0,paramet:[0,1],parenthes:1,parse_5etools_entri:0,part:1,pass:[0,1,3],password:[0,3],pasta:1,path:0,pattern:[0,1],pcm:0,pcm_avail:0,pickl:0,ping:1,pingcommand:1,pip:3,plai:[0,1],plusformat:0,pong:1,port:0,portal:3,possibl:[0,1],postgresql:1,prefix:0,prepar:0,prepend:0,presenc:0,present:1,press:[0,3],previou:1,previous:1,probabl:[0,3],process:3,prompt:3,properli:1,properti:0,python3:3,python:[1,3],queri:2,quiet:0,rais:[0,2],raise_on_error:0,read:[0,1],readi:[1,3],ready_up:0,realli:0,receiv:[0,1],reciev:0,recogn:1,recreat:0,redisplai:1,refer:[1,2],regex:0,regist:[0,3],register_keyboard_kei:0,register_net_handl:0,regular:2,relat:0,relationshiplinkchain:0,rememb:[1,3],remov:0,replac:0,repli:[0,1],request:[0,1],request_dict:0,request_handl:0,requested_pasta:1,requestedpasta:1,requir:[0,1],require_alchemy_t:[0,1],require_at_least:[0,1],required_arg:0,required_secret:0,required_t:0,requrire_alchemy_t:1,respect:1,respons:0,responseerror:0,responsesuccess:0,rest:[1,3],restart:1,result:[0,2],retriev:0,retrieve_for_url:0,right_now:1,role:1,root_path:0,round:1,rout:0,route_packag:0,row:[0,1],royal:1,royalcod:0,royalgam:3,royalnet:0,royalnetlink:0,royalnetrequesterror:0,royalnetresponseerror:0,royalprint:0,royalt:1,run:[0,2],run_block:0,safe_api_cal:0,safeformat:0,same:1,script:1,second:0,secret:[0,3],secret_kei:0,secrets_nam:0,section:1,see:3,select:0,self:[0,1],send:[0,1],sent:[0,1],sentri:3,sentry_dsn:0,separ:[0,1],sequenc:0,serv:0,server:0,session:1,session_acm:0,session_cm:0,set:[0,1],set_secret:0,setup:3,share:1,should:[0,1,3],side:1,signal:0,simpl:1,singl:[0,1],sleep:1,sleep_until:0,slow:2,small:[0,1],some:1,someth:0,somewher:0,song:0,soon:1,sort:1,sourc:0,source_conv_id:0,space:[0,1],spaghetti:1,spaghetticommand:1,spawn_audiosourc:0,special:[0,1],specif:[0,1],specifi:[0,1,3],splitstr:0,sqlalchemi:[0,1],squar:1,stai:1,start:[0,1,3],starting_class:0,statement:0,static_fold:0,static_url_path:0,statu:0,stop:1,store:1,str:[0,1],stream:0,string:[0,2],subdomain:0,submodul:0,success:0,suppli:3,support:[0,1],syntax:[0,1],system:3,tabl:[0,1],take:1,task:[0,1],telegram:[0,1,3],telegram_escap:0,telegrambot:0,tell:[0,1],template_fold:0,text:0,than:[0,1],thei:[0,1,3],them:[0,1],thi:[0,1,3],thing:1,think:1,thought:1,through:[0,1],time:[0,1],titl:0,to_dict:0,to_discord_emb:0,to_json_byt:0,to_json_str:0,todo:[],token:3,too:1,tri:1,tupl:[0,1],two:0,type:[0,1,3],underscor:0,undescrib:0,unexpect:0,unexpectedli:0,union:[0,1],unlock:3,unregister_keyboard_kei:0,unregister_net_handl:0,unsupportederror:[0,1],until:[0,1],updat:0,update_activity_with_source_titl:0,update_info:0,uri:0,url:0,url_default:0,url_prefix:0,usag:3,use:[0,1],used:[0,1,3],useful:[0,1],user:[0,1,3],usernam:[0,1],uses:0,using:[0,1],usual:0,utf8:0,util:[1,2],uuid:0,valid:0,valu:0,variabl:0,variou:0,verbos:0,via:2,video:0,voic:0,wai:[0,1],wait:0,want:[0,1],wasn:1,web:2,websit:1,websocket:0,websocketserverprotocol:0,weird:0,welcom:2,went:0,were:[0,1],what:[0,1],when:[0,1],whenev:1,where:0,which:[0,1],why:0,window:3,without:[0,3],wizard:3,won:[1,3],word:[0,3],work:[0,1],worth:0,wrap:1,wrapper:0,written:0,wrong:0,year:0,yet:0,you:[0,1,3],your:[1,3],youtub:0,youtube_dl:0,youtubedl:0,ytdl_arg:0,ytdl_file:0,ytdldateformat:0,ytdldiscord:0,ytdlfile:0,ytdlinfo:0,ytdlmp3:0,yyyi:0,yyyymmdd:0},titles:["API Reference","Royalnet Commands","royalnet","Running Royalnet"],titleterms:{"new":1,Adding:1,The:3,Using:1,access:1,alchemi:1,api:0,argument:1,audio:0,bot:[0,1,3],code:1,command:[0,1],comun:1,coroutin:1,creat:1,databas:[0,1],delet:1,direct:1,error:[0,1],express:1,fetch:1,filter:1,full:1,initi:1,invok:1,keyr:3,link:2,messag:1,more:1,network:0,oper:1,option:1,order:1,queri:1,rais:1,refer:0,regular:1,result:1,royalnet:[1,2,3],run:[1,3],slow:1,some:2,string:1,useful:2,util:0,via:1,web:0}}) \ No newline at end of file +Search.setIndex({docnames:["apireference","creatingacommand","index","runningroyalnet"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.intersphinx":1,sphinx:56},filenames:["apireference.rst","creatingacommand.rst","index.rst","runningroyalnet.rst"],objects:{},objnames:{},objtypes:{},terms:{"20m":[],"byte":[],"class":1,"default":1,"final":[],"function":1,"import":1,"int":[],"new":[2,3],"null":[],"return":1,"short":1,"static":1,"super":1,"true":1,"try":1,"while":1,Adding:2,And:1,For:1,Not:1,That:[],The:[1,2],Then:[1,3],These:[0,1],Use:1,Using:2,__default__:3,__dict__:[],__doc__:[],__getitem__:[],__init__:1,__module__:[],__slots__:[],__weakref__:[],_bot_factori:[],_create_t:[],_data_factori:[],_default_ytdl_arg:[],_handle_callback_queri:[],_handle_messag:[],_handle_upd:[],_init_cli:[],_init_command:[],_init_databas:[],_init_loop:[],_init_network:[],_init_sentri:[],_init_voic:[],_initi:[],_interface_factori:[],_network_handl:[],aaaaaa:3,aaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaaaaa:3,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:3,abl:3,about:1,abstracteventloop:[],access:2,accur:[],add:1,add_to_music_data:[],added:1,adding:1,addit:[],addition:1,address:[],advance_music_data:[],after:[1,3],akin:[],alchemi:2,alia:[],alias:[],all:[1,3],allow:1,allowed_pasta:1,along:1,alreadi:[1,3],also:1,altern:[],alwai:1,amount:[],andformat:[],ani:1,anonym:3,anoth:[],anymor:[],anystr:[],api:[2,3],app:[],append:1,applic:3,arg:1,argument:2,around:[],arrai:[],ascend:1,ask:3,associ:3,async:1,asyncifi:1,asyncio:1,asyncron:[],attempt:[],attribut:1,audio:[],audiosourc:[],author:3,autocomplet:[],automat:0,avail:[1,3],avoid:1,await:1,back:1,banana:1,base:[],becaus:1,been:[],befor:1,begin:1,being:1,between:1,block:[],blockingli:[],blueprint:[],bool:[],bot:2,botfath:3,both:[],bracket:1,brief:1,bufferediobas:[],bug:1,call:1,callabl:[],callback:[],can:[1,3],cancel:[],cannot:[],carb:1,carbonara:1,caus:1,caution:[],cdj:[],certain:1,chain:[],chang:1,change_pres:[],channel:[],charact:[],chat:1,check:[],class_:[],classmethod:[],client:[],close:1,clue:[],code:[0,2],column:1,come:1,command:2,commandarg:1,commanddata:1,commanderror:1,commandinterfac:[],commun:[],comparis:1,complet:[],complex:1,compon:[],comun:2,config:[],config_obj:[],configur:3,connect:[1,3],connectedcli:[],connectionclosederror:[],consid:1,consum:[],contain:1,context:[],convers:[],convert:[],convert_to_mp3:[],convert_to_pcm:[],core:[],coroutin:2,correct:[],correspond:[],cosafaunapesuunafoglia:3,could:1,creat:[2,3],create_and_ready_from_url:[],create_app:[],create_from_url:[],current:1,custom:[],daemon:3,dai:[],data:1,databas:2,database_config:[],database_uri:[],databaseconfig:[],date:[],datetim:[],db_path:[],declar:[],def:1,delet:2,delete_invok:1,dent:1,desc:1,descend:1,describ:[],descript:1,desir:3,desktop:3,destin:[],destination_conv_id:[],detail:[],develop:3,dfile:[],dict:[],dictionari:[],differ:1,direct:2,directli:1,discord:3,discord_escap:[],discordbot:[],discordcli:[],displai:1,doc:[],docstr:0,document:[1,2],doe:1,doesn:[],don:1,done:1,download:3,download_1_terabyte_of_spaghetti:1,download_fil:[],download_from_url:[],dsn:3,dure:[],dynam:[],eas:[],edit:[],effect:1,either:[],element:1,els:[1,3],emb:[],emoji:1,empti:[],encod:[],end:[],ending_class:[],engin:1,enough:1,ensur:[],enter:3,entri:[],envvar:[],epoch:[],error:2,error_data:[],error_if_non:[],error_if_unavail:1,escap:[],establish:1,even:[],event:[],everi:1,everyth:[],exact:1,exampl:1,except:1,execut:1,exist:1,expect:1,expir:[],explain:[],express:2,ext:[],extern:1,extra_info:[],extract:[],extract_info:[],fals:[],featur:1,fetch:2,field:1,file:1,fileaudiosourc:[],fileformat:[],filenam:[],filter:2,find:[],find_client:[],find_destin:[],finish:1,first:[1,3],flag:[],flask:[],follow:[],format:[],found:1,from:[0,1,3],from_dict:[],from_json_byt:[],from_json_str:[],from_object:[],full:2,fullfil:[],gener:0,genericbot:[],get:[1,3],get_author:[],get_secret:[],github:2,greater:1,group:[1,3],guild:[],handl:[],handler:[],has:1,has_info:[],have:[1,3],headless:3,help:3,here:1,host:3,how:[],html:[],http:[],identifi:[],identity_column_nam:[],identity_t:[],ifi:[],ignor:[1,3],ignoreerror:[],imag:1,imgur:3,import_nam:[],incom:[],incomplet:0,index:2,info:[],inform:[],inherit:1,initi:2,input:[],insid:1,instal:3,instanc:[1,3],instead:1,interact:1,interfac:1,interface_nam:[],interpret:3,invalid:1,invalidinputerror:1,invok:2,is_download:[],is_open:1,is_opu:[],isn:1,itali:1,item:[],join:1,json:[],jsonabl:[],just:[1,3],keep:1,kei:3,key_nam:[],keyboard:[],keyboardexpirederror:[],keyr:2,keyword:1,kind:1,kitchen:1,kwarg:[],last:[],later:1,launch:3,less:[],like:1,link:[],link_typ:[],linux:3,list:1,listen:[],local:3,login:[],look:1,loop:[],made:[],mai:1,main:3,mainli:[],maintain:[],make:1,manag:[],manual:[1,3],mark:[],markup:[],master_secret:[],master_t:[],master_uri:[],match:1,max:[],mean:1,meantim:1,member:1,memori:[],mention:1,messag:2,message_typ:[],metadata:1,method:1,middl:[],might:0,minimum:1,miscellan:[],miss:1,month:[],more:2,multipl:1,music_data:[],must:[],name:[1,3],necessari:3,need:[1,3],net_request:[],network:3,network_config:[],network_handl:[],networkconfig:[],networkerror:[],networkhandl:[],networklink:[],networkserv:[],next:[1,3],nid:[],no_warn:[],nobodi:[],node:[],non:[],none:1,noplaylist:[],normal:1,notat:[],notconnectederror:[],noth:1,notic:1,notidentifiederror:[],notimpl:[],now:[1,3],number:1,numberemojiformat:[],object:1,offset:[],onc:1,one:[1,3],one_or_non:1,ones:1,onli:1,open:[],oper:2,option:[2,3],optional_arg:[],opu:[],order:2,order_bi:1,ordinalformat:[],org:[],orm:1,other:1,otherwis:1,outdat:0,output:[],outtmpl:[],overrid:1,packag:3,packet:[],page:0,paramet:1,parenthes:1,parse_5etools_entri:[],part:1,pass:[1,3],password:3,pasta:1,path:[],pattern:1,pcm:[],pcm_avail:[],pickl:[],ping:1,pingcommand:1,pip:3,plai:1,plusformat:[],pong:1,port:[],portal:3,possibl:1,postgresql:1,prefix:[],prepar:[],prepend:[],presenc:[],present:1,press:3,previou:1,previous:1,probabl:3,process:3,prompt:3,properli:1,properti:[],python3:3,python:[1,3],queri:2,quiet:[],rais:2,raise_on_error:[],read:1,readi:[1,3],ready_up:[],realli:[],receiv:1,reciev:[],recogn:1,recreat:[],redisplai:1,refer:[1,2],regex:[],regist:3,register_keyboard_kei:[],register_net_handl:[],regular:2,relat:[],relationshiplinkchain:[],rememb:[1,3],remov:[],replac:[],repli:1,request:1,request_dict:[],request_handl:[],requested_pasta:1,requestedpasta:1,requir:1,require_alchemy_t:1,require_at_least:1,required_arg:[],required_secret:[],required_t:[],requrire_alchemy_t:1,respect:1,respons:[],responseerror:[],responsesuccess:[],rest:[1,3],restart:1,result:2,retriev:[],retrieve_for_url:[],right_now:1,role:1,root_path:[],round:1,rout:[],route_packag:[],row:1,royal:1,royalcod:[],royalgam:3,royalnet:[],royalnetlink:[],royalnetrequesterror:[],royalnetresponseerror:[],royalprint:[],royalt:1,run:2,run_block:[],safe_api_cal:[],safeformat:[],same:1,script:1,second:[],secret:3,secret_kei:[],secrets_nam:[],section:1,see:3,select:[],self:1,send:1,sent:1,sentri:3,sentry_dsn:[],separ:1,sequenc:[],serv:[],server:[],session:1,session_acm:[],session_cm:[],set:1,set_secret:[],setup:3,share:1,should:[1,3],side:1,signal:[],simpl:1,singl:1,sleep:1,sleep_until:[],slow:2,small:1,some:1,someth:[],somewher:[],song:[],soon:1,sort:1,sourc:[],source_conv_id:[],space:1,spaghetti:1,spaghetticommand:1,spawn_audiosourc:[],special:1,specif:1,specifi:[1,3],splitstr:[],sqlalchemi:1,squar:1,stai:1,start:[1,3],starting_class:[],statement:[],static_fold:[],static_url_path:[],statu:[],stop:1,store:1,str:1,stream:[],string:2,subdomain:[],submodul:[],success:[],suppli:3,support:1,syntax:1,system:3,tabl:1,take:1,task:1,telegram:[1,3],telegram_escap:[],telegrambot:[],tell:1,template_fold:[],text:[],than:1,thei:[0,1,3],them:1,thi:[1,3],thing:1,think:1,thought:1,through:1,time:1,titl:[],to_dict:[],to_discord_emb:[],to_json_byt:[],to_json_str:[],todo:[],token:3,too:1,tri:1,tupl:1,two:[],type:[1,3],underscor:[],undescrib:[],unexpect:[],unexpectedli:[],union:1,unlock:3,unregister_keyboard_kei:[],unregister_net_handl:[],unsupportederror:1,until:1,updat:[],update_activity_with_source_titl:[],update_info:[],uri:[],url:[],url_default:[],url_prefix:[],usag:3,use:1,used:[1,3],useful:1,user:[1,3],usernam:1,uses:[],using:1,usual:[],utf8:[],util:1,uuid:[],valid:[],valu:[],variabl:[],variou:[],verbos:[],via:2,video:[],voic:[],wai:1,wait:[],want:1,wasn:1,web:[],websit:1,websocket:[],websocketserverprotocol:[],weird:[],welcom:2,went:[],were:[0,1],what:1,when:1,whenev:1,where:[],which:1,why:[],window:3,without:3,wizard:3,won:[1,3],word:3,work:1,worth:[],wrap:1,wrapper:[],written:[],wrong:[],year:[],yet:[],you:[1,3],your:[1,3],youtub:[],youtube_dl:[],youtubedl:[],ytdl_arg:[],ytdl_file:[],ytdldateformat:[],ytdldiscord:[],ytdlfile:[],ytdlinfo:[],ytdlmp3:[],yyyi:[],yyyymmdd:[]},titles:["API Reference","Royalnet Commands","royalnet","Running Royalnet"],titleterms:{"new":1,Adding:1,The:3,Using:1,access:1,alchemi:1,api:0,argument:1,audio:[],bot:[1,3],code:1,command:1,comun:1,coroutin:1,creat:1,databas:1,delet:1,direct:1,error:1,express:1,fetch:1,filter:1,full:1,initi:1,invok:1,keyr:3,link:2,messag:1,more:1,network:[],oper:1,option:1,order:1,queri:1,rais:1,refer:0,regular:1,result:1,royalnet:[1,2,3],run:[1,3],slow:1,some:2,string:1,useful:2,util:[],via:1,web:[]}}) \ No newline at end of file diff --git a/royalnet/bots/discord.py b/royalnet/bots/discord.py index 8130e5bd..b5aa86bc 100644 --- a/royalnet/bots/discord.py +++ b/royalnet/bots/discord.py @@ -5,7 +5,7 @@ from .generic import GenericBot from ..utils import * from ..error import * from ..audio import * -from ..packs import * +from ..commands import * log = _logging.getLogger(__name__)