palmtree5 fb125ef619 [V3] Mod initial rewrite (#1034)
* Readd work due to redoing branch

* [modlog] Move to core and start work on separating it from cogs

* More work on modlog separation

* [Core] Finish logic for modlog, do docstrings, async getters

* [Core] Add stuff to dunder all

* [Docs] Add mod log docs

* [Core] Move away from dunder str for Case class

* [Docs] don't need to doc special members in modlog docs

* More on mod log to implement commands

* More work on Mod

* [Mod] compatibility with async getters

* [Tests] start tests for mod

* [Tests] attempted fix

* [Tests] mod tests passing now!

* [ModLog] update for i18n

* modlog.pot -> messages.pot

* [Mod] i18n

* fix getting admin/mod roles

* Fix doc building

* [Mod/Modlog] redo imports

* [Tests] fix imports in mod tests

* [Mod] fix logger problem

* [Mod] cleanup errors

* A couple of bug fixes

Async getters, some old `config.set` syntax

* Filter ignores private channels

* Fix softban

Was still relying on default channels

* Actually ignore private channels

* Add check for ignored channels

* Fix logic for ignore check

* Send confirm messages before making case

* Pass in guild when setting modlog

* Thanks autocomplete

* Maintain all data for case

* Properly ignore softbans in events

* [Mod] bugfixes

* [Mod] more changes

* [ModLog] timestamp change

* [Mod] split filter and cleanup to their own cogs + regen messages.pot

* [Cleanup] change logic

* [Cleanup] increase limit for channel.history

* [Mod] await getter in modset banmentionspam

* [Mod] attempt duplicate modlog message fix

* [Mod] get_user -> get_user_info

* [Modlog] change reason command so the case author can edit their cases (#806)

* [Modlog] make reason command guild only

* [Modlog] clarify the reason command's help

* [Mod] package path changes + numpy style docstrings for modlog

* [Mod] change ban and unban events to need view audit log perms to find/create a case

* [Modlog] refactoring

* [Filter] add autoban feature

* [Mod] update case types + event changes

* [Mod/Modlog] fix tests, fix permissions things

* [Docs] fix up modlog docs

* Regenerate messages.pot
2017-10-22 21:02:16 -04:00

125 lines
3.8 KiB
Python

import asyncio
from typing import List
import discord
from redbot.core import Config
from redbot.core.bot import Red
async def mass_purge(messages: List[discord.Message],
channel: discord.TextChannel):
while messages:
if len(messages) > 1:
await channel.delete_messages(messages[:100])
messages = messages[100:]
else:
await messages[0].delete()
messages = []
await asyncio.sleep(1.5)
async def slow_deletion(messages: List[discord.Message]):
for message in messages:
try:
await message.delete()
except discord.HTTPException:
pass
def get_audit_reason(author: discord.Member, reason: str = None):
"""Helper function to construct a reason to be provided
as the reason to appear in the audit log."""
return \
"Action requested by {} (ID {}). Reason: {}".format(author, author.id, reason) if reason else \
"Action requested by {} (ID {}).".format(author, author.id)
async def is_allowed_by_hierarchy(
bot: Red, settings: Config, server: discord.Guild,
mod: discord.Member, user: discord.Member):
if not await settings.guild(server).respect_hierarchy():
return True
is_special = mod == server.owner or await bot.is_owner(mod)
return mod.top_role.position > user.top_role.position or is_special
async def is_mod_or_superior(bot: Red, obj: discord.Message or discord.Member or discord.Role):
user = None
if isinstance(obj, discord.Message):
user = obj.author
elif isinstance(obj, discord.Member):
user = obj
elif isinstance(obj, discord.Role):
pass
else:
raise TypeError('Only messages, members or roles may be passed')
server = obj.guild
admin_role_id = await bot.db.guild(server).admin_role()
mod_role_id = await bot.db.guild(server).mod_role()
if isinstance(obj, discord.Role):
return obj.id in [admin_role_id, mod_role_id]
mod_roles = [r for r in server.roles if r.id == mod_role_id]
mod_role = mod_roles[0] if len(mod_roles) > 0 else None
admin_roles = [r for r in server.roles if r.id == admin_role_id]
admin_role = admin_roles[0] if len(admin_roles) > 0 else None
if user and user == await bot.is_owner(user):
return True
elif admin_role and discord.utils.get(user.roles, name=admin_role):
return True
elif mod_role and discord.utils.get(user.roles, name=mod_role):
return True
else:
return False
def strfdelta(delta):
s = []
if delta.days:
ds = '%i day' % delta.days
if delta.days > 1:
ds += 's'
s.append(ds)
hrs, rem = divmod(delta.seconds, 60*60)
if hrs:
hs = '%i hr' % hrs
if hrs > 1:
hs += 's'
s.append(hs)
mins, secs = divmod(rem, 60)
if mins:
s.append('%i min' % mins)
if secs:
s.append('%i sec' % secs)
return ' '.join(s)
async def is_admin_or_superior(bot: Red, obj: discord.Message or discord.Role or discord.Member):
user = None
if isinstance(obj, discord.Message):
user = obj.author
elif isinstance(obj, discord.Member):
user = obj
elif isinstance(obj, discord.Role):
pass
else:
raise TypeError('Only messages, members or roles may be passed')
server = obj.guild
admin_role_id = await bot.db.guild(server).admin_role()
if isinstance(obj, discord.Role):
return obj.id == admin_role_id
admin_roles = [r for r in server.roles if r.id == admin_role_id]
admin_role = admin_roles[0] if len(admin_roles) > 0 else None
if user and await bot.is_owner(user):
return True
elif admin_roles and discord.utils.get(user.roles, name=admin_role):
return True
else:
return False