aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bot/cogs/sync/cog.py52
-rw-r--r--bot/cogs/sync/syncers.py26
2 files changed, 51 insertions, 27 deletions
diff --git a/bot/cogs/sync/cog.py b/bot/cogs/sync/cog.py
index 222c1668b..30b66c74e 100644
--- a/bot/cogs/sync/cog.py
+++ b/bot/cogs/sync/cog.py
@@ -30,42 +30,48 @@ class Sync:
self.bot = bot
async def on_ready(self):
+ """Syncs the roles/users of the guild with the database."""
guild = self.bot.get_guild(self.SYNC_SERVER_ID)
if guild is not None:
for syncer in self.ON_READY_SYNCERS:
syncer_name = syncer.__name__[5:] # drop off `sync_`
log.info("Starting `%s` syncer.", syncer_name)
- total_created, total_updated = await syncer(self.bot, guild)
- log.info(
- "`%s` syncer finished, created `%d`, updated `%d`.",
- syncer_name, total_created, total_updated
- )
+ total_created, total_updated, total_deleted = await syncer(self.bot, guild)
+ if total_deleted is None:
+ log.info(
+ "`%s` syncer finished, created `%d`, updated `%d`.",
+ syncer_name, total_created, total_updated
+ )
+ else:
+ log.info(
+ "`%s` syncer finished, created `%d`, updated `%d`, `%d` deleted.",
+ syncer_name, total_created, total_updated, total_deleted
+ )
async def on_guild_role_create(self, role: Role):
+ """Adds newly create role to the database table over the API."""
await self.bot.api_client.post(
'bot/roles',
json={
'colour': role.colour.value,
'id': role.id,
'name': role.name,
- 'permissions': role.permissions.value
+ 'permissions': role.permissions.value,
+ 'position': role.position,
}
)
async def on_guild_role_delete(self, role: Role):
- log.warning(
- (
- "Attempted to delete role `%s` (`%d`), but role deletion "
- "is currently not implementeed."
- ),
- role.name, role.id
- )
+ """Deletes role from the database when it's deleted from the guild."""
+ await self.bot.api_client.delete('bot/roles/' + str(role.id))
async def on_guild_role_update(self, before: Role, after: Role):
+ """Syncs role with the database if any of the stored attributes were updated."""
if (
before.name != after.name
or before.colour != after.colour
or before.permissions != after.permissions
+ or before.position != after.position
):
await self.bot.api_client.put(
'bot/roles/' + str(after.id),
@@ -73,11 +79,19 @@ class Sync:
'colour': after.colour.value,
'id': after.id,
'name': after.name,
- 'permissions': after.permissions.value
+ 'permissions': after.permissions.value,
+ 'position': after.position,
}
)
async def on_member_join(self, member: Member):
+ """
+ Adds a new user or updates existing user to the database when a member joins the guild.
+
+ If the joining member is a user that is already known to the database (i.e., a user that
+ previously left), it will update the user's information. If the user is not yet known by
+ the database, the user is added.
+ """
packed = {
'avatar_hash': member.avatar,
'discriminator': int(member.discriminator),
@@ -106,19 +120,21 @@ class Sync:
await self.bot.api_client.post('bot/users', json=packed)
async def on_member_leave(self, member: Member):
+ """Updates the user information when a member leaves the guild."""
await self.bot.api_client.put(
'bot/users/' + str(member.id),
json={
'avatar_hash': member.avatar,
'discriminator': int(member.discriminator),
'id': member.id,
- 'in_guild': True,
+ 'in_guild': False,
'name': member.name,
'roles': sorted(role.id for role in member.roles)
}
)
async def on_member_update(self, before: Member, after: Member):
+ """Updates the user information if any of relevant attributes have changed."""
if (
before.name != after.name
or before.avatar != after.avatar
@@ -157,11 +173,11 @@ class Sync:
"""Manually synchronize the guild's roles with the roles on the site."""
initial_response = await ctx.send("📊 Synchronizing roles.")
- total_created, total_updated = await syncers.sync_roles(self.bot, ctx.guild)
+ total_created, total_updated, total_deleted = await syncers.sync_roles(self.bot, ctx.guild)
await initial_response.edit(
content=(
f"👌 Role synchronization complete, created **{total_created}** "
- f"and updated **{total_created}** roles."
+ f", updated **{total_created}** roles, and deleted **{total_deleted}** roles."
)
)
@@ -171,7 +187,7 @@ class Sync:
"""Manually synchronize the guild's users with the users on the site."""
initial_response = await ctx.send("📊 Synchronizing users.")
- total_created, total_updated = await syncers.sync_users(self.bot, ctx.guild)
+ total_created, total_updated, total_deleted = await syncers.sync_users(self.bot, ctx.guild)
await initial_response.edit(
content=(
f"👌 User synchronization complete, created **{total_created}** "
diff --git a/bot/cogs/sync/syncers.py b/bot/cogs/sync/syncers.py
index 3037d2e31..8f3f71440 100644
--- a/bot/cogs/sync/syncers.py
+++ b/bot/cogs/sync/syncers.py
@@ -6,13 +6,13 @@ from discord.ext.commands import Bot
# These objects are declared as namedtuples because tuples are hashable,
# something that we make use of when diffing site roles against guild roles.
-Role = namedtuple('Role', ('id', 'name', 'colour', 'permissions'))
+Role = namedtuple('Role', ('id', 'name', 'colour', 'permissions', 'position'))
User = namedtuple('User', ('id', 'name', 'discriminator', 'avatar_hash', 'roles', 'in_guild'))
def get_roles_for_sync(
guild_roles: Set[Role], api_roles: Set[Role]
-) -> Tuple[Set[Role], Set[Role]]:
+) -> Tuple[Set[Role], Set[Role], Set[Role]]:
"""
Determine which roles should be created or updated on the site.
@@ -36,12 +36,14 @@ def get_roles_for_sync(
guild_role_ids = {role.id for role in guild_roles}
api_role_ids = {role.id for role in api_roles}
new_role_ids = guild_role_ids - api_role_ids
+ deleted_role_ids = api_role_ids - guild_role_ids
# New roles are those which are on the cached guild but not on the
# API guild, going by the role ID. We need to send them in for creation.
roles_to_create = {role for role in guild_roles if role.id in new_role_ids}
roles_to_update = guild_roles - api_roles - roles_to_create
- return roles_to_create, roles_to_update
+ roles_to_delete = {role for role in api_roles if role.id in deleted_role_ids}
+ return roles_to_create, roles_to_update, roles_to_delete
async def sync_roles(bot: Bot, guild: Guild):
@@ -71,11 +73,12 @@ async def sync_roles(bot: Bot, guild: Guild):
guild_roles = {
Role(
id=role.id, name=role.name,
- colour=role.colour.value, permissions=role.permissions.value
+ colour=role.colour.value, permissions=role.permissions.value,
+ position=role.position,
)
for role in guild.roles
}
- roles_to_create, roles_to_update = get_roles_for_sync(guild_roles, api_roles)
+ roles_to_create, roles_to_update, roles_to_delete = get_roles_for_sync(guild_roles, api_roles)
for role in roles_to_create:
await bot.api_client.post(
@@ -84,7 +87,8 @@ async def sync_roles(bot: Bot, guild: Guild):
'id': role.id,
'name': role.name,
'colour': role.colour,
- 'permissions': role.permissions
+ 'permissions': role.permissions,
+ 'position': role.position,
}
)
@@ -95,11 +99,15 @@ async def sync_roles(bot: Bot, guild: Guild):
'id': role.id,
'name': role.name,
'colour': role.colour,
- 'permissions': role.permissions
+ 'permissions': role.permissions,
+ 'position': role.position,
}
)
- return (len(roles_to_create), len(roles_to_update))
+ for role in roles_to_delete:
+ await bot.api_client.delete('bot/roles/' + str(role.id))
+
+ return len(roles_to_create), len(roles_to_update), len(roles_to_delete)
def get_users_for_sync(
@@ -224,4 +232,4 @@ async def sync_users(bot: Bot, guild: Guild):
}
)
- return (len(users_to_create), len(users_to_update))
+ return len(users_to_create), len(users_to_update), None