Compare commits

...
17 Commits
Author SHA1 Message Date
HibiKier 00b674cebb Update setu.py 2021-09-09 18:16:15 +08:00
HibiKier 8ac440335e Update README.md 2021-09-09 17:17:13 +08:00
HibiKier 4b1821ce42 Update query_resource.py 2021-09-09 17:15:26 +08:00
HibiKier 3ad955abf9 Update image_utils.py 2021-09-09 17:14:33 +08:00
HibiKier 5fabb974ce Update config.py 2021-09-09 16:39:37 +08:00
HibiKier 5325bc3e32 Update init_config.py 2021-09-09 16:39:03 +08:00
HibiKier 6688c4626b Update update_info.json 2021-09-09 16:26:29 +08:00
HibiKier 2b95ab3d7e Update init_config.py 2021-09-09 16:25:42 +08:00
HibiKier 23e6d7e27e Update config.py 2021-09-09 16:25:09 +08:00
HibiKier 2760e22336 Update update_info.json 2021-09-09 16:05:48 +08:00
HibiKier d026d09f98 Update __version__ 2021-09-09 16:04:34 +08:00
HibiKier e6fd1ce791 Update README.md 2021-09-09 16:02:58 +08:00
HibiKier 342eaa9a97 Update pixiv.py 2021-09-09 16:02:12 +08:00
HibiKier dc7681357e Update omega_pixiv_illusts.py 2021-09-09 16:01:50 +08:00
HibiKier b61cb49c1a Update setu.py 2021-09-09 16:01:35 +08:00
HibiKier c7b341393d Update setu.py 2021-09-09 14:30:42 +08:00
HibiKier 1f9fa2adb9 Update README.md 2021-09-09 12:59:23 +08:00
10 changed files with 79 additions and 399 deletions
+5 -150
View File
@@ -288,7 +288,7 @@ pip install -r requirements.txt
python bot.py
```
## 配置(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False)
## 配置
在 configs/config.py 中的 USE_CONFIG_FILE,默认为False
```
@@ -304,163 +304,15 @@ python bot.py
在./configs/config.py中配置基本配置(除API KEY ,数据库和代理外都含有默认值)
在./configs/path_config.py配置路径(含有默认配置)
########(暂时不更新 json 配置,请将USE_CONFIG_FILE设置为False,直接进入./configs/config.py进行配置)
# 是否使用配置文件(为True时这将会生成三份配置文件
./config.json:主要配置
./configs/plugins2cmd_config.json: 功能模块与对应命令配置
./configs/other_config.json: 一些插件配置)
USE_CONFIG_FILE = True
USE_CONFIG_FILE = False
# 如果不使用配置文件,将USE_CONFIG_FILE设置为False
#可在./configs/config.py文件中修改配置,在./configs/path_config.py修改资源路径
# 已在./configs/config.py和./configs/path_config.py中为各个配置提供注解!
```
## 配置文件注解(如果使用配置文件的话)
<details>
<summary>配置文件注解</summary>
./config.json
```
{
# 必填(影响功能运行)
"apikey": {
"LOLICON_KEY": "", # loliconAPI,缺失会导致色图功能异常
"TL_KEY": [] # 图灵Key(为什么要用列表?因为白嫖用户能拿5个apikey,每个apikey每日限制100条)
},
# (必填!!!)
# 数据库配置(如果填写了bind,后面就不用再填了)只是帮你拼接好)
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
"sql": {
"bind": "",
"sql_name": "",
"user": "",
"password": "",
"address": "",
"port": "",
"database": ""
},
# 路径设置(不填则使用默认)
"path": {
"IMAGE_PATH": "", # 图片路径
"VOICE_PATH": "", # 音频路径
"TXT_PATH": "", # 文本路径
"LOG_PATH": "", # 日志路径
"DATA_PATH": "", # 数据路径
"DRAW_PATH": "" # 抽卡数据路径
"TEMP_PATH": "" # 临时图片路径
},
# 代理设置
"proxy": {
"system_proxy": "", # 系统代理
"buff_proxy": "" # buff代理
},
# RSSHUB地址
"rsshub": {
"RSSHUBAPP": "https:\/\/docs.rsshub.app\/"
},
# 各个管理员功能 对应的 权限
"level": {
"DELETE_IMG_LEVEL": 7,
"MOVE_IMG_LEVEL": 7,
"UPLOAD_LEVEL": 6,
"BAN_LEVEL": 5,
"OC_LEVEL": 2,
"MUTE_LEVEL": 5
}
}
```
./configs/plugins2cmd_config.json
```
# 单个例子注解
"send_img": [
"发送图片",
"萝莉",
"美图",
"壁纸"
]
# 发送 关闭发送图片/关闭萝莉/关闭美图/关闭壁纸 都将触发命令 关闭send_img
```
./configs/other_config.json
```
{
"base": {
# 图库配置,会影响 上传/删除/移动/发送图片等功能
"IMAGE_DIR_LIST": [
"色图",
"美图",
"萝莉",
"壁纸"
],
"BAN_RESULT": "才不会给你发消息." # 当被ban用户触发命令后发送的消息
},
"bool": {
"AUTO_ADD_FRIEND": true, # 是否自动添加好友
"DOWNLOAD_SETU": true # 是否下载bot发送过的色图(不会重复)
},
"max_count": {
"MAXINFO_REIMU": 7, # 上车(reimu)功能查找目的地的最大数
"COUNT_PER_DAY_REIMU": 5, # 每日上车(reimu)次数限制
"MAXINFO_BT": 10, # bt功能单次查找最大数
"MAXINFO_PRIVATE_ANIME": 20, # 私聊搜索动漫返回的最大数量
"MAXINFO_GROUP_ANIME": 5, # 群搜索动漫返回的最大数量
"MAX_FIND_IMG_COUNT": 3, # 识图最大返回数
"MAX_SIGN_GOLD": 200, # 签到好感度加成额外获得的最大金币数
"MAX_SETU_R_COUNT": 5, # 每日色图r次数限制
},
"probability": {
"INITIAL_SETU_PROBABILITY": 0.7, # 涩图触发的基础概率(触发概率 = 基础概率 + 好感度)
"FUDU_PROBABILITY": 0.7 # 复读概率
},
# 注:即在 MALICIOUS_CHECK_TIME 时间内触发相同命令 MALICIOUS_BAN_COUNT 将被ban MALICIOUS_BAN_TIME 分钟
"malicious_ban": {
"MALICIOUS_BAN_TIME": 30, # 恶意触发命令被ban的时长(分钟)
"MALICIOUS_BAN_COUNT": 4, # 恶意触发命令的规定次数
"MALICIOUS_CHECK_TIME": 5 # 恶意触发命令的规定时间(秒)
},
"open_case": {
"INITIAL_OPEN_CASE_COUNT": 20 # 每日开箱的基本数量(总数量=基本数量 + 好感度/3)
},
# 注:即在 MUTE_DEFAULT_TIME 内发送相似(包含)消息超过 MUTE_DEFAULT_COUNT 将会被 MUTE_DEFAULT_DURATION 分钟
# 这只是默认配置,各个群可以自由设置群内刷屏检测配置
"mute": {
"MUTE_DEFAULT_COUNT": 10, # 刷屏检测默认检测最大次数
"MUTE_DEFAULT_TIME": 7, # 刷屏检测默认规定时间(秒)
"MUTE_DEFAULT_DURATION": 10 # 刷屏检测默认禁言时长(分钟)
},
"other": {
"UPDATE_GOCQ_GROUP": [], # 是否需要为某些群上传最新版的gocq?
"ADMIN_DEFAULT_AUTH": 5 # 默认群管理员权限
},
# 管理员功能 和 对应的 权限
"auth": {
"admin_plugins_auth": {
"admin_bot_manage": 2,
"ban": 5,
"delete_img": 7,
"move_img": 7,
"upload_img": 6,
"admin_help": 1,
"mute": 5
}
}
}
```
</details>
## 更新
@@ -472,6 +324,9 @@ python bot.py
* 修复签到可能重复的问题
* 修复无订阅时递归出错
* 启用了plugins2info_dict, plugins2cd_dict, plugins2exists_dict配置文件,通过USE_CONFIG_FILE=True开启
* 修复涩图local_id会被固定为50
* 优化图库数量查询
* 修复原神大地图过大无法打开报错
### 2021/9/7
+1 -1
View File
@@ -1 +1 @@
__version__: v0.0.4.5
__version__: v0.0.4.6
+5 -34
View File
@@ -1,8 +1,7 @@
from typing import List, Optional, Tuple
from services.service_config import TL_M_KEY, SYSTEM_M_PROXY, ALAPI_M_TOKEN
from .path_config import DATA_PATH
from pathlib import Path
from .utils.init_config import init_config
from configs.path_config import DATA_PATH
try:
import ujson as json
except ModuleNotFoundError:
@@ -315,37 +314,9 @@ RSSHUBAPP = RSSHUBAPP[:-1] if RSSHUBAPP[-1] == "/" else RSSHUBAPP
if USE_CONFIG_FILE:
# 读取配置文件
plugins2info_file = Path(DATA_PATH) / 'configs' / 'plugins2info.json'
plugins2info_file.parent.mkdir(exist_ok=True, parents=True)
if plugins2info_file.exists():
with open(plugins2info_file, 'r') as f:
_data = json.load(f)
for p in plugins2info_dict:
if not _data.get(p):
_data[p] = plugins2info_dict[p]
with open(plugins2info_file, 'w') as wf:
json.dump(_data, wf, ensure_ascii=False, indent=4)
plugins2info_dict = _data
else:
with open(plugins2info_file, 'w', encoding='utf8') as wf:
json.dump(plugins2info_dict, wf, ensure_ascii=False, indent=4)
plugins2cd_file = Path(DATA_PATH) / 'configs' / 'plugins2cd.json'
if plugins2cd_file.exists():
with open(plugins2cd_file, 'r', encoding='utf8') as f:
plugins2cd_dict = json.load(f)
else:
with open(plugins2cd_file, 'w', encoding='utf8') as wf:
json.dump(plugins2cd_dict, wf, ensure_ascii=False, indent=4)
plugins2exists_file = Path(DATA_PATH) / 'configs' / 'plugins2exists.json'
if plugins2exists_file.exists():
with open(plugins2exists_file, 'r', encoding='utf8') as f:
plugins2exists_dict = json.load(f)
else:
with open(plugins2exists_file, 'w', encoding='utf8') as wf:
json.dump(plugins2exists_dict, wf, ensure_ascii=False, indent=4)
plugins2info_dict, plugins2cd_dict, plugins2exists_dict = init_config(
plugins2info_dict, plugins2cd_dict, plugins2exists_dict, DATA_PATH
)
# 配置文件应用
+33 -167
View File
@@ -1,176 +1,42 @@
# import nonebot
from pathlib import Path
try:
import ujson as json
except ModuleNotFoundError:
import json
# driver: nonebot.Driver = nonebot.get_driver()
base_config = Path() / 'config.json'
plugins_cmd_config = Path() / 'configs' / 'plugins2cmd_config.json'
plugins_setting = Path() / 'configs' / 'plugins_setting.json'
def init_config():
if not base_config.exists():
base_config.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'apikey': {
'LOLICON_KEY': '',
'TL_KEY': [],
},
'sql': {
'bind': '',
'sql_name': '',
'user': '',
'password': '',
'address': '',
'port': '',
'database': '',
},
'path': {
'IMAGE_PATH': '',
'VOICE_PATH': '',
'TXT_PATH': '',
'LOG_PATH': '',
'DATA_PATH': '',
'DRAW_PATH': '',
'TEMP_PATH': '',
},
'proxy': {
'system_proxy': '',
'buff_proxy': ''
},
'level': {
'DELETE_IMG_LEVEL': 7,
'MOVE_IMG_LEVEL': 7,
'UPLOAD_LEVEL': 6,
'BAN_LEVEL': 5,
'OC_LEVEL': 2,
'MUTE_LEVEL': 5,
},
'auth': {
'ADMIN_DEFAULT_AUTH': 5,
'admin_plugins_auth': {
"admin_bot_manage": 2,
"ban": 5,
"delete_img": 7,
"move_img": 7,
"upload_img": 6,
"admin_help": 1,
"mute": 5
}
}
}
with open(base_config, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)
if not plugins_cmd_config.exists():
plugins_cmd_config.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'base_config': {
'sign_in': ['签到'],
'send_img': ['发送图片', '萝莉', '美图', '壁纸'],
'send_setu': ['色图', '涩图', '瑟图', '查色图'],
'white2black': ['黑白图', '黑白草图'],
'coser': ['coser', 'cos'],
'quotations': ['语录'],
'jitang': ['鸡汤'],
'send_dinggong_voice': ['骂我', '骂老子', '骂劳资'],
'open_cases': ['开箱', '我的开箱', '群开箱统计', '我的金色'],
'luxun': ['鲁迅说过', '鲁迅说'],
'fake_msg': ['假消息'],
'buy': ['购买', '购买道具'],
'my_gold': ['我的金币'],
'my_props': ['我的道具'],
'shop_handle': ['商店'],
'nonebot_plugin_cocdicer': ['骰子娘'],
'update_pic': ['图片', '操作图片', '修改图片'],
'search_buff_skin_price': ['查询皮肤'],
'weather': ['天气', '查询天气', '天气查询'],
'yiqing': ['疫情', '疫情查询', '查询疫情'],
'what_anime': ['识番'],
'search_anime': ['搜番'],
'songpicker2': ['点歌'],
'epic': ['epic'],
'pixiv': ['pixiv', 'p站排行', '搜图'],
'poke': ['戳一戳'],
'draw_card': ['游戏抽卡', '原神一井', '原神来一井', '方舟一井', '方舟来一井'],
'ai': ['ai', 'Ai', 'AI', 'aI'],
'one_friend': ['我有一个朋友', '我有一个朋友想问问'],
'translate': ['翻译', '英翻', '翻英', '日翻', '翻日', '韩翻', '翻韩'],
'nonebot_plugin_picsearcher': ['识图'],
'almanac': ['原神黄历', '黄历'],
'material_remind': ['今日素材', '天赋材料'],
'qiu_qiu_translation': ['丘丘翻译', '丘丘一下', '丘丘语翻译'],
'query_resource_points': ['原神资源查询', '原神资源列表'],
}
}
with open(plugins_cmd_config, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)
if not plugins_setting.exists():
plugins_setting.parent.mkdir(parents=True, exist_ok=True)
config_dict = {
'base': {
'IMAGE_DIR_LIST': ["色图", "美图", "萝莉", "壁纸"],
'BAN_RESULT': "才不会给你发消息.",
},
'draw_card': {
'PRTS_FLAG': True, # 明日方舟
'GENSHIN_FLAG': True, # 原神
'PRETTY_FLAG': True, # 赛马娘
'GUARDIAN_FLAG': True, # 坎公骑冠剑
'PCR_FLAG': True, # 公主连结
'AZUR_FLAG': True, # 碧蓝航线
'FGO_FLAG': True, # 命运-冠位指定(FGO)
'ONMYOJI_FLAG': True, # 阴阳师
'PCR_TAI': False # pcr是否开启台服卡池
},
'fudu': {
'FUDU_PROBABILITY': 0.7,
},
'reimu': {
'MAXINFO_REIMU': 7,
'COUNT_PER_DAY_REIMU': 5,
},
'bt': {
'MAXINFO_BT': 10,
},
'search_anime': {
'MAXINFO_PRIVATE_ANIME': 20,
'MAXINFO_GROUP_ANIME': 5,
},
'picsearcher': {
'MAX_FIND_IMG_COUNT': 3,
},
'sign': {
'MAX_SIGN_GOLD': 200,
},
'send_setu': {
'INITIAL_SETU_PROBABILITY': 0.7,
'MAX_SETU_R_COUNT': 5,
'DOWNLOAD_SETU': True,
},
'malicious_ban': {
'MALICIOUS_BAN_TIME': 30,
'MALICIOUS_BAN_COUNT': 8,
'MALICIOUS_CHECK_TIME': 5,
},
'open_case': {
'INITIAL_OPEN_CASE_COUNT': 20,
},
'mute': {
'MUTE_DEFAULT_COUNT': 10,
'MUTE_DEFAULT_TIME': 7,
'MUTE_DEFAULT_DURATION': 10,
},
'update_gocq': {
'UPDATE_GOCQ_GROUP': [],
},
}
with open(plugins_setting, 'w', encoding='utf8') as f:
json.dump(config_dict, f, indent=4, ensure_ascii=False)
def init_config(plugins2info_dict, plugins2cd_dict, plugins2exists_dict, DATA_PATH):
plugins2info_file = Path(DATA_PATH) / 'configs' / 'plugins2info.json'
plugins2info_file.parent.mkdir(exist_ok=True, parents=True)
if plugins2info_file.exists():
with open(plugins2info_file, 'r', encoding='utf8') as f:
_data = json.load(f)
for p in plugins2info_dict:
if not _data.get(p):
_data[p] = plugins2info_dict[p]
with open(plugins2info_file, 'w') as wf:
json.dump(_data, wf, ensure_ascii=False, indent=4)
plugins2info_dict = _data
else:
with open(plugins2info_file, 'w', encoding='utf8') as wf:
json.dump(plugins2info_dict, wf, ensure_ascii=False, indent=4)
plugins2cd_file = Path(DATA_PATH) / 'configs' / 'plugins2cd.json'
if plugins2cd_file.exists():
with open(plugins2cd_file, 'r', encoding='utf8') as f:
plugins2cd_dict = json.load(f)
else:
with open(plugins2cd_file, 'w', encoding='utf8') as wf:
json.dump(plugins2cd_dict, wf, ensure_ascii=False, indent=4)
plugins2exists_file = Path(DATA_PATH) / 'configs' / 'plugins2exists.json'
if plugins2exists_file.exists():
with open(plugins2exists_file, 'r', encoding='utf8') as f:
plugins2exists_dict = json.load(f)
else:
with open(plugins2exists_file, 'w', encoding='utf8') as wf:
json.dump(plugins2exists_dict, wf, ensure_ascii=False, indent=4)
return plugins2info_dict, plugins2cd_dict, plugins2exists_dict
+8 -7
View File
@@ -118,14 +118,15 @@ class OmegaPixivIllusts(db.Model):
参数:
:param tags: 关键词/Tag
"""
query = cls.query
setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
query = cls.select('count')
if tags:
for tag in tags:
query = query.where(cls.tags.contains(tag))
count = len(await query.where(cls.nsfw_tag == 0).gino.all())
setu_count = len(await query.where(cls.nsfw_tag == 1).gino.all())
r18_count = len(await query.where(cls.nsfw_tag == 2).gino.all())
return count, setu_count, r18_count
count = await query.where(cls.nsfw_tag == 0).gino.first()
setu_count = await query.where(cls.nsfw_tag == 1).gino.first()
r18_count = await query.where(cls.nsfw_tag == 2).gino.first()
return count[0], setu_count[0], r18_count[0]
@classmethod
async def get_all_pid(cls) -> List[int]:
@@ -133,6 +134,6 @@ class OmegaPixivIllusts(db.Model):
说明:
获取所有图片PID
"""
data = await cls.query.gino.all()
return [x.pid for x in data]
data = await cls.select('pid').gino.all()
return [x[0] for x in data]
+6 -5
View File
@@ -159,11 +159,12 @@ class Pixiv(db.Model):
参数:
:param tags: 关键词/Tag
"""
query = cls.query
setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
query = cls.select('count')
if tags:
for tag in tags:
query = cls.query.where(cls.tags.contains(tag))
count = len(await query.where(cls.is_r18 == False).gino.all())
r18_count = len(await query.where(cls.is_r18 == True).gino.all())
return count, r18_count
query = query.where(cls.tags.contains(tag))
count = await query.where(cls.is_r18 == False).gino.first()
r18_count = await query.where(cls.is_r18 == True).gino.first()
return count[0], r18_count[0]
+7 -3
View File
@@ -57,6 +57,7 @@ class Setu(db.Model):
local_id: Optional[int] = None,
tags: Optional[List[str]] = None,
r18: int = 0,
limit: int = 50,
):
"""
说明:
@@ -65,6 +66,7 @@ class Setu(db.Model):
:param local_id: 本地色图 id
:param tags: tags
:param r18: 是否 r18,0:非r18 1:r18 2:混合
:param limit: 获取数量
"""
if local_id:
flag = True if r18 == 1 else False
@@ -80,7 +82,7 @@ class Setu(db.Model):
if tags:
for tag in tags:
query = query.where(cls.tags.contains(tag) | cls.title.contains(tag) | cls.author.contains(tag))
query = query.order_by(db.func.random()).limit(50)
query = query.order_by(db.func.random()).limit(limit)
return await query.gino.all()
@classmethod
@@ -89,8 +91,10 @@ class Setu(db.Model):
说明:
查询图片数量
"""
return len(await cls.query_image(r18=r18))
# return await db.func.count(cls.local_id).gino.scalar()
flag = False if r18 == 0 else True
setattr(Setu, 'count', db.func.count(cls.local_id).label('count'))
count = await cls.select('count').where(cls.is_r18 == flag).gino.first()
return count[0]
@classmethod
async def get_image_in_hash(cls, img_hash: str) -> "Setu":
@@ -164,40 +164,18 @@ async def download_map_init(
if not _map.exists():
# padding_w, padding_h = data['padding']
data = data["slices"]
idx = 0
for x in data:
idj = 0
for j in x:
await download_image(
j["url"],
f"{map_path}/{idx}_{idj}.png",
session,
semaphore,
force_flag=flag,
)
idj += 1
idx += 1
map_width, map_height = CreateImg(
0, 0, background=f"{map_path}/0_0.png"
).size
map_width = map_width * MAP_RATIO
map_height = map_height * MAP_RATIO
lens = len(
[x for x in os.listdir(f"{map_path}") if x.startswith("0")]
map_url = data[0][0]['url']
await download_image(
map_url,
f"{map_path}/map.png",
session,
semaphore,
force_flag=flag,
)
background_image = CreateImg(
map_width * lens, map_height * lens, map_width, map_height
map_file = CreateImg(
0, 0, background=f"{map_path}/map.png", ratio=MAP_RATIO
)
for i in range(idx):
for j in range(idj):
x = CreateImg(
0,
0,
background=f"{map_path}/{i}_{j}.png",
ratio=MAP_RATIO,
)
background_image.paste(x)
background_image.save(f"{map_path}/map.png")
map_file.save(f"{map_path}/map.png")
else:
logger.warning(f'获取原神地图失败 msg: {data["message"]}')
else:
+2
View File
@@ -2,11 +2,13 @@
"update_file": [
"README.md",
"configs/config.py",
"configs/utils/init_config.py",
"models/ban_user.py",
"models/group_member_info.py",
"models/pixiv.py",
"models/russian_user.py",
"models/setu.py",
"models/omega_pixiv_illusts.py",
"plugins/admin_bot_manage",
"plugins/admin_help/__init__.py",
"plugins/ai/__init__.py",
+2
View File
@@ -8,6 +8,8 @@ from pathlib import Path
import cv2
import base64
import imagehash
ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = None
def compare_image_with_hash(