Compare commits

..
20 Commits
Author SHA1 Message Date
HibiKier b63c05a509 Update requirements.txt 2021-12-01 14:17:11 +08:00
HibiKi 2a1a2ee8c5 update 0.0.6.5 2021-12-01 14:03:34 +08:00
HibiKier 8c4b515093 Update update_info.json 2021-12-01 10:53:15 +08:00
HibiKier 6d43989a4d Update update_info.json 2021-12-01 10:52:28 +08:00
HibiKier fb1f15bcb4 Update update_game_simple_info.py 2021-11-29 21:30:06 +08:00
HibiKier 81ad585a18 Update update_game_requests_info.py 2021-11-29 21:29:48 +08:00
HibiKier eb3bd2b4a6 Update update_game_info.py 2021-11-29 21:29:29 +08:00
HibiKier e401914790 Update README.md 2021-11-29 13:11:34 +08:00
HibiKier fef5dadaba Update __version__ 2021-11-29 13:10:43 +08:00
HibiKi c1348d08ed update 0.0.6.4 2021-11-29 13:09:47 +08:00
HibiKier fbd7c568d9 Update pix_update.py 2021-11-24 18:26:52 +08:00
HibiKier 2941774913 Update __init__.py 2021-11-24 18:26:38 +08:00
HibiKier b96d910401 Update __version__ 2021-11-24 14:40:53 +08:00
HibiKier 9275d0782b Update README.md 2021-11-24 14:40:39 +08:00
HibiKier 7acc6cf6af Update data_source.py 2021-11-24 14:33:10 +08:00
HibiKier d380a9aacc Update data_source.py 2021-11-24 14:32:46 +08:00
HibiKier 495377da13 Update README.md 2021-11-24 10:25:00 +08:00
HibiKier 218eed4068 Add files via upload 2021-11-24 10:24:40 +08:00
HibiKier 1e9c99dec1 Delete plugins/search_image directory 2021-11-24 10:07:47 +08:00
HibiKier 0326bc2831 Update __init__.py 2021-11-24 09:56:50 +08:00
56 changed files with 671 additions and 525 deletions
+145
View File
@@ -0,0 +1,145 @@
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
test.py
server.py
member_activity_handle.py
Yu-Gi-Oh/
+21 -1
View File
@@ -1,4 +1,4 @@
<div align=center><img width="320" height="320" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/docs/zhenxun.jpg"/></div>
<div align=center><img width="320" height="320" src="https://raw.githubusercontent.com/HibiKier/zhenxun_bot/main/logo.png"/></div>
![maven](https://img.shields.io/badge/python-3.8%2B-blue)
![maven](https://img.shields.io/badge/nonebot-2.0.0-yellow)
@@ -321,6 +321,26 @@ python bot.py
## 更新
### 2021/12/1 \[v0.0.6.5]
* 群权限-1时超级用户命令依旧生效
* 修复以真寻为开头的词条不会被回复
* 修复购买道具可以为负数
* P站排行/搜图提供配置项,将略过大于指定张数的作品
* 昵称提供关键词屏蔽配置项,会将指定关键词替换为“*”
* 取消了自动更新,改为自动检测版本
### 2021/11/29 \[v0.0.6.4]
* 新增cos图撤回配置项
* 新增默认群权限配置项
* 修复权限等级类配置无法正常应用
### 2021/11/24 \[v0.0.6.3]
* 修复在线搜索色图出错
* 修复pix无法正确获取HIBIAPI
### 2021/11/23 \[v0.0.6.2]
* 替换cos API
+1 -1
View File
@@ -1 +1 @@
__version__: v0.0.6.2
__version__: v0.0.6.5
+13
View File
@@ -20,6 +20,7 @@ from models.ban_user import BanUser
from utils.utils import FreqLimiter
from utils.message_builder import at
from models.level_user import LevelUser
import nonebot
_flmt = FreqLimiter(Config.get_config("hook", "CHECK_NOTICE_INFO_CD"))
@@ -46,6 +47,18 @@ async def _(matcher: Matcher, bot: Bot, event: MessageEvent, state: T_State):
and not plugins2info_dict[module]["limit_superuser"]
):
return
# 超级用户命令
try:
_plugin = nonebot.plugin.get_plugin(module)
_module = _plugin.module
plugin_name = _module.__getattribute__("__zx_plugin_name__")
if (
"[superuser]" in plugin_name.lower()
and str(event.user_id) in bot.config.superusers
):
return
except AttributeError:
pass
# 群黑名单检测
if isinstance(event, GroupMessageEvent):
if group_manager.get_group_level(event.group_id) < 0:
@@ -11,6 +11,7 @@ from .init_plugins_limit import (
)
from .init import init
from .check_plugin_status import check_plugin_status
from utils.manager import admin_manager
from nonebot.adapters.cqhttp import Bot
from configs.path_config import DATA_PATH
from services.log import logger
@@ -92,11 +92,14 @@ def init_plugins_config(data_path):
if user_config_file.exists():
with open(user_config_file, "r", encoding="utf8") as f:
_data = _yaml.load(f)
# 数据替换
for plugin in Config.keys():
_tmp_data[plugin] = {}
for k in Config[plugin].keys():
if _data.get(plugin) and k in _data[plugin].keys():
Config.set_config(plugin, k, _data[plugin][k])
if level2module := Config.get_level2module(plugin, k):
admin_manager.set_admin_level(level2module, _data[plugin][k])
_tmp_data[plugin][k] = Config.get_config(plugin, k)
Config.save()
temp_file = Path() / "configs" / "temp_config.yaml"
@@ -26,7 +26,7 @@ def init_plugins_settings(data_path: str):
plugin_name = _module.__getattribute__("__zx_plugin_name__")
_tmp_module[x] = plugin_name
except (KeyError, AttributeError) as e:
logger.error(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
logger.warning(f"配置文件 模块:{x} 获取 plugin_name 失败...{e}")
_tmp_module[x] = ""
for matcher in _matchers:
if matcher.module not in plugins2settings_manager.keys():
+51 -44
View File
@@ -8,7 +8,7 @@ from models.friend_user import FriendUser
import random
from models.ban_user import BanUser
from services.log import logger
from configs.config import NICKNAME
from configs.config import NICKNAME, Config
__zx_plugin_name__ = "昵称系统"
@@ -23,6 +23,13 @@ __plugin_des__ = "区区昵称,才不想叫呢!"
__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_configs__ = {
"BLACK_WORD": {
"value": ["爸", "妈", "爹", "爷"],
"help": "昵称所屏蔽的关键词,会被替换为 *",
"default_value": None
}
}
nickname = on_command(
"nickname",
@@ -47,52 +54,52 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
if len(msg) > 10:
await nickname.finish("昵称可不能超过10个字!", at_sender=True)
if await GroupInfoUser.set_group_member_nickname(
event.user_id, event.group_id, msg
):
if len(msg) < 5:
if random.random() < 0.5:
msg = "~".join(msg)
await nickname.send(
random.choice(
[
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
f"好突然,突然要叫你昵称什么的...{msg}..",
f"{NICKNAME}会好好记住的{msg}的,放心吧",
f"好..好.,那窝以后就叫你{msg}了.",
]
if msg in bot.config.superusers:
await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
_tmp = ""
black_word = Config.get_config("nickname", "BLACK_WORD")
for x in msg:
_tmp += "*" if x in black_word else x
msg = _tmp
if isinstance(event, GroupMessageEvent):
if await GroupInfoUser.set_group_member_nickname(
event.user_id, event.group_id, msg
):
if len(msg) < 5:
if random.random() < 0.3:
msg = "~".join(msg)
await nickname.send(
random.choice(
[
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
f"好突然,突然要叫你昵称什么的...{msg}..",
f"{NICKNAME}会好好记住的{msg}的,放心吧",
f"好..好.,那窝以后就叫你{msg}了.",
]
)
)
)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
logger.info(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg}")
else:
await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
else:
await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
@nickname.handle()
async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
msg = get_message_text(event.json())
if not msg:
await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
if len(msg) > 10:
await nickname.finish("不要超过10个字!", at_sender=True)
if await FriendUser.set_friend_nickname(event.user_id, msg):
await nickname.send(
random.choice(
[
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
f"好突然,突然要叫你昵称什么的...{msg}..",
f"{NICKNAME}会好好记住的{msg}的,放心吧",
f"好..好.,那窝以后就叫你{msg}了.",
]
if await FriendUser.set_friend_nickname(event.user_id, msg):
await nickname.send(
random.choice(
[
f"好啦好啦,我知道啦,{msg},以后就这么叫你吧",
f"嗯嗯,{NICKNAME}记住你的昵称了哦,{msg}",
f"好突然,突然要叫你昵称什么的...{msg}..",
f"{NICKNAME}会好好记住的{msg}的,放心吧",
f"好..好.,那窝以后就叫你{msg}了.",
]
)
)
)
logger.info(f"USER {event.user_id} 设置昵称 {msg}")
else:
await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
logger.info(f"USER {event.user_id} 设置昵称 {msg}")
else:
await nickname.send("设置昵称失败了,明天再来试一试!或联系管理员更新好友!", at_sender=True)
logger.warning(f"USER {event.user_id} 设置昵称 {msg} 失败")
@my_nickname.handle()
+5 -1
View File
@@ -15,6 +15,10 @@ __zx_plugin_name__ = "重载插件配置 [Superuser]"
__plugin_usage__ = """
usage:
重载插件配置
plugins2settings,
plugins2cd
plugins2block
group_manager
指令:
重载插件配置
""".strip()
@@ -27,7 +31,7 @@ __plugin_author__ = "HibiKier"
reload_plugins_manager = on_command(
"重载插件限制", rule=to_me(), permission=SUPERUSER, priority=1, block=True
"重载配置", rule=to_me(), permission=SUPERUSER, priority=1, block=True
)
+14 -1
View File
@@ -29,7 +29,7 @@ class ConfigsManager:
name: Optional[str] = None,
help_: Optional[str] = None,
default_value: Optional[str] = None,
_override: bool = False
_override: bool = False,
):
"""
为插件添加一个配置,不会被覆盖,只有第一个生效
@@ -61,6 +61,7 @@ class ConfigsManager:
"name": name.strip() if isinstance(name, str) else name,
"help": help_.strip() if isinstance(help_, str) else help_,
"default_value": default_value,
"level_module": _module,
}
def remove_plugin_config(self, module: str):
@@ -119,6 +120,17 @@ class ConfigsManager:
return self._data[module][key]["value"]
return None
def get_level2module(self, module: str, key: str) -> Optional[str]:
"""
获取指定key所绑定的module,一般为权限等级
:param module: 模块名
:param key: 配置名称
:return:
"""
if self._data.get(module) is not None:
if self._data[module].get(key) is not None:
return self._data[module][key].get("level_module")
def get(self, key: str):
"""
获取插件配置数据
@@ -158,3 +170,4 @@ class ConfigsManager:
def __getitem__(self, key):
return self._data[key]
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 694 KiB

+6 -1
View File
@@ -1,4 +1,5 @@
from services.db_context import db
from configs.config import Config
class FriendUser(db.Model):
@@ -80,7 +81,11 @@ class FriendUser(db.Model):
user = await query.gino.first()
if user:
if user.nickname:
return user.nickname
_tmp = ""
black_word = Config.get_config("nickname", "BLACK_WORD")
for x in user.nickname:
_tmp += "*" if x in black_word else x
return _tmp
return ""
@classmethod
+17 -2
View File
@@ -1,5 +1,5 @@
from datetime import datetime
from configs.config import Config
from services.db_context import db
from typing import List, Optional
@@ -128,6 +128,17 @@ class GroupInfoUser(db.Model):
return True
return False
@classmethod
async def get_user_all_group(cls, user_qq: int) -> List[int]:
"""
获取该用户所在的所有群聊
:param user_qq: 用户qq
"""
query = await cls.query.where(cls.user_qq == user_qq).gino.all()
if query:
query = [x.belonging_group for x in query]
return query
@classmethod
async def get_group_member_nickname(cls, user_qq: int, belonging_group: int) -> str:
"""
@@ -143,7 +154,11 @@ class GroupInfoUser(db.Model):
user = await query.gino.first()
if user:
if user.nickname:
return user.nickname
_tmp = ""
black_word = Config.get_config("nickname", "BLACK_WORD")
for x in user.nickname:
_tmp += "*" if x in black_word else x
return _tmp
return ""
@classmethod
-1
View File
@@ -59,7 +59,6 @@ async def get_chat_result(text: str, img_url: str, user_id: int, nickname: str)
nickname += "大~人~"
rst = rst.replace("小主人", nickname).replace("小朋友", nickname)
ai_message_manager.add_result(user_id, rst)
print(ai_message_manager)
return rst
+4 -1
View File
@@ -1,7 +1,6 @@
from configs.config import Config
import nonebot
nonebot.load_plugins("plugins/alapi")
Config.add_plugin_config(
"alapi",
@@ -9,3 +8,7 @@ Config.add_plugin_config(
None,
help_="在https://admin.alapi.cn/user/login登录后获取token"
)
nonebot.load_plugins("plugins/alapi")
+14 -14
View File
@@ -110,17 +110,17 @@ async def _():
f"当前版本:{_version},最新版本:{latest_version}\n"
f"尝试自动更新...",
)
try:
code = await check_update(bot)
except Exception as e:
logger.error(f"更新真寻未知错误 {type(e)}:{e}")
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]),
message=f"更新真寻未知错误 {type(e)}:{e}\n",
)
else:
if code == 200:
await bot.send_private_msg(
user_id=int(list(bot.config.superusers)[0]),
message=f"更新完毕,请重启真寻....",
)
# try:
# code = await check_update(bot)
# except Exception as e:
# logger.error(f"更新真寻未知错误 {type(e)}:{e}")
# await bot.send_private_msg(
# user_id=int(list(bot.config.superusers)[0]),
# message=f"更新真寻未知错误 {type(e)}:{e}\n",
# )
# else:
# if code == 200:
# await bot.send_private_msg(
# user_id=int(list(bot.config.superusers)[0]),
# message=f"更新完毕,请重启真寻....",
# )
+15 -1
View File
@@ -3,6 +3,8 @@ from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, MessageEvent
from utils.message_builder import image
from services.log import logger
from utils.manager import withdraw_message_manager
from configs.config import Config
__zx_plugin_name__ = "coser"
__plugin_usage__ = """
@@ -21,6 +23,13 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["cos", "coser", "括丝", "COS", "Cos", "cOS", "coS"],
}
__plugin_configs__ = {
"WITHDRAW_COS_MESSAGE": {
"value": (0, 1),
"help": "自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
"default_value": (0, 1),
},
}
coser = on_command(
"cos", aliases={"coser", "括丝", "COS", "Cos", "cOS", "coS"}, priority=5, block=True
@@ -33,7 +42,12 @@ url = "http://iw233.cn/API/cos.php"
@coser.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
try:
await coser.send(image(url))
msg_id = await coser.send(image(url))
withdraw_message_manager.withdraw_message(
event,
msg_id["message_id"],
Config.get_config("coser", "WITHDRAW_COS_MESSAGE"),
)
except Exception as e:
await coser.send("你cos给我看!")
logger.error(f"coser 发送了未知错误 {type(e)}:{e}")
-2
View File
@@ -1,6 +1,5 @@
import os
from nonebot.adapters.cqhttp import MessageSegment, Message
import nonebot
import random
from .update_game_info import update_info
from .util import generate_img, init_star_rst, BaseData, set_list, get_star, init_up_char
@@ -15,7 +14,6 @@ try:
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
announcement = GenshinAnnouncement()
-2
View File
@@ -1,6 +1,5 @@
import os
import nonebot
from nonebot.adapters.cqhttp import MessageSegment, Message
from .update_game_info import update_info
from .announcement import GuardianAnnouncement
@@ -18,7 +17,6 @@ try:
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
announcement = GuardianAnnouncement()
-2
View File
@@ -1,5 +1,4 @@
import nonebot
from .update_game_info import update_info
from .announcement import PrettyAnnouncement
from .util import init_star_rst, generate_img, max_card, BaseData, \
@@ -15,7 +14,6 @@ try:
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
announcement = PrettyAnnouncement()
-2
View File
@@ -1,6 +1,5 @@
from nonebot.adapters.cqhttp import MessageSegment, Message
import nonebot
import random
from .config import PRTS_FIVE_P, PRTS_FOUR_P, PRTS_SIX_P, PRTS_THREE_P, DRAW_PATH, PRTS_FLAG
from .update_game_info import update_info
@@ -15,7 +14,6 @@ try:
except ModuleNotFoundError:
import json
driver: nonebot.Driver = nonebot.get_driver()
announcement = PrtsAnnouncement()
+5 -1
View File
@@ -6,6 +6,7 @@ from urllib.parse import unquote
from services.log import logger
from .util import remove_prohibited_str
from utils.http_utils import AsyncHttpx
from httpx import ConnectTimeout, CloseError
import bs4
import re
try:
@@ -57,9 +58,12 @@ async def update_info(url: str, game_name: str, info_list: list = None) -> 'dict
data[name] = member_dict
logger.info(f'{name} is update...')
data = await _last_check(data, game_name)
except TimeoutError:
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f'更新 {game_name} 超时...')
return {}, 999
except Exception as e:
logger.error(f"更新 {game_name} 未知错误 {type(e)}:{e}")
return {}, 998
with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf:
wf.write(json.dumps(data, ensure_ascii=False, indent=4))
return data, 200
@@ -5,6 +5,7 @@ from bs4 import BeautifulSoup
from .util import remove_prohibited_str
from utils.http_utils import AsyncHttpx
from services.log import logger
from httpx import ConnectTimeout, CloseError
import asyncio
try:
@@ -50,9 +51,12 @@ async def update_requests_info(game_name: str):
data = add_to_data(data, x, game_name)
logger.info(f"{key} is update...")
data = await _last_check(data, game_name)
except TimeoutError:
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f"更新 {game_name} 超时...")
return {}, 999
except Exception as e:
logger.error(f"更新 {game_name} 未知错误 {type(e)}:{e}")
return {}, 998
with open(DRAW_PATH + f"{game_name}.json", "w", encoding="utf8") as wf:
json.dump(data, wf, ensure_ascii=False, indent=4)
return data, 200
@@ -150,6 +154,8 @@ async def _async_update_fgo_extra_info(url: str, key: str, _id: str, semaphore):
x = {key: {}}
x[key]["入手方式"] = obtain
return x
except TimeoutError:
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f"访问{url}{_id} 第 {i}次 超时...已再次访问")
except Exception as e:
logger.error(f"访问{url}{_id} 第 {i}次 未知错误 {type(e)}:{e}...已再次访问")
return {}
+10 -5
View File
@@ -6,6 +6,7 @@ from .util import remove_prohibited_str
from urllib.parse import unquote
from services.log import logger
from utils.http_utils import AsyncHttpx
from httpx import ConnectTimeout, CloseError
import bs4
import asyncio
@@ -36,10 +37,13 @@ async def update_simple_info(url: str, game_name: str) -> 'dict, int':
except AttributeError:
continue
for char in contents[1:]:
data = await retrieve_char_data(char, game_name, data, index)
try:
data = await retrieve_char_data(char, game_name, data, index)
except AttributeError:
continue
index += 1
data = await _last_check(data, game_name)
except TimeoutError:
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f'更新 {game_name} 超时...')
return {}, 999
with open(DRAW_PATH + f'{game_name}.json', 'w', encoding='utf8') as wf:
@@ -127,7 +131,6 @@ async def retrieve_char_data(char: bs4.element.Tag, game_name: str, data: dict,
'名称': remove_prohibited_str(char.find('a')['title']),
'星级': 3 - index}
if game_name == 'azur':
print(char)
char = char.find('div').find('div').find('div').find('div')
avatar_img = char.find('a').find('img')
try:
@@ -186,7 +189,9 @@ async def _async_update_azur_extra_info(key: str, semaphore):
x = {key: {'获取途径': []}}
logger.warning(f'碧蓝航线获取额外信息错误 {key}...{[]}')
return x
except TimeoutError:
logger.warning(f'访问 https://wiki.biligame.com/blhx/{key} 第 {i}次 超时...已再次访问')
except (TimeoutError, ConnectTimeout, CloseError):
logger.warning(f'访问 https://wiki.biligame.com/blhx/{key} 第 {i}次 超时/失败...已再次访问')
except Exception as e:
logger.error(f'访问 https://wiki.biligame.com/blhx/{key} 第 {i}次 未知错误 {type(e)}:{e}...已再次访问')
return {}
+1 -1
View File
@@ -65,4 +65,4 @@ async def _():
mes = alc_img + "\n ※ 黄历数据来源于 genshin.pub"
for gid in gl:
if await group_manager.check_group_task_status(gid, "genshin_alc"):
await bot.send_group_msg(group_id=int(gid), message=mes)
await bot.send_group_msg(group_id=int(gid), message="" + mes)
@@ -8,6 +8,7 @@ from asyncio.exceptions import TimeoutError
from asyncio import Semaphore
from utils.image_utils import is_valid
from utils.http_utils import AsyncHttpx
from httpx import ConnectTimeout
from pathlib import Path
from .map import Map
import asyncio
@@ -150,9 +151,11 @@ async def download_resource_data(semaphore: Semaphore):
logger.warning(f'获取原神资源失败 msg: {data["message"]}')
else:
logger.warning(f"获取原神资源失败 code:{response.status_code}")
except TimeoutError:
except (TimeoutError, ConnectTimeout):
logger.warning("获取原神资源数据超时...已再次尝试...")
await download_resource_data(semaphore)
except Exception as e:
logger.error(f"获取原神资源数据未知错误 {type(e)}:{e}")
# 下载原神地图并拼图
@@ -164,55 +167,65 @@ async def download_map_init(
_map = map_path / "map.png"
if _map.exists() and os.path.getsize(_map) > 1024 * 1024 * 30:
_map.unlink()
response = await AsyncHttpx.get(MAP_URL)
if response.status_code == 200:
data = response.json()
if data["message"] == "OK":
data = json.loads(data["data"]["info"]["detail"])
CENTER_POINT = (data["origin"][0], data["origin"][1])
if not _map.exists():
data = data["slices"]
idx = 0
for _map_data in data[0]:
map_url = _map_data['url']
await download_image(
map_url,
f"{map_path}/{idx}.png",
semaphore,
force_flag=flag,
)
idx += 1
_w, h = CreateImg(0, 0, background=f"{map_path}/0.png", ratio=MAP_RATIO).size
w = _w * len(os.listdir(map_path))
map_file = CreateImg(w, h, _w, h, ratio=MAP_RATIO)
for i in range(idx):
map_file.paste(CreateImg(0, 0, background=f"{map_path}/{i}.png", ratio=MAP_RATIO))
map_file.save(f"{map_path}/map.png")
try:
response = await AsyncHttpx.get(MAP_URL)
if response.status_code == 200:
data = response.json()
if data["message"] == "OK":
data = json.loads(data["data"]["info"]["detail"])
CENTER_POINT = (data["origin"][0], data["origin"][1])
if not _map.exists():
data = data["slices"]
idx = 0
for _map_data in data[0]:
map_url = _map_data['url']
await download_image(
map_url,
f"{map_path}/{idx}.png",
semaphore,
force_flag=flag,
)
idx += 1
_w, h = CreateImg(0, 0, background=f"{map_path}/0.png", ratio=MAP_RATIO).size
w = _w * len(os.listdir(map_path))
map_file = CreateImg(w, h, _w, h, ratio=MAP_RATIO)
for i in range(idx):
map_file.paste(CreateImg(0, 0, background=f"{map_path}/{i}.png", ratio=MAP_RATIO))
map_file.save(f"{map_path}/map.png")
else:
logger.warning(f'获取原神地图失败 msg: {data["message"]}')
else:
logger.warning(f'获取原神地图失败 msg: {data["message"]}')
else:
logger.warning(f"获取原神地图失败 code:{response.status}")
logger.warning(f"获取原神地图失败 code:{response.status_code}")
except (TimeoutError, ConnectTimeout):
logger.warning("下载原神地图数据超时....")
except Exception as e:
logger.error(f"下载原神地图数据超时 {type(e)}:{e}")
# 下载资源类型数据
async def download_resource_type():
resource_type_file.parent.mkdir(parents=True, exist_ok=True)
response = await AsyncHttpx.get(LABEL_URL)
if response.status_code == 200:
data = response.json()
if data["message"] == "OK":
data = data["data"]["tree"]
resource_data = {}
for x in data:
id_ = x["id"]
resource_data[id_] = x
with open(resource_type_file, "w", encoding="utf8") as f:
json.dump(resource_data, f, ensure_ascii=False, indent=4)
logger.info(f"更新原神资源类型成功...")
try:
response = await AsyncHttpx.get(LABEL_URL)
if response.status_code == 200:
data = response.json()
if data["message"] == "OK":
data = data["data"]["tree"]
resource_data = {}
for x in data:
id_ = x["id"]
resource_data[id_] = x
with open(resource_type_file, "w", encoding="utf8") as f:
json.dump(resource_data, f, ensure_ascii=False, indent=4)
logger.info(f"更新原神资源类型成功...")
else:
logger.warning(f'获取原神资源类型失败 msg: {data["message"]}')
else:
logger.warning(f'获取原神资源类型失败 msg: {data["message"]}')
else:
logger.warning(f"获取原神资源类型失败 code:{response.status_code}")
logger.warning(f"获取原神资源类型失败 code:{response.status_code}")
except (TimeoutError, ConnectTimeout):
logger.warning("下载原神资源类型数据超时....")
except Exception as e:
logger.error(f"载原神资源类型数据超时 {type(e)}:{e}")
# 初始化资源图标
+1 -2
View File
@@ -1,7 +1,6 @@
from models.bag_user import BagUser
from utils.utils import is_number, get_local_proxy, get_user_avatar
from utils.utils import is_number, get_user_avatar
from utils.image_utils import CreateImg
from utils.user_agent import get_user_agent
from configs.path_config import IMAGE_PATH
from .model import RedbagUser
import random
@@ -67,7 +67,7 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
if length == 0:
logger.warning(f"图库 {path} 为空,调用取消!")
await send_img.finish("该图库中没有图片噢")
index = img_id if img_id else str(random.randint(0, length))
index = img_id if img_id else str(random.randint(0, length - 1))
if not is_number(index):
return
if int(index) > length - 1 or int(index) < 0:
@@ -22,7 +22,7 @@ __plugin_des__ = "指定图库图片上传"
__plugin_cmd__ = ["上传图片 [图库] [图片]", "连续上传图片 [图库]", "查看公开图库"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {"admin_level": Config.get_config("image_management", "DELETE_IMAGE_LEVEL")}
__plugin_settings__ = {"admin_level": Config.get_config("image_management", "UPLOAD_IMAGE_LEVEL")}
upload_img = on_command("上传图片", rule=to_me(), priority=5, block=True)
+48 -48
View File
@@ -1,48 +1,48 @@
from nonebot import on_command
from nonebot.adapters.cqhttp.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from models.group_member_info import GroupInfoUser
from datetime import timedelta
from models.level_user import LevelUser
__zx_plugin_name__ = "个人信息权限查看"
__plugin_usage__ = """
usage:
个人信息权限查看
指令:
我的信息
我的权限
""".strip()
__plugin_des__ = "我们还记得你和你的权利"
__plugin_cmd__ = ["我的信息", "我的权限"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
get_my_group_info = on_command("我的信息", permission=GROUP, priority=1, block=True)
my_level = on_command("我的权限", permission=GROUP, priority=5, block=True)
@get_my_group_info.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
result = await get_member_info(event.user_id, event.group_id)
await get_my_group_info.finish(result)
async def get_member_info(user_qq: int, group_id: int) -> str:
user = await GroupInfoUser.get_member_info(user_qq, group_id)
if user is None:
return "该群员不在列表中,请更新群成员信息"
result = ""
result += "昵称:" + user.user_name + "\n"
result += "加群时间:" + str(user.user_join_time.date() + timedelta(hours=8))
return result
@my_level.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if (level := await LevelUser.get_user_level(event.user_id, event.group_id)) == -1:
await my_level.finish("您目前没有任何权限了,硬要说的话就是0吧~", at_sender=True)
await my_level.finish(f"您目前的权限等级:{level}", at_sender=True)
from nonebot import on_command
from nonebot.adapters.cqhttp.permission import GROUP
from nonebot.typing import T_State
from nonebot.adapters.cqhttp import Bot, GroupMessageEvent
from models.group_member_info import GroupInfoUser
from datetime import timedelta
from models.level_user import LevelUser
__zx_plugin_name__ = "个人信息权限查看"
__plugin_usage__ = """
usage:
个人信息权限查看
指令:
我的信息
我的权限
""".strip()
__plugin_des__ = "我们还记得你和你的权利"
__plugin_cmd__ = ["我的信息", "我的权限"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
get_my_group_info = on_command("我的信息", permission=GROUP, priority=1, block=True)
my_level = on_command("我的权限", permission=GROUP, priority=5, block=True)
@get_my_group_info.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
result = await get_member_info(event.user_id, event.group_id)
await get_my_group_info.finish(result)
async def get_member_info(user_qq: int, group_id: int) -> str:
user = await GroupInfoUser.get_member_info(user_qq, group_id)
if user is None:
return "该群员不在列表中,请更新群成员信息"
result = ""
result += "昵称:" + user.user_name + "\n"
result += "加群时间:" + str(user.user_join_time.date() + timedelta(hours=8))
return result
@my_level.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if (level := await LevelUser.get_user_level(event.user_id, event.group_id)) == -1:
await my_level.finish("您目前没有任何权限了,硬要说的话就是0吧~", at_sender=True)
await my_level.finish(f"您目前的权限等级:{level}", at_sender=True)
+6
View File
@@ -0,0 +1,6 @@
-73
View File
@@ -1,13 +1,5 @@
from configs.config import Config
from services.log import logger
from .model.omega_pixiv_illusts import OmegaPixivIllusts
from pathlib import Path
from nonebot import Driver
from typing import List
from datetime import datetime
import nonebot
import asyncio
import os
__zx_plugin_name__ = "更新扩展图库Omega [Hidden]"
@@ -67,69 +59,4 @@ Config.add_plugin_config(
nonebot.load_plugins("plugins/pix_gallery")
driver: Driver = nonebot.get_driver()
@driver.on_startup
async def _init_omega_pixiv_illusts():
omega_pixiv_illusts = None
for file in os.listdir("."):
if "omega_pixiv_illusts" in file and ".sql" in file:
omega_pixiv_illusts = Path() / file
if omega_pixiv_illusts:
with open(omega_pixiv_illusts, "r", encoding="utf8") as f:
lines = f.readlines()
tasks = []
length = len([x for x in lines if "INSERT INTO" in x.upper()])
all_pid = await OmegaPixivIllusts.get_all_pid()
index = 0
logger.info("检测到OmegaPixivIllusts数据库,准备开始更新....")
for line in lines:
if "INSERT INTO" in line.upper():
index += 1
tasks.append(
asyncio.ensure_future(_tasks(line, all_pid, length, index))
)
await asyncio.gather(*tasks)
omega_pixiv_illusts.unlink()
async def _tasks(line: str, all_pid: List[int], length: int, index: int):
data = line.split("VALUES", maxsplit=1)[-1].strip()
if data.startswith("("):
data = data[1:]
if data.endswith(");"):
data = data[:-2]
x = data.split(maxsplit=3)
pid = int(x[1][:-1].strip())
if pid in all_pid:
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
return
uid = int(x[2][:-1].strip())
x = x[3].split(", '")
title = x[0].strip()[1:-1]
tmp = x[1].split(", ")
author = tmp[0].strip()[:-1]
nsfw_tag = int(tmp[1])
width = int(tmp[2])
height = int(tmp[3])
tags = x[2][:-1]
url = x[3][:-1]
if await OmegaPixivIllusts.add_image_data(
pid,
title,
width,
height,
url,
uid,
author,
nsfw_tag,
tags,
datetime.min,
datetime.min,
):
logger.info(
f"成功添加OmegaPixivIllusts图库数据 pid:{pid} 本次预计存储 {length} 张,已更新第 {index} 张"
)
else:
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
+7 -4
View File
@@ -30,7 +30,10 @@ headers = {
"Referer": "https://www.pixiv.net",
}
HIBIAPI = None
HIBIAPI = Config.get_config("hibiapi", "HIBIAPI")
if not HIBIAPI:
HIBIAPI = "https://api.obfs.dev"
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] == "/" else HIBIAPI
async def start_update_image_url(
@@ -47,9 +50,6 @@ async def start_update_image_url(
pic_count = 0
tasks = []
semaphore = asyncio.Semaphore(10)
if not HIBIAPI:
HIBIAPI = Config.get_config("hibiapi", "HIBIAPI")
HIBIAPI = HIBIAPI[:-1] if HIBIAPI[-1] else HIBIAPI
for keyword in current_keyword:
for page in range(1, 110):
if keyword.startswith("uid:"):
@@ -390,3 +390,6 @@ def _check_black(img_urls: List[str], black: List[str]) -> bool:
if b in img_url:
return False
return True
+1 -3
View File
@@ -1,3 +1 @@
from .pixiv_keyword_user import *
from .omega_pixiv_illusts import *
from .pixiv import *
@@ -139,3 +139,15 @@ class OmegaPixivIllusts(db.Model):
data = await cls.select('pid').gino.all()
return [x[0] for x in data]
@classmethod
async def test(cls, nsfw_tag: int = 1):
if nsfw_tag is not None:
query = cls.query.where(cls.nsfw_tag == nsfw_tag)
else:
query = cls.query
query = query.where((cls.width - cls.height) < 50)
for x in await query.gino.all():
print(x.pid)
+72
View File
@@ -4,9 +4,16 @@ from nonebot.permission import SUPERUSER
from nonebot.typing import T_State
from .data_source import start_update_image_url
from .model.pixiv_keyword_user import PixivKeywordUser
from .model.omega_pixiv_illusts import OmegaPixivIllusts
from .model.pixiv import Pixiv
from nonebot.adapters.cqhttp import Bot, MessageEvent
import time
from services.log import logger
from pathlib import Path
from typing import List
from datetime import datetime
import asyncio
import os
__zx_plugin_name__ = "pix检查更新 [Superuser]"
@@ -36,6 +43,8 @@ check_not_update_uid_pid = on_command(
block=True,
)
check_omega = on_command("检测omega图库", permission=SUPERUSER, priority=1, block=True)
@start_update.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
@@ -130,3 +139,66 @@ async def _(bot: Bot, event: MessageEvent, state: T_State):
f"累计更新PID {pid_count} 个\n"
f"累计更新图片 {pic_count} 张" + "\n耗时:{:.2f}秒".format((time.time() - start_time))
)
@check_omega.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
async def _tasks(line: str, all_pid: List[int], length: int, index: int):
data = line.split("VALUES", maxsplit=1)[-1].strip()
if data.startswith("("):
data = data[1:]
if data.endswith(");"):
data = data[:-2]
x = data.split(maxsplit=3)
pid = int(x[1][:-1].strip())
if pid in all_pid:
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
return
uid = int(x[2][:-1].strip())
x = x[3].split(", '")
title = x[0].strip()[1:-1]
tmp = x[1].split(", ")
author = tmp[0].strip()[:-1]
nsfw_tag = int(tmp[1])
width = int(tmp[2])
height = int(tmp[3])
tags = x[2][:-1]
url = x[3][:-1]
if await OmegaPixivIllusts.add_image_data(
pid,
title,
width,
height,
url,
uid,
author,
nsfw_tag,
tags,
datetime.min,
datetime.min,
):
logger.info(
f"成功添加OmegaPixivIllusts图库数据 pid:{pid} 本次预计存储 {length} 张,已更新第 {index} 张"
)
else:
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
omega_pixiv_illusts = None
for file in os.listdir("."):
if "omega_pixiv_illusts" in file and ".sql" in file:
omega_pixiv_illusts = Path() / file
if omega_pixiv_illusts:
with open(omega_pixiv_illusts, "r", encoding="utf8") as f:
lines = f.readlines()
tasks = []
length = len([x for x in lines if "INSERT INTO" in x.upper()])
all_pid = await OmegaPixivIllusts.get_all_pid()
index = 0
logger.info("检测到OmegaPixivIllusts数据库,准备开始更新....")
for line in lines:
if "INSERT INTO" in line.upper():
index += 1
tasks.append(
asyncio.ensure_future(_tasks(line, all_pid, length, index))
)
await asyncio.gather(*tasks)
omega_pixiv_illusts.unlink()
+5
View File
@@ -64,6 +64,11 @@ __plugin_configs__ = {
"value": 10,
"help": "图片下载超时限制",
"default_value": 10
},
"MAX_PAGE_LIMIT": {
"value": 20,
"help": "作品最大页数限制,超过的作品会被略过",
"default_value": 20
}
}
Config.add_plugin_config(
+6 -1
View File
@@ -89,8 +89,13 @@ async def parser_data(
else:
return ["网络不太好?没有该页数?也许过一会就好了..."], 998
num = num if num < 30 else 30
data = data[:num]
_data = []
for x in data:
if x["page_count"] < Config.get_config("pixiv_rank_search", "MAX_PAGE_LIMIT"):
_data.append(x)
if len(_data) == num:
break
for x in _data:
if type_ == "search" and r18 == 1:
if "R-18" in str(x["tags"]):
continue
-133
View File
@@ -1,133 +0,0 @@
# # -*- coding: utf-8 -*-
# from typing import Dict
#
# from aiohttp.client_exceptions import ClientError
# from nonebot.plugin import on_command, on_message
# from nonebot.adapters.cqhttp import Bot, MessageEvent, GroupMessageEvent
# from nonebot.typing import T_State
# from services.log import logger
# from utils.utils import get_message_text, get_message_imgs
# from configs.config import Config
# from nonebot.rule import to_me
#
#
#
# __zx_plugin_name__ = "识图"
# __plugin_usage__ = """
# usage:
# 识别图片 [二次元图片]
# 指令:
# 识图 [图片]
# """.strip()
# __plugin_des__ = "以图搜图,看破本源"
# __plugin_cmd__ = ["识图"]
# __plugin_type__ = ("一些工具",)
# __plugin_version__ = 0.1
# __plugin_author__ = "synodriver"
# __plugin_settings__ = {
# "level": 5,
# "default_status": True,
# "limit_superuser": False,
# "cmd": ["识图"],
# }
# __plugin_configs__ = {
# "MAX_FIND_IMAGE_COUNT": {"value": 3, "help": "识图返回的最大结果数", "default_value": 3}
# }
#
#
# async def get_des(url: str, mode: str, user_id: int):
# """
# :param url: 图片链接
# :param mode: 图源
# :param user_id: 用户 id
# """
# if mode == "iqdb":
# async for msg in get_des_iqdb(url):
# yield msg
# elif mode == "ex":
# async for msg in get_des_ex(url):
# yield msg
# elif mode == "trace":
# async for msg in get_des_trace(url):
# yield msg
# elif mode == "yandex":
# async for msg in get_des_yandex(url):
# yield msg
# elif mode.startswith("asc"):
# async for msg in get_des_asc(url, user_id):
# yield msg
# else:
# async for msg in get_des_sau(url, user_id):
# yield msg
#
#
# setu = on_command("识图", aliases={"search"}, block=True, priority=5)
#
#
# @setu.handle()
# async def handle_first_receive(bot: Bot, event: MessageEvent, state: T_State):
# msg = get_message_text(event.json())
# imgs = get_message_imgs(event.json())
# if imgs:
# state["setu"] = imgs[0]
# if msg:
# state["mod"] = msg
#
#
# # ex/nao/trace/iqdb/ascii2d
# # @setu.got("mod", prompt="从哪里查找呢? ex/nao/trace/iqdb/ascii2d")
# # async def get_func(bot: Bot, event: MessageEvent, state: dict):
# # pass
#
#
# @setu.args_parser
# async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
# imgs = get_message_imgs(event.json())
# msg = get_message_text(event.json())
# if not imgs:
# await setu.reject()
# if msg:
# state["mod"] = msg
# state["setu"] = imgs[0]
#
#
# @setu.got("setu", prompt="图呢?")
# async def get_setu(bot: Bot, event: MessageEvent, state: T_State):
# """
# 发现没有的时候要发问
# :return:
# """
# url: str = state["setu"]
# mod: str = state["mod"] if state.get("mod") else "nao" # 模式
# try:
# await bot.send(event=event, message="正在处理图片")
# idx = 1
# async for msg in get_des(url, mod, event.user_id):
# if msg:
# await bot.send(event=event, message=msg)
# if idx == Config.get_config(
# "nonebot_plugin_picsearcher", "MAX_FIND_IMAGE_COUNT"
# ):
# break
# idx += 1
# if id == 1:
# await bot.send(event=event, message="没找着.")
# logger.info(
# f"(USER {event.user_id}, GROUP "
# f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 识图:{url}"
# )
# # image_data: List[Tuple] = await get_pic_from_url(url)
# # await setu.finish("hso")
# except IndexError:
# # await bot.send(event, traceback.format_exc())
# await setu.finish("参数错误")
# except ClientError:
# await setu.finish("连接失败")
#
#
#
#
#
#
#
#
-4
View File
@@ -1,4 +0,0 @@
API_URL_SAUCENAO = 'https://saucenao.com/search.php'
API_URL_ASCII2D = 'https://ascii2d.net/search/url/'
API_URL_IQDB = 'https://iqdb.org/'
-47
View File
@@ -1,47 +0,0 @@
from utils.user_agent import get_user_agent
from utils.utils import get_local_proxy
async def get_saucenao_identify_result(url: str) -> Result.DictListResult:
fetcher = HttpFetcher(timeout=10, flag='search_image_saucenao', headers=HEADERS)
if not API_KEY:
logger.opt(colors=True).warning(f'<r>Saucenao API KEY未配置</r>, <y>无法使用Saucenao API进行识图!</y>')
return Result.DictListResult(error=True, info='Saucenao API KEY未配置', result=[])
__payload = {'output_type': 2,
'api_key': API_KEY,
'testmode': 1,
'numres': 6,
'db': 999,
'url': url}
saucenao_result = await fetcher.get_json(url=API_URL_SAUCENAO, params=__payload)
if saucenao_result.error:
logger.warning(f'get_saucenao_identify_result failed, Network error: {saucenao_result.info}')
return Result.DictListResult(error=True, info=f'Network error: {saucenao_result.info}', result=[])
__result_json = saucenao_result.result
if __result_json['header']['status'] != 0:
logger.error(f"get_saucenao_identify_result failed, DataSource error, "
f"status code: {__result_json['header']['status']}")
return Result.DictListResult(
error=True, info=f"DataSource error, status code: {__result_json['header']['status']}", result=[])
__result = []
for __item in __result_json['results']:
try:
if int(float(__item['header']['similarity'])) < 75:
continue
else:
__result.append({'similarity': __item['header']['similarity'],
'thumbnail': __item['header']['thumbnail'],
'index_name': __item['header']['index_name'],
'ext_urls': __item['data']['ext_urls']})
except Exception as res_err:
logger.warning(f"get_saucenao_identify_result failed: {repr(res_err)}, can not resolve results")
continue
return Result.DictListResult(error=False, info='Success', result=__result)
+1 -1
View File
@@ -41,7 +41,7 @@ async def get_setu_urls(
url, timeout=Config.get_config("send_setu", "TIMEOUT"), params=params
)
if response.status_code == 200:
data = await response.json()
data = response.json()
if not data["error"]:
data = data["data"]
(
+22 -26
View File
@@ -37,8 +37,8 @@ async def update_old_setu_data():
for x in data:
if file == setu_data_file:
idx = index
if 'R-18' in data[x]["tags"]:
data[x]["tags"].remove('R-18')
if "R-18" in data[x]["tags"]:
data[x]["tags"].remove("R-18")
else:
idx = r18_index
img_url = (
@@ -58,14 +58,16 @@ async def update_old_setu_data():
",".join(data[x]["tags"]),
)
count += 1
if 'R-18' in data[x]["tags"]:
if "R-18" in data[x]["tags"]:
r18_index += 1
else:
index += 1
logger.info(f'添加旧色图数据成功 PID:{data[x]["pid"]} index:{idx}....')
except UniqueViolationError:
fail_count += 1
logger.info(f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....')
logger.info(
f'添加旧色图数据失败,色图重复 PID:{data[x]["pid"]} index:{idx}....'
)
file.unlink()
setu_url_path = path / "setu_url.json"
setu_r18_url_path = path / "setu_r18_url.json"
@@ -106,21 +108,25 @@ async def update_setu_img():
url_ = image.img_url
ws_url = Config.get_config("pixiv", "PIXIV_NGINX_URL")
if ws_url:
url_ = url_.replace("i.pximg.net", ws_url).replace("i.pixiv.cat", ws_url)
url_ = url_.replace("i.pximg.net", ws_url).replace(
"i.pixiv.cat", ws_url
)
try:
if not await AsyncHttpx.download_file(url_, rar_path / f'{image.local_id}.jpg'):
if not await AsyncHttpx.download_file(
url_, rar_path / f"{image.local_id}.jpg"
):
continue
_success += 1
try:
if (
os.path.getsize(
rar_path / f'{image.local_id}.jpg',
rar_path / f"{image.local_id}.jpg",
)
> 1024 * 1024 * 1.5
):
compressed_image(
rar_path / f"{image.local_id}.jpg",
path / f"{image.local_id}.jpg"
path / f"{image.local_id}.jpg",
)
else:
logger.info(
@@ -134,30 +140,20 @@ async def update_setu_img():
except FileNotFoundError:
logger.warning(f"文件 {image.local_id}.jpg 不存在,跳过...")
continue
img_hash = str(
get_img_hash(
f"{path}/{image.local_id}.jpg"
)
)
await Setu.update_setu_data(
image.pid, img_hash=img_hash
)
img_hash = str(get_img_hash(f"{path}/{image.local_id}.jpg"))
await Setu.update_setu_data(image.pid, img_hash=img_hash)
except Exception as e:
_success -= 1
logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
if type(e) not in error_type:
error_type.append(type(e))
error_info.append(
f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}"
)
error_info.append(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
else:
logger.info(f'更新色图 {image.local_id}.jpg 已存在')
error_info = ['无报错..'] if not error_info else error_info
if count or _success or (error_info and "无报错.." not in error_info):
logger.info(f"更新色图 {image.local_id}.jpg 已存在")
error_info = ["无报错.."] if not error_info else error_info
if count or _success or error_info:
await get_bot().send_private_msg(
user_id=int(list(get_bot().config.superusers)[0]),
message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,以下为更新时未知错误:\n'
+ "\n".join(error_info),
message=f'{str(datetime.now()).split(".")[0]} 更新 色图 完成,本地存在 {count} 张,实际更新 {_success} 张,'
f"以下为更新时未知错误:\n" + "\n".join(error_info),
)
+2 -2
View File
@@ -43,10 +43,10 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
msg = get_message_text(event.json()).strip().split(" ")
num = 1
if len(msg) > 1:
if is_number(msg[1]):
if is_number(msg[1]) and int(msg[1]) > 0:
num = int(msg[1])
else:
await buy.finish("购买的数量要是数字!", at_sender=True)
await buy.finish("购买的数量要是数字且大于0!", at_sender=True)
# print(msg, num)
if is_number(msg[0]):
msg = int(msg[0])
+17 -9
View File
@@ -19,17 +19,23 @@ data_dir = Path(DATA_PATH) / "word_bank"
data_dir.mkdir(parents=True, exist_ok=True)
message_handle = on_message(priority=7, block=True, rule=check)
message_handle = on_message(priority=5, block=True, rule=check)
@message_handle.handle()
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
path = data_dir / f"{event.group_id}"
q = await WordBank.check(event.group_id, get_message_text(event.json()))
placeholder_list = [
(x.split("<_s>")[0], x.split("<_s>")[1])
for x in q.format.split("<format>")[:-1]
] if q.format else []
q = await WordBank.check(
event.group_id, get_message_text(event.json()), event.is_tome()
)
placeholder_list = (
[
(x.split("<_s>")[0], x.split("<_s>")[1])
for x in q.format.split("<format>")[:-1]
]
if q.format
else []
)
answer = ""
_a = q.answer
if not placeholder_list:
@@ -37,8 +43,10 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
else:
for idx, placeholder in placeholder_list:
if placeholder.endswith("jpg"):
answer += _a[:_a.find(f"[__placeholder_{idx}]")] + image(path / placeholder)
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + image(
path / placeholder
)
else:
answer += _a[:_a.find(f"[__placeholder_{idx}]")] + at(placeholder)
_a = _a[_a.find(f"[__placeholder_{idx}]") + len(f"[__placeholder_{idx}]"):]
answer += _a[: _a.find(f"[__placeholder_{idx}]")] + at(placeholder)
_a = _a[_a.find(f"[__placeholder_{idx}]") + len(f"[__placeholder_{idx}]") :]
await message_handle.send(answer)
+27 -5
View File
@@ -3,6 +3,7 @@ from typing import Optional, List, Union, Tuple
from datetime import datetime
from pathlib import Path
from configs.path_config import DATA_PATH
import re
import random
@@ -97,18 +98,39 @@ class WordBank(db.Model):
q = await cls.query.where(cls.group_id == group_id).gino.all()
q = [x.problem for x in q]
q.sort()
return list(set(q))
_tmp = []
for problem in q:
if "[_to_me" in problem:
r = re.search(r"\[_to_me\|(.*?)](.*)", problem)
if r:
bot_name = r.group(1)
problem = problem.replace(f"[_to_me|{bot_name}]", bot_name)
_tmp.append(problem)
return list(set(_tmp))
@classmethod
async def check(cls, group_id: int, problem: str) -> Optional["WordBank"]:
async def check(cls, group_id: int, problem: str, is_tome: bool = False) -> Optional["WordBank"]:
"""
检测词条并随机返回
:param group_id: 群号
:param problem: 问题
:param is_tome:是否at真寻
"""
q = await cls.query.where(
(cls.group_id == group_id) & (cls.problem == problem)
).gino.all()
if is_tome:
q = await cls.query.where(
(cls.group_id == group_id)
).gino.all()
q = [x for x in q if "[_to_me" in x.problem]
if q:
for x in q:
r = re.search(r"\[_to_me\|(.*?)](.*)", x.problem)
if r and r.group(2) == problem:
return x
return None
else:
q = await cls.query.where(
(cls.group_id == group_id) & (cls.problem == problem)
).gino.all()
return random.choice(q) if q else None
@classmethod
+1 -1
View File
@@ -7,6 +7,6 @@ from .model import WordBank
async def check(bot: Bot, event: Event, state: T_State) -> bool:
if isinstance(event, GroupMessageEvent):
return bool(
await WordBank.check(event.group_id, get_message_text(event.json()))
await WordBank.check(event.group_id, get_message_text(event.json()), event.is_tome())
)
return False
+7 -1
View File
@@ -67,7 +67,13 @@ async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
if not answer:
await add_word.finish("未检测到词条回答...")
idx = 0
_builder = WordBankBuilder(event.user_id, event.group_id, problem)
for n in bot.config.nickname:
if problem.startswith(n):
_problem = f"[_to_me|{n}]" + problem[len(n):]
break
else:
_problem = problem
_builder = WordBankBuilder(event.user_id, event.group_id, _problem)
for at_ in get_message_at(event.json()):
r = re.search(rf"\[CQ:at,qq={at_}]", answer)
if r:
+1
View File
@@ -83,3 +83,4 @@ win32-setctime==1.0.3
yarl==1.6.3
zipp==3.4.1
ruamel.yaml==0.17.16
retrying==1.3.3
Regular → Executable
+2 -2
View File
@@ -1,2 +1,2 @@
from .db_context import *
from .log import *
from .db_context import *
from .log import *
Regular → Executable
+25 -25
View File
@@ -1,25 +1,25 @@
from gino import Gino
from .log import logger
from configs.config import bind, sql_name, user, password, address, port, database
# 全局数据库连接对象
db = Gino()
async def init():
i_bind = bind
if not i_bind:
i_bind = f"{sql_name}://{user}:{password}@{address}:{port}/{database}"
try:
await db.set_bind(i_bind)
await db.gino.create_all()
logger.info(f'Database loaded successfully!')
except Exception as e:
raise Exception(f'数据库连接错误.... e: {e}')
async def disconnect():
await db.pop_bind().close()
from gino import Gino
from .log import logger
from configs.config import bind, sql_name, user, password, address, port, database
# 全局数据库连接对象
db = Gino()
async def init():
i_bind = bind
if not i_bind:
i_bind = f"{sql_name}://{user}:{password}@{address}:{port}/{database}"
try:
await db.set_bind(i_bind)
await db.gino.create_all()
logger.info(f'Database loaded successfully!')
except Exception as e:
raise Exception(f'数据库连接错误.... e: {e}')
async def disconnect():
await db.pop_bind().close()
Regular → Executable
View File
+3 -1
View File
@@ -4,7 +4,9 @@
"models",
"basic_plugins",
"utils",
"services",
"configs"
],
"add_file": [],
"delete_file": []
}
}
+5 -1
View File
@@ -8,7 +8,9 @@ from asyncio.exceptions import TimeoutError
from nonebot.adapters.cqhttp import MessageSegment
from playwright.async_api import Page
from .message_builder import image
from httpx import ConnectTimeout
from .browser import get_browser
from retrying import retry
import asyncio
import aiofiles
import httpx
@@ -19,6 +21,7 @@ class AsyncHttpx:
proxy = {"http://": get_local_proxy()}
@classmethod
@retry(stop_max_attempt_number=3)
async def get(
cls,
url: str,
@@ -149,7 +152,7 @@ class AsyncHttpx:
await wf.write(content)
logger.info(f"下载图片 {url} 成功.. Path:{path.absolute()}")
return True
except TimeoutError:
except (TimeoutError, ConnectTimeout):
pass
else:
logger.error(f"下载图片 {url} 下载超时.. Path:{path.absolute()}")
@@ -312,6 +315,7 @@ class AsyncPlaywright:
return image(path)
except Exception as e:
logger.warning(f"Playwright 截图 url:{url} element:{element} 发生错误 {type(e)}:{e}")
finally:
if page:
await page.close()
return None
-4
View File
@@ -13,10 +13,7 @@ from .admin_manager import AdminManager
from .none_plugin_count_manager import NonePluginCountManager
from .requests_manager import RequestManager
from configs.path_config import DATA_PATH
from nonebot import Driver
import nonebot
driver: Driver = nonebot.get_driver()
# 群功能开关 | 群被动技能 | 群权限 管理
group_manager: Optional[GroupManager] = GroupManager(
@@ -69,4 +66,3 @@ requests_manager: Optional[RequestManager] = RequestManager(
# 管理员命令管理器
admin_manager = AdminManager()
+7 -1
View File
@@ -2,9 +2,15 @@ from typing import Optional, List, Union, Dict
from pathlib import Path
from .data_class import StaticData
from utils.utils import get_matchers, get_bot
from configs.config import Config
import nonebot
Config.add_plugin_config(
"group_manager", "DEFAULT_GROUP_LEVEL", 5, help_="默认群权限", default_value=5
)
class GroupManager(StaticData):
"""
群权限 | 功能 | 聊天时间 管理器
@@ -274,7 +280,7 @@ class GroupManager(StaticData):
参数:
:param group_id: 群号
"""
default_group_level = 5 # Config.get_config("group_manager")
default_group_level = Config.get_config("group_manager", "DEFAULT_GROUP_LEVEL")
if not default_group_level:
default_group_level = 5
if not self._data["group_manager"].get(group_id):