update black_word

This commit is contained in:
HibiKier 2022-05-01 15:53:52 +08:00
parent b0ab78340a
commit 56573d1d34
13 changed files with 886 additions and 137 deletions

1
.gitignore vendored
View File

@ -142,6 +142,5 @@ test.py
server_ip.py
member_activity_handle.py
Yu-Gi-Oh/
black_word/
csgo/
fantasy_card/

View File

@ -242,6 +242,11 @@ __Docker 最新版本由 [Sakuracio](https://github.com/Sakuracio) 提供__
## 更新
### 2022/5/1
* 删除了`group_last_chat`插件(该功能可由`chat_history`替代
* 新增敏感词检测(全新反击系统,是时候重拳出击了
### 2022/4/26
* 修复了群白名单无法正确添加

View File

@ -42,7 +42,7 @@ __plugin_settings__ = {
}
msg_handler = on_regex(r"(周|月)?消息统计(des|DES)?(n=[0-9]{1,2})?", priority=5, block=True)
msg_handler = on_regex(r"^(周|月)?消息统计(des|DES)?(n=[0-9]{1,2})?$", priority=5, block=True)
@msg_handler.handle()

View File

@ -277,7 +277,7 @@ def _create_help_img(
0,
plain_text=msg,
font_size=24,
font="yuanshen.ttf",
font="HYWenHei-85W.ttf",
)
B.paste(text, (w, h), True)
h += 50
@ -289,7 +289,7 @@ def _create_help_img(
0,
plain_text="注: 红字代表功能被群管理员禁用,红线代表功能正在维护",
font_size=24,
font="yuanshen.ttf",
font="HYWenHei-85W.ttf",
font_color=(231, 74, 57)
),
(300, 10),

View File

@ -126,35 +126,39 @@ async def xie_ai(text: str) -> str:
"""
res = await AsyncHttpx.get(f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}")
content = ""
data = json.loads(res.text)
if data["result"] == 0:
content = data["content"]
if "菲菲" in content:
content = content.replace("菲菲", NICKNAME)
if "艳儿" in content:
content = content.replace("艳儿", NICKNAME)
if "公众号" in content:
content = ""
if "{br}" in content:
content = content.replace("{br}", "\n")
if "提示" in content:
content = content[: content.find("提示")]
if "淘宝" in content or "taobao.com" in content:
return ""
while True:
r = re.search("{face:(.*)}", content)
if r:
id_ = r.group(1)
content = content.replace(
"{" + f"face:{id_}" + "}", str(face(int(id_)))
)
else:
break
return (
content
if not content and not Config.get_config("ai", "ALAPI_AI_CHECK")
else await check_text(content)
)
try:
data = json.loads(res.text)
if data["result"] == 0:
content = data["content"]
if "菲菲" in content:
content = content.replace("菲菲", NICKNAME)
if "艳儿" in content:
content = content.replace("艳儿", NICKNAME)
if "公众号" in content:
content = ""
if "{br}" in content:
content = content.replace("{br}", "\n")
if "提示" in content:
content = content[: content.find("提示")]
if "淘宝" in content or "taobao.com" in content:
return ""
while True:
r = re.search("{face:(.*)}", content)
if r:
id_ = r.group(1)
content = content.replace(
"{" + f"face:{id_}" + "}", str(face(int(id_)))
)
else:
break
return (
content
if not content and not Config.get_config("ai", "ALAPI_AI_CHECK")
else await check_text(content)
)
except Exception as e:
logger.error(f"Ai xie_ai 发生错误 {type(e)}{e}")
return ""
def hello() -> str:

View File

@ -0,0 +1,249 @@
from nonebot.adapters.onebot.v11 import (
Event,
MessageEvent,
GroupMessageEvent,
Message,
Bot,
)
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor
from utils.image_utils import BuildImage
from utils.utils import get_message_text, is_number
from nonebot.params import RegexGroup, CommandArg
from .utils import black_word_manager
from nonebot import on_command, on_message, on_regex
from configs.config import Config, NICKNAME
from nonebot.permission import SUPERUSER
from .data_source import show_black_text_image, set_user_punish
from services.log import logger
from models.ban_user import BanUser
from datetime import datetime
from utils.message_builder import image
from .model import BlackWord
from typing import Tuple, Any
__zx_plugin_name__ = "敏感词检测"
__plugin_usage__ = """
usage
注意你的发言
指令
惩罚机制
""".strip()
__plugin_superuser_usage__ = """
usage
查看和设置惩罚
Regex^记录名单(u:\d*)?(g:\d*)?(d[=><]\d*-\d{1,2}-\d{1,2})?$
设置惩罚id需要通过 '记录名单u:xxxxxxxx' 获取
指令
记录名单
设置惩罚 [user_id] [id] [punish_level]
示例记录名单
示例记录名单u:12345678
示例设置惩罚 12345678 1 4
""".strip()
__plugin_des__ = "请注意你的发言!!"
__plugin_type__ = ("其他",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_cmd__ = ["惩罚机制", "记录名单 [_superuser]", "设置惩罚 [_superuser]"]
__plugin_settings__ = {
"cmd": ["敏感词检测"],
}
Config.add_plugin_config(
"black_word", "CYCLE_DAYS", 30, name="敏感词检测与惩罚", help_="黑名单词汇记录周期", default_value=30
)
Config.add_plugin_config(
"black_word",
"TOLERATE_COUNT",
[5, 1, 1, 1, 1],
help_="各个级别惩罚的容忍次数依次为1, 2, 3, 4, 5",
default_value=[5, 1, 1, 1, 1],
)
Config.add_plugin_config(
"black_word", "AUTO_PUNISH", True, help_="是否启动自动惩罚机制", default_value=True
)
# Config.add_plugin_config(
# "black_word", "IGNORE_GROUP", [], help_="退出群聊惩罚中忽略的群聊,即不会退出的群聊", default_value=[]
# )
Config.add_plugin_config(
"black_word",
"BAN_4_DURATION",
360,
help_="Union[int, List[int, int]]Ban时长分钟四级惩罚可以为指定数字或指定列表区间(随机),例如 [30, 360]",
default_value=360,
)
Config.add_plugin_config(
"black_word",
"BAN_3_DURATION",
7,
help_="Union[int, List[int, int]]Ban时长三级惩罚可以为指定数字或指定列表区间(随机),例如 [7, 30]",
default_value=360,
)
Config.add_plugin_config(
"black_word",
"WARNING_RESULT",
f"请注意对{NICKNAME}的发言内容",
help_="口头警告内容",
default_value=f"请注意对{NICKNAME}的发言内容",
)
Config.add_plugin_config(
"black_word",
"AUTO_ADD_PUNISH_LEVEL",
True,
help_="自动提级机制,当周期内处罚次数大于某一特定值就提升惩罚等级",
default_value=True,
)
Config.add_plugin_config(
"black_word",
"ADD_PUNISH_LEVEL_TO_COUNT",
3,
help_="在CYCLE_DAYS周期内触发指定惩罚次数后提升惩罚等级",
default_value=3,
)
Config.add_plugin_config(
"black_word",
"ALAPI_CHECK_FLAG",
False,
help_="当未检测到已收录的敏感词时开启ALAPI文本检测并将疑似文本发送给超级用户",
default_value=False,
)
Config.add_plugin_config(
"black_word",
"CONTAIN_BLACK_STOP_PROPAGATION",
True,
help_="当文本包含任意敏感词时停止向下级插件传递即不触发ai",
default_value=True,
)
message_matcher = on_message(priority=1, block=False)
set_punish = on_command("设置惩罚", priority=1, permission=SUPERUSER, block=True)
show_black = on_regex(
r"^记录名单(u:\d*)?(g:\d*)?(d[=><]\d*-\d{1,2}-\d{1,2})?$",
priority=1,
permission=SUPERUSER,
block=True,
)
show_punish = on_command("惩罚机制", aliases={"敏感词检测"}, priority=1, block=True)
# 黑名单词汇检测
@run_preprocessor
async def _(
bot: Bot,
matcher: Matcher,
event: Event,
):
if (
isinstance(event, MessageEvent)
and event.is_tome()
and matcher.plugin_name == "black_word"
and not await BanUser.is_ban(event.user_id)
and str(event.user_id) not in bot.config.superusers
):
user_id = event.user_id
group_id = event.group_id if isinstance(event, GroupMessageEvent) else None
msg = get_message_text(event.json())
if await black_word_manager.check(user_id, group_id, msg) and Config.get_config(
"black_word", "CONTAIN_BLACK_STOP_PROPAGATION"
):
matcher.stop_propagation()
@show_black.handle()
async def _(bot: Bot, reg_group: Tuple[Any, ...] = RegexGroup()):
user_id, group_id, date = reg_group
date_type = "="
if date:
date_type = date[1]
date = date[2:]
try:
date = datetime.strptime(date, "%Y-%m-%d")
except ValueError:
await show_black.finish("日期格式错误,需要:年-月-日")
pic = await show_black_text_image(
bot,
int(user_id.split(":")[1]) if user_id else None,
int(group_id.split(":")[1]) if group_id else None,
date,
date_type,
)
await show_black.send(image(b64=pic.pic2bs4()))
@show_punish.handle()
async def _():
text = f"""
** 惩罚机制 **
惩罚前包含容忍机制在指定周期内会容忍偶尔少次数的敏感词只会进行警告提醒
多次触发同级惩罚会使惩罚等级提高即惩罚自动提级机制
目前公开的惩罚等级
1永久ban
2删除好友
3ban指定/随机天数
4ban指定/随机时长
5警告
备注
该功能为测试阶段如果你有被误封情况请联系管理员会从数据库中提取出你的数据进行审核后判断
目前该功能暂不完善部分情况会由管理员鉴定请注意对真寻的发言
关于敏感词
记住不要骂{NICKNAME}就对了
""".strip()
max_width = 0
for m in text.split("\n"):
max_width = len(m) * 20 if len(m) * 20 > max_width else max_width
max_height = len(text.split("\n")) * 24
A = BuildImage(
max_width, max_height, font="CJGaoDeGuo.otf", font_size=24, color="#E3DBD1"
)
A.text((10, 10), text)
await show_punish.send(image(b64=A.pic2bs4()))
@set_punish.handle()
async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip().split()
if (
len(msg) < 3
or not is_number(msg[0])
or not is_number(msg[1])
or not is_number(msg[2])
):
await set_punish.finish("参数错误,请查看帮助...", at_sender=True)
uid = int(msg[0])
id_ = int(msg[1])
punish_level = int(msg[2])
print(uid, id_, punish_level)
rst = await set_user_punish(uid, id_, punish_level)
await set_punish.send(rst)
logger.info(
f"USER {event.user_id} 设置惩罚 uid{uid} id_{id_} punish_level:{punish_level} --> {rst}"
)

View File

@ -0,0 +1,118 @@
from nonebot.adapters.onebot.v11 import Bot
from utils.image_utils import BuildImage, text2image
from services.log import logger
from typing import Optional
from datetime import datetime
from .model import BlackWord
from .utils import _get_punish, Config
async def show_black_text_image(
bot: Bot,
user: Optional[int],
group_id: Optional[int],
date: Optional[datetime],
data_type: str = "=",
) -> BuildImage:
"""
展示记录名单
:param bot: bot
:param user: 用户qq
:param group_id: 群聊
:param date: 日期
:param data_type: 日期搜索类型
:return:
"""
data = await BlackWord.get_black_data(user, group_id, date, data_type)
A = BuildImage(0, 0, color="#f9f6f2", font_size=20)
image_list = []
friend_str = await bot.get_friend_list()
id_str = ""
uname_str = ""
uid_str = ""
gid_str = ""
plant_text_str = ""
black_word_str = ""
punish_str = ""
punish_level_str = ""
create_time_str = ""
for i, x in enumerate(data):
try:
if x.group_id:
user_name = (
await bot.get_group_member_info(
group_id=x.group_id, user_id=x.user_qq
)
)["card"]
else:
user_name = [
u["nickname"] for u in friend_str if u["user_id"] == x.user_qq
][0]
except Exception as e:
logger.warning(
f"show_black_text_image 获取 USER {x.user_qq} user_name 失败 {type(e)}{e}"
)
user_name = x.user_qq
id_str += f"{i}\n"
uname_str += f"{user_name}\n"
uid_str += f"{x.user_qq}\n"
gid_str += f"{x.group_id}\n"
plant_text = " ".join(x.plant_text.split("\n"))
if A.getsize(plant_text)[0] > 200:
plant_text = plant_text[:20] + "..."
plant_text_str += f"{plant_text}\n"
black_word_str += f"{x.black_word}\n"
punish_str += f"{x.punish}\n"
punish_level_str += f"{x.punish_level}\n"
create_time_str += f"{x.create_time.replace(microsecond=0)}\n"
_tmp_img = BuildImage(0, 0, font_size=35, font="CJGaoDeGuo.otf")
for s, type_ in [
(id_str, "Id"),
(uname_str, "昵称"),
(uid_str, "UID"),
(gid_str, "GID"),
(plant_text_str, "文本"),
(black_word_str, "检测"),
(punish_str, "惩罚"),
(punish_level_str, "等级"),
(create_time_str, "记录日期"),
]:
img = await text2image(s, color="#f9f6f2", _add_height=3.32)
w = _tmp_img.getsize(type_)[0] if _tmp_img.getsize(type_)[0] > img.w else img.w
A = BuildImage(w + 11, img.h + 50, color="#f9f6f2", font_size=35, font="CJGaoDeGuo.otf")
await A.atext((10, 10), type_)
await A.apaste(img, (0, 50))
image_list.append(A)
horizontal_line = []
w, h = 0, 0
for img in image_list:
w += img.w + 20
h = img.h if img.h > h else h
horizontal_line.append(img.w)
A = BuildImage(w, h, color="#f9f6f2")
current_w = 0
for img in image_list:
await A.apaste(img, (current_w, 0))
current_w += img.w + 20
return A
async def set_user_punish(user_id: int, id_: int, punish_level: int) -> str:
"""
设置惩罚
:param user_id: 用户id
:param id_: 记录下标
:param punish_level: 惩罚等级
"""
result = await _get_punish(punish_level, user_id)
punish = {
1: "永久ban",
2: "删除好友",
3: f"ban {result}",
4: f"ban {result} 分钟",
5: "口头警告"
}
if await BlackWord.set_user_punish(user_id, punish[punish_level], id_=id_):
return f"已对 USER {user_id} 进行 {punish[punish_level]} 处罚。"
else:
return "操作失败可能未找到用户id或敏感词"

149
plugins/black_word/model.py Normal file
View File

@ -0,0 +1,149 @@
from services.db_context import db
from typing import Optional, List
from datetime import datetime, timedelta
class BlackWord(db.Model):
__tablename__ = "black_word"
id = db.Column(db.Integer(), primary_key=True, autoincrement=True)
user_qq = db.Column(db.BigInteger(), nullable=False, primary_key=True)
group_id = db.Column(db.BigInteger())
plant_text = db.Column(db.String())
black_word = db.Column(db.String())
punish = db.Column(db.String(), default="")
punish_level = db.Column(db.Integer())
create_time = db.Column(db.DateTime(timezone=True), nullable=False)
@classmethod
async def add_user_black_word(
cls,
user_qq: int,
group_id: Optional[int],
black_word: str,
plant_text: str,
punish_level: int,
):
"""
说明
添加用户发送的敏感词
参数
:param user_qq: 用户id
:param group_id: 群号
:param black_word: 黑名单词汇
:param plant_text: 消息文本
:param punish_level: 惩罚等级
"""
await cls.create(
user_qq=user_qq,
group_id=group_id,
plant_text=plant_text,
black_word=black_word,
punish_level=punish_level,
create_time=datetime.now(),
)
@classmethod
async def set_user_punish(
cls,
user_qq: int,
punish: str,
black_word: Optional[str] = None,
id_: Optional[int] = None,
) -> bool:
"""
说明
设置处罚
参数
:param user_qq: 用户id
:param punish: 处罚
:param black_word: 黑名单词汇
:param id_: 记录下标
"""
user = None
if (not black_word and not id_) or not punish:
return False
query = cls.query.where(cls.user_qq == user_qq).with_for_update()
if black_word:
user = await query.where(cls.black_word == black_word).order_by(cls.id.desc()).gino.first()
elif id_:
user_list = await query.gino.all()
print(len(user_list))
if len(user_list) == 0 or (id_ < 0 or id_ > len(user_list)):
return False
user = user_list[id_]
if not user:
return False
await user.update(punish=cls.punish + punish + " ").apply()
return True
@classmethod
async def get_user_count(
cls, user_qq: int, days: int = 7, punish_level: Optional[int] = None
) -> int:
"""
说明
获取用户规定周期内的犯事次数
参数
:param user_qq: 用户qq
:param days: 周期天数
:param punish_level: 惩罚等级
"""
setattr(BlackWord, "count", db.func.count(cls.id).label("count"))
query = cls.select("count").where(
(cls.user_qq == user_qq)
& (cls.punish_level != -1)
& (cls.create_time > datetime.now() - timedelta(days=days))
)
if punish_level is not None:
query = query.where(cls.punish_level == punish_level)
return (await query.gino.first())[0]
@classmethod
async def get_user_punish_level(cls, user_qq: int, days: int = 7) -> Optional[int]:
"""
说明
获取用户最近一次的惩罚记录等级
参数
:param user_qq: 用户qq
:param days: 周期天数
"""
if (
query := await cls.query.where(cls.user_qq == user_qq)
.where(cls.create_time > datetime.now() - timedelta(days=days))
.order_by(cls.id.desc())
.gino.first()
):
return query.punish_level
return None
@classmethod
async def get_black_data(
cls,
user_qq: Optional[int],
group_id: Optional[int],
date: Optional[datetime],
date_type: str = "=",
) -> List["BlackWord"]:
"""
说明
通过指定条件查询数据
参数
:param user_qq: 用户qq
:param group_id: 群号
:param date: 日期
:param date_type: 日期查询类型
"""
query = cls.query
if user_qq:
query = query.where(cls.user_qq == user_qq)
if group_id:
query = query.where(cls.group_id == group_id)
if date:
if date_type == "=":
query = query.where(cls.create_time == date)
elif date_type == ">":
query = query.where(cls.create_time > date)
elif date_type == "<":
query = query.where(cls.create_time < date)
return await query.gino.all()

324
plugins/black_word/utils.py Normal file
View File

@ -0,0 +1,324 @@
from utils.utils import cn2py, get_bot
from configs.path_config import DATA_PATH
from typing import Optional, Union, Tuple
from .model import BlackWord
from configs.config import Config
from pathlib import Path
from services.log import logger
from models.ban_user import BanUser
from nonebot.adapters.onebot.v11.exception import ActionFailed
from models.group_member_info import GroupInfoUser
from utils.http_utils import AsyncHttpx
import random
try:
import ujson as json
except ModuleNotFoundError:
import json
class BlackWordManager:
"""
敏感词管理 拒绝恶意
"""
def __init__(self, word_file: Path, py_file: Path):
self._word_list = {
"1": [],
"2": [],
"3": [],
"4": ["sb", "nmsl", "mdzz", "2b", "jb", "", "废物", "憨憨", "cnm", "rnm"],
"5": [],
}
self._py_list = {
"1": [],
"2": [],
"3": [],
"4": [
"shabi",
"wocaonima",
"sima",
"sabi",
"zhizhang",
"naocan",
"caonima",
"rinima",
"simadongxi",
"simawanyi",
"hanbi",
"hanpi",
"laji",
"fw"
],
"5": [],
}
word_file.parent.mkdir(parents=True, exist_ok=True)
if word_file.exists():
# 清空默认配置
with open(word_file, "r", encoding="utf8") as f:
self._word_list = json.load(f)
else:
with open(word_file, "w", encoding="utf8") as f:
json.dump(
self._word_list,
f,
ensure_ascii=False,
indent=4,
)
if py_file.exists():
# 清空默认配置
with open(py_file, "r", encoding="utf8") as f:
self._py_list = json.load(f)
else:
with open(py_file, "w", encoding="utf8") as f:
json.dump(
self._py_list,
f,
ensure_ascii=False,
indent=4,
)
async def check(
self, user_id: int, group_id: Optional[int], message: str
) -> Optional[Union[str, bool]]:
"""
检查是否包含黑名单词汇
:param user_id: 用户id
:param group_id: 群号
:param message: 消息
"""
print(user_id, group_id, message)
if data := self._check(message):
print(data)
if data[0]:
await _add_user_black_word(
user_id, group_id, data[0], message, int(data[1])
)
return True
if Config.get_config(
"black_word", "ALAPI_CHECK_FLAG"
) and not await check_text(message):
await send_msg(
0, None, f"USER {user_id} GROUP {group_id} ALAPI 疑似检测:{message}"
)
return False
def _check(self, message: str) -> Tuple[Optional[str], int]:
"""
检测文本是否违规
:param message: 检测消息
"""
# 移除空格
message = message.replace(" ", "")
py_msg = cn2py(message).lower()
# 完全匹配
for x in [self._word_list, self._py_list]:
for level in x:
if message in x[level] or py_msg in x[level]:
return message if message in x[level] else py_msg, level
# 模糊匹配
for x in [self._word_list, self._py_list]:
for level in x:
for m in x[level]:
if m in message or m in py_msg:
return m, -1
return None, 0
async def _add_user_black_word(
user_id: int,
group_id: Optional[int],
black_word: str,
message: str,
punish_level: int,
):
"""
添加敏感词数据
:param user_id: 用户id
:param group_id: 群号
:param black_word: 触发的黑名单词汇
:param message: 原始文本
:param punish_level: 惩罚等级
"""
cycle_days = Config.get_config("black_word", "CYCLE_DAYS") or 7
user_count = await BlackWord.get_user_count(user_id, cycle_days, punish_level)
# 周期内超过次数直接提升惩罚
if Config.get_config(
"black_word", "AUTO_ADD_PUNISH_LEVEL"
) and user_count > Config.get_config("black_word", "ADD_PUNISH_LEVEL_TO_COUNT"):
punish_level -= 1
await BlackWord.add_user_black_word(
user_id, group_id, black_word, message, punish_level
)
logger.info(
f"已将 USER {user_id} GROUP {group_id} 添加至黑名单词汇记录 Black_word{black_word} Plant_text{message}"
)
# 自动惩罚
if Config.get_config("black_word", "AUTO_PUNISH") and punish_level != -1:
await _punish_handle(user_id, group_id, punish_level, black_word)
async def _punish_handle(
user_id: int, group_id: Optional[int], punish_level: int, black_word: str
):
"""
惩罚措施级别越低惩罚越严
:param user_id: 用户id
:param group_id: 群号
:param black_word: 触发的黑名单词汇
"""
logger.info(f"BlackWord USER {user_id} 触发 {punish_level} 级惩罚...")
# 周期天数
cycle_days = Config.get_config("black_word", "CYCLE_DAYS") or 7
# 用户周期内触发punish_level级惩罚的次数
user_count = await BlackWord.get_user_count(user_id, cycle_days, punish_level)
# 获取最近一次的惩罚等级,将在此基础上增加
punish_level = await BlackWord.get_user_punish_level(user_id, cycle_days) or punish_level
# 容忍次数List[int]
tolerate_count = Config.get_config("black_word", "TOLERATE_COUNT")
if not tolerate_count or len(tolerate_count) < 5:
tolerate_count = [5, 2, 2, 2, 2]
if punish_level == 1 and user_count > tolerate_count[punish_level - 1]:
# 永久ban
await _get_punish(1, user_id, group_id)
await BlackWord.set_user_punish(user_id, "永久ban 删除好友", black_word)
elif punish_level == 2 and user_count > tolerate_count[punish_level - 1]:
# 删除好友
await _get_punish(2, user_id, group_id)
await BlackWord.set_user_punish(user_id, "删除好友", black_word)
elif punish_level == 3 and user_count > tolerate_count[punish_level - 1]:
# 永久ban
ban_day = await _get_punish(3, user_id, group_id)
await BlackWord.set_user_punish(user_id, f"ban {ban_day}", black_word)
elif punish_level == 4 and user_count > tolerate_count[punish_level - 1]:
# ban指定时长
ban_time = await _get_punish(4, user_id, group_id)
await BlackWord.set_user_punish(user_id, f"ban {ban_time} 分钟", black_word)
elif punish_level == 5 and user_count > tolerate_count[punish_level - 1]:
# 口头警告
warning_result = await _get_punish(5, user_id, group_id)
await BlackWord.set_user_punish(user_id, f"口头警告:{warning_result}", black_word)
else:
await BlackWord.set_user_punish(user_id, f"提示!", black_word)
await send_msg(
user_id,
group_id,
f"BlackWordChecker该条发言已被记录目前你在{cycle_days}天内的发表{punish_level}"
f"言论记录次数为:{user_count}次,请注意你的发言\n"
f"* 如果你不清楚惩罚机制,请发送“惩罚机制” *",
)
async def _get_punish(
id_: int, user_id: int, group_id: Optional[int] = None
) -> Optional[Union[int, str]]:
"""
通过id_获取惩罚
:param id_: id
:param user_id: 用户id
:param group_id: 群号
"""
bot = get_bot()
# 忽略的群聊
# _ignore_group = Config.get_config("black_word", "IGNORE_GROUP")
# 处罚 id 4 ban 时间intList[int]
ban_3_duration = Config.get_config("black_word", "BAN_3_DURATION")
# 处罚 id 4 ban 时间intList[int]
ban_4_duration = Config.get_config("black_word", "BAN_4_DURATION")
# 口头警告内容
warning_result = Config.get_config("black_word", "WARNING_RESULT")
try:
uname = (await GroupInfoUser.get_member_info(user_id, group_id)).user_name
except AttributeError:
uname = user_id
# 永久ban
if id_ == 1:
if str(user_id) not in bot.config.superusers:
await BanUser.ban(user_id, 10, 99999999)
await send_msg(user_id, group_id, f"BlackWordChecker 永久ban USER {uname}({user_id})")
logger.info(f"BlackWord 永久封禁 USER {user_id}...")
# 删除好友(有的话
elif id_ == 2:
if str(user_id) not in bot.config.superusers:
try:
await bot.delete_friend(user_id=user_id)
await send_msg(
user_id, group_id, f"BlackWordChecker 删除好友 USER {uname}({user_id})"
)
logger.info(f"BlackWord 删除好友 {user_id}...")
except ActionFailed:
pass
# 封禁用户指定时间默认7天
elif id_ == 3:
if isinstance(ban_3_duration, list):
ban_3_duration = random.randint(ban_3_duration[0], ban_3_duration[1])
await BanUser.ban(user_id, 9, ban_4_duration * 60 * 60 * 24)
await send_msg(
user_id,
group_id,
f"BlackWordChecker 对用户 USER {uname}({user_id}) 进行封禁 {ban_3_duration} 天处罚。",
)
logger.info(f"BlackWord 封禁 USER {uname}({user_id}) {ban_3_duration} 天...")
return ban_3_duration
# 封禁用户指定时间默认360分钟
elif id_ == 4:
if isinstance(ban_4_duration, list):
ban_4_duration = random.randint(ban_4_duration[0], ban_4_duration[1])
await BanUser.ban(user_id, 9, ban_4_duration * 60)
await send_msg(
user_id,
group_id,
f"BlackWordChecker 对用户 USER {uname}({user_id}) 进行封禁 {ban_4_duration} 分钟处罚。",
)
logger.info(f"BlackWord 封禁 USER {uname}({user_id}) {ban_4_duration} 分钟...")
return ban_4_duration
# 口头警告
elif id_ == 5:
if group_id:
await bot.send_group_msg(group_id=group_id, message=warning_result)
else:
await bot.send_private_msg(user_id=user_id, message=warning_result)
logger.info(f"BlackWord 口头警告 USER {user_id}")
return warning_result
return None
async def send_msg(user_id: int, group_id: Optional[int], message: str):
"""
发送消息
:param user_id: user_id
:param group_id: group_id
:param message: message
"""
bot = get_bot()
if not user_id:
user_id = int(list(bot.config.superusers)[0])
if group_id:
await bot.send_group_msg(group_id=group_id, message=message)
else:
await bot.send_private_msg(user_id=user_id, message=message)
async def check_text(text: str) -> bool:
"""
ALAPI文本检测检测输入违规
:param text: 回复
"""
if not Config.get_config("alapi", "ALAPI_TOKEN"):
return True
params = {"token": Config.get_config("alapi", "ALAPI_TOKEN"), "text": text}
try:
data = (
await AsyncHttpx.get(
"https://v2.alapi.cn/api/censor/text", timeout=4, params=params
)
).json()
if data["code"] == 200:
return data["data"]["conclusion_type"] == 2
except Exception as e:
logger.error(f"检测违规文本错误...{type(e)}{e}")
return True
black_word_manager = BlackWordManager(DATA_PATH / "black_word" / "black_word.json", DATA_PATH / "black_word" / "black_py.json")

View File

@ -1,34 +0,0 @@
from nonebot import on_message
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from .data_source import cancel_all_notice, save_data, get_data, set_data_value
from services.log import logger
import time
__zx_plugin_name__ = "群聊最后聊天时间记录 [Hidden]"
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
last_chat = on_message(priority=1, block=False, permission=GROUP)
@last_chat.handle()
async def _(event: GroupMessageEvent):
time_data = await get_data()
set_data_value(event.group_id, time.time())
if event.group_id in time_data["_group"]:
time_data["_group"].remove(event.group_id)
set_data_value("_group", time_data["_group"])
for key in time_data.keys():
if key not in ["check_time", "_group"]:
if key not in time_data["_group"]:
if time.time() - time_data[key] > 60 * 60 * 36:
await cancel_all_notice(key)
time_data["_group"].append(key)
set_data_value("_group", time_data["_group"])
logger.info(f"GROUP {event.group_id} 因群内发言时间大于36小时被取消全部通知")
if time.time() - time_data["check_time"] > 60 * 60 * 1:
set_data_value("check_time", time.time())
save_data()

View File

@ -1,67 +0,0 @@
from configs.path_config import DATA_PATH
from utils.utils import get_bot
from datetime import datetime
import time
from services.log import logger
from utils.manager import group_manager
try:
import ujson as json
except ModuleNotFoundError:
import json
time_data = {}
async def init():
global time_data
bot = get_bot()
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
data = read_data("group_last_chat_time.json")
for g in gl:
if not data.get(g):
time_data[g] = time.time()
if not time_data.get("check_time"):
time_data["check_time"] = time.time()
if not time_data.get("_group"):
time_data["_group"] = []
save_data()
return time_data
def read_data(file_name: str):
try:
with open(DATA_PATH / file_name, "r", encoding="utf8") as f:
return json.load(f)
except (ValueError, FileNotFoundError):
return {}
def save_data():
with open(DATA_PATH / "group_last_chat_time.json", "w") as f:
json.dump(time_data, f, indent=4)
logger.info(
f'自动存储 group_last_chat_time.json 时间:{str(datetime.now()).split(".")[0]}'
)
# 取消全部通知
async def cancel_all_notice(group_id):
group_id = int(group_id)
for command in group_manager.get_task_data():
if await group_manager.check_group_task_status(group_id, command):
await group_manager.close_group_task(group_id, command)
logger.info(f"关闭了 {group_id} 群的全部通知")
async def get_data():
global time_data
if not time_data:
time_data = await init()
return time_data
def set_data_value(key, value):
global time_data
time_data[key] = value

View File

View File

@ -1336,6 +1336,7 @@ async def text2image(
font: str = "CJGaoDeGuo.otf",
font_color: Union[str, Tuple[int, int, int]] = "black",
padding: Union[int, Tuple[int, int, int, int]] = 0,
_add_height: float = 0,
) -> BuildImage:
"""
说明
@ -1358,6 +1359,7 @@ async def text2image(
:param font: 普通字体
:param font_color: 普通字体颜色
:param padding: 文本外边距元组类型时为
:param _add_height: 由于get_size无法返回正确的高度采用手动方式额外添加高度
"""
pw = ph = top_padding = left_padding = 0
if padding:
@ -1489,17 +1491,17 @@ async def text2image(
else:
width = 0
height = 0
_tmp = BuildImage(0, 0, font_size=font_size)
_tmp = BuildImage(0, 0, font=font, font_size=font_size)
for x in text.split("\n"):
x = x if x.strip() else ""
w, h = _tmp.getsize(x)
height += h
height += h + _add_height
width = width if width > w else w
width += pw
height += ph
A = BuildImage(
width + left_padding,
height + top_padding,
height + top_padding + 2,
font_size=font_size,
color=color,
font=font,