Пример #1
0
    def __init__(self, prem: tuple, reg: tuple):
        self.types = {
            "user": BucketType.user,
            "channel": BucketType.channel,
            "guild": BucketType.guild,
        }

        self.premium_mapping = CooldownMapping.from_cooldown(*self.clean(prem))
        self.regular_mapping = CooldownMapping.from_cooldown(*self.clean(reg))
Пример #2
0
    def decorator(func):
        try:
            cooldown_obj = Cooldown(rate, per, type)  # type: ignore
        except Exception:
            cooldown_obj = Cooldown(rate, per)

        try:
            mapping = CooldownMapping(cooldown_obj)  # type: ignore
        except Exception:
            mapping = CooldownMapping(cooldown_obj, type)

        if isinstance(func, InvokableApplicationCommand):
            func._buckets = mapping
        else:
            func.__slash_cooldown__ = mapping

        return func
Пример #3
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.db = None  # pylint: disable=invalid-name
        self.session = ClientSession()

        self.xp_cooldown = CooldownMapping.from_cooldown(1, 60, BucketType.member)

        self.players = {}

        self.prefixes = []
        self.welcome_message = None
Пример #4
0
    def __init__(self, bot) -> None:
        self.bot = bot

        self.bot.check(is_not_excluded)
        self.bot.before_invoke(self.before_invoke)

        self.spam_counter = {}
        self.spam_cooldown = CooldownMapping.from_cooldown(
            rate=10, per=7.5, type=BucketType.user)

        self.exclusion_watch = None
Пример #5
0
 def __init__(self,
              func: Callable[..., Awaitable],
              *,
              name: str = None,
              **kwargs):
     self.func = func
     self.name = name or func.__name__
     self._error_handler: Optional[Callable[..., Any]] = None
     self.auto_sync: bool = True
     # Extract checks
     if hasattr(func, "__slash_checks__"):
         self.checks: List[Callable[..., Any]] = func.__slash_checks__
     else:
         self.checks: List[Callable[..., Any]] = []
     # Cooldown
     try:
         cooldown = func.__slash_cooldown__
     except AttributeError:
         cooldown = None
     if cooldown is None:
         try:
             # Assuming that it's discord.py 1.7.0+
             self._buckets = CooldownMapping(cooldown, BucketType.default)
         except Exception:
             # discord.py <= 1.6.x
             try:
                 self._buckets = CooldownMapping(cooldown)  # type: ignore
             except Exception:
                 # Hopefully we never reach this
                 self._buckets: CooldownMapping = None  # type: ignore
     else:
         self._buckets = cooldown
     # Add custom kwargs
     for kw, value in kwargs.items():
         if not hasattr(self, kw):
             setattr(self, kw, value)
Пример #6
0
def cooldown_with_role_bypass(rate: int,
                              per: float,
                              type: BucketType = BucketType.default,
                              *,
                              bypass_roles: Iterable[int]) -> Callable:
    """
    Applies a cooldown to a command, but allows members with certain roles to be ignored.

    NOTE: this replaces the `Command.before_invoke` callback, which *might* introduce problems in the future.
    """
    # Make it a set so lookup is hash based.
    bypass = set(bypass_roles)

    # This handles the actual cooldown logic.
    buckets = CooldownMapping(Cooldown(rate, per, type))

    # Will be called after the command has been parse but before it has been invoked, ensures that
    # the cooldown won't be updated if the user screws up their input to the command.
    async def predicate(cog: Cog, ctx: Context) -> None:
        nonlocal bypass, buckets

        if any(role.id in bypass for role in ctx.author.roles):
            return

        # Cooldown logic, taken from discord.py internals.
        current = ctx.message.created_at.replace(
            tzinfo=datetime.timezone.utc).timestamp()
        bucket = buckets.get_bucket(ctx.message)
        retry_after = bucket.update_rate_limit(current)
        if retry_after:
            raise CommandOnCooldown(bucket, retry_after)

    def wrapper(command: Command) -> Command:
        # NOTE: this could be changed if a subclass of Command were to be used. I didn't see the need for it
        # so I just made it raise an error when the decorator is applied before the actual command object exists.
        #
        # If the `before_invoke` detail is ever a problem then I can quickly just swap over.
        if not isinstance(command, Command):
            raise TypeError(
                'Decorator `cooldown_with_role_bypass` must be applied after the command decorator. '
                'This means it has to be above the command decorator in the code.'
            )

        command._before_invoke = predicate

        return command

    return wrapper
Пример #7
0
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        print('-' * 50)
        self.session = AioClientSession(loop=self.loop)

        for attr in ('_command_cd', '_error_cd', '_clock_cd', '_warn_cd'):
            setattr(
                self, attr,
                CooldownMapping.from_cooldown(1, GLOBAL_USER_COOLDOWN,
                                              BucketType.member))

        for env in ('JISHAKU_NO_UNDERSCORE', 'JISHAKU_NO_UNDERSCORE'):
            environ[env] = 'true'

        for ext in ('jishaku', EXTENSION_LOADER_PATH):
            self.load_extension(ext)
Пример #8
0
 def decorator(func):
     if isinstance(func, Command):
         nonlocal rate, per, type
         db_name = (f"Cooldowns")
         make_db_if_not_exists(path=f"{DBPATH}\\{db_name}.json")
         cooldowns = db_receive(db_name)
         if not rate:
             rate = 1
         if not per:
             if str(func) not in cooldowns:
                 cooldowns[str(func)] = default_cooldown
             db_update(db_name, cooldowns)
             per = cooldowns[str(func)]
         func._buckets = CooldownMapping(Cooldown(rate, per, type))
     else:
         func.__commands_cooldown__ = Cooldown(rate, per, type)
     return func
Пример #9
0
 def __init__(self, bot: Eris):
     self.bot = bot
     self.cooldown = CooldownMapping.from_cooldown(1, 60, BucketType.member)
Пример #10
0
 def __init__(self, bot):
     self.bot = bot
     self.mem_update = CooldownMapping.from_cooldown(
         1, 1, BucketType.member)
Пример #11
0
from dataclasses import dataclass
from functools import partial as funct_partial
from typing import List, Tuple, Union

from discord.ext.commands import BucketType, CooldownMapping
from discord.ext.menus import ListPageSource
from jikanpy import AioJikan

from utils.converters import to_human_datetime, try_unpack_class
from utils.formatters import BetterEmbed

global_cd = BucketType.default

ApiCooldown = namedtuple('ApiCooldown', ['long', 'short'])
API_COOLDOWNS = ApiCooldown(
    long=CooldownMapping.from_cooldown(30, 60, global_cd),
    short=CooldownMapping.from_cooldown(2, 1, global_cd),
)

NSFW_MANGA = {'doujinshi', 'ecchi', 'hentai'}
TIME_TEMPLATE = "%Y-%m-%dT%H:%M:%S%z"  # iso 8601

#* Base classes


@dataclass
class Response:
    request_hash: str
    request_cached: bool
    request_cache_expiry: int
    results: list
Пример #12
0
class InvokableApplicationCommand:
    def __init__(self,
                 func: Callable[..., Awaitable],
                 *,
                 name: str = None,
                 **kwargs):
        self.func = func
        self.name = name or func.__name__
        self._error_handler: Optional[Callable[..., Any]] = None
        self.auto_sync: bool = True
        # Extract checks
        if hasattr(func, "__slash_checks__"):
            self.checks: List[Callable[..., Any]] = func.__slash_checks__
        else:
            self.checks: List[Callable[..., Any]] = []
        # Cooldown
        try:
            cooldown = func.__slash_cooldown__
        except AttributeError:
            cooldown = None
        if cooldown is None:
            try:
                # Assuming that it's discord.py 1.7.0+
                self._buckets = CooldownMapping(cooldown, BucketType.default)
            except Exception:
                # discord.py <= 1.6.x
                try:
                    self._buckets = CooldownMapping(cooldown)  # type: ignore
                except Exception:
                    # Hopefully we never reach this
                    self._buckets: CooldownMapping = None  # type: ignore
        else:
            self._buckets = cooldown
        # Add custom kwargs
        for kw, value in kwargs.items():
            if not hasattr(self, kw):
                setattr(self, kw, value)

    async def __call__(self, *args, **kwargs):
        return await self.func(*args, **kwargs)

    @staticmethod
    def _isinstance(obj: Any, typ: type) -> bool:
        if not isinstance(typ, type) or isinstance(
                typ, EnumMeta):  # special annotation
            return True
        if issubclass(typ, discord.User):
            return isinstance(
                obj, (discord.User, discord.Member, discord.ClientUser))
        else:
            return isinstance(obj, typ)

    def _prepare_cooldowns(self, inter: Any):
        if self._buckets.valid:
            dt = inter.created_at
            current = dt.replace(tzinfo=datetime.timezone.utc).timestamp()
            bucket = self._buckets.get_bucket(inter, current)
            retry_after = bucket.update_rate_limit(current)
            if retry_after:
                raise CommandOnCooldown(bucket, retry_after)

    def _dispatch_error(self, cog: Any, inter: BaseInteraction,
                        error: Exception):
        asyncio.create_task(self._invoke_error_handler(cog, inter, error))

    async def _run_checks(self, inter: BaseInteraction):
        for _check in self.checks:
            if not await _check(inter):
                raise InteractionCheckFailure(
                    f"command <{self.name}> has failed")

    async def _maybe_cog_call(self, cog: Any, inter: BaseInteraction):
        if cog:
            return await self(cog, inter)
        else:
            return await self(inter)

    async def _invoke_error_handler(self, cog: Any, inter: BaseInteraction,
                                    error: Exception):
        if self._error_handler is None:
            return
        if cog:
            await self._error_handler(cog, inter, error)
        else:
            await self._error_handler(inter, error)

    def error(self, func: Callable[..., Awaitable]):
        """
        A decorator that makes the function below
        work as error handler for this command.
        """
        if not asyncio.iscoroutinefunction(func):
            raise TypeError(
                "The local error handler must be an async function")
        self._error_handler = func
        return func

    def is_on_cooldown(self, inter: Any):
        """
        Checks whether the slash command is currently on cooldown.

        Parameters
        -----------
        inter: :class:`SlashInteraction`
            The interaction to use when checking the commands cooldown status.

        Returns
        --------
        :class:`bool`
            A boolean indicating if the slash command is on cooldown.
        """
        if not self._buckets.valid:
            return False

        bucket = self._buckets.get_bucket(inter)
        dt = inter.created_at
        current = dt.replace(tzinfo=datetime.timezone.utc).timestamp()
        return bucket.get_tokens(current) == 0

    def reset_cooldown(self, inter: Any):
        """
        Resets the cooldown on this slash command.

        Parameters
        -----------
        inter: :class:`SlashInteraction`
            The interaction to reset the cooldown under.
        """
        if self._buckets.valid:
            bucket = self._buckets.get_bucket(inter)
            bucket.reset()

    def get_cooldown_retry_after(self, inter: Any):
        """
        Retrieves the amount of seconds before this slash command can be tried again.

        Parameters
        -----------
        inter: :class:`SlashInteraction`
            The interaction to retrieve the cooldown from.

        Returns
        --------
        :class:`float`
            The amount of time left on this slash command's cooldown in seconds.
            If this is ``0.0`` then the slash command isn't on cooldown.
        """
        if self._buckets.valid:
            bucket = self._buckets.get_bucket(inter)
            dt = inter.created_at
            current = dt.replace(tzinfo=datetime.timezone.utc).timestamp()
            return bucket.get_retry_after(current)

        return 0.0
Пример #13
0
 def __init__(self, bot):
     self.bot = bot
     self._cooldown = CooldownMapping.from_cooldown(
         rate=5, per=20, type=BucketType.user
     )
Пример #14
0
 def __init__(self, bot):
     self.bot = bot
     self.cb_client = ac.Cleverbot(TRAVITIA_TOKEN)
     self.cb_client.set_context(ac.DictContext(self.cb_client))
     self.cb_emotions = tuple(ac.Emotion)
     self._cd = CooldownMapping.from_cooldown(1.0, 5.0, BucketType.member)