forked from rejnronuz/muzovkant-cogdump
react to keyword with message
This commit is contained in:
106
cogs/autoreply/autoreply.py
Normal file
106
cogs/autoreply/autoreply.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import discord
|
||||
from discord.ext import commands
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_PATH = os.path.join(os.path.dirname(__file__), "config.json")
|
||||
DATA_PATH = os.path.join(os.path.dirname(__file__), "replies.json")
|
||||
|
||||
|
||||
def load_json(path: str) -> dict:
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def save_json(path: str, data: dict) -> None:
|
||||
with open(path, "w", encoding="utf-8") as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||||
|
||||
|
||||
class AutoReply(commands.Cog):
|
||||
def __init__(self, bot: commands.Bot):
|
||||
self.bot = bot
|
||||
self.config: dict = {}
|
||||
self.rules: list[dict] = []
|
||||
|
||||
async def cog_load(self):
|
||||
self._load_config()
|
||||
self._load_rules()
|
||||
|
||||
def _load_config(self):
|
||||
try:
|
||||
self.config = load_json(CONFIG_PATH)
|
||||
except (FileNotFoundError, json.JSONDecodeError) as e:
|
||||
logger.error("[AutoReply] config error: %s", e)
|
||||
|
||||
def _load_rules(self):
|
||||
try:
|
||||
self.rules = load_json(DATA_PATH).get("rules", [])
|
||||
logger.info("[AutoReply] %d rules loaded.", len(self.rules))
|
||||
except FileNotFoundError:
|
||||
self.rules = []
|
||||
save_json(DATA_PATH, {"rules": []})
|
||||
except json.JSONDecodeError as e:
|
||||
logger.error("[AutoReply] replies.json parse error: %s", e)
|
||||
|
||||
def _save_rules(self):
|
||||
save_json(DATA_PATH, {"rules": self.rules})
|
||||
|
||||
def _match(self, rule: dict, content: str) -> bool:
|
||||
mode = rule.get("match_mode", "contains")
|
||||
case_sensitive = rule.get("case_sensitive", False)
|
||||
text = content if case_sensitive else content.lower()
|
||||
|
||||
for kw in rule.get("keywords", []):
|
||||
kw_cmp = kw if case_sensitive else kw.lower()
|
||||
if mode == "exact" and text == kw_cmp: return True
|
||||
if mode == "contains" and kw_cmp in text: return True
|
||||
if mode == "startswith" and text.startswith(kw_cmp): return True
|
||||
if mode == "regex":
|
||||
flags = 0 if case_sensitive else re.IGNORECASE
|
||||
if re.search(kw, content, flags): return True
|
||||
return False
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message: discord.Message):
|
||||
if message.author.bot or not message.guild:
|
||||
return
|
||||
|
||||
for rule in self.rules:
|
||||
if not rule.get("enabled", True):
|
||||
continue
|
||||
if self._match(rule, message.content):
|
||||
await message.channel.send(rule["reply"])
|
||||
if not self.config.get("match_all", False):
|
||||
break
|
||||
|
||||
@commands.command(name="add_rule")
|
||||
@commands.has_permissions(administrator=True)
|
||||
async def add_rule(self, ctx: commands.Context, keywords: str, *, reply: str):
|
||||
# add rules
|
||||
rule = {
|
||||
"keywords": [k.strip() for k in keywords.split(",")],
|
||||
"match_mode": "contains",
|
||||
"case_sensitive": False,
|
||||
"reply": reply,
|
||||
"enabled": True,
|
||||
}
|
||||
self.rules.append(rule)
|
||||
self._save_rules()
|
||||
kws = ", ".join(f"`{k}`" for k in rule["keywords"])
|
||||
await ctx.send(f"Rule added")
|
||||
|
||||
@add_rule.error
|
||||
async def add_rule_error(self, ctx: commands.Context, error):
|
||||
if isinstance(error, commands.MissingPermissions):
|
||||
await ctx.send("Шпацируй нахуй отсюда")
|
||||
elif isinstance(error, commands.MissingRequiredArgument):
|
||||
await ctx.send("Wrong usage")
|
||||
|
||||
|
||||
async def setup(bot: commands.Bot):
|
||||
await bot.add_cog(AutoReply(bot))
|
||||
8
cogs/autoreply/config.json
Normal file
8
cogs/autoreply/config.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"description": "Usage is admin-only; Reacts to messages containing keywords with a configured reply",
|
||||
"usages": [
|
||||
"!add_rule <keyword1,keyword2,...> <reply>"
|
||||
],
|
||||
"hidden": false,
|
||||
"match_all": false
|
||||
}
|
||||
18
cogs/autoreply/replies.json
Normal file
18
cogs/autoreply/replies.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": [
|
||||
{
|
||||
"keywords": ["ping", "pong"],
|
||||
"match_mode": "contains",
|
||||
"case_sensitive": false,
|
||||
"reply": "Pong",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"keywords": ["kitty", "cat", "IMMEDIATE CAT REQUEST!!!!!!"],
|
||||
"match_mode": "contains",
|
||||
"case_sensitive": false,
|
||||
"reply": "https://cataas.com/cat",
|
||||
"enabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user