Skip to content

Commit

Permalink
Fix issues with temp mutes and bans.
Browse files Browse the repository at this point in the history
Bump to version 1.3.8

Squashed commit of the following:

commit 95d1523
Merge: 8839047 e4b1f9b
Author: retke <laggron42@gmail.com>
Date:   Thu Jul 30 18:31:50 2020 +0200

    Merge branch 'v3' into warnsystem/1.3.8

commit 8839047
Author: retke <laggron42@gmail.com>
Date:   Thu Jul 30 18:28:09 2020 +0200

    Bump to version 1.3.8

commit 9a6c181
Author: retke <laggron42@gmail.com>
Date:   Thu Jul 30 18:27:45 2020 +0200

    Fix multiple issues related to temp kicks and bans

    - handle cases where time/duration is invalid and remove them
    - fix issue with reinvite
    - other inconsistent issues (yes I'm lazy)

commit 6a20113
Merge: 25fdff0 8b7422c
Author: El Laggron <laggron42@gmail.com>
Date:   Tue Jul 28 13:00:47 2020 +0200

    Merge pull request #106 from mikeshardmind/less-invite-iterations

    [WarnSystem] Reduce the iterations needed to get an invite channel

commit 8b7422c
Author: Michael H <michael@michaelhall.tech>
Date:   Tue Jul 28 04:43:52 2020 -0400

    [WarnSystem] Reduce the iterations needed to get an invite channel

      Saw something in your support channel, went to take a look in context

      - guild.text_channels is already sorted by position
      - prior key was (channel.position, len(channel.members))
      - channel.members is a list comp calculated on demand
      - channel.members portion of the key would never be used before

      With these, I dropped the sorted use, from that I made it lazy
      using a generator expression + next()

commit 25fdff0
Author: retke <laggron42@gmail.com>
Date:   Mon Jul 27 11:37:24 2020 +0200

    Fix permissions keyerror

commit b962f39
Author: retke <laggron42@gmail.com>
Date:   Sun Jul 26 17:59:04 2020 +0200

    Use UTC time for unmute/unwarn loop
  • Loading branch information
laggron42 committed Jul 30, 2020
1 parent e4b1f9b commit f91b304
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 31 deletions.
65 changes: 38 additions & 27 deletions warnsystem/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1009,7 +1009,9 @@ async def warn_member(member: Union[discord.Member, UnavailableMember], audit_re
if automod:
# This function can be pretty heavy, and the response can be seriously delayed
# because of this, so we make it a side process instead
self.bot.loop.create_task(self.automod_check_for_autowarn(member, author, level))
self.bot.loop.create_task(
self.automod_check_for_autowarn(guild, member, author, level)
)
i += 1
if progress_tracker:
await progress_tracker(i)
Expand Down Expand Up @@ -1085,19 +1087,15 @@ async def warn_member(member: Union[discord.Member, UnavailableMember], audit_re

async def _check_endwarn(self):
async def reinvite(guild, user, reason, duration):
channel = None
# find an ideal channel for the invite
# we get the one with the most members in the order of the guild
try:
channel = sorted(
[
x
for x in guild.text_channels
if x.permissions_for(guild.me).create_instant_invite
],
key=lambda x: (x.position, len(x.members)),
)[0]
except IndexError:
channel = next(
(
c # guild.text_channels is already sorted by position
for c in guild.text_channels
if c.permissions_for(guild.me).create_instant_invite
),
None,
)
if channel is None:
# can't find a valid channel
log.info(
f"[Guild {guild.id}] Can't find a text channel where I can create an invite "
Expand Down Expand Up @@ -1129,23 +1127,33 @@ async def reinvite(guild, user, reason, duration):
f"(ID: {member.id}) after its temporary ban."
)

now = datetime.today()
now = datetime.utcnow()
for guild in self.bot.guilds:
data = await self.cache.get_temp_action(guild)
if not data:
continue
to_remove = []
for member, action in data.items():
member = int(member)
taken_on = self._get_datetime(action["time"])
duration = self._get_timedelta(action["duration"])
for member_id, action in data.items():
member_id = int(member_id)
try:
taken_on = self._get_datetime(action["time"])
duration = self._get_timedelta(action["duration"])
except ValueError as e:
log.error(
f"[Guild {guild.id}] Time or duration cannot be fetched. This is "
"probably leftovers from the conversion of post 1.3 data. Removing the "
f"temp warning, not taking actions... Member: {member_id}, data: {action}",
exc_info=e,
)
to_remove.append(UnavailableMember(self.bot, guild._state, member_id))
continue
author = guild.get_member(action["author"])
member = guild.get_member(member)
member = guild.get_member(member_id)
case_reason = action["reason"]
level = action["level"]
action_str = _("mute") if level == 2 else _("ban")
if not member:
member = UnavailableMember(self.bot, guild._state, member)
member = UnavailableMember(self.bot, guild._state, member_id)
if level == 2:
to_remove.append(member)
continue
Expand All @@ -1169,7 +1177,12 @@ async def reinvite(guild, user, reason, duration):
if level == 5:
await guild.unban(member, reason=reason)
if await self.data.guild(guild).reinvite():
await reinvite(guild, member, case_reason, action["duration"])
await reinvite(
guild,
member,
case_reason,
self._format_timedelta(timedelta(seconds=action["duration"])),
)
except discord.errors.Forbidden:
log.warn(
f"[Guild {guild.id}] I lost required permissions for "
Expand Down Expand Up @@ -1410,7 +1423,7 @@ def _automod_clean_cache(
del self.automod[guild.id]

async def automod_check_for_autowarn(
self, member: discord.Member, author: discord.Member, level: int
self, guild: discord.Guild, member: discord.Member, author: discord.Member, level: int
):
"""
Iterate through member's modlog, looking for possible automatic warns.
Expand All @@ -1420,10 +1433,9 @@ async def automod_check_for_autowarn(
This can be a heavy call if there are a lot of possible autowarns and a long modlog.
"""
guild = member.guild
t = datetime.now()
try:
await self._automod_check_for_autowarn(member, author, level)
await self._automod_check_for_autowarn(guild, member, author, level)
except Exception as e:
log.error(f"[Guild {guild.id}] A problem occured with automod check.", exc_info=e)
time_taken: timedelta = datetime.now() - t
Expand All @@ -1437,12 +1449,11 @@ async def automod_check_for_autowarn(
)

async def _automod_check_for_autowarn(
self, member: discord.Member, author: discord.Member, level: int
self, guild: discord.Guild, member: discord.Member, author: discord.Member, level: int
):
"""
Prevents having to put this whole function into a try/except block.
"""
guild = member.guild
if not self.cache.is_automod_enabled(guild):
return
# starting the iteration through warnings can cost performances
Expand Down
8 changes: 4 additions & 4 deletions warnsystem/warnsystem.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def __init__(self, bot):

self.task: asyncio.Task

__version__ = "1.3.7"
__version__ = "1.3.8"
__author__ = ["retke (El Laggron)"]

# helpers
Expand Down Expand Up @@ -790,7 +790,7 @@ async def warnings(
if (
not (
await mod.is_mod_or_superior(self.bot, ctx.author)
or ctx.author.guild_permissions.kick
or ctx.author.guild_permissions.kick_members
)
and user != ctx.author
):
Expand Down Expand Up @@ -1321,9 +1321,9 @@ async def on_member_unban(self, guild: discord.Guild, user: discord.User):
warns = await self.cache.get_temp_action(guild)
to_remove = [] # there can be multiple temp bans, let's not question the moderators
for member, data in warns.items():
if data["level"] == 2 or data["member"] != user.id:
if data["level"] == 2 or int(member) != user.id:
continue
to_remove.append(member)
to_remove.append(UnavailableMember(self.bot, guild._state, member))
if to_remove:
await self.cache.bulk_remove_temp_action(guild, to_remove)
log.info(
Expand Down

0 comments on commit f91b304

Please sign in to comment.