aboutsummaryrefslogtreecommitdiffstats
path: root/bot/exts/backend
diff options
context:
space:
mode:
Diffstat (limited to 'bot/exts/backend')
-rw-r--r--bot/exts/backend/error_handler.py10
-rw-r--r--bot/exts/backend/sync/_cog.py9
-rw-r--r--bot/exts/backend/sync/_syncers.py66
3 files changed, 44 insertions, 41 deletions
diff --git a/bot/exts/backend/error_handler.py b/bot/exts/backend/error_handler.py
index c643d346e..5b5840858 100644
--- a/bot/exts/backend/error_handler.py
+++ b/bot/exts/backend/error_handler.py
@@ -8,7 +8,7 @@ from sentry_sdk import push_scope
from bot.api import ResponseCodeError
from bot.bot import Bot
-from bot.constants import Channels, Colours
+from bot.constants import Colours
from bot.converters import TagNameConverter
from bot.errors import LockedResourceError
from bot.utils.checks import InWhitelistCheckFailure
@@ -47,7 +47,6 @@ class ErrorHandler(Cog):
* If CommandNotFound is raised when invoking the tag (determined by the presence of the
`invoked_from_error_handler` attribute), this error is treated as being unexpected
and therefore sends an error message
- * Commands in the verification channel are ignored
2. UserInputError: see `handle_user_input_error`
3. CheckFailure: see `handle_check_failure`
4. CommandOnCooldown: send an error message in the invoking context
@@ -63,10 +62,9 @@ class ErrorHandler(Cog):
if isinstance(e, errors.CommandNotFound) and not hasattr(ctx, "invoked_from_error_handler"):
if await self.try_silence(ctx):
return
- if ctx.channel.id != Channels.verification:
- # Try to look for a tag with the command's name
- await self.try_get_tag(ctx)
- return # Exit early to avoid logging.
+ # Try to look for a tag with the command's name
+ await self.try_get_tag(ctx)
+ return # Exit early to avoid logging.
elif isinstance(e, errors.UserInputError):
await self.handle_user_input_error(ctx, e)
elif isinstance(e, errors.CheckFailure):
diff --git a/bot/exts/backend/sync/_cog.py b/bot/exts/backend/sync/_cog.py
index 6e85e2b7d..48d2b6f02 100644
--- a/bot/exts/backend/sync/_cog.py
+++ b/bot/exts/backend/sync/_cog.py
@@ -18,9 +18,6 @@ class Sync(Cog):
def __init__(self, bot: Bot) -> None:
self.bot = bot
- self.role_syncer = _syncers.RoleSyncer(self.bot)
- self.user_syncer = _syncers.UserSyncer(self.bot)
-
self.bot.loop.create_task(self.sync_guild())
async def sync_guild(self) -> None:
@@ -31,7 +28,7 @@ class Sync(Cog):
if guild is None:
return
- for syncer in (self.role_syncer, self.user_syncer):
+ for syncer in (_syncers.RoleSyncer, _syncers.UserSyncer):
await syncer.sync(guild)
async def patch_user(self, user_id: int, json: Dict[str, Any], ignore_404: bool = False) -> None:
@@ -171,10 +168,10 @@ class Sync(Cog):
@commands.has_permissions(administrator=True)
async def sync_roles_command(self, ctx: Context) -> None:
"""Manually synchronise the guild's roles with the roles on the site."""
- await self.role_syncer.sync(ctx.guild, ctx)
+ await _syncers.RoleSyncer.sync(ctx.guild, ctx)
@sync_group.command(name='users')
@commands.has_permissions(administrator=True)
async def sync_users_command(self, ctx: Context) -> None:
"""Manually synchronise the guild's users with the users on the site."""
- await self.user_syncer.sync(ctx.guild, ctx)
+ await _syncers.UserSyncer.sync(ctx.guild, ctx)
diff --git a/bot/exts/backend/sync/_syncers.py b/bot/exts/backend/sync/_syncers.py
index 38468c2b1..2eb9f9971 100644
--- a/bot/exts/backend/sync/_syncers.py
+++ b/bot/exts/backend/sync/_syncers.py
@@ -6,8 +6,8 @@ from collections import namedtuple
from discord import Guild
from discord.ext.commands import Context
+import bot
from bot.api import ResponseCodeError
-from bot.bot import Bot
log = logging.getLogger(__name__)
@@ -17,57 +17,60 @@ _Role = namedtuple('Role', ('id', 'name', 'colour', 'permissions', 'position'))
_Diff = namedtuple('Diff', ('created', 'updated', 'deleted'))
+# Implementation of static abstract methods are not enforced if the subclass is never instantiated.
+# However, methods are kept abstract to at least symbolise that they should be abstract.
class Syncer(abc.ABC):
"""Base class for synchronising the database with objects in the Discord cache."""
- def __init__(self, bot: Bot) -> None:
- self.bot = bot
-
+ @staticmethod
@property
@abc.abstractmethod
- def name(self) -> str:
+ def name() -> str:
"""The name of the syncer; used in output messages and logging."""
raise NotImplementedError # pragma: no cover
+ @staticmethod
@abc.abstractmethod
- async def _get_diff(self, guild: Guild) -> _Diff:
+ async def _get_diff(guild: Guild) -> _Diff:
"""Return the difference between the cache of `guild` and the database."""
raise NotImplementedError # pragma: no cover
+ @staticmethod
@abc.abstractmethod
- async def _sync(self, diff: _Diff) -> None:
+ async def _sync(diff: _Diff) -> None:
"""Perform the API calls for synchronisation."""
raise NotImplementedError # pragma: no cover
- async def sync(self, guild: Guild, ctx: t.Optional[Context] = None) -> None:
+ @classmethod
+ async def sync(cls, guild: Guild, ctx: t.Optional[Context] = None) -> None:
"""
Synchronise the database with the cache of `guild`.
If `ctx` is given, send a message with the results.
"""
- log.info(f"Starting {self.name} syncer.")
+ log.info(f"Starting {cls.name} syncer.")
if ctx:
- message = await ctx.send(f"📊 Synchronising {self.name}s.")
+ message = await ctx.send(f"📊 Synchronising {cls.name}s.")
else:
message = None
- diff = await self._get_diff(guild)
+ diff = await cls._get_diff(guild)
try:
- await self._sync(diff)
+ await cls._sync(diff)
except ResponseCodeError as e:
- log.exception(f"{self.name} syncer failed!")
+ log.exception(f"{cls.name} syncer failed!")
# Don't show response text because it's probably some really long HTML.
results = f"status {e.status}\n```{e.response_json or 'See log output for details'}```"
- content = f":x: Synchronisation of {self.name}s failed: {results}"
+ content = f":x: Synchronisation of {cls.name}s failed: {results}"
else:
diff_dict = diff._asdict()
results = (f"{name} `{len(val)}`" for name, val in diff_dict.items() if val is not None)
results = ", ".join(results)
- log.info(f"{self.name} syncer finished: {results}.")
- content = f":ok_hand: Synchronisation of {self.name}s complete: {results}"
+ log.info(f"{cls.name} syncer finished: {results}.")
+ content = f":ok_hand: Synchronisation of {cls.name}s complete: {results}"
if message:
await message.edit(content=content)
@@ -78,10 +81,11 @@ class RoleSyncer(Syncer):
name = "role"
- async def _get_diff(self, guild: Guild) -> _Diff:
+ @staticmethod
+ async def _get_diff(guild: Guild) -> _Diff:
"""Return the difference of roles between the cache of `guild` and the database."""
log.trace("Getting the diff for roles.")
- roles = await self.bot.api_client.get('bot/roles')
+ roles = await bot.instance.api_client.get('bot/roles')
# Pack DB roles and guild roles into one common, hashable format.
# They're hashable so that they're easily comparable with sets later.
@@ -110,19 +114,20 @@ class RoleSyncer(Syncer):
return _Diff(roles_to_create, roles_to_update, roles_to_delete)
- async def _sync(self, diff: _Diff) -> None:
+ @staticmethod
+ async def _sync(diff: _Diff) -> None:
"""Synchronise the database with the role cache of `guild`."""
log.trace("Syncing created roles...")
for role in diff.created:
- await self.bot.api_client.post('bot/roles', json=role._asdict())
+ await bot.instance.api_client.post('bot/roles', json=role._asdict())
log.trace("Syncing updated roles...")
for role in diff.updated:
- await self.bot.api_client.put(f'bot/roles/{role.id}', json=role._asdict())
+ await bot.instance.api_client.put(f'bot/roles/{role.id}', json=role._asdict())
log.trace("Syncing deleted roles...")
for role in diff.deleted:
- await self.bot.api_client.delete(f'bot/roles/{role.id}')
+ await bot.instance.api_client.delete(f'bot/roles/{role.id}')
class UserSyncer(Syncer):
@@ -130,7 +135,8 @@ class UserSyncer(Syncer):
name = "user"
- async def _get_diff(self, guild: Guild) -> _Diff:
+ @staticmethod
+ async def _get_diff(guild: Guild) -> _Diff:
"""Return the difference of users between the cache of `guild` and the database."""
log.trace("Getting the diff for users.")
@@ -138,7 +144,7 @@ class UserSyncer(Syncer):
users_to_update = []
seen_guild_users = set()
- async for db_user in self._get_users():
+ async for db_user in UserSyncer._get_users():
# Store user fields which are to be updated.
updated_fields = {}
@@ -185,24 +191,26 @@ class UserSyncer(Syncer):
return _Diff(users_to_create, users_to_update, None)
- async def _get_users(self) -> t.AsyncIterable:
+ @staticmethod
+ async def _get_users() -> t.AsyncIterable:
"""GET users from database."""
query_params = {
"page": 1
}
while query_params["page"]:
- res = await self.bot.api_client.get("bot/users", params=query_params)
+ res = await bot.instance.api_client.get("bot/users", params=query_params)
for user in res["results"]:
yield user
query_params["page"] = res["next_page_no"]
- async def _sync(self, diff: _Diff) -> None:
+ @staticmethod
+ async def _sync(diff: _Diff) -> None:
"""Synchronise the database with the user cache of `guild`."""
log.trace("Syncing created users...")
if diff.created:
- await self.bot.api_client.post("bot/users", json=diff.created)
+ await bot.instance.api_client.post("bot/users", json=diff.created)
log.trace("Syncing updated users...")
if diff.updated:
- await self.bot.api_client.patch("bot/users/bulk_patch", json=diff.updated)
+ await bot.instance.api_client.patch("bot/users/bulk_patch", json=diff.updated)