Aethersprite

A work in progress.

Main

Aethersprite Discord bot/framework

aethersprite.config = {'bot': {'data_folder': '.', 'extensions': ['aethersprite.extensions.base._all'], 'help_command': 'aehelp', 'owner': 'haliphax#4859', 'token': 'SOMEREALLYLONGSTRINGTHATDISCORDGIVESYOU'}, 'webapp': {'flask': {'SERVER_HOST': '0.0.0.0', 'SERVER_NAME': 'localhost:5000', 'SERVER_PORT': 5000}, 'proxies': 1}}

Configuration

aethersprite.log = <Logger aethersprite (WARNING)>[source]

Root logger instance

Web application

aethersprite.webapp.app = <Flask 'aethersprite.webapp'>

Flask application

Common

Common functions module

aethersprite.common.DATETIME_FORMAT = '%a %Y-%m-%d %H:%M:%S %Z'

Formatting string for datetime objects

aethersprite.common.DAY = 86400

One day in seconds

aethersprite.common.FIFTEEN_MINS = 900

15 minutes in seconds

class aethersprite.common.FakeContext(guild)

Fake a context for use in certain functions that expect one

guild

Alias for field number 0

aethersprite.common.HOUR = 3600

One hour in seconds

aethersprite.common.MINUTE = 60

One minute in seconds

aethersprite.common.POLICE_OFFICER = '👮'

Police officer emoji

aethersprite.common.THUMBS_DOWN = '👎'

Thumbs down emoji

aethersprite.common.get_channel_for_id(guild, id: int) → str[source]

Return channel name for given guild and channel ID.

Parameters
  • guild – The guild object to search

  • id – The channel ID to search for

Returns

The name of the channel

aethersprite.common.get_id_for_channel(guild, channel: str) → int[source]

Return channel ID for given guild and channel name.

Parameters
  • guild – The guild object to search

  • channel – The channel to search for

Returns

The ID of the channel

aethersprite.common.get_id_for_role(guild, role: str) → int[source]

Return role ID for given guild and role name.

Parameters
  • guild – The guild object to search

  • role – The role to search for

Returns

The ID of the role

aethersprite.common.get_mixed_channels(value: str) → Tuple[Tuple[str, str]][source]

Return a series of group pairs matched from the provided value. The first element in each pair will be the channel ID if the match was a mention; it will be empty otherwise. The second element in each pair will be the plain text of the string token; it will be empty otherwise.

Parameters

value – The value to match against

Returns

A series of group pairs (channel ID, channel text)

aethersprite.common.get_mixed_roles(value: str) → Tuple[Tuple[str, str]][source]

Return a series of group pairs matched from the provided value. The first element in each pair will be the role ID if the match was a mention; it will be empty otherwise. The second element in each pair will be the plain text of the string token; it will be empty otherwise.

Parameters

value – The value to match against

Returns

A series of group pairs (role ID, role text)

aethersprite.common.get_role_for_id(guild, id: int) → str[source]

Return role name for given guild and role ID.

Parameters
  • guild – The guild object to search

  • id – The role ID to search for

Returns

The name of the role

aethersprite.common.get_timespan_chunks(string: str)[source]

Search string for chunks of timespan parameters, like 5d 10h 15m, etc.

Parameters

string – The string to search

Returns

(days: int, hours: int, minutes: int)

Return type

tuple

aethersprite.common.seconds_to_str(ts)[source]

Convert a span of seconds into a human-readable format (e.g. “5 days 8 hours 1 minute 36 seconds”).

Parameters

ts (int) – The span to convert

Returns

The human-readable representation

Return type

str

Settings

Settings module; interfaced with via aethersprite.extensions.base.settings

This provides methods by which extension authors can register and use settings in their code, and end users can manipulate those settings via bot commands (in the aforementioned settings extension).

Examples for registering a setting and getting/changing/resetting its value:

Note

There are commands for doing each of these things already in the base extension mentioned above that provide authorization checks, but these are just simple examples.

from discord.ext.commands import command
from aethersprite.settings import register, settings

register('my.setting', 'default value', False, lambda x: True,
         'There are many settings like it, but this one is mine.')

@command()
async def check(ctx):
    await ctx.send(settings['my.setting'].get(ctx))

@command()
async def change(ctx):
    settings['my.setting'].set(ctx, 'new value')

@command()
async def reset(ctx):
    settings['my.setting'].clear(ctx)
class aethersprite.settings.Setting(name: str, default: str, validate: callable, channel: Optional[bool] = False, description: Optional[str] = None, filter: Optional[SettingFilter] = None)[source]

Setting class; represents an individual setting definition

channel = None

If this is a channel (and not a guild) setting

default = None

Default value

description = None

This setting’s description

filter = None

The filter used to manipulate setting input/output

get(ctx, raw: bool = False)[source]

Get the setting’s value.

Parameters
  • ctx – The Discord connection context

  • raw – Set to True to bypass filtering

Returns

The setting’s value

Return type

str

name = None

The setting’s name

set(ctx, value: str, raw: bool = False)[source]

Change the setting’s value.

Parameters
  • ctx – The Discord connection context

  • value – The value to assign (or None for the default)

  • raw – Set to True to bypass filtering

Returns

Success

Return type

bool

validate = None

Validator function

aethersprite.settings.register(name: str, default: str, validator: callable, channel: Optional[bool] = False, description: Optional[str] = None, filter: Optional[SettingFilter] = None)[source]

Register a setting.

Parameters
  • name – The name of the setting

  • default – The default value if none is provided

  • validator – The validation function for the setting’s value

  • channel – If this is a channel (and not a guild) setting

  • filter – The aethersprite.filters.SettingFilter to use for filtering value input and output

aethersprite.settings.settings = {}

Setting definitions

Filters

Setting filters module

class aethersprite.filters.ChannelFilter(setting: str, multiple: bool = False)[source]

Filter used for converting channel names to IDs and back

in_(ctx: discord.ext.commands.context.Context, value: str) → None[source]

Filter setting input.

Parameters
  • ctx – The current context

  • value – The incoming value

multiple: bool = False

True to allow multiple values

out(ctx: discord.ext.commands.context.Context, value: List[int]) → List[str][source]

Filter setting output.

Parameters
  • ctx – The current context

  • value – The raw setting value: a list of channel IDs

Returns

The filtered setting value: a list of channel names

class aethersprite.filters.RoleFilter(setting: str, multiple: bool = True)[source]

Filter used for converting role names to IDs and back

in_(ctx: discord.ext.commands.context.Context, value: str) → None[source]

Filter setting input.

Parameters
  • ctx – The current context

  • value – The incoming value

multiple: bool = True

True to allow multiple values

out(ctx: discord.ext.commands.context.Context, value: List[int]) → List[str][source]

Filter setting output.

Parameters
  • ctx – The current context

  • value – The raw setting value: a list of role IDs

Returns

The filtered setting value: a list of role names

class aethersprite.filters.SettingFilter(setting: str)[source]

A class with methods for filtering a setting’s input and output

in_(ctx: discord.ext.commands.context.Context, value: str) → None[source]

Must override; input filter method.

Parameters
  • ctx – The current context

  • value – The incoming value

out(ctx: discord.ext.commands.context.Context, value: Any) → Any[source]

Must override; output filter method.

Parameters
  • ctx – The current context

  • value – The raw setting value

Returns

The filtered setting value

setting: str = None

The name of the setting to filter

Authorization

Authorization module

async aethersprite.authz.channel_only(ctx)[source]

Check for bot commands that should only operate in a channel

aethersprite.authz.is_in_any_role(user: discord.member.Member, roles: Sequence[discord.role.Role]) → bool[source]

Whether or not a member is in any of the given roles.

Parameters
  • user – The user in question

  • roles – The roles to check for membership

async aethersprite.authz.react_if_not_help(ctx: discord.ext.commands.context.Context)[source]

If the command was not invoked as an alias of the help command, react with the police officer emoji.

Parameters

ctx – The current context

async aethersprite.authz.require_admin(ctx)[source]

Check for requiring admin/mod privileges to execute a command.

async aethersprite.authz.require_roles(ctx: discord.ext.commands.context.Context, roles: Sequence[discord.role.Role]) → bool[source]

Check for requiring particular roles to execute a command. Membership in at least one of the roles is requied to pass the filter.

Parameters
  • ctx – The current context

  • roles – The roles to authorize

async aethersprite.authz.require_roles_from_setting(ctx: discord.ext.commands.context.Context, setting: str, open_by_default=True) → bool[source]

Check for requiring particular roles (loaded from the given setting) to execute a command. For more than one setting (if setting is a list/tuple), the aggregate list will be used. Membership in at least one of the roles pulled from the settings is required to pass the filter.

If this check is used and the setting is empty or nonexistent, the default behavior is to allow anyone and everyone to use the command. If you would like for it to default to “closed” behavior, set the open_by_default argument to False.

Example, if your setting with role(s) is setting.name:

from functools import partial
from discord.ext.commands import check, command
from aethersprite.authz require_roles, import require_roles_from_setting
from my_super_secret_special_code import get_roles

authz = partial(require_roles, get_roles())
authz_setting = partial(require_roles_from_setting, setting='setting.name')

@command()
@check(authz)
async def my_command(ctx):
    await ctx.send('You are authorized. Congratulations!')

@command()
@check(authz_setting)
async def my_other_command(ctx):
    # to set via bot command: !set setting.name SomeRoleName, SomeOtherRole
    await ctx.send('You are a member of one of the authorized roles. '
                   'Congratulations!')
Parameters

setting (str or list or tuple) – The name of the setting to pull the roles from