diff options
author | 2019-08-15 20:26:01 +0200 | |
---|---|---|
committer | 2019-08-15 20:26:01 +0200 | |
commit | 99b48e387e99e66669c0e554e122414aa8534f14 (patch) | |
tree | 7a68034106038efc573d8fdf96f3fe42bedcfd73 | |
parent | Merge pull request #395 from kosayoda/no_fun_allowed (diff) |
Adding support for storing role positions and deleting roles
-rw-r--r-- | bot/cogs/sync/cog.py | 52 | ||||
-rw-r--r-- | bot/cogs/sync/syncers.py | 26 |
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 |