feat(AntiPolls): added the cog
Some checks failed
Actions / Build Documentation (MkDocs) (push) Successful in 39s
Actions / Lint Code (Ruff & Pylint) (push) Failing after 54s

This commit is contained in:
Seaswimmer 2024-04-16 10:44:05 -04:00
parent 285257eed5
commit 4344d26096
Signed by: cswimr
GPG key ID: 5D671B5D03D65A7F
4 changed files with 202 additions and 13 deletions

5
antipolls/__init__.py Normal file
View file

@ -0,0 +1,5 @@
from .antipolls import AntiPolls
async def setup(bot):
await bot.add_cog(AntiPolls(bot))

176
antipolls/antipolls.py Normal file
View file

@ -0,0 +1,176 @@
# _____ _
# / ____| (_)
# | (___ ___ __ _ _____ ___ _ __ ___ _ __ ___ ___ _ __
# \___ \ / _ \/ _` / __\ \ /\ / / | '_ ` _ \| '_ ` _ \ / _ \ '__|
# ____) | __/ (_| \__ \\ V V /| | | | | | | | | | | | __/ |
# |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_|
import discord
from red_commons.logging import getLogger
from redbot.core import commands
from redbot.core.bot import Config, Red
from redbot.core.utils.chat_formatting import humanize_list
class AntiPolls(commands.Cog):
"""AntiPolls deletes messages that contain polls, with a configurable per-guild role and channel whitelist and support for default Discord permissions (Manage Messages)."""
__author__ = ["SeaswimmerTheFsh"]
__version__ = "1.0.0"
__documentation__ = "https://seacogs.coastalcommits.com/antipolls/"
def __init__(self, bot: Red):
super().__init__()
self.bot = bot
self.logger = getLogger("red.SeaCogs.AntiPolls")
self.config = Config.get_conf(self, identifier=23517395243, force_registration=True)
self.config.register_guild(
role_whitelist=[],
channel_whitelist=[],
manage_messages=True,
)
def format_help_for_context(self, ctx: commands.Context) -> str:
pre_processed = super().format_help_for_context(ctx) or ""
n = "\n" if "\n\n" not in pre_processed else ""
text = [
f"{pre_processed}{n}",
f"Cog Version: **{self.__version__}**",
f"Author: {humanize_list(self.__author__)}",
f"Documentation: {self.__documentation__}",
]
return "\n".join(text)
async def red_delete_data_for_user(self, **kwargs):
"""Nothing to delete."""
return
@commands.Cog.listener('on_message')
async def listener(self, message: discord.Message) -> None:
if message.guild is None:
return self.logger.verbose("Message in direct messages ignored")
if message.author.bot:
return self.logger.verbose("Message from bot ignored")
if self.bot.cog_disabled_in_guild(self, message.guild):
return self.logger.verbose("Cog disabled in guild")
guild_config = await self.config.guild(message.guild).all()
if guild_config['manage_messages'] is True and message.author.guild_permissions.manage_messages:
return self.logger.verbose("Message from user with Manage Messages permission ignored")
if message.channel.id in guild_config['channel_whitelist']:
return self.logger.verbose(f"Message in whitelisted channel {message.channel.id} ignored")
if any(role.id in guild_config['role_whitelist'] for role in message.author.roles):
return self.logger.verbose(f"Message from whitelisted role {message.author.roles} ignored")
if not message.content and not message.embeds and not message.attachments and not message.stickers:
self.logger.trace(f"Message {message.id} is a poll, attempting to delete")
try:
await message.delete()
except discord.HTTPException as e:
return self.logger.error(f"Failed to delete message: {e}")
self.logger.trace(f"Deleted poll message {message.id}")
@commands.group(name="antipolls", aliases=["ap"])
@commands.guild_only()
@commands.admin_or_permissions(manage_guild=True)
async def antipolls(self, ctx: commands.Context) -> None:
"""Manage AntiPolls settings."""
@antipolls.group(name="roles")
async def antipolls_roles(self, ctx: commands.Context) -> None:
"""Manage role whitelist."""
@antipolls_roles.command(name="add")
async def antipolls_roles_add(self, ctx: commands.Context, *roles: discord.Role) -> None:
"""Add roles to the whitelist."""
async with self.config.guild(ctx.guild).role_whitelist() as role_whitelist:
role_whitelist: list
failed: list[discord.Role] = []
for role in roles:
if role.id in role_whitelist:
failed.extend(role)
continue
role_whitelist.extend(role.id)
await ctx.tick()
if failed:
await ctx.send(f"The following roles were already in the whitelist: {humanize_list(role.mention for role in failed)}", delete_after=10, allowed_mentions=discord.AllowedMentions.none)
@antipolls_roles.command(name="remove")
async def antipolls_roles_remove(self, ctx: commands.Context, *roles: discord.Role) -> None:
"""Remove roles from the whitelist."""
async with self.config.guild(ctx.guild).role_whitelist() as role_whitelist:
role_whitelist: list
failed: list[discord.Role] = []
for role in roles:
if role.id not in role_whitelist:
failed.extend(role)
continue
role_whitelist.remove(role.id)
await ctx.tick()
if failed:
await ctx.send(f"The following roles were not in the whitelist: {humanize_list(role.mention for role in failed)}", delete_after=10, allowed_mentions=discord.AllowedMentions.none)
@antipolls_roles.command(name="list")
async def antipolls_roles_list(self, ctx: commands.Context) -> None:
"""List roles in the whitelist."""
role_whitelist = await self.config.guild(ctx.guild).role_whitelist()
if not role_whitelist:
return await ctx.send("No roles in the whitelist.")
roles = [ctx.guild.get_role(role) for role in role_whitelist]
await ctx.send(humanize_list(role.mention for role in roles))
@antipolls.group(name="channels")
async def antipolls_channels(self, ctx: commands.Context) -> None:
"""Manage channel whitelist."""
@antipolls_channels.command(name="add")
async def antipolls_channels_add(self, ctx: commands.Context, *channels: discord.TextChannel) -> None:
"""Add channels to the whitelist."""
async with self.config.guild(ctx.guild).channel_whitelist() as channel_whitelist:
channel_whitelist: list
failed: list[discord.TextChannel] = []
for channel in channels:
if channel.id in channel_whitelist:
failed.extend(channel)
continue
channel_whitelist.extend(channel.id)
await ctx.tick()
if failed:
await ctx.send(f"The following channels were already in the whitelist: {humanize_list(channel.mention for channel in failed)}", delete_after=10, allowed_mentions=discord.AllowedMentions.none)
@antipolls_channels.command(name="remove")
async def antipolls_channels_remove(self, ctx: commands.Context, *channels: discord.TextChannel) -> None:
"""Remove channels from the whitelist."""
async with self.config.guild(ctx.guild).channel_whitelist() as channel_whitelist:
channel_whitelist: list
failed: list[discord.TextChannel] = []
for channel in channels:
if channel.id not in channel_whitelist:
failed.extend(channel)
continue
channel_whitelist.remove(channel.id)
await ctx.tick()
if failed:
await ctx.send(f"The following channels were not in the whitelist: {humanize_list(channel.mention for channel in failed)}", delete_after=10, allowed_mentions=discord.AllowedMentions.none)
@antipolls_channels.command(name="list")
async def antipolls_channels_list(self, ctx: commands.Context) -> None:
"""List channels in the whitelist."""
channel_whitelist = await self.config.guild(ctx.guild).channel_whitelist()
if not channel_whitelist:
return await ctx.send("No channels in the whitelist.")
channels = [ctx.guild.get_channel(channel) for channel in channel_whitelist]
await ctx.send(humanize_list(channel.mention for channel in channels))
@antipolls.command(name="managemessages")
async def antipolls_managemessages(self, ctx: commands.Context, enabled: bool) -> None:
"""Toggle Manage Messages permission check."""
await self.config.guild(ctx.guild).manage_messages.set(enabled)
await ctx.tick()

17
antipolls/info.json Normal file
View file

@ -0,0 +1,17 @@
{
"author" : ["SeaswimmerTheFsh (seasw.)"],
"install_msg" : "Thank you for installing AntiPolls!\nYou can find the source code of this cog [here](https://coastalcommits.com/SeaswimmerTheFsh/SeaCogs).",
"name" : "AntiPolls",
"short" : "AntiPolls deletes messages that contain polls.",
"description" : "AntiPolls deletes messages that contain polls, with a configurable per-guild role and channel whitelist and support for default Discord permissions (Manage Messages).",
"end_user_data_statement" : "This cog does not store any user data.",
"hidden": true,
"disabled": false,
"min_bot_version": "3.5.0",
"min_python_version": [3, 10, 0],
"tags": [
"automod",
"automoderation",
"polls"
]
}

View file

@ -18,8 +18,7 @@ from redbot.core import app_commands, commands, data_manager
from redbot.core.app_commands import Choice from redbot.core.app_commands import Choice
from redbot.core.bot import Red from redbot.core.bot import Red
from redbot.core.commands.converter import parse_relativedelta, parse_timedelta from redbot.core.commands.converter import parse_relativedelta, parse_timedelta
from redbot.core.utils.chat_formatting import (box, error, humanize_list, from redbot.core.utils.chat_formatting import box, error, humanize_list, humanize_timedelta, warning
humanize_timedelta, warning)
from aurora.importers.aurora import ImportAuroraView from aurora.importers.aurora import ImportAuroraView
from aurora.importers.galacticbot import ImportGalacticBotView from aurora.importers.galacticbot import ImportGalacticBotView
@ -28,18 +27,10 @@ from aurora.menus.guild import Guild
from aurora.menus.immune import Immune from aurora.menus.immune import Immune
from aurora.menus.overrides import Overrides from aurora.menus.overrides import Overrides
from aurora.utilities.config import config, register_config from aurora.utilities.config import config, register_config
from aurora.utilities.database import (connect, create_guild_table, fetch_case, from aurora.utilities.database import connect, create_guild_table, fetch_case, mysql_log
mysql_log) from aurora.utilities.factory import addrole_embed, case_factory, changes_factory, evidenceformat_factory, guild_embed, immune_embed, message_factory, overrides_embed
from aurora.utilities.factory import (addrole_embed, case_factory,
changes_factory, evidenceformat_factory,
guild_embed, immune_embed,
message_factory, overrides_embed)
from aurora.utilities.logger import logger from aurora.utilities.logger import logger
from aurora.utilities.utils import (check_moddable, check_permissions, from aurora.utilities.utils import check_moddable, check_permissions, convert_timedelta_to_str, fetch_channel_dict, fetch_user_dict, generate_dict, log, send_evidenceformat, timedelta_from_relativedelta
convert_timedelta_to_str,
fetch_channel_dict, fetch_user_dict,
generate_dict, log, send_evidenceformat,
timedelta_from_relativedelta)
class Aurora(commands.Cog): class Aurora(commands.Cog):