feat(ranks): Implement event logging.
This commit is contained in:
@@ -254,6 +254,7 @@ class LionGuild(Timezoned):
|
|||||||
*,
|
*,
|
||||||
embed: Optional[discord.Embed] = None,
|
embed: Optional[discord.Embed] = None,
|
||||||
fields: dict[str, tuple[str, bool]]={},
|
fields: dict[str, tuple[str, bool]]={},
|
||||||
|
errors: list[str]=[],
|
||||||
**kwargs: str | int):
|
**kwargs: str | int):
|
||||||
"""
|
"""
|
||||||
Synchronously log an event to the guild event log.
|
Synchronously log an event to the guild event log.
|
||||||
@@ -273,6 +274,9 @@ class LionGuild(Timezoned):
|
|||||||
May be used to completely customise log message.
|
May be used to completely customise log message.
|
||||||
fields: dict[str, tuple[str, bool]]
|
fields: dict[str, tuple[str, bool]]
|
||||||
Optional embed fields to add.
|
Optional embed fields to add.
|
||||||
|
errors: list[str]
|
||||||
|
Optional list of errors to add.
|
||||||
|
Errors will always be added last.
|
||||||
kwargs: str | int
|
kwargs: str | int
|
||||||
Optional embed fields to add to the embed.
|
Optional embed fields to add to the embed.
|
||||||
These differ from `fields` in that the kwargs keys will be automatically matched and localised
|
These differ from `fields` in that the kwargs keys will be automatically matched and localised
|
||||||
@@ -282,7 +286,12 @@ class LionGuild(Timezoned):
|
|||||||
t = self.bot.translator.t
|
t = self.bot.translator.t
|
||||||
|
|
||||||
# Build embed
|
# Build embed
|
||||||
base = embed if embed is not None else discord.Embed(colour=discord.Colour.dark_orange())
|
if embed is not None:
|
||||||
|
base = embed
|
||||||
|
else:
|
||||||
|
base = discord.Embed(
|
||||||
|
colour=(discord.Colour.brand_red() if errors else discord.Colour.dark_orange())
|
||||||
|
)
|
||||||
if description is not None:
|
if description is not None:
|
||||||
base.description = description
|
base.description = description
|
||||||
if title is not None:
|
if title is not None:
|
||||||
@@ -317,6 +326,16 @@ class LionGuild(Timezoned):
|
|||||||
inline=inline,
|
inline=inline,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
error_name = t(_p(
|
||||||
|
'eventlog|field:errors|name',
|
||||||
|
"Errors"
|
||||||
|
))
|
||||||
|
error_value = '\n'.join(f"- {line}" for line in errors)
|
||||||
|
base.add_field(
|
||||||
|
name=error_name, value=error_value, inline=False
|
||||||
|
)
|
||||||
|
|
||||||
# Send embed
|
# Send embed
|
||||||
task = asyncio.create_task(self._log_event(embed=base), name='event-log')
|
task = asyncio.create_task(self._log_event(embed=base), name='event-log')
|
||||||
self._tasks.add(task)
|
self._tasks.add(task)
|
||||||
|
|||||||
@@ -319,10 +319,15 @@ class RankCog(LionCog):
|
|||||||
if roleid in rank_roleids and roleid != current_roleid
|
if roleid in rank_roleids and roleid != current_roleid
|
||||||
]
|
]
|
||||||
|
|
||||||
|
t = self.bot.translator.t
|
||||||
|
log_errors: list[str] = []
|
||||||
|
log_added = None
|
||||||
|
log_removed = None
|
||||||
|
|
||||||
# Now update roles
|
# Now update roles
|
||||||
new_last_roleid = last_roleid
|
new_last_roleid = last_roleid
|
||||||
|
|
||||||
# TODO: Event log here, including errors
|
# TODO: Factor out role updates
|
||||||
to_rm = [role for role in to_rm if role.is_assignable()]
|
to_rm = [role for role in to_rm if role.is_assignable()]
|
||||||
if to_rm:
|
if to_rm:
|
||||||
try:
|
try:
|
||||||
@@ -336,32 +341,68 @@ class RankCog(LionCog):
|
|||||||
f"Removed old rank roles from <uid:{userid}> in <gid:{guildid}>: {roleids}"
|
f"Removed old rank roles from <uid:{userid}> in <gid:{guildid}>: {roleids}"
|
||||||
)
|
)
|
||||||
new_last_roleid = None
|
new_last_roleid = None
|
||||||
except discord.HTTPException:
|
except discord.HTTPException as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"Unexpected error removing old rank roles from <uid:{member.id}> in <gid:{guild.id}>: {to_rm}",
|
f"Unexpected error removing old rank roles from <uid:{member.id}> in <gid:{guild.id}>: {to_rm}",
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:rank_check|error:remove_failed',
|
||||||
|
"Failed to remove old rank roles: `{error}`"
|
||||||
|
)).format(error=str(e)))
|
||||||
|
log_removed = '\n'.join(role.mention for role in to_rm)
|
||||||
|
|
||||||
if to_add and to_add.is_assignable():
|
if to_add:
|
||||||
try:
|
if to_add.is_assignable():
|
||||||
await member.add_roles(
|
try:
|
||||||
to_add,
|
await member.add_roles(
|
||||||
reason="Rewarding Activity Rank",
|
to_add,
|
||||||
atomic=True
|
reason="Rewarding Activity Rank",
|
||||||
)
|
atomic=True
|
||||||
logger.info(
|
)
|
||||||
f"Rewarded rank role <rid:{to_add.id}> to <uid:{userid}> in <gid:{guildid}>."
|
logger.info(
|
||||||
)
|
f"Rewarded rank role <rid:{to_add.id}> to <uid:{userid}> in <gid:{guildid}>."
|
||||||
new_last_roleid = to_add.id
|
)
|
||||||
except discord.HTTPException:
|
last_roleid=to_add.id
|
||||||
logger.warning(
|
except discord.HTTPException as e:
|
||||||
f"Unexpected error giving <uid:{userid}> in <gid:{guildid}> their rank role <rid:{to_add.id}>",
|
logger.warning(
|
||||||
exc_info=True
|
f"Unexpected error giving <uid:{userid}> in <gid:{guildid}> "
|
||||||
)
|
f"their rank role <rid:{to_add.id}>",
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:rank_check|error:add_failed',
|
||||||
|
"Failed to add new rank role: `{error}`"
|
||||||
|
)).format(error=str(e)))
|
||||||
|
else:
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:rank_check|error:add_impossible',
|
||||||
|
"Could not assign new activity rank role. Lacking permissions or invalid role."
|
||||||
|
)))
|
||||||
|
log_added = to_add.mention
|
||||||
|
else:
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:rank_check|error:permissions',
|
||||||
|
"Could not update activity rank roles, I lack the 'Manage Roles' permission."
|
||||||
|
)))
|
||||||
|
|
||||||
if new_last_roleid != last_roleid:
|
if new_last_roleid != last_roleid:
|
||||||
await session_rank.rankrow.update(last_roleid=new_last_roleid)
|
await session_rank.rankrow.update(last_roleid=new_last_roleid)
|
||||||
|
|
||||||
|
if to_add or to_rm:
|
||||||
|
# Log rank role update
|
||||||
|
lguild = await self.bot.core.lions.fetch_guild(guildid)
|
||||||
|
lguild.log_event(
|
||||||
|
t(_p(
|
||||||
|
'eventlog|event:rank_check|name',
|
||||||
|
"Member Activity Rank Roles Updated"
|
||||||
|
)),
|
||||||
|
memberid=member.id,
|
||||||
|
roles_given=log_added,
|
||||||
|
roles_taken=log_removed,
|
||||||
|
errors=log_errors,
|
||||||
|
)
|
||||||
|
|
||||||
@log_wrap(action="Update Rank")
|
@log_wrap(action="Update Rank")
|
||||||
async def update_rank(self, session_rank):
|
async def update_rank(self, session_rank):
|
||||||
# Identify target rank
|
# Identify target rank
|
||||||
@@ -390,6 +431,11 @@ class RankCog(LionCog):
|
|||||||
if member is None:
|
if member is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
t = self.bot.translator.t
|
||||||
|
log_errors: list[str] = []
|
||||||
|
log_added = None
|
||||||
|
log_removed = None
|
||||||
|
|
||||||
last_roleid = session_rank.rankrow.last_roleid
|
last_roleid = session_rank.rankrow.last_roleid
|
||||||
|
|
||||||
# Update ranks
|
# Update ranks
|
||||||
@@ -409,7 +455,6 @@ class RankCog(LionCog):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# Now update roles
|
# Now update roles
|
||||||
# TODO: Event log here, including errors
|
|
||||||
to_rm = [role for role in to_rm if role.is_assignable()]
|
to_rm = [role for role in to_rm if role.is_assignable()]
|
||||||
if to_rm:
|
if to_rm:
|
||||||
try:
|
try:
|
||||||
@@ -423,28 +468,50 @@ class RankCog(LionCog):
|
|||||||
f"Removed old rank roles from <uid:{userid}> in <gid:{guildid}>: {roleids}"
|
f"Removed old rank roles from <uid:{userid}> in <gid:{guildid}>: {roleids}"
|
||||||
)
|
)
|
||||||
last_roleid = None
|
last_roleid = None
|
||||||
except discord.HTTPException:
|
except discord.HTTPException as e:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"Unexpected error removing old rank roles from <uid:{member.id}> in <gid:{guild.id}>: {to_rm}",
|
f"Unexpected error removing old rank roles from <uid:{member.id}> in <gid:{guild.id}>: {to_rm}",
|
||||||
exc_info=True
|
exc_info=True
|
||||||
)
|
)
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:new_rank|error:remove_failed',
|
||||||
|
"Failed to remove old rank roles: `{error}`"
|
||||||
|
)).format(error=str(e)))
|
||||||
|
log_removed = '\n'.join(role.mention for role in to_rm)
|
||||||
|
|
||||||
if to_add and to_add.is_assignable():
|
if to_add:
|
||||||
try:
|
if to_add.is_assignable():
|
||||||
await member.add_roles(
|
try:
|
||||||
to_add,
|
await member.add_roles(
|
||||||
reason="Rewarding Activity Rank",
|
to_add,
|
||||||
atomic=True
|
reason="Rewarding Activity Rank",
|
||||||
)
|
atomic=True
|
||||||
logger.info(
|
)
|
||||||
f"Rewarded rank role <rid:{to_add.id}> to <uid:{userid}> in <gid:{guildid}>."
|
logger.info(
|
||||||
)
|
f"Rewarded rank role <rid:{to_add.id}> to <uid:{userid}> in <gid:{guildid}>."
|
||||||
last_roleid=to_add.id
|
)
|
||||||
except discord.HTTPException:
|
last_roleid=to_add.id
|
||||||
logger.warning(
|
except discord.HTTPException as e:
|
||||||
f"Unexpected error giving <uid:{userid}> in <gid:{guildid}> their rank role <rid:{to_add.id}>",
|
logger.warning(
|
||||||
exc_info=True
|
f"Unexpected error giving <uid:{userid}> in <gid:{guildid}> "
|
||||||
)
|
f"their rank role <rid:{to_add.id}>",
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:new_rank|error:add_failed',
|
||||||
|
"Failed to add new rank role: `{error}`"
|
||||||
|
)).format(error=str(e)))
|
||||||
|
else:
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:new_rank|error:add_impossible',
|
||||||
|
"Could not assign new activity rank role. Lacking permissions or invalid role."
|
||||||
|
)))
|
||||||
|
log_added = to_add.mention
|
||||||
|
else:
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:new_rank|error:permissions',
|
||||||
|
"Could not update activity rank roles, I lack the 'Manage Roles' permission."
|
||||||
|
)))
|
||||||
|
|
||||||
# Update MemberRank row
|
# Update MemberRank row
|
||||||
column = {
|
column = {
|
||||||
@@ -473,7 +540,29 @@ class RankCog(LionCog):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Send notification
|
# Send notification
|
||||||
await self._notify_rank_update(guildid, userid, new_rank)
|
try:
|
||||||
|
await self._notify_rank_update(guildid, userid, new_rank)
|
||||||
|
except discord.HTTPException:
|
||||||
|
log_errors.append(t(_p(
|
||||||
|
'eventlog|event:new_rank|error:notify_failed',
|
||||||
|
"Could not notify member."
|
||||||
|
)))
|
||||||
|
|
||||||
|
# Log rank achieved
|
||||||
|
lguild.log_event(
|
||||||
|
t(_p(
|
||||||
|
'eventlog|event:new_rank|name',
|
||||||
|
"Member Achieved Activity rank"
|
||||||
|
)),
|
||||||
|
t(_p(
|
||||||
|
'eventlog|event:new_rank|desc',
|
||||||
|
"{member} earned the new activity rank {rank}"
|
||||||
|
)).format(member=member.mention, rank=f"<@&{new_rank.roleid}>"),
|
||||||
|
roles_given=log_added,
|
||||||
|
roles_taken=log_removed,
|
||||||
|
coins_earned=new_rank.reward,
|
||||||
|
errors=log_errors,
|
||||||
|
)
|
||||||
|
|
||||||
async def _notify_rank_update(self, guildid, userid, new_rank):
|
async def _notify_rank_update(self, guildid, userid, new_rank):
|
||||||
"""
|
"""
|
||||||
@@ -516,11 +605,7 @@ class RankCog(LionCog):
|
|||||||
text = member.mention
|
text = member.mention
|
||||||
|
|
||||||
# Post!
|
# Post!
|
||||||
try:
|
await destination.send(embed=embed, content=text)
|
||||||
await destination.send(embed=embed, content=text)
|
|
||||||
except discord.HTTPException:
|
|
||||||
# TODO: Logging, guild logging, invalidate channel if permissions are wrong
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_message_map(self,
|
def get_message_map(self,
|
||||||
rank_type: RankType,
|
rank_type: RankType,
|
||||||
@@ -777,6 +862,24 @@ class RankCog(LionCog):
|
|||||||
self.flush_guild_ranks(guild.id)
|
self.flush_guild_ranks(guild.id)
|
||||||
await ui.set_done()
|
await ui.set_done()
|
||||||
|
|
||||||
|
# Event log
|
||||||
|
lguild.log_event(
|
||||||
|
t(_p(
|
||||||
|
'eventlog|event:rank_refresh|name',
|
||||||
|
"Activity Ranks Refreshed"
|
||||||
|
)),
|
||||||
|
t(_p(
|
||||||
|
'eventlog|event:rank_refresh|desc',
|
||||||
|
"{actor} refresh member activity ranks.\n"
|
||||||
|
"**`{removed}`** invalid rank roles removed.\n"
|
||||||
|
"**`{added}`** new rank roles added."
|
||||||
|
)).format(
|
||||||
|
actor=interaction.user.mention,
|
||||||
|
removed=ui.removed,
|
||||||
|
added=ui.added,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# ---------- Commands ----------
|
# ---------- Commands ----------
|
||||||
@cmds.hybrid_command(name=_p('cmd:ranks', "ranks"))
|
@cmds.hybrid_command(name=_p('cmd:ranks', "ranks"))
|
||||||
async def ranks_cmd(self, ctx: LionContext):
|
async def ranks_cmd(self, ctx: LionContext):
|
||||||
|
|||||||
Reference in New Issue
Block a user