diff --git a/filter/filter.py b/filter/filter.py index ec82d63..9cc879b 100644 --- a/filter/filter.py +++ b/filter/filter.py @@ -1,22 +1,54 @@ import discord import json -import io +import sqlite3 from redbot.core import commands, Config +class FilterStorage: + def __init__(self): + self.conn = sqlite3.connect("filter_storage.db") + self.cursor = self.conn.cursor() + self._setup() + + def _setup(self): + self.cursor.execute(""" + CREATE TABLE IF NOT EXISTS filter_data ( + key TEXT PRIMARY KEY, + value TEXT + ) + """) + self.conn.commit() + + def get(self, key): + self.cursor.execute("SELECT value FROM filter_data WHERE key = ?", (key,)) + result = self.cursor.fetchone() + return json.loads(result[0]) if result else [] + + def add(self, key, value): + data = self.get(key) + if value not in data: + data.append(value) + self.cursor.execute("REPLACE INTO filter_data (key, value) VALUES (?, ?)", (key, json.dumps(data))) + self.conn.commit() + + def remove(self, key, value): + data = self.get(key) + if value in data: + data.remove(value) + self.cursor.execute("REPLACE INTO filter_data (key, value) VALUES (?, ?)", (key, json.dumps(data))) + self.conn.commit() + + def clear(self, key): + self.cursor.execute("DELETE FROM filter_data WHERE key = ?", (key,)) + self.conn.commit() + class FilterCog(commands.Cog): def __init__(self, bot): self.bot = bot self.config = Config.get_conf(self, identifier=1234567890, force_registration=True) + self.storage = FilterStorage() self.config.register_global( - regexes=[], - phrases=[], - words=[], - standAloneWords=[], - replacementChars=[], - mutedPlayers=[], - tempMutedPlayers=[], - ignoredPlayers=[], logFiltered=True, + logChannelId=None, ignorePrivateMessages=False, caseSensitive=False, muteCommand=False, @@ -34,78 +66,70 @@ class FilterCog(commands.Cog): async def on_ready(self): print(f"{self.__class__.__name__} cog has been loaded.") + @commands.Cog.listener() + async def on_message(self, message): + if message.author.bot: + return + + if isinstance(message.channel, discord.DMChannel) and await self.config.ignorePrivateMessages(): + return + + words = self.storage.get("words") + case_sensitive = await self.config.caseSensitive() + message_content = message.content if case_sensitive else message.content.lower() + + for word in words: + word_check = word if case_sensitive else word.lower() + if word_check in message_content: + try: + await message.delete() + log_channel_id = await self.config.logChannelId() + if log_channel_id: + log_channel = message.guild.get_channel(log_channel_id) + if log_channel: + await log_channel.send(f"Deleted a message from {message.author.mention} containing a filtered word: `{word}`") + return + except discord.Forbidden: + await message.channel.send("I don't have permission to delete messages.", delete_after=5) + except discord.HTTPException: + print("Failed to delete message due to an HTTP error") + @commands.hybrid_command() async def addword(self, ctx, word: str): """Add a word to the filter list.""" - async with self.config.words() as words: - words.append(word) + self.storage.add("words", word) await ctx.send(f"Added `{word}` to the filter list.") @commands.hybrid_command() async def removeword(self, ctx, word: str): """Remove a word from the filter list.""" - async with self.config.words() as words: - if word in words: - words.remove(word) - await ctx.send(f"Removed `{word}` from the filter list.") - else: - await ctx.send(f"`{word}` was not found in the filter list.") + self.storage.remove("words", word) + await ctx.send(f"Removed `{word}` from the filter list.") @commands.hybrid_command() async def listwords(self, ctx): """List all words in the filter.""" - words = await self.config.words() + words = self.storage.get("words") await ctx.send(f"Filtered words: {', '.join(words) if words else 'None'}") @commands.hybrid_command() async def clearwords(self, ctx): """Clear all words from the filter list.""" - await self.config.words.set([]) + self.storage.clear("words") await ctx.send("All filtered words have been cleared.") @commands.hybrid_command() - async def importconfig(self, ctx, file: discord.Attachment): - """Import a config file.""" - if file.filename.endswith(".json"): - try: - data = await file.read() - config_data = json.loads(data.decode("utf-8")) - async with self.config.all() as config: - for key in config.keys(): - if key in config_data: - config[key] = config_data[key] - await ctx.send("Config imported successfully.") - except Exception as e: - await ctx.send(f"Failed to import config: {str(e)}") - else: - await ctx.send("Please upload a JSON file.") - - @commands.hybrid_command() - async def exportconfig(self, ctx): - """Export the current config as a JSON file.""" - config_data = await self.config.all() - file = discord.File(io.BytesIO(json.dumps(config_data, indent=4).encode()), filename="config.json") - await ctx.send("Here is the current configuration:", file=file) - - @commands.hybrid_command() - async def togglelogging(self, ctx): - """Toggle logging on or off.""" - current = await self.config.logFiltered() - await self.config.logFiltered.set(not current) - await ctx.send(f"Logging is now {'enabled' if not current else 'disabled'}.") - - @commands.hybrid_command() - async def setmuteoffense(self, ctx, number: int): - """Set the number of offenses before muting a user.""" - await self.config.muteAfterOffenseNumber.set(number) - await ctx.send(f"Users will now be muted after {number} offenses.") + async def setlogchannel(self, ctx, channel: discord.TextChannel): + """Set the logging channel.""" + await self.config.logChannelId.set(channel.id) + await ctx.send(f"Log channel set to {channel.mention}") @commands.hybrid_command() async def listautomodrules(self, ctx): """List all AutoMod rules in the server.""" guild = ctx.guild if guild: - rules = await guild.automod_rules() + rules = await guild.fetch_automod_rules() rule_names = [rule.name for rule in rules] await ctx.send(f"AutoMod Rules: {', '.join(rule_names) if rule_names else 'None'}") else: