Brandon209-Red-bot-Cogs/smartreact/smartreact.py
2021-02-06 03:42:47 -05:00

149 lines
5.6 KiB
Python

import discord
from redbot.core import Config, commands, checks
from redbot.core.utils.chat_formatting import pagify
from typing import Literal
class SmartReact(commands.Cog):
"""Create automatic reactions when trigger words are typed in chat"""
default_guild_settings = {"reactions": {}}
def __init__(self, bot):
self.bot = bot
self.conf = Config.get_conf(self, identifier=964952632)
self.conf.register_guild(**self.default_guild_settings)
@checks.mod_or_permissions(administrator=True)
@commands.guild_only()
@commands.command(name="addreact")
async def addreact(self, ctx, word, emoji):
"""Add an auto reaction to a word"""
guild = ctx.message.guild
message = ctx.message
emoji = self.fix_custom_emoji(emoji)
await self.create_smart_reaction(guild, word, emoji, message)
@checks.mod_or_permissions(administrator=True)
@commands.guild_only()
@commands.command(name="delreact")
async def delreact(self, ctx, word, emoji):
"""Delete an auto reaction to a word"""
guild = ctx.message.guild
message = ctx.message
emoji = self.fix_custom_emoji(emoji)
await self.remove_smart_reaction(guild, word, emoji, message)
def fix_custom_emoji(self, emoji):
if emoji[:2] not in ["<:", "<a"]:
# default emoji
return emoji
for guild in self.bot.guilds:
for e in guild.emojis:
if str(e.id) == emoji.split(":")[2][:-1]:
return e
return None
@checks.mod_or_permissions(administrator=True)
@commands.guild_only()
@commands.command(name="listreact")
async def listreact(self, ctx):
"""List reactions for this server"""
emojis = await self.conf.guild(ctx.guild).reactions()
msg = f"Smart Reactions for {ctx.guild.name}:\n"
for emoji in emojis:
for command in emojis[emoji]:
msg += f"{emoji}: {command}\n"
for page in pagify(msg, delims=["\n"]):
await ctx.send(page)
async def create_smart_reaction(self, guild, word, emoji, message):
try:
# Use the reaction to see if it's valid
await message.add_reaction(emoji)
emoji = str(emoji)
reactions = await self.conf.guild(guild).reactions()
if emoji in reactions:
if word.lower() in reactions[emoji]:
await message.channel.send("This smart reaction already exists.")
return
reactions[emoji].append(word.lower())
else:
reactions[emoji] = [word.lower()]
await self.conf.guild(guild).reactions.set(reactions)
await message.channel.send("Successfully added this reaction.")
except (discord.errors.HTTPException, discord.errors.InvalidArgument):
await message.channel.send("That's not an emoji I recognize. " "(might be custom!)")
async def remove_smart_reaction(self, guild, word, emoji, message):
try:
# Use the reaction to see if it's valid
await message.add_reaction(emoji)
emoji = str(emoji)
reactions = await self.conf.guild(guild).reactions()
if emoji in reactions:
if word.lower() in reactions[emoji]:
reactions[emoji].remove(word.lower())
await self.conf.guild(guild).reactions.set(reactions)
await message.channel.send("Removed this smart reaction.")
else:
await message.channel.send("That emoji is not used as a reaction " "for that word.")
else:
await message.channel.send("There are no smart reactions which use " "this emoji.")
except (discord.errors.HTTPException, discord.errors.InvalidArgument):
await message.channel.send("That's not an emoji I recognize. " "(might be custom!)")
async def clean_dead_emojis(self, guild):
"""
Clean all emojis that don't exist anymore in the server
"""
reacts = await self.conf.guild(guild).reactions()
to_delete = []
for emoji in reacts.keys():
e = self.fix_custom_emoji(emoji)
if not e:
to_delete.append(emoji)
for emoji in to_delete:
del reacts[emoji]
await self.conf.guild(guild).reactions.set(reacts)
# Thanks irdumb#1229 for the help making this "more Pythonic"
@commands.Cog.listener()
async def on_message(self, message):
if await self.bot.cog_disabled_in_guild(self, message.guild):
return
if not message.guild:
return
if message.author == self.bot.user:
return
guild = message.guild
reacts = await self.conf.guild(guild).reactions()
if reacts is None:
return
words = message.content.lower().split()
for emoji in reacts:
if set(w.lower() for w in reacts[emoji]).intersection(words):
emoji = self.fix_custom_emoji(emoji)
if not emoji:
await self.clean_dead_emojis(guild)
return
try:
await message.add_reaction(emoji)
except discord.errors.Forbidden:
pass
except discord.errors.InvalidArgument:
pass
async def red_delete_data_for_user(
self,
*,
requester: Literal["discord_deleted_user", "owner", "user", "user_strict"],
user_id: int,
):
pass