async def unban(self, ctx, member: BannedMember, *, reason: Reason = ""): """unban_help""" if reason == "": reason = Translator.translate("no_reason", ctx.guild.id) fid = f"{ctx.guild.id}-{member.user.id}" self.bot.data["unbans"].add(fid) try: await ctx.guild.unban( member.user, reason=Utils.trim_message( f"Moderator: {ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id}) Reason: {reason}", 500)) except Exception as e: self.bot.data["unbans"].remove(fid) raise e Infraction.update(active=False).where( (Infraction.user_id == member.user.id) & (Infraction.type == "Ban") & (Infraction.guild_id == ctx.guild.id)).execute() InfractionUtils.add_infraction(ctx.guild.id, member.user.id, ctx.author.id, "Unban", reason) await ctx.send( f"{Emoji.get_chat_emoji('YES')} {Translator.translate('unban_confirmation', ctx.guild.id, user=Utils.clean_user(member.user), user_id=member.user.id, reason=reason)}" ) GearbotLogging.log_to( ctx.guild.id, "MOD_ACTIONS", f"{Emoji.get_chat_emoji('INNOCENT')} {Translator.translate('unban_log', ctx.guild.id, user=Utils.clean_user(member.user), user_id=member.user.id, moderator=Utils.clean_user(ctx.author), moderator_id=ctx.author.id, reason=reason)}" )
async def on_member_ban(self, guild, user): if user.id == self.bot.user.id or not Features.is_logged(guild.id, "MOD_ACTIONS"): return fid = f"{guild.id}-{user.id}" if fid in self.bot.data["forced_exits"]: return if guild.me.guild_permissions.view_audit_log: async for entry in guild.audit_logs(action=AuditLogAction.ban, limit=25): if entry.target == user and entry.created_at > datetime.datetime.utcfromtimestamp(time.time() - 30): if entry.reason is None: reason = Translator.translate("no_reason", guild.id) else: reason = entry.reason Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Unban") & (Infraction.guild_id == guild.id)).execute() InfractionUtils.add_infraction(guild.id, entry.target.id, entry.user.id, "Ban", "No reason given." if entry.reason is None else entry.reason) GearbotLogging.log_to(guild.id, "MOD_ACTIONS", f":door: {Translator.translate('ban_log', guild.id, user=Utils.clean_user(user), user_id=user.id, moderator=Utils.clean_user(entry.user), moderator_id=entry.user.id, reason=reason)}") return GearbotLogging.log_to(guild.id, "MOD_ACTIONS", f":door: {Translator.translate('manual_ban_log', guild.id, user=Utils.clean_user(user), user_id=user.id)}") Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Unban") & (Infraction.guild_id == guild.id)).execute() self.bot.data["forced_exits"].add(fid)
async def get_infraction_pages(guild_id, query, amount): if f"{guild_id}_{query}" not in cache.keys(): if query is None: infs = Infraction.select().where(Infraction.guild_id == guild_id).order_by(Infraction.id.desc()).limit(amount) else: infs = Infraction.select().where((Infraction.guild_id == guild_id) & ( (Infraction.user_id == query) | (Infraction.mod_id == query))).order_by(Infraction.id.desc()).limit(amount) out = "" longest_user = 0 longest_mod = 9 longest_type = 4 longest_id = len(str(infs[0].id)) if len(infs) > 0 else 2 for inf in infs: user = await Utils.username(inf.user_id) longest_user = max(longest_user, len(user)) mod = await Utils.username(inf.mod_id) longest_mod = max(longest_mod, len(mod)) longest_type = max(longest_type, len(inf.type)) for inf in infs: user = await Utils.username(inf.user_id) mod = await Utils.username(inf.mod_id) out += f"{Utils.pad(str(inf.id), longest_id)} | {Utils.pad(user, longest_user)} | {Utils.pad(mod, longest_mod)} | {inf.start} | {Utils.pad(inf.type, longest_type)} | {inf.reason}\n" prefix = f"{Utils.pad('id', longest_id)} | {Utils.pad('user', longest_user-1)}| {Utils.pad('moderator', longest_mod-1)}| timestamp | {Utils.pad('type', longest_type)} | reason" prefix = f"```md\n{prefix}\n{'-' * len(prefix)}\n" pages = Pages.paginate(out, prefix=prefix, suffix="```") cache[f"{guild_id}_{query}"] = pages if len(cache.keys()) > 20: del cache[list(cache.keys())[0]] return cache[f"{guild_id}_{query}"]
def add_infraction(guild_id, user_id, mod_id, type, reason, end=None, active=True): Infraction.create(guild_id=guild_id, user_id=user_id, mod_id=mod_id, type=type, reason=reason, start=datetime.now(), end=end, active=active) if f"{guild_id}_{user_id}" in cache.keys(): del cache[f"{guild_id}_{user_id}"] if f"{guild_id}_{None}" in cache.keys(): del cache[f"{guild_id}_{None}"]
async def on_member_unban(self, guild, user): fid = f"{guild.id}-{user.id}" if fid in self.bot.data["unbans"]: self.bot.data["unbans"].remove(fid) return elif not Features.is_logged(guild.id, "MOD_ACTIONS"): return Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Ban") & (Infraction.guild_id == guild.id)).execute() limit = datetime.datetime.utcfromtimestamp(time.time() - 60) log = await self.find_log(guild, AuditLogAction.unban, lambda e: e.target == user and e.created_at > limit) if log is None: # this fails way to often for my liking, alternative is adding a delay but this seems to do the trick for now log = await self.find_log(guild, AuditLogAction.unban, lambda e: e.target == user and e.created_at > limit) if log is not None: i = InfractionUtils.add_infraction(guild.id, user.id, log.user.id, "Unban", "Manual unban") GearbotLogging.log_key(guild.id, 'unban_log', user=Utils.clean_user(user), user_id=user.id, moderator=log.user, moderator_id=log.user.id, reason='Manual unban', inf=i.id) else: i = InfractionUtils.add_infraction(guild.id, user.id, 0, "Unban", "Manual ban") GearbotLogging.log_key(guild.id, 'manual_unban_log', user=Utils.clean_user(user), user_id=user.id, inf=i.id)
async def on_member_ban(self, guild, user): if user.id == self.bot.user.id or not Features.is_logged(guild.id, "MOD_ACTIONS"): return fid = f"{guild.id}-{user.id}" if fid in self.bot.data["forced_exits"]: return self.bot.data["forced_exits"].add(fid) Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Unban") & (Infraction.guild_id == guild.id)).execute() limit = datetime.datetime.utcfromtimestamp(time.time() - 60) log = await self.find_log(guild, AuditLogAction.ban, lambda e: e.target == user and e.created_at > limit) if log is None: await asyncio.sleep(1) #is the api having a fit or so? #this fails way to often for my liking, alternative is adding a delay but this seems to do the trick for now log = await self.find_log(guild, AuditLogAction.ban, lambda e: e.target == user and e.created_at > limit) if log is not None: if log.reason is None: reason = Translator.translate("no_reason", guild.id) else: reason = log.reason i = InfractionUtils.add_infraction(guild.id, log.target.id, log.user.id, "Ban", reason) GearbotLogging.log_key(guild.id, 'ban_log', user=Utils.clean_user(user), user_id=user.id, moderator=Utils.clean_user(log.user), moderator_id=log.user.id, reason=reason, inf=i.id) else: i = InfractionUtils.add_infraction(guild.id, user.id, 0, "Ban", "Manual ban") GearbotLogging.log_key(guild.id, 'manual_ban_log', user=Utils.clean_user(user), user_id=user.id, inf=i.id)
def add_infraction(guild_id, user_id, mod_id, type, reason): Infraction.create(guild_id=guild_id, user_id=user_id, mod_id=mod_id, type=type, reason=reason, timestamp=datetime.now()) if f"{guild_id}_{user_id}" in cache.keys(): del cache[f"{guild_id}_{user_id}"]
async def ban_punishment(self, v: Violation): reason = self.assemble_reason(v) self.bot.data["forced_exits"].add(f"{v.guild.id}-{v.member.id}") await v.guild.ban(v.member, reason=reason, delete_message_days=0) Infraction.update(active=False).where( (Infraction.user_id == v.member.id) & (Infraction.type == "Unban") & ( Infraction.guild_id == v.guild.id)).execute() i = InfractionUtils.add_infraction(v.guild.id, v.member.id, self.bot.user.id, 'Ban', reason) GearbotLogging.log_key(v.guild.id, 'ban_log', user=Utils.clean_user(v.member), user_id=v.member.id, moderator=Utils.clean_user(v.guild.me), moderator_id=v.guild.me.id, reason=reason, inf=i.id)
async def fetch_infraction_pages(guild_id, query, amount, fields, requested): key = get_key(guild_id, query, fields, amount) if query == "": infs = Infraction.select().where( Infraction.guild_id == guild_id).order_by( Infraction.id.desc()).limit(50) else: infs = Infraction.select().where((Infraction.guild_id == guild_id) & ( ("[user]" in fields and isinstance(query, int) and Infraction. user_id == query) | ("[mod]" in fields and isinstance(query, int) and Infraction.mod_id == query) | ("[reason]" in fields and fn.lower(Infraction.reason).contains( str(query).lower())))).order_by(Infraction.id.desc()).limit( int(amount)) longest_type = 4 longest_id = len(str(infs[0].id)) if len(infs) > 0 else len( Translator.translate('id', guild_id)) longest_timestamp = max(len(Translator.translate('timestamp', guild_id)), 19) types = dict() for inf in infs: t = inf.type.lower() longest_type = max(longest_type, len(Translator.translate(t, guild_id))) if t not in types: types[t] = 1 else: types[t] += 1 header = ", ".join( Translator.translate(f"{k}s", guild_id, count=v) for k, v in types.items()) name = await Utils.username(query) if isinstance( query, int) else await Utils.clean(bot.get_guild(guild_id).name) title = f"{Emoji.get_chat_emoji('SEARCH')} {Translator.translate('inf_search_header', guild_id, name=name, page_num=100, pages=100)}\n```md\n\n```" page_header = get_header(longest_id, 37, longest_type, longest_timestamp, guild_id) mcount = 2000 - len(header) - len(page_header) - len(title) out = "\n".join( f"{Utils.pad(str(inf.id), longest_id)} | <@{Utils.pad(str(inf.user_id), 37)}> | <@{Utils.pad(str(inf.mod_id), 37)}> | {inf.start} | {Utils.pad(Translator.translate(inf.type.lower(), guild_id), longest_type)} | {Utils.trim_message(inf.reason, 1000)}" for inf in infs) pages = Pages.paginate(out, max_chars=mcount) if bot.redis_pool is not None: GearbotLogging.debug(f"Pushing placeholders for {key}") pipe = bot.redis_pool.pipeline() for page in pages: pipe.lpush(key, "---NO PAGE YET---") await pipe.execute() bot.loop.create_task( update_pages(guild_id, query, fields, amount, pages, requested, longest_id, longest_type, longest_timestamp, header)) return len(pages)
def swap_mute_role(guild, old, new, parts): active_mutes = Infraction.select().where((Infraction.type == "Mute") & ( Infraction.guild_id == guild.id) & Infraction.active) loop = asyncio.get_running_loop() old_role = guild.get_role(old) new_role = guild.get_role(new) parts.update(old_id=old, old_name=Utils.escape_markdown(old_role.name) if old_role is not None else old, new_id=new, new_name=Utils.escape_markdown(new_role.name) if new_role is not None else new, count=len(active_mutes)) if old != 0: if old_role is not None: loop.create_task(role_remover(active_mutes, guild, old_role)) if new != 0: GearbotLogging.log_key(guild.id, "config_mute_role_changed", **parts) else: GearbotLogging.log_key( guild.id, "config_mute_role_disabled", **parts, ) if new != 0: if new_role is not None: loop.create_task(role_adder(active_mutes, guild, new_role)) if old == 0: GearbotLogging.log_key(guild.id, "config_mute_role_set", **parts)
async def delete(self, ctx: commands.Context, inf_id: int): """inf_delete_help""" infraction = Infraction.get_or_none(id=inf_id, guild_id=ctx.guild.id) if infraction is None: await ctx.send( f"{Emoji.get_chat_emoji('NO')} {Translator.translate('inf_not_found', ctx.guild.id, id=inf_id)}" ) else: reason = infraction.reason target = await Utils.get_user(infraction.user_id) mod = await Utils.get_user(infraction.mod_id) async def yes(): infraction.delete_instance() key = f"{ctx.guild.id}_{infraction.user_id}" if key in InfractionUtils.cache.keys(): del InfractionUtils.cache[key] await GearbotLogging.send_to(ctx, "YES", "inf_delete_deleted", id=inf_id) GearbotLogging.log_to( ctx.guild.id, "MOD_ACTIONS", f":wastebasket: {Translator.translate('inf_delete_log', ctx.guild.id, id=inf_id, target=str(target), target_id=target.id, mod=str(mod), mod_id=mod.id, reason=reason, user=str(ctx.author), user_id=ctx.author.id)}" ) await Confirmation.confirm( ctx, text= f"{Emoji.get_chat_emoji('WARNING')} {Translator.translate('inf_delete_confirmation', ctx.guild.id, id=inf_id, user=str(target), user_id=target.id, reason=reason)}", on_yes=yes)
async def on_member_join(self, member: discord.Member): now = datetime.datetime.fromtimestamp(time.time()) if Infraction.get_or_none(Infraction.type == "Mute", Infraction.active == True, Infraction.end >= now, Infraction.guild_id == member.guild.id, Infraction.user_id == member.id): roleid = Configuration.get_var(member.guild.id, "MUTE_ROLE") if roleid is not 0: role = member.guild.get_role(roleid) if role is not None: if member.guild.me.guild_permissions.manage_roles: await member.add_roles(role, reason=Translator.translate( 'mute_reapply_reason', member.guild.id)) GearbotLogging.log_to( member.guild.id, "MOD_ACTIONS", f"{Emoji.get_chat_emoji('MUTE')} {Translator.translate('mute_reapply_log', member.guild.id, user=Utils.clean_user(member), user_id=member.id)}" ) else: GearbotLogging.log_to( member.guild.id, "MOD_ACTIONS", Translator.translate('mute_reapply_failed_log', member.build.id))
async def convert(self, ctx, argument): try: argument = int(argument) except ValueError: raise TranslatedBadArgument('NaN', ctx) infraction = Infraction.get_or_none(id=argument, guild_id=ctx.guild.id) if infraction is None: raise TranslatedBadArgument('inf_not_found', ctx, id=argument) else: return infraction
async def mute_punishment(self, v: Violation): duration = v.bucket["PUNISHMENT"]["DURATION"] until = time.time() + duration reason = self.assemble_reason(v) role = AntiSpam._get_mute_role(v.guild) i = Infraction.get_or_none((Infraction.user_id == v.member.id) & (Infraction.type == "Mute") & (Infraction.guild_id == v.member.guild.id) & Infraction.active) if i is None: i = InfractionUtils.add_infraction(v.guild.id, v.member.id, self.bot.user.id, 'Mute', reason, end=until) try: await v.member.add_roles(role, reason=reason) except Forbidden: GearbotLogging.log_key(v.guild.id, 'mute_punishment_failure', user=Utils.clean_user(v.member), user_id=v.member.id, duration=Utils.to_pretty_time( duration, v.guild.id), reason=reason, inf=i.id) else: GearbotLogging.log_key(v.guild.id, 'mute_log', user=Utils.clean_user(v.member), user_id=v.member.id, moderator=Utils.clean_user(v.guild.me), moderator_id=v.guild.me.id, duration=Utils.to_pretty_time( duration, v.guild.id), reason=reason, inf=i.id) else: i.end += datetime.timedelta(seconds=duration) i.reason += f'+ {reason}' i.save() GearbotLogging.log_key(v.guild.id, 'mute_duration_extended_log', user=Utils.clean_user(v.member), user_id=v.member.id, moderator=Utils.clean_user(v.guild.me), moderator_id=v.guild.me.id, duration=Utils.to_pretty_time( duration, v.guild.id), reason=reason, inf_id=i.id, end=i.end) InfractionUtils.clear_cache(v.guild.id)
async def update(self, ctx:commands.Context, inf_id:int, *, reason:str): """inf_update_help""" infraction = Infraction.get_or_none(id=inf_id, guild_id=ctx.guild.id) if infraction is None: await ctx.send(f"{Emoji.get_chat_emoji('NO')} {Translator.translate('inf_not_found', ctx.guild.id, id=inf_id)}") else: infraction.mod_id = ctx.author.id infraction.reason = reason infraction.save() if f"{ctx.guild.id}_{infraction.user_id}" in InfractionUtils.cache.keys(): del InfractionUtils.cache[f"{ctx.guild.id}_{infraction.user_id}"] await ctx.send(f"{Emoji.get_chat_emoji('YES')} {Translator.translate('inf_updated', ctx.guild.id, id=inf_id)}")
async def _ban(self, ctx, user, reason, confirm): self.bot.data["forced_exits"].add(f"{ctx.guild.id}-{user.id}") await ctx.guild.ban( user, reason=Utils.trim_message( f"Moderator: {ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id}) Reason: {reason}", 500), delete_message_days=0) Infraction.update(active=False).where( (Infraction.user_id == user.id) & (Infraction.type == "Unban") & (Infraction.guild_id == ctx.guild.id)).execute() InfractionUtils.add_infraction(ctx.guild.id, user.id, ctx.author.id, "Ban", reason) GearbotLogging.log_to( ctx.guild.id, "MOD_ACTIONS", f":door: {Translator.translate('ban_log', ctx.guild.id, user=Utils.clean_user(user), user_id=user.id, moderator=Utils.clean_user(ctx.author), moderator_id=ctx.author.id, reason=reason)}" ) if confirm: await GearbotLogging.send_to(ctx, "YES", "ban_confirmation", user=Utils.clean_user(user), user_id=user.id, reason=reason)
async def on_member_unban(self, guild, user): fid = f"{guild.id}-{user.id}" if fid in self.bot.data["unbans"]: self.bot.data["unbans"].remove(fid) return elif not Features.is_logged(guild.id, "MOD_ACTIONS"): return else: if guild.me.guild_permissions.view_audit_log: async for entry in guild.audit_logs(action=AuditLogAction.unban, limit=2): if entry.target == user and entry.created_at > datetime.datetime.utcfromtimestamp(time.time() - 30): Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Ban") & (Infraction.guild_id == guild.id)).execute() InfractionUtils.add_infraction(guild.id, entry.target.id, entry.user.id, "Unban", "Manual unban") GearbotLogging.log_to(guild.id, "MOD_ACTIONS", f":door: {Translator.translate('unban_log', guild.id, user=Utils.clean_user(user), user_id=user.id, moderator=entry.user, moderator_id=entry.user.id, reason='Manual unban')}") return GearbotLogging.log_to(guild.id, "MOD_ACTIONS", f"{Emoji.get_chat_emoji('INNOCENT')} {Translator.translate('manual_unban_log', guild.id, user=Utils.clean_user(user), user_id=user.id)}") Infraction.update(active=False).where((Infraction.user_id == user.id) & (Infraction.type == "Ban") & (Infraction.guild_id == guild.id)).execute()
def add_infraction(guild_id, user_id, mod_id, type, reason, end=None, active=True): i = Infraction.create(guild_id=guild_id, user_id=user_id, mod_id=mod_id, type=type, reason=reason, start=datetime.now(), end=end, active=active) bot.loop.create_task(clear_cache(guild_id)) return i
async def timed_actions(self): GearbotLogging.info("Started timed moderation action background task") while self.running: # actions to handle and the function handling it types = {"Mute": self._lift_mute, "Tempban": self._lift_tempban} now = datetime.datetime.fromtimestamp(time.time()) limit = datetime.datetime.fromtimestamp(time.time() + 30) for name, action in types.items(): for infraction in Infraction.select().where( Infraction.type == name, Infraction.active == True, Infraction.end <= limit): if infraction.id not in self.handling: self.handling.add(infraction.id) self.bot.loop.create_task( self.run_after( (infraction.end - now).total_seconds(), action(infraction))) await asyncio.sleep(10) GearbotLogging.info( "Timed moderation actions background task terminated")
async def censor_message(self, message: discord.Message): ctx = await self.bot.get_context(message) if message.guild is None or \ message.webhook_id is not None or \ message.author == message.guild.me or \ not Configuration.get_var(message.guild.id, "CENSOR_MESSAGES") or \ Permissioncheckers.get_user_lvl(ctx) >= 2: return blacklist = Configuration.get_var(message.guild.id, "WORD_BLACKLIST") max_mentions = Configuration.get_var(message.guild.id, "MAX_MENTIONS") guilds = Configuration.get_var(message.guild.id, "INVITE_WHITELIST") content = message.content.replace('\\', '') censored = False if len(guilds) is not 0: codes = INVITE_MATCHER.findall(content) for code in codes: try: invite: discord.Invite = await self.bot.get_invite(code) except discord.NotFound: await censor_invite(ctx, code, "INVALID INVITE") except KeyError: await censor_invite(ctx, code, "DM group") censored = True else: if invite.guild is None or (not invite.guild.id in guilds and invite.guild.id != message.guild.id): await censor_invite(ctx, code, invite.guild.name) censored = True if not censored: content = content.lower() for bad in (w.lower() for w in blacklist): if bad in content: if message.channel.permissions_for(message.guild.me).manage_messages: try: self.bot.data["message_deletes"].add(message.id) await message.delete() except discord.NotFound as ex: pass # lost the race with another bot? else: clean_message = await clean_content().convert(ctx, message.content) GearbotLogging.log_to(ctx.guild.id, "CENSORED_MESSAGES", f":no_entry_sign: {Translator.translate('censored_message', ctx.guild.id, user=message.author, user_id=message.author.id, message=clean_message, sequence=bad, channel=message.channel.mention)}") else: clean_message = await clean_content().convert(ctx, message.content) GearbotLogging.log_to(ctx.guild.id, "CENSORED_MESSAGES", f":no_entry_sign: {Translator.translate('censor_message_failed', ctx.guild.id, user=message.author, user_id=message.author.id, message=clean_message, sequence=bad, link=message.jump_url)}") mentions = len(message.mentions) + len(message.role_mentions) if mentions > max_mentions > 4: self.bot.data["forced_exits"].add(message.author.id) reason = Translator.translate('autoban_too_many_mentions', message.guild.id, count=mentions) if message.guild.me.guild_permissions.ban_members: await message.guild.ban(message.author, reason=reason) Infraction.update(active=False).where( (Infraction.user_id == message.author.id) & (Infraction.type == "Unban") & (Infraction.guild_id == ctx.guild.id)).execute() InfractionUtils.add_infraction(message.guild.id, message.author.id, self.bot.user.id, "AUTOBAN", reason) GearbotLogging.log_to(ctx.guild.id, "MOD_ACTIONS", f":door: {Translator.translate('ban_log', ctx.guild.id, user=message.author, user_id=message.author.id, moderator=self.bot.user, moderator_id=self.bot.user.id, reason=reason)}") else: self.bot.data["forced_exits"].remove(message.author.id) translated = Translator.translate('automod_ban_failed', message.guild.id, user=message.author, user_id=message.author.id, reason=reason) GearbotLogging.log_to(message.guild.id, "MOD_ACTIONS", f"{Emoji.get_chat_emoji('WARNING')} {translated}")
async def forceban(self, ctx: commands.Context, user_id: UserID, *, reason: Reason = ""): """forceban_help""" if reason == "": reason = Translator.translate("no_reason", ctx.guild.id) try: member = await commands.MemberConverter().convert( ctx, str(user_id)) except BadArgument: user = await ctx.bot.get_user_info(user_id) self.bot.data["forced_exits"].add(f"{ctx.guild.id}-{user.id}") await ctx.guild.ban( user, reason=Utils.trim_message( f"Moderator: {ctx.author.name}#{ctx.author.discriminator} ({ctx.author.id}) Reason: {reason}", 500), delete_message_days=0) await ctx.send( f"{Emoji.get_chat_emoji('YES')} {Translator.translate('forceban_confirmation', ctx.guild.id, user=Utils.clean_user(user), user_id=user_id, reason=reason)}" ) GearbotLogging.log_to( ctx.guild.id, "MOD_ACTIONS", f":door: {Translator.translate('forceban_log', ctx.guild.id, user=Utils.clean_user(user), user_id=user_id, moderator=Utils.clean_user(ctx.author), moderator_id=ctx.author.id, reason=reason)}" ) tempbans = list(Infraction.select().where( (Infraction.user_id == user.id) & (Infraction.type == "Tempban") & (Infraction.guild_id == ctx.guild.id))) if len(tempbans) > 0: inf = tempbans[0] timeframe = datetime.datetime.utcfromtimestamp( inf.end.timestamp()) - datetime.datetime.utcfromtimestamp( time.time()) hours, remainder = divmod(int(timeframe.total_seconds()), 3600) minutes, seconds = divmod(remainder, 60) tt = Translator.translate("hours", ctx, hours=hours, minutes=minutes) await GearbotLogging.send_to(ctx, "WARNING", "forceban_override_tempban", user=Utils.clean_user(user), timeframe=tt, inf_id=inf.id) Infraction.update(active=False).where( (Infraction.user_id == user.id) & ((Infraction.type == "Unban") | (Infraction.type == "Tempban")) & (Infraction.guild_id == ctx.guild.id)).execute() InfractionUtils.add_infraction(ctx.guild.id, user.id, ctx.author.id, "Forced ban", reason) else: await ctx.send( f"{Emoji.get_chat_emoji('WARNING')} {Translator.translate('forceban_to_ban', ctx.guild.id, user=Utils.clean_user(member))}" ) await ctx.invoke(self.ban, member, reason=reason)
from database.DatabaseConnector import Infraction connection = MySQLDatabase( Configuration.get_master_var("DATABASE_NAME"), user=Configuration.get_master_var("DATABASE_USER"), password=Configuration.get_master_var("DATABASE_PASS"), host=Configuration.get_master_var("DATABASE_HOST"), port=Configuration.get_master_var("DATABASE_PORT"), use_unicode=True, charset="utf8mb4") #make connection migrator = MySQLMigrator(connection) #run everything in a transaction so we don't turn the database into 💩 if something goes wrong with connection.atomic(): #fields to add end = TimestampField(null=True) active = BooleanField(default=True) #add fields migrate( migrator.add_column("infraction", "end", end), migrator.add_column("infraction", "active", active), migrator.rename_column("infraction", "timestamp", "start"), ) #some infractions are not active anymore Infraction.update( active=False).where((Infraction.type == "Mute") | (Infraction.type == "Kick")).execute()