2024-04-16 10:44:05 -04:00
# _____ _
# / ____| (_)
# | (___ ___ __ _ _____ ___ _ __ ___ _ __ ___ ___ _ __
# \___ \ / _ \/ _` / __\ \ /\ / / | '_ ` _ \| '_ ` _ \ / _ \ '__|
# ____) | __/ (_| \__ \\ V V /| | | | | | | | | | | | __/ |
# |_____/ \___|\__,_|___/ \_/\_/ |_|_| |_| |_|_| |_| |_|\___|_|
import discord
from red_commons . logging import getLogger
from redbot . core import commands
from redbot . core . bot import Config , Red
2024-08-27 14:22:19 -04:00
from redbot . core . utils . chat_formatting import bold , humanize_list
2024-04-16 10:44:05 -04:00
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). """
2024-08-27 14:22:19 -04:00
__author__ = [ " [cswimr](https://www.coastalcommits.com/cswimr) " ]
__git__ = " https://www.coastalcommits.com/cswimr/SeaCogs "
__version__ = " 1.0.1 "
2024-04-16 10:44:05 -04:00
__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 ,
)
2024-04-16 12:13:15 -04:00
if not self . bot . intents . message_content :
self . logger . error ( " Message Content intent is not enabled, cog will not load. " )
raise RuntimeError ( " This cog requires the Message Content intent to function. To prevent potentially destructive behavior, the cog will not load without the intent enabled. " )
2024-04-16 10:44:05 -04:00
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 } " ,
2024-08-27 14:22:19 -04:00
f " { bold ( ' Cog Version: ' ) } [ { self . __version__ } ]( { self . __git__ } ) " ,
f " { bold ( ' Author: ' ) } { humanize_list ( self . __author__ ) } " ,
f " { bold ( ' Documentation: ' ) } { self . __documentation__ } " ,
2024-04-16 10:44:05 -04:00
]
return " \n " . join ( text )
2024-04-16 12:38:00 -04:00
async def red_delete_data_for_user ( self , * * kwargs ) : # pylint: disable=unused-argument
2024-04-16 10:44:05 -04:00
""" Nothing to delete. """
return
@commands.Cog.listener ( ' on_message ' )
2024-04-16 12:38:00 -04:00
async def polls_listener ( self , message : discord . Message ) - > None :
2024-04-16 10:44:05 -04:00
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 " )
2024-04-16 10:49:20 -04:00
if await self . bot . cog_disabled_in_guild ( self , message . guild ) :
2024-04-16 12:38:00 -04:00
return self . logger . verbose ( " Message ignored, cog is disabled in guild %s " , message . guild . id )
2024-04-16 10:44:05 -04:00
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 ' ] :
2024-04-16 12:38:00 -04:00
return self . logger . verbose ( " Message in whitelisted channel %s ignored " , message . channel . id )
2024-04-16 10:44:05 -04:00
if any ( role . id in guild_config [ ' role_whitelist ' ] for role in message . author . roles ) :
2024-04-16 12:38:00 -04:00
return self . logger . verbose ( " Message from whitelisted role %s ignored " , message . author . roles )
2024-04-16 10:44:05 -04:00
if not message . content and not message . embeds and not message . attachments and not message . stickers :
2024-04-16 12:38:00 -04:00
self . logger . trace ( " Message %s is a poll, attempting to delete " , message . id )
2024-04-16 10:44:05 -04:00
try :
await message . delete ( )
except discord . HTTPException as e :
2024-04-16 12:38:00 -04:00
return self . logger . error ( " Failed to delete message: %s " , e )
2024-04-16 10:44:05 -04:00
2024-04-16 12:38:00 -04:00
return self . logger . trace ( " Deleted poll message %s " , message . id )
self . logger . verbose ( " Message %s is not a poll, ignoring " , message . id )
2024-04-16 10:44:05 -04:00
@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
2024-04-16 11:02:31 -04:00
failed : list [ discord . Role ] = [ ]
2024-04-16 10:44:05 -04:00
for role in roles :
if role . id in role_whitelist :
2024-04-16 12:38:00 -04:00
failed . append ( role )
2024-04-16 10:44:05 -04:00
continue
2024-04-16 10:56:10 -04:00
role_whitelist . append ( role . id )
2024-04-16 10:44:05 -04:00
await ctx . tick ( )
if failed :
2024-04-16 12:38:00 -04:00
await ctx . send ( f " The following roles were already in the whitelist: { humanize_list ( [ role . mention for role in failed ] ) } " , delete_after = 10 )
2024-04-16 10:44:05 -04:00
@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
2024-04-16 11:02:31 -04:00
failed : list [ discord . Role ] = [ ]
2024-04-16 10:44:05 -04:00
for role in roles :
if role . id not in role_whitelist :
2024-04-16 11:02:31 -04:00
failed . append ( role )
2024-04-16 10:44:05 -04:00
continue
role_whitelist . remove ( role . id )
await ctx . tick ( )
if failed :
2024-04-16 11:08:15 -04:00
await ctx . send ( f " The following roles were not in the whitelist: { humanize_list ( [ role . mention for role in failed ] ) } " , delete_after = 10 )
2024-04-16 10:44:05 -04:00
@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 ]
2024-04-16 11:05:37 -04:00
await ctx . send ( humanize_list ( [ role . mention for role in roles ] ) )
2024-04-16 10:44:05 -04:00
@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
2024-04-16 11:02:31 -04:00
failed : list [ discord . TextChannel ] = [ ]
2024-04-16 10:44:05 -04:00
for channel in channels :
if channel . id in channel_whitelist :
2024-04-16 10:56:10 -04:00
failed . append ( channel )
2024-04-16 10:44:05 -04:00
continue
2024-04-16 10:56:10 -04:00
channel_whitelist . append ( channel . id )
2024-04-16 10:44:05 -04:00
await ctx . tick ( )
if failed :
2024-04-16 11:08:15 -04:00
await ctx . send ( f " The following channels were already in the whitelist: { humanize_list ( [ channel . mention for channel in failed ] ) } " , delete_after = 10 )
2024-04-16 10:44:05 -04:00
@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
2024-04-16 11:02:31 -04:00
failed : list [ discord . TextChannel ] = [ ]
2024-04-16 10:44:05 -04:00
for channel in channels :
if channel . id not in channel_whitelist :
2024-04-16 11:02:31 -04:00
failed . append ( channel )
2024-04-16 10:44:05 -04:00
continue
channel_whitelist . remove ( channel . id )
await ctx . tick ( )
if failed :
2024-04-16 11:08:15 -04:00
await ctx . send ( f " The following channels were not in the whitelist: { humanize_list ( [ channel . mention for channel in failed ] ) } " , delete_after = 10 )
2024-04-16 10:44:05 -04:00
@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 ]
2024-04-16 11:05:37 -04:00
await ctx . send ( humanize_list ( [ channel . mention for channel in channels ] ) )
2024-04-16 10:44:05 -04:00
@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 ( )