[Mod] Move ignored guilds and channels to core (#3472)

* Move ignored guilds and channels to core
Add caching for ignored guilds and channels
Add caching for whitelist and blacklist
Fix #3220
Add consume-rest for whitelist and blacklist commands to add multiple users or roles in one command

* Add ability to ignore channel categories

* black

* moveignorechannels should be owner only and cleanup changes

* add changelog entries

* address Feedback
This commit is contained in:
TrustyJAID 2020-02-14 23:21:09 -07:00 committed by GitHub
parent 78192dc1af
commit 74a3eba08f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 457 additions and 238 deletions

View File

@ -0,0 +1,4 @@
Add caching for ignored channels/guilds.
Add caching for white/blacklist.
Add consume-rest for white/blacklist commands.
Allow ignoring channel categories.

View File

@ -0,0 +1 @@
Move ignore commands and checks into core.

View File

@ -17,7 +17,7 @@ from .settings import ModSettings
_ = T_ = Translator("Mod", __file__)
__version__ = "1.0.0"
__version__ = "1.1.0"
class CompositeMetaClass(type(commands.Cog), type(ABC)):
@ -85,35 +85,36 @@ class Mod(
async def _maybe_update_config(self):
"""Maybe update `delete_delay` value set by Config prior to Mod 1.0.0."""
if await self.settings.version():
return
guild_dict = await self.settings.all_guilds()
for guild_id, info in guild_dict.items():
delete_repeats = info.get("delete_repeats", False)
if delete_repeats:
val = 3
else:
val = -1
await self.settings.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.settings.version.set(__version__)
if not await self.settings.version():
guild_dict = await self.settings.all_guilds()
for guild_id, info in guild_dict.items():
delete_repeats = info.get("delete_repeats", False)
if delete_repeats:
val = 3
else:
val = -1
await self.settings.guild(discord.Object(id=guild_id)).delete_repeats.set(val)
await self.settings.version.set("1.0.0") # set version of last update
if await self.settings.version() < "1.1.0":
prefixes = await self.bot.get_valid_prefixes()
msg = _(
"Ignored guilds and channels have been moved. "
"Please use `{prefix}moveignoredchannels` if "
"you were previously using these functions."
).format(prefix=prefixes[0])
await self.bot.send_to_owners(msg)
await self.settings.version.set(__version__)
# TODO: Move this to core.
# This would be in .movetocore , but the double-under name here makes that more trouble
async def bot_check(self, ctx):
"""Global check to see if a channel or server is ignored.
Any users who have permission to use the `ignore` or `unignore` commands
surpass the check.
"""
perms = ctx.channel.permissions_for(ctx.author)
surpass_ignore = (
isinstance(ctx.channel, discord.abc.PrivateChannel)
or perms.manage_guild
or await ctx.bot.is_owner(ctx.author)
or await ctx.bot.is_admin(ctx.author)
)
if surpass_ignore:
return True
guild_ignored = await self.settings.guild(ctx.guild).ignored()
chann_ignored = await self.settings.channel(ctx.channel).ignored()
return not (guild_ignored or chann_ignored and not perms.manage_channels)
@commands.command()
@commands.is_owner()
async def moveignoredchannels(self, ctx: commands.Context) -> None:
"""Move ignored channels and servers to core"""
all_guilds = await self.settings.all_guilds()
all_channels = await self.settings.all_channels()
for guild_id, settings in all_guilds.items():
await self.bot._config.guild_from_id(guild_id).ignored.set(settings["ignored"])
await self.settings.guild_from_id(guild_id).ignored.clear()
for channel_id, settings in all_channels.items():
await self.bot._config.channel_from_id(channel_id).ignored.set(settings["ignored"])
await self.settings.channel_fro_id(channel_id).clear()
await ctx.send(_("Ignored channels and guilds restored."))

View File

@ -47,84 +47,3 @@ class MoveToCore(MixinMeta):
await asyncio.sleep(delay)
await _delete_helper(message)
# When the below are moved to core, the global check in .modcore needs to be moved as well.
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def ignore(self, ctx: commands.Context):
"""Add servers or channels to the ignore list."""
if ctx.invoked_subcommand is None:
await ctx.send(await self.count_ignored())
@ignore.command(name="channel")
async def ignore_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Ignore commands in the channel.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel
if not await self.settings.channel(channel).ignored():
await self.settings.channel(channel).ignored.set(True)
await ctx.send(_("Channel added to ignore list."))
else:
await ctx.send(_("Channel already in ignore list."))
@ignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def ignore_guild(self, ctx: commands.Context):
"""Ignore commands in this server."""
guild = ctx.guild
if not await self.settings.guild(guild).ignored():
await self.settings.guild(guild).ignored.set(True)
await ctx.send(_("This server has been added to the ignore list."))
else:
await ctx.send(_("This server is already being ignored."))
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def unignore(self, ctx: commands.Context):
"""Remove servers or channels from the ignore list."""
if ctx.invoked_subcommand is None:
await ctx.send(await self.count_ignored())
@unignore.command(name="channel")
async def unignore_channel(self, ctx: commands.Context, channel: discord.TextChannel = None):
"""Remove a channel from ignore the list.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel
if await self.settings.channel(channel).ignored():
await self.settings.channel(channel).ignored.set(False)
await ctx.send(_("Channel removed from ignore list."))
else:
await ctx.send(_("That channel is not in the ignore list."))
@unignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def unignore_guild(self, ctx: commands.Context):
"""Remove this server from the ignore list."""
guild = ctx.message.guild
if await self.settings.guild(guild).ignored():
await self.settings.guild(guild).ignored.set(False)
await ctx.send(_("This server has been removed from the ignore list."))
else:
await ctx.send(_("This server is not in the ignore list."))
async def count_ignored(self):
ch_count = 0
svr_count = 0
for guild in self.bot.guilds:
if not await self.settings.guild(guild).ignored():
for channel in guild.text_channels:
if await self.settings.channel(channel).ignored():
ch_count += 1
else:
svr_count += 1
msg = _("Currently ignoring:\n{} channels\n{} guilds\n").format(ch_count, svr_count)
return box(msg)

View File

@ -38,7 +38,7 @@ from .dev_commands import Dev
from .events import init_events
from .global_checks import init_global_checks
from .settings_caches import PrefixManager
from .settings_caches import PrefixManager, IgnoreManager, WhitelistBlacklistManager
from .rpc import RPCMixin
from .utils import common_filters
@ -118,13 +118,14 @@ class RedBase(
admin_role=[],
mod_role=[],
embeds=None,
ignored=False,
use_bot_color=False,
fuzzy=False,
disabled_commands=[],
autoimmune_ids=[],
)
self._config.register_channel(embeds=None)
self._config.register_channel(embeds=None, ignored=False)
self._config.register_user(embeds=None)
self._config.init_custom(CUSTOM_GROUPS, 2)
@ -133,6 +134,8 @@ class RedBase(
self._config.init_custom(SHARED_API_TOKENS, 2)
self._config.register_custom(SHARED_API_TOKENS)
self._prefix_cache = PrefixManager(self._config, cli_flags)
self._ignored_cache = IgnoreManager(self._config)
self._whiteblacklist_cache = WhitelistBlacklistManager(self._config)
async def prefix_manager(bot, message) -> List[str]:
prefixes = await self._prefix_cache.get_prefixes(message.guild)
@ -350,13 +353,13 @@ class RedBase(
if await self.is_owner(who):
return True
global_whitelist = await self._config.whitelist()
global_whitelist = await self._whiteblacklist_cache.get_whitelist()
if global_whitelist:
if who.id not in global_whitelist:
return False
else:
# blacklist is only used when whitelist doesn't exist.
global_blacklist = await self._config.blacklist()
global_blacklist = await self._whiteblacklist_cache.get_blacklist()
if who.id in global_blacklist:
return False
@ -375,17 +378,44 @@ class RedBase(
# there is a silent failure potential, and role blacklist/whitelists will break.
ids = {i for i in (who.id, *(getattr(who, "_roles", []))) if i != guild.id}
guild_whitelist = await self._config.guild(guild).whitelist()
guild_whitelist = await self._whiteblacklist_cache.get_whitelist(guild)
if guild_whitelist:
if ids.isdisjoint(guild_whitelist):
return False
else:
guild_blacklist = await self._config.guild(guild).blacklist()
guild_blacklist = await self._whiteblacklist_cache.get_blacklist(guild)
if not ids.isdisjoint(guild_blacklist):
return False
return True
async def ignored_channel_or_guild(self, ctx: commands.Context) -> bool:
"""
This checks if the bot is meant to be ignoring commands in a channel or guild,
as considered by Red's whitelist and blacklist.
Parameters
----------
ctx : Context of where the command is being run.
Returns
-------
bool
`True` if commands are allowed in the channel, `False` otherwise
"""
perms = ctx.channel.permissions_for(ctx.author)
surpass_ignore = (
isinstance(ctx.channel, discord.abc.PrivateChannel)
or perms.manage_guild
or await ctx.bot.is_owner(ctx.author)
or await ctx.bot.is_admin(ctx.author)
)
if surpass_ignore:
return True
guild_ignored = await self._ignored_cache.get_ignored_guild(ctx.guild)
chann_ignored = await self._ignored_cache.get_ignored_channel(ctx.channel)
return not (guild_ignored or chann_ignored and not perms.manage_channels)
async def get_valid_prefixes(self, guild: Optional[discord.Guild] = None) -> List[str]:
"""
This gets the valid prefixes for a guild.

View File

@ -1702,16 +1702,14 @@ class Core(commands.Cog, CoreLogic):
pass
@whitelist.command(name="add")
async def whitelist_add(self, ctx, *, user: Union[discord.Member, int]):
async def whitelist_add(self, ctx: commands.Context, *users: List[Union[discord.Member, int]]):
"""
Adds a user to the whitelist.
"""
uid = getattr(user, "id", user)
async with ctx.bot._config.whitelist() as curr_list:
if uid not in curr_list:
curr_list.append(uid)
uids = [getattr(user, "id", user) for user in users]
await self.bot._whiteblacklist_cache.add_to_whitelist(None, uids)
await ctx.send(_("User added to whitelist."))
await ctx.send(_("Users added to whitelist."))
@whitelist.command(name="list")
async def whitelist_list(self, ctx: commands.Context):
@ -1732,28 +1730,23 @@ class Core(commands.Cog, CoreLogic):
await ctx.send(box(page))
@whitelist.command(name="remove")
async def whitelist_remove(self, ctx: commands.Context, *, user: Union[discord.Member, int]):
async def whitelist_remove(
self, ctx: commands.Context, *users: List[Union[discord.Member, int]]
):
"""
Removes user from whitelist.
"""
removed = False
uid = getattr(user, "id", user)
async with ctx.bot._config.whitelist() as curr_list:
if uid in curr_list:
removed = True
curr_list.remove(uid)
uids = [getattr(user, "id", user) for user in users]
await self.bot._whiteblacklist_cache.remove_from_whitelist(None, uids)
if removed:
await ctx.send(_("User has been removed from whitelist."))
else:
await ctx.send(_("User was not in the whitelist."))
await ctx.send(_("Users have been removed from whitelist."))
@whitelist.command(name="clear")
async def whitelist_clear(self, ctx: commands.Context):
"""
Clears the whitelist.
"""
await ctx.bot._config.whitelist.set([])
await self.bot._whiteblacklist_cache.clear_whitelist()
await ctx.send(_("Whitelist has been cleared."))
@commands.group()
@ -1765,18 +1758,21 @@ class Core(commands.Cog, CoreLogic):
pass
@blacklist.command(name="add")
async def blacklist_add(self, ctx: commands.Context, *, user: Union[discord.Member, int]):
async def blacklist_add(self, ctx: commands.Context, *users: List[Union[discord.Member, int]]):
"""
Adds a user to the blacklist.
"""
if await ctx.bot.is_owner(user):
await ctx.send(_("You cannot blacklist an owner!"))
return
for user in users:
if isinstance(user, int):
user_obj = discord.Object(id=user)
else:
user_obj = user
if await ctx.bot.is_owner(user_obj):
await ctx.send(_("You cannot blacklist an owner!"))
return
uid = getattr(user, "id", user)
async with ctx.bot._config.blacklist() as curr_list:
if uid not in curr_list:
curr_list.append(uid)
uids = [getattr(user, "id", user) for user in users]
await self.bot._whiteblacklist_cache.add_to_blacklist(None, uids)
await ctx.send(_("User added to blacklist."))
@ -1785,7 +1781,7 @@ class Core(commands.Cog, CoreLogic):
"""
Lists blacklisted users.
"""
curr_list = await ctx.bot._config.blacklist()
curr_list = await self.bot._whiteblacklist_cache.get_blacklist(None)
if not curr_list:
await ctx.send("Blacklist is empty.")
@ -1799,29 +1795,24 @@ class Core(commands.Cog, CoreLogic):
await ctx.send(box(page))
@blacklist.command(name="remove")
async def blacklist_remove(self, ctx: commands.Context, *, user: Union[discord.Member, int]):
async def blacklist_remove(
self, ctx: commands.Context, *users: List[Union[discord.Member, int]]
):
"""
Removes user from blacklist.
"""
removed = False
uid = getattr(user, "id", user)
async with ctx.bot._config.blacklist() as curr_list:
if uid in curr_list:
removed = True
curr_list.remove(uid)
uids = [getattr(user, "id", user) for user in users]
await self.bot._whiteblacklist_cache.remove_from_blacklist(None, uids)
if removed:
await ctx.send(_("User has been removed from blacklist."))
else:
await ctx.send(_("User was not in the blacklist."))
await ctx.send(_("Users have been removed from blacklist."))
@blacklist.command(name="clear")
async def blacklist_clear(self, ctx: commands.Context):
"""
Clears the blacklist.
"""
await ctx.bot._config.blacklist.set([])
await self.bot._whiteblacklist_cache.clear_blacklist()
await ctx.send(_("Blacklist has been cleared."))
@commands.group()
@ -1835,31 +1826,25 @@ class Core(commands.Cog, CoreLogic):
@localwhitelist.command(name="add")
async def localwhitelist_add(
self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int]
self,
ctx: commands.Context,
*users_or_roles: List[Union[discord.Member, discord.Role, int]],
):
"""
Adds a user or role to the whitelist.
"""
user = isinstance(user_or_role, discord.Member)
if isinstance(user_or_role, int):
user_or_role = discord.Object(id=user_or_role)
user = True
names = [getattr(users_or_roles, "name", users_or_roles) for u_or_r in users_or_roles]
uids = [getattr(users_or_roles, "id", users_or_roles) for u_or_r in users_or_roles]
await self.bot._whiteblacklist_cache.add_to_whitelist(ctx.guild, uids)
async with ctx.bot._config.guild(ctx.guild).whitelist() as curr_list:
if user_or_role.id not in curr_list:
curr_list.append(user_or_role.id)
if user:
await ctx.send(_("User added to whitelist."))
else:
await ctx.send(_("Role added to whitelist."))
await ctx.send(_("{names} added to whitelist.").format(names=humanize_list(names)))
@localwhitelist.command(name="list")
async def localwhitelist_list(self, ctx: commands.Context):
"""
Lists whitelisted users and roles.
"""
curr_list = await ctx.bot._config.guild(ctx.guild).whitelist()
curr_list = await self.bot._whiteblacklist_cache.get_whitelist(ctx.guild)
if not curr_list:
await ctx.send("Local whitelist is empty.")
@ -1874,40 +1859,28 @@ class Core(commands.Cog, CoreLogic):
@localwhitelist.command(name="remove")
async def localwhitelist_remove(
self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int]
self,
ctx: commands.Context,
*users_or_roles: List[Union[discord.Member, discord.Role, int]],
):
"""
Removes user or role from whitelist.
"""
user = isinstance(user_or_role, discord.Member)
if isinstance(user_or_role, int):
user_or_role = discord.Object(id=user_or_role)
user = True
names = [getattr(users_or_roles, "name", users_or_roles) for u_or_r in users_or_roles]
uids = [getattr(users_or_roles, "id", users_or_roles) for u_or_r in users_or_roles]
await self.bot._whiteblacklist_cache.remove_from_whitelist(ctx.guild, uids)
removed = False
async with ctx.bot._config.guild(ctx.guild).whitelist() as curr_list:
if user_or_role.id in curr_list:
removed = True
curr_list.remove(user_or_role.id)
if removed:
if user:
await ctx.send(_("User has been removed from whitelist."))
else:
await ctx.send(_("Role has been removed from whitelist."))
else:
if user:
await ctx.send(_("User was not in the whitelist."))
else:
await ctx.send(_("Role was not in the whitelist."))
await ctx.send(
_("{names} removed from the local whitelist.").format(names=humanize_list(names))
)
@localwhitelist.command(name="clear")
async def localwhitelist_clear(self, ctx: commands.Context):
"""
Clears the whitelist.
"""
await ctx.bot._config.guild(ctx.guild).whitelist.set([])
await ctx.send(_("Whitelist has been cleared."))
await self.bot._whiteblacklist_cache.clear_whitelist(ctx.guild)
await ctx.send(_("Local whitelist has been cleared."))
@commands.group()
@commands.guild_only()
@ -1920,42 +1893,38 @@ class Core(commands.Cog, CoreLogic):
@localblacklist.command(name="add")
async def localblacklist_add(
self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int]
self,
ctx: commands.Context,
*users_or_roles: List[Union[discord.Member, discord.Role, int]],
):
"""
Adds a user or role to the blacklist.
"""
user = isinstance(user_or_role, discord.Member)
if isinstance(user_or_role, int):
user_or_role = discord.Object(id=user_or_role)
user = True
if user:
if user_or_role.id == ctx.author.id:
for user_or_role in users_or_roles:
uid = discord.Object(id=getattr(user_or_role, "id", user_or_role))
if uid.id == ctx.author.id:
await ctx.send(_("You cannot blacklist yourself!"))
return
if user_or_role.id == ctx.guild.owner_id and not await ctx.bot.is_owner(ctx.author):
if uid.id == ctx.guild.owner_id and not await ctx.bot.is_owner(ctx.author):
await ctx.send(_("You cannot blacklist the guild owner!"))
return
if await ctx.bot.is_owner(user_or_role):
if await ctx.bot.is_owner(uid):
await ctx.send(_("You cannot blacklist a bot owner!"))
return
names = [getattr(users_or_roles, "name", users_or_roles) for u_or_r in users_or_roles]
uids = [getattr(users_or_roles, "id", users_or_roles) for u_or_r in users_or_roles]
await self.bot._whiteblacklist_cache.add_to_blacklist(ctx.guild, uids)
async with ctx.bot._config.guild(ctx.guild).blacklist() as curr_list:
if user_or_role.id not in curr_list:
curr_list.append(user_or_role.id)
if user:
await ctx.send(_("User added to blacklist."))
else:
await ctx.send(_("Role added to blacklist."))
await ctx.send(
_("{names} added to the local blacklist.").format(names=humanize_list(names))
)
@localblacklist.command(name="list")
async def localblacklist_list(self, ctx: commands.Context):
"""
Lists blacklisted users and roles.
"""
curr_list = await ctx.bot._config.guild(ctx.guild).blacklist()
curr_list = await self.bot._whiteblacklist_cache.get_blacklist(ctx.guild)
if not curr_list:
await ctx.send("Local blacklist is empty.")
@ -1970,32 +1939,18 @@ class Core(commands.Cog, CoreLogic):
@localblacklist.command(name="remove")
async def localblacklist_remove(
self, ctx: commands.Context, *, user_or_role: Union[discord.Member, discord.Role, int]
self, ctx: commands.Context, *users_or_roles: Union[discord.Member, discord.Role, int]
):
"""
Removes user or role from blacklist.
"""
removed = False
user = isinstance(user_or_role, discord.Member)
if isinstance(user_or_role, int):
user_or_role = discord.Object(id=user_or_role)
user = True
names = [getattr(users_or_roles, "name", users_or_roles) for u_or_r in users_or_roles]
uids = [getattr(users_or_roles, "id", users_or_roles) for u_or_r in users_or_roles]
await self.bot._whiteblacklist_cache.remove_from_whitelist(ctx.guild, uids)
async with ctx.bot._config.guild(ctx.guild).blacklist() as curr_list:
if user_or_role.id in curr_list:
removed = True
curr_list.remove(user_or_role.id)
if removed:
if user:
await ctx.send(_("User has been removed from blacklist."))
else:
await ctx.send(_("Role has been removed from blacklist."))
else:
if user:
await ctx.send(_("User was not in the blacklist."))
else:
await ctx.send(_("Role was not in the blacklist."))
await ctx.send(
_("{names} removed from the local blacklist.").format(names=humanize_list(names))
)
@localblacklist.command(name="clear")
async def localblacklist_clear(self, ctx: commands.Context):
@ -2003,7 +1958,7 @@ class Core(commands.Cog, CoreLogic):
Clears the blacklist.
"""
await ctx.bot._config.guild(ctx.guild).blacklist.set([])
await ctx.send(_("Blacklist has been cleared."))
await ctx.send(_("Local blacklist has been cleared."))
@checks.guildowner_or_permissions(administrator=True)
@commands.group(name="command")
@ -2409,6 +2364,107 @@ class Core(commands.Cog, CoreLogic):
await self.rpc_unload(request)
await self.rpc_load(request)
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def ignore(self, ctx: commands.Context):
"""Add servers or channels to the ignore list."""
if ctx.invoked_subcommand is None:
for page in pagify(await self.count_ignored(ctx)):
await ctx.maybe_send_embed(page)
@ignore.command(name="channel")
async def ignore_channel(
self,
ctx: commands.Context,
channel: Optional[Union[discord.TextChannel, discord.CategoryChannel]] = None,
):
"""Ignore commands in the channel or category.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel
if not await self.bot._ignored_cache.get_ignored_channel(channel):
await self.bot._ignored_cache.set_ignored_channel(channel, True)
await ctx.send(_("Channel added to ignore list."))
else:
await ctx.send(_("Channel already in ignore list."))
@ignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def ignore_guild(self, ctx: commands.Context):
"""Ignore commands in this server."""
guild = ctx.guild
if not await self.bot._ignored_cache.get_ignored_guild(guild):
await self.bot._ignored_cache.set_ignored_guild(guild, True)
await ctx.send(_("This server has been added to the ignore list."))
else:
await ctx.send(_("This server is already being ignored."))
@commands.group()
@commands.guild_only()
@checks.admin_or_permissions(manage_channels=True)
async def unignore(self, ctx: commands.Context):
"""Remove servers or channels from the ignore list."""
if ctx.invoked_subcommand is None:
for page in pagify(await self.count_ignored(ctx)):
await ctx.maybe_send_embed(page)
@unignore.command(name="channel")
async def unignore_channel(
self,
ctx: commands.Context,
channel: Optional[Union[discord.TextChannel, discord.CategoryChannel]] = None,
):
"""Remove a channel or category from ignore the list.
Defaults to the current channel.
"""
if not channel:
channel = ctx.channel
if await self.bot._ignored_cache.get_ignored_channel(channel):
await self.bot._ignored_cache.set_ignored_channel(channel, False)
await ctx.send(_("Channel removed from ignore list."))
else:
await ctx.send(_("That channel is not in the ignore list."))
@unignore.command(name="server", aliases=["guild"])
@checks.admin_or_permissions(manage_guild=True)
async def unignore_guild(self, ctx: commands.Context):
"""Remove this server from the ignore list."""
guild = ctx.message.guild
if await self.bot._ignored_cache.get_ignored_guild(guild):
await self.bot._ignored_cache.set_ignored_guild(guild, False)
await ctx.send(_("This server has been removed from the ignore list."))
else:
await ctx.send(_("This server is not in the ignore list."))
async def count_ignored(self, ctx: commands.Context):
category_channels: List[discord.CategoryChannel] = []
text_channels: List[discord.TextChannel] = []
if await self.bot._ignored_cache.get_ignored_guild(ctx.guild):
return _("This server is currently being ignored.")
for channel in ctx.guild.text_channels:
if channel.category and channel.category not in category_channels:
if await self.bot._ignored_cache.get_ignored_channel(channel.category):
category_channels.append(channel.category)
continue
else:
continue
if await self.bot._ignored_cache.get_ignored_channel(channel):
text_channels.append(channel)
cat_str = (
humanize_list([c.name for c in category_channels]) if category_channels else "None"
)
chan_str = humanize_list([c.mention for c in text_channels]) if text_channels else "None"
msg = _("Currently ignored categories: {categories}\nChannels:{channels}").format(
categories=cat_str, channels=chan_str
)
return msg
# Removing this command from forks is a violation of the GPLv3 under which it is licensed.
# Otherwise interfering with the ability for this command to be accessible is also a violation.

View File

@ -7,7 +7,7 @@ def init_global_checks(bot):
def minimum_bot_perms(ctx) -> bool:
"""
Too many 403, 401, and 429 Errors can cause bots to get global'd
It's reasonable to assume the below as a minimum amount of perms for
commands.
"""
@ -17,6 +17,11 @@ def init_global_checks(bot):
async def whiteblacklist_checks(ctx) -> bool:
return await ctx.bot.allowed_by_whitelist_blacklist(ctx.author)
@bot.check_once
async def ignore_checks(ctx) -> bool:
"""Check the channel or server is not ignored"""
return await ctx.bot.ignored_channel_or_guild(ctx)
@bot.check_once
def bots(ctx) -> bool:
"""Check the user is not another bot."""

View File

@ -1,6 +1,6 @@
from __future__ import annotations
from typing import Dict, List, Optional
from typing import Dict, List, Optional, Union
from argparse import Namespace
import discord
@ -51,3 +51,206 @@ class PrefixManager:
else:
del self._cached[gid]
await self._config.guild_from_id(gid).prefix.set(prefixes)
class IgnoreManager:
def __init__(self, config: Config):
self._config: Config = config
self._cached_channels: Dict[int, bool] = {}
self._cached_guilds: Dict[int, bool] = {}
async def get_ignored_channel(self, channel: discord.TextChannel) -> bool:
ret: bool
cid: int = channel.id
cat_id: Optional[int] = channel.category.id if channel.category else None
if cid in self._cached_channels:
chan_ret = self._cached_channels[cid]
else:
chan_ret = await self._config.channel_from_id(cid).ignored()
self._cached_channels[cid] = chan_ret
if cat_id and cat_id in self._cached_channels:
cat_ret = self._cached_channels[cat_id]
else:
if cat_id:
cat_ret = await self._config.channel_from_id(cat_id).ignored()
self._cached_channels[cat_id] = cat_ret
else:
cat_ret = False
ret = chan_ret or cat_ret
return ret
async def set_ignored_channel(
self, channel: Union[discord.TextChannel, discord.CategoryChannel], set_to: bool
):
cid: int = channel.id
self._cached_channels[cid] = set_to
if set_to:
await self._config.channel_from_id(cid).ignored.set(set_to)
else:
await self._config.channel_from_id(cid).ignored.clear()
async def get_ignored_guild(self, guild: discord.Guild) -> bool:
ret: bool
gid: int = guild.id
if gid in self._cached_guilds:
ret = self._cached_guilds[gid]
else:
ret = await self._config.guild_from_id(gid).ignored()
self._cached_guilds[gid] = ret
return ret
async def set_ignored_guild(self, guild: discord.Guild, set_to: bool):
gid: int = guild.id
self._cached_guilds[gid] = set_to
if set_to:
await self._config.guild_from_id(gid).ignored.set(set_to)
else:
await self._config.guild_from_id(gid).ignored.clear()
class WhitelistBlacklistManager:
def __init__(self, config: Config):
self._config: Config = config
self._cached_whitelist: Dict[Optional[int], List[int]] = {}
self._cached_blacklist: Dict[Optional[int], List[int]] = {}
async def get_whitelist(self, guild: Optional[discord.Guild] = None) -> List[int]:
ret: List[int]
gid: Optional[int] = guild.id if guild else None
if gid in self._cached_whitelist:
ret = self._cached_whitelist[gid].copy()
else:
if gid is not None:
ret = await self._config.guild_from_id(gid).whitelsit()
if not ret:
ret = []
else:
ret = await self._config.whitelist()
self._cached_whitelist[gid] = ret.copy()
return ret
async def add_to_whitelist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
gid: Optional[int] = guild.id if guild else None
role_or_user = role_or_user or []
if not isinstance(role_or_user, list) and not all(
isinstance(r_or_u, str) for r_or_u in role_or_user
):
raise TypeError("Whitelisted objects must be a list of ints")
if gid is None:
for obj_id in role_or_user:
if obj_id not in self._cached_whitelist:
self._cached_whitelist[gid].append(obj_id)
async with self._config.whitelist() as curr_list:
curr_list.append(obj_id)
else:
for obj_id in role_or_user:
if obj_id not in self._cached_whitelist:
self._cached_whitelist[gid].append(obj_id)
async with self._config.guild_from_id(gid).whitelist() as curr_list:
curr_list.append(obj_id)
async def clear_whitelist(self, guild: Optional[discord.Guild] = None):
gid: Optional[int] = guild.id if guild else None
self._cached_whitelist[gid]
if gid is None:
await self._config.whitelist.clear()
else:
await self._config.guild_from_id(gid).whitelist.clear()
async def remove_from_whitelist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
gid: Optional[int] = guild.id if guild else None
role_or_user = role_or_user or []
if not isinstance(role_or_user, list) and not all(
isinstance(r_or_u, str) for r_or_u in role_or_user
):
raise TypeError("Whitelisted objects must be a list of ints")
if gid is None:
for obj_id in role_or_user:
if obj_id in self._cached_whitelist:
self._cached_whitelist[gid].remove(obj_id)
async with self._config.whitelist() as curr_list:
curr_list.remove(obj_id)
else:
for obj_id in role_or_user:
if obj_id not in self._cached_whitelist:
self._cached_whitelist[gid].remove(obj_id)
async with self._config.guild_from_id(gid).whitelist() as curr_list:
curr_list.remove(obj_id)
async def get_blacklist(self, guild: Optional[discord.Guild] = None) -> List[int]:
ret: List[int]
gid: Optional[int] = guild.id if guild else None
if gid in self._cached_blacklist:
ret = self._cached_blacklist[gid].copy()
else:
if gid is not None:
ret = await self._config.guild_from_id(gid).whitelsit()
if not ret:
ret = []
else:
ret = await self._config.blacklist()
self._cached_blacklist[gid] = ret.copy()
return ret
async def add_to_blacklist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
gid: Optional[int] = guild.id if guild else None
role_or_user = role_or_user or []
if not isinstance(role_or_user, list) and not all(
isinstance(r_or_u, str) for r_or_u in role_or_user
):
raise TypeError("Blacklisted objects must be a list of ints")
if gid is None:
for obj_id in role_or_user:
if obj_id not in self._cached_blacklist:
self._cached_blacklist[gid].append(obj_id)
async with self._config.blacklist() as curr_list:
curr_list.append(obj_id)
else:
for obj_id in role_or_user:
if obj_id not in self._cached_blacklist:
self._cached_blacklist[gid].append(obj_id)
async with self._config.guild_from_id(gid).blacklist() as curr_list:
curr_list.append(obj_id)
async def clear_blacklist(self, guild: Optional[discord.Guild] = None):
gid: Optional[int] = guild.id if guild else None
self._cached_whitelist[gid]
if gid is None:
await self._config.blacklist.clear()
else:
await self._config.guild_from_id(gid).blacklist.clear()
async def remove_from_blacklist(self, guild: Optional[discord.Guild], role_or_user: List[int]):
gid: Optional[int] = guild.id if guild else None
role_or_user = role_or_user or []
if not isinstance(role_or_user, list) and not all(
isinstance(r_or_u, str) for r_or_u in role_or_user
):
raise TypeError("Blacklisted objects must be a list of ints")
if gid is None:
for obj_id in role_or_user:
if obj_id in self._cached_blacklist:
self._cached_blacklist[gid].remove(obj_id)
async with self._config.blacklist() as curr_list:
curr_list.remove(obj_id)
else:
for obj_id in role_or_user:
if obj_id not in self._cached_blacklist:
self._cached_blacklist[gid].remove(obj_id)
async with self._config.guild_from_id(gid).blacklist() as curr_list:
curr_list.remove(obj_id)