def _get_self_reference(self): self_reference = self._self_reference if (self_reference is None): self_reference = WeakReferer(self) self._self_reference = self_reference return self_reference
def keep_alive(self, value): if value: while True: handler = self._handler if handler is None: break handler = handler() if handler is None: break if (self._key is not handler): self._key = handler return key = self._key handler = self.client.http.handlers.set(key) if (handler is not key): self._key = handler self._handler = WeakReferer(handler) return else: handler = self._handler if handler is None: return handler = handler() if handler is None: return if self._key is handler: self._key = handler.copy() return
def __new__(cls, client): """ Creates and binds a lavalink manager client. Parameters ---------- client : ``Client`` Hata client instance to extend. """ if not isinstance(client, Client): raise TypeError( f'`client` parameter can be `{Client.__name__}`, got {client.__class__.__name__}; {client!r}.' ) event_plugin = SolarLinkEventManager() client.events.register_plugin(event_plugin) client_reference = WeakReferer(client) self = object.__new__(cls) self._client_reference = client_reference self.nodes = set() self.players = {} self._player_queue = None self._events = event_plugin return self
def __new__(cls, channel, when): """ Creates a new ``MessageHistoryCollector """ self = object.__new__(cls) self.channel_reference = WeakReferer(channel) self.delay = 0.0 self.handle = KOKORO.call_at(when, self) return self
def __new__(cls, client): """ Creates a new ready state instance from the given parameters. Parameters ---------- client : ``Client`` The respective client instance. """ self = object.__new__(cls) self.shard_count = client.shard_count self.shard_user_requesters = {} self.task = Task(self._runner(), KOKORO) self.shard_ready_waiter = None self.client_reference = WeakReferer(client) return self
def handler(self): """ Returns the client's represented active handler if applicable. Returns ------- handler : `None`, ``RateLimitHandler`` """ handler = self._handler if (handler is not None): handler = handler() if (handler is not None): return handler handler = self.client.http.handlers.get(self._key) if (handler is not None): self._handler = WeakReferer(handler) return handler
def start_auto_posting(self): """ Starts auto posting bot stats. """ if not self._auto_post_running: self._auto_post_running = True # We can only start it, if our client is running. client = self.client_reference() if (client is not None) and client.running: # Check edge case auto_post_handler = self._auto_post_handler if (auto_post_handler is None): self._auto_post_handler = KOKORO.call_later( AUTO_POST_INTERVAL, _trigger_auto_post, WeakReferer(self), )
async def _start_auto_post(client): """ Client launch event handler starting auto post. This method is a coroutine. Parameters ---------- client : ``Client`` """ top_gg_client = client.top_gg # update client is if required top_gg_client.client_id = client.id # Do not post initially, we might not have all the guilds loaded yet. if top_gg_client._auto_post_running: top_gg_client._auto_post_handler = KOKORO.call_later( AUTO_POST_INTERVAL, _trigger_auto_post, WeakReferer(top_gg_client), )
def __new__(cls, name, help_): """ Creates a new command line command. Parameters ---------- name : `str` The command's name. help : `str` The command's help message. """ name = normalize_command_name(name) self = object.__new__(cls) self._command_category = None self.name = name self.help = None self._self_reference = None self._self_reference = WeakReferer(self) self._command_category = CommandLineCommandCategory(self, '') return self
def __new__(cls, parent, name): """ Creates a new command line command category. Parameters ---------- parent : ``CommandLineCommand``, ``CommandLineCommandCategory`` The parent command or command category. name : `None`, `str` The command category's name. """ if (name is not None): name = normalize_command_name(name) self = object.__new__(cls) self.name = name self._command_function = None self._command_categories = None self._self_reference = None self._parent_reference = parent._self_reference self._self_reference = WeakReferer(self) return self
async def wait_till_limits_expire(self): """ Waits till the represented rate limits expire. This method is a coroutine. Raises ------ RuntimeError If the method is called meanwhile `keep_alive` is `True`. Notes ----- The waiting is implemented with weakreference callback, so the coroutine returns when the source callback is garbage collected. This also means waiting on the exact same limit multiple times causes misbehaviour. """ handler = self._handler while True: if (handler is not None): handler = handler() if (handler is not None): break handler = self.client.http.handlers.get(self._key) if handler is None: return break if handler is self._key: raise RuntimeError('Cannot use `.wait_till_limits_expire` meanwhile `keep_alive` is `True`.') future = Future(current_thread()) self._handler = WeakReferer(handler, self._wait_till_limits_expire_callback(future)) await future
def __new__(cls, name, *, checks=None, description=None, hidden=False, hidden_if_checks_fail=True): """ Creates a new category with the given parameters. Parameters ---------- name : `str` The category's name. checks : `None`, ``CheckBase``, ``CommandCheckWrapper`` or (`list`, `tuple`, `set`) of \ (``CheckBase``, ``CommandCheckWrapper``) = `None`, Optional (Keyword only) The checks of the category. description : `Any` = `None`, Optional (Keyword only) Description of the category. hidden : `bool` = `False`, Optional (Keyword only) Whether the category should be hidden from help commands. hidden_if_checks_fail : `bool` = `True`, Optional (Keyword only) Whether the category should be hidden from help commands if it's checks fail. Defaults to `True`. Raises ------ TypeError - If `name` is not `str`. - If `checks`'s type is incorrect. - If a `check`'s type is incorrect. - If `hidden` was not given as `bool`. - If `hidden_if_checks_fail` was not given as `bool`. """ name_type = type(name) if name_type is str: pass elif issubclass(name_type, str): name = str(name) else: raise TypeError( f'`name` can be `str`, got {name_type.__name__}; {name!r}.') if not isinstance(hidden, bool): raise TypeError( f'`hidden` can be `bool`, got {hidden.__class__.__name__}; {hidden!r}.' ) if not isinstance(hidden_if_checks_fail, bool): raise TypeError( f'`hidden_if_checks_fail` can be `bool`, got ' f'{hidden_if_checks_fail.__class__.__name__}; {hidden_if_checks_fail!r}.' ) name = raw_name_to_display(name) checks = validate_checks(checks) description = normalize_description(description) self = object.__new__(cls) self._checks = checks self._command_processor_reference = None self._error_handlers = None self._self_reference = None self.command_instances = set() self.display_name = name self.description = description self.name = name self.hidden = hidden self.hidden_if_checks_fail = hidden_if_checks_fail self._self_reference = WeakReferer(self) return self
def __new__(cls, client, group, limiter=None, keep_alive=False): """ Creates a new rate limit proxy. Parameters ---------- client : ``Client`` Who's rate limits will be looked up. group : ``RateLimitGroup`` The proxy's rate limit group to pull additional information. limiter : `None`, ``DiscordEntity`` = `None`, Optional What's rate limits will be looked up. The accepted types depend on the group's limiter: +-----------------------+-----------------------------------------------------------------------+ | Respective limiter | Accepted values | +=======================+=======================================================================+ | LIMITER_CHANNEL | ``ChannelBase``, ``Message`` | +-----------------------+-----------------------------------------------------------------------+ | LIMITER_GUILD | ``Guild``, ``ChannelGuildBase``, ``Message``, ``Role``, ``Webhook``, | | | ``WebhookRepr`` | +-----------------------+-----------------------------------------------------------------------+ | LIMITER_WEBHOOK | ``Webhook``, ``WebhookRepr`` | +-----------------------+-----------------------------------------------------------------------+ | LIMITER_INTERACTION | ``InteractionEvent`` | +-----------------------+-----------------------------------------------------------------------+ | LIMITER_GLOBAL | `Any` | +-----------------------+-----------------------------------------------------------------------+ | LIMITER_UNLIMITED | `Any` | +-----------------------+-----------------------------------------------------------------------+ Note that at the case of `LIMITER_GUILD` partial objects will yield `.guild` as `None` so `ValueError` will still be raised. keep_alive : `bool` = `False`, Optional Whether the rate limit proxy should keep alive the respective rate limit handler. Defaults to `False`. Raises ------ RuntimeError If the given `group`'s limiter is not any of the predefined ones. Note that limiters are compared by memory address and not by value. TypeError If `group` was not given as ``RateLimitGroup``. ValueError If the given `limiter` cannot be casted to `limiter_id` with the specified `group` . """ if (type(group) is not RateLimitGroup): raise TypeError( f'`group` can be `{RateLimitGroup.__name__}`, got {group.__class__.__name__}; {group!r}.' ) while True: group_limiter = group.limiter if group_limiter is LIMITER_GLOBAL: limiter_id = 0 break elif group_limiter is LIMITER_UNLIMITED: limiter_id = 0 break elif group_limiter is LIMITER_CHANNEL: if (limiter is not None): if isinstance(limiter, ChannelBase): limiter_id = limiter.id break if isinstance(limiter, Message): limiter_id = limiter.channel_id break elif group_limiter is LIMITER_GUILD: if (limiter is not None): if isinstance(limiter, Guild): limiter_id = limiter.id break if isinstance(limiter, (ChannelGuildBase, Message, Role, Webhook, WebhookRepr)): guild = limiter.guild if (guild is not None): limiter_id = limiter.id break elif group_limiter is LIMITER_WEBHOOK: if (limiter is not None): if isinstance(limiter, (Webhook, WebhookRepr)): limiter_id = limiter.id break elif group_limiter is LIMITER_INTERACTION: if (limiter is not None): if isinstance(limiter, InteractionEvent): limiter_id = limiter.id break else: raise RuntimeError( f'`{group!r}.limiter` is not any of the defined limit groups.' ) raise ValueError( f'Cannot cast rate limit `{group!r}` group\'s rate `limit_id` from {limiter!r}.' ) key = RateLimitHandler(group, limiter_id) if keep_alive: key = client.http.handlers.set(key) handler = WeakReferer(key) else: handler = None self = object.__new__(cls) self.client = client self.group = group self._handler = handler self._key = key return self
def __new__(cls, client, top_gg_token, auto_post_bot_stats=True, raise_on_top_gg_global_rate_limit=False): """ Creates a new top.gg client instance. Parameters ---------- client : ``Client`` The discord client. top_gg_token : `str` Top.gg api token. auto_post_bot_stats : `bool` = `True`, Optional Whether auto post should be started as the client launches up. raise_on_top_gg_global_rate_limit : `bool` = `False`, Optional Whether ``TopGGGloballyRateLimited`` should be raised when the client gets globally rate limited. Raises ------ TypeError - If `client` is not ``Client``. - If `top_gg_token` is not `str`. - If `auto_post_bot_stats` is not `bool`. - If `raise_on_top_gg_global_rate_limit` is not `bool` isinstance. """ if not isinstance(client, Client): raise TypeError( f'`client` can be `{Client.__name__}`, got {client.__class__.__name__}; {client!r}.' ) if not isinstance(top_gg_token, str): raise TypeError( f'`top_gg_token` can be `str`, got {top_gg_token.__class__.__name__}; {top_gg_token!r}.' ) if not isinstance(auto_post_bot_stats, bool): raise TypeError( f'`auto_post_bot_stats` can be `bool`, got ' f'{auto_post_bot_stats.__class__.__name__}; {auto_post_bot_stats!r}.' ) if not isinstance(raise_on_top_gg_global_rate_limit, bool): raise TypeError( f'`raise_on_top_gg_global_rate_limit` can be `bool`, got ' f'{raise_on_top_gg_global_rate_limit.__class__.__name__}; {raise_on_top_gg_global_rate_limit!r}.' ) client_reference = WeakReferer(client) headers = IgnoreCaseMultiValueDictionary() headers[USER_AGENT] = LIBRARY_USER_AGENT headers[AUTHORIZATION] = top_gg_token self = object.__new__(cls) self.client_reference = client_reference self._auto_post_handler = None self._auto_post_running = auto_post_bot_stats self._raise_on_top_gg_global_rate_limit = raise_on_top_gg_global_rate_limit self._headers = headers self.client_id = client.id self.http = client.http self.top_gg_token = top_gg_token self._global_rate_limit_expires_at = 0.0 self._rate_limit_handler_global = RateLimitGroup( RATE_LIMIT_GLOBAL_SIZE, RATE_LIMIT_GLOBAL_RESET_AFTER) self._rate_limit_handler_bots = RateLimitGroup( RATE_LIMIT_BOTS_SIZE, RATE_LIMIT_BOTS_RESET_AFTER) self._weekend_status_cache_time = 0.0 self._weekend_status_cache_value = False self._weekend_status_request_task = None return self
def __new__(cls, prefix, *, precheck=None, mention_prefix_enabled=True, category_name_rule=None, command_name_rule=None, default_category_name=None, prefix_ignore_case=True): """ Creates a new command processor instance. Parameters ---------- prefix : `str`, `tuple` of `str`, `callable` Prefix of the command processor. Can be given as a normal `callable` or as an `async-callable` as well, which should accept `1` parameter: +-------------------+---------------+ | Name | Type | +===================+===============+ | message | ``Message`` | +-------------------+---------------+ And return the following value: +-------------------+---------------------------+ | Name | Type | +===================+===========================+ | prefix | `str`, `tuple` of `str` | +-------------------+---------------------------+ precheck : `None`, `callable` = `None`, Optional (Keyword only) A function used to detect whether a message should be handled. mention_prefix_enabled : `bool` = `True`, Optional (Keyword only) Whether mentioning the client at the start of a message counts as prefix. Defaults to `True`. category_name_rule : `None`, `FunctionType` = `None`, Optional (Keyword only) Function to generate category display names. Defaults to `None`. command_name_rule : `None`, `FunctionType` = `None`, Optional (Keyword only) Function to generate command display names. Defaults to `None`. default_category_name : `None`, `str` = `None`, Optional (Keyword only) The command processor's default category's name. Defaults to `None`. prefix_ignore_case : `bool` = `True` Whether the prefix's case should be ignored. Raises ------ TypeError - If `precheck` accepts bad amount of parameters. - If `precheck` is async. - If `mention_prefix_enabled` was not given as a `bool`. - If `category_name_rule` is not `None` nor `function`. - If `category_name_rule` is `async-function`. - If `category_name_rule` accepts bad amount of parameters. - If `category_name_rule` raises exception when `str` is passed to it. - If `category_name_rule` not returns `str`, when passing `str` to it. - If `command_name_rule` is not `None` nor `function`. - If `command_name_rule` is `async-function`. - If `command_name_rule` accepts bad amount of parameters. - If `command_name_rule` raises exception when `str` is passed to it. - If `command_name_rule` not returns `str`, when `str` is passed to it. - If `default_category_name` was not given neither as `None` nor as `str`. - If `prefix_ignore_case` was not given as `bool`. - Prefix's type is incorrect. - Prefix is a callable but accepts bad amount of parameters. ValueError - If `default_category_name`'s length is out of range [1:128]. """ if (category_name_rule is not None): test_name_rule(category_name_rule, 'category_name_rule') if (command_name_rule is not None): test_name_rule(command_name_rule, 'command_name_rule') if default_category_name is None: default_category_name = DEFAULT_CATEGORY_NAME else: default_category_name = validate_category_or_command_name(default_category_name) default_category = Category(default_category_name) if precheck is None: precheck = default_precheck else: test_precheck(precheck) mention_prefix_enabled = preconvert_bool(mention_prefix_enabled, 'mention_prefix_enabled') prefix_ignore_case = preconvert_bool(prefix_ignore_case, 'prefix_ignore_case') prefix_parser, prefix_getter = get_prefix_parser(prefix, prefix_ignore_case) self = object.__new__(cls) self._self_reference = None self._precheck = precheck self._error_handlers = None self._mention_prefix_enabled = mention_prefix_enabled self._category_name_rule = category_name_rule # Assign it later, exception may occur self._self_reference = WeakReferer(self) self._prefix_ignore_case = prefix_ignore_case self._prefix_parser = prefix_parser self._prefix_raw = prefix self._prefix_getter = prefix_getter self._default_category = default_category self._command_name_rule = command_name_rule self._category_name_rule = category_name_rule self.command_name_to_command = {} self.category_name_to_category = {} self.commands = set() self.categories = set() self._unknown_command = None self._self_reference = WeakReferer(self) default_category.set_command_processor(self) return self