From a053c120c46b4e789f7f393c40f866e209c54531 Mon Sep 17 00:00:00 2001
From: yajiwa <839790708@qq.com>
Date: Mon, 6 Feb 2023 02:06:36 +0800
Subject: [PATCH 1/5] update gold_redbag
---
plugins/gold_redbag/__init__.py | 129 +++++++++++++-------------------
1 file changed, 54 insertions(+), 75 deletions(-)
diff --git a/plugins/gold_redbag/__init__.py b/plugins/gold_redbag/__init__.py
index 313125f3..8e578fcc 100755
--- a/plugins/gold_redbag/__init__.py
+++ b/plugins/gold_redbag/__init__.py
@@ -29,7 +29,6 @@ from nonebot.params import CommandArg
import random
import time
-
__zx_plugin_name__ = "金币红包"
__plugin_usage__ = """
usage:
@@ -64,11 +63,16 @@ __plugin_settings__ = {
}
__plugin_resources__ = {"prts": IMAGE_PATH}
+
+async def rule(event: GroupMessageEvent) -> bool:
+ return check_on_gold_red(event)
+
+
gold_redbag = on_command(
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
)
-open_ = on_command("开", aliases={"抢"}, priority=5, block=True, permission=GROUP)
+open_ = on_command("开", aliases={"抢"}, priority=5, block=True, permission=GROUP, rule=rule)
poke_ = on_notice(priority=6, block=False)
@@ -85,27 +89,11 @@ festive_redbag_data = {}
# 阻断其他poke
@run_preprocessor
-async def _(matcher: Matcher, event: PokeNotifyEvent):
+async def _(matcher: Matcher, event: PokeNotifyEvent, ):
try:
if matcher.type == "notice" and event.self_id == event.target_id:
- flag1 = True
- flag2 = True
- try:
- if festive_redbag_data[event.group_id]["user_id"]:
- if (
- event.user_id
- in festive_redbag_data[event.group_id]["open_user"]
- ):
- flag1 = False
- except KeyError:
- flag1 = False
- try:
- if redbag_data[event.group_id]["user_id"]:
- if event.user_id in redbag_data[event.group_id]["open_user"]:
- flag2 = False
- except KeyError:
- flag2 = False
- if flag1 or flag2:
+ flag = check_on_gold_red(event)
+ if flag:
if matcher.plugin_name == "poke":
raise IgnoredException("目前正在抢红包...")
else:
@@ -121,8 +109,8 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
try:
if time.time() - redbag_data[event.group_id]["time"] > 60:
amount = (
- redbag_data[event.group_id]["amount"]
- - redbag_data[event.group_id]["open_amount"]
+ redbag_data[event.group_id]["amount"]
+ - redbag_data[event.group_id]["open_amount"]
)
await return_gold(redbag_data[event.group_id]["user_id"], event.group_id, amount)
await gold_redbag.send(
@@ -185,43 +173,21 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
msg = (
msg.replace("!", "")
- .replace("!", "")
- .replace(",", "")
- .replace(",", "")
- .replace(".", "")
- .replace("。", "")
+ .replace("!", "")
+ .replace(",", "")
+ .replace(",", "")
+ .replace(".", "")
+ .replace("。", "")
)
if msg:
if "红包" not in msg:
return
- flag1 = True
- flag2 = True
- open_flag1 = True
- open_flag2 = True
try:
- if festive_redbag_data[event.group_id]["user_id"]:
- if event.user_id in festive_redbag_data[event.group_id]["open_user"]:
- open_flag1 = False
- except KeyError:
- open_flag1 = False
- flag1 = False
- try:
- if redbag_data[event.group_id]["user_id"]:
- if event.user_id in redbag_data[event.group_id]["open_user"]:
- open_flag2 = False
- except KeyError:
- flag2 = False
- if not flag1 and not flag2:
- await open_.finish("目前没有红包可以开...", at_sender=True)
- if open_flag1 or open_flag2:
- try:
- await open_.send(
- image(b64=await get_redbag_img(event.user_id, event.group_id)),
- at_sender=True,
+ await open_.send(
+ image(b64=await get_redbag_img(event.user_id, event.group_id)),
+ at_sender=True,
)
- except KeyError:
- await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
- else:
+ except KeyError:
await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
@@ -229,19 +195,8 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
async def _poke_(event: PokeNotifyEvent):
global redbag_data, festive_redbag_data
if event.self_id == event.target_id:
- flag1 = True
- flag2 = True
- try:
- if event.user_id in festive_redbag_data[event.group_id]["open_user"]:
- flag1 = False
- except KeyError:
- flag1 = False
- try:
- if event.user_id in redbag_data[event.group_id]["open_user"]:
- flag2 = False
- except KeyError:
- flag2 = False
- if not flag1 and not flag2:
+ flag = check_on_gold_red(event)
+ if not flag:
return
await poke_.send(
image(b64=await get_redbag_img(event.user_id, event.group_id)),
@@ -331,7 +286,7 @@ async def _(bot: Bot, arg: Message = CommandArg()):
await bot.send_group_msg(
group_id=g,
message=f"{NICKNAME}发起了金币红包\n金额:{amount}\n数量:{num}\n"
- + image(
+ + image(
b64=await generate_send_redbag_pic(int(bot.self_id), greetings)
),
)
@@ -342,13 +297,13 @@ async def _(bot: Bot, arg: Message = CommandArg()):
# 红包数据初始化
def init_redbag(
- user_id: int,
- group_id: int,
- nickname: str,
- amount: int,
- num: int,
- bot_self_id: int,
- mode: int = 0,
+ user_id: int,
+ group_id: int,
+ nickname: str,
+ amount: int,
+ num: int,
+ bot_self_id: int,
+ mode: int = 0,
):
global redbag_data, festive_redbag_data
data = redbag_data if mode == 0 else festive_redbag_data
@@ -428,3 +383,27 @@ async def end_festive_redbag(bot: Bot, group_id: int):
)
await bot.send_group_msg(group_id=group_id, message=message)
festive_redbag_data[group_id] = {}
+
+
+def check_on_gold_red(event) -> bool:
+ flag1 = True
+ flag2 = True
+ try:
+ if festive_redbag_data[event.group_id]["user_id"]:
+ if (
+ event.user_id
+ in festive_redbag_data[event.group_id]["open_user"]
+ ):
+ flag1 = False
+ except KeyError:
+ flag1 = False
+ try:
+ if redbag_data[event.group_id]["user_id"]:
+ if event.user_id in redbag_data[event.group_id]["open_user"]:
+ flag2 = False
+ except KeyError:
+ flag2 = False
+ if flag1 or flag2:
+ return True
+ else:
+ return False
From 9feea3ba1d3855714baccf14a3e179ecf9b819b3 Mon Sep 17 00:00:00 2001
From: CRAZYShimakaze <674015283@qq.com>
Date: Thu, 16 Feb 2023 22:59:53 +0800
Subject: [PATCH 2/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=8F=92=E4=BB=B6?=
=?UTF-8?q?=E5=B8=AE=E5=8A=A9=E5=91=BD=E4=BB=A4=E4=B8=8D=E7=94=9F=E6=95=88?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
basic_plugins/init_plugin_config/init_plugins_settings.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/basic_plugins/init_plugin_config/init_plugins_settings.py b/basic_plugins/init_plugin_config/init_plugins_settings.py
index ef47798b..4165d1ca 100755
--- a/basic_plugins/init_plugin_config/init_plugins_settings.py
+++ b/basic_plugins/init_plugin_config/init_plugins_settings.py
@@ -27,6 +27,8 @@ def init_plugins_settings():
else:
if plugin_data := plugin_data_manager.get(matcher.plugin_name):
if plugin_settings := plugin_data.plugin_setting:
+ if (name := _module.__getattribute__("__zx_plugin_name__")) not in plugin_settings.cmd:
+ plugin_settings.cmd.append(name)
# 管理员命令
if plugin_data.plugin_type == PluginType.ADMIN:
admin_manager.add_admin_plugin_settings(
From a6105e8a1b2b3517a16622a13cbd7f2e58a3d6a2 Mon Sep 17 00:00:00 2001
From: HibiKier <775757368@qq.com>
Date: Sat, 18 Feb 2023 17:51:22 +0800
Subject: [PATCH 3/5] modified: .gitignore
---
.gitignore | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.gitignore b/.gitignore
index 9a886520..f56858ea 100644
--- a/.gitignore
+++ b/.gitignore
@@ -156,8 +156,9 @@ data/
.env.dev
/resources/text/
/resources/image/
+/resources/temp/
!/resources/template/
-configs/config.py
+/configs/config.py
configs/config.yaml
./.env
./.env.dev
@@ -165,3 +166,4 @@ plugins/csgo_server/
plugins/activity/
!/resources/image/genshin/alc/back.png
!/data/genshin_alc/
+.vscode/launch.json
\ No newline at end of file
From 7685b95031e27dab947a2bf08b37a47958682402 Mon Sep 17 00:00:00 2001
From: HibiKier <775757368@qq.com>
Date: Sat, 18 Feb 2023 18:46:54 +0800
Subject: [PATCH 4/5] modified:
basic_plugins/admin_bot_manage/_data_source.py modified:
basic_plugins/admin_bot_manage/admin_config.py modified:
basic_plugins/admin_bot_manage/custom_welcome_message.py modified:
basic_plugins/admin_bot_manage/timing_task.py modified:
basic_plugins/apscheduler/__init__.py modified:
basic_plugins/ban/__init__.py modified: basic_plugins/ban/data_source.py
modified: basic_plugins/chat_history/chat_message.py modified:
basic_plugins/chat_history/chat_message_handle.py modified:
basic_plugins/group_handle/__init__.py modified:
basic_plugins/hooks/_utils.py modified: basic_plugins/hooks/ban_hook.py
modified: basic_plugins/hooks/chkdsk_hook.py modified:
basic_plugins/init_plugin_config/__init__.py deleted:
basic_plugins/init_plugin_config/init_group_manager.py modified:
basic_plugins/invite_manager/__init__.py new file:
basic_plugins/invite_manager/utils.py modified: basic_plugins/nickname.py
modified: basic_plugins/plugin_shop/__init__.py modified:
basic_plugins/plugin_shop/data_source.py modified:
basic_plugins/scripts.py modified: basic_plugins/shop/__init__.py
modified: basic_plugins/shop/buy.py modified: basic_plugins/shop/gold.py
modified: basic_plugins/shop/my_props/__init__.py deleted:
basic_plugins/shop/reset_today_gold.py modified:
basic_plugins/shop/shop_handle/__init__.py modified:
basic_plugins/shop/shop_handle/data_source.py modified:
basic_plugins/shop/use/__init__.py modified:
basic_plugins/shop/use/data_source.py modified:
basic_plugins/super_cmd/__init__.py modified:
basic_plugins/super_cmd/bot_friend_group.py modified:
basic_plugins/super_cmd/clear_data.py modified:
basic_plugins/super_cmd/exec_sql.py modified:
basic_plugins/super_cmd/manager_group.py modified:
basic_plugins/super_cmd/reload_setting.py modified:
basic_plugins/super_cmd/set_admin_permissions.py deleted:
basic_plugins/super_cmd/super_task_switch.py modified:
basic_plugins/super_cmd/update_friend_group_info.py modified:
basic_plugins/super_help/__init__.py modified:
basic_plugins/update_info.py modified: configs/config.py modified:
configs/utils/__init__.py modified: models/bag_user.py modified:
models/ban_user.py modified: models/chat_history.py modified:
models/friend_user.py modified: models/goods_info.py modified:
models/group_info.py modified: models/group_member_info.py
modified: models/level_user.py modified: models/sign_group_user.py
modified: models/user_shop_gold_log.py modified:
plugins/aconfig/__init__.py modified: plugins/ai/__init__.py
modified: plugins/ai/data_source.py modified:
plugins/bilibili_sub/__init__.py modified:
plugins/bilibili_sub/data_source.py modified:
plugins/bilibili_sub/model.py modified: plugins/black_word/__init__.py
modified: plugins/black_word/model.py modified:
plugins/black_word/utils.py modified: plugins/bt/data_source.py
modified: plugins/genshin/almanac/__init__.py modified:
plugins/genshin/material_remind/__init__.py modified:
plugins/genshin/query_user/_models/__init__.py modified:
plugins/genshin/query_user/_utils/__init__.py modified:
plugins/genshin/query_user/bind/__init__.py modified:
plugins/genshin/query_user/genshin_sign/__init__.py modified:
plugins/genshin/query_user/genshin_sign/data_source.py modified:
plugins/genshin/query_user/genshin_sign/init_task.py modified:
plugins/genshin/query_user/mihoyobbs_sign/__init__.py modified:
plugins/genshin/query_user/query_memo/__init__.py modified:
plugins/genshin/query_user/query_memo/data_source.py modified:
plugins/genshin/query_user/query_role/__init__.py modified:
plugins/genshin/query_user/query_role/data_source.py modified:
plugins/genshin/query_user/reset_today_query_user_data/__init__.py
modified: plugins/genshin/query_user/resin_remind/__init__.py
modified: plugins/genshin/query_user/resin_remind/init_task.py
modified: plugins/gold_redbag/model.py modified:
plugins/image_management/send_image/__init__.py modified:
plugins/my_info/__init__.py modified:
plugins/open_cases/models/buff_prices.py modified:
plugins/open_cases/models/open_cases_user.py modified:
plugins/open_cases/open_cases_c.py modified:
plugins/open_cases/utils.py modified: plugins/parse_bilibili_json.py
modified: plugins/pid_search.py modified:
plugins/pix_gallery/__init__.py modified:
plugins/pix_gallery/_data_source.py modified:
plugins/pix_gallery/_model/omega_pixiv_illusts.py modified:
plugins/pix_gallery/_model/pixiv.py modified:
plugins/pix_gallery/_model/pixiv_keyword_user.py modified:
plugins/pix_gallery/pix_add_keyword.py modified:
plugins/pix_gallery/pix_pass_del_keyword.py modified:
plugins/pix_gallery/pix_show_info.py modified:
plugins/pix_gallery/pix_update.py modified:
plugins/pixiv_rank_search/data_source.py modified:
plugins/poke/__init__.py modified: plugins/russian/__init__.py
modified: plugins/russian/data_source.py modified:
plugins/russian/model.py modified:
plugins/send_dinggong_voice/__init__.py modified:
plugins/send_setu_/_model.py modified:
plugins/send_setu_/send_setu/__init__.py modified:
plugins/send_setu_/send_setu/data_source.py modified:
plugins/send_setu_/update_setu/data_source.py modified:
plugins/sign_in/goods_register.py modified:
plugins/sign_in/group_user_checkin.py modified:
plugins/sign_in/random_event.py modified: plugins/sign_in/utils.py
modified: plugins/statistics/_model.py modified:
plugins/statistics/statistics_handle.py modified:
plugins/statistics/statistics_hook.py modified: plugins/update_picture.py
modified: plugins/web_ui/api/request.py modified:
plugins/word_bank/_model.py deleted: plugins/word_bank/_old_model.py
modified: plugins/word_bank/_rule.py modified:
plugins/word_bank/word_handle.py modified:
plugins/word_clouds/data_source.py modified:
resources/image/sign/sign_res/bar.png modified:
resources/image/sign/sign_res/bar_white.png modified:
services/db_context.py modified: services/log.py modified:
utils/browser.py modified: utils/data_utils.py modified:
utils/depends/__init__.py modified: utils/http_utils.py
modified: utils/image_utils.py modified:
utils/manager/admin_manager.py modified: utils/message_builder.py
modified: utils/utils.py
---
.../admin_bot_manage/_data_source.py | 118 ++---
.../admin_bot_manage/admin_config.py | 18 +-
.../custom_welcome_message.py | 20 +-
basic_plugins/admin_bot_manage/timing_task.py | 19 +-
basic_plugins/apscheduler/__init__.py | 125 +++--
basic_plugins/ban/__init__.py | 136 ++---
basic_plugins/ban/data_source.py | 67 ++-
basic_plugins/chat_history/chat_message.py | 41 +-
.../chat_history/chat_message_handle.py | 33 +-
basic_plugins/group_handle/__init__.py | 99 ++--
basic_plugins/hooks/_utils.py | 64 ++-
basic_plugins/hooks/ban_hook.py | 19 +-
basic_plugins/hooks/chkdsk_hook.py | 6 +-
basic_plugins/init_plugin_config/__init__.py | 30 +-
.../init_plugin_config/init_group_manager.py | 73 ---
basic_plugins/invite_manager/__init__.py | 192 +++----
basic_plugins/invite_manager/utils.py | 87 +++
basic_plugins/nickname.py | 261 +++++----
basic_plugins/plugin_shop/__init__.py | 43 +-
basic_plugins/plugin_shop/data_source.py | 32 +-
basic_plugins/scripts.py | 280 +++++-----
basic_plugins/shop/__init__.py | 37 +-
basic_plugins/shop/buy.py | 94 ++--
basic_plugins/shop/gold.py | 17 +-
basic_plugins/shop/my_props/__init__.py | 16 +-
basic_plugins/shop/reset_today_gold.py | 26 -
basic_plugins/shop/shop_handle/__init__.py | 65 ++-
basic_plugins/shop/shop_handle/data_source.py | 154 ++++--
basic_plugins/shop/use/__init__.py | 40 +-
basic_plugins/shop/use/data_source.py | 3 +-
basic_plugins/super_cmd/__init__.py | 8 +-
basic_plugins/super_cmd/bot_friend_group.py | 48 +-
basic_plugins/super_cmd/clear_data.py | 43 +-
basic_plugins/super_cmd/exec_sql.py | 110 ++--
basic_plugins/super_cmd/manager_group.py | 210 +++++---
basic_plugins/super_cmd/reload_setting.py | 38 +-
.../super_cmd/set_admin_permissions.py | 63 ++-
basic_plugins/super_cmd/super_task_switch.py | 58 --
.../super_cmd/update_friend_group_info.py | 65 ++-
basic_plugins/super_help/__init__.py | 8 +-
basic_plugins/update_info.py | 5 +-
configs/config.py | 15 +-
configs/utils/__init__.py | 7 +-
models/bag_user.py | 222 +++-----
models/ban_user.py | 111 ++--
models/chat_history.py | 202 ++-----
models/friend_user.py | 99 +---
models/goods_info.py | 197 ++++---
models/group_info.py | 121 +----
models/group_member_info.py | 200 ++-----
models/level_user.py | 103 ++--
models/sign_group_user.py | 129 ++---
models/user_shop_gold_log.py | 76 +--
plugins/aconfig/__init__.py | 29 +-
plugins/ai/__init__.py | 18 +-
plugins/ai/data_source.py | 39 +-
plugins/bilibili_sub/__init__.py | 63 +--
plugins/bilibili_sub/data_source.py | 236 ++++-----
plugins/bilibili_sub/model.py | 298 ++++-------
plugins/black_word/__init__.py | 66 ++-
plugins/black_word/model.py | 118 ++---
plugins/black_word/utils.py | 60 ++-
plugins/bt/data_source.py | 15 +-
plugins/genshin/almanac/__init__.py | 2 +-
plugins/genshin/material_remind/__init__.py | 29 +-
.../genshin/query_user/_models/__init__.py | 501 ++----------------
plugins/genshin/query_user/_utils/__init__.py | 13 +-
plugins/genshin/query_user/bind/__init__.py | 109 ++--
.../query_user/genshin_sign/__init__.py | 73 +--
.../query_user/genshin_sign/data_source.py | 78 +--
.../query_user/genshin_sign/init_task.py | 47 +-
.../query_user/mihoyobbs_sign/__init__.py | 59 ++-
.../genshin/query_user/query_memo/__init__.py | 26 +-
.../query_user/query_memo/data_source.py | 160 +++---
.../genshin/query_user/query_role/__init__.py | 49 +-
.../query_user/query_role/data_source.py | 155 +++---
.../reset_today_query_user_data/__init__.py | 7 +-
.../query_user/resin_remind/__init__.py | 47 +-
.../query_user/resin_remind/init_task.py | 86 +--
plugins/gold_redbag/model.py | 97 ++--
.../image_management/send_image/__init__.py | 37 +-
plugins/my_info/__init__.py | 23 +-
plugins/open_cases/models/buff_prices.py | 42 +-
plugins/open_cases/models/open_cases_user.py | 101 ++--
plugins/open_cases/open_cases_c.py | 376 ++++++-------
plugins/open_cases/utils.py | 249 +++++----
plugins/parse_bilibili_json.py | 71 +--
plugins/pid_search.py | 20 +-
plugins/pix_gallery/__init__.py | 37 +-
plugins/pix_gallery/_data_source.py | 239 +++++----
.../pix_gallery/_model/omega_pixiv_illusts.py | 177 +++----
plugins/pix_gallery/_model/pixiv.py | 185 ++-----
.../pix_gallery/_model/pixiv_keyword_user.py | 133 ++---
plugins/pix_gallery/pix_add_keyword.py | 73 ++-
plugins/pix_gallery/pix_pass_del_keyword.py | 69 ++-
plugins/pix_gallery/pix_show_info.py | 24 +-
plugins/pix_gallery/pix_update.py | 65 +--
plugins/pixiv_rank_search/data_source.py | 27 +-
plugins/poke/__init__.py | 24 +-
plugins/russian/__init__.py | 50 +-
plugins/russian/data_source.py | 39 +-
plugins/russian/model.py | 176 +++---
plugins/send_dinggong_voice/__init__.py | 23 +-
plugins/send_setu_/_model.py | 209 ++------
plugins/send_setu_/send_setu/__init__.py | 90 ++--
plugins/send_setu_/send_setu/data_source.py | 105 ++--
plugins/send_setu_/update_setu/data_source.py | 77 +--
plugins/sign_in/goods_register.py | 38 +-
plugins/sign_in/group_user_checkin.py | 106 ++--
plugins/sign_in/random_event.py | 24 +-
plugins/sign_in/utils.py | 83 +--
plugins/statistics/_model.py | 47 +-
plugins/statistics/statistics_handle.py | 24 +-
plugins/statistics/statistics_hook.py | 21 +-
plugins/update_picture.py | 48 +-
plugins/web_ui/api/request.py | 34 +-
plugins/word_bank/_model.py | 292 +++++-----
plugins/word_bank/_old_model.py | 20 -
plugins/word_bank/_rule.py | 27 +-
plugins/word_bank/word_handle.py | 30 +-
plugins/word_clouds/data_source.py | 30 +-
resources/image/sign/sign_res/bar.png | Bin 755 -> 2535 bytes
resources/image/sign/sign_res/bar_white.png | Bin 584 -> 1431 bytes
services/db_context.py | 57 +-
services/log.py | 147 ++++-
utils/browser.py | 37 +-
utils/data_utils.py | 25 +-
utils/depends/__init__.py | 79 ++-
utils/game_utils.py | 192 +++++++
utils/http_utils.py | 161 +++---
utils/image_utils.py | 54 +-
utils/manager/admin_manager.py | 13 +-
utils/message_builder.py | 88 ++-
utils/utils.py | 184 +++++--
134 files changed, 5402 insertions(+), 6033 deletions(-)
delete mode 100755 basic_plugins/init_plugin_config/init_group_manager.py
create mode 100644 basic_plugins/invite_manager/utils.py
delete mode 100644 basic_plugins/shop/reset_today_gold.py
delete mode 100755 basic_plugins/super_cmd/super_task_switch.py
delete mode 100644 plugins/word_bank/_old_model.py
create mode 100644 utils/game_utils.py
diff --git a/basic_plugins/admin_bot_manage/_data_source.py b/basic_plugins/admin_bot_manage/_data_source.py
index 50a56879..750141ef 100644
--- a/basic_plugins/admin_bot_manage/_data_source.py
+++ b/basic_plugins/admin_bot_manage/_data_source.py
@@ -1,29 +1,29 @@
+import asyncio
+import os
+import time
+from datetime import datetime
+from pathlib import Path
from typing import List
+
+import ujson as json
from nonebot.adapters.onebot.v11.message import MessageSegment
-from services.log import logger
+
+from configs.config import Config
from configs.path_config import DATA_PATH, IMAGE_PATH
+from models.group_member_info import GroupInfoUser
+from models.level_user import LevelUser
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import BuildImage
+from utils.manager import group_manager, plugins2settings_manager, plugins_manager
from utils.message_builder import image
from utils.utils import get_bot, get_matchers
-from pathlib import Path
-from models.group_member_info import GroupInfoUser
-from datetime import datetime
-from services.db_context import db
-from models.level_user import LevelUser
-from configs.config import Config
-from utils.manager import group_manager, plugins2settings_manager, plugins_manager
-from utils.image_utils import BuildImage
-from utils.http_utils import AsyncHttpx
-import asyncio
-import time
-import os
-import ujson as json
-
custom_welcome_msg_json = (
Path() / "data" / "custom_welcome_msg" / "custom_welcome_msg.json"
)
-ICON_PATH = IMAGE_PATH / 'other'
+ICON_PATH = IMAGE_PATH / "other"
async def group_current_status(group_id: int) -> str:
@@ -38,7 +38,9 @@ async def group_current_status(group_id: int) -> str:
for i, task in enumerate(_data):
name = _data[task]
name_image = BuildImage(0, 0, plain_text=f"{i+1}.{name}", font_size=20)
- bk = BuildImage(name_image.w + 200, name_image.h + 20, color=(103, 177, 109), font_size=15)
+ bk = BuildImage(
+ name_image.w + 200, name_image.h + 20, color=(103, 177, 109), font_size=15
+ )
await bk.apaste(name_image, (10, 0), True, "by_height")
a_icon = BuildImage(40, 40, background=ICON_PATH / "btn_false.png")
if group_manager.check_group_task_status(group_id, task):
@@ -123,7 +125,7 @@ def change_global_task_status(cmd: str) -> str:
task_data = group_manager.get_task_data()
status = cmd[:2]
_cmd = cmd[4:]
- if '全部被动' in cmd:
+ if "全部被动" in cmd:
for task in task_data:
if status == "开启":
group_manager.open_global_task(task)
@@ -134,7 +136,7 @@ def change_global_task_status(cmd: str) -> str:
else:
modules = [x for x in task_data if task_data[x].lower() == _cmd.lower()]
if not modules:
- return '未查询到该被动任务'
+ return "未查询到该被动任务"
if status == "开启":
group_manager.open_global_task(modules[0])
else:
@@ -301,50 +303,40 @@ async def update_member_info(group_id: int, remind_superuser: bool = False) -> b
# try:
for user_info in _group_user_list:
nickname = user_info["card"] or user_info["nickname"]
- async with db.transaction():
- # 更新权限
- if user_info["role"] in [
- "owner",
- "admin",
- ] and not await LevelUser.is_group_flag(user_info["user_id"], group_id):
- await LevelUser.set_level(
- user_info["user_id"],
- user_info["group_id"],
- Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
- )
- if str(user_info["user_id"]) in bot.config.superusers:
- await LevelUser.set_level(
- user_info["user_id"], user_info["group_id"], 9
- )
- user = await GroupInfoUser.get_member_info(
- user_info["user_id"], user_info["group_id"]
- )
- if user:
- if user.user_name != nickname:
- await user.update(user_name=nickname).apply()
- logger.info(
- f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
- )
- _exist_member_list.append(int(user_info["user_id"]))
- continue
- join_time = datetime.strptime(
- time.strftime(
- "%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])
- ),
- "%Y-%m-%d %H:%M:%S",
- )
- if await GroupInfoUser.add_member_info(
+ # 更新权限
+ if user_info["role"] in [
+ "owner",
+ "admin",
+ ] and not await LevelUser.is_group_flag(user_info["user_id"], group_id):
+ await LevelUser.set_level(
user_info["user_id"],
user_info["group_id"],
- nickname,
- join_time,
- ):
- _exist_member_list.append(int(user_info["user_id"]))
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
- else:
- _error_member_list.append(
- f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败\n"
+ Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH"),
+ )
+ if str(user_info["user_id"]) in bot.config.superusers:
+ await LevelUser.set_level(user_info["user_id"], user_info["group_id"], 9)
+ user = await GroupInfoUser.filter(
+ user_qq=user_info["user_id"], group_id=user_info["group_id"]
+ ).first()
+ if user:
+ if user.user_name != nickname:
+ await user.update(user_name=nickname).apply()
+ logger.info(
+ f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新群昵称成功"
)
+ _exist_member_list.append(int(user_info["user_id"]))
+ continue
+ join_time = datetime.strptime(
+ time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(user_info["join_time"])),
+ "%Y-%m-%d %H:%M:%S",
+ )
+ await GroupInfoUser.update_or_create(
+ user_qq=user_info["user_id"],
+ group_id=user_info["group_id"],
+ defaults={"user_name": nickname, "user_join_time": join_time},
+ )
+ _exist_member_list.append(int(user_info["user_id"]))
+ logger.info("更新成功", "更新成员信息", user_info["user_id"], user_info["group_id"])
_del_member_list = list(
set(_exist_member_list).difference(
set(await GroupInfoUser.get_group_member_id_list(group_id))
@@ -352,10 +344,8 @@ async def update_member_info(group_id: int, remind_superuser: bool = False) -> b
)
if _del_member_list:
for del_user in _del_member_list:
- if await GroupInfoUser.delete_member_info(del_user, group_id):
- logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
- else:
- logger.info(f"退群用户{del_user} 所属{group_id} 删除失败")
+ await GroupInfoUser.filter(user_qq=del_user, group_id=group_id).delete()
+ logger.info(f"退群用户{del_user} 所属{group_id} 已删除")
if _error_member_list and remind_superuser:
result = ""
for error_user in _error_member_list:
diff --git a/basic_plugins/admin_bot_manage/admin_config.py b/basic_plugins/admin_bot_manage/admin_config.py
index a1bc200a..72f685df 100755
--- a/basic_plugins/admin_bot_manage/admin_config.py
+++ b/basic_plugins/admin_bot_manage/admin_config.py
@@ -1,10 +1,10 @@
from nonebot import on_notice
-from services.log import logger
from nonebot.adapters.onebot.v11 import GroupAdminNoticeEvent
-from models.level_user import LevelUser
-from models.group_member_info import GroupInfoUser
-from configs.config import Config
+from configs.config import Config
+from models.group_member_info import GroupInfoUser
+from models.level_user import LevelUser
+from services.log import logger
__zx_plugin_name__ = "群管理员变动监测 [Hidden]"
__plugin_version__ = 0.1
@@ -16,11 +16,11 @@ admin_notice = on_notice(priority=5)
@admin_notice.handle()
async def _(event: GroupAdminNoticeEvent):
- try:
- nickname = (
- await GroupInfoUser.get_member_info(event.user_id, event.group_id)
- ).user_name
- except AttributeError:
+ if user := await GroupInfoUser.filter(
+ user_qq=event.user_id, group_id=event.group_id
+ ).first():
+ nickname = user.nickname
+ else:
nickname = event.user_id
if event.sub_type == "set":
await LevelUser.set_level(
diff --git a/basic_plugins/admin_bot_manage/custom_welcome_message.py b/basic_plugins/admin_bot_manage/custom_welcome_message.py
index 607e13c1..dd1b1594 100755
--- a/basic_plugins/admin_bot_manage/custom_welcome_message.py
+++ b/basic_plugins/admin_bot_manage/custom_welcome_message.py
@@ -1,14 +1,14 @@
from typing import List
+from configs.config import Config
from nonebot import on_command
from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
-from nonebot.params import CommandArg
-from ._data_source import custom_group_welcome
from nonebot.adapters.onebot.v11.permission import GROUP
-from configs.config import Config
+from nonebot.params import CommandArg
from services.log import logger
from utils.depends import ImageList
+from ._data_source import custom_group_welcome
__zx_plugin_name__ = "自定义进群欢迎消息 [Admin]"
__plugin_usage__ = """
@@ -19,12 +19,14 @@ usage:
Note:可以通过[at]来确认是否艾特新成员
示例:自定义进群欢迎消息 欢迎你[at]
""".strip()
-__plugin_des__ = '简易的自定义群欢迎消息'
-__plugin_cmd__ = ['自定义群欢迎消息 ?[文本] ?[图片]']
+__plugin_des__ = "简易的自定义群欢迎消息"
+__plugin_cmd__ = ["自定义群欢迎消息 ?[文本] ?[图片]"]
__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
+__plugin_author__ = "HibiKier"
__plugin_settings__ = {
- "admin_level": Config.get_config("admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"),
+ "admin_level": Config.get_config(
+ "admin_bot_manage", "SET_GROUP_WELCOME_MESSAGE_LEVEL"
+ ),
}
custom_welcome = on_command(
@@ -37,7 +39,9 @@ custom_welcome = on_command(
@custom_welcome.handle()
-async def _(event: GroupMessageEvent, arg: Message = CommandArg(), img: List[str] = ImageList()):
+async def _(
+ event: GroupMessageEvent, arg: Message = CommandArg(), img: List[str] = ImageList()
+):
msg = arg.extract_plain_text().strip()
if not msg and not img:
await custom_welcome.finish(__plugin_usage__)
diff --git a/basic_plugins/admin_bot_manage/timing_task.py b/basic_plugins/admin_bot_manage/timing_task.py
index 840a44ad..198eef5e 100755
--- a/basic_plugins/admin_bot_manage/timing_task.py
+++ b/basic_plugins/admin_bot_manage/timing_task.py
@@ -1,15 +1,16 @@
-from utils.utils import scheduler, get_bot
-from ._data_source import update_member_info
-from services.log import logger
-from models.group_info import GroupInfo
from asyncpg.exceptions import ConnectionDoesNotExistError, UndefinedColumnError
+from models.group_info import GroupInfo
+from services.log import logger
+from utils.utils import get_bot, scheduler
-__zx_plugin_name__ = '管理方面定时任务 [Hidden]'
-__plugin_usage__ = '无'
-__plugin_des__ = '成员信息和管理权限的定时更新'
+from ._data_source import update_member_info
+
+__zx_plugin_name__ = "管理方面定时任务 [Hidden]"
+__plugin_usage__ = "无"
+__plugin_des__ = "成员信息和管理权限的定时更新"
__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
+__plugin_author__ = "HibiKier"
# 自动更新群员信息
@@ -42,7 +43,7 @@ async def _():
if bot:
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
- all_group = [x.group_id for x in await GroupInfo.get_all_group()]
+ all_group = [x.group_id for x in await GroupInfo.all()]
for g in gl:
if g not in all_group:
await update_member_info(g, False)
diff --git a/basic_plugins/apscheduler/__init__.py b/basic_plugins/apscheduler/__init__.py
index 5b6d2370..70ddf922 100755
--- a/basic_plugins/apscheduler/__init__.py
+++ b/basic_plugins/apscheduler/__init__.py
@@ -1,18 +1,22 @@
-from utils.message_builder import image
-from utils.utils import scheduler, get_bot
-from nonebot import on_message
-from services.log import logger
-from models.group_info import GroupInfo
-from models.friend_user import FriendUser
-from nonebot.adapters.onebot.v11 import ActionFailed
-from configs.config import NICKNAME, Config
-from pathlib import Path
import shutil
+from pathlib import Path
+
+import nonebot
+from nonebot import on_message
+from nonebot.adapters.onebot.v11 import ActionFailed
+
+from configs.config import NICKNAME, Config
+from configs.path_config import IMAGE_PATH
+from models.friend_user import FriendUser
+from models.group_info import GroupInfo
+from services.log import logger
+from utils.message_builder import image
+from utils.utils import broadcast_group, get_bot, scheduler
__zx_plugin_name__ = "定时任务相关 [Hidden]"
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
-__plugin_task__ = {'zwa': '早晚安'}
+__plugin_task__ = {"zwa": "早晚安"}
Config.add_plugin_config(
@@ -24,20 +28,23 @@ Config.add_plugin_config(
)
Config.add_plugin_config(
- "_backup",
- "BACKUP_FLAG",
- True,
- help_="是否开启文件备份",
- default_value=True
+ "_backup", "BACKUP_FLAG", True, help_="是否开启文件备份", default_value=True
)
Config.add_plugin_config(
"_backup",
"BACKUP_DIR_OR_FILE",
- ['data/black_word', 'data/configs', 'data/statistics', 'data/word_bank', 'data/manager', 'configs'],
+ [
+ "data/black_word",
+ "data/configs",
+ "data/statistics",
+ "data/word_bank",
+ "data/manager",
+ "configs",
+ ],
name="文件备份",
help_="备份的文件夹或文件",
- default_value=[]
+ default_value=[],
)
@@ -51,18 +58,9 @@ cx = on_message(priority=9999, block=False, rule=lambda: False)
minute=1,
)
async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- result = image("zao.jpg", "zhenxun")
- try:
- await bot.send_group_msg(group_id=g, message="[[_task|zwa]]早上好" + result)
- except ActionFailed:
- logger.warning(f"{g} 发送早安失败")
- except Exception as e:
- logger.error(f"早晚安错误 e:{e}")
+ img = image(IMAGE_PATH / "zhenxun" / "zao.jpg")
+ await broadcast_group("[[_task|zwa]]早上好" + img, log_cmd="被动早晚安")
+ logger.info("每日早安发送")
# 睡觉了
@@ -72,20 +70,9 @@ async def _():
minute=59,
)
async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- result = image("sleep.jpg", "zhenxun")
- try:
- await bot.send_group_msg(
- group_id=g, message=f"[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + result
- )
- except ActionFailed:
- logger.warning(f"{g} 发送晚安失败")
- except Exception as e:
- logger.error(f"早晚安错误 e:{e}")
+ img = image(IMAGE_PATH / "zhenxun" / "sleep.jpg")
+ await broadcast_group("[[_task|zwa]]{NICKNAME}要睡觉了,你们也要早点睡呀" + img, log_cmd="被动早晚安")
+ logger.info("每日晚安发送")
# 自动更新群组信息
@@ -95,22 +82,27 @@ async def _():
minute=1,
)
async def _():
- try:
- bot = get_bot()
- gl = await bot.get_group_list()
- gl = [g["group_id"] for g in gl]
- for g in gl:
- group_info = await bot.get_group_info(group_id=g)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1
- )
- logger.info(f"自动更新群组 {g} 信息成功")
- except Exception as e:
- logger.error(f"自动更新群组信息错误 e:{e}")
+ bots = nonebot.get_bots()
+ _used_group = []
+ for bot in bots.values():
+ try:
+ group_list = await bot.get_group_list()
+ gl = [g["group_id"] for g in group_list if g["group_id"] not in _used_group]
+ for g in gl:
+ _used_group.append(g)
+ group_info = await bot.get_group_info(group_id=g)
+ await GroupInfo.update_or_create(
+ group_id=group_info["group_id"],
+ defaults={
+ "group_name": group_info["group_name"],
+ "max_member_count": group_info["max_member_count"],
+ "member_count": group_info["member_count"],
+ "group_flag": 1,
+ },
+ )
+ logger.info(f"自动更新群组信息成功", group_id=g)
+ except Exception as e:
+ logger.error(f"Bot: {bot.self_id} 自动更新群组信息", e=e)
# 自动更新好友信息
@@ -124,10 +116,10 @@ async def _():
bot = get_bot()
fl = await bot.get_friend_list()
for f in fl:
- if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
- logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
- else:
- logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
+ await FriendUser.create(user_id=f["user_id"], user_name=f["nickname"])
+ logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
+ # else:
+ # logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
except Exception as e:
logger.error(f"自动更新群组信息错误 e:{e}")
@@ -140,7 +132,7 @@ async def _():
)
async def _():
if Config.get_config("_backup", "BACKUP_FLAG"):
- _backup_path = Path() / 'backup'
+ _backup_path = Path() / "backup"
_backup_path.mkdir(exist_ok=True, parents=True)
for x in Config.get_config("_backup", "BACKUP_DIR_OR_FILE"):
try:
@@ -155,12 +147,13 @@ async def _():
if _p.exists():
_p.unlink()
shutil.copy(x, _p)
- logger.info(f'已完成自动备份:{x}')
+ logger.info(f"已完成自动备份:{x}")
except Exception as e:
logger.error(f"自动备份文件 {x} 发生错误 {type(e)}:{e}")
-
# 一次性任务
+
+
# 固定时间触发,仅触发一次:
#
# from datetime import datetime
diff --git a/basic_plugins/ban/__init__.py b/basic_plugins/ban/__init__.py
index b5b37942..a9a3318c 100755
--- a/basic_plugins/ban/__init__.py
+++ b/basic_plugins/ban/__init__.py
@@ -1,16 +1,22 @@
-from typing import Tuple, List
+from typing import List
+
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import (
+ Bot,
+ GroupMessageEvent,
+ Message,
+ MessageEvent,
+ PrivateMessageEvent,
+)
+from nonebot.params import CommandArg
+from nonebot.permission import SUPERUSER
from configs.config import NICKNAME, Config
from models.ban_user import BanUser
from models.level_user import LevelUser
-from nonebot import on_command
-from nonebot.adapters.onebot.v11 import (Bot, GroupMessageEvent, Message,
- MessageEvent, PrivateMessageEvent)
-from nonebot.params import Command, CommandArg
-from nonebot.permission import SUPERUSER
from services.log import logger
-from utils.depends import AtList
-from utils.utils import get_message_at, is_number
+from utils.depends import AtList, OneCommand
+from utils.utils import is_number
from .data_source import a_ban, parse_ban_time
@@ -68,46 +74,38 @@ super_ban = on_command("b了", permission=SUPERUSER, priority=5, block=True)
async def _(
bot: Bot,
event: GroupMessageEvent,
- cmd: Tuple[str, ...] = Command(),
+ cmd: str = OneCommand(),
arg: Message = CommandArg(),
- qq: List[int] = AtList()
+ at_list: List[int] = AtList(),
):
- cmd = cmd[0]
result = ""
- if qq:
- qq = qq[0]
- user_name = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
- user_name = user_name["card"] or user_name["nickname"]
+ if at_list:
+ qq = at_list[0]
+ user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
+ user_name = user["card"] or user["nickname"]
msg = arg.extract_plain_text().strip()
time = parse_ban_time(msg)
if isinstance(time, str):
await ban.finish(time, at_sender=True)
+ user_level = await LevelUser.get_user_level(event.user_id, event.group_id)
+ is_not_superuser = str(event.user_id) not in bot.config.superusers
if cmd in [".ban", "/ban"]:
- if (
- await LevelUser.get_user_level(event.user_id, event.group_id)
- <= await LevelUser.get_user_level(qq, event.group_id)
- and str(event.user_id) not in bot.config.superusers
- ):
+ at_user_level = await LevelUser.get_user_level(qq, event.group_id)
+ if user_level <= at_user_level and is_not_superuser:
await ban.finish(
f"您的权限等级比对方低或相等, {NICKNAME}不能为您使用此功能!",
at_sender=True,
)
+ logger.info(f"用户封禁 时长: {time}", cmd, event.user_id, event.group_id, qq)
result = await a_ban(qq, time, user_name, event)
else:
- if (
- await BanUser.check_ban_level(
- qq, await LevelUser.get_user_level(event.user_id, event.group_id)
- )
- and str(event.user_id) not in bot.config.superusers
- ):
+ if await BanUser.check_ban_level(qq, user_level) and is_not_superuser:
await ban.finish(
f"ban掉 {user_name} 的管理员权限比您高,无法进行unban", at_sender=True
)
if await BanUser.unban(qq):
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} 将 USER {qq} 解禁"
- )
- result = f"已经把 {user_name} 从黑名单中删除了!"
+ logger.info(f"解除用户封禁", cmd, event.user_id, event.group_id, qq)
+ result = f"已经将 {user_name} 从黑名单中删除了!"
else:
result = f"{user_name} 不在黑名单!"
else:
@@ -119,54 +117,62 @@ async def _(
async def _(
bot: Bot,
event: PrivateMessageEvent,
- cmd: Tuple[str, ...] = Command(),
+ cmd: str = OneCommand(),
arg: Message = CommandArg(),
):
- cmd = cmd[0]
msg = arg.extract_plain_text().strip()
- if msg:
- if str(event.user_id) in bot.config.superusers:
- msg_splt = msg.split()
- if is_number(msg_splt[0]):
- qq = int(msg_splt[0])
- msg = msg_splt[1:]
- if cmd in [".ban", "/ban"]:
- time = parse_ban_time(" ".join(msg))
- if isinstance(time, str):
- await ban.finish(time)
- result = await a_ban(qq, time, str(qq), event, 9)
- else:
- if await BanUser.unban(qq):
- logger.info(f"USER {event.user_id} 将 USER {qq} 解禁")
- result = f"已经把 {qq} 从黑名单中删除了!"
- else:
- result = f"{qq} 不在黑名单!"
- await ban.send(result)
+ if msg and str(event.user_id) in bot.config.superusers:
+ msg_split = msg.split()
+ if msg_split and is_number(msg_split[0]):
+ qq = int(msg_split[0])
+ param = msg_split[1:]
+ if cmd in [".ban", "/ban"]:
+ time = parse_ban_time(" ".join(param))
+ if isinstance(time, str):
+ logger.info(time, cmd, event.user_id, target=qq)
+ await ban.finish(time)
+ result = await a_ban(qq, time, str(qq), event, 9)
else:
- await ban.finish(
- "qq号必须是数字!\n格式:.ban [qq] [hour]? [minute]?", at_sender=True
- )
+ if await BanUser.unban(qq):
+ result = f"已经把 {qq} 从黑名单中删除了!"
+ else:
+ result = f"{qq} 不在黑名单!"
+ await ban.send(result)
+ logger.info(result, cmd, event.user_id, target=qq)
+ else:
+ await ban.send("参数不正确!\n格式:.ban [qq] [hour]? [minute]?", at_sender=True)
@super_ban.handle()
-async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
+async def _(
+ bot: Bot,
+ event: MessageEvent,
+ cmd: str = OneCommand(),
+ arg: Message = CommandArg(),
+ at_list: List[int] = AtList(),
+):
user_name = ""
+ qq = None
if isinstance(event, GroupMessageEvent):
- qq = get_message_at(event.json())
- if qq:
- qq = qq[0]
+ if at_list:
+ qq = at_list[0]
user = await bot.get_group_member_info(group_id=event.group_id, user_id=qq)
user_name = user["card"] or user["nickname"]
else:
- qq = arg.extract_plain_text().strip()
- if not is_number(qq):
+ msg = arg.extract_plain_text().strip()
+ if not is_number(msg):
await super_ban.finish("对象qq必须为纯数字...")
- qq = int(qq)
- user_name = qq
+ qq = int(msg)
+ user_name = msg
if qq:
- if not await BanUser.ban(qq, 10, 99999999):
- await BanUser.unban(qq)
- await BanUser.ban(qq, 10, 99999999)
+ await BanUser.ban(qq, 10, 99999999)
await ban.send(f"已将 {user_name} 拉入黑名单!")
+ logger.info(
+ f"已将 {user_name} 拉入黑名单!",
+ cmd,
+ event.user_id,
+ event.group_id if isinstance(event, GroupMessageEvent) else None,
+ qq,
+ )
else:
- await super_ban.send("需要添加被super ban的对象,可以使用at或者指定qq..")
+ await super_ban.send("需要提供被super ban的对象,可以使用at或者指定qq...")
diff --git a/basic_plugins/ban/data_source.py b/basic_plugins/ban/data_source.py
index 4121d2e9..6878a8b9 100644
--- a/basic_plugins/ban/data_source.py
+++ b/basic_plugins/ban/data_source.py
@@ -1,10 +1,12 @@
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
+from typing import Optional, Union
+
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+
from configs.config import NICKNAME
-from models.level_user import LevelUser
-from utils.utils import is_number
from models.ban_user import BanUser
+from models.level_user import LevelUser
from services.log import logger
-from typing import Union
+from utils.utils import is_number
def parse_ban_time(msg: str) -> Union[int, str]:
@@ -12,21 +14,31 @@ def parse_ban_time(msg: str) -> Union[int, str]:
解析ban时长
:param msg: 文本消息
"""
- if not msg:
- return -1
- msg = msg.split()
- if len(msg) == 1:
- if not is_number(msg[0].strip()):
- return "参数必须是数字!"
- return int(msg[0]) * 60 * 60
- else:
- if not is_number(msg[0].strip()) or not is_number(msg[1].strip()):
- return "参数必须是数字!"
- return int(msg[0]) * 60 * 60 + int(msg[1]) * 60
+ try:
+ if not msg:
+ return -1
+ msg_split = msg.split()
+ if len(msg_split) == 1:
+ if not is_number(msg_split[0].strip()):
+ return "参数必须是数字!"
+ return int(msg_split[0]) * 60 * 60
+ else:
+ if not is_number(msg_split[0].strip()) or not is_number(
+ msg_split[1].strip()
+ ):
+ return "参数必须是数字!"
+ return int(msg_split[0]) * 60 * 60 + int(msg_split[1]) * 60
+ except ValueError as e:
+ logger.error("解析ban时长错误", ".ban", e=e)
+ return "时长不可以带小数点!"
async def a_ban(
- qq: int, time: int, user_name: str, event: MessageEvent, ban_level: int = None
+ qq: int,
+ time: int,
+ user_name: str,
+ event: MessageEvent,
+ ban_level: Optional[int] = None,
) -> str:
"""
ban
@@ -36,12 +48,15 @@ async def a_ban(
:param event: event
:param ban_level: ban级别
"""
+ group_id = None
if isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
ban_level = await LevelUser.get_user_level(event.user_id, event.group_id)
+ if not ban_level:
+ return "未查询到ban级用户权限"
if await BanUser.ban(qq, ban_level, time):
logger.info(
- f"USER {event.user_id} GROUP"
- f" {event.group_id if isinstance(event, GroupMessageEvent) else ''} 将 USER {qq} 封禁 时长 {time / 60} 分钟"
+ f"将 [Target]({qq})封禁 时长 {time / 60} 分钟", ".ban", event.user_id, group_id
)
result = f"已经将 {user_name} 加入{NICKNAME}的黑名单了!"
if time != -1:
@@ -49,14 +64,14 @@ async def a_ban(
else:
result += f"将在 ∞ 分钟后解封"
else:
- time = await BanUser.check_ban_time(qq)
- if is_number(time):
- time = abs(int(time))
- if time < 60:
- time = str(time) + " 秒"
+ ban_time = await BanUser.check_ban_time(qq)
+ if isinstance(ban_time, int):
+ ban_time = abs(float(ban_time))
+ if ban_time < 60:
+ ban_time = str(ban_time) + " 秒"
else:
- time = str(int(time / 60)) + " 分钟"
+ ban_time = str(int(ban_time / 60)) + " 分钟"
else:
- time += " 分钟"
- result = f"{user_name} 已在黑名单!预计 {time}后解封"
+ ban_time += " 分钟"
+ result = f"{user_name} 已在黑名单!预计 {ban_time}后解封"
return result
diff --git a/basic_plugins/chat_history/chat_message.py b/basic_plugins/chat_history/chat_message.py
index e8bfbdf6..fbfa1d6a 100644
--- a/basic_plugins/chat_history/chat_message.py
+++ b/basic_plugins/chat_history/chat_message.py
@@ -1,8 +1,11 @@
-from configs.config import Config
-from models.chat_history import ChatHistory
from nonebot import on_message
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+
+from configs.config import Config
+from models.chat_history import ChatHistory
+from services.log import logger
from utils.depends import PlaintText
+from utils.utils import scheduler
from ._rule import rule
@@ -19,14 +22,38 @@ Config.add_plugin_config(
chat_history = on_message(rule=rule, priority=1, block=False)
+TEMP_LIST = []
+
+
@chat_history.handle()
async def _(event: MessageEvent, msg: str = PlaintText()):
+ group_id = None
if isinstance(event, GroupMessageEvent):
- await ChatHistory.add_chat_msg(
- event.user_id, event.group_id, str(event.get_message()), msg
- )
- else:
- await ChatHistory.add_chat_msg(event.user_id, None, str(event.get_message()), msg)
+ group_id = event.group_id
+ TEMP_LIST.append(
+ {
+ "user_qq": event.user_id,
+ "group_id": group_id,
+ "text": str(event.get_message()),
+ "plain_text": msg,
+ }
+ )
+
+
+@scheduler.scheduled_job(
+ "interval",
+ minutes=1,
+)
+async def _():
+ try:
+ message_list = TEMP_LIST.copy()
+ TEMP_LIST.clear()
+ if message_list:
+ model_list = [ChatHistory(**x) for x in message_list]
+ await ChatHistory.bulk_create(model_list)
+ logger.debug(f"批量添加聊天记录 {len(message_list)} 条", "定时任务")
+ except Exception as e:
+ logger.error(f"定时批量添加聊天记录", "定时任务", e=e)
# @test.handle()
diff --git a/basic_plugins/chat_history/chat_message_handle.py b/basic_plugins/chat_history/chat_message_handle.py
index b050490f..3c1c2ddb 100644
--- a/basic_plugins/chat_history/chat_message_handle.py
+++ b/basic_plugins/chat_history/chat_message_handle.py
@@ -1,16 +1,16 @@
from datetime import datetime, timedelta
+from typing import Any, Tuple
import pytz
-from models.chat_history import ChatHistory
-from models.group_member_info import GroupInfoUser
from nonebot import on_regex
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.params import RegexGroup
-from utils.image_utils import BuildImage, text2image
-from utils.utils import is_number
-from utils.message_builder import image
-from typing import Tuple, Any
+from models.chat_history import ChatHistory
+from models.group_member_info import GroupInfoUser
+from utils.image_utils import BuildImage, text2image
+from utils.message_builder import image
+from utils.utils import is_number
__zx_plugin_name__ = "消息统计"
__plugin_usage__ = """
@@ -29,12 +29,7 @@ usage:
消息统计n=15
""".strip()
__plugin_des__ = "发言消息排行"
-__plugin_cmd__ = [
- "消息统计",
- "周消息统计",
- "月消息统计",
- "日消息统计"
-]
+__plugin_cmd__ = ["消息统计", "周消息统计", "月消息统计", "日消息统计"]
__plugin_type__ = ("数据统计", 1)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
@@ -44,7 +39,9 @@ __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()
@@ -56,7 +53,9 @@ async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup())
if num and is_number(num) and 10 < int(num) < 50:
num = int(num)
time_now = datetime.now()
- zero_today = time_now - timedelta(hours=time_now.hour, minutes=time_now.minute, seconds=time_now.second)
+ zero_today = time_now - timedelta(
+ hours=time_now.hour, minutes=time_now.minute, seconds=time_now.second
+ )
if date in ["日"]:
date_scope = (zero_today, time_now)
elif date in ["周"]:
@@ -70,9 +69,9 @@ async def _(event: GroupMessageEvent, reg_group: Tuple[Any, ...] = RegexGroup())
num_str = "发言次数:\n\n"
idx = 1
for uid, num in rank_data:
- try:
- user_name = (await GroupInfoUser.get_member_info(uid, gid)).user_name
- except AttributeError:
+ if user := await GroupInfoUser.filter(user_qq=uid, group_id=gid).first():
+ user_name = user.user_name
+ else:
user_name = uid
name += f"\t{idx}.{user_name} \n\n"
num_str += f"\t{num}\n\n"
diff --git a/basic_plugins/group_handle/__init__.py b/basic_plugins/group_handle/__init__.py
index b5eaacc6..d30fcdf7 100755
--- a/basic_plugins/group_handle/__init__.py
+++ b/basic_plugins/group_handle/__init__.py
@@ -1,26 +1,27 @@
-from nonebot import on_notice, on_request
-from configs.path_config import IMAGE_PATH, DATA_PATH
-from models.level_user import LevelUser
-from utils.message_builder import image
-from models.group_member_info import GroupInfoUser
-from datetime import datetime
-from services.log import logger
-from nonebot.adapters.onebot.v11 import (
- Bot,
- ActionFailed,
- GroupIncreaseNoticeEvent,
- GroupDecreaseNoticeEvent,
-)
-from utils.manager import group_manager, plugins2settings_manager, requests_manager
-from configs.config import NICKNAME
-from models.group_info import GroupInfo
-from utils.utils import FreqLimiter
-from configs.config import Config
-from pathlib import Path
-import random
import os
-import ujson as json
+import random
+from datetime import datetime
+from pathlib import Path
+import ujson as json
+from nonebot import on_notice, on_request
+from nonebot.adapters.onebot.v11 import (
+ ActionFailed,
+ Bot,
+ GroupDecreaseNoticeEvent,
+ GroupIncreaseNoticeEvent,
+)
+
+from configs.config import NICKNAME, Config
+from configs.path_config import DATA_PATH, IMAGE_PATH
+from models.group_info import GroupInfo
+from models.group_member_info import GroupInfoUser
+from models.level_user import LevelUser
+from services.log import logger
+from utils.depends import GetConfig
+from utils.manager import group_manager, plugins2settings_manager, requests_manager
+from utils.message_builder import image
+from utils.utils import FreqLimiter
__zx_plugin_name__ = "群事件处理 [Hidden]"
__plugin_version__ = 0.1
@@ -65,7 +66,7 @@ add_group = on_request(priority=1, block=False)
@group_increase_handle.handle()
async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
if event.user_id == int(bot.self_id):
- group = await GroupInfo.get_group_info(event.group_id)
+ group = await GroupInfo.filter(group_id=event.group_id).first()
# 群聊不存在或被强制拉群,退出该群
if (not group or group.group_flag == 0) and Config.get_config(
"invite_manager", "flag"
@@ -115,15 +116,12 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
user_info = await bot.get_group_member_info(
group_id=event.group_id, user_id=event.user_id
)
- if await GroupInfoUser.add_member_info(
- user_info["user_id"],
- user_info["group_id"],
- user_info["nickname"],
- join_time,
- ):
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
- else:
- logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新失败")
+ await GroupInfoUser.update_or_create(
+ user_qq=user_info["user_id"],
+ group_id=user_info["group_id"],
+ defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
+ )
+ logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
# 群欢迎消息
if _flmt.check(event.group_id):
@@ -152,7 +150,11 @@ async def _(bot: Bot, event: GroupIncreaseNoticeEvent):
else:
await group_increase_handle.send(
"[[_task|group_welcome]]新人快跑啊!!本群现状↓(快使用自定义!)"
- + image(random.choice(os.listdir(IMAGE_PATH / "qxz")), "qxz")
+ + image(
+ IMAGE_PATH
+ / "qxz"
+ / random.choice(os.listdir(IMAGE_PATH / "qxz"))
+ )
)
@@ -162,13 +164,13 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
if event.sub_type == "kick_me":
group_id = event.group_id
operator_id = event.operator_id
- try:
- operator_name = (
- await GroupInfoUser.get_member_info(event.operator_id, event.group_id)
- ).user_name
- except AttributeError:
+ if user := await GroupInfoUser.get_or_none(
+ user_qq=event.operator_id, group_id=event.group_id
+ ):
+ operator_name = user.user_name
+ else:
operator_name = "None"
- group = await GroupInfo.get_group_info(group_id)
+ group = await GroupInfo.filter(group_id=group_id).first()
group_name = group.group_name if group else ""
coffee = int(list(bot.config.superusers)[0])
await bot.send_private_msg(
@@ -182,16 +184,19 @@ async def _(bot: Bot, event: GroupDecreaseNoticeEvent):
if event.user_id == int(bot.self_id):
group_manager.delete_group(event.group_id)
return
- try:
- user_name = (
- await GroupInfoUser.get_member_info(event.user_id, event.group_id)
- ).user_name
- except AttributeError:
- user_name = str(event.user_id)
- if await GroupInfoUser.delete_member_info(event.user_id, event.group_id):
- logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除成功")
+ if user := await GroupInfoUser.get_or_none(
+ user_qq=event.user_id, group_id=event.group_id
+ ):
+ user_name = user.user_name
else:
- logger.info(f"用户{user_name}, qq={event.user_id} 所属{event.group_id} 删除失败")
+ user_name = f"{event.user_id}"
+ await GroupInfoUser.filter(user_qq=event.user_id, group_id=event.group_id).delete()
+ logger.info(
+ f"名称: {user_name} 退出群聊",
+ "group_decrease_handle",
+ event.user_id,
+ event.group_id,
+ )
rst = ""
if event.sub_type == "leave":
rst = f"{user_name}离开了我们..."
diff --git a/basic_plugins/hooks/_utils.py b/basic_plugins/hooks/_utils.py
index a5ded1e5..fcf6cce0 100644
--- a/basic_plugins/hooks/_utils.py
+++ b/basic_plugins/hooks/_utils.py
@@ -1,39 +1,40 @@
+import time
from typing import Optional
import nonebot
from nonebot.adapters.onebot.v11 import (
- GroupMessageEvent,
- PrivateMessageEvent,
Bot,
Event,
- MessageEvent,
+ GroupMessageEvent,
Message,
+ MessageEvent,
PokeNotifyEvent,
+ PrivateMessageEvent,
)
from nonebot.exception import ActionFailed, IgnoredException
from nonebot.internal.matcher import Matcher
+from configs.config import Config
from models.bag_user import BagUser
from models.ban_user import BanUser
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from models.level_user import LevelUser
from models.user_shop_gold_log import UserShopGoldLog
+from services.log import logger
from utils.decorator import Singleton
from utils.manager import (
- plugins2block_manager,
StaticData,
- plugins2settings_manager,
- group_manager,
admin_manager,
- plugins_manager,
+ group_manager,
+ plugins2block_manager,
plugins2cd_manager,
plugins2count_manager,
+ plugins2settings_manager,
+ plugins_manager,
)
from utils.message_builder import at
from utils.utils import FreqLimiter
-from configs.config import Config
-import time
ignore_rst_module = ["ai", "poke", "dialogue"]
@@ -97,11 +98,11 @@ async def send_msg(msg: str, bot: Bot, event: MessageEvent):
msg = msg.replace("[uname]", uname)
if "[nickname]" in msg:
if isinstance(event, GroupMessageEvent):
- nickname = await GroupInfoUser.get_group_member_nickname(
+ nickname = await GroupInfoUser.get_user_nickname(
event.user_id, event.group_id
)
else:
- nickname = await FriendUser.get_friend_nickname(event.user_id)
+ nickname = await FriendUser.get_user_nickname(event.user_id)
msg = msg.replace("[nickname]", nickname)
if "[at]" in msg and isinstance(event, GroupMessageEvent):
msg = msg.replace("[at]", str(at(event.user_id)))
@@ -142,16 +143,19 @@ class AuthChecker:
:param event: event
"""
try:
- plugin_name = matcher.plugin_name
- cost_gold = await self.auth_cost(plugin_name, bot, event)
- if hasattr(event, "user_id") and str(event.user_id) not in bot.config.superusers:
- await self.auth_basic(plugin_name, bot, event)
- self.auth_group(plugin_name, bot, event)
- await self.auth_admin(plugin_name, matcher, bot, event)
- await self.auth_plugin(plugin_name, matcher, bot, event)
- await self.auth_limit(plugin_name, bot, event)
- if cost_gold:
- await BagUser.spend_gold(event.user_id, event.group_id, cost_gold)
+ if plugin_name := matcher.plugin_name:
+ cost_gold = await self.auth_cost(plugin_name, bot, event)
+ user_id = getattr(event, "user_id", None)
+ if user_id and str(user_id) not in bot.config.superusers:
+ await self.auth_basic(plugin_name, bot, event)
+ self.auth_group(plugin_name, bot, event)
+ await self.auth_admin(plugin_name, matcher, bot, event)
+ await self.auth_plugin(plugin_name, matcher, bot, event)
+ await self.auth_limit(plugin_name, bot, event)
+ if cost_gold:
+ await BagUser.spend_gold(
+ event.user_id, event.group_id, cost_gold
+ )
except IsSuperuserException:
return
@@ -221,7 +225,9 @@ class AuthChecker:
else:
plugins2count_manager.increase(plugin_name, count_type_)
- async def auth_plugin(self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event):
+ async def auth_plugin(
+ self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event
+ ):
"""
说明:
插件状态
@@ -345,6 +351,7 @@ class AuthChecker:
and plugin_name not in ignore_rst_module
):
self._flmt_c.start_cd(event.group_id)
+ logger.info(f"{event.user_id} ||XXXXXX: {matcher.module}")
await bot.send_group_msg(
group_id=event.group_id, message="此功能正在维护..."
)
@@ -364,7 +371,9 @@ class AuthChecker:
set_block_limit_false(event, plugin_name)
raise IgnoredException("此功能正在维护...")
- async def auth_admin(self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event):
+ async def auth_admin(
+ self, plugin_name: str, matcher: Matcher, bot: Bot, event: Event
+ ):
"""
说明:
管理员命令 个人权限
@@ -504,8 +513,13 @@ class AuthChecker:
await BagUser.spend_gold(
event.user_id, event.group_id, psm.cost_gold
)
- await UserShopGoldLog.add_shop_log(
- event.user_id, event.group_id, 2, plugin_name, psm.cost_gold, 1
+ await UserShopGoldLog.create(
+ user_qq=event.user_id,
+ group_id=event.group_id,
+ type=2,
+ name=plugin_name,
+ num=1,
+ spend_gold=psm.cost_gold,
)
cost_gold = psm.cost_gold
return cost_gold
diff --git a/basic_plugins/hooks/ban_hook.py b/basic_plugins/hooks/ban_hook.py
index 27f1a012..3f53684f 100755
--- a/basic_plugins/hooks/ban_hook.py
+++ b/basic_plugins/hooks/ban_hook.py
@@ -1,20 +1,21 @@
-from nonebot.matcher import Matcher
-from nonebot.message import run_preprocessor, IgnoredException
-from nonebot.typing import T_State
from nonebot.adapters.onebot.v11 import (
+ ActionFailed,
Bot,
Event,
- MessageEvent,
- ActionFailed,
- PokeNotifyEvent,
GroupMessageEvent,
+ MessageEvent,
+ PokeNotifyEvent,
)
+from nonebot.matcher import Matcher
+from nonebot.message import IgnoredException, run_preprocessor
+from nonebot.typing import T_State
+
from configs.config import Config
from models.ban_user import BanUser
-from utils.utils import is_number, static_flmt, FreqLimiter
from utils.message_builder import at
-from ._utils import ignore_rst_module, other_limit_plugins
+from utils.utils import FreqLimiter, is_number, static_flmt
+from ._utils import ignore_rst_module, other_limit_plugins
Config.add_plugin_config(
"hook",
@@ -49,7 +50,7 @@ async def _(matcher: Matcher, bot: Bot, event: Event, state: T_State):
and str(event.user_id) not in bot.config.superusers
):
time = await BanUser.check_ban_time(event.user_id)
- if is_number(time):
+ if isinstance(time, int):
time = abs(int(time))
if time < 60:
time = str(time) + " 秒"
diff --git a/basic_plugins/hooks/chkdsk_hook.py b/basic_plugins/hooks/chkdsk_hook.py
index 055ffa1c..46c53410 100755
--- a/basic_plugins/hooks/chkdsk_hook.py
+++ b/basic_plugins/hooks/chkdsk_hook.py
@@ -28,12 +28,12 @@ async def _(matcher: Matcher, bot: Bot, event: GroupMessageEvent, state: T_State
if matcher.type == "message" and matcher.priority not in [1, 999]:
if state["_prefix"]["raw_command"]:
if _blmt.check(f'{event.user_id}{state["_prefix"]["raw_command"]}'):
- if await BanUser.ban(
+ await BanUser.ban(
event.user_id,
9,
Config.get_config("hook", "MALICIOUS_BAN_TIME") * 60,
- ):
- logger.info(f"USER {event.user_id} 触发了恶意触发检测")
+ )
+ logger.info(f"USER {event.user_id} 触发了恶意触发检测")
if isinstance(event, GroupMessageEvent):
try:
await bot.send_group_msg(
diff --git a/basic_plugins/init_plugin_config/__init__.py b/basic_plugins/init_plugin_config/__init__.py
index 4e5a5b15..355239fe 100755
--- a/basic_plugins/init_plugin_config/__init__.py
+++ b/basic_plugins/init_plugin_config/__init__.py
@@ -1,23 +1,23 @@
+import nonebot
+from nonebot import Driver
+from nonebot.adapters.onebot.v11 import Bot
+
from configs.path_config import DATA_PATH
-from .init_group_manager import init_group_manager, group_manager
+from services.log import logger
+
+from .check_plugin_status import check_plugin_status
+from .init import init
+from .init_none_plugin_count_manager import init_none_plugin_count_manager
+from .init_plugin_info import init_plugin_info
from .init_plugins_config import init_plugins_config
from .init_plugins_data import init_plugins_data, plugins_manager
-from .init_none_plugin_count_manager import init_none_plugin_count_manager
-from .init_plugins_resources import init_plugins_resources
-from .init_plugins_settings import init_plugins_settings
-from .init_plugin_info import init_plugin_info
from .init_plugins_limit import (
init_plugins_block_limit,
- init_plugins_count_limit,
init_plugins_cd_limit,
+ init_plugins_count_limit,
)
-from .init import init
-from .check_plugin_status import check_plugin_status
-from nonebot.adapters.onebot.v11 import Bot
-from services.log import logger
-from nonebot import Driver
-import nonebot
-
+from .init_plugins_resources import init_plugins_resources
+from .init_plugins_settings import init_plugins_settings
__zx_plugin_name__ = "初始化插件数据 [Hidden]"
__plugin_version__ = 0.1
@@ -44,10 +44,6 @@ async def _():
init_plugins_config()
init_plugins_resources()
init_none_plugin_count_manager()
- # x = group_manager.get_super_old_data()
- # if x:
- # for key in x.keys():
- # plugins_manager.block_plugin(key, block_type=x[key])
if _flag:
raise Exception("首次运行,已在configs目录下生成配置文件config.yaml,修改后重启即可...")
logger.info("初始化数据完成...")
diff --git a/basic_plugins/init_plugin_config/init_group_manager.py b/basic_plugins/init_plugin_config/init_group_manager.py
deleted file mode 100755
index 58a1a744..00000000
--- a/basic_plugins/init_plugin_config/init_group_manager.py
+++ /dev/null
@@ -1,73 +0,0 @@
-from pathlib import Path
-from utils.manager import group_manager
-from services.db_context import db
-from asyncpg.exceptions import DuplicateColumnError
-from services.log import logger
-
-try:
- import ujson as json
-except ModuleNotFoundError:
- import json
-try:
- from models.group_remind import GroupRemind
-except ModuleNotFoundError:
- pass
-
-
-async def init_group_manager():
- """
- 旧数据格式替换为新格式
- 初始化数据
- """
- old_group_level_file = Path() / "data" / "manager" / "group_level.json"
- old_plugin_list_file = Path() / "data" / "manager" / "plugin_list.json"
- if old_group_level_file.exists():
- data = json.load(open(old_group_level_file, "r", encoding="utf8"))
- for key in data.keys():
- group = key
- level = data[key]
- group_manager.set_group_level(group, level)
- old_group_level_file.unlink()
- group_manager.save()
-
- if old_plugin_list_file.exists():
- data = json.load(open(old_plugin_list_file, "r", encoding="utf8"))
- for plugin in data.keys():
- for group in data[plugin].keys():
- if group == "default" and not data[plugin]["default"]:
- group_manager.block_plugin(plugin)
- elif not data[plugin][group]:
- group_manager.block_plugin(plugin, group)
- old_plugin_list_file.unlink()
- old_data_table = Path() / "models" / "group_remind.py"
- try:
- if old_data_table.exists():
- b = {
- "hy": "group_welcome",
- "kxcz": "open_case_reset_remind",
- "zwa": "zwa",
- "blpar": "bilibili_parse",
- "epic": "epic_free_game",
- "pa": "pa",
- "almanac": "genshin_alc",
- }
- for group in group_manager.get_data()["group_manager"]:
- for remind in b:
- try:
- status = await GroupRemind.get_status(int(group), remind)
- if status is not None:
- if status:
- await group_manager.open_group_task(group, b[remind])
- logger.info(f"读取旧数据-->{group} 开启 {b[remind]}")
- else:
- await group_manager.close_group_task(group, b[remind])
- logger.info(f"读取旧数据-->{group} 关闭 {b[remind]}")
- except Exception as e:
- pass
- query = db.text("DROP TABLE group_reminds;")
- await db.first(query)
- old_data_table.unlink()
- logger.info("旧数据读取完毕,删除了舍弃表 group_reminds...")
- except (ModuleNotFoundError, DuplicateColumnError):
- pass
- group_manager.save()
diff --git a/basic_plugins/invite_manager/__init__.py b/basic_plugins/invite_manager/__init__.py
index 502f8812..4a07128f 100755
--- a/basic_plugins/invite_manager/__init__.py
+++ b/basic_plugins/invite_manager/__init__.py
@@ -1,20 +1,25 @@
-from nonebot import on_request, on_message
+import asyncio
+import re
+import time
+from datetime import datetime
+
+from nonebot import on_message, on_request
from nonebot.adapters.onebot.v11 import (
- Bot,
ActionFailed,
+ Bot,
FriendRequestEvent,
GroupRequestEvent,
MessageEvent,
)
-from models.friend_user import FriendUser
-from datetime import datetime
+
from configs.config import NICKNAME, Config
-from utils.manager import requests_manager
+from models.friend_user import FriendUser
from models.group_info import GroupInfo
+from services.log import logger
+from utils.manager import requests_manager
from utils.utils import scheduler
-import asyncio
-import time
-import re
+
+from .utils import time_manager
__zx_plugin_name__ = "好友群聊处理请求 [Hidden]"
__plugin_version__ = 0.1
@@ -27,101 +32,109 @@ friend_req = on_request(priority=5, block=True)
group_req = on_request(priority=5, block=True)
x = on_message(priority=999, block=False, rule=lambda: False)
-exists_data = {"private": {}, "group": {}}
-
@friend_req.handle()
async def _(bot: Bot, event: FriendRequestEvent):
- global exists_data
- if exists_data["private"].get(event.user_id):
- if time.time() - exists_data["private"][event.user_id] < 60 * 5:
- return
- exists_data["private"][event.user_id] = time.time()
- user = await bot.get_stranger_info(user_id=event.user_id)
- nickname = user["nickname"]
- sex = user["sex"]
- age = str(user["age"])
- comment = event.comment
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"*****一份好友申请*****\n"
- f"昵称:{nickname}({event.user_id})\n"
- f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
- f"日期:{str(datetime.now()).split('.')[0]}\n"
- f"备注:{event.comment}",
- )
- if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
- await bot.set_friend_add_request(flag=event.flag, approve=True)
- await FriendUser.add_friend_info(user["user_id"], user["nickname"])
- else:
- requests_manager.add_request(
- event.user_id,
- "private",
- event.flag,
- nickname=nickname,
- sex=sex,
- age=age,
- comment=comment,
+ if time_manager.add_user_request(event.user_id):
+ logger.debug(f"收录 用户[{event.user_id}] 好友请求", "好友请求")
+ user = await bot.get_stranger_info(user_id=event.user_id)
+ nickname = user["nickname"]
+ sex = user["sex"]
+ age = str(user["age"])
+ comment = event.comment
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"*****一份好友申请*****\n"
+ f"昵称:{nickname}({event.user_id})\n"
+ f"自动同意:{'√' if Config.get_config('invite_manager', 'AUTO_ADD_FRIEND') else '×'}\n"
+ f"日期:{str(datetime.now()).split('.')[0]}\n"
+ f"备注:{event.comment}",
)
+ if Config.get_config("invite_manager", "AUTO_ADD_FRIEND"):
+ logger.debug(f"已开启好友请求自动同意,成功通过该请求", "好友请求", target=event.user_id)
+ await bot.set_friend_add_request(flag=event.flag, approve=True)
+ await FriendUser.create(user_id=user["user_id"], user_name=user["nickname"])
+ else:
+ requests_manager.add_request(
+ event.user_id,
+ "private",
+ event.flag,
+ nickname=nickname,
+ sex=sex,
+ age=age,
+ comment=comment,
+ )
+ else:
+ logger.debug(f"好友请求五分钟内重复, 已忽略", "好友请求", target=event.user_id)
@group_req.handle()
async def _(bot: Bot, event: GroupRequestEvent):
- global exists_data
+ # 邀请
if event.sub_type == "invite":
if str(event.user_id) in bot.config.superusers:
try:
- if await GroupInfo.get_group_info(event.group_id):
- await GroupInfo.set_group_flag(event.group_id, 1)
- else:
- group_info = await bot.get_group_info(group_id=event.group_id)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
- )
+ logger.debug(
+ f"超级用户自动同意加入群聊", "群聊请求", event.user_id, target=event.group_id
+ )
await bot.set_group_add_request(
flag=event.flag, sub_type="invite", approve=True
)
- except ActionFailed:
- pass
+ group_info = await bot.get_group_info(group_id=event.group_id)
+ await GroupInfo.update_or_create(
+ group_id=group_info["group_id"],
+ defaults={
+ "group_name": group_info["group_name"],
+ "max_member_count": group_info["max_member_count"],
+ "member_count": group_info["member_count"],
+ "group_flag": 1,
+ },
+ )
+ except ActionFailed as e:
+ logger.error(
+ "超级用户自动同意加入群聊发生错误",
+ "群聊请求",
+ event.user_id,
+ target=event.group_id,
+ e=e,
+ )
else:
- user = await bot.get_stranger_info(user_id=event.user_id)
- sex = user["sex"]
- age = str(user["age"])
- if exists_data["group"].get(f"{event.user_id}:{event.group_id}"):
- if (
- time.time()
- - exists_data["group"][f"{event.user_id}:{event.group_id}"]
- < 60 * 5
- ):
- return
- exists_data["group"][f"{event.user_id}:{event.group_id}"] = time.time()
- nickname = await FriendUser.get_user_name(event.user_id)
- await bot.send_private_msg(
- user_id=int(list(bot.config.superusers)[0]),
- message=f"*****一份入群申请*****\n"
- f"申请人:{nickname}({event.user_id})\n"
- f"群聊:{event.group_id}\n"
- f"邀请日期:{str(datetime.now()).split('.')[0]}",
- )
- await bot.send_private_msg(
- user_id=event.user_id,
- message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
- "请确保已经群主或群管理沟通过!\n"
- "等待管理员处理吧!",
- )
- requests_manager.add_request(
- event.user_id,
- "group",
- event.flag,
- invite_group=event.group_id,
- nickname=nickname,
- sex=sex,
- age=age,
- )
+ if time_manager.add_group_request(event.user_id, event.group_id):
+ logger.debug(
+ f"收录 用户[{event.user_id}] 群聊[{event.group_id}] 群聊请求", "群聊请求"
+ )
+ user = await bot.get_stranger_info(user_id=event.user_id)
+ sex = user["sex"]
+ age = str(user["age"])
+ nickname = await FriendUser.get_user_name(event.user_id)
+ await bot.send_private_msg(
+ user_id=int(list(bot.config.superusers)[0]),
+ message=f"*****一份入群申请*****\n"
+ f"申请人:{nickname}({event.user_id})\n"
+ f"群聊:{event.group_id}\n"
+ f"邀请日期:{datetime.now().replace(microsecond=0)}",
+ )
+ await bot.send_private_msg(
+ user_id=event.user_id,
+ message=f"想要邀请我偷偷入群嘛~已经提醒{NICKNAME}的管理员大人了\n"
+ "请确保已经群主或群管理沟通过!\n"
+ "等待管理员处理吧!",
+ )
+ requests_manager.add_request(
+ event.user_id,
+ "group",
+ event.flag,
+ invite_group=event.group_id,
+ nickname=nickname,
+ sex=sex,
+ age=age,
+ )
+ else:
+ logger.debug(
+ f"群聊请求五分钟内重复, 已忽略",
+ "群聊请求",
+ target=f"{event.user_id}:{event.group_id}",
+ )
@x.handle()
@@ -145,5 +158,4 @@ async def _(event: MessageEvent):
minutes=5,
)
async def _():
- global exists_data
- exists_data = {"private": {}, "group": {}}
+ time_manager.clear()
diff --git a/basic_plugins/invite_manager/utils.py b/basic_plugins/invite_manager/utils.py
new file mode 100644
index 00000000..aee7c6f1
--- /dev/null
+++ b/basic_plugins/invite_manager/utils.py
@@ -0,0 +1,87 @@
+import time
+from dataclasses import dataclass
+from typing import Dict
+
+
+@dataclass
+class PrivateRequest:
+
+ """
+ 好友请求
+ """
+
+ user_id: int
+ time: float = time.time()
+
+
+@dataclass
+class GroupRequest:
+
+ """
+ 群聊请求
+ """
+
+ user_id: int
+ group_id: int
+ time: float = time.time()
+
+
+class RequestTimeManage:
+
+ """
+ 过滤五分钟以内的重复请求
+ """
+
+ def __init__(self):
+
+ self._group: Dict[str, GroupRequest] = {}
+ self._user: Dict[int, PrivateRequest] = {}
+
+ def add_user_request(self, user_id: int) -> bool:
+ """
+ 添加请求时间
+
+ Args:
+ user_id (int): 用户id
+
+ Returns:
+ bool: 是否满足时间
+ """
+ if user := self._user.get(user_id):
+ if time.time() - user.time < 60 * 5:
+ return False
+ self._user[user_id] = PrivateRequest(user_id)
+ return True
+
+ def add_group_request(self, user_id: int, group_id: int) -> bool:
+ """
+ 添加请求时间
+
+ Args:
+ user_id (int): 用户id
+ group_id (int): 邀请群聊
+
+ Returns:
+ bool: 是否满足时间
+ """
+ key = f"{user_id}:{group_id}"
+ if group := self._group.get(key):
+ if time.time() - group.time < 60 * 5:
+ return False
+ self._group[key] = GroupRequest(user_id=user_id, group_id=group_id)
+ return True
+
+ def clear(self):
+ """
+ 清理过期五分钟请求
+ """
+ now = time.time()
+ for user_id in self._user:
+ if now - self._user[user_id].time < 60 * 5:
+ del self._user[user_id]
+ for key in self._group:
+ if now - self._group[key].time < 60 * 5:
+ del self._group[key]
+
+
+time_manager = RequestTimeManage()
diff --git a/basic_plugins/nickname.py b/basic_plugins/nickname.py
index c46fc79a..74ed4542 100755
--- a/basic_plugins/nickname.py
+++ b/basic_plugins/nickname.py
@@ -1,121 +1,162 @@
-from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, PrivateMessageEvent, Message, MessageEvent
-from nonebot import on_command
-from nonebot.typing import T_State
-from nonebot.rule import to_me
-from models.group_member_info import GroupInfoUser
-from models.friend_user import FriendUser
-from models.ban_user import BanUser
-from services.log import logger
-from configs.config import NICKNAME, Config
-from nonebot.params import CommandArg
import random
+from typing import Any, Tuple
+
+from nonebot import on_command, on_regex
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.internal.matcher import Matcher
+from nonebot.internal.params import Depends
+from nonebot.params import CommandArg, RegexGroup
+from nonebot.rule import to_me
+
+from configs.config import NICKNAME
+from models.ban_user import BanUser
+from models.friend_user import FriendUser
+from models.group_member_info import GroupInfoUser
+from services.log import logger
+from utils.depends import GetConfig
__zx_plugin_name__ = "昵称系统"
__plugin_usage__ = f"""
usage:
- 个人昵称系统,群聊 与 私聊 昵称相互独立
+ 个人昵称,将替换真寻称呼你的名称,群聊 与 私聊 昵称相互独立,全局昵称设置将更改您目前所有群聊中及私聊的昵称
指令:
- 以后叫我 [昵称]
+ 以后叫我 [昵称]: 设置当前群聊/私聊的昵称
+ 全局昵称设置 [昵称]: 设置当前所有群聊和私聊的昵称
{NICKNAME}我是谁
""".strip()
__plugin_des__ = "区区昵称,才不想叫呢!"
-__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁"]
+__plugin_cmd__ = ["以后叫我 [昵称]", f"{NICKNAME}我是谁", "全局昵称设置 [昵称]"]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
- "cmd": ["昵称", "昵称系统"],
+ "cmd": ["昵称"],
}
__plugin_configs__ = {
"BLACK_WORD": {
- "value": ["爸", "爹", "爷", "父亲"],
- "help": "昵称所屏蔽的关键词,会被替换为 *",
- "default_value": None
+ "value": ["爸", "爹", "爷", "父"],
+ "help": "昵称所屏蔽的关键词,已设置的昵称会被替换为 *,未设置的昵称会在设置时提示",
+ "default_value": None,
}
}
-nickname = on_command(
- "nickname",
- aliases={"以后叫我", "以后请叫我", "称呼我", "以后请称呼我", "以后称呼我", "叫我", "请叫我"},
+nickname = on_regex(
+ "(?:以后)?(?:叫我|请叫我|称呼我)(.*)",
rule=to_me(),
priority=5,
block=True,
)
my_nickname = on_command(
- "my_name", aliases={"我叫什么", "我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
+ "我叫什么", aliases={"我是谁", "我的名字"}, rule=to_me(), priority=5, block=True
)
+global_nickname = on_regex("设置全局昵称(.*)", rule=to_me(), priority=5, block=True)
+
cancel_nickname = on_command("取消昵称", rule=to_me(), priority=5, block=True)
-@nickname.handle()
-async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
- msg = arg.extract_plain_text().strip()
- if not msg:
- await nickname.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
- if len(msg) > 10:
- await nickname.finish("昵称可不能超过10个字!", at_sender=True)
- if msg in bot.config.superusers:
- await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
- _tmp = ""
- black_word = Config.get_config("nickname", "BLACK_WORD")
- if black_word:
- for x in msg:
- _tmp += "*" if x in black_word else x
- msg = _tmp
+def CheckNickname():
+ """
+ 说明:
+ 检查名称是否合法
+ """
+
+ async def dependency(
+ bot: Bot,
+ matcher: Matcher,
+ event: MessageEvent,
+ reg_group: Tuple[Any, ...] = RegexGroup(),
+ black_word: Any = GetConfig(config="BLACK_WORD"),
+ ):
+ (msg,) = reg_group
+ logger.debug(f"昵称检查: {msg}", "昵称设置", event.user_id)
+ if not msg:
+ await matcher.finish("叫你空白?叫你虚空?叫你无名??", at_sender=True)
+ if str(event.user_id) in bot.config.superusers:
+ logger.debug(f"超级用户设置昵称, 跳过合法检测: {msg}", "昵称设置", event.user_id)
+ return
+ if len(msg) > 20:
+ await nickname.finish("昵称可不能超过20个字!", at_sender=True)
+ if msg in bot.config.nickname:
+ await nickname.finish("笨蛋!休想占用我的名字!#", at_sender=True)
+ if black_word:
+ for x in msg:
+ if x in black_word:
+ logger.debug("昵称设置禁止字符: [{x}]", "昵称设置", event.user_id)
+ await nickname.finish(f"字符 [{x}] 为禁止字符!", at_sender=True)
+ for word in black_word:
+ if word in msg:
+ logger.debug("昵称设置禁止字符: [{word}]", "昵称设置", event.user_id)
+ await nickname.finish(f"字符 [{word}] 为禁止字符!", at_sender=True)
+
+ return Depends(dependency)
+
+
+@global_nickname.handle(parameterless=[CheckNickname()])
+async def _(
+ event: MessageEvent,
+ reg_group: Tuple[Any, ...] = RegexGroup(),
+):
+ (msg,) = reg_group
+ await FriendUser.set_user_nickname(event.user_id, msg)
+ await GroupInfoUser.filter(user_qq=event.user_id).update(nickname=msg)
+ logger.info(f"设置全局昵称成功: {msg}", "设置全局昵称", event.user_id)
+ await global_nickname.send(f"设置全局昵称成功!亲爱的{msg}")
+
+
+@nickname.handle(parameterless=[CheckNickname()])
+async def _(
+ event: MessageEvent,
+ reg_group: Tuple[Any, ...] = RegexGroup(),
+):
+ (msg,) = reg_group
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}了.",
- ]
- )
+ await GroupInfoUser.set_user_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}")
- else:
- await nickname.send("设置昵称失败,请更新群组成员信息!", at_sender=True)
- logger.warning(f"USER {event.user_id} GROUP {event.group_id} 设置群昵称 {msg} 失败")
+ )
+ logger.info(f"设置群昵称成功: {msg}", "昵称设置", event.user_id, event.group_id)
else:
- 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}了.",
- ]
- )
+ await FriendUser.set_user_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"设置私聊昵称成功: {msg}", "昵称设置", event.user_id)
@my_nickname.handle()
-async def _(event: GroupMessageEvent):
- try:
- nickname_ = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
- except AttributeError:
- nickname_ = ""
+async def _(event: MessageEvent):
+ nickname_ = None
+ card = None
+ if isinstance(event, GroupMessageEvent):
+ nickname_ = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
+ card = event.sender.card or event.sender.nickname
+ else:
+ nickname_ = await FriendUser.get_user_nickname(event.user_id)
+ card = event.sender.nickname
if nickname_:
await my_nickname.send(
random.choice(
@@ -130,44 +171,20 @@ async def _(event: GroupMessageEvent):
)
)
else:
- nickname_ = event.sender.card or event.sender.nickname
await my_nickname.send(
random.choice(
["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
- ).format(nickname_)
- )
-
-
-@my_nickname.handle()
-async def _(bot: Bot, event: PrivateMessageEvent, state: T_State):
- nickname_ = await FriendUser.get_friend_nickname(event.user_id)
- if nickname_:
- await my_nickname.send(
- random.choice(
- [
- f"我肯定记得你啊,你是{nickname_}啊",
- f"我不会忘记你的,你也不要忘记我!{nickname_}",
- f"哼哼,{NICKNAME}记忆力可是很好的,{nickname_}",
- f"嗯?你是失忆了嘛...{nickname_}..",
- f"不要小看{NICKNAME}的记忆力啊!笨蛋{nickname_}!QAQ",
- f"哎?{nickname_}..怎么了吗..突然这样问..",
- ]
- )
- )
- else:
- nickname_ = (await bot.get_stranger_info(user_id=event.user_id))["nickname"]
- await my_nickname.send(
- random.choice(
- ["没..没有昵称嘛,{}", "啊,你是{}啊,我想叫你的昵称!", "是{}啊,有什么事吗?", "你是{}?"]
- ).format(nickname_)
+ ).format(card)
)
@cancel_nickname.handle()
-async def _(event: GroupMessageEvent):
- nickname_ = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
+async def _(event: MessageEvent):
+ nickname_ = None
+ if isinstance(event, GroupMessageEvent):
+ nickname_ = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
+ else:
+ nickname_ = await FriendUser.get_user_nickname(event.user_id)
if nickname_:
await cancel_nickname.send(
random.choice(
@@ -180,28 +197,10 @@ async def _(event: GroupMessageEvent):
]
)
)
- await GroupInfoUser.set_group_member_nickname(event.user_id, event.group_id, "")
- await BanUser.ban(event.user_id, 9, 60)
- else:
- await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
-
-
-@cancel_nickname.handle()
-async def _(event: PrivateMessageEvent):
- nickname_ = await FriendUser.get_friend_nickname(event.user_id)
- if nickname_:
- await cancel_nickname.send(
- random.choice(
- [
- f"呜..{NICKNAME}睡一觉就会忘记的..和梦一样..{nickname_}",
- f"窝知道了..{nickname_}..",
- f"是{NICKNAME}哪里做的不好嘛..好吧..晚安{nickname_}",
- f"呃,{nickname_},下次我绝对绝对绝对不会再忘记你!",
- f"可..可恶!{nickname_}!太可恶了!呜",
- ]
- )
- )
- await FriendUser.get_user_name(event.user_id)
+ if isinstance(event, GroupMessageEvent):
+ await GroupInfoUser.set_user_nickname(event.user_id, event.group_id, "")
+ else:
+ await FriendUser.set_user_nickname(event.user_id, "")
await BanUser.ban(event.user_id, 9, 60)
else:
await cancel_nickname.send("你在做梦吗?你没有昵称啊", at_sender=True)
diff --git a/basic_plugins/plugin_shop/__init__.py b/basic_plugins/plugin_shop/__init__.py
index 4af777d5..0ef17cb9 100644
--- a/basic_plugins/plugin_shop/__init__.py
+++ b/basic_plugins/plugin_shop/__init__.py
@@ -1,13 +1,17 @@
from nonebot import on_command, on_regex
-
-from .data_source import show_plugin_repo, install_plugin, uninstall_plugin, download_json
-from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.params import CommandArg
-
-from utils.message_builder import image
from nonebot.permission import SUPERUSER
+from services.log import logger
+from utils.message_builder import image
+
+from .data_source import (
+ download_json,
+ install_plugin,
+ show_plugin_repo,
+ uninstall_plugin,
+)
__zx_plugin_name__ = "插件商店 [Superuser]"
__plugin_usage__ = """
@@ -28,23 +32,29 @@ show_repo = on_regex("^查看插件仓库$", priority=1, block=True, permission=
update_repo = on_regex("^更新插件仓库$", priority=1, block=True, permission=SUPERUSER)
-install_plugin_matcher = on_command("安装插件", priority=1, block=True, permission=SUPERUSER)
+install_plugin_matcher = on_command(
+ "安装插件", priority=1, block=True, permission=SUPERUSER
+)
-uninstall_plugin_matcher = on_command("卸载插件", priority=1, block=True, permission=SUPERUSER)
+uninstall_plugin_matcher = on_command(
+ "卸载插件", priority=1, block=True, permission=SUPERUSER
+)
@install_plugin_matcher.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
- arg = arg.extract_plain_text().strip()
- msg = await install_plugin(arg)
+ name = arg.extract_plain_text().strip()
+ msg = await install_plugin(name)
await install_plugin_matcher.send(msg)
+ logger.info(f"安装插件: {name}", "安装插件", event.user_id)
@uninstall_plugin_matcher.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
- arg = arg.extract_plain_text().strip()
- msg = await uninstall_plugin(arg)
+ name = arg.extract_plain_text().strip()
+ msg = await uninstall_plugin(name)
await install_plugin_matcher.send(msg)
+ logger.info(f"卸载插件: {name}", "卸载插件", event.user_id)
@update_repo.handle()
@@ -53,16 +63,13 @@ async def _(bot: Bot, event: MessageEvent):
if code == 200:
await update_repo.finish("更新插件仓库信息成功!")
await update_repo.send("更新插件仓库信息失败!")
-
+ logger.info("更新插件仓库信息", "更新插件仓库信息", event.user_id)
+
@show_repo.handle()
async def _(bot: Bot, event: MessageEvent):
msg = await show_plugin_repo()
if isinstance(msg, int):
await show_repo.finish("文件下载失败或解压失败..")
- await show_repo.send(image(b64=msg))
- logger.info(
- f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 查看插件仓库"
- )
-
+ await show_repo.send(image(msg))
+ logger.info("查看插件仓库", "查看插件仓库", event.user_id)
diff --git a/basic_plugins/plugin_shop/data_source.py b/basic_plugins/plugin_shop/data_source.py
index c73d3d7d..e582ded5 100644
--- a/basic_plugins/plugin_shop/data_source.py
+++ b/basic_plugins/plugin_shop/data_source.py
@@ -2,15 +2,15 @@ import os
import shutil
import zipfile
from pathlib import Path
-from typing import Union, Tuple
-from utils.manager import plugins_manager
+from typing import Tuple, Union
import ujson as json
+from configs.path_config import DATA_PATH, TEMP_PATH
from services import logger
from utils.http_utils import AsyncHttpx
-from configs.path_config import TEMP_PATH, DATA_PATH
-from utils.image_utils import text2image, BuildImage
+from utils.image_utils import BuildImage, text2image
+from utils.manager import plugins_manager
from utils.utils import is_number
path = DATA_PATH / "plugin_shop"
@@ -48,7 +48,7 @@ async def install_plugin(name: str) -> str:
if zip_file.exists():
zip_file.unlink()
if await AsyncHttpx.download_file(url, zip_file):
- logger.debug("开始解压插件压缩包...")
+ logger.debug("开始解压插件压缩包...", "安装插件", target=name)
# 解压
zf = zipfile.ZipFile(zip_file, "r")
extract_path = TEMP_PATH / f"{name}"
@@ -58,32 +58,34 @@ async def install_plugin(name: str) -> str:
for file in zf.namelist():
zf.extract(file, extract_path)
zf.close()
- logger.debug("解压插件压缩包完成...")
- logger.debug("开始移动插件文件夹...")
+ logger.debug("解压插件压缩包完成...", "安装插件", target=name)
+ logger.debug("开始移动插件文件夹...", "安装插件", target=name)
if (extensive_plugin_path / f"{name}").exists():
- logger.debug("extensive_plugin目录下文件夹已存在,删除该目录插件文件夹...")
+ logger.debug(
+ "extensive_plugin目录下文件夹已存在,删除该目录插件文件夹...", "安装插件", target=name
+ )
shutil.rmtree(
(extensive_plugin_path / f"{name}").absolute(), ignore_errors=True
)
extract_path.rename(extensive_plugin_path / f"{name}")
- tmp = ""
+ prompt = ""
if "pyproject.toml" in os.listdir(extensive_plugin_path / f"{name}"):
- tmp = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
+ prompt = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
os.system(
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'pyproject.toml').absolute()}"
)
elif "requirements.txt" in os.listdir(extensive_plugin_path / f"{name}"):
- tmp = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
+ prompt = "检测到该插件含有额外依赖,当前安装无法保证依赖完全安装成功。"
os.system(
f"poetry run pip install -r {(extensive_plugin_path / f'{name}' / 'requirements.txt').absolute()}"
)
with open(extensive_plugin_path / f"{name}" / "plugin_info.json", "w") as f:
json.dump(data[name], f, ensure_ascii=False, indent=4)
- logger.debug("移动插件文件夹完成...")
- logger.info(f"成功安装插件 {name} 成功!\n{tmp}")
+ logger.debug("移动插件文件夹完成...", "安装插件", target=name)
+ logger.info(f"成功安装插件 {name} 成功!\n{prompt}", "安装插件", target=name)
return f"成功安装插件 {name},请重启真寻!"
except Exception as e:
- logger.error(f"安装插件 {name} 失败 {type(e)}:{e}")
+ logger.error(f"安装插失败", "安装插件", target=name, e=e)
return f"安装插件 {name} 失败 {type(e)}:{e}"
@@ -138,7 +140,7 @@ async def show_plugin_repo() -> Union[int, str]:
version = f"[{plugins_data[key].version}]"
s = (
f'id:{i+1}\n名称:{plugin_info[key]["plugin_name"]}'
- f' \t\t{status}\n'
+ f" \t\t{status}\n"
f"模块:{key}\n"
f'作者:{plugin_info[key]["author"]}\n'
f'版本:{plugin_info[key]["version"]} \t\t{version}\n'
diff --git a/basic_plugins/scripts.py b/basic_plugins/scripts.py
index 3e711d4b..1a16d7a1 100755
--- a/basic_plugins/scripts.py
+++ b/basic_plugins/scripts.py
@@ -1,23 +1,16 @@
import random
-
-from asyncpg.exceptions import (
- DuplicateColumnError,
- UndefinedColumnError,
- PostgresSyntaxError,
-)
-from nonebot import Driver
-from services.db_context import db
-from models.group_info import GroupInfo
-from models.bag_user import BagUser
-from nonebot.adapters.onebot.v11 import Bot
-from services.log import logger
-from configs.path_config import TEXT_PATH
from asyncio.exceptions import TimeoutError
-from typing import List
-from utils.http_utils import AsyncHttpx
-from utils.utils import GDict
-from utils.utils import scheduler
+
import nonebot
+from nonebot.adapters.onebot.v11 import Bot
+from nonebot.drivers import Driver
+
+from configs.path_config import TEXT_PATH
+from models.bag_user import BagUser
+from models.group_info import GroupInfo
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.utils import GDict, scheduler
try:
import ujson as json
@@ -38,6 +31,7 @@ async def update_city():
data = {}
if not china_city.exists():
try:
+ logger.debug("开始更新城市列表...")
res = await AsyncHttpx.get(
"http://www.weather.com.cn/data/city3jdata/china.html", timeout=5
)
@@ -56,103 +50,97 @@ async def update_city():
with open(china_city, "w", encoding="utf8") as f:
json.dump(data, f, indent=4, ensure_ascii=False)
logger.info("自动更新城市列表完成.....")
- except TimeoutError:
- logger.warning("自动更新城市列表超时.....")
- except ValueError:
- logger.warning("自动城市列表失败.....")
+ except TimeoutError as e:
+ logger.warning("自动更新城市列表超时...", e=e)
+ except ValueError as e:
+ logger.warning("自动城市列表失败.....", e=e)
except Exception as e:
- logger.error(f"自动城市列表未知错误 {type(e)}:{e}")
+ logger.error(f"自动城市列表未知错误", e=e)
-@driver.on_startup
-async def _():
- """
- 数据库表结构变换
- """
- _flag = []
- sql_str = [
- (
- "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
- "group_info",
- ), # group_info表添加一个group_flag
- (
- "ALTER TABLE bag_users rename belonging_group To group_id;",
- "bag_users",
- ), # 将 bag_users 的 belonging_group 改为 group_id
- (
- "ALTER TABLE group_info_users rename belonging_group To group_id;",
- "group_info_users",
- ),
- (
- "ALTER TABLE sign_group_users rename belonging_group To group_id;",
- "sign_group_users",
- ),
- (
- "ALTER TABLE open_cases_users rename belonging_group To group_id;",
- "open_cases_users",
- ),
- (
- "ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
- "bag_users",
- ), # bag_users 新增字段 property 替代 props
- (
- "ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
- "genshin"
- ), # 新增原神自动签到字段
- (
- "ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
- "genshin"
- ), # 新增原神自动签到字段
- (
- "ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
- "genshin"
- ), # 新增原神自动签到字段
- (
- "ALTER TABLE genshin ADD bind_group Integer;",
- "genshin"
- ), # 新增原神群号绑定字段
- (
- "ALTER TABLE genshin ADD login_ticket VARCHAR(255) DEFAULT '';",
- "genshin"
- ), # 新增米游社login_ticket绑定字段
- (
- "ALTER TABLE genshin ADD stuid VARCHAR(255) DEFAULT '';",
- "genshin"
- ), # 新增米游社stuid绑定字段
- (
- "ALTER TABLE genshin ADD stoken VARCHAR(255) DEFAULT '';",
- "genshin"
- ), # 新增米游社stoken绑定字段
- (
- "ALTER TABLE chat_history ADD plain_text Text;",
- "chat_history"
- ), # 新增纯文本
- (
- "ALTER TABLE goods_info ADD daily_limit Integer DEFAULT 0;",
- "goods_info"
- ), # 新增纯文本
- (
- "ALTER TABLE goods_info ADD daily_purchase_limit Json DEFAULT '{}';",
- "goods_info"
- ), # 新增纯文本
- ]
- for sql in sql_str + GDict.get('run_sql', []):
- try:
- if isinstance(sql, str):
- flag = f'{random.randint(1, 10000)}'
- else:
- flag = sql[1]
- sql = sql[0]
- query = db.text(sql)
- await db.first(query)
- logger.info(f"完成sql操作:{sql}")
- _flag.append(flag)
- except (DuplicateColumnError, UndefinedColumnError):
- pass
- except PostgresSyntaxError:
- logger.error(f"语法错误:执行sql失败:{sql}")
- # bag_user 将文本转为字典格式
- await __database_script(_flag)
+# @driver.on_startup
+# async def _():
+# """
+# 数据库表结构变换
+# """
+# _flag = []
+# sql_str = [
+# (
+# "ALTER TABLE group_info ADD group_flag Integer NOT NULL DEFAULT 0;",
+# "group_info",
+# ), # group_info表添加一个group_flag
+# (
+# "ALTER TABLE bag_users rename belonging_group To group_id;",
+# "bag_users",
+# ), # 将 bag_users 的 belonging_group 改为 group_id
+# (
+# "ALTER TABLE group_info_users rename belonging_group To group_id;",
+# "group_info_users",
+# ),
+# (
+# "ALTER TABLE sign_group_users rename belonging_group To group_id;",
+# "sign_group_users",
+# ),
+# (
+# "ALTER TABLE open_cases_users rename belonging_group To group_id;",
+# "open_cases_users",
+# ),
+# (
+# "ALTER TABLE bag_users ADD property json NOT NULL DEFAULT '{}';",
+# "bag_users",
+# ), # bag_users 新增字段 property 替代 props
+# (
+# "ALTER TABLE genshin ADD auto_sign_time timestamp with time zone;",
+# "genshin",
+# ), # 新增原神自动签到字段
+# (
+# "ALTER TABLE genshin ADD resin_remind boolean DEFAULT False;",
+# "genshin",
+# ), # 新增原神自动签到字段
+# (
+# "ALTER TABLE genshin ADD resin_recovery_time timestamp with time zone;",
+# "genshin",
+# ), # 新增原神自动签到字段
+# ("ALTER TABLE genshin ADD bind_group Integer;", "genshin"), # 新增原神群号绑定字段
+# (
+# "ALTER TABLE genshin ADD login_ticket VARCHAR(255) DEFAULT '';",
+# "genshin",
+# ), # 新增米游社login_ticket绑定字段
+# (
+# "ALTER TABLE genshin ADD stuid VARCHAR(255) DEFAULT '';",
+# "genshin",
+# ), # 新增米游社stuid绑定字段
+# (
+# "ALTER TABLE genshin ADD stoken VARCHAR(255) DEFAULT '';",
+# "genshin",
+# ), # 新增米游社stoken绑定字段
+# ("ALTER TABLE chat_history ADD plain_text Text;", "chat_history"), # 新增纯文本
+# (
+# "ALTER TABLE goods_info ADD daily_limit Integer DEFAULT 0;",
+# "goods_info",
+# ), # 新增纯文本
+# (
+# "ALTER TABLE goods_info ADD daily_purchase_limit Json DEFAULT '{}';",
+# "goods_info",
+# ), # 新增纯文本
+# ]
+# for sql in sql_str + GDict.get("run_sql", []):
+# try:
+# if isinstance(sql, str):
+# flag = f"{random.randint(1, 10000)}"
+# else:
+# flag = sql[1]
+# sql = sql[0]
+# query = db.text(sql)
+# await db.first(query)
+# logger.info(f"完成sql操作:{sql}")
+# _flag.append(flag)
+# except (DuplicateColumnError, UndefinedColumnError):
+# pass
+# except PostgresSyntaxError:
+# logger.error(f"语法错误:执行sql失败:{sql}")
+# bag_user 将文本转为字典格式
+# await __database_script(_flag)
@driver.on_bot_connect
@@ -161,51 +149,57 @@ async def _(bot: Bot):
版本某些需要的变换
"""
# 清空不存在的群聊信息,并将已所有已存在的群聊group_flag设置为1(认证所有已存在的群)
- if not await GroupInfo.get_group_info(114514):
+ if not await GroupInfo.get_or_none(group_id=114514):
# 标识符,该功能只需执行一次
- await GroupInfo.add_group_info(114514, "114514", 114514, 114514, 1)
+ await GroupInfo.create(
+ group_id=114514,
+ group_name="114514",
+ max_member_count=114514,
+ member_count=114514,
+ group_flag=1,
+ )
group_list = await bot.get_group_list()
group_list = [g["group_id"] for g in group_list]
- _gl = [x.group_id for x in await GroupInfo.get_all_group()]
+ _gl = [x.group_id for x in await GroupInfo.all()]
if 114514 in _gl:
_gl.remove(114514)
for group_id in _gl:
if group_id in group_list:
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 1)
+ if group := await GroupInfo.get_or_none(group_id=group_id):
+ await group.update_or_create(group_flag=1)
else:
group_info = await bot.get_group_info(group_id=group_id)
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
+ await GroupInfo.create(
+ group_id=group_info["group_id"],
+ group_name=group_info["group_name"],
+ max_member_count=group_info["max_member_count"],
+ member_count=group_info["member_count"],
+ group_flag=1,
)
- logger.info(f"已将群聊 {group_id} 添加认证...")
+ logger.info(f"已添加群认证...", group_id=group_id)
else:
- await GroupInfo.delete_group_info(group_id)
- logger.info(f"移除不存在的群聊信息:{group_id}")
+ await GroupInfo.filter(group_id=group_id).delete()
+ logger.info(f"移除不存在的群聊信息", group_id=group_id)
-async def __database_script(_flag: List[str]):
- # bag_user 将文本转为字典格式
- if "bag_users" in _flag:
- for x in await BagUser.get_all_users():
- props = {}
- if x.props:
- for prop in [p for p in x.props.split(",") if p]:
- if props.get(prop):
- props[prop] += 1
- else:
- props[prop] = 1
- logger.info(
- f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
- )
- await x.update(
- property=props,
- props="",
- ).apply()
+# async def __database_script(_flag: List[str]):
+# # bag_user 将文本转为字典格式
+# if "bag_users" in _flag:
+# for x in await BagUser.get_all_users():
+# props = {}
+# if x.props:
+# for prop in [p for p in x.props.split(",") if p]:
+# if props.get(prop):
+# props[prop] += 1
+# else:
+# props[prop] = 1
+# logger.info(
+# f"__database_script USER {x.user_qq} GROUP {x.group_id} 更新数据 {props}"
+# )
+# await x.update(
+# property=props,
+# props="",
+# ).apply()
# 自动更新城市列表
diff --git a/basic_plugins/shop/__init__.py b/basic_plugins/shop/__init__.py
index 501ebfa4..58dac39a 100644
--- a/basic_plugins/shop/__init__.py
+++ b/basic_plugins/shop/__init__.py
@@ -1,21 +1,40 @@
-from configs.config import Config
-from nonebot import Driver
-from utils.decorator.shop import shop_register
+from pathlib import Path
+
import nonebot
+from nonebot.drivers import Driver
+
+from configs.config import Config
+from utils.decorator.shop import shop_register
driver: Driver = nonebot.get_driver()
Config.add_plugin_config(
- "shop",
- "IMPORT_DEFAULT_SHOP_GOODS",
- True,
- help_="导入商店自带的三个商品",
- default_value=True
+ "shop", "IMPORT_DEFAULT_SHOP_GOODS", True, help_="导入商店自带的三个商品", default_value=True
)
-nonebot.load_plugins("basic_plugins/shop")
+nonebot.load_plugins(str(Path(__file__).parent.resolve()))
+
+
+@shop_register(
+ name=("好感度双倍加持卡Ⅰ", "好感度双倍加持卡Ⅱ", "好感度双倍加持卡Ⅲ"),
+ price=(30, 150, 250),
+ des=(
+ "下次签到双倍好感度概率 + 10%(谁才是真命天子?)(同类商品将覆盖)",
+ "下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)",
+ "下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)",
+ ),
+ load_status=bool(Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS")),
+ icon=(
+ "favorability_card_1.png",
+ "favorability_card_2.png",
+ "favorability_card_3.png",
+ ),
+ **{"好感度双倍加持卡Ⅰ_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3},
+)
+async def sign_card(user_id: int, group_id: int):
+ pass
@driver.on_bot_connect
diff --git a/basic_plugins/shop/buy.py b/basic_plugins/shop/buy.py
index 99592d1c..a89031f8 100644
--- a/basic_plugins/shop/buy.py
+++ b/basic_plugins/shop/buy.py
@@ -1,16 +1,15 @@
-from nonebot import on_command
-
-from models.user_shop_gold_log import UserShopGoldLog
-from services.log import logger
-from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
-from nonebot.params import CommandArg
-from utils.utils import is_number
-from models.bag_user import BagUser
-from services.db_context import db
-from nonebot.adapters.onebot.v11.permission import GROUP
-from models.goods_info import GoodsInfo
import time
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message
+from nonebot.adapters.onebot.v11.permission import GROUP
+from nonebot.params import CommandArg
+
+from models.bag_user import BagUser
+from models.goods_info import GoodsInfo
+from models.user_shop_gold_log import UserShopGoldLog
+from services.log import logger
+from utils.utils import is_number
__zx_plugin_name__ = "商店 - 购买道具"
__plugin_usage__ = """
@@ -71,39 +70,40 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
await buy.finish("请输入正确的商品名称!")
else:
await buy.finish("请输入正确的商品名称!", at_sender=True)
- async with db.transaction():
- if (
- await BagUser.get_gold(event.user_id, event.group_id)
- ) < goods.goods_price * num * goods.goods_discount:
- await buy.finish("您的金币好像不太够哦", at_sender=True)
- flag, n = await GoodsInfo.check_user_daily_purchase(
- goods, event.user_id, event.group_id, num
- )
- if flag:
- await buy.finish(f"该次购买将超过每日次数限制,目前该道具还可以购买{n}次哦", at_sender=True)
- if await BagUser.buy_property(event.user_id, event.group_id, goods, num):
- await GoodsInfo.add_user_daily_purchase(
- goods, event.user_id, event.group_id, num
- )
- await buy.send(
- f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
- at_sender=True,
- )
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} "
- f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!"
- )
- await UserShopGoldLog.add_shop_log(
- event.user_id,
- event.group_id,
- 0,
- goods.goods_name,
- num,
- goods.goods_price * num * goods.goods_discount,
- )
- else:
- await buy.send(f"{goods.goods_name} 购买失败!", at_sender=True)
- logger.info(
- f"USER {event.user_id} GROUP {event.group_id} "
- f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 失败!"
- )
+ if (
+ await BagUser.get_gold(event.user_id, event.group_id)
+ ) < goods.goods_price * num * goods.goods_discount:
+ await buy.finish("您的金币好像不太够哦", at_sender=True)
+ flag, n = await GoodsInfo.check_user_daily_purchase(
+ goods, event.user_id, event.group_id, num
+ )
+ if flag:
+ await buy.finish(f"该次购买将超过每日次数限制,目前该道具还可以购买{n}次哦", at_sender=True)
+ spend_gold = int(goods.goods_discount * goods.goods_price * num)
+ await BagUser.spend_gold(event.user_id, event.group_id, spend_gold)
+ await BagUser.add_property(event.user_id, event.group_id, goods.goods_name, num)
+ await GoodsInfo.add_user_daily_purchase(goods, event.user_id, event.group_id, num)
+ await buy.send(
+ f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 成功!",
+ at_sender=True,
+ )
+ logger.info(
+ f"花费 {goods.goods_price*num} 金币购买 {goods.goods_name} ×{num} 成功!",
+ "购买道具",
+ event.user_id,
+ event.group_id,
+ )
+ await UserShopGoldLog.create(
+ user_qq=event.user_id,
+ group_id=event.group_id,
+ type=0,
+ name=goods.goods_name,
+ num=num,
+ spend_gold=goods.goods_price * num * goods.goods_discount,
+ )
+ # else:
+ # await buy.send(f"{goods.goods_name} 购买失败!", at_sender=True)
+ # logger.info(
+ # f"USER {event.user_id} GROUP {event.group_id} "
+ # f"花费 {goods.goods_price * num * goods.goods_discount} 金币购买 {goods.goods_name} ×{num} 失败!"
+ # )
diff --git a/basic_plugins/shop/gold.py b/basic_plugins/shop/gold.py
index e3635338..e761361c 100644
--- a/basic_plugins/shop/gold.py
+++ b/basic_plugins/shop/gold.py
@@ -1,9 +1,10 @@
from nonebot import on_command
-from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, ActionFailed
-from nonebot.params import CommandArg
+from nonebot.adapters.onebot.v11 import ActionFailed, GroupMessageEvent, Message
from nonebot.adapters.onebot.v11.permission import GROUP
-from utils.data_utils import init_rank
+from nonebot.params import CommandArg
+
from models.bag_user import BagUser
+from utils.data_utils import init_rank
from utils.image_utils import text2image
from utils.message_builder import image
from utils.utils import is_number
@@ -39,7 +40,9 @@ async def _(event: GroupMessageEvent):
try:
await my_gold.send(msg)
except ActionFailed:
- await my_gold.send(image(b64=(await text2image(msg, color="#f9f6f2", padding=10)).pic2bs4()))
+ await my_gold.send(
+ image(b64=(await text2image(msg, color="#f9f6f2", padding=10)).pic2bs4())
+ )
@gold_rank.handle()
@@ -49,9 +52,11 @@ async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
num = int(num)
else:
num = 10
- all_users = await BagUser.get_all_users(event.group_id)
+ all_users = await BagUser.filter(group_id=event.group_id)
all_user_id = [user.user_qq for user in all_users]
all_user_data = [user.gold for user in all_users]
- rank_image = await init_rank("金币排行", all_user_id, all_user_data, event.group_id, num)
+ rank_image = await init_rank(
+ "金币排行", all_user_id, all_user_data, event.group_id, num
+ )
if rank_image:
await gold_rank.finish(image(b64=rank_image.pic2bs4()))
diff --git a/basic_plugins/shop/my_props/__init__.py b/basic_plugins/shop/my_props/__init__.py
index 4f5e9827..fc3bd6cf 100644
--- a/basic_plugins/shop/my_props/__init__.py
+++ b/basic_plugins/shop/my_props/__init__.py
@@ -1,12 +1,12 @@
from nonebot import on_command
-
-from utils.message_builder import image
-from ._data_source import create_bag_image
-from services.log import logger
from nonebot.adapters.onebot.v11 import GroupMessageEvent
-from models.bag_user import BagUser
from nonebot.adapters.onebot.v11.permission import GROUP
+from models.bag_user import BagUser
+from services.log import logger
+from utils.message_builder import image
+
+from ._data_source import create_bag_image
__zx_plugin_name__ = "商店 - 我的道具"
__plugin_usage__ = """
@@ -17,7 +17,7 @@ usage:
""".strip()
__plugin_des__ = "商店 - 我的道具"
__plugin_cmd__ = ["我的道具"]
-__plugin_type__ = ('商店',)
+__plugin_type__ = ("商店",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
@@ -36,10 +36,6 @@ async def _(event: GroupMessageEvent):
props = await BagUser.get_property(event.user_id, event.group_id)
if props:
await my_props.send(image(b64=await create_bag_image(props)))
- # rst = ""
- # for i, p in enumerate(props.keys()):
- # rst += f"{i+1}.{p}\t×{props[p]}\n"
- # await my_props.send("\n" + rst[:-1], at_sender=True)
logger.info(f"USER {event.user_id} GROUP {event.group_id} 查看我的道具")
else:
await my_props.finish("您的背包里没有任何的道具噢~", at_sender=True)
diff --git a/basic_plugins/shop/reset_today_gold.py b/basic_plugins/shop/reset_today_gold.py
deleted file mode 100644
index 7097f043..00000000
--- a/basic_plugins/shop/reset_today_gold.py
+++ /dev/null
@@ -1,26 +0,0 @@
-from utils.utils import scheduler
-from models.bag_user import BagUser
-from services.log import logger
-
-
-__zx_plugin_name__ = "每日金币重置 [Hidden]"
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-# 重置每日金币
-@scheduler.scheduled_job(
- "cron",
- hour=0,
- minute=1,
-)
-async def _():
- try:
- user_list = await BagUser.get_all_users()
- for user in user_list:
- await user.update(
- get_today_gold=0,
- spend_today_gold=0,
- ).apply()
- except Exception as e:
- logger.error(f"重置每日金币错误 e:{e}")
diff --git a/basic_plugins/shop/shop_handle/__init__.py b/basic_plugins/shop/shop_handle/__init__.py
index 6323f8af..9748330a 100644
--- a/basic_plugins/shop/shop_handle/__init__.py
+++ b/basic_plugins/shop/shop_handle/__init__.py
@@ -1,14 +1,24 @@
-from .data_source import create_shop_help, delete_goods, update_goods, register_goods, parse_goods_info, GoodsInfo
-from nonebot.adapters.onebot.v11 import MessageEvent, Message
-from nonebot import on_command
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from nonebot.permission import SUPERUSER
-from utils.utils import is_number, scheduler
-from nonebot.params import CommandArg
-from services.log import logger
import os
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Message, MessageEvent
+from nonebot.params import CommandArg
+from nonebot.permission import SUPERUSER
+
+from configs.path_config import IMAGE_PATH
+from models.bag_user import BagUser
+from services.log import logger
+from utils.message_builder import image
+from utils.utils import is_number, scheduler
+
+from .data_source import (
+ GoodsInfo,
+ create_shop_help,
+ delete_goods,
+ parse_goods_info,
+ register_goods,
+ update_goods,
+)
__zx_plugin_name__ = "商店"
__plugin_usage__ = """
@@ -37,7 +47,7 @@ __plugin_cmd__ = [
"删除商品 [名称或序号] [_superuser]",
"修改商品 name:[名称或序号] price:[价格] des:[描述] discount:[折扣] limit_time:[限时] [_superuser]",
]
-__plugin_type__ = ('商店',)
+__plugin_type__ = ("商店",)
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
@@ -46,9 +56,7 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["商店"],
}
-__plugin_block_limit__ = {
- "limit_type": "group"
-}
+__plugin_block_limit__ = {"limit_type": "group"}
shop_help = on_command("商店", priority=5, block=True)
@@ -75,12 +83,15 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
if not data.get("name") or not data.get("price") or not data.get("des"):
await shop_add_goods.finish("name:price:des 参数不可缺少!")
if await register_goods(**data):
- await shop_add_goods.send(f"添加商品 {data['name']} 成功!\n"
- f"名称:{data['name']}\n"
- f"价格:{data['price']}金币\n"
- f"简介:{data['des']}\n"
- f"折扣:{data.get('discount')}\n"
- f"限时:{data.get('limit_time')}", at_sender=True)
+ await shop_add_goods.send(
+ f"添加商品 {data['name']} 成功!\n"
+ f"名称:{data['name']}\n"
+ f"价格:{data['price']}金币\n"
+ f"简介:{data['des']}\n"
+ f"折扣:{data.get('discount')}\n"
+ f"限时:{data.get('limit_time')}",
+ at_sender=True,
+ )
logger.info(f"USER {event.user_id} 添加商品 {msg} 成功")
else:
await shop_add_goods.send(f"添加商品 {msg} 失败了...", at_sender=True)
@@ -133,7 +144,19 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
)
async def _():
try:
- await GoodsInfo.reset_daily_purchase()
+ await GoodsInfo.all().update(daily_purchase_limit={})
logger.info("商品每日限购次数重置成功...")
except Exception as e:
- logger.error(f"商品每日限购次数重置发生错误 {type(e)}:{e}")
+ logger.error(f"商品每日限购次数重置出错 {type(e)}:{e}")
+
+
+@scheduler.scheduled_job(
+ "cron",
+ hour=0,
+ minute=1,
+)
+async def _():
+ try:
+ await BagUser.all().update(get_today_gold=0, spend_today_gold=0)
+ except Exception as e:
+ logger.error(f"重置每日金币", "定时任务", e=e)
diff --git a/basic_plugins/shop/shop_handle/data_source.py b/basic_plugins/shop/shop_handle/data_source.py
index a1e9dd27..a4b90e23 100644
--- a/basic_plugins/shop/shop_handle/data_source.py
+++ b/basic_plugins/shop/shop_handle/data_source.py
@@ -1,18 +1,18 @@
+import time
+from typing import Optional, Tuple, Union
+
from PIL import Image
+from configs.path_config import IMAGE_PATH
from models.goods_info import GoodsInfo
from utils.image_utils import BuildImage, text2image
-from utils.utils import is_number
-from configs.path_config import IMAGE_PATH
-from typing import Optional, Union, Tuple
-from utils.utils import GDict
-import time
+from utils.utils import GDict, is_number
-icon_path = IMAGE_PATH / 'shop_icon'
+icon_path = IMAGE_PATH / "shop_icon"
-GDict['run_sql'].append("ALTER TABLE goods_info ADD is_passive boolean DEFAULT False;")
-GDict['run_sql'].append("ALTER TABLE goods_info ADD icon VARCHAR(255);")
+GDict["run_sql"].append("ALTER TABLE goods_info ADD is_passive boolean DEFAULT False;")
+GDict["run_sql"].append("ALTER TABLE goods_info ADD icon VARCHAR(255);")
# 创建商店界面
@@ -43,17 +43,31 @@ async def create_shop_help() -> str:
await name_image.atext((390, 0), "售价:", center_type="by_height")
if goods.goods_discount != 1:
discount_price = int(goods.goods_discount * goods.goods_price)
- old_price_image = BuildImage(0, 0, plain_text=str(goods.goods_price), font_color=(194, 194, 194), font="CJGaoDeGuo.otf", font_size=15)
- await old_price_image.aline((0, int(old_price_image.h / 2), old_price_image.w + 1, int(old_price_image.h / 2)), (0, 0, 0))
- await name_image.apaste(
- old_price_image, (440, 0), True
+ old_price_image = BuildImage(
+ 0,
+ 0,
+ plain_text=str(goods.goods_price),
+ font_color=(194, 194, 194),
+ font="CJGaoDeGuo.otf",
+ font_size=15,
)
- await name_image.atext(
- (440, 15), str(discount_price), (255, 255, 255)
+ await old_price_image.aline(
+ (
+ 0,
+ int(old_price_image.h / 2),
+ old_price_image.w + 1,
+ int(old_price_image.h / 2),
+ ),
+ (0, 0, 0),
)
+ await name_image.apaste(old_price_image, (440, 0), True)
+ await name_image.atext((440, 15), str(discount_price), (255, 255, 255))
else:
await name_image.atext(
- (440, 0), str(goods.goods_price), (255, 255, 255), center_type="by_height"
+ (440, 0),
+ str(goods.goods_price),
+ (255, 255, 255),
+ center_type="by_height",
)
await name_image.atext(
(
@@ -68,38 +82,48 @@ async def create_shop_help() -> str:
font_img = BuildImage(
600, 80, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
)
- p = font_img.getsize('简介:')[0] + 20
+ p = font_img.getsize("简介:")[0] + 20
if goods.goods_description:
- des_list = goods.goods_description.split('\n')
- desc = ''
+ des_list = goods.goods_description.split("\n")
+ desc = ""
for des in des_list:
if font_img.getsize(des)[0] > font_img.w - p - 20:
- msg = ''
- tmp = ''
+ msg = ""
+ tmp = ""
for i in range(len(des)):
if font_img.getsize(tmp)[0] < font_img.w - p - 20:
tmp += des[i]
else:
- msg += tmp + '\n'
+ msg += tmp + "\n"
tmp = des[i]
desc += msg
if tmp:
desc += tmp
else:
- desc += des + '\n'
- if desc[-1] == '\n':
+ desc += des + "\n"
+ if desc[-1] == "\n":
desc = desc[:-1]
des_image = await text2image(desc, color="#a29ad6")
goods_image = BuildImage(
- 600, (50 + des_image.h) if des_image else 50, font_size=20, color="#a29ad6", font="CJGaoDeGuo.otf"
+ 600,
+ (50 + des_image.h) if des_image else 50,
+ font_size=20,
+ color="#a29ad6",
+ font="CJGaoDeGuo.otf",
)
if des_image:
- await goods_image.atext((15, 50), '简介:')
+ await goods_image.atext((15, 50), "简介:")
await goods_image.apaste(des_image, (p, 50))
await name_image.acircle_corner(5)
await goods_image.apaste(name_image, (0, 5), True, center_type="by_width")
await goods_image.acircle_corner(20)
- bk = BuildImage(1180, (50 + des_image.h) if des_image else 50, font_size=15, color="#f9f6f2", font="CJGaoDeGuo.otf")
+ bk = BuildImage(
+ 1180,
+ (50 + des_image.h) if des_image else 50,
+ font_size=15,
+ color="#f9f6f2",
+ font="CJGaoDeGuo.otf",
+ )
if goods.icon and (icon_path / goods.icon).exists():
icon = BuildImage(70, 70, background=icon_path / goods.icon)
await bk.apaste(icon)
@@ -129,7 +153,9 @@ async def create_shop_help() -> str:
_w += 140
if goods.goods_discount != 1:
n += 140
- _discount_logo = BuildImage(30, 30, background=f"{IMAGE_PATH}/other/discount.png")
+ _discount_logo = BuildImage(
+ 30, 30, background=f"{IMAGE_PATH}/other/discount.png"
+ )
await bk.apaste(_discount_logo, (_w + 50, 10), True)
await bk.apaste(
BuildImage(0, 0, plain_text="折扣!", font_size=23, font="CJGaoDeGuo.otf"),
@@ -137,14 +163,23 @@ async def create_shop_help() -> str:
True,
)
await bk.apaste(
- BuildImage(0, 0, plain_text=f"{10 * goods.goods_discount:.1f} 折", font_size=30, font="CJGaoDeGuo.otf", font_color=(85, 156, 75)),
+ BuildImage(
+ 0,
+ 0,
+ plain_text=f"{10 * goods.goods_discount:.1f} 折",
+ font_size=30,
+ font="CJGaoDeGuo.otf",
+ font_color=(85, 156, 75),
+ ),
(_w + 50, 44),
True,
)
_w += 140
if goods.daily_limit != 0:
n += 140
- _daily_limit_logo = BuildImage(35, 35, background=f"{IMAGE_PATH}/other/daily_limit.png")
+ _daily_limit_logo = BuildImage(
+ 35, 35, background=f"{IMAGE_PATH}/other/daily_limit.png"
+ )
await bk.apaste(_daily_limit_logo, (_w + 50, 10), True)
await bk.apaste(
BuildImage(0, 0, plain_text="限购!", font_size=23, font="CJGaoDeGuo.otf"),
@@ -152,7 +187,13 @@ async def create_shop_help() -> str:
True,
)
await bk.apaste(
- BuildImage(0, 0, plain_text=f"{goods.daily_limit}", font_size=30, font="CJGaoDeGuo.otf"),
+ BuildImage(
+ 0,
+ 0,
+ plain_text=f"{goods.daily_limit}",
+ font_size=30,
+ font="CJGaoDeGuo.otf",
+ ),
(_w + 72, 45),
True,
)
@@ -220,22 +261,30 @@ async def register_goods(
:param icon: 图标
:return: 是否添加成功
"""
- if not await GoodsInfo.get_goods_info(name):
- limit_time = float(limit_time) if limit_time else limit_time
+ if not await GoodsInfo.get_or_none(goods_name=name):
+ limit_time_ = float(limit_time) if limit_time else limit_time
discount = discount if discount is not None else 1
- limit_time = (
- int(time.time() + limit_time * 60 * 60)
- if limit_time is not None and limit_time != 0
+ limit_time_ = (
+ int(time.time() + limit_time_ * 60 * 60)
+ if limit_time_ is not None and limit_time_ != 0
else 0
)
- return await GoodsInfo.add_goods(
- name, int(price), des, float(discount), limit_time, daily_limit, is_passive, icon
+ await GoodsInfo.create(
+ goods_name=name,
+ goods_price=int(price),
+ goods_description=des,
+ goods_discount=float(discount),
+ goods_limit_time=limit_time_,
+ daily_limit=daily_limit,
+ is_passive=is_passive,
+ icon=icon,
)
+ return True
return False
# 删除商品
-async def delete_goods(name: str, id_: int) -> "str, str, int":
+async def delete_goods(name: str, id_: int) -> Tuple[str, str, int]:
"""
删除商品
:param name: 商品名称
@@ -256,6 +305,7 @@ async def delete_goods(name: str, id_: int) -> "str, str, int":
return f"删除商品 {name} 成功!", name, 200
else:
return f"删除商品 {name} 失败!", name, 999
+ return "获取商品失败", "", 999
# 更新商品信息
@@ -272,7 +322,7 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
return False, "序号错误,没有该序号的商品...", ""
goods = goods_lst[int(kwargs["name"]) - 1]
else:
- goods = await GoodsInfo.get_goods_info(kwargs["name"])
+ goods = await GoodsInfo.filter(goods_name=kwargs["name"]).first()
if not goods:
return False, "名称错误,没有该名称的商品...", ""
name: str = goods.goods_name
@@ -295,14 +345,22 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
discount = kwargs["discount"]
if kwargs.get("limit_time"):
kwargs["limit_time"] = float(kwargs["limit_time"])
- new_time = time.strftime(
- "%Y-%m-%d %H:%M:%S",
- time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
- ) if kwargs["limit_time"] != 0 else 0
+ new_time = (
+ time.strftime(
+ "%Y-%m-%d %H:%M:%S",
+ time.localtime(time.time() + kwargs["limit_time"] * 60 * 60),
+ )
+ if kwargs["limit_time"] != 0
+ else 0
+ )
tmp += f"限时至: {new_time}\n" if new_time else "取消了限时\n"
limit_time = kwargs["limit_time"]
if kwargs.get("daily_limit"):
- tmp += f'每日购买限制:{daily_limit} --> {kwargs["daily_limit"]}\n' if daily_limit else "取消了购买限制\n"
+ tmp += (
+ f'每日购买限制:{daily_limit} --> {kwargs["daily_limit"]}\n'
+ if daily_limit
+ else "取消了购买限制\n"
+ )
daily_limit = int(kwargs["daily_limit"])
if kwargs.get("is_passive"):
tmp += f'被动道具:{is_passive} --> {kwargs["is_passive"]}\n'
@@ -318,9 +376,13 @@ async def update_goods(**kwargs) -> Tuple[bool, str, str]:
else 0
),
daily_limit,
- is_passive
+ is_passive,
+ )
+ return (
+ True,
+ name,
+ tmp[:-1],
)
- return True, name, tmp[:-1],
def parse_goods_info(msg: str) -> Union[dict, str]:
diff --git a/basic_plugins/shop/use/__init__.py b/basic_plugins/shop/use/__init__.py
index 1c3ffca0..57cc5c00 100644
--- a/basic_plugins/shop/use/__init__.py
+++ b/basic_plugins/shop/use/__init__.py
@@ -1,19 +1,17 @@
from typing import Any, Tuple
from nonebot import on_command, on_regex
-
-from models.user_shop_gold_log import UserShopGoldLog
-from services.log import logger
from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message
+from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.params import CommandArg, RegexGroup
+from models.bag_user import BagUser
+from models.user_shop_gold_log import UserShopGoldLog
+from services.log import logger
from utils.decorator.shop import NotMeetUseConditionsException
from utils.utils import is_number
-from models.bag_user import BagUser
-from nonebot.adapters.onebot.v11.permission import GROUP
-from services.db_context import db
-from .data_source import effect, register_use, func_manager, build_params
+from .data_source import build_params, effect, func_manager, register_use
__zx_plugin_name__ = "商店 - 使用道具"
__plugin_usage__ = """
@@ -75,17 +73,25 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
if prop_n not in property_.keys():
await use_props.finish("道具名称错误!", at_sender=True)
name = prop_n
+ if not name:
+ await use_props.finish("未获取到道具名称", at_sender=True)
_user_prop_count = property_[name]
if num > _user_prop_count:
await use_props.finish(f"道具数量不足,无法使用{num}次!")
if num > (n := func_manager.get_max_num_limit(name)):
await use_props.finish(f"该道具单次只能使用 {n} 个!")
- model, kwargs = build_params(bot, event, name, num, text)
try:
- await func_manager.run_handle(type_="before_handle", param=model, **kwargs)
- except NotMeetUseConditionsException as e:
- await use_props.finish(e.get_info(), at_sender=True)
- async with db.transaction():
+ model, kwargs = build_params(bot, event, name, num, text)
+ except KeyError:
+ logger.warning(f"{name} 未注册使用函数")
+ await use_props.finish(f"{name} 未注册使用方法")
+ else:
+ try:
+ await func_manager.run_handle(
+ type_="before_handle", param=model, **kwargs
+ )
+ except NotMeetUseConditionsException as e:
+ await use_props.finish(e.get_info(), at_sender=True)
if await BagUser.delete_property(event.user_id, event.group_id, name, num):
if func_manager.check_send_success_message(name):
await use_props.send(f"使用道具 {name} {num} 次成功!", at_sender=True)
@@ -94,14 +100,18 @@ async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次成功"
)
- await UserShopGoldLog.add_shop_log(
- event.user_id, event.group_id, 1, name, num
+ await UserShopGoldLog.create(
+ user_qq=event.user_id,
+ group_id=event.group_id,
+ type=1,
+ name=name,
+ num=num,
)
else:
await use_props.send(f"使用道具 {name} {num} 次失败!", at_sender=True)
logger.info(
f"USER {event.user_id} GROUP {event.group_id} 使用道具 {name} {num} 次失败"
)
- await func_manager.run_handle(type_="after_handle", param=model, **kwargs)
+ await func_manager.run_handle(type_="after_handle", param=model, **kwargs)
else:
await use_props.send("您的背包里没有任何的道具噢", at_sender=True)
diff --git a/basic_plugins/shop/use/data_source.py b/basic_plugins/shop/use/data_source.py
index 7b8dafbf..b52d2c52 100644
--- a/basic_plugins/shop/use/data_source.py
+++ b/basic_plugins/shop/use/data_source.py
@@ -108,7 +108,7 @@ class GoodsUseFuncManager:
)
async def run_handle(self, goods_name: str, type_: str, param: ShopParam, **kwargs):
- if self._data[goods_name].get(type_):
+ if self._data.get(goods_name) and self._data[goods_name].get(type_):
for func in self._data[goods_name].get(type_):
args = inspect.signature(func).parameters
if args and list(args.keys())[0] != "kwargs":
@@ -170,7 +170,6 @@ def build_params(
:param goods_name: 商品名称
:param num: 数量
:param text: 其他信息
- :return:
"""
_kwargs = func_manager.get_kwargs(goods_name)
return (
diff --git a/basic_plugins/super_cmd/__init__.py b/basic_plugins/super_cmd/__init__.py
index 2d381421..87ae4077 100755
--- a/basic_plugins/super_cmd/__init__.py
+++ b/basic_plugins/super_cmd/__init__.py
@@ -1,11 +1,5 @@
-import nonebot
from pathlib import Path
+import nonebot
nonebot.load_plugins(str(Path(__file__).parent.resolve()))
-
-
-
-
-
-
diff --git a/basic_plugins/super_cmd/bot_friend_group.py b/basic_plugins/super_cmd/bot_friend_group.py
index ab313a97..1470a9d8 100755
--- a/basic_plugins/super_cmd/bot_friend_group.py
+++ b/basic_plugins/super_cmd/bot_friend_group.py
@@ -1,14 +1,17 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.adapters.onebot.v11 import Bot, Message
-from nonebot.params import Command, CommandArg
from typing import Tuple
+
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
+from nonebot.params import Command, CommandArg
+from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
-from utils.utils import is_number
+
+from models.group_info import GroupInfo
+from services.log import logger
+from utils.depends import OneCommand
from utils.manager import requests_manager
from utils.message_builder import image
-from models.group_info import GroupInfo
-
+from utils.utils import is_number
__zx_plugin_name__ = "显示所有好友群组 [Superuser]"
__plugin_usage__ = """
@@ -76,8 +79,7 @@ async def _(bot: Bot):
@friend_handle.handle()
-async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
+async def _(bot: Bot, cmd: str = OneCommand(), arg: Message = CommandArg()):
id_ = arg.extract_plain_text().strip()
if is_number(id_):
id_ = int(id_)
@@ -97,8 +99,9 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
@group_handle.handle()
-async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
+async def _(
+ bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
+):
id_ = arg.extract_plain_text().strip()
flag = None
if is_number(id_):
@@ -106,20 +109,21 @@ async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandAr
if cmd[:2] == "同意":
rid = requests_manager.get_group_id(id_)
if rid:
- if await GroupInfo.get_group_info(rid):
- await GroupInfo.set_group_flag(rid, 1)
+ if group := await GroupInfo.filter(group_id=rid).first():
+ await group.update_or_create(group_flag=1)
else:
group_info = await bot.get_group_info(group_id=rid)
- await GroupInfo.add_group_info(
- rid,
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1
+ await GroupInfo.create(
+ group_id=rid,
+ group_name=group_info["group_name"],
+ max_member_count=group_info["max_member_count"],
+ member_count=group_info["member_count"],
+ group_flag=1,
)
flag = await requests_manager.approve(bot, id_, "group")
else:
await group_handle.send("同意群聊请求失败,未找到此id的请求..")
+ logger.info("同意群聊请求失败,未找到此id的请求..", cmd, event.user_id)
else:
flag = await requests_manager.refused(bot, id_, "group")
if flag == 1:
@@ -139,15 +143,15 @@ async def _():
for type_ in ["private", "group"]:
msg = await requests_manager.show(type_)
if msg:
- _str += image(b64=msg)
+ _str += image(msg)
else:
_str += "没有任何好友请求.." if type_ == "private" else "没有任何群聊请求.."
if type_ == "private":
- _str += '\n--------------------\n'
+ _str += "\n--------------------\n"
await cls_request.send(Message(_str))
@clear_request.handle()
async def _():
requests_manager.clear()
- await clear_request.send("已清空所有好友/群聊请求..")
\ No newline at end of file
+ await clear_request.send("已清空所有好友/群聊请求..")
diff --git a/basic_plugins/super_cmd/clear_data.py b/basic_plugins/super_cmd/clear_data.py
index 8fcd7bfc..effca772 100755
--- a/basic_plugins/super_cmd/clear_data.py
+++ b/basic_plugins/super_cmd/clear_data.py
@@ -1,13 +1,15 @@
+import asyncio
+import os
+import time
+
from nonebot import on_command
from nonebot.permission import SUPERUSER
-from configs.path_config import TEMP_PATH
from nonebot.rule import to_me
-from utils.utils import scheduler
+
+from configs.path_config import TEMP_PATH
from services.log import logger
from utils.manager import resources_manager
-import asyncio
-import time
-import os
+from utils.utils import scheduler
__zx_plugin_name__ = "清理临时数据 [Superuser]"
__plugin_usage__ = """
@@ -37,22 +39,29 @@ async def _():
await clear_data.send("开始清理临时数据....")
size = await asyncio.get_event_loop().run_in_executor(None, _clear_data)
await clear_data.send("共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
+ logger.info("清理临时数据完成," + "共清理了 {:.2f}MB 的数据...".format(size / 1024 / 1024))
def _clear_data() -> float:
+ logger.debug("开始清理临时文件...")
size = 0
- for dir_ in resources_manager.get_temp_data_dir():
- if dir_.exists():
- for file in os.listdir(dir_):
- file = dir_ / file
- if file.is_file():
- try:
- if time.time() - os.path.getatime(file) > 300:
- file_size = os.path.getsize(file)
- file.unlink()
- size += file_size
- except Exception as e:
- logger.error(f"清理临时数据错误...{type(e)}:{e}")
+ dir_list = [dir_ for dir_ in resources_manager.get_temp_data_dir() if dir_.exists()]
+ for dir_ in dir_list:
+ logger.debug(f"尝试清理文件夹: {dir_.absolute()}", "清理临时数据")
+ dir_size = 0
+ for file in os.listdir(dir_):
+ file = dir_ / file
+ if file.is_file():
+ try:
+ if time.time() - os.path.getatime(file) > 10:
+ file_size = os.path.getsize(file)
+ file.unlink()
+ size += file_size
+ dir_size += file_size
+ logger.debug(f"移除临时文件: {file.absolute()}", "清理临时数据")
+ except Exception as e:
+ logger.error(f"清理临时数据错误,临时文件夹: {dir_.absolute()}...", "清理临时数据", e=e)
+ logger.debug("清理临时文件夹大小: {:.2f}MB".format(size / 1024 / 1024), "清理临时数据")
return float(size)
diff --git a/basic_plugins/super_cmd/exec_sql.py b/basic_plugins/super_cmd/exec_sql.py
index 2914046a..26763de9 100644
--- a/basic_plugins/super_cmd/exec_sql.py
+++ b/basic_plugins/super_cmd/exec_sql.py
@@ -1,13 +1,15 @@
-from nonebot.adapters.onebot.v11 import Message, Bot, MessageEvent
+import asyncio
+
from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
-from utils.message_builder import custom_forward_msg
-from services.db_context import db
-from nonebot.params import CommandArg
-from services.log import logger
+from tortoise import Tortoise
-import asyncio
+from services.db_context import TestSQL
+from services.log import logger
+from utils.message_builder import custom_forward_msg
__zx_plugin_name__ = "执行sql [Superuser]"
__plugin_usage__ = """
@@ -18,9 +20,7 @@ usage:
查看所有表
""".strip()
__plugin_des__ = "执行一段sql语句"
-__plugin_cmd__ = [
- "exec [sql语句]",
-]
+__plugin_cmd__ = ["exec [sql语句]", "查看所有表"]
__plugin_version__ = 0.2
__plugin_author__ = "HibiKier"
@@ -32,55 +32,61 @@ tables = on_command("查看所有表", rule=to_me(), permission=SUPERUSER, prior
@exec_.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
sql = arg.extract_plain_text().strip()
- async with db.transaction():
+ if not sql:
+ await exec_.finish("未接受到sql语句")
+ db = Tortoise.get_connection("default")
+ # try:
+ # 判断是否为SELECT语句
+ if sql.lower().startswith("select"):
+ pass
+ # # 分割语句
try:
- # 判断是否为SELECT语句
- if sql.lower().startswith("select"):
- # 分割语句
- try:
- page = int(sql.split(" ")[-1]) - 1
- sql_list = sql.split(" ")[:-1]
- except ValueError:
- page = 0
- sql_list = sql.split(" ")
- # 拼接语句
- sql = " ".join(sql_list)
- query = db.text(sql)
- res = await db.all(query)
- msg_list = [f"第{page+1}页查询结果:"]
- # logger.info(res)
- # 获取所有字段
- keys = res[0].keys()
- # 每页10条
- for i in res[page * 10 : (page + 1) * 10]:
- msg = ""
- for key in keys:
- msg += f"{key}: {i[key]}\n"
- msg += f"第{page+1}页第{res.index(i)+1}条"
- msg_list.append(msg)
- # 检查是私聊还是群聊
- try:
- forward_msg_list = custom_forward_msg(msg_list, bot.self_id)
- await bot.send_group_forward_msg(group_id=event.group_id, messages=forward_msg_list)
- except:
- for msg in msg_list:
- await exec_.send(msg)
- await asyncio.sleep(0.2)
- return
- query = db.text(sql)
- await db.first(query)
- await exec_.send("执行 sql 语句成功.")
- except Exception as e:
- await exec_.send(f"执行 sql 语句失败 {type(e)}:{e}")
- logger.error(f"执行 sql 语句失败 {type(e)}:{e}")
+ page = int(sql.split(" ")[-1]) - 1
+ sql_list = sql.split(" ")[:-1]
+ except ValueError:
+ page = 0
+ sql_list = sql.split(" ")
+ # 拼接语句
+ sql = " ".join(sql_list)
+ res = await db.execute_query_dict(sql)
+ msg_list = [f"第{page+1}页查询结果:"]
+ # logger.info(res)
+ # 获取所有字段
+ keys = res[0].keys()
+ # 每页10条
+ for i in res[page * 10 : (page + 1) * 10]:
+ msg = ""
+ for key in keys:
+ msg += f"{key}: {i[key]}\n"
+ msg += f"第{page+1}页第{res.index(i)+1}条"
+ msg_list.append(msg)
+ # 检查是私聊还是群聊
+ if isinstance(event, GroupMessageEvent):
+ forward_msg_list = custom_forward_msg(msg_list, bot.self_id)
+ await bot.send_group_forward_msg(
+ group_id=event.group_id, messages=forward_msg_list
+ )
+ else:
+ for msg in msg_list:
+ await exec_.send(msg)
+ await asyncio.sleep(0.2)
+ return
+ else:
+ await TestSQL.raw(sql)
+ await exec_.send("执行 sql 语句成功.")
+ # except Exception as e:
+ # await exec_.send(f"执行 sql 语句失败 {type(e)}:{e}")
+ # logger.error(f"执行 sql 语句失败 {type(e)}:{e}")
@tables.handle()
async def _(bot: Bot, event: MessageEvent):
# 获取所有表
- query = db.text("select tablename from pg_tables where schemaname = 'public'")
- res = await db.all(query)
+ db = Tortoise.get_connection("default")
+ query = await db.execute_query_dict(
+ "select tablename from pg_tables where schemaname = 'public'"
+ )
msg = "数据库中的所有表名:\n"
- for tablename in res:
+ for tablename in query:
msg += str(tablename["tablename"]) + "\n"
await tables.finish(msg)
diff --git a/basic_plugins/super_cmd/manager_group.py b/basic_plugins/super_cmd/manager_group.py
index f74a32fd..b1add260 100755
--- a/basic_plugins/super_cmd/manager_group.py
+++ b/basic_plugins/super_cmd/manager_group.py
@@ -1,35 +1,39 @@
-from nonebot.adapters.onebot.v11 import (
- Bot,
- MessageEvent,
- GROUP,
- GroupMessageEvent,
- Message,
- ActionFailed,
-)
-from nonebot import on_command, on_regex
-from nonebot.permission import SUPERUSER
-from nonebot.typing import T_State
-from nonebot.rule import to_me
-from utils.utils import is_number
-from utils.manager import group_manager, plugins2settings_manager
-from models.group_info import GroupInfo
-from services.log import logger
-from configs.config import NICKNAME
-from nonebot.params import Command, CommandArg
from typing import Tuple
+from nonebot import on_command, on_regex
+from nonebot.adapters.onebot.v11 import (
+ GROUP,
+ Bot,
+ GroupMessageEvent,
+ Message,
+ MessageEvent,
+)
+from nonebot.params import Command, CommandArg
+from nonebot.permission import SUPERUSER
+from nonebot.rule import to_me
+
+from configs.config import NICKNAME
+from models.group_info import GroupInfo
+from services.log import logger
+from utils.depends import OneCommand
+from utils.image_utils import text2image
+from utils.manager import group_manager, plugins2settings_manager
+from utils.message_builder import image
+from utils.utils import is_number
__zx_plugin_name__ = "管理群操作 [Superuser]"
__plugin_usage__ = """
usage:
群权限 | 群白名单 | 退出群 操作
- 指令:
- 退群 [group_id]
+ 退群,添加/删除群白名单,添加/删除群认证,当在群聊中这五个命令且没有指定群号时,默认指定当前群聊
+ 指令:
+ 退群 ?[group_id]
修改群权限 [group_id] [等级]
- 添加群白名单 *[group_id]
- 删除群白名单 *[group_id]
- 添加群认证 *[group_id]
- 删除群认证 *[group_id]
+ 修改群权限 [等级]: 该命令仅在群聊时生效,默认修改当前群聊
+ 添加群白名单 ?*[group_id]
+ 删除群白名单 ?*[group_id]
+ 添加群认证 ?*[group_id]
+ 删除群认证 ?*[group_id]
查看群白名单
""".strip()
__plugin_des__ = "管理群操作"
@@ -53,7 +57,7 @@ my_group_level = on_command(
"查看群权限", aliases={"群权限"}, priority=5, permission=GROUP, block=True
)
what_up_group_level = on_regex(
- ".*?(提高|提升|升高|增加|加上)(.*?)群权限.*?",
+ "(:?提高|提升|升高|增加|加上).*?群权限",
rule=to_me(),
priority=5,
permission=GROUP,
@@ -73,47 +77,57 @@ group_auth = on_command(
@del_group.handle()
-async def _(bot: Bot, arg: Message = CommandArg()):
+async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
group_id = arg.extract_plain_text().strip()
+ if not group_id and isinstance(event, GroupMessageEvent):
+ group_id = event.group_id
if group_id:
if is_number(group_id):
+ group_list = [x["group_id"] for x in await bot.get_group_list()]
+ group_id = int(group_id)
+ if group_id not in group_list:
+ logger.debug("群聊不存在", "退群", event.user_id, target=group_id)
+ await del_group.finish(f"{NICKNAME}未在该群聊中...")
try:
- await bot.set_group_leave(group_id=int(group_id))
- logger.info(f"退出群聊 {group_id} 成功")
+ await bot.set_group_leave(group_id=group_id)
+ logger.info(f"{NICKNAME}退出群聊成功", "退群", event.user_id, target=group_id)
await del_group.send(f"退出群聊 {group_id} 成功", at_sender=True)
- group_manager.delete_group(int(group_id))
- await GroupInfo.delete_group_info(int(group_id))
+ group_manager.delete_group(group_id)
+ await GroupInfo.filter(group_id=group_id).delete()
except Exception as e:
- logger.info(f"退出群聊 {group_id} 失败 e:{e}")
+ logger.error(f"退出群聊失败", "退群", event.user_id, target=group_id, e=e)
+ await del_group.send(f"退出群聊 {group_id} 失败", at_sender=True)
else:
- await del_group.finish(f"请输入正确的群号", at_sender=True)
+ await del_group.send(f"请输入正确的群号", at_sender=True)
else:
- await del_group.finish(f"请输入群号", at_sender=True)
+ await del_group.send(f"请输入群号", at_sender=True)
@add_group_level.handle()
async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
+ msg = msg.split()
group_id = 0
level = 0
+ if isinstance(event, GroupMessageEvent) and len(msg) == 1:
+ msg = [event.group_id, msg[0]]
if not msg:
- await add_group_level.finish("用法:修改群权限 [group] [level]")
- msg = msg.split()
+ await add_group_level.finish("缺失参数...")
if len(msg) < 2:
- await add_group_level.finish("参数不完全..[group] [level]")
+ await add_group_level.finish("缺失参数...")
if is_number(msg[0]) and is_number(msg[1]):
- group_id = msg[0]
+ group_id = int(msg[0])
level = int(msg[1])
else:
- await add_group_level.finish("参数错误...group和level必须是数字..")
+ await add_group_level.finish("参数错误...群号和等级必须是数字..")
old_level = group_manager.get_group_level(group_id)
group_manager.set_group_level(group_id, level)
await add_group_level.send("修改成功...", at_sender=True)
if level > -1:
await bot.send_group_msg(
- group_id=int(group_id), message=f"管理员修改了此群权限:{old_level} -> {level}"
+ group_id=group_id, message=f"管理员修改了此群权限:{old_level} -> {level}"
)
- logger.info(f"{event.user_id} 修改了 {group_id} 的权限:{level}")
+ logger.info(f"修改群权限:{level}", "修改群权限", event.user_id, target=group_id)
@my_group_level.handle()
@@ -127,78 +141,104 @@ async def _(event: GroupMessageEvent):
if plugin_name == "pixiv":
plugin_name = "搜图 p站排行"
tmp += f"{plugin_name}\n"
- if tmp:
- tmp = "\n目前无法使用的功能:\n" + tmp
- await my_group_level.finish(f"当前群权限:{level}{tmp}")
+ if not tmp:
+ await my_group_level.finish(f"当前群权限:{level}")
+ await my_group_level.finish(
+ f"当前群权限:{level}\n目前无法使用的功能:\n"
+ + image(await text2image(tmp, padding=10, color="#f9f6f2"))
+ )
@what_up_group_level.handle()
async def _():
await what_up_group_level.finish(
- f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.管理员修改权限"
+ f"[此功能用于防止内鬼,如果引起不便那真是抱歉了]\n" f"目前提高群权限的方法:\n" f"\t1.超级管理员修改权限"
)
@manager_group_whitelist.handle()
-async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
+async def _(
+ bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
+):
msg = arg.extract_plain_text().strip().split()
+ if not msg and isinstance(event, GroupMessageEvent):
+ msg = [event.group_id]
+ if not msg:
+ await manager_group_whitelist.finish("请输入群号")
all_group = [g["group_id"] for g in await bot.get_group_list()]
+ error_group = []
group_list = []
- for group in msg:
- if is_number(group) and int(group) in all_group:
- group_list.append(int(group))
+ for group_id in msg:
+ if is_number(group_id) and int(group_id) in all_group:
+ group_list.append(int(group_id))
+ else:
+ logger.debug(f"群号不合法或不存在", cmd, target=group_id)
+ error_group.append(group_id)
if group_list:
- for group in group_list:
+ for group_id in group_list:
if cmd in ["添加群白名单"]:
- group_manager.add_group_white_list(group)
+ group_manager.add_group_white_list(group_id)
else:
- group_manager.delete_group_white_list(group)
+ group_manager.delete_group_white_list(group_id)
group_list = [str(x) for x in group_list]
await manager_group_whitelist.send("已成功将 " + "\n".join(group_list) + " " + cmd)
- else:
- await manager_group_whitelist.send(f"添加失败,请检查{NICKNAME}是否已加入这些群聊或重复添加/删除群白单名")
+ group_manager.save()
+ if error_group:
+ await manager_group_whitelist.send("以下群聊不合法或不存在:\n" + "\n".join(error_group))
@show_group_whitelist.handle()
async def _():
- x = group_manager.get_group_white_list()
- x = [str(g) for g in x]
- if x:
- await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(x))
- else:
- await show_group_whitelist.send("没有任何群在群白名单...")
+ group = [str(g) for g in group_manager.get_group_white_list()]
+ if not group:
+ await show_group_whitelist.finish("没有任何群在群白名单...")
+ await show_group_whitelist.send("目前的群白名单:\n" + "\n".join(group))
@group_auth.handle()
-async def _(bot: Bot, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
+async def _(
+ bot: Bot, event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()
+):
msg = arg.extract_plain_text().strip().split()
+ if isinstance(event, GroupMessageEvent) and not msg:
+ msg = [event.group_id]
+ if not msg:
+ await manager_group_whitelist.finish("请输入群号")
+ error_group = []
+ all_group = [g["group_id"] for g in await bot.get_group_list()]
for group_id in msg:
- if not is_number(group_id):
- await group_auth.send(f"{group_id}非纯数字,已跳过该项..")
group_id = int(group_id)
- if cmd[:2] == "添加":
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 1)
- else:
+ if is_number(group_id) and group_id in all_group:
+ if cmd[:2] == "添加":
try:
group_info = await bot.get_group_info(group_id=group_id)
- except ActionFailed:
- group_info = {
- "group_id": group_id,
- "group_name": "_",
- "max_member_count": -1,
- "member_count": -1,
- }
- await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
- )
+ await GroupInfo.update_or_create(
+ group_id=group_info["group_id"],
+ defaults={
+ "group_flag": 1,
+ "group_name": group_info["group_name"],
+ "max_member_count": group_info["max_member_count"],
+ "member_count": group_info["member_count"],
+ },
+ )
+ except Exception as e:
+ await group_auth.send(f"添加群认证 {group_id} 发生错误!")
+ logger.error(f"添加群认证发生错误", cmd, target=group_id, e=e)
+ else:
+ await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
+ logger.info(f"添加群认证成功", cmd, target=group_id)
+ else:
+ if group := await GroupInfo.filter(group_id=group_id).first():
+ await group.update_or_create(
+ group_id=group_id, defaults={"group_flag": 0}
+ )
+ await group_auth.send(f"已删除 {group_id} 群认证..")
+ logger.info(f"删除群认证成功", cmd, target=group_id)
+ else:
+ await group_auth.send(f"未查找到群聊: {group_id}")
+ logger.info(f"未找到群聊", cmd, target=group_id)
else:
- if await GroupInfo.get_group_info(group_id):
- await GroupInfo.set_group_flag(group_id, 0)
- await group_auth.send(f"已为 {group_id} {cmd[:2]}群认证..")
+ logger.debug(f"群号不合法或不存在", cmd, target=group_id)
+ error_group.append(str(group_id))
+ if error_group:
+ await manager_group_whitelist.send("以下群聊不合法或不存在:\n" + "\n".join(error_group))
diff --git a/basic_plugins/super_cmd/reload_setting.py b/basic_plugins/super_cmd/reload_setting.py
index acbd616e..7ff020c6 100755
--- a/basic_plugins/super_cmd/reload_setting.py
+++ b/basic_plugins/super_cmd/reload_setting.py
@@ -1,21 +1,21 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
-from utils.manager import (
- plugins2cd_manager,
- plugins2settings_manager,
- plugins2block_manager,
- group_manager,
-)
+
from configs.config import Config
from services.log import logger
+from utils.manager import (
+ group_manager,
+ plugins2block_manager,
+ plugins2cd_manager,
+ plugins2settings_manager,
+)
from utils.utils import scheduler
-
-__zx_plugin_name__ = "重载插件配置 [Superuser]"
+__zx_plugin_name__ = "重载配置 [Superuser]"
__plugin_usage__ = """
usage:
- 重载插件配置
+ 重载配置
plugins2settings,
plugins2cd
plugins2block
@@ -23,23 +23,15 @@ usage:
指令:
重载插件配置
""".strip()
-__plugin_des__ = "重载插件配置"
+__plugin_des__ = "重载配置"
__plugin_cmd__ = [
- "重载插件配置",
+ "重载配置",
]
-__plugin_version__ = 0.1
+__plugin_version__ = 0.2
__plugin_author__ = "HibiKier"
__plugin_configs__ = {
- "AUTO_RELOAD": {
- "value": False,
- "help": "自动重载配置文件",
- "default_value": False
- },
- "AUTO_RELOAD_TIME": {
- "value": 180,
- "help": "控制自动重载配置文件时长",
- "default_value": 180
- }
+ "AUTO_RELOAD": {"value": False, "help": "自动重载配置文件", "default_value": False},
+ "AUTO_RELOAD_TIME": {"value": 180, "help": "控制自动重载配置文件时长", "default_value": 180},
}
@@ -59,7 +51,7 @@ async def _():
@scheduler.scheduled_job(
- 'interval',
+ "interval",
seconds=Config.get_config("reload_setting", "AUTO_RELOAD_TIME", 180),
)
async def _():
diff --git a/basic_plugins/super_cmd/set_admin_permissions.py b/basic_plugins/super_cmd/set_admin_permissions.py
index c64028d0..03835f76 100755
--- a/basic_plugins/super_cmd/set_admin_permissions.py
+++ b/basic_plugins/super_cmd/set_admin_permissions.py
@@ -1,12 +1,16 @@
+from typing import List, Tuple
+
from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.exception import ActionFailed
+from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
+
from models.level_user import LevelUser
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
-from utils.utils import get_message_at, is_number
from services.log import logger
+from utils.depends import AtList, OneCommand
from utils.message_builder import at
-from nonebot.params import Command, CommandArg
-from typing import Tuple
+from utils.utils import is_number
__zx_plugin_name__ = "用户权限管理 [Superuser]"
__plugin_usage__ = """
@@ -16,12 +20,14 @@ usage:
添加权限 [at] [权限]
添加权限 [qq] [group_id] [权限]
删除权限 [at]
+ 删除权限 [qq] [group_id]
""".strip()
__plugin_des__ = "增删改用户的权限"
__plugin_cmd__ = [
"添加权限 [at] [权限]",
"添加权限 [qq] [group_id] [权限]",
"删除权限 [at]",
+ "删除权限 [qq] [group_id]",
]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
@@ -40,21 +46,22 @@ super_cmd = on_command(
async def _(
bot: Bot,
event: MessageEvent,
- cmd: Tuple[str, ...] = Command(),
+ cmd: str = OneCommand(),
arg: Message = CommandArg(),
+ at_list: List[int] = AtList(),
):
group_id = event.group_id if isinstance(event, GroupMessageEvent) else -1
level = None
args = arg.extract_plain_text().strip().split()
- qq = get_message_at(event.json())
flag = 2
+ qq = None
try:
- if qq:
- qq = qq[0]
- if cmd[0][:2] == "添加" and args and is_number(args[0]):
+ if at_list:
+ qq = at_list[0]
+ if cmd[:2] == "添加" and args and is_number(args[0]):
level = int(args[0])
else:
- if cmd[0][:2] == "添加":
+ if cmd[:2] == "添加":
if (
len(args) > 2
and is_number(args[0])
@@ -69,33 +76,39 @@ async def _(
qq = int(args[0])
group_id = int(args[1])
flag = 1
- level = -1 if cmd[0][:2] == "删除" else level
+ level = -1 if cmd[:2] == "删除" else level
if group_id == -1 or not level or not qq:
raise IndexError()
except IndexError:
await super_cmd.finish(__plugin_usage__)
+ if not qq:
+ await super_cmd.finish("未指定对象...")
try:
- if cmd[0][:2] == "添加":
- if await LevelUser.set_level(qq, group_id, level, 1):
- result = f"添加管理成功, 权限: {level}"
- else:
- result = f"管理已存在, 更新权限: {level}"
+ if cmd[:2] == "添加":
+ await LevelUser.set_level(qq, group_id, level, 1)
+ result = f"设置权限成功, 权限: {level}"
else:
- if await LevelUser.delete_level(qq, event.group_id):
+ if await LevelUser.delete_level(qq, group_id):
result = "删除管理成功!"
else:
result = "该账号无管理权限!"
if flag == 2:
await super_cmd.send(result)
elif flag == 1:
- await bot.send_group_msg(
- group_id=group_id,
- message=Message(
- f"{at(qq)}管理员修改了你的权限"
- f"\n--------\n你当前的权限等级:{level if level != -1 else 0}"
- ),
- )
+ try:
+ await bot.send_group_msg(
+ group_id=group_id,
+ message=Message(
+ f"{at(qq)}管理员修改了你的权限"
+ f"\n--------\n你当前的权限等级:{level if level != -1 else 0}"
+ ),
+ )
+ except ActionFailed:
+ pass
await super_cmd.send("修改成功")
+ logger.info(
+ f"修改权限: {level if level != -1 else 0}", cmd, event.user_id, group_id, qq
+ )
except Exception as e:
await super_cmd.send("执行指令失败!")
- logger.error(f"执行指令失败 e:{e}")
+ logger.error(f"执行指令失败", cmd, event.user_id, group_id, qq, e=e)
diff --git a/basic_plugins/super_cmd/super_task_switch.py b/basic_plugins/super_cmd/super_task_switch.py
deleted file mode 100755
index ba1df382..00000000
--- a/basic_plugins/super_cmd/super_task_switch.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from nonebot import on_command
-from nonebot.permission import SUPERUSER
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
-from nonebot.rule import to_me
-from utils.utils import is_number
-from services.log import logger
-from utils.manager import group_manager
-from nonebot.params import Command, CommandArg
-from typing import Tuple
-
-
-__zx_plugin_name__ = "超级用户被动开关 [Superuser]"
-__plugin_usage__ = """
-usage:
- 超级用户被动开关
- 指令:
- 开启/关闭广播通知
-""".strip()
-__plugin_des__ = "超级用户被动开关"
-__plugin_cmd__ = [
- "开启/关闭广播通知",
-]
-__plugin_version__ = 0.1
-__plugin_author__ = "HibiKier"
-
-
-oc_gb = on_command(
- "开启广播通知",
- aliases={"关闭广播通知"},
- rule=to_me(),
- permission=SUPERUSER,
- priority=1,
- block=True,
-)
-
-
-@oc_gb.handle()
-async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
- group = arg.extract_plain_text().strip()
- if group:
- if is_number(group):
- group = int(group)
- for g in await bot.get_group_list():
- if g["group_id"] == group:
- break
- else:
- await oc_gb.finish("没有加入这个群...", at_sender=True)
- if cmd == "开启广播通知":
- logger.info(f"USER {event.user_id} 开启了 GROUP {group} 的广播")
- await oc_gb.finish(await group_manager.open_group_task(group, "broadcast",), at_sender=True)
- else:
- logger.info(f"USER {event.user_id} 关闭了 GROUP {group} 的广播")
- await oc_gb.finish(await group_manager.close_group_task(group, "broadcast"), at_sender=True)
- else:
- await oc_gb.finish("请输入正确的群号", at_sender=True)
- else:
- await oc_gb.finish("请输入要关闭广播的群号", at_sender=True)
\ No newline at end of file
diff --git a/basic_plugins/super_cmd/update_friend_group_info.py b/basic_plugins/super_cmd/update_friend_group_info.py
index 8f528c78..f56c4ae6 100755
--- a/basic_plugins/super_cmd/update_friend_group_info.py
+++ b/basic_plugins/super_cmd/update_friend_group_info.py
@@ -1,11 +1,11 @@
from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
-from utils.utils import get_bot
-from services.log import logger
-from models.group_info import GroupInfo
-from models.friend_user import FriendUser
+from models.friend_user import FriendUser
+from models.group_info import GroupInfo
+from services.log import logger
__zx_plugin_name__ = "更新群/好友信息 [Superuser]"
__plugin_usage__ = """
@@ -32,39 +32,46 @@ update_friend_info = on_command(
@update_group_info.handle()
-async def _():
- bot = get_bot()
+async def _(bot: Bot, event: MessageEvent):
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
num = 0
- rst = ""
for g in gl:
- group_info = await bot.get_group_info(group_id=g)
- if await GroupInfo.add_group_info(
- group_info["group_id"],
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1
- ):
+ try:
+ group_info = await bot.get_group_info(group_id=g)
+ await GroupInfo.update_or_create(
+ group_id=group_info["group_id"],
+ defaults={
+ "group_name": group_info["group_name"],
+ "max_member_count": group_info["max_member_count"],
+ "member_count": group_info["member_count"],
+ },
+ )
num += 1
- logger.info(f"自动更新群组 {g} 信息成功")
- else:
- logger.info(f"自动更新群组 {g} 信息失败")
- rst += f"{g} 更新失败\n"
- await update_group_info.send(f"成功更新了 {num} 个群的信息\n{rst[:-1]}")
+ logger.debug(
+ "群聊信息更新成功", "更新群信息", event.user_id, target=group_info["group_id"]
+ )
+ except Exception as e:
+ logger.error(f"更新群聊信息失败", "更新群信息", event.user_id, target=g, e=e)
+ await update_group_info.send(f"成功更新了 {len(gl)} 个群的信息")
+ logger.info(f"更新群聊信息完成,共更新了 {len(gl)} 个群的信息", "更新群信息", event.user_id)
@update_friend_info.handle()
-async def _():
+async def _(bot: Bot, event: MessageEvent):
num = 0
- rst = ""
- fl = await get_bot().get_friend_list()
+ error_list = []
+ fl = await bot.get_friend_list()
for f in fl:
- if await FriendUser.add_friend_info(f["user_id"], f["nickname"]):
- logger.info(f'自动更新好友 {f["user_id"]} 信息成功')
+ try:
+ await FriendUser.update_or_create(
+ user_id=f["user_id"], defaults={"nickname": f["nickname"]}
+ )
+ logger.debug(f"更新好友信息成功", "更新好友信息", event.user_id, target=f["user_id"])
num += 1
- else:
- logger.warning(f'自动更新好友 {f["user_id"]} 信息失败')
- rst += f'{f["user_id"]} 更新失败\n'
- await update_friend_info.send(f"成功更新了 {num} 个好友的信息\n{rst[:-1]}")
+ except Exception as e:
+ logger.error(f"更新好友信息失败", "更新好友信息", event.user_id, target=f["user_id"], e=e)
+ await update_friend_info.send(f"成功更新了 {num} 个好友的信息")
+ if error_list:
+ await update_friend_info.send(f"以下好友更新失败:\n" + "\n".join(error_list))
+ logger.info(f"更新好友信息完成,共更新了 {num} 个群的信息", "更新好友信息", event.user_id)
diff --git a/basic_plugins/super_help/__init__.py b/basic_plugins/super_help/__init__.py
index b6c29cee..574b3d1b 100755
--- a/basic_plugins/super_help/__init__.py
+++ b/basic_plugins/super_help/__init__.py
@@ -1,11 +1,12 @@
from nonebot import on_command
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
+
from utils.message_builder import image
-from .data_source import create_help_image, SUPERUSER_HELP_IMAGE
+from .data_source import SUPERUSER_HELP_IMAGE, create_help_image
-__zx_plugin_name__ = '超级用户帮助 [Superuser]'
+__zx_plugin_name__ = "超级用户帮助 [Superuser]"
if SUPERUSER_HELP_IMAGE.exists():
@@ -20,5 +21,4 @@ super_help = on_command(
async def _():
if not SUPERUSER_HELP_IMAGE.exists():
await create_help_image()
- x = image(SUPERUSER_HELP_IMAGE)
- await super_help.finish(x)
+ await super_help.finish(image(SUPERUSER_HELP_IMAGE))
diff --git a/basic_plugins/update_info.py b/basic_plugins/update_info.py
index 7c19d86c..074d72a9 100755
--- a/basic_plugins/update_info.py
+++ b/basic_plugins/update_info.py
@@ -1,6 +1,6 @@
from nonebot import on_command
-from utils.message_builder import image
+from utils.message_builder import image
__zx_plugin_name__ = "更新信息"
__plugin_usage__ = """
@@ -26,8 +26,7 @@ update_info = on_command("更新信息", aliases={"更新日志"}, priority=5, b
@update_info.handle()
async def _():
- img = image("update_info.png")
- if img:
+ if img := image("update_info.png"):
await update_info.finish(image("update_info.png"))
else:
await update_info.finish("目前没有更新信息哦")
diff --git a/configs/config.py b/configs/config.py
index 6528e3a8..9aff1fcb 100644
--- a/configs/config.py
+++ b/configs/config.py
@@ -1,11 +1,18 @@
-from typing import Optional
+import platform
from pathlib import Path
+from typing import Optional
+
from .utils import ConfigsManager
-import platform
if platform.system() == "Linux":
import os
- hostip = os.popen("cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'").read().replace("\n","")
+
+ hostip = (
+ os.popen("cat /etc/resolv.conf | grep nameserver | awk '{ print $2 }'")
+ .read()
+ .replace("\n", "")
+ )
+
# 回复消息名称
NICKNAME: str = "小真寻"
@@ -14,7 +21,7 @@ NICKNAME: str = "小真寻"
# 如果填写了bind就不需要再填写后面的字段了#)
# 示例:"bind": "postgresql://user:password@127.0.0.1:5432/database"
bind: str = "" # 数据库连接链接
-sql_name: str = "postgresql"
+sql_name: str = "postgres"
user: str = "" # 数据用户名
password: str = "" # 数据库密码
address: str = "" # 数据库地址
diff --git a/configs/utils/__init__.py b/configs/utils/__init__.py
index 10de0138..79641dd7 100644
--- a/configs/utils/__init__.py
+++ b/configs/utils/__init__.py
@@ -1,8 +1,9 @@
import copy
-from typing import Optional, Any, Union
from pathlib import Path
-from ruamel.yaml import YAML
+from typing import Any, Optional, Union
+
from ruamel import yaml
+from ruamel.yaml import YAML
from ruamel.yaml.scanner import ScannerError
@@ -50,7 +51,7 @@ class ConfigsManager:
*,
name: Optional[str] = None,
help_: Optional[str] = None,
- default_value: Optional[str] = None,
+ default_value: Optional[Any] = None,
_override: bool = False,
):
"""
diff --git a/models/bag_user.py b/models/bag_user.py
index 0027d0d6..9bbce1c0 100755
--- a/models/bag_user.py
+++ b/models/bag_user.py
@@ -1,24 +1,37 @@
-from services.db_context import db
from typing import Dict
-from typing import Optional, List
-from services.log import logger
+
+from tortoise import fields
+
+from services.db_context import Model
+
from .goods_info import GoodsInfo
-class BagUser(db.Model):
- __tablename__ = "bag_users"
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- gold = db.Column(db.Integer(), default=100)
- props = db.Column(db.TEXT(), nullable=False, default="") # 旧道具字段(废弃)
- spend_total_gold = db.Column(db.Integer(), default=0)
- get_total_gold = db.Column(db.Integer(), default=0)
- get_today_gold = db.Column(db.Integer(), default=0)
- spend_today_gold = db.Column(db.Integer(), default=0)
- property = db.Column(db.JSON(), nullable=False, default={}) # 新道具字段
+class BagUser(Model):
- _idx1 = db.Index("bag_group_users_idx1", "user_qq", "group_id", unique=True)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ gold = fields.IntField(default=100)
+ """金币数量"""
+ spend_total_gold = fields.IntField(default=0)
+ """花费金币总数"""
+ get_total_gold = fields.IntField(default=0)
+ """获取金币总数"""
+ get_today_gold = fields.IntField(default=0)
+ """今日获取金币"""
+ spend_today_gold = fields.IntField(default=0)
+ """今日获取金币"""
+ property: Dict[str, int] = fields.JSONField(default={})
+ """道具"""
+
+ class Meta:
+ table = "bag_users"
+ table_description = "用户道具数据表"
+ unique_together = ("user_qq", "group_id")
@classmethod
async def get_user_total_gold(cls, user_qq: int, group_id: int) -> str:
@@ -29,13 +42,7 @@ class BagUser(db.Model):
:param user_qq: qq号
:param group_id: 所在群号
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.gino.first()
- if not user:
- user = await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
return (
f"当前金币:{user.gold}\n今日获取金币:{user.get_today_gold}\n今日花费金币:{user.spend_today_gold}"
f"\n今日收益:{user.get_today_gold - user.spend_today_gold}"
@@ -51,19 +58,13 @@ class BagUser(db.Model):
:param user_qq: qq号
:param group_id: 所在群号
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.gino.first()
- if user:
- return user.gold
- else:
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
- return 100
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ return user.gold
@classmethod
- async def get_property(cls, user_qq: int, group_id: int, only_active: bool = False) -> Dict[str, int]:
+ async def get_property(
+ cls, user_qq: int, group_id: int, only_active: bool = False
+ ) -> Dict[str, int]:
"""
说明:
获取当前道具
@@ -72,22 +73,18 @@ class BagUser(db.Model):
:param group_id: 所在群号
:param only_active: 仅仅获取主动使用的道具
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.gino.first()
- if user:
- if only_active and user.property:
- data = {}
- name_list = [x.goods_name for x in await GoodsInfo.get_all_goods() if not x.is_passive]
- for key in [x for x in user.property.keys() if x in name_list]:
- data[key] = user.property[key]
- return data
- return user.property
- else:
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
- return {}
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ if only_active and user.property:
+ data = {}
+ name_list = [
+ x.goods_name
+ for x in await GoodsInfo.get_all_goods()
+ if not x.is_passive
+ ]
+ for key in [x for x in user.property if x in name_list]:
+ data[key] = user.property[key]
+ return data
+ return user.property
@classmethod
async def add_gold(cls, user_qq: int, group_id: int, num: int):
@@ -99,23 +96,11 @@ class BagUser(db.Model):
:param group_id: 所在群号
:param num: 金币数量
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(
- gold=user.gold + num,
- get_total_gold=user.get_total_gold + num,
- get_today_gold=user.get_today_gold + num,
- ).apply()
- else:
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- gold=100 + num,
- get_total_gold=num,
- get_today_gold=num,
- )
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ user.gold = user.gold + num
+ user.get_total_gold = user.get_total_gold + num
+ user.get_today_gold = user.get_today_gold + num
+ await user.save(update_fields=["gold", "get_today_gold", "get_total_gold"])
@classmethod
async def spend_gold(cls, user_qq: int, group_id: int, num: int):
@@ -127,26 +112,14 @@ class BagUser(db.Model):
:param group_id: 所在群号
:param num: 金币数量
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(
- gold=user.gold - num,
- spend_total_gold=user.spend_total_gold + num,
- spend_today_gold=user.spend_today_gold + num,
- ).apply()
- else:
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- gold=100 - num,
- spend_total_gold=num,
- spend_today_gold=num,
- )
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ user.gold = user.gold - num
+ user.spend_total_gold = user.spend_total_gold + num
+ user.spend_today_gold = user.spend_today_gold + num
+ await user.save(update_fields=["gold", "spend_total_gold", "spend_today_gold"])
@classmethod
- async def add_property(cls, user_qq: int, group_id: int, name: str):
+ async def add_property(cls, user_qq: int, group_id: int, name: str, num: int = 1):
"""
说明:
增加道具
@@ -154,19 +127,15 @@ class BagUser(db.Model):
:param user_qq: qq号
:param group_id: 所在群号
:param name: 道具名称
+ :param num: 道具数量
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- if user:
- p = user.property
- if p.get(name) is None:
- p[name] = 1
- else:
- p[name] += 1
- await user.update(property=p).apply()
- else:
- await cls.create(user_qq=user_qq, group_id=group_id, property={name: 1})
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ property_ = user.property
+ if property_.get(name) is None:
+ property_[name] = 0
+ property_[name] += num
+ user.property = property_
+ await user.save(update_fields=["property"])
@classmethod
async def delete_property(
@@ -181,54 +150,15 @@ class BagUser(db.Model):
:param name: 道具名称
:param num: 使用个数
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- if user:
- property_ = user.property
- if name in property_:
- if property_.get(name) == num:
- del property_[name]
- else:
- property_[name] -= num
- await user.update(property=property_).apply()
- return True
- return False
-
- @classmethod
- async def buy_property(
- cls, user_qq: int, group_id: int, goods: "GoodsInfo", goods_num: int
- ) -> bool:
- """
- 说明:
- 购买道具
- 参数:
- :param user_qq: 用户qq
- :param group_id: 所在群聊
- :param goods: 商品
- :param goods_num: 商品数量
- """
- try:
- # 折扣后金币
- spend_gold = goods.goods_discount * goods.goods_price * goods_num
- await BagUser.spend_gold(user_qq, group_id, spend_gold)
- for _ in range(goods_num):
- await BagUser.add_property(user_qq, group_id, goods.goods_name)
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ property_ = user.property
+ if name in property_:
+ if (n := property_.get(name, 0)) < num:
+ return False
+ if n == num:
+ del property_[name]
+ else:
+ property_[name] -= num
+ await user.save(update_fields=["property"])
return True
- except Exception as e:
- logger.error(f"buy_property 发生错误 {type(e)}:{e}")
return False
-
- @classmethod
- async def get_all_users(cls, group_id: Optional[int] = None) -> List["BagUser"]:
- """
- 说明:
- 获取所有用户数据
- 参数:
- :param group_id: 群号
- """
- if not group_id:
- query = await cls.query.gino.all()
- else:
- query = await cls.query.where((cls.group_id == group_id)).gino.all()
- return query
diff --git a/models/ban_user.py b/models/ban_user.py
index 6ed406d4..e092e26a 100755
--- a/models/ban_user.py
+++ b/models/ban_user.py
@@ -1,16 +1,26 @@
-from services.db_context import db
import time
+from typing import Union
+
+from tortoise import fields
+
+from services.db_context import Model
+from services.log import logger
-class BanUser(db.Model):
- __tablename__ = "ban_users"
+class BanUser(Model):
- user_qq = db.Column(db.BigInteger(), nullable=False, primary_key=True)
- ban_level = db.Column(db.Integer(), nullable=False)
- ban_time = db.Column(db.BigInteger())
- duration = db.Column(db.BigInteger())
+ user_qq = fields.IntField(pk=True)
+ """用户id"""
+ ban_level = fields.IntField()
+ """使用ban命令的用户等级"""
+ ban_time = fields.BigIntField()
+ """ban开始的时间"""
+ duration = fields.BigIntField()
+ """ban时长"""
- _idx1 = db.Index("ban_group_users_idx1", "user_qq", unique=True)
+ class Meta:
+ table = "ban_users"
+ table_description = ".ban/b了 封禁人员数据表"
@classmethod
async def check_ban_level(cls, user_qq: int, level: int) -> bool:
@@ -21,30 +31,34 @@ class BanUser(db.Model):
:param user_qq: unban用户的qq号
:param level: ban掉目标用户的权限等级
"""
- user = await cls.query.where((cls.user_qq == user_qq)).gino.first()
- if not user:
- return False
- if user.ban_level > level:
- return True
+ user = await cls.filter(user_qq=user_qq).first()
+ if user:
+ logger.debug(
+ f"检测用户被ban等级,user_level: {user.ban_level},level: {level}",
+ target=user_qq,
+ )
+ return bool(user and user.ban_level > level)
return False
@classmethod
- async def check_ban_time(cls, user_qq: int) -> str:
+ async def check_ban_time(cls, user_qq: int) -> Union[str, int]:
"""
说明:
检测用户被ban时长
参数:
:param user_qq: qq号
"""
- query = cls.query.where((cls.user_qq == user_qq))
- user = await query.gino.first()
- if not user:
- return ""
- if time.time() - (user.ban_time + user.duration) > 0 and user.duration != -1:
- return ""
- if user.duration == -1:
- return "∞"
- return time.time() - user.ban_time - user.duration
+ logger.debug(f"获取用户ban时长", target=user_qq)
+ if user := await cls.filter(user_qq=user_qq).first():
+ if (
+ time.time() - (user.ban_time + user.duration) > 0
+ and user.duration != -1
+ ):
+ return ""
+ if user.duration == -1:
+ return "∞"
+ return int(time.time() - user.ban_time - user.duration)
+ return ""
@classmethod
async def is_ban(cls, user_qq: int) -> bool:
@@ -54,28 +68,29 @@ class BanUser(db.Model):
参数:
:param user_qq: qq号
"""
+ logger.debug(f"检测是否被ban", target=user_qq)
if await cls.check_ban_time(user_qq):
return True
else:
await cls.unban(user_qq)
- return False
+ return False
@classmethod
async def is_super_ban(cls, user_qq: int) -> bool:
"""
说明:
- 判断用户是否被ban
+ 判断用户是否被超级用户ban / b了
参数:
:param user_qq: qq号
"""
- user = await cls.query.where((cls.user_qq == user_qq)).gino.first()
- if not user:
- return False
- if user.ban_level == 10:
- return True
+ logger.debug(f"检测是否被超级用户权限封禁", target=user_qq)
+ if user := await cls.filter(user_qq=user_qq).first():
+ if user.ban_level == 10:
+ return True
+ return False
@classmethod
- async def ban(cls, user_qq: int, ban_level: int, duration: int) -> bool:
+ async def ban(cls, user_qq: int, ban_level: int, duration: int):
"""
说明:
ban掉目标用户
@@ -84,22 +99,15 @@ class BanUser(db.Model):
:param ban_level: 使用ban命令用户的权限
:param duration: ban时长,秒
"""
- query = cls.query.where((cls.user_qq == user_qq))
- query = query.with_for_update()
- user = await query.gino.first()
- if not await cls.check_ban_time(user_qq):
+ logger.debug(f"封禁用户,等级:{ban_level},时长: {duration}", target=user_qq)
+ if await cls.filter(user_qq=user_qq).first():
await cls.unban(user_qq)
- user = None
- if user is None:
- await cls.create(
- user_qq=user_qq,
- ban_level=ban_level,
- ban_time=time.time(),
- duration=duration,
- )
- return True
- else:
- return False
+ await cls.create(
+ user_qq=user_qq,
+ ban_level=ban_level,
+ ban_time=time.time(),
+ duration=duration,
+ )
@classmethod
async def unban(cls, user_qq: int) -> bool:
@@ -109,11 +117,8 @@ class BanUser(db.Model):
参数:
:param user_qq: qq号
"""
- query = cls.query.where((cls.user_qq == user_qq))
- query = query.with_for_update()
- user = await query.gino.first()
- if user is None:
- return False
- else:
- await cls.delete.where((cls.user_qq == user_qq)).gino.status()
+ logger.debug("解除封禁", target=user_qq)
+ if user := await cls.filter(user_qq=user_qq).first():
+ await user.delete()
return True
+ return False
diff --git a/models/chat_history.py b/models/chat_history.py
index 9eb6cafc..9816fa5b 100644
--- a/models/chat_history.py
+++ b/models/chat_history.py
@@ -1,81 +1,30 @@
from datetime import datetime, timedelta
-from typing import List, Literal, Optional, Tuple, Union
+from typing import Any, List, Literal, Optional, Tuple, Union
-from services.db_context import db
+from tortoise import fields
+from tortoise.functions import Count
+
+from services.db_context import Model
-class ChatHistory(db.Model):
- __tablename__ = "chat_history"
+class ChatHistory(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger())
- text = db.Column(db.Text())
- plain_text = db.Column(db.Text())
- create_time = db.Column(db.DateTime(timezone=True), nullable=False)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ text = fields.TextField()
+ """文本内容"""
+ plain_text = fields.TextField()
+ """纯文本"""
+ create_time = fields.DatetimeField(auto_now_add=True)
+ """创建时间"""
- @classmethod
- async def add_chat_msg(cls, user_qq: int, group_id: Optional[int], text: str, plain_text: str):
- await cls.create(
- user_qq=user_qq, group_id=group_id, text=text, plain_text=plain_text, create_time=datetime.now()
- )
-
- @classmethod
- async def get_user_msg(
- cls,
- uid: int,
- msg_type: Optional[Literal["private", "group"]],
- days: Optional[int] = None,
- ) -> List["ChatHistory"]:
- """
- 说明:
- 获取用户消息
- 参数:
- :param uid: 用户qq
- :param msg_type: 消息类型,私聊或群聊
- :param days: 限制日期
- """
- return await cls._get_msg(uid, None, "user", msg_type, days).gino.all()
-
- @classmethod
- async def get_group_user_msg(
- cls,
- uid: int,
- gid: int,
- limit: int = 10,
- date_scope: Tuple[datetime, datetime] = None,
- ) -> List["ChatHistory"]:
- """
- 说明:
- 获取群聊指定用户聊天记录
- 参数:
- :param uid: qq
- :param gid: 群号
- :param limit: 获取数量
- :param date_scope: 日期范围,默认None为全搜索
- """
- return (
- await cls._get_msg(uid, gid, "group", days=date_scope)
- .limit(limit)
- .gino.all()
- )
-
- @classmethod
- async def get_group_user_msg_count(cls, uid: int, gid: int) -> Optional[int]:
- """
- 说明:
- 查询群聊指定用户的聊天记录数量
- 参数:
- :param uid: qq
- :param gid: 群号
- """
- if x := await db.first(
- db.text(
- f"SELECT COUNT(id) as sum FROM public.chat_history WHERE user_qq = {uid} AND group_id = {gid}"
- )
- ):
- return x[0]
- return None
+ class Meta:
+ table = "chat_history"
+ table_description = "聊天记录数据表"
@classmethod
async def get_group_msg_rank(
@@ -84,7 +33,7 @@ class ChatHistory(db.Model):
limit: int = 10,
order: str = "DESC",
date_scope: Optional[Tuple[datetime, datetime]] = None,
- ) -> Optional[Tuple[int, int]]:
+ ) -> List["ChatHistory"]:
"""
说明:
获取排行数据
@@ -94,89 +43,39 @@ class ChatHistory(db.Model):
:param order: 排序类型,desc,des
:param date_scope: 日期范围
"""
- sql = f"SELECT user_qq, COUNT(id) as sum FROM public.chat_history WHERE group_id = {gid} "
- if date_scope:
- sql += f"AND create_time BETWEEN '{date_scope[0]}' AND '{date_scope[1]}' "
- sql += f"GROUP BY user_qq ORDER BY sum {order if order and order.upper() != 'DES' else ''} LIMIT {limit}"
- return await db.all(db.text(sql))
+ return list(
+ await cls.filter(group_id=gid, create_time__range=date_scope)
+ .annotate(count=Count("user_qq"))
+ .order_by(order)
+ .group_by("user_qq")
+ .limit(limit)
+ .values_list("user_qq", "count")
+ )
@classmethod
- async def get_group_first_msg_datetime(cls, gid: int) -> Optional[datetime]:
+ async def get_group_first_msg_datetime(cls, group_id: int) -> Optional[datetime]:
"""
说明:
获取群第一条记录消息时间
参数:
- :param gid:
+ :param group_id: 群聊id
"""
if (
- msg := await cls.query.where(cls.group_id == gid)
- .order_by(cls.create_time)
- .gino.first()
+ message := await cls.filter(group_id=group_id)
+ .order_by("create_time")
+ .first()
):
- return msg.create_time
- return None
+ return message.create_time
@classmethod
- async def get_user_msg_count(
- cls,
- uid: int,
- msg_type: Optional[Literal["private", "group"]],
- days: Optional[int] = None,
- ) -> int:
- """
- 说明:
- 获取用户消息数量
- 参数:
- :param uid: 用户qq
- :param msg_type: 消息类型,私聊或群聊
- :param days: 限制日期
- """
- return (
- await cls._get_msg(uid, None, "user", msg_type, days, True).gino.first()
- )[0]
-
- @classmethod
- async def get_group_msg(
- cls,
- gid: int,
- days: Optional[int] = None,
- ) -> List["ChatHistory"]:
- """
- 说明:
- 获取群聊消息
- 参数:
- :param gid: 用户qq
- :param days: 限制日期
- """
- return await cls._get_msg(None, gid, "group", None, days).gino.all()
-
- @classmethod
- async def get_group_msg_count(
- cls,
- gid: int,
- days: Optional[int] = None,
- ) -> List["ChatHistory"]:
- """
- 说明:
- 获取群聊消息数量
- 参数:
- :param gid: 用户qq
- :param days: 限制日期
- """
- return (await cls._get_msg(None, gid, "group", None, days, True).gino.first())[
- 0
- ]
-
- @classmethod
- def _get_msg(
+ async def get_message(
cls,
uid: Optional[int],
gid: Optional[int],
type_: Literal["user", "group"],
msg_type: Optional[Literal["private", "group"]] = None,
days: Optional[Union[int, Tuple[datetime, datetime]]] = None,
- is_select_count: bool = False,
- ):
+ ) -> List["ChatHistory"]:
"""
说明:
获取消息查询query
@@ -187,28 +86,21 @@ class ChatHistory(db.Model):
:param msg_type: 消息类型,用户或群聊
:param days: 限制日期
"""
- if is_select_count:
- setattr(ChatHistory, "count", db.func.count(cls.id).label("count"))
- query = cls.select("count")
- else:
- query = cls.query
if type_ == "user":
- query = query.where(cls.user_qq == uid)
+ query = cls.filter(user_qq=uid)
if msg_type == "private":
- query = query.where(cls.group_id == None)
+ query = query.filter(group_id__isnull=True)
elif msg_type == "group":
- query = query.where(cls.group_id != None)
+ query = query.filter(group_id__not_isnull=True)
else:
- query = query.where(cls.group_id == gid)
+ query = cls.filter(group_id=gid)
if uid:
- query = query.where(cls.user_qq == uid)
+ query = query.filter(user_qq=uid)
if days:
if isinstance(days, int):
- query = query.where(
- cls.create_time >= datetime.now() - timedelta(days=days)
+ query = query.filter(
+ create_time__gte=datetime.now() - timedelta(days=days)
)
elif isinstance(days, tuple):
- query = query.where(cls.create_time >= days[0]).where(
- cls.create_time <= days[1]
- )
- return query
+ query = query.filter(create_at__range=days)
+ return await query.all()
diff --git a/models/friend_user.py b/models/friend_user.py
index 0881041c..3b41259a 100755
--- a/models/friend_user.py
+++ b/models/friend_user.py
@@ -1,16 +1,23 @@
-from services.db_context import db
+from tortoise import fields
+
from configs.config import Config
+from services.db_context import Model
-class FriendUser(db.Model):
- __tablename__ = "friend_users"
+class FriendUser(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_id = db.Column(db.BigInteger(), nullable=False)
- user_name = db.Column(db.Unicode(), nullable=False, default="")
- nickname = db.Column(db.Unicode())
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_id = fields.BigIntField(unique=True)
+ """用户id"""
+ user_name = fields.CharField(max_length=255, default="")
+ """用户名称"""
+ nickname = fields.CharField(max_length=255, null=True)
+ """私聊下自定义昵称"""
- _idx1 = db.Index("friend_users_idx1", "user_id", unique=True)
+ class Meta:
+ table = "friend_users"
+ table_description = "好友信息数据表"
@classmethod
async def get_user_name(cls, user_id: int) -> str:
@@ -20,77 +27,29 @@ class FriendUser(db.Model):
参数:
:param user_id: qq号
"""
- query = cls.query.where(cls.user_id == user_id)
- user = await query.gino.first()
- if user:
+ if user := await cls.get_or_none(user_id=user_id):
return user.user_name
- else:
- return ""
+ return ""
@classmethod
- async def add_friend_info(cls, user_id: int, user_name: str) -> bool:
- """
- 说明:
- 添加好友信息
- 参数:
- :param user_id: qq号
- :param user_name: 用户名称
- """
- try:
- query = cls.query.where(cls.user_id == user_id)
- user = await query.with_for_update().gino.first()
- if not user:
- await cls.create(
- user_id=user_id,
- user_name=user_name,
- )
- else:
- await user.update(
- user_name=user_name,
- ).apply()
- return True
- except Exception:
- return False
-
- @classmethod
- async def delete_friend_info(cls, user_id: int) -> bool:
- """
- 说明:
- 删除好友信息
- 参数:
- :param user_id: qq号
- """
- try:
- query = cls.query.where(cls.user_id == user_id)
- user = await query.with_for_update().gino.first()
- if user:
- await user.delete()
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_friend_nickname(cls, user_id: int) -> str:
+ async def get_user_nickname(cls, user_id: int) -> str:
"""
说明:
获取用户昵称
参数:
:param user_id: qq号
"""
- query = cls.query.where(cls.user_id == user_id)
- user = await query.gino.first()
- if user:
+ if user := await cls.get_or_none(user_id=user_id):
if user.nickname:
_tmp = ""
- black_word = Config.get_config("nickname", "BLACK_WORD")
- if black_word:
+ if 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
- async def set_friend_nickname(cls, user_id: int, nickname: str) -> bool:
+ async def set_user_nickname(cls, user_id: int, nickname: str):
"""
说明:
设置用户昵称
@@ -98,18 +57,4 @@ class FriendUser(db.Model):
:param user_id: qq号
:param nickname: 昵称
"""
- try:
- query = cls.query.where(cls.user_id == user_id)
- user = await query.with_for_update().gino.first()
- if not user:
- await cls.create(
- user_id=user_id,
- nickname=nickname,
- )
- else:
- await user.update(
- nickname=nickname,
- ).apply()
- return True
- except Exception:
- return False
+ await cls.update_or_create(user_id=user_id, defaults={"nickname": nickname})
diff --git a/models/goods_info.py b/models/goods_info.py
index 64926be4..431c1da8 100644
--- a/models/goods_info.py
+++ b/models/goods_info.py
@@ -1,38 +1,50 @@
-from services.db_context import db
-from typing import Optional, List, Tuple
-from services.log import logger
+from typing import Dict, List, Optional, Tuple
+
+from tortoise import fields
+
+from services.db_context import Model
-class GoodsInfo(db.Model):
+class GoodsInfo(Model):
__tablename__ = "goods_info"
- id = db.Column(db.Integer(), primary_key=True)
- goods_name = db.Column(db.TEXT(), nullable=False) # 名称
- goods_price = db.Column(db.Integer(), nullable=False) # 价格
- goods_description = db.Column(db.TEXT(), nullable=False) # 商品描述
- goods_discount = db.Column(db.Numeric(scale=3, asdecimal=False), default=1) # 打折
- goods_limit_time = db.Column(db.BigInteger(), default=0) # 限时
- daily_limit = db.Column(db.Integer(), nullable=False, default=0) # 每日购买限制
- daily_purchase_limit = db.Column(
- db.JSON(), nullable=False, default={}
- ) # 每日购买限制数据存储
- is_passive = db.Column(db.Boolean(), nullable=False, default=0) # 是否为被动
- icon = db.Column(db.String(), default=0) # 图标
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ goods_name = fields.CharField(255, unique=True)
+ """商品名称"""
+ goods_price = fields.IntField()
+ """价格"""
+ goods_description = fields.TextField()
+ """描述"""
+ goods_discount = fields.FloatField(default=1)
+ """折扣"""
+ goods_limit_time = fields.BigIntField(default=0)
+ """限时"""
+ daily_limit = fields.IntField(default=0)
+ """每日限购"""
+ daily_purchase_limit: Dict[str, Dict[str, int]] = fields.JSONField(default={})
+ """用户限购记录"""
+ is_passive = fields.BooleanField(default=False)
+ """是否为被动道具"""
+ icon = fields.TextField(null=True)
+ """图标路径"""
- _idx1 = db.Index("goods_group_users_idx1", "goods_name", unique=True)
+ class Meta:
+ table = "goods_info"
+ table_description = "商品数据表"
@classmethod
async def add_goods(
- cls,
- goods_name: str,
- goods_price: int,
- goods_description: str,
- goods_discount: float = 1,
- goods_limit_time: int = 0,
- daily_limit: int = 0,
- is_passive: bool = False,
- icon: Optional[str] = None,
- ) -> bool:
+ cls,
+ goods_name: str,
+ goods_price: int,
+ goods_description: str,
+ goods_discount: float = 1,
+ goods_limit_time: int = 0,
+ daily_limit: int = 0,
+ is_passive: bool = False,
+ icon: Optional[str] = None,
+ ):
"""
说明:
添加商品
@@ -46,22 +58,17 @@ class GoodsInfo(db.Model):
:param is_passive: 是否为被动道具
:param icon: 图标
"""
- try:
- if not await cls.get_goods_info(goods_name):
- await cls.create(
- goods_name=goods_name,
- goods_price=goods_price,
- goods_description=goods_description,
- goods_discount=goods_discount,
- goods_limit_time=goods_limit_time,
- daily_limit=daily_limit,
- is_passive=is_passive,
- icon=icon
- )
- return True
- except Exception as e:
- logger.error(f"GoodsInfo add_goods {goods_name} 发生错误 {type(e)}:{e}")
- return False
+ if not await cls.filter(goods_name=goods_name).first():
+ await cls.create(
+ goods_name=goods_name,
+ goods_price=goods_price,
+ goods_description=goods_description,
+ goods_discount=goods_discount,
+ goods_limit_time=goods_limit_time,
+ daily_limit=daily_limit,
+ is_passive=is_passive,
+ icon=icon,
+ )
@classmethod
async def delete_goods(cls, goods_name: str) -> bool:
@@ -71,28 +78,23 @@ class GoodsInfo(db.Model):
参数:
:param goods_name: 商品名称
"""
- query = (
- await cls.query.where(cls.goods_name == goods_name)
- .with_for_update()
- .gino.first()
- )
- if not query:
- return False
- await query.delete()
- return True
+ if goods := await cls.get_or_none(goods_name=goods_name):
+ await goods.delete()
+ return True
+ return False
@classmethod
async def update_goods(
- cls,
- goods_name: str,
- goods_price: Optional[int] = None,
- goods_description: Optional[str] = None,
- goods_discount: Optional[float] = None,
- goods_limit_time: Optional[int] = None,
- daily_limit: Optional[int] = None,
- is_passive: Optional[bool] = None,
- icon: Optional[str] = None,
- ) -> bool:
+ cls,
+ goods_name: str,
+ goods_price: Optional[int] = None,
+ goods_description: Optional[str] = None,
+ goods_discount: Optional[float] = None,
+ goods_limit_time: Optional[int] = None,
+ daily_limit: Optional[int] = None,
+ is_passive: Optional[bool] = None,
+ icon: Optional[str] = None,
+ ):
"""
说明:
更新商品信息
@@ -106,37 +108,25 @@ class GoodsInfo(db.Model):
:param is_passive: 是否为被动
:param icon: 图标
"""
- try:
- query = (
- await cls.query.where(cls.goods_name == goods_name)
- .with_for_update()
- .gino.first()
+ if goods := await cls.get_or_none(goods_name=goods_name):
+ await cls.update_or_create(
+ goods_name=goods_name,
+ defaults={
+ "goods_price": goods_price or goods.goods_price,
+ "goods_description": goods_description or goods.goods_description,
+ "goods_discount": goods_discount or goods.goods_discount,
+ "goods_limit_time": goods_limit_time
+ if goods_limit_time is not None
+ else goods.goods_limit_time,
+ "daily_limit": daily_limit
+ if daily_limit is not None
+ else goods.daily_limit,
+ "is_passive": is_passive
+ if is_passive is not None
+ else goods.is_passive,
+ "icon": icon or goods.icon,
+ },
)
- if not query:
- return False
- await query.update(
- goods_price=goods_price or query.goods_price,
- goods_description=goods_description or query.goods_description,
- goods_discount=goods_discount or query.goods_discount,
- goods_limit_time=goods_limit_time if goods_limit_time is not None else query.goods_limit_time,
- daily_limit=daily_limit if daily_limit is not None else query.daily_limit,
- is_passive=is_passive if is_passive is not None else query.is_passive,
- icon=icon or query.icon
- ).apply()
- return True
- except Exception as e:
- logger.error(f"GoodsInfo update_goods 发生错误 {type(e)}:{e}")
- return False
-
- @classmethod
- async def get_goods_info(cls, goods_name: str) -> "GoodsInfo":
- """
- 说明:
- 获取商品对象
- 参数:
- :param goods_name: 商品名称
- """
- return await cls.query.where(cls.goods_name == goods_name).gino.first()
@classmethod
async def get_all_goods(cls) -> List["GoodsInfo"]:
@@ -144,7 +134,7 @@ class GoodsInfo(db.Model):
说明:
获得全部有序商品对象
"""
- query = await cls.query.gino.all()
+ query = await cls.all()
id_lst = [x.id for x in query]
goods_lst = []
for _ in range(len(query)):
@@ -155,7 +145,7 @@ class GoodsInfo(db.Model):
@classmethod
async def add_user_daily_purchase(
- cls, goods: "GoodsInfo", user_id: int, group_id: int, num: int = 1
+ cls, goods: "GoodsInfo", user_id_: int, group_id_: int, num: int = 1
):
"""
说明:
@@ -166,19 +156,19 @@ class GoodsInfo(db.Model):
:param group_id: 群号
:param num: 数量
"""
- user_id = str(user_id)
- group_id = str(group_id)
+ user_id = str(user_id_)
+ group_id = str(group_id_)
if goods and goods.daily_limit and goods.daily_limit > 0:
if not goods.daily_purchase_limit.get(group_id):
goods.daily_purchase_limit[group_id] = {}
if not goods.daily_purchase_limit[group_id].get(user_id):
goods.daily_purchase_limit[group_id][user_id] = 0
goods.daily_purchase_limit[group_id][user_id] += num
- await goods.update(daily_purchase_limit=goods.daily_purchase_limit).apply()
+ await goods.save(update_fields=["daily_purchase_limit"])
@classmethod
async def check_user_daily_purchase(
- cls, goods: "GoodsInfo", user_id: int, group_id: int, num: int = 1
+ cls, goods: "GoodsInfo", user_id_: int, group_id_: int, num: int = 1
) -> Tuple[bool, int]:
"""
说明:
@@ -189,8 +179,8 @@ class GoodsInfo(db.Model):
:param group_id: 群号
:param num: 数量
"""
- user_id = str(user_id)
- group_id = str(group_id)
+ user_id = str(user_id_)
+ group_id = str(group_id_)
if goods and goods.daily_limit > 0:
if (
not goods.daily_limit
@@ -204,10 +194,3 @@ class GoodsInfo(db.Model):
goods.daily_limit - goods.daily_purchase_limit[group_id][user_id],
)
return False, 0
-
- @classmethod
- async def reset_daily_purchase(cls):
- """
- 重置每次次数限制
- """
- await cls.update.values(daily_purchase_limit={}).gino.status()
diff --git a/models/group_info.py b/models/group_info.py
index 6131b341..88c598da 100755
--- a/models/group_info.py
+++ b/models/group_info.py
@@ -1,111 +1,24 @@
-from services.db_context import db
-from services.log import logger
from typing import List, Optional
+from tortoise import fields
-class GroupInfo(db.Model):
- __tablename__ = "group_info"
+from services.db_context import Model
+from services.log import logger
- group_id = db.Column(db.BigInteger(), nullable=False, primary_key=True)
- group_name = db.Column(db.Unicode(), nullable=False, default="")
- max_member_count = db.Column(db.Integer(), nullable=False, default=0)
- member_count = db.Column(db.Integer(), nullable=False, default=0)
- group_flag = db.Column(db.Integer(), nullable=False, default=0)
- _idx1 = db.Index("group_info_idx1", "group_id", unique=True)
+class GroupInfo(Model):
- @classmethod
- async def get_group_info(cls, group_id: int) -> "GroupInfo":
- """
- 说明:
- 获取群信息
- 参数:
- :param group_id: 群号
- """
- query = cls.query.where(cls.group_id == group_id)
- return await query.gino.first()
+ group_id = fields.BigIntField(pk=True)
+ """群聊id"""
+ group_name = fields.TextField(default="")
+ """群聊名称"""
+ max_member_count = fields.IntField(default=0)
+ """最大人数"""
+ member_count = fields.IntField(default=0)
+ """当前人数"""
+ group_flag: int = fields.IntField(default=0)
+ """群认证标记"""
- @classmethod
- async def add_group_info(
- cls,
- group_id: int,
- group_name: str,
- max_member_count: int,
- member_count: int,
- group_flag: Optional[int] = None,
- ) -> bool:
- """
- 说明:
- 添加群信息
- 参数:
- :param group_id: 群号
- :param group_name: 群名称
- :param max_member_count: 群员最大数量
- :param member_count: 群员数量
- :param group_flag: 群认证,0为未认证,1为认证
- """
- try:
- group = (
- await cls.query.where(cls.group_id == group_id)
- .with_for_update()
- .gino.first()
- )
- if group:
- await group.update(
- group_name=group_name,
- max_member_count=max_member_count,
- member_count=member_count,
- ).apply()
- if group_flag is not None:
- await group.update(group_flag=group_flag).apply()
- else:
- await cls.create(
- group_id=group_id,
- group_name=group_name,
- max_member_count=max_member_count,
- member_count=member_count,
- group_flag=group_flag,
- )
- return True
- except Exception as e:
- logger.info(f"GroupInfo 调用 add_group_info 发生错误 {type(e)}:{e}")
- return False
-
- @classmethod
- async def delete_group_info(cls, group_id: int):
- """
- 说明:
- 删除群信息
- 参数:
- :param group_id: 群号
- """
- await cls.delete.where(cls.group_id == group_id).gino.status()
-
- @classmethod
- async def get_all_group(cls) -> List["GroupInfo"]:
- """
- 说明:
- 获取所有群对象
- """
- query = await cls.query.gino.all()
- return query
-
- @classmethod
- async def set_group_flag(cls, group_id: int, group_flag: int) -> bool:
- """
- 设置群认证
- :param group_id: 群号
- :param group_flag: 群认证,0为未认证,1为认证
- """
- group = (
- await cls.query.where(cls.group_id == group_id)
- .with_for_update()
- .gino.first()
- )
- if group:
- if group.group_flag != group_flag:
- await group.update(
- group_flag=group_flag,
- ).apply()
- return True
- return False
+ class Meta:
+ table = "group_info"
+ table_description = "群聊信息表"
diff --git a/models/group_member_info.py b/models/group_member_info.py
index 4d37b10d..d374dc63 100755
--- a/models/group_member_info.py
+++ b/models/group_member_info.py
@@ -1,116 +1,48 @@
from datetime import datetime
+from typing import List, Optional, Set
+
+from tortoise import fields
+
from configs.config import Config
-from services.db_context import db
-from typing import List, Optional
+from services.db_context import Model
-class GroupInfoUser(db.Model):
- __tablename__ = "group_info_users"
+class GroupInfoUser(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- user_name = db.Column(db.Unicode(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- user_join_time = db.Column(db.DateTime(), nullable=False)
- nickname = db.Column(db.Unicode())
- uid = db.Column(db.BigInteger())
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ user_name = fields.CharField(255, default="")
+ """用户昵称"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ user_join_time = fields.DatetimeField(null=True)
+ """用户入群时间"""
+ nickname = fields.CharField(255, null=True)
+ """群聊昵称"""
+ uid = fields.BigIntField(null=True)
+ """用户uid"""
- _idx1 = db.Index("info_group_users_idx1", "user_qq", "group_id", unique=True)
+ class Meta:
+ table = "group_info_users"
+ table_description = "群员信息数据表"
+ unique_together = ("user_qq", "group_id")
@classmethod
- async def add_member_info(
- cls,
- user_qq: int,
- group_id: int,
- user_name: str,
- user_join_time: datetime,
- uid: Optional[int] = None,
- ) -> bool:
- """
- 说明:
- 添加群内用户信息
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- :param user_name: 用户名称
- :param user_join_time: 入群时间
- :param uid: 用户唯一 id(自动生成)
- """
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- try:
- if not await query.gino.first():
- await cls.create(
- user_qq=user_qq,
- user_name=user_name,
- group_id=group_id,
- user_join_time=user_join_time,
- uid=uid
- )
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_member_info(
- cls, user_qq: int, group_id: int
- ) -> "GroupInfoUser":
- """
- 说明:
- 查询群员信息
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- """
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- return await query.gino.first()
-
- @classmethod
- async def delete_member_info(cls, user_qq: int, group_id: int) -> bool:
- """
- 说明:
- 删除群员信息
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- """
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- query = query.with_for_update()
- user = await query.gino.first()
- try:
- if user is None:
- return True
- else:
- await cls.delete.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- ).gino.status()
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_group_member_id_list(cls, group_id: int) -> List[int]:
+ async def get_group_member_id_list(cls, group_id: int) -> Set[int]:
"""
说明:
获取该群所有用户qq
参数:
:param group_id: 群号
"""
- member_list = []
- query = cls.query.where((cls.group_id == group_id))
- for user in await query.gino.all():
- member_list.append(user.user_qq)
- return member_list
+ return set(
+ await cls.filter(group_id=group_id).values_list("user_qq", flat=True)
+ )
@classmethod
- async def set_group_member_nickname(
- cls, user_qq: int, group_id: int, nickname: str
- ) -> bool:
+ async def set_user_nickname(cls, user_qq: int, group_id: int, nickname: str):
"""
说明:
设置群员在该群内的昵称
@@ -119,14 +51,11 @@ class GroupInfoUser(db.Model):
:param group_id: 群号
:param nickname: 昵称
"""
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
+ await cls.update_or_create(
+ user_qq=user_qq,
+ group_id=group_id,
+ defaults={"nickname": nickname},
)
- user = await query.with_for_update().gino.first()
- if user:
- await user.update(nickname=nickname).apply()
- return True
- return False
@classmethod
async def get_user_all_group(cls, user_qq: int) -> List[int]:
@@ -136,13 +65,12 @@ class GroupInfoUser(db.Model):
参数:
:param user_qq: 用户qq
"""
- query = await cls.query.where(cls.user_qq == user_qq).gino.all()
- if query:
- query = [x.group_id for x in query]
- return query
+ return list(
+ await cls.filter(user_qq=user_qq).values_list("group_id", flat=True)
+ )
@classmethod
- async def get_group_member_nickname(cls, user_qq: int, group_id: int) -> str:
+ async def get_user_nickname(cls, user_qq: int, group_id: int) -> str:
"""
说明:
获取用户在该群的昵称
@@ -150,46 +78,34 @@ class GroupInfoUser(db.Model):
:param user_qq: qq号
:param group_id: 群号
"""
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- user = await query.gino.first()
- if user:
+ if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
if user.nickname:
- _tmp = ""
- black_word = Config.get_config("nickname", "BLACK_WORD")
- if black_word:
+ nickname = ""
+ if black_word := Config.get_config("nickname", "BLACK_WORD"):
for x in user.nickname:
- _tmp += "*" if x in black_word else x
- return _tmp
+ nickname += "*" if x in black_word else x
+ return nickname
+ return user.nickname
return ""
@classmethod
- async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[str]:
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- user = await query.gino.first()
- _max_uid = cls.query.where((cls.user_qq == 114514) & (cls.group_id == 114514)).with_for_update()
- _max_uid_user = await _max_uid.gino.first()
+ async def get_group_member_uid(cls, user_qq: int, group_id: int) -> Optional[int]:
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ _max_uid_user, _ = await cls.get_or_create(user_qq=114514, group_id=114514)
_max_uid = _max_uid_user.uid
- if not user or not user.uid:
- all_user = await cls.query.where(cls.user_qq == user_qq).gino.all()
+ if not user.uid:
+ all_user = await cls.filter(user_qq=user_qq).all()
for x in all_user:
if x.uid:
return x.uid
- else:
- if not user:
- await GroupInfoUser.add_member_info(user_qq, group_id, '', datetime.min)
- user = await cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- ).gino.first()
- await user.update(
- uid=_max_uid + 1,
- ).apply()
- await _max_uid_user.update(
- uid=_max_uid + 1,
- ).apply()
-
- return user.uid if user and user.uid else None
+ user.uid = _max_uid + 1
+ _max_uid_user.uid = _max_uid + 1
+ await cls.bulk_update([user, _max_uid_user], ["uid"])
+ return user.uid
+ @classmethod
+ async def _run_script(cls):
+ await cls.raw(
+ "alter table group_info_users alter user_join_time drop not null;"
+ )
+ """允许 user_join_time 为空"""
diff --git a/models/level_user.py b/models/level_user.py
index bbc02db7..e0766fca 100755
--- a/models/level_user.py
+++ b/models/level_user.py
@@ -1,18 +1,25 @@
-from asyncpg import UniqueViolationError
+from tortoise import fields
-from services.db_context import db
+from services.db_context import Model
-class LevelUser(db.Model):
- __tablename__ = "level_users"
+class LevelUser(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- user_level = db.Column(db.BigInteger(), nullable=False)
- group_flag = db.Column(db.Integer(), nullable=False, default=0)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ user_level = fields.BigIntField()
+ """用户权限等级"""
+ group_flag = fields.IntField(default=0)
+ """特殊标记,是否随群管理员变更而设置权限"""
- _idx1 = db.Index("level_group_users_idx1", "user_qq", "group_id", unique=True)
+ class Meta:
+ table = "level_users"
+ table_description = "用户权限数据库"
+ unique_together = ("user_qq", "group_id")
@classmethod
async def get_user_level(cls, user_qq: int, group_id: int) -> int:
@@ -23,17 +30,14 @@ class LevelUser(db.Model):
:param user_qq: qq号
:param group_id: 群号
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.gino.first()
- if user:
+ if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
return user.user_level
- else:
- return -1
+ return -1
@classmethod
async def set_level(
cls, user_qq: int, group_id: int, level: int, group_flag: int = 0
- ) -> bool:
+ ):
"""
说明:
设置用户在群内的权限
@@ -43,23 +47,11 @@ class LevelUser(db.Model):
:param level: 权限等级
:param group_flag: 是否被自动更新刷新权限 0:是,1:否
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- try:
- if not user:
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- user_level=level,
- group_flag=group_flag,
- )
- return True
- else:
- await user.update(user_level=level, group_flag=group_flag).apply()
- return False
- except UniqueViolationError:
- return False
+ await cls.update_or_create(
+ user_qq=user_qq,
+ group_id=group_id,
+ defaults={"user_level": level, "group_flag": group_flag},
+ )
@classmethod
async def delete_level(cls, user_qq: int, group_id: int) -> bool:
@@ -70,14 +62,10 @@ class LevelUser(db.Model):
:param user_qq: qq号
:param group_id: 群号
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- query = query.with_for_update()
- user = await query.gino.first()
- if user is None:
- return False
- else:
+ if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
await user.delete()
return True
+ return False
@classmethod
async def check_level(cls, user_qq: int, group_id: int, level: int) -> bool:
@@ -89,25 +77,14 @@ class LevelUser(db.Model):
:param group_id: 群号
:param level: 权限等级
"""
- if group_id != 0:
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- user = await query.gino.first()
- if user is None:
- return False
- user_level = user.user_level
+ if group_id:
+ if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
+ return user.user_level > level
else:
- query = cls.query.where(cls.user_qq == user_qq)
- highest_level = 0
- for user in await query.gino.all():
- if user.user_level > highest_level:
- highest_level = user.user_level
- user_level = highest_level
- if user_level >= level:
- return True
- else:
- return False
+ user_list = await cls.filter(user_qq=user_qq).all()
+ user = max(user_list, key=lambda x: x.user_level)
+ return user.user_level > level
+ return False
@classmethod
async def is_group_flag(cls, user_qq: int, group_id: int) -> bool:
@@ -118,12 +95,6 @@ class LevelUser(db.Model):
:param user_qq: qq号
:param group_id: 群号
"""
- user = await cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- ).gino.first()
- if not user:
- return False
- if user.group_flag == 1:
- return True
- else:
- return False
+ if user := await cls.get_or_none(user_qq=user_qq, group_id=group_id):
+ return user.group_flag == 1
+ return False
diff --git a/models/sign_group_user.py b/models/sign_group_user.py
index c7919b9f..a0803f05 100755
--- a/models/sign_group_user.py
+++ b/models/sign_group_user.py
@@ -1,99 +1,78 @@
from datetime import datetime
-from typing import List
-from services.db_context import db
+from typing import Dict, List, Literal, Optional, Tuple, Union
+
+from tortoise import fields
+
+from services.db_context import Model
-class SignGroupUser(db.Model):
- __tablename__ = "sign_group_users"
+class SignGroupUser(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- checkin_count = db.Column(db.Integer(), nullable=False)
- checkin_time_last = db.Column(db.DateTime(timezone=True), nullable=False)
- impression = db.Column(db.Numeric(scale=3, asdecimal=False), nullable=False)
- add_probability = db.Column(
- db.Numeric(scale=3, asdecimal=False), nullable=False, default=0
- )
- specify_probability = db.Column(
- db.Numeric(scale=3, asdecimal=False), nullable=False, default=0
- )
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ checkin_count = fields.IntField(default=0)
+ """签到次数"""
+ checkin_time_last = fields.DatetimeField(auto_now=True)
+ """最后签到时间"""
+ impression = fields.DecimalField(10, 3, default=0)
+ """好感度"""
+ add_probability = fields.DecimalField(10, 3, default=0)
+ """双倍签到增加概率"""
+ specify_probability = fields.DecimalField(10, 3, default=0)
+ """使用指定双倍概率"""
+ # specify_probability = fields.DecimalField(10, 3, default=0)
- _idx1 = db.Index("sign_group_users_idx1", "user_qq", "group_id", unique=True)
+ class Meta:
+ table = "sign_group_users"
+ table_description = "群员签到数据表"
+ unique_together = ("user_qq", "group_id")
@classmethod
- async def ensure(
- cls, user_qq: int, group_id: int, for_update: bool = False
- ) -> "SignGroupUser":
- """
- 说明:
- 获取签到用户
- 参数:
- :param user_qq: 用户qq
- :param group_id: 所在群聊
- :param for_update: 是否存在修改数据
- """
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- if for_update:
- query = query.with_for_update()
- user = await query.gino.first()
- return user or await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- checkin_count=0,
- checkin_time_last=datetime.min, # 从未签到过
- impression=0,
- )
-
- @classmethod
- async def get_user_all_data(cls, user_qq: int) -> List["SignGroupUser"]:
- """
- 说明:
- 获取某用户所有数据
- 参数:
- :param user_qq: 用户qq
- """
- query = cls.query.where(cls.user_qq == user_qq)
- query = query.with_for_update()
- return await query.gino.all()
-
- @classmethod
- async def sign(cls, user: "SignGroupUser", impression: float, checkin_time_last: datetime):
+ async def sign(cls, user: "SignGroupUser", impression: float):
"""
说明:
签到
说明:
:param user: 用户
:param impression: 增加的好感度
- :param checkin_time_last: 签到时间
"""
- await user.update(
- checkin_count=user.checkin_count + 1,
- checkin_time_last=checkin_time_last,
- impression=user.impression + impression,
- add_probability=0,
- specify_probability=0,
- ).apply()
+ user.checkin_count = user.checkin_count + 1
+ user.add_probability = 0
+ user.specify_probability = 0
+ user.impression = float(user.impression) + impression
+ await user.save(
+ update_fields=[
+ "checkin_count",
+ "add_probability",
+ "specify_probability",
+ "impression",
+ ]
+ )
@classmethod
- async def get_all_impression(cls, group_id: int) -> "list, list, list":
+ async def get_all_impression(
+ cls, group_id: Optional[int]
+ ) -> Tuple[List[int], List[int], List[float]]:
"""
说明:
获取该群所有用户 id 及对应 好感度
参数:
:param group_id: 群号
"""
- impression_list = []
- user_qq_list = []
- user_group = []
if group_id:
- query = cls.query.where(cls.group_id == group_id)
+ query = cls.filter(group_id=group_id)
else:
- query = cls.query
- for user in await query.gino.all():
- impression_list.append(user.impression)
- user_qq_list.append(user.user_qq)
- user_group.append(user.group_id)
- return user_qq_list, impression_list, user_group
+ query = cls
+ value_list = await query.all().values_list("user_qq", "group_id", "impression") # type: ignore
+ qq_list = []
+ group_list = []
+ impression_list = []
+ for value in value_list:
+ qq_list.append(value[0])
+ group_list.append(value[1])
+ impression_list.append(float(value[2]))
+ return qq_list, impression_list, group_list
diff --git a/models/user_shop_gold_log.py b/models/user_shop_gold_log.py
index 76868fcb..5e444196 100644
--- a/models/user_shop_gold_log.py
+++ b/models/user_shop_gold_log.py
@@ -1,59 +1,29 @@
from datetime import datetime
-from services.db_context import db
+from tortoise import fields
+
+from services.db_context import Model
-class UserShopGoldLog(db.Model):
- __tablename__ = "user_shop_gold_log"
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- type = db.Column(db.Integer(), nullable=False) # 0: 购买,1: 使用,2: 插件
- name = db.Column(db.String())
- spend_gold = db.Column(db.Integer(), nullable=False)
- num = db.Column(db.Integer(), nullable=False)
- create_time = db.Column(db.DateTime(timezone=True), nullable=False)
+class UserShopGoldLog(Model):
- @classmethod
- async def add_shop_log(
- cls,
- user_qq: int,
- group_id: int,
- type_: int,
- name: str,
- num: int,
- spend_gold: int = 0,
- ):
- """
- 说明:
- 添加商店购买或使用日志
- 参数:
- :param user_qq: qq号
- :param group_id: 所在群号
- :param type_: 类型
- :param name: 商品名称
- :param num: 数量
- :param spend_gold: 花费金币
- """
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- type=type_,
- name=name,
- num=num,
- spend_gold=spend_gold,
- create_time=datetime.now(),
- )
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ type = fields.IntField()
+ """金币使用类型 0: 购买, 1: 使用, 2: 插件"""
+ name = fields.CharField(255)
+ """商品/插件 名称"""
+ spend_gold = fields.IntField(default=0)
+ """花费金币"""
+ num = fields.IntField()
+ """数量"""
+ create_time = fields.DatetimeField(auto_now_add=True)
+ """创建时间"""
- @classmethod
- async def get_user_log(cls, user_qq: int, group_id: int) -> "UserShopGoldLog":
- """
- 说明:
- 获取用户日志
- 参数:
- :param user_qq: qq号
- :param group_id: 所在群号
- """
- return await cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_qq == group_id)
- ).first()
+ class Meta:
+ table = "user_shop_gold_log"
+ table_description = "金币使用日志表"
diff --git a/plugins/aconfig/__init__.py b/plugins/aconfig/__init__.py
index 27afa36e..3397495b 100755
--- a/plugins/aconfig/__init__.py
+++ b/plugins/aconfig/__init__.py
@@ -1,20 +1,20 @@
-from utils.message_builder import image
-from configs.path_config import IMAGE_PATH
-from nonebot import on_command
-from nonebot.rule import to_me
+import os
+import random
+
+from nonebot import on_command, on_keyword
from nonebot.adapters.onebot.v11 import GroupMessageEvent
from nonebot.adapters.onebot.v11.permission import GROUP
-from utils.utils import FreqLimiter
-from configs.config import NICKNAME
-import random
-from nonebot import on_keyword
-import os
+from nonebot.rule import to_me
+from configs.config import NICKNAME
+from configs.path_config import IMAGE_PATH
+from utils.message_builder import image
+from utils.utils import FreqLimiter
__zx_plugin_name__ = "基本设置 [Hidden]"
__plugin_usage__ = "用法: 无"
__plugin_version__ = 0.1
-__plugin_author__ = 'HibiKier'
+__plugin_author__ = "HibiKier"
_flmt = FreqLimiter(300)
@@ -29,7 +29,7 @@ async def _(event: GroupMessageEvent):
return
_flmt.start_cd(event.group_id)
await config_play_game.finish(
- image(random.choice(os.listdir(IMAGE_PATH / "dayouxi")), "dayouxi")
+ image(IMAGE_PATH / random.choice(os.listdir(IMAGE_PATH / "dayouxi")))
)
@@ -40,14 +40,14 @@ self_introduction = on_command(
@self_introduction.handle()
async def _():
- if NICKNAME.find('真寻') != -1:
+ if NICKNAME.find("真寻") != -1:
result = (
"我叫绪山真寻\n"
"你们可以叫我真寻,小真寻,哪怕你们叫我小寻子我也能接受!\n"
"年龄的话我还是个**岁初中生(至少现在是)\n"
"身高保密!!!(也就比美波里(姐姐..(妹妹))矮一点)\n"
"我生日是在3月6号, 能记住的话我会很高兴的\n现在是自宅警备系的现役JC\n"
- "最好的朋友是椛!\n" + image("zhenxun")
+ "最好的朋友是椛!\n" + image("zhenxun.jpg")
)
await self_introduction.finish(result)
@@ -57,5 +57,4 @@ my_wife = on_keyword({"老婆"}, rule=to_me(), priority=5, block=True)
@my_wife.handle()
async def _():
- await my_wife.finish(image("laopo.jpg", "other"))
-
+ await my_wife.finish(image(IMAGE_PATH / "other" / "laopo.jpg"))
diff --git a/plugins/ai/__init__.py b/plugins/ai/__init__.py
index 96a1ad0c..361f5e34 100755
--- a/plugins/ai/__init__.py
+++ b/plugins/ai/__init__.py
@@ -1,18 +1,14 @@
-
from nonebot import on_message
-from nonebot.adapters.onebot.v11 import (
- Bot,
- GroupMessageEvent,
- Message,
- MessageEvent,
-)
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
from nonebot.rule import to_me
+
+from configs.config import NICKNAME, Config
from models.friend_user import FriendUser
from models.group_member_info import GroupInfoUser
from services.log import logger
from utils.utils import get_message_img, get_message_text
+
from .data_source import get_chat_result, hello, no_result
-from configs.config import NICKNAME, Config
__zx_plugin_name__ = "AI"
__plugin_usage__ = f"""
@@ -61,11 +57,9 @@ async def _(bot: Bot, event: MessageEvent):
await ai.finish(hello())
img = img[0] if img else ""
if isinstance(event, GroupMessageEvent):
- nickname = await GroupInfoUser.get_group_member_nickname(
- event.user_id, event.group_id
- )
+ nickname = await GroupInfoUser.get_user_nickname(event.user_id, event.group_id)
else:
- nickname = await FriendUser.get_friend_nickname(event.user_id)
+ nickname = await FriendUser.get_user_nickname(event.user_id)
if not nickname:
if isinstance(event, GroupMessageEvent):
nickname = event.sender.card or event.sender.nickname
diff --git a/plugins/ai/data_source.py b/plugins/ai/data_source.py
index 8aadfa7a..295b5b40 100755
--- a/plugins/ai/data_source.py
+++ b/plugins/ai/data_source.py
@@ -1,11 +1,13 @@
import os
import random
import re
-from utils.http_utils import AsyncHttpx
-from configs.path_config import IMAGE_PATH, DATA_PATH
+
+from configs.config import NICKNAME, Config
+from configs.path_config import DATA_PATH, IMAGE_PATH
from services.log import logger
-from utils.message_builder import image, face
-from configs.config import Config, NICKNAME
+from utils.http_utils import AsyncHttpx
+from utils.message_builder import face, image
+
from .utils import ai_message_manager
try:
@@ -124,7 +126,9 @@ async def xie_ai(text: str) -> str:
:param text: 问题
:return: 青云可回复
"""
- res = await AsyncHttpx.get(f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}")
+ res = await AsyncHttpx.get(
+ f"http://api.qingyunke.com/api.php?key=free&appid=0&msg={text}"
+ )
content = ""
try:
data = json.loads(res.text)
@@ -176,9 +180,9 @@ def hello() -> str:
)
img = random.choice(os.listdir(IMAGE_PATH / "zai"))
if img[-4:] == ".gif":
- result += image(img, "zai")
+ result += image(IMAGE_PATH / "zai" / img)
else:
- result += image(img, "zai")
+ result += image(IMAGE_PATH / "zai" / img)
return result
@@ -187,17 +191,16 @@ def no_result() -> str:
"""
没有回答时的回复
"""
- return (
- random.choice(
- [
- "你在说啥子?",
- f"纯洁的{NICKNAME}没听懂",
- "下次再告诉你(下次一定)",
- "你觉得我听懂了吗?嗯?",
- "我!不!知!道!",
- ]
- )
- + image(random.choice(os.listdir(IMAGE_PATH / "noresult")), "noresult")
+ return random.choice(
+ [
+ "你在说啥子?",
+ f"纯洁的{NICKNAME}没听懂",
+ "下次再告诉你(下次一定)",
+ "你觉得我听懂了吗?嗯?",
+ "我!不!知!道!",
+ ]
+ ) + image(
+ IMAGE_PATH / "noresult" / random.choice(os.listdir(IMAGE_PATH / "noresult"))
)
diff --git a/plugins/bilibili_sub/__init__.py b/plugins/bilibili_sub/__init__.py
index ec567d33..83f30471 100755
--- a/plugins/bilibili_sub/__init__.py
+++ b/plugins/bilibili_sub/__init__.py
@@ -1,28 +1,29 @@
-from nonebot import on_command, on_regex
-from nonebot.typing import T_State
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
+from typing import Any, Optional, Tuple
+import nonebot
+from nonebot import Driver, on_command, on_regex
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import ArgStr, CommandArg, RegexGroup
+from nonebot.typing import T_State
+
+from configs.config import Config
+from models.level_user import LevelUser
+from services.log import logger
from utils.image_utils import text2image
+from utils.manager import group_manager
from utils.message_builder import image
+from utils.utils import get_bot, is_number, scheduler
+
from .data_source import (
+ BilibiliSub,
+ SubManager,
add_live_sub,
- delete_sub,
- add_up_sub,
add_season_sub,
+ add_up_sub,
+ delete_sub,
get_media_id,
get_sub_status,
- SubManager,
- BilibiliSub,
)
-from models.level_user import LevelUser
-from utils.manager import group_manager
-from configs.config import Config
-from utils.utils import is_number, scheduler, get_bot
-from typing import Optional, Tuple, Any
-from services.log import logger
-from nonebot import Driver
-from nonebot.params import CommandArg, ArgStr, RegexGroup
-import nonebot
__zx_plugin_name__ = "B站订阅"
__plugin_usage__ = """
@@ -168,20 +169,20 @@ async def _(
sub_user: str = ArgStr("sub_user"),
):
if sub_type in ["主播", "直播"]:
- result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user,"live")
+ result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "live")
elif sub_type.lower() in ["up", "用户"]:
- result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user,"up")
- else: result = await BilibiliSub.delete_bilibili_sub(int(id_),sub_user)
+ result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user, "up")
+ else:
+ result = await BilibiliSub.delete_bilibili_sub(int(id_), sub_user)
if result:
await del_sub.send(f"删除订阅id:{id_} 成功...")
logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 删除订阅 {id_}"
- )
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f" 删除订阅 {id_}"
+ )
else:
await del_sub.send(f"删除订阅id:{id_} 失败...")
-
@show_sub_info.handle()
@@ -190,7 +191,7 @@ async def _(event: MessageEvent):
id_ = f"{event.group_id}"
else:
id_ = f"{event.user_id}"
- data = await BilibiliSub.get_sub_data(id_)
+ data = await BilibiliSub.filter(sub_users__contains=id_).all()
live_rst = ""
up_rst = ""
season_rst = ""
@@ -217,11 +218,9 @@ async def _(event: MessageEvent):
)
await show_sub_info.send(
image(
- b64=(
- await text2image(
- live_rst + up_rst + season_rst, padding=10, color="#f9f6f2"
- )
- ).pic2bs4()
+ await text2image(
+ live_rst + up_rst + season_rst, padding=10, color="#f9f6f2"
+ )
)
)
@@ -277,7 +276,9 @@ async def send_sub_msg(rst: str, sub: BilibiliSub, bot: Bot):
):
rst = "[CQ:at,qq=all]\n" + rst
if group_manager.get_plugin_status("bilibili_sub", group_id):
- await bot.send_group_msg(group_id=group_id, message=Message(rst))
+ await bot.send_group_msg(
+ group_id=group_id, message=Message(rst)
+ )
else:
await bot.send_private_msg(user_id=int(x), message=Message(rst))
except Exception as e:
diff --git a/plugins/bilibili_sub/data_source.py b/plugins/bilibili_sub/data_source.py
index dd3cdebb..a8175257 100755
--- a/plugins/bilibili_sub/data_source.py
+++ b/plugins/bilibili_sub/data_source.py
@@ -1,34 +1,33 @@
-from bilireq.exceptions import ResponseCodeError
-from nonebot.adapters.onebot.v11 import MessageSegment
-
-from utils.manager import resources_manager
+import random
from asyncio.exceptions import TimeoutError
+from datetime import datetime
+from typing import Optional, Tuple
-from utils.utils import get_bot
-from .model import BilibiliSub
-from bilireq.live import get_room_info_by_id
-from .utils import get_meta, get_user_card
-from utils.message_builder import image
-from bilireq.user import get_videos
# from .utils import get_videos
from bilireq import dynamic
-from typing import Optional, Tuple
-from configs.path_config import IMAGE_PATH
-from datetime import datetime
-from utils.browser import get_browser
-from services.db_context import db
+from bilireq.exceptions import ResponseCodeError
+from bilireq.live import get_room_info_by_id
+from bilireq.user import get_videos
+from nonebot.adapters.onebot.v11 import MessageSegment
+
+from configs.path_config import IMAGE_PATH, TEMP_PATH
from services.log import logger
-from utils.http_utils import AsyncHttpx
-import random
+from utils.browser import get_browser
+from utils.http_utils import AsyncHttpx, AsyncPlaywright
+from utils.manager import resources_manager
+from utils.message_builder import image
+from utils.utils import get_bot
+
+from .model import BilibiliSub
+from .utils import get_meta, get_user_card
+
+SEARCH_URL = "https://api.bilibili.com/x/web-interface/search/all/v2"
+
+DYNAMIC_PATH = IMAGE_PATH / "bilibili_sub" / "dynamic"
+DYNAMIC_PATH.mkdir(exist_ok=True, parents=True)
-bilibili_search_url = "https://api.bilibili.com/x/web-interface/search/all/v2"
-
-dynamic_path = IMAGE_PATH / "bilibili_sub" / "dynamic"
-dynamic_path.mkdir(exist_ok=True, parents=True)
-
-
-resources_manager.add_temp_dir(dynamic_path)
+resources_manager.add_temp_dir(DYNAMIC_PATH)
async def add_live_sub(live_id: int, sub_user: str) -> str:
@@ -49,7 +48,7 @@ async def add_live_sub(live_id: int, sub_user: str) -> str:
short_id = live_info["short_id"]
title = live_info["title"]
live_status = live_info["live_status"]
- if await BilibiliSub.add_bilibili_sub(
+ if await BilibiliSub.sub_handle(
room_id,
"live",
sub_user,
@@ -58,14 +57,14 @@ async def add_live_sub(live_id: int, sub_user: str) -> str:
live_status=live_status,
):
await _get_up_status(room_id)
- uname = (await BilibiliSub.get_sub(room_id)).uname
+ uname = (await BilibiliSub.get_or_none(sub_id=room_id)).uname
return (
"已成功订阅主播:\n"
f"\ttitle:{title}\n"
f"\tname: {uname}\n"
f"\tlive_id:{room_id}\n"
f"\tuid:{uid}"
- )
+ )
else:
return "添加订阅失败..."
except Exception as e:
@@ -80,35 +79,34 @@ async def add_up_sub(uid: int, sub_user: str) -> str:
:param sub_user: 订阅用户
"""
try:
- async with db.transaction():
- try:
- """bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
- user_info = await get_user_card(uid)
- except ResponseCodeError:
- return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
- uname = user_info["name"]
- """bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
- dynamic_info = await dynamic.get_user_dynamics(uid)
- dynamic_upload_time = 0
- if dynamic_info.get("cards"):
- dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
- """bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
- video_info = await get_videos(uid)
- latest_video_created = 0
- if video_info["list"].get("vlist"):
- latest_video_created = video_info["list"]["vlist"][0]["created"]
- if await BilibiliSub.add_bilibili_sub(
- uid,
- "up",
- sub_user,
- uid=uid,
- uname=uname,
- dynamic_upload_time=dynamic_upload_time,
- latest_video_created=latest_video_created,
- ):
- return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
- else:
- return "添加订阅失败..."
+ try:
+ """bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
+ user_info = await get_user_card(uid)
+ except ResponseCodeError:
+ return f"未找到UpId:{uid} 的信息,请检查Id是否正确"
+ uname = user_info["name"]
+ """bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
+ dynamic_info = await dynamic.get_user_dynamics(uid)
+ dynamic_upload_time = 0
+ if dynamic_info.get("cards"):
+ dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
+ """bilibili_api.user库中User类的get_videos改为bilireq.user库的get_videos方法"""
+ video_info = await get_videos(uid)
+ latest_video_created = 0
+ if video_info["list"].get("vlist"):
+ latest_video_created = video_info["list"]["vlist"][0]["created"]
+ if await BilibiliSub.sub_handle(
+ uid,
+ "up",
+ sub_user,
+ uid=uid,
+ uname=uname,
+ dynamic_upload_time=dynamic_upload_time,
+ latest_video_created=latest_video_created,
+ ):
+ return "已成功订阅UP:\n" f"\tname: {uname}\n" f"\tuid:{uid}"
+ else:
+ return "添加订阅失败..."
except Exception as e:
logger.error(f"订阅Up uid:{uid} 发生了错误 {type(e)}:{e}")
return "添加订阅失败..."
@@ -121,30 +119,29 @@ async def add_season_sub(media_id: int, sub_user: str) -> str:
:param sub_user: 订阅用户
"""
try:
- async with db.transaction():
- try:
- """bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
- season_info = await get_meta(media_id)
- except ResponseCodeError:
- return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
- season_id = season_info["media"]["season_id"]
- season_current_episode = season_info["media"]["new_ep"]["index"]
- season_name = season_info["media"]["title"]
- if await BilibiliSub.add_bilibili_sub(
- media_id,
- "season",
- sub_user,
- season_name=season_name,
- season_id=season_id,
- season_current_episode=season_current_episode,
- ):
- return (
- "已成功订阅番剧:\n"
- f"\ttitle: {season_name}\n"
- f"\tcurrent_episode: {season_current_episode}"
- )
- else:
- return "添加订阅失败..."
+ try:
+ """bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
+ season_info = await get_meta(media_id)
+ except ResponseCodeError:
+ return f"未找到media_id:{media_id} 的信息,请检查Id是否正确"
+ season_id = season_info["media"]["season_id"]
+ season_current_episode = season_info["media"]["new_ep"]["index"]
+ season_name = season_info["media"]["title"]
+ if await BilibiliSub.sub_handle(
+ media_id,
+ "season",
+ sub_user,
+ season_name=season_name,
+ season_id=season_id,
+ season_current_episode=season_current_episode,
+ ):
+ return (
+ "已成功订阅番剧:\n"
+ f"\ttitle: {season_name}\n"
+ f"\tcurrent_episode: {season_current_episode}"
+ )
+ else:
+ return "添加订阅失败..."
except Exception as e:
logger.error(f"订阅番剧 media_id:{media_id} 发生了错误 {type(e)}:{e}")
return "添加订阅失败..."
@@ -171,9 +168,7 @@ async def get_media_id(keyword: str) -> dict:
for _ in range(3):
try:
_season_data = {}
- response = await AsyncHttpx.get(
- bilibili_search_url, params=params, timeout=5
- )
+ response = await AsyncHttpx.get(SEARCH_URL, params=params, timeout=5)
if response.status_code == 200:
data = response.json()
if data.get("data"):
@@ -227,9 +222,9 @@ async def _get_live_status(id_: int) -> Optional[str]:
room_id = live_info["room_id"]
live_status = live_info["live_status"]
cover = live_info["user_cover"]
- sub = await BilibiliSub.get_sub(id_)
+ sub = await BilibiliSub.get_or_none(sub_id=id_)
if sub.live_status != live_status:
- await BilibiliSub.update_sub_info(id_, live_status=live_status)
+ await BilibiliSub.sub_handle(id_, live_status=live_status)
if sub.live_status in [0, 2] and live_status == 1:
return (
f""
@@ -247,7 +242,7 @@ async def _get_up_status(id_: int) -> Optional[str]:
:param id_: 订阅 id
:return:
"""
- _user = await BilibiliSub.get_sub(id_)
+ _user = await BilibiliSub.get_or_none(sub_id=id_)
"""bilibili_api.user库中User类的get_user_info改为bilireq.user库的get_user_info方法"""
user_info = await get_user_card(_user.uid)
uname = user_info["name"]
@@ -257,14 +252,14 @@ async def _get_up_status(id_: int) -> Optional[str]:
video = None
dividing_line = "\n-------------\n"
if _user.uname != uname:
- await BilibiliSub.update_sub_info(id_, uname=uname)
+ await BilibiliSub.sub_handle(id_, uname=uname)
dynamic_img, dynamic_upload_time, link = await get_user_dynamic(_user.uid, _user)
if video_info["list"].get("vlist"):
video = video_info["list"]["vlist"][0]
latest_video_created = video["created"]
rst = ""
if dynamic_img:
- await BilibiliSub.update_sub_info(id_, dynamic_upload_time=dynamic_upload_time)
+ await BilibiliSub.sub_handle(id_, dynamic_upload_time=dynamic_upload_time)
rst += f"{uname} 发布了动态!\n" f"{dynamic_img}\n{link}"
if (
latest_video_created
@@ -273,9 +268,7 @@ async def _get_up_status(id_: int) -> Optional[str]:
and _user.latest_video_created < latest_video_created
):
rst = rst + dividing_line if rst else rst
- await BilibiliSub.update_sub_info(
- id_, latest_video_created=latest_video_created
- )
+ await BilibiliSub.sub_handle(id_, latest_video_created=latest_video_created)
rst += (
f'{image(video["pic"])}\n'
f"{uname} 投稿了新视频啦\n"
@@ -295,10 +288,10 @@ async def _get_season_status(id_) -> Optional[str]:
"""bilibili_api.bangumi库中get_meta改为bilireq.bangumi库的get_meta方法"""
season_info = await get_meta(id_)
title = season_info["media"]["title"]
- _idx = (await BilibiliSub.get_sub(id_)).season_current_episode
+ _idx = (await BilibiliSub.get_or_none(sub_id=id_)).season_current_episode
new_ep = season_info["media"]["new_ep"]["index"]
if new_ep != _idx:
- await BilibiliSub.update_sub_info(
+ await BilibiliSub.sub_handle(
id_, season_current_episode=new_ep, season_update_time=datetime.now()
)
return (
@@ -320,55 +313,22 @@ async def get_user_dynamic(
"""
"""bilibili_api.user库中User类的get_dynamics改为bilireq.dynamic库的get_user_dynamics方法"""
dynamic_info = await dynamic.get_user_dynamics(uid)
- browser = await get_browser()
- if dynamic_info.get("cards") and browser:
+ if dynamic_info.get("cards"):
dynamic_upload_time = dynamic_info["cards"][0]["desc"]["timestamp"]
dynamic_id = dynamic_info["cards"][0]["desc"]["dynamic_id"]
if local_user.dynamic_upload_time < dynamic_upload_time:
- context = await browser.new_context()
- page = await context.new_page()
- try:
- await page.goto(
- f"https://t.bilibili.com/{dynamic_id}",
- wait_until="networkidle",
- timeout=10000,
- )
- # await page.set_viewport_size({"width": 2560, "height": 1080, "timeout": 10000*20}) # timeout: 200s
- # 删除置顶
- # await page.evaluate(
- # """
- # xs = document.getElementsByClassName('bili-dyn-item__tag');
- # for (x of xs) {
- # x.parentNode.parentNode.remove();
- # }
- # """
- # )
- # async with page.expect_popup() as popup_info:
- # await page.locator(".bili-rich-text__content").click()
- # details_page = await popup_info.value
- await page.set_viewport_size(
- {"width": 2560, "height": 1080, "timeout": 10000 * 20}
- )
- await page.wait_for_selector(".bili-dyn-item__main")
- card = page.locator(".bili-dyn-item__main")
- await card.wait_for()
- await card.screenshot(
- path=dynamic_path / f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
- )
- except Exception as e:
- logger.error(f"B站订阅:获取用户动态 发送错误 {type(e)}:{e}")
- finally:
- await context.close()
- await page.close()
- return (
- image(
- f"{local_user.sub_id}_{dynamic_upload_time}.jpg",
- "bilibili_sub/dynamic",
- ),
- dynamic_upload_time,
- f"https://t.bilibili.com/{dynamic_id}"
+ image = await AsyncPlaywright.screenshot(
+ f"https://t.bilibili.com/{dynamic_id}",
+ DYNAMIC_PATH / f"sub_{local_user.sub_id}.png",
+ ".bili-dyn-item__main",
+ wait_until="networkidle",
)
- return None, 0, ''
+ return (
+ image,
+ dynamic_upload_time,
+ f"https://t.bilibili.com/{dynamic_id}",
+ )
+ return None, 0, ""
class SubManager:
diff --git a/plugins/bilibili_sub/model.py b/plugins/bilibili_sub/model.py
index 4ef5ae70..1f73d39d 100755
--- a/plugins/bilibili_sub/model.py
+++ b/plugins/bilibili_sub/model.py
@@ -1,43 +1,58 @@
-from services.log import logger
-from services.db_context import db
from datetime import datetime
-from typing import Optional, List
+from typing import List, Optional, Tuple
+
+from tortoise import fields
+
+from services.db_context import Model
+from services.log import logger
-class BilibiliSub(db.Model):
- __tablename__ = "bilibili_sub"
+class BilibiliSub(Model):
- id = db.Column(db.Integer(), primary_key=True)
- sub_id = db.Column(db.Integer(), nullable=False)
- sub_type = db.Column(db.String(), nullable=False)
- # 订阅用户
- sub_users = db.Column(db.String(), nullable=False)
- # 直播
- live_short_id = db.Column(db.Integer())
- live_status = db.Column(db.Integer)
- # 主播/UP
- uid = db.Column(db.BigInteger())
- uname = db.Column(db.String())
- latest_video_created = db.Column(db.BigInteger()) # 视频上传时间
- dynamic_upload_time = db.Column(db.BigInteger(), default=0) # 动态发布时间
- # 番剧
- season_name = db.Column(db.String())
- season_id = db.Column(db.Integer())
- season_current_episode = db.Column(db.String())
- season_update_time = db.Column(db.DateTime())
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ sub_id = fields.IntField()
+ """订阅id"""
+ sub_type = fields.CharField(255)
+ """订阅类型"""
+ sub_users = fields.TextField()
+ """订阅用户"""
+ live_short_id = fields.IntField(null=True)
+ """直播短id"""
+ live_status = fields.IntField(null=True)
+ """直播状态 0: 停播 1: 直播"""
+ uid = fields.BigIntField(null=True)
+ """主播/UP UID"""
+ uname = fields.CharField(255, null=True)
+ """主播/UP 名称"""
+ latest_video_created = fields.BigIntField(null=True)
+ """最后视频上传时间"""
+ dynamic_upload_time = fields.BigIntField(null=True, default=0)
+ """动态发布时间"""
+ season_name = fields.CharField(255, null=True)
+ """番剧名称"""
+ season_id = fields.IntField(null=True)
+ """番剧id"""
+ season_current_episode = fields.CharField(255, null=True)
+ """番剧最新集数"""
+ season_update_time = fields.DateField(null=True)
+ """番剧更新日期"""
- _idx1 = db.Index("bilibili_sub_idx1", "sub_id", "sub_type", unique=True)
+ class Meta:
+ table = "bilibili_sub"
+ table_description = "B站订阅数据表"
+ unique_together = ("sub_id", "sub_type")
@classmethod
- async def add_bilibili_sub(
+ async def sub_handle(
cls,
sub_id: int,
- sub_type: str,
- sub_user: str,
+ sub_type: Optional[str] = None,
+ sub_user: str = "",
*,
live_short_id: Optional[int] = None,
live_status: Optional[int] = None,
- dynamic_upload_time: Optional[int] = None,
+ dynamic_upload_time: int = 0,
uid: Optional[int] = None,
uname: Optional[str] = None,
latest_video_created: Optional[int] = None,
@@ -64,50 +79,60 @@ class BilibiliSub(db.Model):
:param season_current_episode: 番剧最新集数
:param season_update_time: 番剧更新时间
"""
- try:
- query = (
- await cls.query.where( (cls.sub_id == sub_id) & (cls.sub_type == sub_type) )
- .with_for_update()
- .gino.first()
- )
+ # try:
+ data = {
+ "sub_type": sub_type,
+ "sub_user": sub_user,
+ "live_short_id": live_short_id,
+ "live_status": live_status,
+ "dynamic_upload_time": dynamic_upload_time,
+ "uid": uid,
+ "uname": uname,
+ "latest_video_created": latest_video_created,
+ "season_name": season_name,
+ "season_id": season_id,
+ "season_current_episode": season_current_episode,
+ "season_update_time": season_update_time,
+ }
+ if sub_user:
sub_user = sub_user if sub_user[-1] == "," else f"{sub_user},"
- if query:
- if sub_user not in query.sub_users:
- sub_users = query.sub_users + sub_user
- await query.update(sub_users=sub_users).apply()
- else:
- sub = await cls.create(
- sub_id=sub_id, sub_type=sub_type, sub_users=sub_user
- )
- await sub.update(
- live_short_id=live_short_id
- if live_short_id
- else sub.live_short_id,
- live_status=live_status if live_status else sub.live_status,
- dynamic_upload_time=dynamic_upload_time
- if dynamic_upload_time
- else sub.dynamic_upload_time,
- uid=uid if uid else sub.uid,
- uname=uname if uname else sub.uname,
- latest_video_created=latest_video_created
- if latest_video_created
- else sub.latest_video_created,
- season_update_time=season_update_time
- if season_update_time
- else sub.season_update_time,
- season_current_episode=season_current_episode
- if season_current_episode
- else sub.season_current_episode,
- season_id=season_id if season_id else sub.season_id,
- season_name=season_name if season_name else sub.season_name,
- ).apply()
- return True
- except Exception as e:
- logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
- return False
+ sub = None
+ if sub_type:
+ sub = await cls.get_or_none(sub_id=sub_id, sub_type=sub_type)
+ else:
+ sub = await cls.get_or_none(sub_id=sub_id)
+ if sub:
+ sub_users = sub.sub_users + sub_user
+ data["sub_type"] = sub_type or sub.sub_type
+ data["sub_user"] = sub_users
+ data["live_short_id"] = live_short_id or sub.live_short_id
+ data["live_status"] = (
+ live_status if live_status is not None else sub.live_status
+ )
+ data["dynamic_upload_time"] = dynamic_upload_time or sub.dynamic_upload_time
+ data["uid"] = uid or sub.uid
+ data["uname"] = uname or sub.uname
+ data["latest_video_created"] = (
+ latest_video_created or sub.latest_video_created
+ )
+ data["season_name"] = season_name or sub.season_name
+ data["season_id"] = season_id or sub.season_id
+ data["season_current_episode"] = (
+ season_current_episode or sub.season_current_episode
+ )
+ data["season_update_time"] = season_update_time or sub.season_update_time
+ else:
+ await cls.create(sub_id=sub_id, sub_type=sub_type, sub_users=sub_user)
+ await cls.update_or_create(sub_id=sub_id, defaults=data)
+ return True
+ # except Exception as e:
+ # logger.info(f"bilibili_sub 添加订阅错误 {type(e)}: {e}")
+ # return False
@classmethod
- async def delete_bilibili_sub(cls, sub_id: int, sub_user: str,sub_type: Optional[str] = None) -> bool:
+ async def delete_bilibili_sub(
+ cls, sub_id: int, sub_user: str, sub_type: Optional[str] = None
+ ) -> bool:
"""
说明:
删除订阅
@@ -116,129 +141,30 @@ class BilibiliSub(db.Model):
:param sub_user: 删除此条目的用户
"""
try:
- async with db.transaction():
- if sub_type:
- query = (
- await cls.query.where(
- (cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user) & (cls.sub_type == sub_type))
- )
- .with_for_update()
- .gino.first()
- )
- else:
- query = (
- await cls.query.where(
- (cls.sub_id == sub_id) & (cls.sub_users.contains(sub_user))
- )
- .with_for_update()
- .gino.first()
- )
- if not query:
- return False
- await query.update(
- sub_users=query.sub_users.replace(f"{sub_user},", "")
- ).apply()
- if not query.sub_users.strip():
- await query.delete()
- return True
+ if sub_type:
+ sub = await cls.filter(
+ sub_id=sub_id, sub_type=sub_type, sub_users__contains=sub_user
+ ).first()
+ else:
+ sub = await cls.filter(
+ sub_id=sub_id, sub_users__contains=sub_user
+ ).first()
+ if not sub:
+ return False
+ sub.sub_users = sub.sub_users.replace(f"{sub_user},", "")
+ if sub.sub_users.strip():
+ await sub.save(update_fields=["sub_users"])
+ else:
+ await sub.delete()
+ return True
except Exception as e:
logger.info(f"bilibili_sub 删除订阅错误 {type(e)}: {e}")
return False
- @classmethod
- async def get_sub(cls, sub_id: int) -> Optional["BilibiliSub"]:
- """
- 说明:
- 获取订阅对象
- 参数:
- :param sub_id: 订阅 id
- """
- return await cls.query.where(cls.sub_id == sub_id).gino.first()
-
- @classmethod
- async def get_sub_data(cls, id_: str) -> List["BilibiliSub"]:
- """
- 获取 id_ 订阅的所有内容
- :param id_: id
- """
- query = cls.query.where(cls.sub_users.contains(id_))
- return await query.gino.all()
-
- @classmethod
- async def update_sub_info(
- cls,
- sub_id: int,
- *,
- live_short_id: Optional[int] = None,
- live_status: Optional[int] = None,
- dynamic_upload_time: Optional[int] = None,
- uid: Optional[int] = None,
- uname: Optional[str] = None,
- latest_video_created: Optional[int] = None,
- season_name: Optional[str] = None,
- season_id: Optional[int] = None,
- season_current_episode: Optional[str] = None,
- season_update_time: Optional[datetime] = None,
- ) -> bool:
- """
- 说明:
- 更新订阅信息
- 参数:
- :param sub_id: 订阅名称,房间号,番剧号等
- :param live_short_id: 直接短 id
- :param live_status: 主播开播状态
- :param dynamic_upload_time: 主播/UP最新动态时间
- :param uid: 主播/UP uid
- :param uname: 用户名称
- :param latest_video_created: 最新视频上传时间
- :param season_name: 番剧名称
- :param season_id: 番剧 season_id
- :param season_current_episode: 番剧最新集数
- :param season_update_time: 番剧更新时间
- """
- try:
- async with db.transaction():
- sub = (
- await cls.query.where(cls.sub_id == sub_id)
- .with_for_update()
- .gino.first()
- )
- if sub:
- await sub.update(
- live_short_id=live_short_id
- if live_short_id is not None
- else sub.live_short_id,
- live_status=live_status
- if live_status is not None
- else sub.live_status,
- dynamic_upload_time=dynamic_upload_time
- if dynamic_upload_time is not None
- else sub.dynamic_upload_time,
- uid=uid if uid is not None else sub.uid,
- uname=uname if uname is not None else sub.uname,
- latest_video_created=latest_video_created
- if latest_video_created is not None
- else sub.latest_video_created,
- season_update_time=season_update_time
- if season_update_time is not None
- else sub.season_update_time,
- season_current_episode=season_current_episode
- if season_current_episode is not None
- else sub.season_current_episode,
- season_id=season_id if season_id is not None else sub.season_id,
- season_name=season_name
- if season_name is not None
- else sub.season_name,
- ).apply()
- return True
- except Exception as e:
- logger.info(f"bilibili_sub 更新订阅错误 {type(e)}: {e}")
- return False
-
@classmethod
async def get_all_sub_data(
cls,
- ) -> "List[BilibiliSub], List[BilibiliSub], List[BilibiliSub]":
+ ) -> Tuple[List["BilibiliSub"], List["BilibiliSub"], List["BilibiliSub"]]:
"""
说明:
分类获取所有数据
@@ -246,7 +172,7 @@ class BilibiliSub(db.Model):
live_data = []
up_data = []
season_data = []
- query = await cls.query.gino.all()
+ query = await cls.all()
for x in query:
if x.sub_type == "live":
live_data.append(x)
diff --git a/plugins/black_word/__init__.py b/plugins/black_word/__init__.py
index 1e1b1639..04372d59 100644
--- a/plugins/black_word/__init__.py
+++ b/plugins/black_word/__init__.py
@@ -1,28 +1,30 @@
+from datetime import datetime
+from typing import Any, Tuple
+
+from nonebot import on_command, on_message, on_regex
from nonebot.adapters.onebot.v11 import (
+ Bot,
Event,
- MessageEvent,
GroupMessageEvent,
Message,
- Bot,
+ MessageEvent,
)
from nonebot.matcher import Matcher
from nonebot.message import run_preprocessor
+from nonebot.params import CommandArg, RegexGroup
+from nonebot.permission import SUPERUSER
+
+from configs.config import NICKNAME, Config
+from models.ban_user import BanUser
+from services.log import logger
from utils.image_utils import BuildImage
from utils.manager import group_manager
-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
+from utils.utils import get_message_text, is_number
+from .data_source import set_user_punish, show_black_text_image
+from .model import BlackWord
+from .utils import black_word_manager
__zx_plugin_name__ = "敏感词检测"
__plugin_usage__ = """
@@ -38,7 +40,7 @@ usage:
设置惩罚id需要通过 '记录名单u:xxxxxxxx' 获取
指令:
记录名单
- 设置惩罚 [user_id] [id] [punish_level]
+ 设置惩罚 [user_id] [下标] [惩罚等级]
示例:记录名单
示例:记录名单u:12345678
示例:设置惩罚 12345678 1 4
@@ -150,24 +152,32 @@ async def _(
matcher: Matcher,
event: Event,
):
+ msg = get_message_text(event.json())
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
- and not get_message_text(event.json()).startswith("原神绑定")
+ and not msg.startswith("原神绑定")
):
- # 屏蔽群权限-1的群
- if isinstance(event, GroupMessageEvent) and group_manager.get_group_level(event.group_id) < 0:
- return
- 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"
+ # if str(event.user_id) not in bot.config.superusers:
+ # return logger.debug(f"超级用户跳过黑名单词汇检查 Message: {msg}", target=event.user_id)
+ if (
+ event.is_tome()
+ and matcher.plugin_name == "black_word"
+ and not await BanUser.is_ban(event.user_id)
):
- matcher.stop_propagation()
+ # 屏蔽群权限-1的群
+ if (
+ isinstance(event, GroupMessageEvent)
+ and group_manager.get_group_level(event.group_id) < 0
+ ):
+ return
+ 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()
diff --git a/plugins/black_word/model.py b/plugins/black_word/model.py
index 30d74b4e..ef746f77 100644
--- a/plugins/black_word/model.py
+++ b/plugins/black_word/model.py
@@ -1,47 +1,34 @@
-from services.db_context import db
-from typing import Optional, List
from datetime import datetime, timedelta
+from typing import List, Optional
+
+from tortoise import fields
+
+from services.db_context import Model
-class BlackWord(db.Model):
- __tablename__ = "black_word"
+class BlackWord(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)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField(null=True)
+ """群聊id"""
+ plant_text = fields.TextField()
+ """检测文本"""
+ black_word = fields.TextField()
+ """黑名单词语"""
+ punish = fields.TextField(default="")
+ """惩罚内容"""
+ punish_level = fields.IntField()
+ """惩罚等级"""
+ create_time = fields.DatetimeField(auto_now_add=True)
+ """创建时间"""
- @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(),
- )
+ class Meta:
+ table = "black_word"
+ table_description = "惩罚机制数据表"
@classmethod
async def set_user_punish(
@@ -63,17 +50,21 @@ class BlackWord(db.Model):
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()
+ user = (
+ await cls.filter(user_qq=user_qq, black_word=black_word)
+ .order_by("id")
+ .first()
+ )
elif id_:
- user_list = await query.gino.all()
+ user_list = await cls.filter(user_qq=user_qq).order_by("id").all()
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()
+ user.punish = f"{user.punish}{punish} "
+ await user.save(update_fields=["punish"])
return True
@classmethod
@@ -88,15 +79,14 @@ class BlackWord(db.Model):
: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))
+ query = cls.filter(
+ user_qq=user_qq,
+ create_time__gte=datetime.now() - timedelta(days=days),
+ punish_level__not_in=[-1],
)
if punish_level is not None:
- query = query.where(cls.punish_level == punish_level)
- return (await query.gino.first())[0]
+ query = query.filter(punish_level=punish_level)
+ return await query.count()
@classmethod
async def get_user_punish_level(cls, user_qq: int, days: int = 7) -> Optional[int]:
@@ -108,12 +98,14 @@ class BlackWord(db.Model):
: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()
+ user := await cls.filter(
+ user_qq=user_qq,
+ create_time__gte=datetime.now() - timedelta(days=days),
+ )
+ .order_by("id")
+ .first()
):
- return query.punish_level
+ return user.punish_level
return None
@classmethod
@@ -133,16 +125,18 @@ class BlackWord(db.Model):
:param date: 日期
:param date_type: 日期查询类型
"""
- query = cls.query
+ query = cls
if user_qq:
- query = query.where(cls.user_qq == user_qq)
+ query = query.filter(user_qq=user_qq)
if group_id:
- query = query.where(cls.group_id == group_id)
+ query = query.filter(group_id=group_id)
if date:
if date_type == "=":
- query = query.where(cls.create_time == date)
+ query = query.filter(
+ create_time__range=[date, date + timedelta(days=1)]
+ )
elif date_type == ">":
- query = query.where(cls.create_time > date)
+ query = query.filter(create_time__gte=date)
elif date_type == "<":
- query = query.where(cls.create_time < date)
- return await query.gino.all()
+ query = query.filter(create_time__lte=date)
+ return await query.order_by("id").all()
diff --git a/plugins/black_word/utils.py b/plugins/black_word/utils.py
index 88b45ec3..bcd42254 100644
--- a/plugins/black_word/utils.py
+++ b/plugins/black_word/utils.py
@@ -1,15 +1,18 @@
-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 import ActionFailed
-from models.group_member_info import GroupInfoUser
-from utils.http_utils import AsyncHttpx
import random
+from pathlib import Path
+from typing import Optional, Tuple, Union
+
+from nonebot.adapters.onebot.v11 import ActionFailed
+
+from configs.config import Config
+from configs.path_config import DATA_PATH
+from models.ban_user import BanUser
+from models.group_member_info import GroupInfoUser
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.utils import cn2py, get_bot
+
+from .model import BlackWord
try:
import ujson as json
@@ -49,7 +52,7 @@ class BlackWordManager:
"hanbi",
"hanpi",
"laji",
- "fw"
+ "fw",
],
"5": [],
}
@@ -94,9 +97,9 @@ class BlackWordManager:
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):
+ 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}"
)
@@ -146,8 +149,12 @@ async def _add_user_black_word(
"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
+ await BlackWord.create(
+ user_qq=user_id,
+ group_id=group_id,
+ plant_text=message,
+ black_word=black_word,
+ punish_level=punish_level,
)
logger.info(
f"已将 USER {user_id} GROUP {group_id} 添加至黑名单词汇记录 Black_word:{black_word} Plant_text:{message}"
@@ -172,7 +179,9 @@ async def _punish_handle(
# 用户周期内触发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
+ 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:
@@ -226,15 +235,17 @@ async def _get_punish(
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:
+ if user := await GroupInfoUser.get_or_none(user_qq=user_id, group_id=group_id):
+ uname = user.user_name
+ else:
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})")
+ await send_msg(
+ user_id, group_id, f"BlackWordChecker 永久ban USER {uname}({user_id})"
+ )
logger.info(f"BlackWord 永久封禁 USER {user_id}...")
# 删除好友(有的话
elif id_ == 2:
@@ -319,4 +330,7 @@ async def check_text(text: str) -> bool:
return True
-black_word_manager = BlackWordManager(DATA_PATH / "black_word" / "black_word.json", DATA_PATH / "black_word" / "black_py.json")
+black_word_manager = BlackWordManager(
+ DATA_PATH / "black_word" / "black_word.json",
+ DATA_PATH / "black_word" / "black_py.json",
+)
diff --git a/plugins/bt/data_source.py b/plugins/bt/data_source.py
index b5035e3d..a35382ae 100755
--- a/plugins/bt/data_source.py
+++ b/plugins/bt/data_source.py
@@ -1,13 +1,7 @@
-from utils.http_utils import AsyncHttpx
-from configs.config import Config
from bs4 import BeautifulSoup
-import platform
-
-# if platform.system() == "Windows":
-# import asyncio
-#
-# asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
+from configs.config import Config
+from utils.http_utils import AsyncHttpx
url = "http://www.eclzz.love"
@@ -28,10 +22,7 @@ async def get_bt_info(keyword: str, page: int):
for item in item_lst[:bt_max_num]:
divs = item.find_all("div")
title = (
- str(divs[0].find("a").text)
- .replace("", "")
- .replace("", "")
- .strip()
+ str(divs[0].find("a").text).replace("", "").replace("", "").strip()
)
spans = divs[2].find_all("span")
type_ = spans[0].text
diff --git a/plugins/genshin/almanac/__init__.py b/plugins/genshin/almanac/__init__.py
index a28a33ba..a1f29e7f 100755
--- a/plugins/genshin/almanac/__init__.py
+++ b/plugins/genshin/almanac/__init__.py
@@ -65,4 +65,4 @@ async def _():
mes = "[[_task|genshin_alc]]" + alc_img
for gid in gl:
if 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)
diff --git a/plugins/genshin/material_remind/__init__.py b/plugins/genshin/material_remind/__init__.py
index df64ee27..116e2df0 100755
--- a/plugins/genshin/material_remind/__init__.py
+++ b/plugins/genshin/material_remind/__init__.py
@@ -1,18 +1,19 @@
-from nonebot import on_command, Driver
-from nonebot.adapters.onebot.v11 import MessageEvent, Message, GroupMessageEvent
-from utils.message_builder import image
-from utils.image_utils import BuildImage
-from utils.browser import get_browser
-from configs.path_config import IMAGE_PATH
-import nonebot
-from services.log import logger
-from nonebot.permission import SUPERUSER
-from typing import List
-from datetime import datetime, timedelta
-import os
import asyncio
+import os
import time
+from datetime import datetime, timedelta
+from typing import List
+import nonebot
+from nonebot import Driver, on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
+from nonebot.permission import SUPERUSER
+
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.browser import get_browser
+from utils.image_utils import BuildImage
+from utils.message_builder import image
__zx_plugin_name__ = "原神今日素材"
__plugin_usage__ = """
@@ -56,7 +57,7 @@ async def _(event: MessageEvent):
await update_image()
await material.send(
Message(
- image(f"{file_name}.png", "genshin/material")
+ image(IMAGE_PATH / "genshin" / "material" / f"{file_name}.png")
+ "\n※ 每日素材数据来源于 genshin.pub"
)
)
@@ -163,5 +164,3 @@ def get_background_height(weapons_img: List[str]) -> int:
last_weapon.save(weapons_img[-1])
return height
-
-
diff --git a/plugins/genshin/query_user/_models/__init__.py b/plugins/genshin/query_user/_models/__init__.py
index 5c775c3f..c33b83c5 100644
--- a/plugins/genshin/query_user/_models/__init__.py
+++ b/plugins/genshin/query_user/_models/__init__.py
@@ -1,219 +1,49 @@
-from services.db_context import db
-from typing import Optional, Union, List
-from datetime import datetime, timedelta
import random
+from datetime import datetime, timedelta
+from typing import Optional
+
import pytz
+from tortoise import fields
+from tortoise.contrib.postgres.functions import Random
+
+from services.db_context import Model
-class Genshin(db.Model):
- __tablename__ = "genshin"
+class Genshin(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- uid = db.Column(db.BigInteger())
- mys_id = db.Column(db.BigInteger())
- cookie = db.Column(db.String(), default="")
- today_query_uid = db.Column(db.String(), default="") # 该cookie今日查询的uid
- auto_sign = db.Column(db.Boolean(), default=False)
- auto_sign_time = db.Column(db.DateTime(timezone=True))
- resin_remind = db.Column(db.Boolean(), default=False) # 树脂提醒
- resin_recovery_time = db.Column(db.DateTime(timezone=True)) # 满树脂提醒日期
- bind_group = db.Column(db.BigInteger())
- login_ticket = db.Column(db.String(), default="")
- stuid = db.Column(db.String(), default="")
- stoken = db.Column(db.String(), default="")
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ uid = fields.BigIntField()
+ """uid"""
+ mys_id: int = fields.BigIntField(null=True)
+ """米游社id"""
+ cookie: str = fields.TextField(default="")
+ """米游社cookie"""
+ auto_sign = fields.BooleanField(default=False)
+ """是否自动签到"""
+ today_query_uid = fields.TextField(default="")
+ """cookie今日查询uid"""
+ auto_sign_time = fields.DatetimeField(null=True)
+ """签到日期时间"""
+ resin_remind = fields.BooleanField(default=False)
+ """树脂提醒"""
+ resin_recovery_time = fields.DatetimeField(null=True)
+ """满树脂提醒日期"""
+ bind_group: int = fields.BigIntField(null=True)
+ """发送提示 绑定群聊"""
+ login_ticket = fields.TextField(default="")
+ """login_ticket"""
+ stuid: str = fields.TextField(default="")
+ """stuid"""
+ stoken: str = fields.TextField(default="")
+ """stoken"""
- _idx1 = db.Index("genshin_uid_idx1", "user_qq", "uid", unique=True)
-
- @classmethod
- async def add_uid(cls, user_qq: int, uid: int):
- """
- 说明:
- 添加一个uid
- 参数:
- :param user_qq: 用户qq
- :param uid: 原神uid
- """
- query = cls.query.where((cls.user_qq == user_qq) & (cls.uid == uid))
- user = await query.gino.first()
- if not user:
- await cls.create(
- user_qq=user_qq,
- uid=uid,
- )
- return True
- return False
-
- @classmethod
- async def set_mys_id(cls, uid: int, mys_id: int) -> bool:
- """
- 说明:
- 设置米游社id
- 参数:
- :param uid: 原神uid
- :param mys_id: 米游社id
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(mys_id=mys_id).apply()
- return True
- return False
-
- @classmethod
- async def set_bind_group(cls, uid: int, bind_group) -> bool:
- """
- 说明:
- 绑定group_id,除私聊外的提醒将在此群发送
- 参数:
- :param uid: uid
- :param bind_group: 群号
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(bind_group=bind_group).apply()
- return True
- return False
-
- @classmethod
- async def get_bind_group(cls, uid: int) -> Optional[int]:
- """
- 说明:
- 获取用户绑定的群聊
- 参数:
- :param uid: uid
- """
- user = await cls.query.where(cls.uid == uid).gino.first()
- if user:
- return user.bind_group
- return None
-
- @classmethod
- async def set_cookie(cls, uid: int, cookie: str) -> bool:
- """
- 说明:
- 设置cookie
- 参数:
- :param uid: 原神uid
- :param cookie: 米游社id
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(cookie=cookie).apply()
- return True
- return False
-
- @classmethod
- async def set_resin_remind(cls, uid: int, flag: bool) -> bool:
- """
- 说明:
- 设置体力提醒
- 参数:
- :param uid: 原神uid
- :param flag: 开关状态
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(resin_remind=flag).apply()
- return True
- return False
-
- @classmethod
- async def set_user_resin_recovery_time(cls, uid: int, date: datetime):
- """
- 说明:
- 设置体力完成时间
- 参数:
- :param uid: uid
- :param date: 提醒日期
- """
- u = await cls.query.where(cls.uid == uid).gino.first()
- if u:
- await u.update(resin_recovery_time=date).apply()
-
- @classmethod
- async def get_user_resin_recovery_time(cls, uid: int) -> Optional[datetime]:
- """
- 说明:
- 获取体力完成时间
- 参数:
- :param uid: uid
- """
- u = await cls.query.where(cls.uid == uid).gino.first()
- if u:
- return u.resin_recovery_time.astimezone(pytz.timezone("Asia/Shanghai"))
- return None
-
- @classmethod
- async def get_all_resin_remind_user(cls) -> List["Genshin"]:
- """
- 说明:
- 获取所有开启体力提醒的用户
- """
- return await cls.query.where(cls.resin_remind == True).gino.all()
-
- @classmethod
- async def clear_resin_remind_time(cls, uid: int) -> bool:
- """
- 说明:
- 清空提醒日期
- 参数:
- :param uid: uid
- """
- user = await cls.query.where(cls.uid == uid).gino.first()
- if user:
- await user.update(resin_recovery_time=None).apply()
- return True
- return False
-
- @classmethod
- async def set_auto_sign(cls, uid: int, flag: bool) -> bool:
- """
- 说明:
- 设置米游社/原神自动签到
- 参数:
- :param uid: 原神uid
- :param flag: 开关状态
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(auto_sign=flag).apply()
- return True
- return False
-
- @classmethod
- async def get_all_auto_sign_user(cls) -> List["Genshin"]:
- """
- 说明:
- 获取所有开启自动签到的用户
- """
- return await cls.query.where(cls.auto_sign == True).gino.all()
-
- @classmethod
- async def get_all_sign_user(cls) -> List["Genshin"]:
- """
- 说明:
- 获取 原神 所有今日签到用户
- """
- return await cls.query.where(cls.auto_sign_time != None).gino.all()
-
- @classmethod
- async def clear_sign_time(cls, uid: int) -> bool:
- """
- 说明:
- 清空签到日期
- 参数:
- :param uid: uid
- """
- user = await cls.query.where(cls.uid == uid).gino.first()
- if user:
- await user.update(auto_sign_time=None).apply()
- return True
- return False
+ class Meta:
+ table = "genshin"
+ table_description = "原神数据表"
+ unique_together = ("user_qq", "uid")
@classmethod
async def random_sign_time(cls, uid: int) -> Optional[datetime]:
@@ -223,262 +53,43 @@ class Genshin(db.Model):
说明:
:param uid: uid
"""
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
+ user = await cls.get_or_none(uid=uid)
if user and user.cookie:
if user.auto_sign_time and user.auto_sign_time.astimezone(
- pytz.timezone("Asia/Shanghai")
+ pytz.timezone("Asia/Shanghai")
) - timedelta(seconds=2) >= datetime.now(pytz.timezone("Asia/Shanghai")):
return user.auto_sign_time.astimezone(pytz.timezone("Asia/Shanghai"))
hours = int(str(datetime.now()).split()[1].split(":")[0])
minutes = int(str(datetime.now()).split()[1].split(":")[1])
date = (
- datetime.now()
- + timedelta(days=1)
- - timedelta(hours=hours)
- - timedelta(minutes=minutes - 1)
+ datetime.now()
+ + timedelta(days=1)
+ - timedelta(hours=hours)
+ - timedelta(minutes=minutes - 1)
)
random_hours = random.randint(0, 22)
random_minutes = random.randint(1, 59)
date += timedelta(hours=random_hours) + timedelta(minutes=random_minutes)
- await user.update(auto_sign_time=date).apply()
+ user.auto_sign_time = date
+ await user.save(update_fields=["auto_sign_time"])
return date
return None
@classmethod
- async def get_query_cookie(cls, uid: int) -> Optional[str]:
+ async def random_cookie(cls, uid: int) -> Optional[str]:
"""
说明:
- 获取查询角色信息cookie
+ 随机获取查询角色信息cookie
参数:
:param uid: 原神uid
"""
# 查找用户今日是否已经查找过,防止重复
- query = cls.query.where(cls.today_query_uid.contains(str(uid)))
- x = await query.gino.first()
- if x:
- await cls._add_query_uid(uid, uid)
- return x.cookie
- for u in await cls.query.where(cls.cookie != "").order_by(db.func.random()).gino.all():
- if not u.today_query_uid or len(u.today_query_uid[:-1].split()) < 30:
- await cls._add_query_uid(uid, u.uid)
- return u.cookie
- return None
-
- @classmethod
- async def get_user_cookie(cls, uid: int, flag: bool = False) -> Optional[str]:
- """
- 说明:
- 获取用户cookie
- 参数:
- :param uid:原神uid
- :param flag:必须使用自己的cookie
- """
- cookie = await cls._get_user_data(None, uid, "cookie")
- if not cookie and not flag:
- cookie = await cls.get_query_cookie(uid)
- return cookie
-
- @classmethod
- async def get_user_by_qq(cls, user_qq: int) -> Optional["Genshin"]:
- """
- 说明:
- 通过qq获取用户对象
- 参数:
- :param user_qq: qq
- """
- return await cls.query.where(cls.user_qq == user_qq).gino.first()
-
- @classmethod
- async def get_user_by_uid(cls, uid: int) -> Optional["Genshin"]:
- """
- 说明:
- 通过uid获取用户对象
- 参数:
- :param uid: qq
- """
- return await cls.query.where(cls.uid == uid).gino.first()
-
- @classmethod
- async def get_user_uid(cls, user_qq: int) -> Optional[int]:
- """
- 说明:
- 获取用户uid
- 参数:
- :param user_qq:用户qq
- """
- return await cls._get_user_data(user_qq, None, "uid")
-
- @classmethod
- async def get_user_mys_id(cls, uid: int) -> Optional[int]:
- """
- 说嘛:
- 获取用户米游社id
- 参数:
- :param uid:原神id
- """
- return await cls._get_user_data(None, uid, "mys_id")
-
- @classmethod
- async def delete_user_cookie(cls, uid: int):
- """
- 说明:
- 删除用户cookie
- 参数:
- :param uid: 原神uid
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
+ user = await cls.get_or_none(today_query_uid__contains=str(uid))
if user:
- await user.update(cookie="").apply()
-
- @classmethod
- async def delete_user(cls, user_qq: int):
- """
- 说明:
- 删除用户数据
- 参数:
- :param user_qq: 用户qq
- """
- query = cls.query.where(cls.user_qq == user_qq).with_for_update()
- user = await query.gino.first()
- if not user:
- return False
- await user.delete()
- return True
-
- @classmethod
- async def _add_query_uid(cls, uid: int, cookie_uid: int):
- """
- 说明:
- 添加每日查询重复uid的cookie
- 参数:
- :param uid: 原神uid
- :param cookie_uid: cookie的uid
- """
- query = cls.query.where(cls.uid == cookie_uid).with_for_update()
- user = await query.gino.first()
- await user.update(today_query_uid=user.today_query_uid + f"{uid} ").apply()
-
- @classmethod
- async def _get_user_data(
- cls, user_qq: Optional[int], uid: Optional[int], type_: str
- ) -> Optional[Union[int, str]]:
- """
- 说明:
- 获取用户数据
- 参数:
- :param user_qq: 用户qq
- :param uid: uid
- :param type_: 数据类型
- """
- if type_ == "uid":
- user = await cls.query.where(cls.user_qq == user_qq).gino.first()
- return user.uid if user else None
- user = await cls.query.where(cls.uid == uid).gino.first()
- if not user:
- return None
- if type_ == "mys_id":
- return user.mys_id
- elif type_ == "cookie":
return user.cookie
- return None
-
- @classmethod
- async def reset_today_query_uid(cls):
- for u in await cls.query.with_for_update().gino.all():
- if u.today_query_uid:
- await u.update(today_query_uid="").apply()
-
- @classmethod
- async def set_stuid(cls, uid: int, stuid: str) -> bool:
- """
- 说明:
- 设置stuid
- 参数:
- :param uid: 原神uid
- :param stuid: stuid
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(stuid=stuid).apply()
- return True
- return False
-
- @classmethod
- async def set_stoken(cls, uid: int, stoken: str) -> bool:
- """
- 说明:
- 设置stoken
- 参数:
- :param uid: 原神uid
- :param stoken: stoken
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(stoken=stoken).apply()
- return True
- return False
-
- @classmethod
- async def set_login_ticket(cls, uid: int, login_ticket: str) -> bool:
- """
- 说明:
- 设置login_ticket
- 参数:
- :param uid: 原神uid
- :param login_ticket: login_ticket
- """
- query = cls.query.where(cls.uid == uid).with_for_update()
- user = await query.gino.first()
- if user:
- await user.update(login_ticket=login_ticket).apply()
- return True
- return False
-
- # 获取login_ticket
- @classmethod
- async def get_login_ticket(cls, uid: int) -> Optional[str]:
- """
- 说明:
- 获取login_ticket
- 参数:
- :param uid: 原神uid
- """
- query = cls.query.where(cls.uid == uid)
- user = await query.gino.first()
- if user:
- return user.login_ticket
- return None
-
- # 获取stuid
- @classmethod
- async def get_stuid(cls, uid: int) -> Optional[str]:
- """
- 说明:
- 获取stuid
- 参数:
- :param uid: 原神uid
- """
- query = cls.query.where(cls.uid == uid)
- user = await query.gino.first()
- if user:
- return user.stuid
- return None
-
- # 获取stoken
- @classmethod
- async def get_stoken(cls, uid: int) -> Optional[str]:
- """
- 说明:
- 获取stoken
- 参数:
- :param uid: 原神uid
- """
- query = cls.query.where(cls.uid == uid)
- user = await query.gino.first()
- if user:
- return user.stoken
+ for user in await cls.filter(cookie__not="").annotate(rand=Random()).all():
+ if not user.today_query_uid or len(user.today_query_uid[:-1].split()) < 30:
+ user.today_query_uid = user.today_query_uid + f"{uid} "
+ await user.save(update_fields=["today_query_uid"])
+ return user.cookie
return None
diff --git a/plugins/genshin/query_user/_utils/__init__.py b/plugins/genshin/query_user/_utils/__init__.py
index 10fa36f8..8dddb2c9 100644
--- a/plugins/genshin/query_user/_utils/__init__.py
+++ b/plugins/genshin/query_user/_utils/__init__.py
@@ -1,9 +1,10 @@
-from configs.config import Config
-import json
-import time
-import random
import hashlib
+import json
+import random
import string
+import time
+
+from configs.config import Config
def _md5(text):
@@ -15,7 +16,7 @@ def _md5(text):
def get_old_ds() -> str:
n = Config.get_config("genshin", "n")
i = str(int(time.time()))
- r = ''.join(random.sample(string.ascii_lowercase + string.digits, 6))
+ r = "".join(random.sample(string.ascii_lowercase + string.digits, 6))
c = _md5("salt=" + n + "&t=" + i + "&r=" + r)
return i + "," + r + "," + c
@@ -33,7 +34,7 @@ def get_ds(q: str = "", b: dict = None) -> str:
def random_hex(length: int) -> str:
- result = hex(random.randint(0, 16 ** length)).replace("0x", "").upper()
+ result = hex(random.randint(0, 16**length)).replace("0x", "").upper()
if len(result) < length:
result = "0" * (length - len(result)) + result
return result
diff --git a/plugins/genshin/query_user/bind/__init__.py b/plugins/genshin/query_user/bind/__init__.py
index cc77b022..9c9bbaca 100644
--- a/plugins/genshin/query_user/bind/__init__.py
+++ b/plugins/genshin/query_user/bind/__init__.py
@@ -1,13 +1,16 @@
-from nonebot import on_command
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
-from utils.utils import is_number
-from .._models import Genshin
-from services.log import logger
-from nonebot.params import CommandArg, Command
-from typing import Tuple
-from utils.http_utils import AsyncHttpx
import json
+from typing import Tuple
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Command, CommandArg
+
+from services.log import logger
+from utils.depends import OneCommand
+from utils.http_utils import AsyncHttpx
+from utils.utils import is_number
+
+from .._models import Genshin
__zx_plugin_name__ = "原神绑定"
__plugin_usage__ = """
@@ -43,82 +46,94 @@ unbind = on_command("原神解绑", priority=5, block=True)
web_Api = "https://api-takumi.mihoyo.com"
bbs_Cookie_url = "https://webapi.account.mihoyo.com/Api/cookie_accountinfo_by_loginticket?login_ticket={}"
-bbs_Cookie_url2 = web_Api + "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
+bbs_Cookie_url2 = (
+ web_Api
+ + "/auth/api/getMultiTokenByLoginTicket?login_ticket={}&token_types=3&uid={}"
+)
@bind.handle()
-async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
- cmd = cmd[0]
+async def _(event: MessageEvent, cmd: str = OneCommand(), arg: Message = CommandArg()):
msg = arg.extract_plain_text().strip()
+ user = await Genshin.get_or_none(user_qq=event.user_id)
if cmd in ["原神绑定uid", "原神绑定米游社id"]:
if not is_number(msg):
await bind.finish("uid/id必须为纯数字!", at_senders=True)
msg = int(msg)
if cmd == "原神绑定uid":
- uid = await Genshin.get_user_uid(event.user_id)
- if uid:
- await bind.finish(f"您已绑定过uid:{uid},如果希望更换uid,请先发送原神解绑")
- flag = await Genshin.add_uid(event.user_id, msg)
- if not flag:
+ if user:
+ await bind.finish(f"您已绑定过uid:{user.uid},如果希望更换uid,请先发送原神解绑")
+ if await Genshin.get_or_none(user_qq=event.user_id, uid=msg):
await bind.finish("添加失败,该uid可能已存在...")
+ user = await Genshin.create(user_qq=event.user_id, uid=msg)
_x = f"已成功添加原神uid:{msg}"
elif cmd == "原神绑定米游社id":
- uid = await Genshin.get_user_uid(event.user_id)
- if not uid:
+ if not user:
await bind.finish("请先绑定原神uid..")
- await Genshin.set_mys_id(uid, msg)
- _x = f"已成功为uid:{uid} 设置米游社id:{msg}"
+ user.mys_id = int(msg)
+ _x = f"已成功为uid:{user.uid} 设置米游社id:{msg}"
else:
if not msg:
- await bind.finish("""私聊发送!!
+ await bind.finish(
+ """私聊发送!!
1.以无痕模式打开浏览器(Edge请新建InPrivate窗口)
- 2.打开http://bbs.mihoyo.com/ys/并登陆
+ 2.打开http://bbs.mihoyo.com/ys/ 并登陆
3.登陆后打开http://user.mihoyo.com/进行登陆
4.按下F12,打开控制台,输入以下命令:
var cookie=document.cookie;var ask=confirm('Cookie:'+cookie+'\\n\\nDo you want to copy the cookie to the clipboard?');if(ask==true){copy(cookie);msg=cookie}else{msg='Cancel'}
- 5.私聊发送:原神绑定cookie 刚刚复制的cookie""")
+ 5.私聊发送:原神绑定cookie 刚刚复制的cookie"""
+ )
if isinstance(event, GroupMessageEvent):
await bind.finish("请立即撤回你的消息并私聊发送!")
- uid = await Genshin.get_user_uid(event.user_id)
- if not uid:
+ if not user:
await bind.finish("请先绑定原神uid..")
if msg.startswith('"') or msg.startswith("'"):
msg = msg[1:]
if msg.endswith('"') or msg.endswith("'"):
msg = msg[:-1]
- await Genshin.set_cookie(uid, msg)
cookie = msg
# 用: 代替=, ,代替;
- cookie = '{"' + cookie.replace('=', '": "').replace("; ", '","') + '"}'
- print(cookie)
+ cookie = '{"' + cookie.replace("=", '": "').replace("; ", '","') + '"}'
+ # print(cookie)
cookie_json = json.loads(cookie)
- print(cookie_json)
- if 'login_ticket' not in cookie_json:
+ # print(cookie_json)
+ if "login_ticket" not in cookie_json:
await bind.finish("请发送正确完整的cookie!")
- login_ticket = cookie_json['login_ticket']
+ user.cookie = str(msg)
+ login_ticket = cookie_json["login_ticket"]
# try:
res = await AsyncHttpx.get(url=bbs_Cookie_url.format(login_ticket))
res.encoding = "utf-8"
data = json.loads(res.text)
- print(data)
+ # print(data)
if "成功" in data["data"]["msg"]:
stuid = str(data["data"]["cookie_info"]["account_id"])
- res = await AsyncHttpx.get(url=bbs_Cookie_url2.format(
- login_ticket, stuid))
+ res = await AsyncHttpx.get(url=bbs_Cookie_url2.format(login_ticket, stuid))
res.encoding = "utf-8"
data = json.loads(res.text)
stoken = data["data"]["list"][0]["token"]
# await Genshin.set_cookie(uid, cookie)
- await Genshin.set_stoken(uid, stoken)
- await Genshin.set_stuid(uid, stuid)
- await Genshin.set_login_ticket(uid, login_ticket)
+ user.stoken = stoken
+ user.stuid = stuid
+ user.login_ticket = login_ticket
# except Exception as e:
# await bind.finish("获取登陆信息失败,请检查cookie是否正确或更新cookie")
elif data["data"]["msg"] == "登录信息已失效,请重新登录":
await bind.finish("登录信息失效,请重新获取最新cookie进行绑定")
- _x = f"已成功为uid:{uid} 设置cookie"
+ _x = f"已成功为uid:{user.uid} 设置cookie"
if isinstance(event, GroupMessageEvent):
- await Genshin.set_bind_group(uid, event.group_id)
+ user.bind_group = event.group_id
+ if user:
+ await user.save(
+ update_fields=[
+ "mys_id",
+ "cookie",
+ "stoken",
+ "stuid",
+ "login_ticket",
+ "bind_group",
+ ]
+ )
await bind.send(_x)
logger.info(
f"(USER {event.user_id}, "
@@ -129,12 +144,10 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message
@unbind.handle()
async def _(event: MessageEvent):
- if await Genshin.delete_user(event.user_id):
- await unbind.send("用户数据删除成功...")
- logger.info(
- f"(USER {event.user_id}, GROUP "
- f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f"原神解绑"
- )
- else:
- await unbind.send("该用户数据不存在..")
+ await Genshin.filter(user_qq=event.user_id).delete()
+ await unbind.send("用户数据删除成功...")
+ logger.info(
+ f"(USER {event.user_id}, GROUP "
+ f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
+ f"原神解绑"
+ )
diff --git a/plugins/genshin/query_user/genshin_sign/__init__.py b/plugins/genshin/query_user/genshin_sign/__init__.py
index 99585662..79a76c31 100644
--- a/plugins/genshin/query_user/genshin_sign/__init__.py
+++ b/plugins/genshin/query_user/genshin_sign/__init__.py
@@ -1,14 +1,17 @@
-from .data_source import get_sign_reward_list, genshin_sign
-from ..mihoyobbs_sign import mihoyobbs_sign
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
-from nonebot import on_command
-from services.log import logger
-from .init_task import add_job, scheduler, _sign
-from apscheduler.jobstores.base import JobLookupError
-from .._models import Genshin
-from nonebot.params import Command
from typing import Tuple
+from apscheduler.jobstores.base import JobLookupError
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+from nonebot.params import Command
+
+from services.log import logger
+from utils.depends import OneCommand
+
+from .._models import Genshin
+from ..mihoyobbs_sign import mihoyobbs_sign
+from .data_source import genshin_sign, get_sign_reward_list
+from .init_task import _sign, add_job, scheduler
__zx_plugin_name__ = "原神自动签到"
__plugin_usage__ = """
@@ -39,45 +42,46 @@ genshin_matcher = on_command(
@genshin_matcher.handle()
-async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
- cmd = cmd[0]
- uid = await Genshin.get_user_uid(event.user_id)
+async def _(event: MessageEvent, cmd: str = OneCommand()):
+ user = await Genshin.get_or_none(user_qq=event.user_id)
+ if not user:
+ await genshin_matcher.finish("请先绑定user.uid...")
if cmd == "查看我的cookie":
- my_cookie = await Genshin.get_user_cookie(uid, True)
if isinstance(event, GroupMessageEvent):
await genshin_matcher.finish("请私聊查看您的cookie!")
- await genshin_matcher.finish("您的cookie为" + my_cookie)
- if not uid or not await Genshin.get_user_cookie(uid, True):
- await genshin_matcher.finish("请先绑定uid和cookie!")
- # if "account_id" not in await Genshin.get_user_cookie(uid, True):
+ await genshin_matcher.finish("您的cookie为" + user.cookie)
+ if not user.uid or not user.cookie:
+ await genshin_matcher.finish("请先绑定user.uid和cookie!")
+ # if "account_id" not in await Genshin.get_user_cookie(user.uid, True):
# await genshin_matcher.finish("请更新cookie!")
if cmd == "原神我硬签":
try:
await genshin_matcher.send("正在进行签到...", at_sender=True)
- msg = await genshin_sign(uid)
+ msg = await genshin_sign(user.uid)
return_data = await mihoyobbs_sign(event.user_id)
logger.info(
f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到"
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{user.uid} 原神签到"
)
logger.info(msg)
# 硬签,移除定时任务
try:
for i in range(3):
- scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}",)
+ scheduler.remove_job(
+ f"genshin_auto_sign_{user.uid}_{event.user_id}_{i}",
+ )
except JobLookupError:
pass
- u = await Genshin.get_user_by_uid(uid)
- if u and u.auto_sign:
- await u.clear_sign_time(uid)
- next_date = await Genshin.random_sign_time(uid)
- add_job(event.user_id, uid, next_date)
+ if user.auto_sign:
+ user.auto_sign_time = None
+ next_date = await Genshin.random_sign_time(user.uid)
+ add_job(event.user_id, user.uid, next_date)
msg += f"\n{return_data}\n因开启自动签到\n下一次签到时间为:{next_date.replace(microsecond=0)}"
except Exception as e:
msg = "原神签到失败..请尝试检查cookie或报告至管理员!"
logger.info(
f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{uid} 原神签到发生错误 "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) UID:{user.uid} 原神签到发生错误 "
f"{type(e)}:{e}"
)
msg = msg or "请检查cookie是否更新!"
@@ -85,13 +89,16 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
else:
for i in range(3):
try:
- scheduler.remove_job(f"genshin_auto_sign_{uid}_{event.user_id}_{i}")
+ scheduler.remove_job(
+ f"genshin_auto_sign_{user.uid}_{event.user_id}_{i}"
+ )
except JobLookupError:
pass
if cmd[0] == "开":
- await Genshin.set_auto_sign(uid, True)
- next_date = await Genshin.random_sign_time(uid)
- add_job(event.user_id, uid, next_date)
+ next_date = await Genshin.random_sign_time(user.uid)
+ user.auto_sign = True
+ user.auto_sign_time = next_date
+ add_job(event.user_id, user.uid, next_date)
await genshin_matcher.send(
f"已开启原神自动签到!\n下一次签到时间为:{next_date.replace(microsecond=0)}",
at_sender=True,
@@ -102,11 +109,13 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
f" 开启原神自动签到"
)
else:
- await Genshin.set_auto_sign(uid, False)
- await Genshin.clear_sign_time(uid)
+ user.auto_sign = False
+ user.auto_sign_time = None
await genshin_matcher.send(f"已关闭原神自动签到!", at_sender=True)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 关闭原神自动签到"
)
+ if user:
+ await user.save(update_fields=["auto_sign_time", "auto_sign"])
diff --git a/plugins/genshin/query_user/genshin_sign/data_source.py b/plugins/genshin/query_user/genshin_sign/data_source.py
index ba39e1e0..1dbaac4c 100644
--- a/plugins/genshin/query_user/genshin_sign/data_source.py
+++ b/plugins/genshin/query_user/genshin_sign/data_source.py
@@ -1,14 +1,16 @@
-from utils.http_utils import AsyncHttpx
-from configs.config import Config
-from services.log import logger
-from ..mihoyobbs_sign.setting import *
-from .._models import Genshin
-from typing import Optional, Dict
import hashlib
import random
import string
-import uuid
import time
+import uuid
+from typing import Dict, Optional
+
+from configs.config import Config
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+
+from .._models import Genshin
+from ..mihoyobbs_sign.setting import *
async def genshin_sign(uid: int) -> Optional[str]:
@@ -28,10 +30,10 @@ async def genshin_sign(uid: int) -> Optional[str]:
sign_list = await get_sign_reward_list()
get_reward = sign_list["data"]["awards"][
int(sign_info["total_sign_day"]) - 1
- ]["name"]
+ ]["name"]
reward_num = sign_list["data"]["awards"][
int(sign_info["total_sign_day"]) - 1
- ]["cnt"]
+ ]["cnt"]
get_im = f"本次签到获得:{get_reward}x{reward_num}"
logger.info("get_im:" + get_im + "\nsign_info:" + str(sign_info))
if status == "OK" and sign_info["is_sign"]:
@@ -64,7 +66,7 @@ def timestamp() -> int:
def random_text(num: int) -> str:
- return ''.join(random.sample(string.ascii_lowercase + string.digits, num))
+ return "".join(random.sample(string.ascii_lowercase + string.digits, num))
def md5(text: str) -> str:
@@ -75,8 +77,7 @@ def md5(text: str) -> str:
# 生成一个device id
def get_device_id(cookie) -> str:
- return str(uuid.uuid3(uuid.NAMESPACE_URL, cookie)).replace(
- '-', '').upper()
+ return str(uuid.uuid3(uuid.NAMESPACE_URL, cookie)).replace("-", "").upper()
async def _sign(uid: int, server_id: str = "cn_gf01") -> Optional[Dict[str, str]]:
@@ -88,18 +89,20 @@ async def _sign(uid: int, server_id: str = "cn_gf01") -> Optional[Dict[str, str]
if str(uid)[0] == "5":
server_id = "cn_qd01"
try:
- cookie = await Genshin.get_user_cookie(uid, True)
- headers['DS'] = get_ds(web=True)
- headers['Referer'] = 'https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true' \
- f'&act_id={genshin_Act_id}&utm_source=bbs&utm_medium=mys&utm_campaign=icon'
- headers['Cookie'] = cookie
- headers['x-rpc-device_id'] = get_device_id(cookie)
- req = await AsyncHttpx.post(
- url=genshin_Signurl,
- headers=headers,
- json={"act_id": genshin_Act_id, "uid": uid, "region": server_id},
- )
- return req.json()
+ if user := await Genshin.get_or_none(uid=uid):
+ headers["DS"] = get_ds(web=True)
+ headers["Referer"] = (
+ "https://webstatic.mihoyo.com/bbs/event/signin-ys/index.html?bbs_auth_required=true"
+ f"&act_id={genshin_Act_id}&utm_source=bbs&utm_medium=mys&utm_campaign=icon"
+ )
+ headers["Cookie"] = user.cookie
+ headers["x-rpc-device_id"] = get_device_id(user.cookie)
+ req = await AsyncHttpx.post(
+ url=genshin_Signurl,
+ headers=headers,
+ json={"act_id": genshin_Act_id, "uid": uid, "region": server_id},
+ )
+ return req.json()
except Exception as e:
logger.error(f"米游社签到发生错误 UID:{uid} {type(e)}:{e}")
return None
@@ -129,17 +132,22 @@ async def _get_sign_info(uid: int, server_id: str = "cn_gf01"):
if str(uid)[0] == "5":
server_id = "cn_qd01"
try:
- req = await AsyncHttpx.get(
- url=f"https://api-takumi.mihoyo.com/event/bbs_sign_reward/info?act_id=e202009291139501®ion={server_id}&uid={uid}",
- headers={
- "x-rpc-app_version": str(Config.get_config("genshin", "mhyVersion")),
- "Cookie": await Genshin.get_user_cookie(int(uid), True),
- "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
- "x-rpc-client_type": str(Config.get_config("genshin", "client_type")),
- "Referer": "https://webstatic.mihoyo.com/",
- },
- )
- return req.json()
+ if user := await Genshin.get_or_none(uid=uid):
+ req = await AsyncHttpx.get(
+ url=f"https://api-takumi.mihoyo.com/event/bbs_sign_reward/info?act_id=e202009291139501®ion={server_id}&uid={uid}",
+ headers={
+ "x-rpc-app_version": str(
+ Config.get_config("genshin", "mhyVersion")
+ ),
+ "Cookie": user.cookie,
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": str(
+ Config.get_config("genshin", "client_type")
+ ),
+ "Referer": "https://webstatic.mihoyo.com/",
+ },
+ )
+ return req.json()
except Exception as e:
logger.error(f"获取签到信息发生错误 UID:{uid} {type(e)}:{e}")
return None
diff --git a/plugins/genshin/query_user/genshin_sign/init_task.py b/plugins/genshin/query_user/genshin_sign/init_task.py
index b1453400..318a0867 100644
--- a/plugins/genshin/query_user/genshin_sign/init_task.py
+++ b/plugins/genshin/query_user/genshin_sign/init_task.py
@@ -1,17 +1,19 @@
-from .data_source import genshin_sign
-from ..mihoyobbs_sign import mihoyobbs_sign
-from models.group_member_info import GroupInfoUser
-from utils.message_builder import at
-from services.log import logger
-from utils.utils import scheduler, get_bot
-from apscheduler.jobstores.base import ConflictingIdError
-from .._models import Genshin
-from datetime import datetime, timedelta
-from nonebot import Driver
-import nonebot
import random
-import pytz
+from datetime import datetime, timedelta
+import nonebot
+import pytz
+from apscheduler.jobstores.base import ConflictingIdError
+from nonebot import Driver
+
+from models.group_member_info import GroupInfoUser
+from services.log import logger
+from utils.message_builder import at
+from utils.utils import get_bot, scheduler
+
+from .._models import Genshin
+from ..mihoyobbs_sign import mihoyobbs_sign
+from .data_source import genshin_sign
driver: Driver = nonebot.get_driver()
@@ -21,7 +23,7 @@ async def _():
"""
启动时分配定时任务
"""
- g_list = await Genshin.get_all_auto_sign_user()
+ g_list = await Genshin.filter(auto_sign=True).all()
for u in g_list:
if u.auto_sign_time:
if date := await Genshin.random_sign_time(u.uid):
@@ -33,7 +35,8 @@ async def _():
args=[u.user_qq, u.uid, 0],
)
logger.info(
- f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} " f"{date} 原神自动签到"
+ f"genshin_sign add_job:USER:{u.user_qq} UID:{u.uid} "
+ f"{date} 原神自动签到"
)
@@ -110,10 +113,12 @@ async def _sign(user_id: int, uid: int, count: int):
await bot.send_private_msg(user_id=user_id, message=return_data)
await bot.send_private_msg(user_id=user_id, message=msg)
else:
- if not (group_id := await Genshin.get_bind_group(uid)):
- group_list = await GroupInfoUser.get_user_all_group(user_id)
- if group_list:
- group_id = group_list[0]
- await bot.send_group_msg(
- group_id=group_id, message=at(user_id) + msg
- )
+ if user := await Genshin.get_or_none(uid=uid):
+ group_id = user.bind_group
+ if not group_id:
+ if group_list := await GroupInfoUser.get_user_all_group(user_id):
+ group_id = group_list[0]
+ if group_id:
+ await bot.send_group_msg(
+ group_id=group_id, message=at(user_id) + msg
+ )
diff --git a/plugins/genshin/query_user/mihoyobbs_sign/__init__.py b/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
index 4298183c..e98d67cd 100644
--- a/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
+++ b/plugins/genshin/query_user/mihoyobbs_sign/__init__.py
@@ -1,14 +1,16 @@
-from nonebot.adapters.onebot.v11 import MessageEvent
+from typing import Tuple
+
from nonebot import on_command
+from nonebot.adapters.onebot.v11 import MessageEvent
+from nonebot.params import Command
+
from services.log import logger
+
# from .init_task import add_job, scheduler, _sign
# from apscheduler.jobstores.base import JobLookupError
from .._models import Genshin
-from nonebot.params import Command
-from typing import Tuple
from .mihoyobbs import *
-
__zx_plugin_name__ = "米游社自动签到"
__plugin_usage__ = """
usage:
@@ -28,12 +30,10 @@ __plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
- "cmd": ["原神签到"],
+ "cmd": ["米游社签到"],
}
-mihoyobbs_matcher = on_command(
- "米游社签到", aliases={"米游社我硬签"}, priority=5, block=True
-)
+mihoyobbs_matcher = on_command("米游社签到", aliases={"米游社我硬签"}, priority=5, block=True)
@mihoyobbs_matcher.handle()
@@ -47,24 +47,29 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
async def mihoyobbs_sign(user_id):
- uid = await Genshin.get_user_uid(user_id)
- if not uid or not await Genshin.get_user_cookie(uid, True):
+ user = await Genshin.get_or_none(user_qq=user_id)
+ if not user or not user.uid or not user.cookie:
await mihoyobbs_matcher.finish("请先绑定uid和cookie!", at_sender=True)
- stuid = await Genshin.get_stuid(uid)
- stoken = await Genshin.get_stoken(uid)
- cookie = await Genshin.get_user_cookie(uid)
- bbs = mihoyobbs.Mihoyobbs(stuid=stuid, stoken=stoken, cookie=cookie)
+ bbs = mihoyobbs.Mihoyobbs(stuid=user.stuid, stoken=user.stoken, cookie=user.cookie)
await bbs.init()
return_data = ""
- if bbs.Task_do["bbs_Sign"] and bbs.Task_do["bbs_Read_posts"] and bbs.Task_do["bbs_Like_posts"] and \
- bbs.Task_do["bbs_Share"]:
- return_data += f"今天的米游社签到任务已经全部完成了!\n" \
- f"一共获得{mihoyobbs.today_have_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
- logger.info(f"今天已经全部完成了!一共获得{mihoyobbs.today_have_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币")
+ if (
+ bbs.Task_do["bbs_Sign"]
+ and bbs.Task_do["bbs_Read_posts"]
+ and bbs.Task_do["bbs_Like_posts"]
+ and bbs.Task_do["bbs_Share"]
+ ):
+ return_data += (
+ f"今天的米游社签到任务已经全部完成了!\n"
+ f"一共获得{mihoyobbs.today_have_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
+ )
+ logger.info(
+ f"今天已经全部完成了!一共获得{mihoyobbs.today_have_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币"
+ )
else:
i = 0
- print("开始签到")
- print(mihoyobbs.today_have_get_coins)
+ # print("开始签到")
+ # print(mihoyobbs.today_have_get_coins)
while mihoyobbs.today_get_coins != 0 and i < 3:
# if i > 0:
await bbs.refresh_list()
@@ -74,8 +79,12 @@ async def mihoyobbs_sign(user_id):
await bbs.share_post()
await bbs.get_tasks_list()
i += 1
- return_data += "\n" + f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币\n" \
- f"还能获得{mihoyobbs.today_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
- logger.info(f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币,"
- f"还能获得{mihoyobbs.today_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币")
+ return_data += (
+ "\n" + f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币\n"
+ f"还能获得{mihoyobbs.today_get_coins}个米游币\n目前有{mihoyobbs.Have_coins}个米游币"
+ )
+ logger.info(
+ f"今天已经获得{mihoyobbs.today_have_get_coins}个米游币,"
+ f"还能获得{mihoyobbs.today_get_coins}个米游币,目前有{mihoyobbs.Have_coins}个米游币"
+ )
return return_data
diff --git a/plugins/genshin/query_user/query_memo/__init__.py b/plugins/genshin/query_user/query_memo/__init__.py
index 3d66f3bf..5331c2bf 100644
--- a/plugins/genshin/query_user/query_memo/__init__.py
+++ b/plugins/genshin/query_user/query_memo/__init__.py
@@ -1,9 +1,10 @@
from nonebot import on_command
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
-from services.log import logger
-from .data_source import get_user_memo, get_memo
-from .._models import Genshin
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+from services.log import logger
+
+from .._models import Genshin
+from .data_source import get_memo, get_user_memo
__zx_plugin_name__ = "原神便笺查询"
__plugin_usage__ = """
@@ -27,30 +28,27 @@ __plugin_settings__ = {
__plugin_block_limit__ = {}
-query_memo_matcher = on_command("原神便签查询", aliases={"原神便笺查询", "yss"}, priority=5, block=True)
+query_memo_matcher = on_command(
+ "原神便签查询", aliases={"原神便笺查询", "yss"}, priority=5, block=True
+)
@query_memo_matcher.handle()
async def _(event: MessageEvent):
- uid = await Genshin.get_user_uid(event.user_id)
- if not uid or not await Genshin.get_user_cookie(uid, True):
+ user = await Genshin.get_or_none(user_qq=event.user_id)
+ if not user or not user.uid or not user.cookie:
await query_memo_matcher.finish("请先绑定uid和cookie!")
if isinstance(event, GroupMessageEvent):
uname = event.sender.card or event.sender.nickname
else:
uname = event.sender.nickname
- data = await get_user_memo(event.user_id, uid, uname)
+ data = await get_user_memo(event.user_id, user.uid, uname)
if data:
await query_memo_matcher.send(data)
logger.info(
f"(USER {event.user_id}, "
f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
- f"使用原神便笺查询 uid:{uid}"
+ f"使用原神便笺查询 uid:{user.uid}"
)
else:
await query_memo_matcher.send("未查询到数据...")
-
-
-
-
-
diff --git a/plugins/genshin/query_user/query_memo/data_source.py b/plugins/genshin/query_user/query_memo/data_source.py
index e1e1c25a..f7fe592f 100644
--- a/plugins/genshin/query_user/query_memo/data_source.py
+++ b/plugins/genshin/query_user/query_memo/data_source.py
@@ -1,20 +1,22 @@
-from typing import Optional, Union
-from nonebot.adapters.onebot.v11 import MessageSegment
-from configs.config import Config
-from asyncio.exceptions import TimeoutError
-from services.log import logger
-from configs.path_config import IMAGE_PATH
-from utils.image_utils import BuildImage
-from utils.http_utils import AsyncHttpx
-from utils.utils import get_user_avatar
-from utils.message_builder import image
-from .._utils import get_ds
-from .._models import Genshin
-from io import BytesIO
-from nonebot import Driver
import asyncio
-import nonebot
+from asyncio.exceptions import TimeoutError
+from io import BytesIO
+from typing import Optional, Tuple, Union
+import nonebot
+from nonebot import Driver
+from nonebot.adapters.onebot.v11 import MessageSegment
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import BuildImage
+from utils.message_builder import image
+from utils.utils import get_user_avatar
+
+from .._models import Genshin
+from .._utils import get_ds
driver: Driver = nonebot.get_driver()
@@ -26,10 +28,7 @@ memo_path.mkdir(exist_ok=True, parents=True)
@driver.on_startup
async def _():
for name, url in zip(
- [
- "resin.png", "task.png", "resin_discount.png", "chengehu.png",
- "zhibian.png"
- ],
+ ["resin.png", "task.png", "resin_discount.png", "chengehu.png", "zhibian.png"],
[
"https://upload-bbs.mihoyo.com/upload/2021/09/29/8819732/54266243c7d15ba31690c8f5d63cc3c6_71491376413333325"
"20.png?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,png",
@@ -45,8 +44,9 @@ async def _():
logger.info(f"已下载原神便签资源 -> {file}...")
-async def get_user_memo(user_id: int, uid: int,
- uname: str) -> Optional[Union[str, MessageSegment]]:
+async def get_user_memo(
+ user_id: int, uid: int, uname: str
+) -> Optional[Union[str, MessageSegment]]:
uid = str(uid)
if uid[0] in ["1", "2"]:
server_id = "cn_gf01"
@@ -57,21 +57,17 @@ async def get_user_memo(user_id: int, uid: int,
return await parse_data_and_draw(user_id, uid, server_id, uname)
-async def get_memo(uid: str, server_id: str) -> "Union[str, dict], int":
+async def get_memo(uid: str, server_id: str) -> Tuple[Union[str, dict], int]:
try:
req = await AsyncHttpx.get(
- url=
- f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/dailyNote?server={server_id}&role_id={uid}",
+ url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/dailyNote?server={server_id}&role_id={uid}",
headers={
"DS": get_ds(f"role_id={uid}&server={server_id}"),
- "x-rpc-app_version": Config.get_config("genshin",
- "mhyVersion"),
- "User-Agent":
- "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
- "x-rpc-client_type": Config.get_config("genshin",
- "client_type"),
+ "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": Config.get_config("genshin", "client_type"),
"Referer": "https://webstatic.mihoyo.com/",
- "Cookie": await Genshin.get_user_cookie(int(uid))
+ "Cookie": await Genshin.random_cookie(uid),
},
)
data = req.json()
@@ -85,18 +81,13 @@ async def get_memo(uid: str, server_id: str) -> "Union[str, dict], int":
return "发生了一些错误,请稍后再试", 998
-def create_border(image_name: str, content: str, notice_text: str,
- value: str) -> BuildImage:
- border = BuildImage(500,
- 75,
- color="#E0D9D1",
- font="HYWenHei-85W.ttf",
- font_size=20)
- text_bk = BuildImage(350,
- 75,
- color="#F5F1EB",
- font_size=23,
- font="HYWenHei-85W.ttf")
+def create_border(
+ image_name: str, content: str, notice_text: str, value: str
+) -> BuildImage:
+ border = BuildImage(500, 75, color="#E0D9D1", font="HYWenHei-85W.ttf", font_size=20)
+ text_bk = BuildImage(
+ 350, 75, color="#F5F1EB", font_size=23, font="HYWenHei-85W.ttf"
+ )
_x = 70 if image_name == "resin.png" else 50
_px = 10 if image_name == "resin.png" else 20
text_bk.paste(
@@ -119,15 +110,14 @@ def create_border(image_name: str, content: str, notice_text: str,
True,
)
font_width, _ = border.getsize(value)
- border.text((350 + 76 - int(font_width / 2), 0),
- value,
- center_type="by_height")
+ border.text((350 + 76 - int(font_width / 2), 0), value, center_type="by_height")
border.paste(text_bk, (2, 0), center_type="by_height")
return border
-async def parse_data_and_draw(user_id: int, uid: str, server_id: str,
- uname: str) -> Union[str, MessageSegment]:
+async def parse_data_and_draw(
+ user_id: int, uid: str, server_id: str, uname: str
+) -> Union[str, MessageSegment]:
data, code = await get_memo(uid, server_id)
if code != 200:
return data
@@ -138,11 +128,13 @@ async def parse_data_and_draw(user_id: int, uid: str, server_id: str,
if not role_avatar.exists():
await AsyncHttpx.download_file(x["avatar_side_icon"], role_avatar)
return await asyncio.get_event_loop().run_in_executor(
- None, _parse_data_and_draw, data, user_avatar, uid, uname)
+ None, _parse_data_and_draw, data, user_avatar, uid, uname
+ )
-def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
- uname: str) -> Union[str, MessageSegment]:
+def _parse_data_and_draw(
+ data: dict, user_avatar: BytesIO, uid: int, uname: str
+) -> Union[str, MessageSegment]:
current_resin = data["current_resin"] # 当前树脂
max_resin = data["max_resin"] # 最大树脂
resin_recovery_time = data["resin_recovery_time"] # 树脂全部回复时间
@@ -157,33 +149,24 @@ def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
max_coin = data["max_home_coin"] # 最大宝钱
coin_recovery_time = data["home_coin_recovery_time"] # 宝钱全部回复时间
transformer_available = data["transformer"]["obtained"] # 参量质变仪可获取
- transformer_state = data["transformer"]["recovery_time"][
- "reached"] # 参量质变仪状态
- transformer_recovery_time = data["transformer"]["recovery_time"][
- "Day"] # 参量质变仪回复时间
+ transformer_state = data["transformer"]["recovery_time"]["reached"] # 参量质变仪状态
+ transformer_recovery_time = data["transformer"]["recovery_time"]["Day"] # 参量质变仪回复时间
transformer_recovery_hour = data["transformer"]["recovery_time"][
- "Hour"] # 参量质变仪回复时间
+ "Hour"
+ ] # 参量质变仪回复时间
coin_minute, coin_second = divmod(int(coin_recovery_time), 60)
coin_hour, coin_minute = divmod(coin_minute, 60)
- #print(data)
+ # print(data)
minute, second = divmod(int(resin_recovery_time), 60)
hour, minute = divmod(minute, 60)
- A = BuildImage(1030,
- 570,
- color="#f1e9e1",
- font_size=15,
- font="HYWenHei-85W.ttf")
+ A = BuildImage(1030, 570, color="#f1e9e1", font_size=15, font="HYWenHei-85W.ttf")
A.text((10, 15), "原神便笺 | Create By ZhenXun", (198, 186, 177))
ava = BuildImage(100, 100, background=user_avatar)
ava.circle()
A.paste(ava, (40, 40), True)
A.paste(
- BuildImage(0,
- 0,
- plain_text=uname,
- font_size=20,
- font="HYWenHei-85W.ttf"),
+ BuildImage(0, 0, plain_text=uname, font_size=20, font="HYWenHei-85W.ttf"),
(160, 62),
True,
)
@@ -225,40 +208,39 @@ def _parse_data_and_draw(data: dict, user_avatar: BytesIO, uid: int,
"chengehu.png",
"洞天财翁-洞天宝钱",
"洞天财翁已达到存储上限"
- if current_coin == max_coin else f"{coin_hour}小时{coin_minute}分钟后存满",
+ if current_coin == max_coin
+ else f"{coin_hour}小时{coin_minute}分钟后存满",
f"{current_coin}/{max_coin}",
)
A.paste(border, (10, 395))
border = create_border(
"zhibian.png",
"参量质变仪",
- "不存在" if not transformer_available else
- "已准备完成 " if transformer_state else f"{transformer_recovery_hour}小时后可使用" if not transformer_recovery_time else f"{transformer_recovery_time}天后可使用",
- "不存在" if not transformer_available else
- "可使用" if transformer_state else "冷却中",
+ "不存在"
+ if not transformer_available
+ else "已准备完成 "
+ if transformer_state
+ else f"{transformer_recovery_hour}小时后可使用"
+ if not transformer_recovery_time
+ else f"{transformer_recovery_time}天后可使用",
+ "不存在" if not transformer_available else "可使用" if transformer_state else "冷却中",
)
A.paste(border, (10, 475))
- expeditions_border = BuildImage(470,
- 510,
- color="#E0D9D1",
- font="HYWenHei-85W.ttf",
- font_size=20)
- expeditions_text = BuildImage(466,
- 506,
- color="#F5F1EB",
- font_size=23,
- font="HYWenHei-85W.ttf")
+ expeditions_border = BuildImage(
+ 470, 510, color="#E0D9D1", font="HYWenHei-85W.ttf", font_size=20
+ )
+ expeditions_text = BuildImage(
+ 466, 506, color="#F5F1EB", font_size=23, font="HYWenHei-85W.ttf"
+ )
expeditions_text.text(
- (5, 5), f"探索派遣限制{current_expedition_num}/{max_expedition_num}",
- (100, 100, 98))
+ (5, 5), f"探索派遣限制{current_expedition_num}/{max_expedition_num}", (100, 100, 98)
+ )
h = 45
for x in expeditions:
- _bk = BuildImage(400,
- 82,
- color="#ECE3D8",
- font="HYWenHei-85W.ttf",
- font_size=21)
+ _bk = BuildImage(
+ 400, 82, color="#ECE3D8", font="HYWenHei-85W.ttf", font_size=21
+ )
file_name = x["avatar_side_icon"].split("_")[-1]
role_avatar = memo_path / "role_avatar" / file_name
_ava_img = BuildImage(75, 75, background=role_avatar)
diff --git a/plugins/genshin/query_user/query_role/__init__.py b/plugins/genshin/query_user/query_role/__init__.py
index e4623e79..ce39e809 100644
--- a/plugins/genshin/query_user/query_role/__init__.py
+++ b/plugins/genshin/query_user/query_role/__init__.py
@@ -1,11 +1,13 @@
+from httpx import ConnectError
from nonebot import on_command
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
-from services.log import logger
-from .data_source import query_role_data
-from .._models import Genshin
-from utils.utils import is_number
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
from nonebot.params import CommandArg
+from services.log import logger
+from utils.utils import is_number
+
+from .._models import Genshin
+from .data_source import query_role_data
__zx_plugin_name__ = "原神玩家查询"
__plugin_usage__ = """
@@ -29,7 +31,9 @@ __plugin_settings__ = {
__plugin_block_limit__ = {}
-query_role_info_matcher = on_command("原神玩家查询", aliases={"原神玩家查找", "ys"}, priority=5, block=True)
+query_role_info_matcher = on_command(
+ "原神玩家查询", aliases={"原神玩家查找", "ys"}, priority=5, block=True
+)
@query_role_info_matcher.handle()
@@ -39,24 +43,25 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
if not is_number(msg):
await query_role_info_matcher.finish("查询uid必须为数字!")
msg = int(msg)
- if not msg:
- uid = await Genshin.get_user_uid(event.user_id)
+ uid = None
+ user = await Genshin.get_or_none(user_qq=event.user_id)
+ if not msg and user:
+ uid = user.uid
else:
uid = msg
if not uid: # or not await Genshin.get_user_cookie(uid):
await query_role_info_matcher.finish("请先绑定uid和cookie!")
nickname = event.sender.card or event.sender.nickname
- mys_id = await Genshin.get_user_mys_id(uid)
- data = await query_role_data(event.user_id, uid, mys_id, nickname)
- if data:
- await query_role_info_matcher.send(data)
- logger.info(
- f"(USER {event.user_id}, "
- f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 使用原神玩家查询 uid:{uid}"
- )
- else:
- await query_role_info_matcher.send("查询失败..")
-
-
-
-
+ mys_id = user.mys_id if user else None
+ try:
+ data = await query_role_data(event.user_id, uid, mys_id, nickname)
+ if data:
+ await query_role_info_matcher.send(data)
+ logger.info(
+ f"(USER {event.user_id}, "
+ f"GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) 使用原神玩家查询 uid:{uid}"
+ )
+ else:
+ await query_role_info_matcher.send("查询失败..")
+ except ConnectError:
+ await query_role_info_matcher.send("网络出小差啦~")
diff --git a/plugins/genshin/query_user/query_role/data_source.py b/plugins/genshin/query_user/query_role/data_source.py
index 01b6fb70..58f0ffe9 100644
--- a/plugins/genshin/query_user/query_role/data_source.py
+++ b/plugins/genshin/query_user/query_role/data_source.py
@@ -1,11 +1,14 @@
-from typing import Optional, List, Dict, Union
-from .draw_image import init_image, get_genshin_image
+from typing import Dict, List, Optional, Tuple, Union
+
from nonebot.adapters.onebot.v11 import MessageSegment
-from .._utils import get_ds, element_mastery
+
+from configs.config import Config
from services.log import logger
from utils.http_utils import AsyncHttpx
-from configs.config import Config
+
from .._models import Genshin
+from .._utils import element_mastery, get_ds
+from .draw_image import get_genshin_image, init_image
try:
import ujson as json
@@ -96,66 +99,66 @@ b=body q=query
"""
-async def get_info(uid_: str, server_id: str) -> "Optional[Union[dict, str]], int":
- try:
- req = await AsyncHttpx.get(
- url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index?server={server_id}&role_id={uid_}",
- headers={
- "Accept": "application/json, text/plain, */*",
- "DS": get_ds(f"role_id={uid_}&server={server_id}"),
- "Origin": "https://webstatic.mihoyo.com",
- "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
- "User-Agent": "Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0",
- "x-rpc-client_type": Config.get_config("genshin", "client_type"),
- "Referer": "https://webstatic.mihoyo.com/app/community-game-records/index.html?v=6",
- "Accept-Encoding": "gzip, deflate",
- "Accept-Language": "zh-CN,en-US;q=0.8",
- "X-Requested-With": "com.mihoyo.hyperion",
- "Cookie": await Genshin.get_user_cookie(int(uid_))
- },
- )
- data = req.json()
- if data["message"] == "OK":
- return data["data"], 200
- return data["message"], 999
- except Exception as e:
- logger.error(f"访问失败,请重试! {type(e)}: {e}")
+async def get_info(uid_: str, server_id: str) -> Tuple[Optional[Union[dict, str]], int]:
+ # try:
+ req = await AsyncHttpx.get(
+ url=f"https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/index?server={server_id}&role_id={uid_}",
+ headers={
+ "Accept": "application/json, text/plain, */*",
+ "DS": get_ds(f"role_id={uid_}&server={server_id}"),
+ "Origin": "https://webstatic.mihoyo.com",
+ "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
+ "User-Agent": "Mozilla/5.0 (Linux; Android 9; Unspecified Device) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/39.0.0.0 Mobile Safari/537.36 miHoYoBBS/2.2.0",
+ "x-rpc-client_type": Config.get_config("genshin", "client_type"),
+ "Referer": "https://webstatic.mihoyo.com/app/community-game-records/index.html?v=6",
+ "Accept-Encoding": "gzip, deflate",
+ "Accept-Language": "zh-CN,en-US;q=0.8",
+ "X-Requested-With": "com.mihoyo.hyperion",
+ "Cookie": await Genshin.random_cookie(uid_),
+ },
+ )
+ data = req.json()
+ if data["message"] == "OK":
+ return data["data"], 200
+ return data["message"], 999
+ # except Exception as e:
+ # logger.error(f"访问失败,请重试! {type(e)}: {e}")
return None, -1
async def get_character(
uid: str, character_ids: List[str], server_id="cn_gf01"
) -> Optional[dict]:
- try:
- req = await AsyncHttpx.post(
- url="https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/character",
- headers={
- "Accept": "application/json, text/plain, */*",
- "DS": get_ds(
- "",
- {
- "character_ids": character_ids,
- "role_id": uid,
- "server": server_id,
- },
- ),
- "Origin": "https://webstatic.mihoyo.com",
- "Cookie": await Genshin.get_user_cookie(int(uid)),
- "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
- "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
- "x-rpc-client_type": "5",
- "Referer": "https://webstatic.mihoyo.com/",
- "Accept-Encoding": "gzip, deflate",
- "Accept-Language": "zh-CN,en-US;q=0.8",
- "X-Requested-With": "com.mihoyo.hyperion",
- },
- json={"character_ids": character_ids, "role_id": uid, "server": server_id},
- )
- data = req.json()
- if data["message"] == "OK":
- return data["data"]
- except Exception as e:
- logger.error(f"访问失败,请重试! {type(e)}: {e}")
+ # try:
+ req = await AsyncHttpx.post(
+ url="https://api-takumi-record.mihoyo.com/game_record/app/genshin/api/character",
+ headers={
+ "Accept": "application/json, text/plain, */*",
+ "DS": get_ds(
+ "",
+ {
+ "character_ids": character_ids,
+ "role_id": uid,
+ "server": server_id,
+ },
+ ),
+ "Origin": "https://webstatic.mihoyo.com",
+ "Cookie": await Genshin.random_cookie(uid),
+ "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": "5",
+ "Referer": "https://webstatic.mihoyo.com/",
+ "Accept-Encoding": "gzip, deflate",
+ "Accept-Language": "zh-CN,en-US;q=0.8",
+ "X-Requested-With": "com.mihoyo.hyperion",
+ },
+ json={"character_ids": character_ids, "role_id": uid, "server": server_id},
+ )
+ data = req.json()
+ if data["message"] == "OK":
+ return data["data"]
+ # except Exception as e:
+ # logger.error(f"访问失败,请重试! {type(e)}: {e}")
return None
@@ -205,7 +208,7 @@ def parsed_data(
"image": world["icon"],
"name": world["name"],
"offerings": world["offerings"],
- "icon": world["icon"]
+ "icon": world["icon"],
}
world_data_dict[world["name"]] = _x
home_data_list = []
@@ -231,21 +234,21 @@ async def get_mys_data(uid: str, mys_id: Optional[str]) -> Optional[List[Dict]]:
:param mys_id: 米游社id
"""
if mys_id:
- try:
- req = await AsyncHttpx.get(
- url=f"https://api-takumi-record.mihoyo.com/game_record/card/wapi/getGameRecordCard?uid={mys_id}",
- headers={
- "DS": get_ds(f"uid={mys_id}"),
- "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
- "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
- "x-rpc-client_type": "5",
- "Referer": "https://webstatic.mihoyo.com/",
- "Cookie": await Genshin.get_user_cookie(int(uid))
- },
- )
- data = req.json()
- if data["message"] == "OK":
- return data["data"]["list"]
- except Exception as e:
- logger.error(f"访问失败,请重试! {type(e)}: {e}")
+ # try:
+ req = await AsyncHttpx.get(
+ url=f"https://api-takumi-record.mihoyo.com/game_record/card/wapi/getGameRecordCard?uid={mys_id}",
+ headers={
+ "DS": get_ds(f"uid={mys_id}"),
+ "x-rpc-app_version": Config.get_config("genshin", "mhyVersion"),
+ "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) miHoYoBBS/2.11.1",
+ "x-rpc-client_type": "5",
+ "Referer": "https://webstatic.mihoyo.com/",
+ "Cookie": await Genshin.random_cookie(uid),
+ },
+ )
+ data = req.json()
+ if data["message"] == "OK":
+ return data["data"]["list"]
+ # except Exception as e:
+ # logger.error(f"访问失败,请重试! {type(e)}: {e}")
return None
diff --git a/plugins/genshin/query_user/reset_today_query_user_data/__init__.py b/plugins/genshin/query_user/reset_today_query_user_data/__init__.py
index 867e1982..667ba90a 100644
--- a/plugins/genshin/query_user/reset_today_query_user_data/__init__.py
+++ b/plugins/genshin/query_user/reset_today_query_user_data/__init__.py
@@ -1,6 +1,7 @@
-from utils.utils import scheduler
-from .._models import Genshin
from services.log import logger
+from utils.utils import scheduler
+
+from .._models import Genshin
@scheduler.scheduled_job(
@@ -10,7 +11,7 @@ from services.log import logger
)
async def _():
try:
- await Genshin.reset_today_query_uid()
+ await Genshin.all().update(today_query_uid="")
logger.warning(f"重置原神查询记录成功..")
except Exception as e:
logger.error(f"重置原神查询记录失败. {type(e)}:{e}")
diff --git a/plugins/genshin/query_user/resin_remind/__init__.py b/plugins/genshin/query_user/resin_remind/__init__.py
index 4de7b2a9..60c1984d 100644
--- a/plugins/genshin/query_user/resin_remind/__init__.py
+++ b/plugins/genshin/query_user/resin_remind/__init__.py
@@ -1,12 +1,15 @@
-from nonebot import on_command
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
-from apscheduler.jobstores.base import JobLookupError
-from services.log import logger
-from .init_task import scheduler, add_job
-from .._models import Genshin
-from nonebot.params import Command
from typing import Tuple
+from apscheduler.jobstores.base import JobLookupError
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+from nonebot.params import Command
+
+from services.log import logger
+from utils.depends import OneCommand
+
+from .._models import Genshin
+from .init_task import add_job, scheduler
__zx_plugin_name__ = "原神树脂提醒"
__plugin_usage__ = """
@@ -33,31 +36,32 @@ __plugin_configs__ = {
"AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND": {
"value": True,
"help": "当请求连续三次失败时,关闭用户的树脂提醒",
- "default_value": True
+ "default_value": True,
},
"CUSTOM_RESIN_OVERFLOW_REMIND": {
"value": 20,
"help": "自定义树脂溢出指定数量时的提醒,空值是为关闭",
- "default_value": None
- }
+ "default_value": None,
+ },
}
resin_remind = on_command("开原神树脂提醒", aliases={"关原神树脂提醒"}, priority=5, block=True)
@resin_remind.handle()
-async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
- cmd = cmd[0]
- uid = await Genshin.get_user_uid(event.user_id)
- if not uid or not await Genshin.get_user_cookie(uid, True):
+async def _(event: MessageEvent, cmd: str = OneCommand()):
+ user = await Genshin.get_or_none(user_qq=event.user_id)
+ if not user or not user.uid or not user.cookie:
await resin_remind.finish("请先绑定uid和cookie!")
try:
- scheduler.remove_job(f"genshin_resin_remind_{uid}_{event.user_id}")
+ scheduler.remove_job(f"genshin_resin_remind_{user.uid}_{event.user_id}")
except JobLookupError:
pass
if cmd[0] == "开":
- await Genshin.set_resin_remind(uid, True)
- add_job(event.user_id, uid)
+ if user.resin_remind:
+ await resin_remind.finish("原神树脂提醒已经是开启状态,请勿重复开启!", at_sender=True)
+ user.resin_remind = True
+ add_job(event.user_id, user.uid)
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
@@ -65,12 +69,15 @@ async def _(event: MessageEvent, cmd: Tuple[str, ...] = Command()):
)
await resin_remind.send("开启原神树脂提醒成功!", at_sender=True)
else:
- await Genshin.set_resin_remind(uid, False)
- await Genshin.clear_resin_remind_time(uid)
+ if not user.resin_remind:
+ await resin_remind.finish("原神树脂提醒已经是开启状态,请勿重复开启!", at_sender=True)
+ user.resin_remind = False
+ user.resin_recovery_time = None
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 关闭原神体力提醒"
)
await resin_remind.send("已关闭原神树脂提醒..", at_sender=True)
-
+ if user:
+ await user.save(update_fields=["resin_remind", "resin_recovery_time"])
diff --git a/plugins/genshin/query_user/resin_remind/init_task.py b/plugins/genshin/query_user/resin_remind/init_task.py
index f8cf62a8..63d0b288 100644
--- a/plugins/genshin/query_user/resin_remind/init_task.py
+++ b/plugins/genshin/query_user/resin_remind/init_task.py
@@ -1,20 +1,20 @@
-from nonebot.adapters.onebot.v11 import ActionFailed
-
-from utils.utils import get_bot, scheduler
-from utils.message_builder import at
-from models.group_member_info import GroupInfoUser
-from apscheduler.jobstores.base import ConflictingIdError
-from nonebot import Driver
-from .._models import Genshin
-from datetime import datetime, timedelta
-from apscheduler.jobstores.base import JobLookupError
-from services.log import logger
-from nonebot.plugin import require
-from configs.config import Config
import random
+from datetime import datetime, timedelta
+
import nonebot
import pytz
+from apscheduler.jobstores.base import ConflictingIdError, JobLookupError
+from nonebot import Driver
+from nonebot.adapters.onebot.v11 import ActionFailed
+from nonebot.plugin import require
+from configs.config import Config
+from models.group_member_info import GroupInfoUser
+from services.log import logger
+from utils.message_builder import at
+from utils.utils import get_bot, scheduler
+
+from .._models import Genshin
driver: Driver = nonebot.get_driver()
@@ -23,7 +23,6 @@ require("query_memo")
from ..query_memo import get_memo
-
global_map = {}
@@ -80,12 +79,13 @@ async def _():
"""
启动时分配定时任务
"""
- g_list = await Genshin.get_all_resin_remind_user()
+ g_list = await Genshin.filter(resin_remind=True).all()
+ update_list = []
date = datetime.now(pytz.timezone("Asia/Shanghai")) + timedelta(seconds=30)
for u in g_list:
if u.resin_remind:
if u.resin_recovery_time:
- if await Genshin.get_user_resin_recovery_time(u.uid) > datetime.now(
+ if u.resin_recovery_time and u.resin_recovery_time > datetime.now(
pytz.timezone("Asia/Shanghai")
):
# date = await Genshin.get_user_resin_recovery_time(u.uid) # 不能要,因为可能在这期间用户使用了树脂
@@ -101,7 +101,8 @@ async def _():
f"genshin_resin_remind add_job:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
)
else:
- await Genshin.clear_resin_remind_time(u.uid)
+ u.resin_recovery_time = None
+ update_list.append(u)
add_job(u.user_qq, u.uid)
logger.info(
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
@@ -111,6 +112,8 @@ async def _():
logger.info(
f"genshin_resin_remind add_job CHECK:USER:{u.user_qq} UID:{u.uid}启动原神树脂提醒 "
)
+ if update_list:
+ await Genshin.bulk_update(update_list, ["resin_recovery_time"])
def add_job(user_id: int, uid: int):
@@ -133,6 +136,7 @@ def add_job(user_id: int, uid: int):
async def _remind(user_id: int, uid: str):
+ user = await Genshin.get_or_none(user_qq=user_id, uid=int(uid))
uid = str(uid)
if uid[0] in ["1", "2"]:
server_id = "cn_gf01"
@@ -158,7 +162,9 @@ async def _remind(user_id: int, uid: str):
elif max_resin - 20 <= current_resin < max_resin:
next_time = now + timedelta(minutes=(max_resin - current_resin) * 8)
elif current_resin == max_resin:
- custom_overflow_resin = Config.get_config("resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND")
+ custom_overflow_resin = Config.get_config(
+ "resin_remind", "CUSTOM_RESIN_OVERFLOW_REMIND"
+ )
if user_manager.is_overflow(uid) and custom_overflow_resin:
next_time = now + timedelta(minutes=custom_overflow_resin * 8)
user_manager.add_overflow(uid)
@@ -178,28 +184,35 @@ async def _remind(user_id: int, uid: str):
message=msg,
)
else:
- group_id = await Genshin.get_bind_group(int(uid))
- if not group_id:
- group_list = await GroupInfoUser.get_user_all_group(user_id)
- if group_list:
- group_id = group_list[0]
- try:
- await bot.send_group_msg(
- group_id=group_id,
- message=at(user_id) + msg
- )
- except ActionFailed as e:
- logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
+ if user:
+ group_id = user.bind_group
+ if not group_id:
+ if group_list := await GroupInfoUser.get_user_all_group(
+ user_id
+ ):
+ group_id = group_list[0]
+ try:
+ await bot.send_group_msg(
+ group_id=group_id, message=at(user_id) + msg
+ )
+ except ActionFailed as e:
+ logger.error(f"树脂提醒推送发生错误 {type(e)}:{e}")
if not next_time:
- if user_manager.check(uid) and Config.get_config("resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"):
- await Genshin.set_resin_remind(int(uid), False)
- await Genshin.clear_resin_remind_time(int(uid))
+ if user_manager.check(uid) and Config.get_config(
+ "resin_remind", "AUTO_CLOSE_QUERY_FAIL_RESIN_REMIND"
+ ):
+ if user:
+ user.resin_remind = False
+ user.resin_recovery_time = None
+ await user.save(update_fields=["resin_recovery_time", "resin_remind"])
next_time = now + timedelta(minutes=(20 + random.randint(5, 20)) * 8)
user_manager.add_error_count(uid)
else:
user_manager.remove_error_count(uid)
- await Genshin.set_user_resin_recovery_time(int(uid), next_time)
+ if user:
+ user.resin_recovery_time = next_time
+ await user.save(update_fields=["resin_recovery_time", "resin_remind"])
scheduler.add_job(
_remind,
"date",
@@ -208,6 +221,5 @@ async def _remind(user_id: int, uid: str):
args=[user_id, uid],
)
logger.info(
- f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} "
- f"{next_time} 原神树脂提醒"
- )
+ f"genshin_resin_remind add_job:USER:{user_id} UID:{uid} " f"{next_time} 原神树脂提醒"
+ )
diff --git a/plugins/gold_redbag/model.py b/plugins/gold_redbag/model.py
index a797463b..9516a4bd 100755
--- a/plugins/gold_redbag/model.py
+++ b/plugins/gold_redbag/model.py
@@ -1,73 +1,58 @@
-from services.db_context import db
from typing import List
+from tortoise import fields
-class RedbagUser(db.Model):
- __tablename__ = "redbag_users"
+from services.db_context import Model
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- send_redbag_count = db.Column(db.Integer(), default=0)
- get_redbag_count = db.Column(db.Integer(), default=0)
- spend_gold = db.Column(db.Integer(), default=0)
- get_gold = db.Column(db.Integer(), default=0)
- _idx1 = db.Index("redbag_group_users_idx1", "user_qq", "group_id", unique=True)
+class RedbagUser(Model):
+
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ send_redbag_count = fields.IntField(default=0)
+ """发送红包次数"""
+ get_redbag_count = fields.IntField(default=0)
+ """开启红包次数"""
+ spend_gold = fields.IntField(default=0)
+ """发送红包花费金额"""
+ get_gold = fields.IntField(default=0)
+ """开启红包获取金额"""
+
+ class Meta:
+ table = "redbag_users"
+ table_description = "红包统计数据表"
+ unique_together = ("user_qq", "group_id")
@classmethod
- async def add_redbag_data(cls, user_qq: int, group_id: int, itype: str, money: int):
+ async def add_redbag_data(
+ cls, user_qq: int, group_id: int, i_type: str, money: int
+ ):
"""
说明:
添加收发红包数据
参数:
:param user_qq: qq号
:param group_id: 群号
- :param itype: 收或发
+ :param i_type: 收或发
:param money: 金钱数量
"""
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.with_for_update().gino.first() or await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
- if itype == "get":
- await user.update(
- get_redbag_count=user.get_redbag_count + 1,
- get_gold=user.get_gold + money,
- ).apply()
- else:
- await user.update(
- send_redbag_count=user.send_redbag_count + 1,
- spend_gold=user.spend_gold + money,
- ).apply()
- @classmethod
- async def ensure(cls, user_qq: int, group_id: int) -> bool:
- """
- 说明:
- 获取用户对象
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- """
- query = cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- user = await query.gino.first() or await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
- return user
-
- @classmethod
- async def get_user_all(cls, group_id: int = None) -> List["RedbagUser"]:
- """
- 说明:
- 获取所有用户对象
- 参数:
- :param group_id: 群号
- """
- if not group_id:
- query = await cls.query.gino.all()
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ if i_type == "get":
+ user.get_redbag_count = user.get_redbag_count + 1
+ user.get_gold = user.get_gold + money
else:
- query = await cls.query.where((cls.group_id == group_id)).gino.all()
- return query
+ user.send_redbag_count = user.send_redbag_count + 1
+ user.spend_gold = user.spend_gold + money
+ await user.save(
+ update_fields=[
+ "get_redbag_count",
+ "get_gold",
+ "send_redbag_count",
+ "spend_gold",
+ ]
+ )
diff --git a/plugins/image_management/send_image/__init__.py b/plugins/image_management/send_image/__init__.py
index 64e1b2e9..827201c4 100755
--- a/plugins/image_management/send_image/__init__.py
+++ b/plugins/image_management/send_image/__init__.py
@@ -1,15 +1,17 @@
-from nonebot import on_message, on_regex
-from configs.path_config import IMAGE_PATH
-from utils.message_builder import image
-from utils.utils import is_number, get_message_text
-from services.log import logger
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent
-from utils.utils import FreqLimiter, cn2py
-from configs.config import Config
-from utils.manager import withdraw_message_manager
-from .rule import rule
-import random
import os
+import random
+
+from nonebot import on_message, on_regex
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.manager import withdraw_message_manager
+from utils.message_builder import image
+from utils.utils import FreqLimiter, cn2py, get_message_text, is_number
+
+from .rule import rule
try:
import ujson as json
@@ -66,16 +68,14 @@ async def _(event: MessageEvent):
if len(msg) > 1:
img_id = msg[1]
path = _path / cn2py(gallery)
- if gallery in Config.get_config(
- "image_management", "IMAGE_DIR_LIST"
- ):
+ if gallery in Config.get_config("image_management", "IMAGE_DIR_LIST"):
if not path.exists() and (path.parent.parent / cn2py(gallery)).exists():
path = IMAGE_PATH / cn2py(gallery)
else:
path.mkdir(parents=True, exist_ok=True)
length = len(os.listdir(path))
if length == 0:
- logger.warning(f'图库 {cn2py(gallery)} 为空,调用取消!')
+ logger.warning(f"图库 {cn2py(gallery)} 为空,调用取消!")
await send_img.finish("该图库中没有图片噢")
index = img_id if img_id else str(random.randint(0, length - 1))
if not is_number(index):
@@ -87,8 +87,7 @@ async def _(event: MessageEvent):
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'}) "
- f"发送{cn2py(gallery)}:"
- + result
+ f"发送{cn2py(gallery)}:" + result
)
msg_id = await send_img.send(
f"id:{index}" + result
@@ -113,4 +112,6 @@ async def _(event: MessageEvent):
async def _(event: MessageEvent):
if _flmt.check(event.user_id):
_flmt.start_cd(event.user_id)
- await pa_reg.finish(image(random.choice(os.listdir(IMAGE_PATH / "pa")), "pa"))
+ await pa_reg.finish(
+ image(IMAGE_PATH / "pa" / random.choice(os.listdir(IMAGE_PATH / "pa")))
+ )
diff --git a/plugins/my_info/__init__.py b/plugins/my_info/__init__.py
index 4b5946e3..e7ba778c 100644
--- a/plugins/my_info/__init__.py
+++ b/plugins/my_info/__init__.py
@@ -1,10 +1,11 @@
-from nonebot import on_command
-from nonebot.adapters.onebot.v11.permission import GROUP
-from nonebot.adapters.onebot.v11 import GroupMessageEvent
-from models.group_member_info import GroupInfoUser
from datetime import timedelta
-from models.level_user import LevelUser
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent
+from nonebot.adapters.onebot.v11.permission import GROUP
+
+from models.group_member_info import GroupInfoUser
+from models.level_user import LevelUser
__zx_plugin_name__ = "个人信息权限查看"
__plugin_usage__ = """
@@ -31,13 +32,13 @@ async def _(event: GroupMessageEvent):
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:
+ if user := await GroupInfoUser.get_or_none(user_qq=user_qq, group_id=group_id):
+ result = ""
+ result += "昵称:" + user.user_name + "\n"
+ result += "加群时间:" + str(user.user_join_time.date())
+ return result
+ else:
return "该群员不在列表中,请更新群成员信息"
- result = ""
- result += "昵称:" + user.user_name + "\n"
- result += "加群时间:" + str(user.user_join_time.date() + timedelta(hours=8))
- return result
@my_level.handle()
diff --git a/plugins/open_cases/models/buff_prices.py b/plugins/open_cases/models/buff_prices.py
index 1c988ee1..5402d5e0 100755
--- a/plugins/open_cases/models/buff_prices.py
+++ b/plugins/open_cases/models/buff_prices.py
@@ -1,35 +1,23 @@
-from datetime import datetime
+from tortoise import fields
-from services.db_context import db
+from services.db_context import Model
# 1.狂牙武器箱
-class BuffPrice(db.Model):
- __tablename__ = 'buff_prices'
- __table_args__ = {'extend_existing': True}
+class BuffPrice(Model):
- id = db.Column(db.Integer(), primary_key=True)
- case_id = db.Column(db.Integer(), nullable=False)
- skin_name = db.Column(db.Unicode(), nullable=False)
- skin_price = db.Column(db.Float(), nullable=False)
- update_date = db.Column(db.DateTime(), nullable=False)
-
- _idx1 = db.Index('buff_price_idx1', 'skin_name', unique=True)
-
- @classmethod
- async def ensure(cls, skin_name: str, for_update: bool = False) -> 'BuffPrice':
- query = cls.query.where(
- (cls.skin_name == skin_name)
- )
- if for_update:
- query = query.with_for_update()
- user = await query.gino.first()
- return user or await cls.create(
- case_id=1,
- skin_name=skin_name,
- skin_price=0,
- update_date=datetime.min,
- )
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ case_id = fields.IntField()
+ """箱子id"""
+ skin_name = fields.CharField(255, unique=True)
+ """皮肤名称"""
+ skin_price = fields.FloatField()
+ """皮肤价格"""
+ update_date = fields.DatetimeField()
+ class Meta:
+ table = "buff_prices"
+ table_description = "Buff价格数据表"
diff --git a/plugins/open_cases/models/open_cases_user.py b/plugins/open_cases/models/open_cases_user.py
index c74cd9f6..0cef31bc 100755
--- a/plugins/open_cases/models/open_cases_user.py
+++ b/plugins/open_cases/models/open_cases_user.py
@@ -1,60 +1,51 @@
-from datetime import datetime
+from tortoise import fields
-from services.db_context import db
-
-
-class OpenCasesUser(db.Model):
- __tablename__ = 'open_cases_users'
- __table_args__ = {'extend_existing': True}
-
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- total_count = db.Column(db.Integer(), nullable=False, default=0)
- blue_count = db.Column(db.Integer(), nullable=False, default=0)
- blue_st_count = db.Column(db.Integer(), nullable=False, default=0)
- purple_count = db.Column(db.Integer(), nullable=False, default=0)
- purple_st_count = db.Column(db.Integer(), nullable=False, default=0)
- pink_count = db.Column(db.Integer(), nullable=False, default=0)
- pink_st_count = db.Column(db.Integer(), nullable=False, default=0)
- red_count = db.Column(db.Integer(), nullable=False, default=0)
- red_st_count = db.Column(db.Integer(), nullable=False, default=0)
- knife_count = db.Column(db.Integer(), nullable=False, default=0)
- knife_st_count = db.Column(db.Integer(), nullable=False, default=0)
- spend_money = db.Column(db.Integer(), nullable=False, default=0)
- make_money = db.Column(db.Float(), nullable=False, default=0)
- today_open_total = db.Column(db.Integer(), nullable=False, default=0)
- open_cases_time_last = db.Column(db.DateTime(timezone=True), nullable=False, default=datetime.now())
- knifes_name = db.Column(db.Unicode(), nullable=False, default="")
-
- _idx1 = db.Index('open_cases_group_users_idx1', 'user_qq', 'group_id', unique=True)
-
- @classmethod
- async def ensure(cls, user_qq: int, group_id: int, for_update: bool = False) -> 'OpenCasesUser':
- query = cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- if for_update:
- query = query.with_for_update()
- user = await query.gino.first()
- return user or await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- )
-
- @classmethod
- async def get_user_all(cls, group_id: int = None) -> 'list':
- user_list = []
- if not group_id:
- query = await cls.query.gino.all()
- else:
- query = await cls.query.where(
- (cls.group_id == group_id)
- ).gino.all()
- for user in query:
- user_list.append(user)
- return user_list
+from services.db_context import Model
+class OpenCasesUser(Model):
+ __tablename__ = "open_cases_users"
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ total_count = fields.IntField(default=0)
+ """总开启次数"""
+ blue_count = fields.IntField(default=0)
+ """蓝色"""
+ blue_st_count = fields.IntField(default=0)
+ """蓝色暗金"""
+ purple_count = fields.IntField(default=0)
+ """紫色"""
+ purple_st_count = fields.IntField(default=0)
+ """紫色暗金"""
+ pink_count = fields.IntField(default=0)
+ """粉色"""
+ pink_st_count = fields.IntField(default=0)
+ """粉色暗金"""
+ red_count = fields.IntField(default=0)
+ """紫色"""
+ red_st_count = fields.IntField(default=0)
+ """紫色暗金"""
+ knife_count = fields.IntField(default=0)
+ """金色"""
+ knife_st_count = fields.IntField(default=0)
+ """金色暗金"""
+ spend_money = fields.IntField(default=0)
+ """花费金币"""
+ make_money = fields.IntField(default=0)
+ """赚取金币"""
+ today_open_total = fields.IntField(default=0)
+ """今日开箱数量"""
+ open_cases_time_last = fields.DatetimeField()
+ """最后开箱日期"""
+ knifes_name = fields.TextField(default="")
+ """已获取金色"""
+ class Meta:
+ table = "open_cases_users"
+ table_description = "开箱统计数据表"
+ unique_together = ("user_qq", "group_id")
diff --git a/plugins/open_cases/open_cases_c.py b/plugins/open_cases/open_cases_c.py
index 792ce4d5..ed1c83b3 100755
--- a/plugins/open_cases/open_cases_c.py
+++ b/plugins/open_cases/open_cases_c.py
@@ -1,20 +1,22 @@
-from datetime import datetime, timedelta
-from .config import *
-from services.log import logger
-from services.db_context import db
-from .models.open_cases_user import OpenCasesUser
-from models.sign_group_user import SignGroupUser
-from utils.message_builder import image
-import pypinyin
-import random
-from .utils import get_price
-from .models.buff_prices import BuffPrice
-from PIL import Image
-from utils.image_utils import alpha2white_pil, BuildImage
-from configs.path_config import IMAGE_PATH
import asyncio
-from utils.utils import cn2py
+import random
+from datetime import datetime, timedelta
+
+import pypinyin
+from PIL import Image
+
from configs.config import Config
+from configs.path_config import IMAGE_PATH
+from models.sign_group_user import SignGroupUser
+from services.log import logger
+from utils.image_utils import BuildImage, alpha2white_pil
+from utils.message_builder import image
+from utils.utils import cn2py
+
+from .config import *
+from .models.buff_prices import BuffPrice
+from .models.open_cases_user import OpenCasesUser
+from .utils import get_price
async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动") -> str:
@@ -26,71 +28,76 @@ async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动"
case = ""
for i in pypinyin.pinyin(case_name, style=pypinyin.NORMAL):
case += "".join(i)
- impression = (await SignGroupUser.ensure(user_qq, group)).impression
+ user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
+ impression = user.impression
rand = random.random()
- async with db.transaction():
- user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
- # 一天次数上限
- if user.today_open_total >= int(
- Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
- + int(impression)
- / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
- ):
- return _handle_is_MAX_COUNT()
- skin, mosun = get_color_quality(rand, case_name)
- # 调侃
- if skin[:2] == "军规":
- if skin.find("StatTrak") == -1:
- uplist[0] = 1
- else:
- uplist[1] = 1
- ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"])
- if skin[:2] == "受限":
- if skin.find("StatTrak") == -1:
- uplist[2] = 1
- else:
- uplist[3] = 1
- ridicule_result = random.choice(
- ["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."]
- )
- if skin[:2] == "保密":
- if skin.find("StatTrak") == -1:
- uplist[4] = 1
- else:
- uplist[5] = 1
- ridicule_result = random.choice(
- ["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"]
- )
- if skin[:2] == "隐秘":
- if skin.find("StatTrak") == -1:
- uplist[6] = 1
- else:
- uplist[7] = 1
- ridicule_result = random.choice(
- ["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"]
- )
- if skin[:2] == "罕见":
- knifes_flag = True
- if skin.find("StatTrak") == -1:
- uplist[8] = 1
- else:
- uplist[9] = 1
- ridicule_result = random.choice(
- ["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."]
- )
- if skin.find("(") != -1:
- cskin = skin.split("(")
- skin = cskin[0].strip() + "(" + cskin[1].strip()
- skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
- # 价格
- if skin.find("无涂装") == -1:
- dbprice = await BuffPrice.ensure(skin[9:])
+ await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
+ # user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
+ user = await OpenCasesUser.get_or_none(user_qq=user_qq, group_id=group)
+ if not user:
+ user = await OpenCasesUser.create(
+ user_qq=user_qq, group_id=group, open_cases_time_last=datetime.now()
+ )
+ # 一天次数上限
+ if user.today_open_total >= int(
+ Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ + int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
+ ):
+ return _handle_is_MAX_COUNT()
+ skin, mosun = get_color_quality(rand, case_name)
+ # 调侃
+ if skin[:2] == "军规":
+ if skin.find("StatTrak") == -1:
+ uplist[0] = 1
else:
- dbprice = await BuffPrice.ensure(skin[9 : skin.rfind("(")].strip())
- if dbprice.skin_price != 0:
- price_result = dbprice.skin_price
- logger.info("数据库查询到价格: ", dbprice.skin_price)
- uplist[10] = dbprice.skin_price
+ uplist[1] = 1
+ ridicule_result = random.choice(["这样看着才舒服", "是自己人,大伙把刀收好", "非常舒适~"])
+ if skin[:2] == "受限":
+ if skin.find("StatTrak") == -1:
+ uplist[2] = 1
+ else:
+ uplist[3] = 1
+ ridicule_result = random.choice(
+ ["还行吧,勉强接受一下下", "居然不是蓝色,太假了", "运气-1-1-1-1-1..."]
+ )
+ if skin[:2] == "保密":
+ if skin.find("StatTrak") == -1:
+ uplist[4] = 1
+ else:
+ uplist[5] = 1
+ ridicule_result = random.choice(["开始不适....", "你妈妈买菜必涨价!涨三倍!", "你最近不适合出门,真的"])
+ if skin[:2] == "隐秘":
+ if skin.find("StatTrak") == -1:
+ uplist[6] = 1
+ else:
+ uplist[7] = 1
+ ridicule_result = random.choice(
+ ["已经非常不适", "好兄弟你开的什么箱子啊,一般箱子不是只有蓝色的吗", "开始拿阳寿开箱子了?"]
+ )
+ if skin[:2] == "罕见":
+ knifes_flag = True
+ if skin.find("StatTrak") == -1:
+ uplist[8] = 1
+ else:
+ uplist[9] = 1
+ ridicule_result = random.choice(
+ ["你的好运我收到了,你可以去喂鲨鱼了", "最近该吃啥就迟点啥吧,哎,好好的一个人怎么就....哎", "众所周知,欧皇寿命极短."]
+ )
+ if skin.find("(") != -1:
+ cskin = skin.split("(")
+ skin = cskin[0].strip() + "(" + cskin[1].strip()
+ skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
+ # 价格
+ if skin.find("无涂装") == -1:
+ search_name = skin[9:]
+ else:
+ search_name = skin[9 : skin.rfind("(")].strip()
+ price_result = 0
+ if data := await BuffPrice.get_or_none(skin_name=search_name):
+ if data.skin_price != 0:
+ price_result = data.skin_price
+ logger.info("数据库查询到价格: ", data.skin_price)
+ uplist[10] = data.skin_price
else:
price = -1
price_result = "未查询到"
@@ -102,55 +109,56 @@ async def open_case(user_qq: int, group: int, case_name: str = "狂牙大行动"
price = float(pcp[1].strip())
break
if price != -1:
- logger.info("存储入数据库---->", price)
+ logger.info("存储入数据库---->{price}")
uplist[10] = price
price_result = str(price)
- await dbprice.update(
- skin_price=price,
- update_date=datetime.now(),
- ).apply()
- # sp = skin.split("|")
- # cskin_word = sp[1][:sp[1].find("(") - 1].strip()
- if knifes_flag:
- await user.update(
- knifes_name=user.knifes_name
- + f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{uplist[10]},"
- ).apply()
- cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "")
- cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
- skin_name = cn2py(
- cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip()
+ data.skin_price = price
+ data.update_date = datetime.now()
+ await data.save(update_fields=["skin_price", "update_date"])
+ # sp = skin.split("|")
+ # cskin_word = sp[1][:sp[1].find("(") - 1].strip()
+ if knifes_flag:
+ await user.update(
+ knifes_name=user.knifes_name
+ + f"{case}||{skin.split(':')[1].strip()} 磨损:{str(mosun)[:11]}, 价格:{uplist[10]},"
+ ).apply()
+ cskin_word = skin.split(":")[1].replace("|", "-").replace("(StatTrak™)", "")
+ cskin_word = cskin_word[: cskin_word.rfind("(")].strip()
+ skin_name = cn2py(cskin_word.replace("|", "-").replace("(StatTrak™)", "").strip())
+ img = image(IMAGE_PATH / "cases" / case / f"{skin_name}.png")
+ # if knifes_flag:
+ # await user.update(
+ # knifes_name=user.knifes_name + f"{skin} 磨损:{mosun}, 价格:{uplist[10]}"
+ # ).apply()
+ if await update_user_total(user, uplist):
+ logger.info(
+ f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新成功"
)
- img = image(f"{skin_name}.png", "cases/" + case)
- # if knifes_flag:
- # await user.update(
- # knifes_name=user.knifes_name + f"{skin} 磨损:{mosun}, 价格:{uplist[10]}"
- # ).apply()
- if await update_user_total(user, uplist):
- logger.info(
- f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新成功"
- )
- else:
- logger.warning(
- f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新失败"
- )
- user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
- over_count = int(
+ else:
+ logger.warning(
+ f"qq:{user_qq} 群:{group} 开启{case_name}武器箱 获得 {skin} 磨损:{mosun}, 价格:{uplist[10]}, 数据更新失败"
+ )
+ user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
+ over_count = (
+ int(
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ int(impression)
/ Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
- ) - user.today_open_total
- return (
- f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n"
- f"磨损:{mosun:.9f}\n"
- f"价格:{price_result}\n"
- f"{ridicule_result}"
)
+ - user.today_open_total
+ )
+ return (
+ f"开启{case_name}武器箱.\n剩余开箱次数:{over_count}.\n" + img + "\n" + f"皮肤:{skin}\n"
+ f"磨损:{mosun:.9f}\n"
+ f"价格:{price_result}\n"
+ f"{ridicule_result}"
+ )
async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int = 10):
- user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
- impression = (await SignGroupUser.ensure(user_qq, group)).impression
+ user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
+ sign_user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
+ impression = sign_user.impression
max_count = int(
Config.get_config("open_cases", "INITIAL_OPEN_CASE_COUNT")
+ int(impression) / Config.get_config("open_cases", "EACH_IMPRESSION_ADD_COUNT")
@@ -162,11 +170,10 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
f"今天开箱次数不足{num}次噢,请单抽试试看(也许单抽运气更好?)"
f"\n剩余开箱次数:{max_count - user.today_open_total}"
)
- await user.update(
- total_count=user.total_count + num,
- spend_money=user.spend_money + 17 * num,
- today_open_total=user.today_open_total + num,
- ).apply()
+ user.total_count = user.total_count + num
+ user.spend_money = user.spend_money + 17 * num
+ user.today_open_total = user.today_open_total + num
+ await user.save(update_fields=["total_count", "spend_money", "today_open_total"])
if num < 5:
h = 270
elif num % 5 == 0:
@@ -180,46 +187,46 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0]
img_list = []
name_list = ["蓝", "蓝(暗金)", "紫", "紫(暗金)", "粉", "粉(暗金)", "红", "红(暗金)", "金", "金(暗金)"]
- async with db.transaction():
- for _ in range(num):
- knifes_flag = False
- rand = random.random()
- skin, mosun = get_color_quality(rand, case_name)
- if skin[:2] == "军规":
- if skin.find("StatTrak") == -1:
- uplist[0] += 1
- else:
- uplist[1] += 1
- if skin[:2] == "受限":
- if skin.find("StatTrak") == -1:
- uplist[2] += 1
- else:
- uplist[3] += 1
- if skin[:2] == "保密":
- if skin.find("StatTrak") == -1:
- uplist[4] += 1
- else:
- uplist[5] += 1
- if skin[:2] == "隐秘":
- if skin.find("StatTrak") == -1:
- uplist[6] += 1
- else:
- uplist[7] += 1
- if skin[:2] == "罕见":
- knifes_flag = True
- if skin.find("StatTrak") == -1:
- uplist[8] += 1
- else:
- uplist[9] += 1
- if skin.find("(") != -1:
- cskin = skin.split("(")
- skin = cskin[0].strip() + "(" + cskin[1].strip()
- skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
- # 价格
- if skin.find("无涂装") == -1:
- dbprice = await BuffPrice.ensure(skin[9:])
+ for _ in range(num):
+ knifes_flag = False
+ rand = random.random()
+ skin, mosun = get_color_quality(rand, case_name)
+ if skin[:2] == "军规":
+ if skin.find("StatTrak") == -1:
+ uplist[0] += 1
else:
- dbprice = await BuffPrice.ensure(skin[9 : skin.rfind("(")].strip())
+ uplist[1] += 1
+ if skin[:2] == "受限":
+ if skin.find("StatTrak") == -1:
+ uplist[2] += 1
+ else:
+ uplist[3] += 1
+ if skin[:2] == "保密":
+ if skin.find("StatTrak") == -1:
+ uplist[4] += 1
+ else:
+ uplist[5] += 1
+ if skin[:2] == "隐秘":
+ if skin.find("StatTrak") == -1:
+ uplist[6] += 1
+ else:
+ uplist[7] += 1
+ if skin[:2] == "罕见":
+ knifes_flag = True
+ if skin.find("StatTrak") == -1:
+ uplist[8] += 1
+ else:
+ uplist[9] += 1
+ if skin.find("(") != -1:
+ cskin = skin.split("(")
+ skin = cskin[0].strip() + "(" + cskin[1].strip()
+ skin = skin.split("|")[0].strip() + " | " + skin.split("|")[1].strip()
+ # 价格
+ if skin.find("无涂装") == -1:
+ search_name = skin[9:]
+ else:
+ search_name = skin[9 : skin.rfind("(")].strip()
+ if dbprice := await BuffPrice.get_or_none(skin_name=search_name):
if dbprice.skin_price != 0:
price_result = dbprice.skin_price
uplist[10] += price_result
@@ -238,7 +245,6 @@ async def open_shilian_case(user_qq: int, group: int, case_name: str, num: int =
style=pypinyin.NORMAL,
):
skin_name += "".join(i)
- # img = image(skin_name, "cases/" + case, "png")
wImg = BuildImage(200, 270, 200, 200)
wImg.paste(
alpha2white_pil(
@@ -296,7 +302,7 @@ def _handle_is_MAX_COUNT() -> str:
async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) -> bool:
try:
- await user.update(
+ await user.update_or_create(
total_count=user.total_count + num,
blue_count=user.blue_count + up_list[0],
blue_st_count=user.blue_st_count + up_list[1],
@@ -312,36 +318,35 @@ async def update_user_total(user: OpenCasesUser, up_list: list, num: int = 1) ->
make_money=user.make_money + up_list[10],
today_open_total=user.today_open_total + num,
open_cases_time_last=datetime.now(),
- ).apply()
+ )
return True
except:
return False
async def total_open_statistics(user_qq: int, group: int) -> str:
- async with db.transaction():
- user = await OpenCasesUser.ensure(user_qq, group, for_update=True)
- return (
- f"开箱总数:{user.total_count}\n"
- f"今日开箱:{user.today_open_total}\n"
- f"蓝色军规:{user.blue_count}\n"
- f"蓝色暗金:{user.blue_st_count}\n"
- f"紫色受限:{user.purple_count}\n"
- f"紫色暗金:{user.purple_st_count}\n"
- f"粉色保密:{user.pink_count}\n"
- f"粉色暗金:{user.pink_st_count}\n"
- f"红色隐秘:{user.red_count}\n"
- f"红色暗金:{user.red_st_count}\n"
- f"金色罕见:{user.knife_count}\n"
- f"金色暗金:{user.knife_st_count}\n"
- f"花费金额:{user.spend_money}\n"
- f"获取金额:{user.make_money:.2f}\n"
- f"最后开箱日期:{(user.open_cases_time_last + timedelta(hours=8)).date()}"
- )
+ user, _ = await OpenCasesUser.get_or_create(user_qq=user_qq, group_id=group)
+ return (
+ f"开箱总数:{user.total_count}\n"
+ f"今日开箱:{user.today_open_total}\n"
+ f"蓝色军规:{user.blue_count}\n"
+ f"蓝色暗金:{user.blue_st_count}\n"
+ f"紫色受限:{user.purple_count}\n"
+ f"紫色暗金:{user.purple_st_count}\n"
+ f"粉色保密:{user.pink_count}\n"
+ f"粉色暗金:{user.pink_st_count}\n"
+ f"红色隐秘:{user.red_count}\n"
+ f"红色暗金:{user.red_st_count}\n"
+ f"金色罕见:{user.knife_count}\n"
+ f"金色暗金:{user.knife_st_count}\n"
+ f"花费金额:{user.spend_money}\n"
+ f"获取金额:{user.make_money:.2f}\n"
+ f"最后开箱日期:{user.open_cases_time_last.date()}"
+ )
async def group_statistics(group: int):
- user_list = await OpenCasesUser.get_user_all(group)
+ user_list = await OpenCasesUser.filter(group_id=group).all()
# lan zi fen hong jin pricei
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0]
for user in user_list:
@@ -377,7 +382,8 @@ async def group_statistics(group: int):
async def my_knifes_name(user_id: int, group: int):
- knifes_name = (await OpenCasesUser.ensure(user_id, group)).knifes_name
+ user, _ = await OpenCasesUser.get_or_create(user_qq=user_id, group_id=group)
+ knifes_name = user.knifes_name
if knifes_name:
knifes_list = knifes_name[:-1].split(",")
length = len(knifes_list)
diff --git a/plugins/open_cases/utils.py b/plugins/open_cases/utils.py
index 83f3787e..d588e55d 100755
--- a/plugins/open_cases/utils.py
+++ b/plugins/open_cases/utils.py
@@ -1,17 +1,19 @@
-from .models.buff_prices import BuffPrice
-from services.db_context import db
-from datetime import datetime, timedelta
-from configs.path_config import IMAGE_PATH
-from utils.http_utils import AsyncHttpx
-from .models.open_cases_user import OpenCasesUser
-from services.log import logger
-from utils.utils import get_bot, cn2py
-from asyncio.exceptions import TimeoutError
-from nonebot.adapters.onebot.v11 import ActionFailed
-from configs.config import Config
-from utils.manager import group_manager
-from .config import *
import os
+from asyncio.exceptions import TimeoutError
+from datetime import datetime, timedelta
+
+from nonebot.adapters.onebot.v11 import ActionFailed
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.manager import group_manager
+from utils.utils import cn2py, get_bot
+
+from .config import *
+from .models.buff_prices import BuffPrice
+from .models.open_cases_user import OpenCasesUser
url = "https://buff.163.com/api/market/goods"
# proxies = 'http://49.75.59.242:3128'
@@ -49,108 +51,102 @@ async def util_get_buff_price(case_name: str = "狂牙大行动") -> str:
"骷髅匕首 | 无涂装",
]:
skin = skin.split("|")[0].strip()
- async with db.transaction():
- name_list = []
- price_list = []
- parameter = {"game": "csgo", "page_num": "1", "search": skin}
- try:
- response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"),
+ name_list = []
+ price_list = []
+ parameter = {"game": "csgo", "page_num": "1", "search": skin}
+ try:
+ response = await AsyncHttpx.get(
+ url,
+ proxy=Config.get_config("open_cases", "BUFF_PROXY"),
params=parameter,
- cookies=cookie,)
- if response.status_code == 200:
- data = response.json()["data"]
- total_page = data["total_page"]
- data = data["items"]
- flag = False
- if (
- skin.find("|") == -1
- ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
- for i in range(1, total_page + 1):
- name_list = []
- price_list = []
- parameter = {
- "game": "csgo",
- "page_num": f"{i}",
- "search": skin,
- }
- res = await AsyncHttpx.get(url, params=parameter, cookies=cookie)
- data = res.json()["data"][
- "items"
- ]
- for j in range(len(data)):
- if data[j]["name"] in [f"{skin}(★)"]:
- name = data[j]["name"]
- price = data[j][
- "sell_reference_price"
- ]
- name_list.append(
- name.split("(")[0].strip()
- + " | 无涂装"
- )
- price_list.append(price)
- flag = True
- break
- if flag:
+ cookies=cookie,
+ )
+ if response.status_code == 200:
+ data = response.json()["data"]
+ total_page = data["total_page"]
+ data = data["items"]
+ flag = False
+ if (
+ skin.find("|") == -1
+ ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
+ for i in range(1, total_page + 1):
+ name_list = []
+ price_list = []
+ parameter = {
+ "game": "csgo",
+ "page_num": f"{i}",
+ "search": skin,
+ }
+ res = await AsyncHttpx.get(
+ url, params=parameter, cookies=cookie
+ )
+ data = res.json()["data"]["items"]
+ for j in range(len(data)):
+ if data[j]["name"] in [f"{skin}(★)"]:
+ name = data[j]["name"]
+ price = data[j]["sell_reference_price"]
+ name_list.append(
+ name.split("(")[0].strip() + " | 无涂装"
+ )
+ price_list.append(price)
+ flag = True
break
- else:
- try:
- for _ in range(total_page):
- for i in range(len(data)):
- name = data[i]["name"]
- price = data[i]["sell_reference_price"]
- name_list.append(name)
- price_list.append(price)
- except Exception as e:
- failed_list.append(skin)
- logger.warning(f"{skin}更新失败")
+ if flag:
+ break
else:
- failed_list.append(skin)
- logger.warning(f"{skin}更新失败")
- except Exception:
+ try:
+ for _ in range(total_page):
+ for i in range(len(data)):
+ name = data[i]["name"]
+ price = data[i]["sell_reference_price"]
+ name_list.append(name)
+ price_list.append(price)
+ except Exception as e:
+ failed_list.append(skin)
+ logger.warning(f"{skin}更新失败")
+ else:
failed_list.append(skin)
logger.warning(f"{skin}更新失败")
- continue
- for i in range(len(name_list)):
- name = name_list[i].strip()
- price = float(price_list[i])
- if name.find("(★)") != -1:
- name = name[: name.find("(")] + name[name.find(")") + 1 :]
- if name.find("消音") != -1 and name.find("(S") != -1:
- name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
- name = (
- name.split("|")[0].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- elif name.find("消音") != -1:
- name = (
- name.split("|")[0][:-5].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- if name.find(" 18 ") != -1 and name.find("(S") != -1:
- name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
- name = (
- name.split("|")[0].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- elif name.find(" 18 ") != -1:
- name = (
- name.split("|")[0][:-6].strip()
- + " | "
- + name.split("|")[1].strip()
- )
- dbskin = await BuffPrice.ensure(name, True)
- if (
- dbskin.update_date + timedelta(8)
- ).date() == datetime.now().date():
+ except Exception:
+ failed_list.append(skin)
+ logger.warning(f"{skin}更新失败")
+ continue
+ for i in range(len(name_list)):
+ name = name_list[i].strip()
+ price = float(price_list[i])
+ if name.find("(★)") != -1:
+ name = name[: name.find("(")] + name[name.find(")") + 1 :]
+ if name.find("消音") != -1 and name.find("(S") != -1:
+ name = name.split("(")[0][:-4] + "(" + name.split("(")[1]
+ name = (
+ name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
+ )
+ elif name.find("消音") != -1:
+ name = (
+ name.split("|")[0][:-5].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ if name.find(" 18 ") != -1 and name.find("(S") != -1:
+ name = name.split("(")[0][:-5] + "(" + name.split("(")[1]
+ name = (
+ name.split("|")[0].strip() + " | " + name.split("|")[1].strip()
+ )
+ elif name.find(" 18 ") != -1:
+ name = (
+ name.split("|")[0][:-6].strip()
+ + " | "
+ + name.split("|")[1].strip()
+ )
+ if dbskin := await BuffPrice.get_or_none(skin_name=name):
+ if dbskin.update_date.date() == datetime.now().date():
continue
- await dbskin.update(
- case_id=case_id,
- skin_price=price,
- update_date=datetime.now(),
- ).apply()
+ dbskin.case_id = case_id
+ dbskin.skin_price = price
+ dbskin.update_date = datetime.now()
+ await dbskin.save(
+ update_fields=["case_id", "skin_price", "update_date"]
+ )
logger.info(f"{name_list[i]}---------->成功更新")
result = None
if failed_list:
@@ -186,14 +182,16 @@ async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
logger.info(f"开始更新----->{skin}")
skin_name = ""
# try:
- response = await AsyncHttpx.get(url, proxy=Config.get_config("open_cases", "BUFF_PROXY"), params=parameter)
+ response = await AsyncHttpx.get(
+ url,
+ proxy=Config.get_config("open_cases", "BUFF_PROXY"),
+ params=parameter,
+ )
if response.status_code == 200:
data = response.json()["data"]
total_page = data["total_page"]
flag = False
- if (
- skin.find("|") == -1
- ): # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
+ if skin.find("|") == -1: # in ['蝴蝶刀', '求生匕首', '流浪者匕首', '系绳匕首', '骷髅匕首']:
for i in range(1, total_page + 1):
res = await AsyncHttpx.get(url, params=parameter)
data = res.json()["data"]["items"]
@@ -201,17 +199,21 @@ async def util_get_buff_img(case_name: str = "狂牙大行动") -> str:
if data[j]["name"] in [f"{skin}(★)"]:
img_url = data[j]["goods_info"]["icon_url"]
skin_name = cn2py(skin + "无涂装")
- await AsyncHttpx.download_file(img_url, path / f"{skin_name}.png")
+ await AsyncHttpx.download_file(
+ img_url, path / f"{skin_name}.png"
+ )
flag = True
break
if flag:
break
else:
- img_url = (await response.json())["data"]["items"][0][
- "goods_info"
- ]["icon_url"]
+ img_url = (await response.json())["data"]["items"][0]["goods_info"][
+ "icon_url"
+ ]
skin_name += cn2py(skin.replace("|", "-").strip())
- if await AsyncHttpx.download_file(img_url, path / f"{skin_name}.png"):
+ if await AsyncHttpx.download_file(
+ img_url, path / f"{skin_name}.png"
+ ):
logger.info(f"------->写入 {skin} 成功")
else:
logger.info(f"------->写入 {skin} 失败")
@@ -255,18 +257,15 @@ async def get_price(d_name):
async def update_count_daily():
try:
- users = await OpenCasesUser.get_user_all()
- if users:
- for user in users:
- await user.update(
- today_open_total=0,
- ).apply()
+ await OpenCasesUser.all().update(today_open_total=0)
bot = get_bot()
gl = await bot.get_group_list()
gl = [g["group_id"] for g in gl]
for g in gl:
try:
- await bot.send_group_msg(group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功")
+ await bot.send_group_msg(
+ group_id=g, message="[[_task|open_case_reset_remind]]今日开箱次数重置成功"
+ )
except ActionFailed:
logger.warning(f"{g} 群被禁言,无法发送 开箱重置提醒")
logger.info("今日开箱次数重置成功")
diff --git a/plugins/parse_bilibili_json.py b/plugins/parse_bilibili_json.py
index 2dfe8817..13aa7e57 100755
--- a/plugins/parse_bilibili_json.py
+++ b/plugins/parse_bilibili_json.py
@@ -1,22 +1,24 @@
-from nonebot import on_message
-from services.log import logger
-from nonebot.adapters.onebot.v11 import GroupMessageEvent, ActionFailed
-
-from utils.manager import group_manager
-from utils.utils import get_message_json, get_local_proxy, is_number, get_message_text
-from nonebot.adapters.onebot.v11.permission import GROUP
-from utils.message_builder import image
-from utils.image_utils import BuildImage
-from utils.browser import get_browser
-from configs.path_config import IMAGE_PATH
-from utils.http_utils import AsyncHttpx
-from configs.config import Config
-from utils.user_agent import get_user_agent
-import aiohttp
import asyncio
import time
+
+import aiohttp
import ujson as json
from bilireq import video
+from nonebot import on_message
+from nonebot.adapters.onebot.v11 import ActionFailed, GroupMessageEvent
+from nonebot.adapters.onebot.v11.permission import GROUP
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH, TEMP_PATH
+from services.log import logger
+from utils.browser import get_browser
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import BuildImage
+from utils.manager import group_manager
+from utils.message_builder import image
+from utils.user_agent import get_user_agent
+from utils.utils import get_local_proxy, get_message_json, get_message_text, is_number
+
__zx_plugin_name__ = "B站转发解析"
__plugin_usage__ = """
usage:
@@ -39,7 +41,10 @@ Config.add_plugin_config(
async def plugin_on_checker(event: GroupMessageEvent) -> bool:
return group_manager.get_plugin_status("parse_bilibili_json", event.group_id)
-parse_bilibili_json = on_message(priority=1, permission=GROUP, block=False, rule=plugin_on_checker)
+
+parse_bilibili_json = on_message(
+ priority=1, permission=GROUP, block=False, rule=plugin_on_checker
+)
_tmp = {}
@@ -55,16 +60,14 @@ async def _(event: GroupMessageEvent):
data = None
if data:
# 转发视频
- if data.get("desc") == "哔哩哔哩" or data.get('prompt').find('哔哩哔哩') != -1:
- async with aiohttp.ClientSession(
- headers=get_user_agent()
- ) as session:
+ if data.get("desc") == "哔哩哔哩" or "哔哩哔哩" in data.get("prompt"):
+ async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(
- data["meta"]["detail_1"]["qqdocurl"],
- timeout=7,
+ data["meta"]["detail_1"]["qqdocurl"],
+ timeout=7,
) as response:
url = str(response.url).split("?")[0]
- if url[-1] == '/':
+ if url[-1] == "/":
url = url[:-1]
bvid = url.split("/")[-1]
vd_info = await video.get_video_base_info(bvid)
@@ -93,10 +96,11 @@ async def _(event: GroupMessageEvent):
timeout=100000,
)
await asyncio.get_event_loop().run_in_executor(
- None, resize, f"{IMAGE_PATH}/temp/cv_{event.user_id}.png"
+ None, resize, TEMP_PATH / f"cv_{event.user_id}.png"
)
await parse_bilibili_json.send(
- "[[_task|bilibili_parse]]" + image(f"cv_{event.user_id}.png", "temp")
+ "[[_task|bilibili_parse]]"
+ + image(TEMP_PATH / f"cv_{event.user_id}.png")
)
await page.close()
logger.info(
@@ -121,15 +125,13 @@ async def _(event: GroupMessageEvent):
msg = msg[index + 2 : index + 11]
if is_number(msg):
url = f"https://www.bilibili.com/video/av{msg}"
- vd_info = await video.get_video_base_info('av' + msg)
+ vd_info = await video.get_video_base_info("av" + msg)
elif "https://b23.tv" in msg:
- url = "https://" + msg[msg.find("b23.tv"): msg.find("b23.tv") + 14]
- async with aiohttp.ClientSession(
- headers=get_user_agent()
- ) as session:
+ url = "https://" + msg[msg.find("b23.tv") : msg.find("b23.tv") + 14]
+ async with aiohttp.ClientSession(headers=get_user_agent()) as session:
async with session.get(
- url,
- timeout=7,
+ url,
+ timeout=7,
) as response:
url = (str(response.url).split("?")[0]).strip("/")
bvid = url.split("/")[-1]
@@ -150,8 +152,9 @@ async def _(event: GroupMessageEvent):
date = time.strftime("%Y-%m-%d", time.localtime(vd_info["ctime"]))
try:
await parse_bilibili_json.send(
- "[[_task|bilibili_parse]]" +
- image(vd_info["pic"]) + f"\nav{aid}\n标题:{title}\n"
+ "[[_task|bilibili_parse]]"
+ + image(vd_info["pic"])
+ + f"\nav{aid}\n标题:{title}\n"
f"UP:{author}\n"
f"上传日期:{date}\n"
f"回复:{reply},收藏:{favorite},投币:{coin}\n"
diff --git a/plugins/pid_search.py b/plugins/pid_search.py
index 6e1483af..ff8da011 100755
--- a/plugins/pid_search.py
+++ b/plugins/pid_search.py
@@ -1,17 +1,17 @@
+from asyncio.exceptions import TimeoutError
+
from nonebot import on_command
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message, GroupMessageEvent
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Arg, CommandArg
from nonebot.typing import T_State
from configs.config import Config
-from utils.utils import is_number, change_pixiv_image_links
-from utils.message_builder import image
+from configs.path_config import IMAGE_PATH, TEMP_PATH
from services.log import logger
-from asyncio.exceptions import TimeoutError
-from configs.path_config import IMAGE_PATH
-from utils.manager import withdraw_message_manager
from utils.http_utils import AsyncHttpx
-from nonebot.params import CommandArg, Arg
-
+from utils.manager import withdraw_message_manager
+from utils.message_builder import image
+from utils.utils import change_pixiv_image_links, is_number
__zx_plugin_name__ = "pid搜索"
__plugin_usage__ = """
@@ -88,7 +88,7 @@ async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
img_url = change_pixiv_image_links(img_url)
if not await AsyncHttpx.download_file(
img_url,
- IMAGE_PATH / "temp" / f"pid_search_{event.user_id}_{i}.png",
+ TEMP_PATH / f"pid_search_{event.user_id}_{i}.png",
headers=headers,
):
await pid_search.send("图片下载失败了....", at_sender=True)
@@ -101,7 +101,7 @@ async def _g(event: MessageEvent, state: T_State, pid: str = Arg("pid")):
f"pid:{pid}\n"
f"author:{author}\n"
f"author_id:{author_id}\n"
- f'{image(f"pid_search_{event.user_id}_{i}.png", "temp")}'
+ f'{image(TEMP_PATH / f"pid_search_{event.user_id}_{i}.png")}'
f"{tmp}"
)
)
diff --git a/plugins/pix_gallery/__init__.py b/plugins/pix_gallery/__init__.py
index d1952402..b33c447a 100755
--- a/plugins/pix_gallery/__init__.py
+++ b/plugins/pix_gallery/__init__.py
@@ -1,7 +1,7 @@
-from configs.config import Config
-from utils.utils import GDict
import nonebot
+from configs.config import Config
+from utils.utils import GDict
Config.add_plugin_config(
"hibiapi",
@@ -10,59 +10,42 @@ Config.add_plugin_config(
help_="如果没有自建或其他hibiapi请不要修改",
default_value="https://api.obfs.dev",
)
-Config.add_plugin_config(
- "pixiv",
- "PIXIV_NGINX_URL",
- "i.pximg.cf",
- help_="Pixiv反向代理"
-)
+Config.add_plugin_config("pixiv", "PIXIV_NGINX_URL", "i.pximg.cf", help_="Pixiv反向代理")
Config.add_plugin_config(
"pix",
"PIX_IMAGE_SIZE",
"master",
name="PIX图库",
help_="PIX图库下载的画质 可能的值:original:原图,master:缩略图(加快发送速度)",
- default_value="master"
+ default_value="master",
)
Config.add_plugin_config(
"pix",
"SEARCH_HIBIAPI_BOOKMARKS",
5000,
help_="最低收藏,PIX使用HIBIAPI搜索图片时达到最低收藏才会添加至图库",
- default_value=5000
+ default_value=5000,
)
Config.add_plugin_config(
"pix",
"WITHDRAW_PIX_MESSAGE",
(0, 1),
help_="自动撤回,参1:延迟撤回色图时间(秒),0 为关闭 | 参2:监控聊天类型,0(私聊) 1(群聊) 2(群聊+私聊)",
- default_value=(0, 1)
+ default_value=(0, 1),
)
Config.add_plugin_config(
"pix",
"PIX_OMEGA_PIXIV_RATIO",
(10, 0),
help_="PIX图库 与 额外图库OmegaPixivIllusts 混合搜索的比例 参1:PIX图库 参2:OmegaPixivIllusts扩展图库(没有此图库请设置为0)",
- default_value=(10, 0)
-)
-Config.add_plugin_config(
- "pix",
- "TIMEOUT",
- 10,
- help_="下载图片超时限制(秒)",
- default_value=10
+ default_value=(10, 0),
)
+Config.add_plugin_config("pix", "TIMEOUT", 10, help_="下载图片超时限制(秒)", default_value=10)
Config.add_plugin_config(
- "pix",
- "SHOW_INFO",
- True,
- help_="是否显示图片的基本信息,如PID等",
- default_value=True
+ "pix", "SHOW_INFO", True, help_="是否显示图片的基本信息,如PID等", default_value=True
)
-GDict['run_sql'].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
+GDict["run_sql"].append("ALTER TABLE omega_pixiv_illusts ADD classified Integer;")
nonebot.load_plugins("plugins/pix_gallery")
-
-
diff --git a/plugins/pix_gallery/_data_source.py b/plugins/pix_gallery/_data_source.py
index 28fd52e8..0b9f92d8 100644
--- a/plugins/pix_gallery/_data_source.py
+++ b/plugins/pix_gallery/_data_source.py
@@ -1,19 +1,23 @@
-from asyncpg.exceptions import UniqueViolationError
-from ._model.omega_pixiv_illusts import OmegaPixivIllusts
-from asyncio.locks import Semaphore
-from asyncio.exceptions import TimeoutError
-from ._model.pixiv import Pixiv
-from typing import List, Optional
-from utils.utils import change_pixiv_image_links, change_img_md5
-from utils.image_utils import BuildImage
-from utils.http_utils import AsyncHttpx
-from services.log import logger
-from configs.config import Config
-from configs.path_config import TEMP_PATH
-import aiofiles
-import platform
import asyncio
import math
+import platform
+from asyncio.exceptions import TimeoutError
+from asyncio.locks import Semaphore
+from copy import deepcopy
+from typing import List, Optional, Tuple
+
+import aiofiles
+from asyncpg.exceptions import UniqueViolationError
+
+from configs.config import Config
+from configs.path_config import TEMP_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import BuildImage
+from utils.utils import change_img_md5, change_pixiv_image_links
+
+from ._model.omega_pixiv_illusts import OmegaPixivIllusts
+from ._model.pixiv import Pixiv
try:
import ujson as json
@@ -65,9 +69,7 @@ async def start_update_image_url(
params = {"word": keyword, "page": page}
tasks.append(
asyncio.ensure_future(
- search_image(
- url, keyword, params, semaphore, page, black_pid
- )
+ search_image(url, keyword, params, semaphore, page, black_pid)
)
)
if keyword.startswith("pid:"):
@@ -101,96 +103,91 @@ async def search_image(
pic_count = 0
pid_count = 0
async with semaphore:
- try:
- data = (await AsyncHttpx.get(url, params=params)).json()
- if (
- not data
- or data.get("error")
- or (not data.get("illusts") and not data.get("illust"))
- ):
- return 0, 0
- if url != f"{HIBIAPI}/api/pixiv/illust":
- logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
- data = data["illusts"]
+ # try:
+ data = (await AsyncHttpx.get(url, params=params)).json()
+ if (
+ not data
+ or data.get("error")
+ or (not data.get("illusts") and not data.get("illust"))
+ ):
+ return 0, 0
+ if url != f"{HIBIAPI}/api/pixiv/illust":
+ logger.info(f'{keyword}: 获取数据成功...数据总量:{len(data["illusts"])}')
+ data = data["illusts"]
+ else:
+ logger.info(f'获取数据成功...PID:{params.get("id")}')
+ data = [data["illust"]]
+ img_data = {}
+ for x in data:
+ pid = x["id"]
+ title = x["title"]
+ width = x["width"]
+ height = x["height"]
+ view = x["total_view"]
+ bookmarks = x["total_bookmarks"]
+ uid = x["user"]["id"]
+ author = x["user"]["name"]
+ tags = []
+ for tag in x["tags"]:
+ for i in tag:
+ if tag[i]:
+ tags.append(tag[i])
+ img_urls = []
+ if x["page_count"] == 1:
+ img_urls.append(x["meta_single_page"]["original_image_url"])
else:
- logger.info(f'获取数据成功...PID:{params.get("id")}')
- data = [data["illust"]]
- img_data = {}
- for x in data:
- pid = x["id"]
- title = x["title"]
- width = x["width"]
- height = x["height"]
- view = x["total_view"]
- bookmarks = x["total_bookmarks"]
- uid = x["user"]["id"]
- author = x["user"]["name"]
- tags = []
- for tag in x["tags"]:
- for i in tag:
- if tag[i]:
- tags.append(tag[i])
- img_urls = []
- if x["page_count"] == 1:
- img_urls.append(x["meta_single_page"]["original_image_url"])
- else:
- for urls in x["meta_pages"]:
- img_urls.append(urls["image_urls"]["original"])
- if (
- (
- bookmarks
- >= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
- or (
- url == f"{HIBIAPI}/api/pixiv/member_illust"
- and bookmarks >= 1500
- )
- or (url == f"{HIBIAPI}/api/pixiv/illust")
+ for urls in x["meta_pages"]:
+ img_urls.append(urls["image_urls"]["original"])
+ if (
+ (
+ bookmarks >= Config.get_config("pix", "SEARCH_HIBIAPI_BOOKMARKS")
+ or (
+ url == f"{HIBIAPI}/api/pixiv/member_illust"
+ and bookmarks >= 1500
)
- and len(img_urls) < 10
- and _check_black(img_urls, black)
+ or (url == f"{HIBIAPI}/api/pixiv/illust")
+ )
+ and len(img_urls) < 10
+ and _check_black(img_urls, black)
+ ):
+ img_data[pid] = {
+ "pid": pid,
+ "title": title,
+ "width": width,
+ "height": height,
+ "view": view,
+ "bookmarks": bookmarks,
+ "img_urls": img_urls,
+ "uid": uid,
+ "author": author,
+ "tags": tags,
+ }
+ else:
+ continue
+ for x in img_data.keys():
+ data = img_data[x]
+ data_copy = deepcopy(data)
+ del data_copy["img_urls"]
+ for img_url in data["img_urls"]:
+ img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
+ data_copy["img_url"] = img_url
+ data_copy["img_p"] = img_p
+ data_copy["is_r18"] = "R-18" in data["tags"]
+ if not await Pixiv.exists(
+ pid=data["pid"], img_url=img_url, img_p=img_p
):
- img_data[pid] = {
- "pid": pid,
- "title": title,
- "width": width,
- "height": height,
- "view": view,
- "bookmarks": bookmarks,
- "img_urls": img_urls,
- "uid": uid,
- "author": author,
- "tags": tags,
- }
+ data_copy["img_url"] = img_url
+ await Pixiv.create(**data_copy)
+ if data["pid"] not in tmp_pid:
+ pid_count += 1
+ tmp_pid.append(data["pid"])
+ pic_count += 1
+ logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
else:
- continue
- for x in img_data.keys():
- data = img_data[x]
- for img_url in data["img_urls"]:
- img_p = img_url[img_url.rfind("_") + 1 : img_url.rfind(".")]
- try:
- if await Pixiv.add_image_data(
- data["pid"],
- data["title"],
- data["width"],
- data["height"],
- data["view"],
- data["bookmarks"],
- img_url,
- img_p,
- data["uid"],
- data["author"],
- ",".join(data["tags"]),
- ):
- if data["pid"] not in tmp_pid:
- pid_count += 1
- tmp_pid.append(data["pid"])
- pic_count += 1
- logger.info(f'存储图片PID:{data["pid"]} IMG_P:{img_p}')
- except UniqueViolationError:
- logger.warning(f'{data["pid"]} | {img_url} 已存在...')
- except Exception as e:
- logger.warning(f"PIX在线搜索图片错误,已再次调用 {type(e)}:{e}")
- await search_image(url, keyword, params, semaphore, page, black)
+ logger.warning(f'{data["pid"]} | {img_url} 已存在...')
+ # except Exception as e:
+ # logger.warning(f"PIX在线搜索图片错误,已再次调用 {type(e)}:{e}")
+ # await search_image(url, keyword, params, semaphore, page, black)
return pid_count, pic_count
@@ -206,7 +203,9 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
params = {"id": pid}
for _ in range(3):
try:
- response = await AsyncHttpx.get(f"{HIBIAPI}/api/pixiv/illust", params=params)
+ response = await AsyncHttpx.get(
+ f"{HIBIAPI}/api/pixiv/illust", params=params
+ )
if response.status_code == 200:
data = response.json()
if data.get("illust"):
@@ -215,22 +214,28 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
"original_image_url"
]
else:
- img_url = data["illust"]["meta_pages"][0][
- "image_urls"
- ]["original"]
+ img_url = data["illust"]["meta_pages"][0]["image_urls"][
+ "original"
+ ]
break
except TimeoutError:
pass
old_img_url = img_url
img_url = change_pixiv_image_links(
- img_url, Config.get_config("pix", "PIX_IMAGE_SIZE"), Config.get_config("pixiv", "PIXIV_NGINX_URL")
+ img_url,
+ Config.get_config("pix", "PIX_IMAGE_SIZE"),
+ Config.get_config("pixiv", "PIXIV_NGINX_URL"),
)
old_img_url = change_pixiv_image_links(
old_img_url, None, Config.get_config("pixiv", "PIXIV_NGINX_URL")
)
for _ in range(3):
try:
- response = await AsyncHttpx.get(img_url, headers=headers, timeout=Config.get_config("pix", "TIMEOUT"),)
+ response = await AsyncHttpx.get(
+ img_url,
+ headers=headers,
+ timeout=Config.get_config("pix", "TIMEOUT"),
+ )
if response.status_code == 404:
img_url = old_img_url
continue
@@ -238,7 +243,9 @@ async def get_image(img_url: str, user_id: int) -> Optional[str]:
TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg", "wb"
) as f:
await f.write(response.content)
- change_img_md5(TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg")
+ change_img_md5(
+ TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg"
+ )
return TEMP_PATH / f"pix_{user_id}_{img_url.split('/')[-1][:-4]}.jpg"
except TimeoutError:
logger.warning(f"PIX:{img_url} 图片下载超时...")
@@ -264,7 +271,7 @@ async def uid_pid_exists(id_: str) -> bool:
return True
-async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
+async def get_keyword_num(keyword: str) -> Tuple[int, int, int, int, int]:
"""
查看图片相关 tag 数量
:param keyword: 关键词tag
@@ -276,7 +283,7 @@ async def get_keyword_num(keyword: str) -> "int, int, int, int, int":
return count, r18_count, count_, setu_count, r18_count_
-async def remove_image(pid: int, img_p: str) -> bool:
+async def remove_image(pid: int, img_p: Optional[str]):
"""
删除置顶图片
:param pid: pid
@@ -285,7 +292,10 @@ async def remove_image(pid: int, img_p: str) -> bool:
if img_p:
if "p" not in img_p:
img_p = f"p{img_p}"
- return await Pixiv.remove_image_data(pid, img_p)
+ if img_p:
+ await Pixiv.filter(pid=pid, img_p=img_p).delete()
+ else:
+ await Pixiv.filter(pid=pid).delete()
def gen_keyword_pic(
@@ -392,6 +402,3 @@ def _check_black(img_urls: List[str], black: List[str]) -> bool:
if b in img_url:
return False
return True
-
-
-
diff --git a/plugins/pix_gallery/_model/omega_pixiv_illusts.py b/plugins/pix_gallery/_model/omega_pixiv_illusts.py
index 27721fc3..c80c5f45 100644
--- a/plugins/pix_gallery/_model/omega_pixiv_illusts.py
+++ b/plugins/pix_gallery/_model/omega_pixiv_illusts.py
@@ -1,79 +1,50 @@
-from typing import Optional, List, Tuple
-from services.db_context import db
+from typing import List, Optional, Tuple
+
+from tortoise import fields
+from tortoise.contrib.postgres.functions import Random
+
+from services.db_context import Model
-class OmegaPixivIllusts(db.Model):
- __tablename__ = "omega_pixiv_illusts"
- __table_args__ = {'extend_existing': True}
+class OmegaPixivIllusts(Model):
- id = db.Column(db.Integer(), primary_key=True)
- pid = db.Column(db.BigInteger(), nullable=False)
- uid = db.Column(db.BigInteger(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- uname = db.Column(db.String(), nullable=False)
- classified = db.Column(db.Integer(), nullable=False)
- nsfw_tag = db.Column(db.Integer(), nullable=False)
- width = db.Column(db.Integer(), nullable=False)
- height = db.Column(db.Integer(), nullable=False)
- tags = db.Column(db.String(), nullable=False)
- url = db.Column(db.String(), nullable=False)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ pid = fields.BigIntField()
+ """pid"""
+ uid = fields.BigIntField()
+ """uid"""
+ title = fields.CharField(255)
+ """标题"""
+ uname = fields.CharField(255)
+ """画师名称"""
+ classified = fields.IntField()
+ """标记标签, 0=未标记, 1=已人工标记或从可信已标记来源获取"""
+ nsfw_tag = fields.IntField()
+ """nsfw标签,-1=未标记, 0=safe, 1=setu. 2=r18"""
+ width = fields.IntField()
+ """宽度"""
+ height = fields.IntField()
+ """高度"""
+ tags = fields.TextField()
+ """tags"""
+ url = fields.CharField(255)
+ """pixiv url链接"""
- _idx1 = db.Index("omega_pixiv_illusts_idx1", "pid", "url", unique=True)
-
- @classmethod
- async def add_image_data(
- cls,
- pid: int,
- title: str,
- width: int,
- height: int,
- url: str,
- uid: int,
- uname: str,
- classified: int,
- nsfw_tag: int,
- tags: str,
- ):
- """
- 说明:
- 添加图片信息
- 参数:
- :param pid: pid
- :param title: 标题
- :param width: 宽度
- :param height: 长度
- :param url: url链接
- :param uid: 作者uid
- :param uname: 作者名称
- :param classified: 标记标签, 0=未标记, 1=已人工标记或从可信已标记来源获取
- :param nsfw_tag: nsfw标签,-1=未标记, 0=safe, 1=setu. 2=r18
- :param tags: 相关tag
- """
- if not await cls.check_exists(pid):
- await cls.create(
- pid=pid,
- title=title,
- width=width,
- height=height,
- url=url,
- uid=uid,
- uname=uname,
- classified=classified,
- nsfw_tag=nsfw_tag,
- tags=tags,
- )
- return True
- return False
+ class Meta:
+ table = "omega_pixiv_illusts"
+ table_description = "omega图库数据表"
+ unique_together = ("pid", "url")
@classmethod
async def query_images(
- cls,
- keywords: Optional[List[str]] = None,
- uid: Optional[int] = None,
- pid: Optional[int] = None,
- nsfw_tag: Optional[int] = 0,
- num: int = 100
- ) -> List[Optional["OmegaPixivIllusts"]]:
+ cls,
+ keywords: Optional[List[str]] = None,
+ uid: Optional[int] = None,
+ pid: Optional[int] = None,
+ nsfw_tag: Optional[int] = 0,
+ num: int = 100,
+ ) -> List["OmegaPixivIllusts"]:
"""
说明:
查找符合条件的图片
@@ -84,66 +55,38 @@ class OmegaPixivIllusts(db.Model):
:param nsfw_tag: nsfw标签, 0=safe, 1=setu. 2=r18
:param num: 获取图片数量
"""
+ if not num:
+ return []
+ query = cls
if nsfw_tag is not None:
- query = cls.query.where(cls.nsfw_tag == nsfw_tag)
- else:
- query = cls.query
+ query = cls.filter(nsfw_tag=nsfw_tag)
if keywords:
for keyword in keywords:
- query = query.where(cls.tags.contains(keyword))
+ query = query.filter(tags__contains=keyword)
elif uid:
- query = query.where(cls.uid == uid)
+ query = query.filter(uid=uid)
elif pid:
- query = query.where(cls.uid == pid)
- query = query.order_by(db.func.random()).limit(num)
- return await query.gino.all()
+ query = query.filter(pid=pid)
+ query = query.annotate(rand=Random()).limit(num)
+ return await query.all() # type: ignore
@classmethod
- async def check_exists(cls, pid: int) -> bool:
- """
- 说明:
- 检测pid是否已存在
- 参数:
- :param pid: 图片PID
- """
- query = await cls.query.where(cls.pid == pid).gino.all()
- return bool(query)
-
- @classmethod
- async def get_keyword_num(cls, tags: List[str] = None) -> Tuple[int, int, int]:
+ async def get_keyword_num(
+ cls, tags: Optional[List[str]] = None
+ ) -> Tuple[int, int, int]:
"""
说明:
获取相关关键词(keyword, tag)在图库中的数量
参数:
:param tags: 关键词/Tag
"""
- setattr(OmegaPixivIllusts, 'count', db.func.count(cls.pid).label('count'))
- query = cls.select('count')
+ query = cls
if tags:
for tag in tags:
- query = query.where(cls.tags.contains(tag))
- 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]:
- """
- 说明:
- 获取所有图片PID
- """
- data = await cls.select('pid').gino.all()
- return [x[0] for x in data]
-
- # 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)
-
-
-
+ query = query.filter(tags__contains=tag)
+ else:
+ query = query.all()
+ count = await query.filter(nsfw_tag=0).count()
+ setu_count = await query.filter(nsfw_tag=1).count()
+ r18_count = await query.filter(nsfw_tag=2).count()
+ return count, setu_count, r18_count
diff --git a/plugins/pix_gallery/_model/pixiv.py b/plugins/pix_gallery/_model/pixiv.py
index 485d5934..4af995a5 100644
--- a/plugins/pix_gallery/_model/pixiv.py
+++ b/plugins/pix_gallery/_model/pixiv.py
@@ -1,105 +1,43 @@
-from typing import Optional, List
-from services.db_context import db
+from typing import List, Optional, Tuple
+
+from tortoise import fields
+from tortoise.contrib.postgres.functions import Random
+
+from services.db_context import Model
-class Pixiv(db.Model):
- __tablename__ = "pixiv"
- __table_args__ = {'extend_existing': True}
+class Pixiv(Model):
- id = db.Column(db.Integer(), primary_key=True)
- pid = db.Column(db.BigInteger(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- width = db.Column(db.Integer(), nullable=False)
- height = db.Column(db.Integer(), nullable=False)
- view = db.Column(db.Integer(), nullable=False)
- bookmarks = db.Column(db.Integer(), nullable=False)
- img_url = db.Column(db.String(), nullable=False)
- img_p = db.Column(db.String(), nullable=False)
- uid = db.Column(db.BigInteger(), nullable=False)
- author = db.Column(db.String(), nullable=False)
- is_r18 = db.Column(db.Boolean(), nullable=False)
- tags = db.Column(db.String(), nullable=False)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ pid = fields.BigIntField()
+ """pid"""
+ uid = fields.BigIntField()
+ """uid"""
+ author = fields.CharField(255)
+ """作者"""
+ title = fields.CharField(255)
+ """标题"""
+ width = fields.IntField()
+ """宽度"""
+ height = fields.IntField()
+ """高度"""
+ view = fields.IntField()
+ """pixiv查看数"""
+ bookmarks = fields.IntField()
+ """收藏数"""
+ tags = fields.TextField()
+ """tags"""
+ img_url = fields.CharField(255)
+ """pixiv url链接"""
+ img_p = fields.CharField(255)
+ """图片pN"""
+ is_r18 = fields.BooleanField()
- _idx1 = db.Index("pixiv_idx1", "pid", "img_url", unique=True)
-
- @classmethod
- async def add_image_data(
- cls,
- pid: int,
- title: str,
- width: int,
- height: int,
- view: int,
- bookmarks: int,
- img_url: str,
- img_p: str,
- uid: int,
- author: str,
- tags: str,
- ):
- """
- 说明:
- 添加图片信息
- 参数:
- :param pid: pid
- :param title: 标题
- :param width: 宽度
- :param height: 长度
- :param view: 被查看次数
- :param bookmarks: 收藏数
- :param img_url: url链接
- :param img_p: 张数
- :param uid: 作者uid
- :param author: 作者名称
- :param tags: 相关tag
- """
- if not await cls.check_exists(pid, img_p):
- await cls.create(
- pid=pid,
- title=title,
- width=width,
- height=height,
- view=view,
- bookmarks=bookmarks,
- img_url=img_url,
- img_p=img_p,
- uid=uid,
- author=author,
- is_r18=True if "R-18" in tags else False,
- tags=tags,
- )
- return True
- return False
-
- @classmethod
- async def remove_image_data(cls, pid: int, img_p: str) -> bool:
- """
- 说明:
- 删除图片数据
- 参数:
- :param pid: 图片pid
- :param img_p: 图片pid的张数,如:p0,p1
- """
- try:
- if img_p:
- await cls.delete.where(
- (cls.pid == pid) & (cls.img_p == img_p)
- ).gino.status()
- else:
- await cls.delete.where(cls.pid == pid).gino.status()
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_all_pid(cls) -> List[int]:
- """
- 说明:
- 获取所有PID
- """
- query = await cls.query.select("pid").gino.first()
- pid = [x[0] for x in query]
- return list(set(pid))
+ class Meta:
+ table = "pixiv"
+ table_description = "pix图库数据表"
+ unique_together = ("pid", "img_url", "img_p")
# 0:非r18 1:r18 2:混合
@classmethod
@@ -109,7 +47,7 @@ class Pixiv(db.Model):
uid: Optional[int] = None,
pid: Optional[int] = None,
r18: Optional[int] = 0,
- num: int = 100
+ num: int = 100,
) -> List[Optional["Pixiv"]]:
"""
说明:
@@ -121,50 +59,37 @@ class Pixiv(db.Model):
:param r18: 是否r18,0:非r18 1:r18 2:混合
:param num: 查找图片的数量
"""
+ if not num:
+ return []
+ query = cls
if r18 == 0:
- query = cls.query.where(cls.is_r18 == False)
+ query = query.filter(is_r18=False)
elif r18 == 1:
- query = cls.query.where(cls.is_r18 == True)
- else:
- query = cls.query
+ query = query.filter(is_r18=True)
if keywords:
for keyword in keywords:
- query = query.where(cls.tags.contains(keyword))
+ query = query.filter(tags__contains=keyword)
elif uid:
- query = query.where(cls.uid == uid)
+ query = query.filter(uid=uid)
elif pid:
- query = query.where(cls.pid == pid)
- query = query.order_by(db.func.random()).limit(num)
- return await query.gino.all()
+ query = query.filter(pid=pid)
+ query = query.annotate(rand=Random()).limit(num)
+ return await query.all() # type: ignore
@classmethod
- async def check_exists(cls, pid: int, img_p: str) -> bool:
- """
- 说明:
- 检测pid是否已存在
- 参数:
- :param pid: 图片PID
- :param img_p: 张数
- """
- query = await cls.query.where(
- (cls.pid == pid) & (cls.img_p == img_p)
- ).gino.all()
- return bool(query)
-
- @classmethod
- async def get_keyword_num(cls, tags: List[str] = None) -> "int, int":
+ async def get_keyword_num(cls, tags: Optional[List[str]] = None) -> Tuple[int, int]:
"""
说明:
获取相关关键词(keyword, tag)在图库中的数量
参数:
:param tags: 关键词/Tag
"""
- setattr(Pixiv, 'count', db.func.count(cls.pid).label('count'))
- query = cls.select('count')
+ query = cls
if tags:
for tag in tags:
- 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]
-
+ query = query.filter(tags__contains=tag)
+ else:
+ query = query.all()
+ count = await query.filter(is_r18=False).count()
+ r18_count = await query.filter(is_r18=True).count()
+ return count, r18_count
diff --git a/plugins/pix_gallery/_model/pixiv_keyword_user.py b/plugins/pix_gallery/_model/pixiv_keyword_user.py
index 8271c179..4e7797c0 100644
--- a/plugins/pix_gallery/_model/pixiv_keyword_user.py
+++ b/plugins/pix_gallery/_model/pixiv_keyword_user.py
@@ -1,101 +1,42 @@
-from services.db_context import db
-from typing import Set, List
+from typing import List, Set, Tuple
+
+from tortoise import fields
+
+from services.db_context import Model
-class PixivKeywordUser(db.Model):
+class PixivKeywordUser(Model):
__tablename__ = "pixiv_keyword_users"
- __table_args__ = {'extend_existing': True}
+ __table_args__ = {"extend_existing": True}
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- keyword = db.Column(db.String(), nullable=False)
- is_pass = db.Column(db.Boolean(), default=False)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ keyword = fields.CharField(255, unique=True)
+ """关键词"""
+ is_pass = fields.BooleanField()
+ """是否通过"""
- _idx1 = db.Index("pixiv_keyword_users_idx1", "keyword", unique=True)
+ class Meta:
+ table = "pixiv_keyword_users"
+ table_description = "pixiv关键词数据表"
@classmethod
- async def add_keyword(
- cls, user_qq: int, group_id: int, keyword: str, superusers: Set[str]
- ) -> bool:
- """
- 说明:
- 添加搜图的关键词
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- :param keyword: 关键词
- :param superusers: 是否为超级用户
- """
- is_pass = True if str(user_qq) in superusers else False
- if not await cls._check_keyword_exists(keyword):
- await cls.create(
- user_qq=user_qq, group_id=group_id, keyword=keyword, is_pass=is_pass
- )
- return True
- return False
-
- @classmethod
- async def delete_keyword(cls, keyword: str) -> bool:
- """
- 说明:
- 删除关键词
- 参数:
- :param keyword: 关键词
- """
- if await cls._check_keyword_exists(keyword):
- query = cls.query.where(cls.keyword == keyword).with_for_update()
- query = await query.gino.first()
- await query.delete()
- return True
- return False
-
- @classmethod
- async def set_keyword_pass(cls, keyword: str, is_pass: bool) -> "int, int":
- """
- 说明:
- 通过或禁用关键词
- 参数:
- :param keyword: 关键词
- :param is_pass: 通过状态
- """
- if await cls._check_keyword_exists(keyword):
- query = cls.query.where(cls.keyword == keyword).with_for_update()
- query = await query.gino.first()
- await query.update(
- is_pass=is_pass,
- ).apply()
- return query.user_qq, query.group_id
- return 0, 0
-
- @classmethod
- async def get_all_user_dict(cls) -> dict:
- """
- 说明:
- 获取关键词数据库各个用户贡献的关键词字典
- """
- tmp = {}
- query = await cls.query.gino.all()
- for user in query:
- if not tmp.get(user.user_qq):
- tmp[user.user_qq] = {"keyword": []}
- tmp[user.user_qq]["keyword"].append(user.keyword)
- return tmp
-
- @classmethod
- async def get_current_keyword(cls) -> "List[str], List[str]":
+ async def get_current_keyword(cls) -> Tuple[List[str], List[str]]:
"""
说明:
获取当前通过与未通过的关键词
"""
pass_keyword = []
not_pass_keyword = []
- query = await cls.query.gino.all()
- for user in query:
- if user.is_pass:
- pass_keyword.append(user.keyword)
+ for data in await cls.all().values_list("keyword", "is_pass"):
+ if data[1]:
+ pass_keyword.append(data[0])
else:
- not_pass_keyword.append(user.keyword)
+ not_pass_keyword.append(data[0])
return pass_keyword, not_pass_keyword
@classmethod
@@ -105,23 +46,9 @@ class PixivKeywordUser(db.Model):
获取黑名单PID
"""
black_pid = []
- query = await cls.query.where(cls.user_qq == 114514).gino.all()
- for image in query:
- black_pid.append(image.keyword[6:])
+ keyword_list = await cls.filter(user_qq=114514).values_list(
+ "keyword", flat=True
+ )
+ for image in keyword_list:
+ black_pid.append(image[6:])
return black_pid
-
- @classmethod
- async def _check_keyword_exists(cls, keyword: str) -> bool:
- """
- 说明:
- 检测关键词是否已存在
- 参数:
- :param keyword: 关键词
- """
- current_keyword = []
- query = await cls.query.gino.all()
- for user in query:
- current_keyword.append(user.keyword)
- if keyword in current_keyword:
- return True
- return False
diff --git a/plugins/pix_gallery/pix_add_keyword.py b/plugins/pix_gallery/pix_add_keyword.py
index 2f3b8c0e..9ac1bdf1 100755
--- a/plugins/pix_gallery/pix_add_keyword.py
+++ b/plugins/pix_gallery/pix_add_keyword.py
@@ -1,14 +1,17 @@
-from nonebot import on_command
-from utils.utils import is_number
-from services.log import logger
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
-from nonebot.params import CommandArg, Command
from typing import Tuple
-from ._data_source import uid_pid_exists
-from ._model.pixiv_keyword_user import PixivKeywordUser
-from ._model.pixiv import Pixiv
+
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Command, CommandArg
from nonebot.permission import SUPERUSER
+from services.log import logger
+from utils.utils import is_number
+
+from ._data_source import uid_pid_exists
+from ._model.pixiv import Pixiv
+from ._model.pixiv_keyword_user import PixivKeywordUser
+
__zx_plugin_name__ = "PIX关键词/UID/PID添加管理 [Superuser]"
__plugin_usage__ = """
usage:
@@ -46,9 +49,16 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
if isinstance(event, GroupMessageEvent):
group_id = event.group_id
if msg:
- if await PixivKeywordUser.add_keyword(
- event.user_id, group_id, msg, bot.config.superusers
- ):
+ # if await PixivKeywordUser.add_keyword(
+ # event.user_id, group_id, msg, bot.config.superusers
+ # ):
+ if not await PixivKeywordUser.exists(keyword=msg):
+ await PixivKeywordUser.create(
+ user_qq=event.user_id,
+ group_id=group_id,
+ keyword=msg,
+ is_pass=str(event.user_id) in bot.config.superusers,
+ )
await add_keyword.send(
f"已成功添加pixiv搜图关键词:{msg},请等待管理员通过该关键词!", at_sender=True
)
@@ -63,7 +73,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
@add_uid_pid.handle()
-async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
+async def _(
+ bot: Bot,
+ event: MessageEvent,
+ cmd: Tuple[str, ...] = Command(),
+ arg: Message = CommandArg(),
+):
msg = arg.extract_plain_text().strip()
exists_flag = True
if msg.find("-f") != -1 and str(event.user_id) in bot.config.superusers:
@@ -77,16 +92,23 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
msg = f"uid:{msg}"
else:
msg = f"pid:{msg}"
- if await Pixiv.check_exists(int(msg[4:]), "p0"):
+ if await Pixiv.get_or_none(pid=int(msg[4:]), img_p="p0"):
await add_uid_pid.finish(f"该PID:{msg[4:]}已存在...", at_sender=True)
if not await uid_pid_exists(msg) and exists_flag:
await add_uid_pid.finish("画师或作品不存在或搜索正在CD,请稍等...", at_sender=True)
group_id = -1
if isinstance(event, GroupMessageEvent):
group_id = event.group_id
- if await PixivKeywordUser.add_keyword(
- event.user_id, group_id, msg, bot.config.superusers
- ):
+ # if await PixivKeywordUser.add_keyword(
+ # event.user_id, group_id, msg, bot.config.superusers
+ # ):
+ if not await PixivKeywordUser.exists(keyword=msg):
+ await PixivKeywordUser.create(
+ user_qq=event.user_id,
+ group_id=group_id,
+ keyword=msg,
+ is_pass=str(event.user_id) in bot.config.superusers,
+ )
await add_uid_pid.send(
f"已成功添加pixiv搜图UID/PID:{msg[4:]},请等待管理员通过!", at_sender=True
)
@@ -106,12 +128,21 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
pid = pid[: pid.find("p")]
if not is_number(pid):
await add_black_pid.finish("PID必须全部是数字!", at_sender=True)
- if await PixivKeywordUser.add_keyword(
- 114514,
- 114514,
- f"black:{pid}{f'_p{img_p}' if img_p else ''}",
- bot.config.superusers,
+ # if await PixivKeywordUser.add_keyword(
+ # 114514,
+ # 114514,
+ # f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ # bot.config.superusers,
+ # ):
+ if not await PixivKeywordUser.exists(
+ keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
):
+ await PixivKeywordUser.create(
+ user_qq=114514,
+ group_id=114514,
+ keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ is_pass=str(event.user_id) in bot.config.superusers,
+ )
await add_black_pid.send(f"已添加PID:{pid} 至黑名单中...")
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
diff --git a/plugins/pix_gallery/pix_pass_del_keyword.py b/plugins/pix_gallery/pix_pass_del_keyword.py
index 3ce7e83b..293bb80b 100755
--- a/plugins/pix_gallery/pix_pass_del_keyword.py
+++ b/plugins/pix_gallery/pix_pass_del_keyword.py
@@ -1,15 +1,17 @@
-from nonebot import on_command
-from utils.utils import is_number
-from utils.message_builder import at
-from services.log import logger
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent, Message
-from nonebot.params import CommandArg, Command
-from nonebot.permission import SUPERUSER
-from ._data_source import remove_image
-from ._model.pixiv_keyword_user import PixivKeywordUser
-from ._model.pixiv import Pixiv
from typing import Tuple
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Command, CommandArg
+from nonebot.permission import SUPERUSER
+
+from services.log import logger
+from utils.message_builder import at
+from utils.utils import is_number
+
+from ._data_source import remove_image
+from ._model.pixiv import Pixiv
+from ._model.pixiv_keyword_user import PixivKeywordUser
__zx_plugin_name__ = "PIX关键词/UID/PID删除管理 [Superuser]"
__plugin_usage__ = """
@@ -60,7 +62,8 @@ async def _(event: MessageEvent, arg: Message = CommandArg()):
msg = f"uid:{msg}"
if msg.lower().startswith("pid"):
msg = "pid:" + msg.replace("pid", "").replace(":", "")
- if await PixivKeywordUser.delete_keyword(msg):
+ if data := await PixivKeywordUser.get_or_none(keyword=msg):
+ await data.delete()
await del_keyword.send(f"删除搜图关键词/UID:{msg} 成功...")
logger.info(
f"(USER {event.user_id}, GROUP {event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
@@ -97,22 +100,31 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
if await remove_image(int(pid), img_p):
msg += f'{pid}{f"_p{img_p}" if img_p else ""},'
if flag:
- if await PixivKeywordUser.add_keyword(
- 114514,
- 114514,
- f"black:{pid}{f'_p{img_p}' if img_p else ''}",
- bot.config.superusers,
+ # if await PixivKeywordUser.add_keyword(
+ # 114514,
+ # 114514,
+ # f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ # bot.config.superusers,
+ # ):
+ if await PixivKeywordUser.exists(
+ keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}"
):
+ await PixivKeywordUser.create(
+ user_qq=114514,
+ group_id=114514,
+ keyword=f"black:{pid}{f'_p{img_p}' if img_p else ''}",
+ is_pass=False,
+ )
black_pid += f'{pid}{f"_p{img_p}" if img_p else ""},'
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
f" 删除了PIX图片 PID:{pid}{f'_p{img_p}' if img_p else ''}"
)
- else:
- await del_pic.send(
- f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
- )
+ # else:
+ # await del_pic.send(
+ # f"PIX:删除pid:{pid}{f'_p{img_p}' if img_p else ''} 失败.."
+ # )
else:
await del_pic.send(
f"PIX:图片pix:{pid}{f'_p{img_p}' if img_p else ''} 不存在...无法删除.."
@@ -127,7 +139,12 @@ async def _(bot: Bot, event: MessageEvent, arg: Message = CommandArg()):
@pass_keyword.handle()
-async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg: Message = CommandArg()):
+async def _(
+ bot: Bot,
+ event: MessageEvent,
+ cmd: Tuple[str, ...] = Command(),
+ arg: Message = CommandArg(),
+):
tmp = {"group": {}, "private": {}}
msg = arg.extract_plain_text().strip()
if not msg:
@@ -145,7 +162,13 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
if not is_number(x[4:]):
await pass_keyword.send(f"UID/PID:{x} 非全数字,跳过该关键词...")
continue
- user_id, group_id = await PixivKeywordUser.set_keyword_pass(x, flag)
+ data = await PixivKeywordUser.get_or_none(keyword=x)
+ user_id = 0
+ group_id = 0
+ if data:
+ data.is_pass = flag
+ await data.save(update_fields=["is_pass"])
+ user_id, group_id = data.user_qq, data.group_id
if not user_id:
await pass_keyword.send(f"未找到关键词/UID:{x},请检查关键词/UID是否存在...")
continue
@@ -163,7 +186,7 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
else:
tmp["group"][group_id][user_id]["keyword"].append(x)
msg = " ".join(msg)
- await pass_keyword.send(f'已成功{cmd[0][:2]}搜图关键词:{msg}....')
+ await pass_keyword.send(f"已成功{cmd[0][:2]}搜图关键词:{msg}....")
for user in tmp["private"]:
x = ",".join(tmp["private"][user]["keyword"])
await bot.send_private_msg(
diff --git a/plugins/pix_gallery/pix_show_info.py b/plugins/pix_gallery/pix_show_info.py
index 6ea55d03..dcfbef4b 100755
--- a/plugins/pix_gallery/pix_show_info.py
+++ b/plugins/pix_gallery/pix_show_info.py
@@ -1,11 +1,13 @@
-from nonebot import on_command
-from utils.message_builder import image
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, Message
-from ._data_source import gen_keyword_pic, get_keyword_num
-from ._model.pixiv_keyword_user import PixivKeywordUser
-from nonebot.params import CommandArg
import asyncio
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, Message, MessageEvent
+from nonebot.params import CommandArg
+
+from utils.message_builder import image
+
+from ._data_source import gen_keyword_pic, get_keyword_num
+from ._model.pixiv_keyword_user import PixivKeywordUser
__zx_plugin_name__ = "查看pix图库"
__plugin_usage__ = """
@@ -35,12 +37,12 @@ show_pix = on_command("查看pix图库", priority=1, block=True)
@my_keyword.handle()
async def _(event: MessageEvent):
- data = await PixivKeywordUser.get_all_user_dict()
- if data.get(event.user_id) is None or not data[event.user_id]["keyword"]:
- await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
- await my_keyword.send(
- f"您目前提供的如下关键字:\n\t" + ",".join(data[event.user_id]["keyword"])
+ data = await PixivKeywordUser.filter(user_qq=event.user_id).values_list(
+ "keyword", flat=True
)
+ if not data:
+ await my_keyword.finish("您目前没有提供任何Pixiv搜图关键字...", at_sender=True)
+ await my_keyword.send(f"您目前提供的如下关键字:\n\t" + ",".join(data))
@show_keyword.handle()
diff --git a/plugins/pix_gallery/pix_update.py b/plugins/pix_gallery/pix_update.py
index 4db3d5fa..ce19604f 100755
--- a/plugins/pix_gallery/pix_update.py
+++ b/plugins/pix_gallery/pix_update.py
@@ -1,21 +1,22 @@
-import re
-
-from nonebot import on_command
-from utils.utils import is_number
-from nonebot.permission import SUPERUSER
-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.onebot.v11 import Message
-from nonebot.params import CommandArg
-import time
-from services.log import logger
-from pathlib import Path
-from typing import List
import asyncio
import os
+import re
+import time
+from pathlib import Path
+from typing import List
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Message
+from nonebot.params import CommandArg
+from nonebot.permission import SUPERUSER
+
+from services.log import logger
+from utils.utils import is_number
+
+from ._data_source import start_update_image_url
+from ._model.omega_pixiv_illusts import OmegaPixivIllusts
+from ._model.pixiv import Pixiv
+from ._model.pixiv_keyword_user import PixivKeywordUser
__zx_plugin_name__ = "pix检查更新 [Superuser]"
__plugin_usage__ = """
@@ -146,11 +147,11 @@ async def _(arg: Message = CommandArg()):
async def _():
async def _tasks(line: str, all_pid: List[int], length: int, index: int):
data = line.split("VALUES", maxsplit=1)[-1].strip()[1:-2]
- num_list = re.findall(r'(\d+)', data)
+ num_list = re.findall(r"(\d+)", data)
pid = int(num_list[1])
uid = int(num_list[2])
id_ = 3
- while num_list[id_] not in ['0', '1']:
+ while num_list[id_] not in ["0", "1"]:
id_ += 1
classified = int(num_list[id_])
nsfw_tag = int(num_list[id_ + 1])
@@ -164,23 +165,25 @@ async def _():
if pid in all_pid:
logger.info(f"添加OmegaPixivIllusts图库数据已存在 ---> pid:{pid}")
return
- if await OmegaPixivIllusts.add_image_data(
- pid=pid,
- title=title,
- width=width,
- height=height,
- url=url,
- uid=uid,
- nsfw_tag=nsfw_tag,
- tags=tags,
- uname=uname,
- classified=classified
- ):
+ _, is_create = await OmegaPixivIllusts.get_or_create(
+ pid=pid,
+ title=title,
+ width=width,
+ height=height,
+ url=url,
+ uid=uid,
+ nsfw_tag=nsfw_tag,
+ tags=tags,
+ uname=uname,
+ classified=classified,
+ )
+ if is_create:
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_artwork" in file and ".sql" in file:
@@ -190,13 +193,13 @@ async def _():
lines = f.readlines()
tasks = []
length = len([x for x in lines if "INSERT INTO" in x.upper()])
- all_pid = await OmegaPixivIllusts.get_all_pid()
+ all_pid = await OmegaPixivIllusts.all().values_list("pid", flat=True)
index = 0
logger.info("检测到OmegaPixivIllusts数据库,准备开始更新....")
for line in lines:
if "INSERT INTO" in line.upper():
index += 1
- logger.info(f'line: {line} 加入更新计划')
+ logger.info(f"line: {line} 加入更新计划")
tasks.append(
asyncio.ensure_future(_tasks(line, all_pid, length, index))
)
diff --git a/plugins/pixiv_rank_search/data_source.py b/plugins/pixiv_rank_search/data_source.py
index b4eb3f2e..d9b007a0 100755
--- a/plugins/pixiv_rank_search/data_source.py
+++ b/plugins/pixiv_rank_search/data_source.py
@@ -1,13 +1,14 @@
-from configs.path_config import IMAGE_PATH
+import platform
+from asyncio.exceptions import TimeoutError
+from pathlib import Path
+from typing import Optional
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH, TEMP_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
from utils.message_builder import image
from utils.utils import change_img_md5
-from asyncio.exceptions import TimeoutError
-from configs.config import Config
-from utils.http_utils import AsyncHttpx
-from typing import Optional
-from services.log import logger
-from pathlib import Path
-import platform
# if platform.system() == "Windows":
# import asyncio
@@ -133,9 +134,9 @@ async def download_pixiv_imgs(
)
try:
file = (
- f"{IMAGE_PATH}/temp/{user_id}_{forward_msg_index}_{index}_pixiv.jpg"
+ TEMP_PATH / f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg"
if forward_msg_index is not None
- else f"{IMAGE_PATH}/temp/{user_id}_{index}_pixiv.jpg"
+ else TEMP_PATH / f"{user_id}_{index}_pixiv.jpg"
)
file = Path(file)
try:
@@ -147,11 +148,11 @@ async def download_pixiv_imgs(
change_img_md5(file)
if forward_msg_index is not None:
result += image(
- f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
- "temp",
+ TEMP_PATH
+ / f"{user_id}_{forward_msg_index}_{index}_pixiv.jpg",
)
else:
- result += image(f"{user_id}_{index}_pixiv.jpg", "temp")
+ result += image(TEMP_PATH / f"{user_id}_{index}_pixiv.jpg")
index += 1
except OSError:
if file.exists():
diff --git a/plugins/poke/__init__.py b/plugins/poke/__init__.py
index 43e87ebb..180935c2 100755
--- a/plugins/poke/__init__.py
+++ b/plugins/poke/__init__.py
@@ -1,12 +1,14 @@
+import os
+import random
+
from nonebot import on_notice
from nonebot.adapters.onebot.v11 import PokeNotifyEvent
-from configs.path_config import RECORD_PATH, IMAGE_PATH
-from utils.message_builder import record, image, poke
-from services.log import logger
-import random
-from utils.utils import CountLimiter
+
+from configs.path_config import IMAGE_PATH, RECORD_PATH
from models.ban_user import BanUser
-import os
+from services.log import logger
+from utils.message_builder import image, poke, record
+from utils.utils import CountLimiter
__zx_plugin_name__ = "戳一戳"
@@ -64,13 +66,17 @@ async def _poke_event(event: PokeNotifyEvent):
rand = random.random()
path = random.choice(["luoli", "meitu"])
if rand <= 0.3 and len(os.listdir(IMAGE_PATH / "image_management" / path)) > 0:
- index = random.randint(0, len(os.listdir(IMAGE_PATH / "image_management" / path)) - 1)
- result = f"id:{index}" + image(f"{index}.jpg", "image_management/" + path)
+ index = random.randint(
+ 0, len(os.listdir(IMAGE_PATH / "image_management" / path)) - 1
+ )
+ result = f"id:{index}" + image(
+ IMAGE_PATH / "image_management" / path / f"{index}.jpg"
+ )
await poke_.send(result)
logger.info(f"USER {event.user_id} 戳了戳我 回复: {result} {result}")
elif 0.3 < rand < 0.6:
voice = random.choice(os.listdir(RECORD_PATH / "dinggong"))
- result = record(voice, "dinggong")
+ result = record(RECORD_PATH / "dinggong" / voice)
await poke_.send(result)
await poke_.send(voice.split("_")[1])
logger.info(
diff --git a/plugins/russian/__init__.py b/plugins/russian/__init__.py
index c10ea1e6..99b8792d 100755
--- a/plugins/russian/__init__.py
+++ b/plugins/russian/__init__.py
@@ -1,20 +1,22 @@
+import asyncio
+import random
+import time
+from typing import Tuple
+
from nonebot import on_command
from nonebot.adapters.onebot.v11 import GROUP, Bot, GroupMessageEvent, Message
+from nonebot.params import ArgStr, Command, CommandArg
from nonebot.typing import T_State
-from utils.utils import is_number, get_message_at
-from nonebot.params import CommandArg, Command, ArgStr
-from models.group_member_info import GroupInfoUser
-from utils.message_builder import at, image
-from .model import RussianUser
-from models.bag_user import BagUser
-from services.log import logger
-from .data_source import rank
-from configs.config import NICKNAME, Config
-from typing import Tuple
-import random
-import asyncio
-import time
+from configs.config import NICKNAME, Config
+from models.bag_user import BagUser
+from models.group_member_info import GroupInfoUser
+from services.log import logger
+from utils.message_builder import at, image
+from utils.utils import get_message_at, is_number
+
+from .data_source import rank
+from .model import RussianUser
__zx_plugin_name__ = "俄罗斯轮盘"
__plugin_usage__ = """
@@ -156,7 +158,9 @@ async def _(event: GroupMessageEvent):
await accept.finish("又不是找你决斗,你拒绝什么啊!气!", at_sender=True)
if rs_player[event.group_id]["at"] == event.user_id:
at_player_name = (
- await GroupInfoUser.get_member_info(event.user_id, event.group_id)
+ await GroupInfoUser.get_or_none(
+ user_qq=event.user_id, group_id=event.group_id
+ )
).user_name
await accept.send(
Message(f"{at(rs_player[event.group_id][1])}\n" f"{at_player_name}拒绝了你的对决!")
@@ -291,7 +295,7 @@ async def _(
at_ = at_[0]
try:
at_player_name = (
- await GroupInfoUser.get_member_info(at_, event.group_id)
+ await GroupInfoUser.get_or_none(user_qq=at_, group_id=event.group_id)
).user_name
except AttributeError:
at_player_name = at(at_)
@@ -359,14 +363,14 @@ async def _(bot: Bot, event: GroupMessageEvent):
[
f"不要打扰 {player1_name} 和 {player2_name} 的决斗啊!",
f"给我好好做好一个观众!不然{NICKNAME}就要生气了",
- f"不要捣乱啊baka{(await GroupInfoUser.get_member_info(event.user_id, event.group_id)).user_name}!",
+ f"不要捣乱啊baka{(await GroupInfoUser.get_or_none(user_qq=event.user_id, group_id=event.group_id)).user_name}!",
]
),
at_sender=True,
)
await shot.finish(
f"你的左轮不是连发的!该 "
- f'{(await GroupInfoUser.get_member_info(int(rs_player[event.group_id]["next"]), event.group_id)).user_name} 开枪了'
+ f'{(await GroupInfoUser.get_or_none(user_qq=int(rs_player[event.group_id]["next"]), group_id=event.group_id)).user_name} 开枪了'
)
if rs_player[event.group_id]["bullet"][rs_player[event.group_id]["index"]] != 1:
await shot.send(
@@ -440,8 +444,12 @@ async def end_game(bot: Bot, event: GroupMessageEvent):
await RussianUser.money(lose_user_id, event.group_id, "lose", money)
await BagUser.add_gold(win_user_id, event.group_id, money - fee)
await BagUser.spend_gold(lose_user_id, event.group_id, money)
- win_user = await RussianUser.ensure(win_user_id, event.group_id)
- lose_user = await RussianUser.ensure(lose_user_id, event.group_id)
+ win_user, _ = await RussianUser.get_or_create(
+ user_qq=win_user_id, group_id=event.group_id
+ )
+ lose_user, _ = await RussianUser.get_or_create(
+ user_qq=lose_user_id, group_id=event.group_id
+ )
bullet_str = ""
for x in rs_player[event.group_id]["bullet"]:
bullet_str += "__ " if x == 0 else "| "
@@ -467,7 +475,9 @@ async def end_game(bot: Bot, event: GroupMessageEvent):
@record.handle()
async def _(event: GroupMessageEvent):
- user = await RussianUser.ensure(event.user_id, event.group_id)
+ user, _ = await RussianUser.get_or_create(
+ user_qq=event.user_id, group_id=event.group_id
+ )
await record.send(
f"俄罗斯轮盘\n"
f"总胜利场次:{user.win_count}\n"
diff --git a/plugins/russian/data_source.py b/plugins/russian/data_source.py
index 765cbaca..e5ae6e7d 100755
--- a/plugins/russian/data_source.py
+++ b/plugins/russian/data_source.py
@@ -1,42 +1,33 @@
-from .model import RussianUser
from typing import Optional
+
from utils.data_utils import init_rank
from utils.image_utils import BuildMat
+from .model import RussianUser
+
async def rank(group_id: int, itype: str, num: int) -> Optional[BuildMat]:
- all_users = await RussianUser.get_all_user(group_id)
+ all_users = await RussianUser.filter(group_id=group_id).all()
all_user_id = [user.user_qq for user in all_users]
- if itype == 'win_rank':
- rank_name = '胜场排行榜'
+ if itype == "win_rank":
+ rank_name = "胜场排行榜"
all_user_data = [user.win_count for user in all_users]
- elif itype == 'lose_rank':
- rank_name = '败场排行榜'
+ elif itype == "lose_rank":
+ rank_name = "败场排行榜"
all_user_data = [user.fail_count for user in all_users]
- elif itype == 'make_money':
- rank_name = '赢取金币排行榜'
+ elif itype == "make_money":
+ rank_name = "赢取金币排行榜"
all_user_data = [user.make_money for user in all_users]
- elif itype == 'spend_money':
- rank_name = '输掉金币排行榜'
+ elif itype == "spend_money":
+ rank_name = "输掉金币排行榜"
all_user_data = [user.lose_money for user in all_users]
- elif itype == 'max_winning_streak':
- rank_name = '最高连胜排行榜'
+ elif itype == "max_winning_streak":
+ rank_name = "最高连胜排行榜"
all_user_data = [user.max_winning_streak for user in all_users]
else:
- rank_name = '最高连败排行榜'
+ rank_name = "最高连败排行榜"
all_user_data = [user.max_losing_streak for user in all_users]
rst = None
if all_users:
rst = await init_rank(rank_name, all_user_id, all_user_data, group_id, num)
return rst
-
-
-
-
-
-
-
-
-
-
-
diff --git a/plugins/russian/model.py b/plugins/russian/model.py
index 577b96c8..62a4a08c 100755
--- a/plugins/russian/model.py
+++ b/plugins/russian/model.py
@@ -1,43 +1,41 @@
-from services.db_context import db
-from typing import List
+
+from tortoise import fields
+
+from services.db_context import Model
-class RussianUser(db.Model):
- __tablename__ = "russian_users"
- __table_args__ = {'extend_existing': True}
+class RussianUser(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger(), nullable=False)
- win_count = db.Column(db.Integer(), default=0)
- fail_count = db.Column(db.Integer(), default=0)
- make_money = db.Column(db.Integer(), default=0)
- lose_money = db.Column(db.Integer(), default=0)
- winning_streak = db.Column(db.Integer(), default=0)
- losing_streak = db.Column(db.Integer(), default=0)
- max_winning_streak = db.Column(db.Integer(), default=0)
- max_losing_streak = db.Column(db.Integer(), default=0)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField()
+ """群聊id"""
+ win_count = fields.IntField(default=0)
+ """胜利次数"""
+ fail_count = fields.IntField(default=0)
+ """失败次数"""
+ make_money = fields.IntField(default=0)
+ """赢得金币"""
+ lose_money = fields.IntField(default=0)
+ """输得金币"""
+ winning_streak = fields.IntField(default=0)
+ """当前连胜"""
+ losing_streak = fields.IntField(default=0)
+ """当前连败"""
+ max_winning_streak = fields.IntField(default=0)
+ """最大连胜"""
+ max_losing_streak = fields.IntField(default=0)
+ """最大连败"""
- _idx1 = db.Index("russian_group_users_idx1", "user_qq", "group_id", unique=True)
+ class Meta:
+ table = "russian_users"
+ table_description = "俄罗斯轮盘数据表"
+ unique_together = ("user_qq", "group_id")
@classmethod
- async def ensure(cls, user_qq: int, group_id: int) -> "RussianUser":
- """
- 说明:
- 获取用户对象
- 参数:
- :param user_qq: qq号
- :param group_id: 群号
- """
- user = (
- await cls.query.where((cls.user_qq == user_qq) & (cls.group_id == group_id))
- .with_for_update()
- .gino.first()
- )
- return user or await cls.create(user_qq=user_qq, group_id=group_id)
-
- @classmethod
- async def add_count(cls, user_qq: int, group_id: int, itype: str) -> bool:
+ async def add_count(cls, user_qq: int, group_id: int, itype: str):
"""
说明:
添加用户输赢次数
@@ -46,43 +44,43 @@ class RussianUser(db.Model):
:param group_id: 群号
:param itype: 输或赢 'win' or 'lose'
"""
- try:
- user = (
- await cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- .with_for_update()
- .gino.first()
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ if itype == "win":
+ _max = (
+ user.max_winning_streak
+ if user.max_winning_streak > user.winning_streak + 1
+ else user.winning_streak + 1
+ )
+ user.win_count = user.win_count + 1
+ user.winning_streak = user.winning_streak + 1
+ user.losing_streak = 0
+ user.max_winning_streak = _max
+ await user.save(
+ update_fields=[
+ "win_count",
+ "winning_streak",
+ "losing_streak",
+ "max_winning_streak",
+ ]
+ )
+ elif itype == "lose":
+ _max = (
+ user.max_losing_streak
+ if user.max_losing_streak > user.losing_streak + 1
+ else user.losing_streak + 1
+ )
+ user.fail_count = user.fail_count + 1
+ user.losing_streak = user.losing_streak + 1
+ user.winning_streak = 0
+ user.max_losing_streak = _max
+ await user.save(
+ update_fields=[
+ "fail_count",
+ "winning_streak",
+ "losing_streak",
+ "max_losing_streak",
+ ]
)
- if not user:
- user = await cls.create(user_qq=user_qq, group_id=group_id)
- if itype == "win":
- _max = (
- user.max_winning_streak
- if user.max_winning_streak > user.winning_streak + 1
- else user.winning_streak + 1
- )
- await user.update(
- win_count=user.win_count + 1,
- winning_streak=user.winning_streak + 1,
- losing_streak=0,
- max_winning_streak=_max
- ).apply()
- elif itype == "lose":
- _max = (
- user.max_losing_streak
- if user.max_losing_streak > user.losing_streak + 1
- else user.losing_streak + 1
- )
- await user.update(
- fail_count=user.fail_count + 1,
- losing_streak=user.losing_streak + 1,
- winning_streak=0,
- max_losing_streak=_max,
- ).apply()
- return True
- except Exception:
- return False
@classmethod
async def money(cls, user_qq: int, group_id: int, itype: str, count: int) -> bool:
@@ -95,35 +93,9 @@ class RussianUser(db.Model):
:param itype: 输或赢 'win' or 'lose'
:param count: 金钱数量
"""
- try:
- user = (
- await cls.query.where(
- (cls.user_qq == user_qq) & (cls.group_id == group_id)
- )
- .with_for_update()
- .gino.first()
- )
- if not user:
- user = await cls.create(user_qq=user_qq, group_id=group_id)
- if itype == "win":
- await user.update(
- make_money=user.make_money + count,
- ).apply()
- elif itype == "lose":
- await user.update(
- lose_money=user.lose_money + count,
- ).apply()
- return True
- except Exception:
- return False
-
- @classmethod
- async def get_all_user(cls, group_id: int) -> List["RussianUser"]:
- """
- 说明:
- 获取该群所有用户对象
- 参数:
- :param group_id: 群号
- """
- users = await cls.query.where((cls.group_id == group_id)).gino.all()
- return users
+ user, _ = await cls.get_or_create(user_qq=user_qq, group_id=group_id)
+ if itype == "win":
+ user.make_money = user.make_money + count
+ elif itype == "lose":
+ user.lose_money = user.lose_money + count
+ await user.save(update_fields=["make_money", "lose_money"])
diff --git a/plugins/send_dinggong_voice/__init__.py b/plugins/send_dinggong_voice/__init__.py
index 438634f7..5fe37c44 100755
--- a/plugins/send_dinggong_voice/__init__.py
+++ b/plugins/send_dinggong_voice/__init__.py
@@ -1,12 +1,14 @@
+import os
+import random
+
from nonebot import on_keyword
-from utils.message_builder import record
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+
from configs.path_config import RECORD_PATH
from services.log import logger
-from nonebot.typing import T_State
-from nonebot.adapters.onebot.v11 import Bot, MessageEvent, GroupMessageEvent
-from nonebot.rule import to_me
-import random
-import os
+from utils.message_builder import record
__zx_plugin_name__ = "骂我"
__plugin_usage__ = """
@@ -25,10 +27,7 @@ __plugin_settings__ = {
"limit_superuser": False,
"cmd": ["骂老子", "骂我"],
}
-__plugin_cd_limit__ = {
- "cd": 3,
- "rst": "就...就算求我骂你也得慢慢来..."
-}
+__plugin_cd_limit__ = {"cd": 3, "rst": "就...就算求我骂你也得慢慢来..."}
dg_voice = on_keyword({"骂"}, rule=to_me(), priority=5, block=True)
@@ -38,7 +37,9 @@ dg_voice = on_keyword({"骂"}, rule=to_me(), priority=5, block=True)
async def _(bot: Bot, event: MessageEvent, state: T_State):
if len(str((event.get_message()))) > 1:
voice = random.choice(os.listdir(RECORD_PATH / "dinggong"))
- result = record(voice, "dinggong")
+ result = record(
+ RECORD_PATH / "dinggong" / voice,
+ )
await dg_voice.send(result)
await dg_voice.send(voice.split("_")[1])
logger.info(
diff --git a/plugins/send_setu_/_model.py b/plugins/send_setu_/_model.py
index 403333a9..82f52c3b 100644
--- a/plugins/send_setu_/_model.py
+++ b/plugins/send_setu_/_model.py
@@ -1,64 +1,44 @@
-from services.db_context import db
from typing import List, Optional
+from tortoise import fields
+from tortoise.contrib.postgres.functions import Random
+from tortoise.expressions import Q
-class Setu(db.Model):
- __tablename__ = "setu"
- __table_args__ = {'extend_existing': True}
+from services.db_context import Model
- id = db.Column(db.Integer(), primary_key=True)
- local_id = db.Column(db.Integer(), nullable=False)
- title = db.Column(db.String(), nullable=False)
- author = db.Column(db.String(), nullable=False)
- pid = db.Column(db.BigInteger(), nullable=False)
- img_hash = db.Column(db.String(), nullable=False)
- img_url = db.Column(db.String(), nullable=False)
- is_r18 = db.Column(db.Boolean(), nullable=False)
- tags = db.Column(db.String())
- _idx1 = db.Index("setu_pid_img_url_idx1", "pid", "img_url", unique=True)
+class Setu(Model):
- @classmethod
- async def add_setu_data(
- cls,
- local_id: int,
- title: str,
- author: str,
- pid: int,
- img_hash: str,
- img_url: str,
- tags: str,
- ):
- """
- 说明:
- 添加一份色图数据
- 参数:
- :param local_id: 本地存储id
- :param title: 标题
- :param author: 作者
- :param pid: 图片pid
- :param img_hash: 图片hash值
- :param img_url: 图片链接
- :param tags: 图片标签
- """
- if not await cls._check_exists(pid, img_url):
- await cls.create(
- local_id=local_id,
- title=title,
- author=author,
- pid=pid,
- img_hash=img_hash,
- img_url=img_url,
- is_r18=True if "R-18" in tags else False,
- tags=tags,
- )
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ local_id = fields.IntField()
+ """本地存储下标"""
+ title = fields.CharField(255)
+ """标题"""
+ author = fields.CharField(255)
+ """作者"""
+ pid = fields.BigIntField()
+ """pid"""
+ img_hash = fields.TextField()
+ """图片hash"""
+ img_url = fields.CharField(255)
+ """pixiv url链接"""
+ is_r18 = fields.BooleanField()
+ """是否r18"""
+ tags = fields.TextField()
+ """tags"""
+
+ class Meta:
+ table = "setu"
+ table_description = "色图数据表"
+ unique_together = ("pid", "img_url")
@classmethod
async def query_image(
cls,
local_id: Optional[int] = None,
tags: Optional[List[str]] = None,
- r18: int = 0,
+ r18: bool = False,
limit: int = 50,
):
"""
@@ -71,58 +51,17 @@ class Setu(db.Model):
:param limit: 获取数量
"""
if local_id:
- flag = True if r18 == 1 else False
- return await cls.query.where(
- (cls.local_id == local_id) & (cls.is_r18 == flag)
- ).gino.first()
- if r18 == 0:
- query = cls.query.where(cls.is_r18 == False)
- elif r18 == 1:
- query = cls.query.where(cls.is_r18 == True)
- else:
- query = cls.query
+ return await cls.filter(is_r18=r18, local_id=local_id).first()
+ query = cls.filter(is_r18=r18)
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(limit)
- return await query.gino.all()
-
- @classmethod
- async def get_image_count(cls, r18: int = 0) -> int:
- """
- 说明:
- 查询图片数量
- """
- 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":
- """
- 说明:
- 通过图像hash获取图像信息
- 参数:
- :param img_hash: = 图像hash值
- """
- query = await cls.query.where(cls.img_hash == img_hash).gino.first()
- return query
-
- @classmethod
- async def _check_exists(cls, pid: int, img_url: str) -> bool:
- """
- 说明:
- 检测图片是否存在
- 参数:
- :param pid: 图片pid
- :param img_url: 图片链接
- """
- return bool(
- await cls.query.where(
- (cls.pid == pid) & (cls.img_url == img_url)
- ).gino.first()
- )
+ query = query.filter(
+ Q(tags__contains=tag)
+ | Q(title__contains=tag)
+ | Q(author__contains=tag)
+ )
+ query = query.annotate(rand=Random()).limit(limit)
+ return await query.all()
@classmethod
async def delete_image(cls, pid: int) -> int:
@@ -132,66 +71,14 @@ class Setu(db.Model):
参数:
:param pid: 图片pid
"""
- query = await cls.query.where(cls.pid == pid).gino.first()
+ return_id = -1
+ query = await cls.get_or_none(pid=pid)
if query:
- is_r18 = query.is_r18
- num = await cls.get_image_count(is_r18)
- x = await cls.query.where((cls.is_r18 == is_r18) & (cls.local_id == num - 1)).gino.first()
- _tmp_local_id = x.local_id
- if x:
- x.update(local_id=query.local_id).apply()
- await cls.delete.where(cls.pid == pid).gino.status()
- return _tmp_local_id
- return -1
-
- @classmethod
- async def update_setu_data(
- cls,
- pid: int,
- *,
- local_id: Optional[int] = None,
- title: Optional[str] = None,
- author: Optional[str] = None,
- img_hash: Optional[str] = None,
- img_url: Optional[str] = None,
- tags: Optional[str] = None,
- ) -> bool:
- """
- 说明:
- 根据PID修改图片数据
- 参数:
- :param local_id: 本地id
- :param pid: 图片pid
- :param title: 标题
- :param author: 作者
- :param img_hash: 图片hash值
- :param img_url: 图片链接
- :param tags: 图片标签
- """
- query = cls.query.where(cls.pid == pid).with_for_update()
- image_list = await query.gino.all()
- if image_list:
- for image in image_list:
- if local_id:
- await image.update(local_id=local_id).apply()
- if title:
- await image.update(title=title).apply()
- if author:
- await image.update(author=author).apply()
- if img_hash:
- await image.update(img_hash=img_hash).apply()
- if img_url:
- await image.update(img_url=img_url).apply()
- if tags:
- await image.update(tags=tags).apply()
- return True
- return False
-
- @classmethod
- async def get_all_setu(cls) -> List["Setu"]:
- """
- 说明:
- 获取所有图片对象
- """
- return await cls.query.gino.all()
-
+ num = await cls.filter(is_r18=query.is_r18).count()
+ last_image = await cls.get_or_none(is_r18=query.is_r18, local_id=num - 1)
+ if last_image:
+ return_id = last_image.local_id
+ last_image.local_id = query.local_id
+ await last_image.save(update_fields=["local_id"])
+ await query.delete()
+ return return_id
diff --git a/plugins/send_setu_/send_setu/__init__.py b/plugins/send_setu_/send_setu/__init__.py
index 1a9cf25d..b6c4fb6c 100755
--- a/plugins/send_setu_/send_setu/__init__.py
+++ b/plugins/send_setu_/send_setu/__init__.py
@@ -1,42 +1,40 @@
import random
-from nonebot import on_command, on_regex
-from services.log import logger
-from models.sign_group_user import SignGroupUser
-from nonebot.message import run_postprocessor
-from nonebot.matcher import Matcher
-from typing import Optional, Type, Any
-from gino.exceptions import UninitializedError
+import re
+from typing import Any, Optional, Tuple, Type
-from utils.message_builder import custom_forward_msg
-from utils.utils import (
- is_number,
-)
-from nonebot.typing import T_State
+from nonebot import on_command, on_regex
from nonebot.adapters.onebot.v11 import (
- Bot,
ActionFailed,
- MessageEvent,
- GroupMessageEvent,
- PrivateMessageEvent,
- Message,
+ Bot,
Event,
+ GroupMessageEvent,
+ Message,
+ MessageEvent,
+ PrivateMessageEvent,
)
+from nonebot.matcher import Matcher
+from nonebot.message import run_postprocessor
+from nonebot.params import Command, CommandArg, RegexGroup
+from nonebot.typing import T_State
+
+from configs.config import NICKNAME, Config
+from models.sign_group_user import SignGroupUser
+from services.log import logger
+from utils.manager import withdraw_message_manager
+from utils.message_builder import custom_forward_msg
+from utils.utils import is_number
+
+from .._model import Setu
from .data_source import (
- get_setu_list,
- get_luoxiang,
- search_online_setu,
- get_setu_urls,
+ add_data_to_database,
+ check_local_exists_or_download,
find_img_index,
gen_message,
- check_local_exists_or_download,
- add_data_to_database,
- get_setu_count,
+ get_luoxiang,
+ get_setu_list,
+ get_setu_urls,
+ search_online_setu,
)
-from configs.config import Config, NICKNAME
-from utils.manager import withdraw_message_manager
-from nonebot.params import CommandArg, Command, RegexGroup
-from typing import Tuple
-import re
try:
import ujson as json
@@ -126,7 +124,7 @@ async def do_something(
await add_data_to_database(setu_data_list)
logger.info("色图数据自动存储数据库成功...")
setu_data_list = []
- except UninitializedError:
+ except Exception:
pass
@@ -146,17 +144,18 @@ async def _(
):
msg = arg.extract_plain_text().strip()
if isinstance(event, GroupMessageEvent):
- impression = (
- await SignGroupUser.ensure(event.user_id, event.group_id)
- ).impression
+ user, _ = await SignGroupUser.get_or_create(
+ user_qq=event.user_id, group_id=event.group_id
+ )
+ impression = user.impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox)
- r18 = 0
+ r18 = False
num = 1
# 是否看r18
if cmd[0] == "色图r" and isinstance(event, PrivateMessageEvent):
- r18 = 1
+ r18 = True
num = 10
elif cmd[0] == "色图r" and isinstance(event, GroupMessageEvent):
if not Config.get_config("send_setu", "ALLOW_GROUP_R18"):
@@ -164,18 +163,20 @@ async def _(
random.choice(["这种不好意思的东西怎么可能给这么多人看啦", "羞羞脸!给我滚出克私聊!", "变态变态变态变态大变态!"])
)
else:
- r18 = 1
+ r18 = False
# 有 数字 的话先尝试本地色图id
if msg and is_number(msg):
setu_list, code = await get_setu_list(int(msg), r18=r18)
if code != 200:
await setu.finish(setu_list[0], at_sender=True)
setu_img, code = await check_local_exists_or_download(setu_list[0])
- msg_id = await setu.send(gen_message(setu_list[0]) + setu_img, at_sender=True)
+ msg_id = await setu.send(
+ Message(gen_message(setu_list[0])) + setu_img, at_sender=True
+ )
logger.info(
f"(USER {event.user_id}, GROUP "
f"{event.group_id if isinstance(event, GroupMessageEvent) else 'private'})"
- f" 发送色图 {setu_list[0].local_id}.png"
+ f" 发送色图 {setu_list[0].local_id}.jpd"
)
if msg_id:
withdraw_message_manager.withdraw_message(
@@ -205,9 +206,10 @@ num_key = {
@setu_reg.handle()
async def _(bot: Bot, event: MessageEvent, reg_group: Tuple[Any, ...] = RegexGroup()):
if isinstance(event, GroupMessageEvent):
- impression = (
- await SignGroupUser.ensure(event.user_id, event.group_id)
- ).impression
+ user, _ = await SignGroupUser.get_or_create(
+ user_qq=event.user_id, group_id=event.group_id
+ )
+ impression = user.impression
luox = get_luoxiang(impression)
if luox:
await setu.finish(luox, at_sender=True)
@@ -220,7 +222,7 @@ async def _(bot: Bot, event: MessageEvent, reg_group: Tuple[Any, ...] = RegexGro
num = int(num)
except ValueError:
num = 1
- await send_setu_handle(bot, setu_reg, event, "色图", tags, num, 0)
+ await send_setu_handle(bot, setu_reg, event, "色图", tags, num, False)
async def send_setu_handle(
@@ -230,7 +232,7 @@ async def send_setu_handle(
command: str,
msg: str,
num: int,
- r18: int,
+ r18: bool,
):
global setu_data_list
# 非 id,在线搜索
@@ -240,7 +242,7 @@ async def send_setu_handle(
await matcher.finish("咳咳咳,虽然我很可爱,但是我木有自己的色图~~~有的话记得发我一份呀")
# 本地先拿图,下载失败补上去
setu_list, code = None, 200
- setu_count = await get_setu_count(r18)
+ setu_count = await Setu.filter(is_r18=r18).count()
if (
not Config.get_config("send_setu", "ONLY_USE_LOCAL_SETU") and tags
) or setu_count <= 0:
diff --git a/plugins/send_setu_/send_setu/data_source.py b/plugins/send_setu_/send_setu/data_source.py
index 66f3c046..4bca9e12 100755
--- a/plugins/send_setu_/send_setu/data_source.py
+++ b/plugins/send_setu_/send_setu/data_source.py
@@ -1,18 +1,22 @@
-from configs.path_config import IMAGE_PATH, TEMP_PATH
-from utils.message_builder import image
-from services.log import logger
-from utils.image_utils import get_img_hash, compressed_image
-from utils.utils import change_img_md5
-from asyncpg.exceptions import UniqueViolationError
-from asyncio.exceptions import TimeoutError
-from typing import List, Optional
-from configs.config import NICKNAME, Config
-from utils.http_utils import AsyncHttpx
-from .._model import Setu
import asyncio
import os
import random
import re
+from asyncio.exceptions import TimeoutError
+from typing import List, Optional, Tuple, Union
+
+from asyncpg.exceptions import UniqueViolationError
+from nonebot.adapters.onebot.v11 import Message, MessageSegment
+
+from configs.config import NICKNAME, Config
+from configs.path_config import IMAGE_PATH, TEMP_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import compressed_image, get_img_hash
+from utils.message_builder import image
+from utils.utils import change_img_md5
+
+from .._model import Setu
try:
import ujson as json
@@ -28,11 +32,11 @@ host_pattern = re.compile(r"https?://([^/]+)")
# 获取url
async def get_setu_urls(
- tags: List[str], num: int = 1, r18: int = 0, command: str = ""
-) -> "List[str], List[str], List[tuple], int":
+ tags: List[str], num: int = 1, r18: bool = False, command: str = ""
+) -> Tuple[List[str], List[str], List[tuple], int]:
tags = tags[:3] if len(tags) > 3 else tags
params = {
- "r18": r18, # 添加r18参数 0为否,1为是,2为混合
+ "r18": 1 if r18 else 0, # 添加r18参数 0为否,1为是,2为混合
"tag": tags, # 若指定tag
"num": 20, # 一次返回的结果数量
"size": ["original"],
@@ -82,7 +86,7 @@ headers = {
async def search_online_setu(
url_: str, id_: Optional[int] = None, path_: Optional[str] = None
-) -> "MessageSegment, int":
+) -> Tuple[Union[MessageSegment, str], int]:
"""
下载色图
:param url_: 色图url
@@ -108,10 +112,7 @@ async def search_online_setu(
):
continue
if id_ is not None:
- if (
- os.path.getsize(path_ / f"{index}.jpg")
- > 1024 * 1024 * 1.5
- ):
+ if os.path.getsize(path_ / f"{index}.jpg") > 1024 * 1024 * 1.5:
compressed_image(
path_ / f"{index}.jpg",
)
@@ -126,7 +127,9 @@ async def search_online_setu(
# 检测本地是否有id涩图,无的话则下载
-async def check_local_exists_or_download(setu_image: Setu) -> "MessageSegment, int":
+async def check_local_exists_or_download(
+ setu_image: Setu,
+) -> Tuple[MessageSegment, int]:
path_ = None
id_ = None
if Config.get_config("send_setu", "DOWNLOAD_SETU"):
@@ -148,27 +151,28 @@ async def add_data_to_database(lst: List[tuple]):
if tmp:
for x in tmp:
try:
- r18 = 1 if "R-18" in x[5] else 0
- idx = await Setu.get_image_count(r18)
- await Setu.add_setu_data(
- idx,
- x[0],
- x[1],
- x[2],
- x[3],
- x[4],
- x[5],
- )
+ idx = await Setu.filter(is_r18="R-18" in x[5]).count()
+ if not await Setu.exists(pid=x[2], img_url=x[4]):
+ await Setu.create(
+ local_id=idx,
+ title=x[0],
+ author=x[1],
+ pid=x[2],
+ img_hash=x[3],
+ img_url=x[4],
+ tags=x[5],
+ is_r18="R-18" in x[5],
+ )
except UniqueViolationError:
pass
# 拿到本地色图列表
async def get_setu_list(
- index: Optional[int] = None, tags: Optional[List[str]] = None, r18: int = 0
-) -> "list, int":
+ index: Optional[int] = None, tags: Optional[List[str]] = None, r18: bool = False
+) -> Tuple[list, int]:
if index:
- image_count = await Setu.get_image_count(r18) - 1
+ image_count = await Setu.filter(is_r18=r18).count() - 1
if index < 0 or index > image_count:
return [f"超过当前上下限!({image_count})"], 999
image_list = [await Setu.query_image(index, r18=r18)]
@@ -182,44 +186,44 @@ async def get_setu_list(
# 初始化消息
-def gen_message(setu_image: Setu, img_msg: bool = False) -> str:
+def gen_message(
+ setu_image: Setu, img_msg: bool = False
+) -> Union[Message, MessageSegment]:
local_id = setu_image.local_id
title = setu_image.title
author = setu_image.author
pid = setu_image.pid
+ path_ = r18_path if setu_image.is_r18 else path
+ image_path = IMAGE_PATH / path_ / f"{local_id}.jpg"
if Config.get_config("send_setu", "SHOW_INFO"):
- return (
+ return Message(
f"id:{local_id}\n"
f"title:{title}\n"
f"author:{author}\n"
- f"PID:{pid}\n"
- f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
+ f"PID:{pid}\n" + image(image_path)
)
- return f"{image(f'{local_id}', f'{r18_path if setu_image.is_r18 else path}') if img_msg else ''}"
+ return image(image_path)
# 罗翔老师!
def get_luoxiang(impression):
probability = (
- impression + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
+ float(impression)
+ + Config.get_config("send_setu", "INITIAL_SETU_PROBABILITY") * 100
)
if probability < random.randint(1, 101):
return (
"我为什么要给你发这个?"
- + image(random.choice(os.listdir(IMAGE_PATH / "luoxiang")), "luoxiang")
+ + image(
+ IMAGE_PATH
+ / "luoxiang"
+ / random.choice(os.listdir(IMAGE_PATH / "luoxiang"))
+ )
+ f"\n(快向{NICKNAME}签到提升好感度吧!)"
)
return None
-async def get_setu_count(r18: int) -> int:
- """
- 获取色图数量
- :param r18: r18类型
- """
- return await Setu.get_image_count(r18)
-
-
async def find_img_index(img_url, user_id):
if not await AsyncHttpx.download_file(
img_url,
@@ -228,8 +232,7 @@ async def find_img_index(img_url, user_id):
):
return "检索图片下载上失败..."
img_hash = str(get_img_hash(TEMP_PATH / f"{user_id}_find_setu_index.jpg"))
- setu_img = await Setu.get_image_in_hash(img_hash)
- if setu_img:
+ if setu_img := await Setu.get_or_none(img_hash=img_hash):
return (
f"id:{setu_img.local_id}\n"
f"title:{setu_img.title}\n"
diff --git a/plugins/send_setu_/update_setu/data_source.py b/plugins/send_setu_/update_setu/data_source.py
index 771b0d83..039e3118 100755
--- a/plugins/send_setu_/update_setu/data_source.py
+++ b/plugins/send_setu_/update_setu/data_source.py
@@ -1,18 +1,21 @@
-from configs.path_config import IMAGE_PATH, TEXT_PATH, TEMP_PATH
-from services.log import logger
-from datetime import datetime
-from utils.image_utils import compressed_image, get_img_hash
-from utils.utils import get_bot
-from PIL import UnidentifiedImageError
-from .._model import Setu
-from asyncpg.exceptions import UniqueViolationError
-from configs.config import Config
-from utils.http_utils import AsyncHttpx
-from nonebot import Driver
-import nonebot
import os
-import ujson as json
import shutil
+from datetime import datetime
+
+import nonebot
+import ujson as json
+from asyncpg.exceptions import UniqueViolationError
+from nonebot import Driver
+from PIL import UnidentifiedImageError
+
+from configs.config import Config
+from configs.path_config import IMAGE_PATH, TEMP_PATH, TEXT_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import compressed_image, get_img_hash
+from utils.utils import change_pixiv_image_links, get_bot
+
+from .._model import Setu
driver: Driver = nonebot.get_driver()
@@ -47,15 +50,17 @@ async def update_old_setu_data():
)
# idx = r18_index if 'R-18' in data[x]["tags"] else index
try:
- await Setu.add_setu_data(
- idx,
- data[x]["title"],
- data[x]["author"],
- data[x]["pid"],
- data[x]["img_hash"],
- img_url,
- ",".join(data[x]["tags"]),
- )
+ if not await Setu.exists(pid=data[x]["pid"], url=img_url):
+ await Setu.create(
+ local_id=idx,
+ title=data[x]["title"],
+ author=data[x]["author"],
+ pid=data[x]["pid"],
+ img_hash=data[x]["img_hash"],
+ img_url=img_url,
+ is_r18="R-18" in data[x]["tags"],
+ tags=",".join(data[x]["tags"]),
+ )
count += 1
if "R-18" in data[x]["tags"]:
r18_index += 1
@@ -94,7 +99,7 @@ async def update_setu_img(flag: bool = False):
更新色图
:param flag: 是否手动更新
"""
- image_list = await Setu.get_all_setu()
+ image_list = await Setu.all().order_by("local_id")
image_list.reverse()
_success = 0
error_info = []
@@ -110,12 +115,7 @@ async def update_setu_img(flag: bool = False):
temp_file = TEMP_PATH / f"{image.local_id}.jpg"
if temp_file.exists():
temp_file.unlink()
- 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_ = change_pixiv_image_links(image.img_url)
try:
if not await AsyncHttpx.download_file(
url_, TEMP_PATH / f"{image.local_id}.jpg"
@@ -146,15 +146,20 @@ async def update_setu_img(flag: bool = False):
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)
+ image.img_hash = img_hash
+ await image.save(update_fields=["img_hash"])
+ # await Setu.update_setu_data(image.pid, img_hash=img_hash)
except UnidentifiedImageError:
# 图片已删除
- with open(local_image, 'r') as f:
- if '404 Not Found' in f.read():
- max_num = await Setu.delete_image(image.pid)
- local_image.unlink()
- os.rename(path / f"{max_num}.jpg", local_image)
- logger.warning(f"更新色图 PID:{image.pid} 404,已删除并替换")
+ unlink = False
+ with open(local_image, "r") as f:
+ if "404 Not Found" in f.read():
+ unlink = True
+ if unlink:
+ local_image.unlink()
+ max_num = await Setu.delete_image(image.pid)
+ os.rename(path / f"{max_num}.jpg", local_image)
+ logger.warning(f"更新色图 PID:{image.pid} 404,已删除并替换")
except Exception as e:
_success -= 1
logger.error(f"更新色图 {image.local_id}.jpg 错误 {type(e)}: {e}")
diff --git a/plugins/sign_in/goods_register.py b/plugins/sign_in/goods_register.py
index 545b5e0d..748400c3 100644
--- a/plugins/sign_in/goods_register.py
+++ b/plugins/sign_in/goods_register.py
@@ -1,9 +1,9 @@
-
-from models.sign_group_user import SignGroupUser
-from configs.config import Config
-from nonebot import Driver
-from utils.decorator.shop import shop_register, NotMeetUseConditionsException
import nonebot
+from nonebot import Driver
+
+from configs.config import Config
+from models.sign_group_user import SignGroupUser
+from utils.decorator.shop import NotMeetUseConditionsException, shop_register
driver: Driver = nonebot.get_driver()
@@ -22,13 +22,18 @@ async def _():
"下次签到双倍好感度概率 + 20%(平平庸庸)(同类商品将覆盖)",
"下次签到双倍好感度概率 + 30%(金币才是真命天子!)(同类商品将覆盖)",
),
- load_status=Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS"),
- icon=("favorability_card_1.png", "favorability_card_2.png", "favorability_card_3.png"),
- ** {"好感度双倍加持卡Ⅰ_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3},
+ load_status=bool(Config.get_config("shop", "IMPORT_DEFAULT_SHOP_GOODS")),
+ icon=(
+ "favorability_card_1.png",
+ "favorability_card_2.png",
+ "favorability_card_3.png",
+ ),
+ **{"好感度双倍加持卡Ⅰ_prob": 0.1, "好感度双倍加持卡Ⅱ_prob": 0.2, "好感度双倍加持卡Ⅲ_prob": 0.3},
)
async def sign_card(user_id: int, group_id: int, prob: float):
- user = await SignGroupUser.ensure(user_id, group_id)
- await user.update(add_probability=prob).apply()
+ user, _ = await SignGroupUser.get_or_create(user_qq=user_id, group_id=group_id)
+ user.add_probability = prob
+ await user.save(update_fields=["add_probability"])
@shop_register(
name="测试道具A",
@@ -38,20 +43,17 @@ async def _():
icon="sword.png",
)
async def _(user_id: int, group_id: int):
- print(user_id, group_id, '使用测试道具')
+ print(user_id, group_id, "使用测试道具")
@shop_register.before_handle(name="测试道具A", load_status=False)
async def _(user_id: int, group_id: int):
- print(user_id, group_id, '第一个使用前函数(before handle)')
+ print(user_id, group_id, "第一个使用前函数(before handle)")
@shop_register.before_handle(name="测试道具A", load_status=False)
async def _(user_id: int, group_id: int):
- print(user_id, group_id, '第二个使用前函数(before handle)222')
- raise NotMeetUseConditionsException("太笨了!") # 抛出异常,阻断使用,并返回信息
+ print(user_id, group_id, "第二个使用前函数(before handle)222")
+ raise NotMeetUseConditionsException("太笨了!") # 抛出异常,阻断使用,并返回信息
@shop_register.after_handle(name="测试道具A", load_status=False)
async def _(user_id: int, group_id: int):
- print(user_id, group_id, '第一个使用后函数(after handle)')
-
-
-
+ print(user_id, group_id, "第一个使用后函数(after handle)")
diff --git a/plugins/sign_in/group_user_checkin.py b/plugins/sign_in/group_user_checkin.py
index 87174d34..596ff1ec 100755
--- a/plugins/sign_in/group_user_checkin.py
+++ b/plugins/sign_in/group_user_checkin.py
@@ -1,23 +1,25 @@
-from datetime import datetime, timedelta
-from models.sign_group_user import SignGroupUser
-from models.group_member_info import GroupInfoUser
-from models.bag_user import BagUser
-from configs.config import NICKNAME
-from nonebot.adapters.onebot.v11 import MessageSegment
-from utils.image_utils import BuildImage, BuildMat
-from services.db_context import db
-from .utils import get_card, SIGN_TODAY_CARD_PATH
-from typing import Optional
-from services.log import logger
-from .random_event import random_event
-from utils.data_utils import init_rank
-from utils.utils import get_user_avatar
-from io import BytesIO
-import random
-import math
import asyncio
-import secrets
+import math
import os
+import random
+import secrets
+from datetime import datetime, timedelta
+from io import BytesIO
+from typing import Optional
+
+from nonebot.adapters.onebot.v11 import MessageSegment
+
+from configs.config import NICKNAME
+from models.bag_user import BagUser
+from models.group_member_info import GroupInfoUser
+from models.sign_group_user import SignGroupUser
+from services.log import logger
+from utils.data_utils import init_rank
+from utils.image_utils import BuildImage, BuildMat
+from utils.utils import get_user_avatar
+
+from .random_event import random_event
+from .utils import SIGN_TODAY_CARD_PATH, get_card
async def group_user_check_in(
@@ -25,18 +27,17 @@ async def group_user_check_in(
) -> MessageSegment:
"Returns string describing the result of checking in"
present = datetime.now()
- async with db.transaction():
- # 取得相应用户
- user = await SignGroupUser.ensure(user_qq, group, for_update=True)
- # 如果同一天签到过,特殊处理
- if (
- user.checkin_time_last + timedelta(hours=8)
- ).date() >= present.date() or f"{user}_{group}_sign_{datetime.now().date()}" in os.listdir(
- SIGN_TODAY_CARD_PATH
- ):
- gold = await BagUser.get_gold(user_qq, group)
- return await get_card(user, nickname, -1, gold, "")
- return await _handle_check_in(nickname, user_qq, group, present) # ok
+ # 取得相应用户
+ user, is_create = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
+ # 如果同一天签到过,特殊处理
+ if not is_create and (
+ user.checkin_time_last.date() >= present.date()
+ or f"{user}_{group}_sign_{datetime.now().date()}"
+ in os.listdir(SIGN_TODAY_CARD_PATH)
+ ):
+ gold = await BagUser.get_gold(user_qq, group)
+ return await get_card(user, nickname, -1, gold, "")
+ return await _handle_check_in(nickname, user_qq, group, present) # ok
async def check_in_all(nickname: str, user_qq: int):
@@ -47,40 +48,39 @@ async def check_in_all(nickname: str, user_qq: int):
:param nickname: 昵称
:param user_qq: 用户qq
"""
- async with db.transaction():
- present = datetime.now()
- for u in await SignGroupUser.get_user_all_data(user_qq):
- group = u.group_id
- if not ((
- u.checkin_time_last + timedelta(hours=8)
- ).date() >= present.date() or f"{u}_{group}_sign_{datetime.now().date()}" in os.listdir(
- SIGN_TODAY_CARD_PATH
- )):
- await _handle_check_in(nickname, user_qq, group, present)
+ present = datetime.now()
+ for u in await SignGroupUser.filter(user_qq=user_qq).all():
+ group = u.group_id
+ if not (
+ u.checkin_time_last.date() >= present.date()
+ or f"{u}_{group}_sign_{datetime.now().date()}"
+ in os.listdir(SIGN_TODAY_CARD_PATH)
+ ):
+ await _handle_check_in(nickname, user_qq, group, present)
async def _handle_check_in(
nickname: str, user_qq: int, group: int, present: datetime
) -> MessageSegment:
- user = await SignGroupUser.ensure(user_qq, group, for_update=True)
- impression_added = (secrets.randbelow(99)+1)/100
+ user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
+ impression_added = (secrets.randbelow(99) + 1) / 100
critx2 = random.random()
- add_probability = user.add_probability
+ add_probability = float(user.add_probability)
specify_probability = user.specify_probability
if critx2 + add_probability > 0.97:
impression_added *= 2
elif critx2 < specify_probability:
impression_added *= 2
- await SignGroupUser.sign(user, impression_added, present)
+ await SignGroupUser.sign(user, impression_added)
gold = random.randint(1, 100)
- gift, gift_type = random_event(user.impression)
+ gift, gift_type = random_event(float(user.impression))
if gift_type == "gold":
await BagUser.add_gold(user_qq, group, gold + gift)
gift = f"额外金币 + {gift}"
else:
await BagUser.add_gold(user_qq, group, gold)
await BagUser.add_property(user_qq, group, gift)
- gift += ' + 1'
+ gift += " + 1"
logger.info(
f"(USER {user.user_qq}, GROUP {user.group_id})"
@@ -95,7 +95,7 @@ async def _handle_check_in(
async def group_user_check(nickname: str, user_qq: int, group: int) -> MessageSegment:
# heuristic: if users find they have never checked in they are probable to check in
- user = await SignGroupUser.ensure(user_qq, group)
+ user, _ = await SignGroupUser.get_or_create(user_qq=user_qq, group_id=group)
gold = await BagUser.get_gold(user_qq, group)
return await get_card(user, nickname, None, gold, "", is_card_view=True)
@@ -171,18 +171,14 @@ async def _pst(users: list, impressions: list, groups: list):
impressions.pop(index)
users.pop(index)
groups.pop(index)
- try:
- user_name = (
- await GroupInfoUser.get_member_info(user, group)
- ).user_name
- except AttributeError:
+ if user_ := await GroupInfoUser.get_or_none(user_qq=user, group_id=group):
+ user_name = user_.user_name
+ else:
user_name = f"我名字呢?"
user_name = user_name if len(user_name) < 11 else user_name[:10] + "..."
ava = await get_user_avatar(user)
if ava:
- ava = BuildImage(
- 50, 50, background=BytesIO(ava)
- )
+ ava = BuildImage(50, 50, background=BytesIO(ava))
else:
ava = BuildImage(50, 50, color="white")
ava.circle()
diff --git a/plugins/sign_in/random_event.py b/plugins/sign_in/random_event.py
index 22d799c0..b451d848 100755
--- a/plugins/sign_in/random_event.py
+++ b/plugins/sign_in/random_event.py
@@ -1,11 +1,12 @@
-from configs.config import Config
import random
+from typing import Tuple, Union
+from configs.config import Config
PROB_DATA = None
-def random_event(impression: float) -> 'Union[str, int], str':
+def random_event(impression: float) -> Tuple[Union[str, int], str]:
"""
签到随机事件
:param impression: 好感度
@@ -14,20 +15,17 @@ def random_event(impression: float) -> 'Union[str, int], str':
global PROB_DATA
if not PROB_DATA:
PROB_DATA = {
- Config.get_config("sign_in", "SIGN_CARD3_PROB"): '好感度双倍加持卡Ⅲ',
- Config.get_config("sign_in", "SIGN_CARD2_PROB"): '好感度双倍加持卡Ⅱ',
- Config.get_config("sign_in", "SIGN_CARD1_PROB"): '好感度双倍加持卡Ⅰ'
+ Config.get_config("sign_in", "SIGN_CARD3_PROB"): "好感度双倍加持卡Ⅲ",
+ Config.get_config("sign_in", "SIGN_CARD2_PROB"): "好感度双倍加持卡Ⅱ",
+ Config.get_config("sign_in", "SIGN_CARD1_PROB"): "好感度双倍加持卡Ⅰ",
}
rand = random.random() - impression / 1000
for prob in PROB_DATA.keys():
if rand <= prob:
- return PROB_DATA[prob], 'props'
- gold = random.randint(1, random.randint(1, int(1 if impression < 1 else impression)))
+ return PROB_DATA[prob], "props"
+ gold = random.randint(
+ 1, random.randint(1, int(1 if impression < 1 else impression))
+ )
max_sign_gold = Config.get_config("sign_in", "MAX_SIGN_GOLD")
gold = max_sign_gold if gold > max_sign_gold else gold
- return gold, 'gold'
-
-
-
-
-
+ return gold, "gold"
diff --git a/plugins/sign_in/utils.py b/plugins/sign_in/utils.py
index f1a62bc6..741a9392 100755
--- a/plugins/sign_in/utils.py
+++ b/plugins/sign_in/utils.py
@@ -1,31 +1,33 @@
-from .config import (
- SIGN_RESOURCE_PATH,
- SIGN_TODAY_CARD_PATH,
- SIGN_BORDER_PATH,
- SIGN_BACKGROUND_PATH,
- lik2level,
- lik2relation,
- level2attitude,
- weekdays,
-)
-from models.sign_group_user import SignGroupUser
-from models.group_member_info import GroupInfoUser
+import asyncio
+import os
+import random
+from datetime import datetime
+from io import BytesIO
+from pathlib import Path
+from typing import List, Optional
+
+import nonebot
+from nonebot import Driver
from nonebot.adapters.onebot.v11 import MessageSegment
-from configs.config import Config
-from utils.utils import get_user_avatar
+
+from configs.config import NICKNAME, Config
+from configs.path_config import IMAGE_PATH
+from models.group_member_info import GroupInfoUser
+from models.sign_group_user import SignGroupUser
from utils.image_utils import BuildImage
from utils.message_builder import image
-from configs.config import NICKNAME
-from pathlib import Path
-from datetime import datetime
-from typing import Optional, List
-from nonebot import Driver
-from io import BytesIO
-import asyncio
-import random
-import nonebot
-import os
+from utils.utils import get_user_avatar
+from .config import (
+ SIGN_BACKGROUND_PATH,
+ SIGN_BORDER_PATH,
+ SIGN_RESOURCE_PATH,
+ SIGN_TODAY_CARD_PATH,
+ level2attitude,
+ lik2level,
+ lik2relation,
+ weekdays,
+)
driver: Driver = nonebot.get_driver()
@@ -34,10 +36,13 @@ driver: Driver = nonebot.get_driver()
async def init_image():
SIGN_RESOURCE_PATH.mkdir(parents=True, exist_ok=True)
SIGN_TODAY_CARD_PATH.mkdir(exist_ok=True, parents=True)
- await GroupInfoUser.add_member_info(114514, 114514, "", datetime.min, 0)
- _u = await GroupInfoUser.get_member_info(114514, 114514)
- if _u.uid is None:
- await _u.update(uid=0).apply()
+ if not await GroupInfoUser.get_or_none(user_qq=114514):
+ await GroupInfoUser.create(
+ user_qq=114514,
+ group_id=114514,
+ user_name="",
+ uid=0,
+ )
generate_progress_bar_pic()
clear_sign_data_pic()
@@ -58,7 +63,12 @@ async def get_card(
Path(SIGN_TODAY_CARD_PATH) / f"{user_id}_{user.group_id}_{_type}_{date}.png"
)
if card_file.exists():
- return image(f"{user_id}_{user.group_id}_{_type}_{date}.png", "sign/today_card")
+ return image(
+ IMAGE_PATH
+ / "sign"
+ / "today_card"
+ / f"{user_id}_{user.group_id}_{_type}_{date}.png"
+ )
else:
if add_impression == -1:
card_file = (
@@ -67,8 +77,10 @@ async def get_card(
)
if card_file.exists():
return image(
- f"{user_id}_{user.group_id}_view_{date}.png",
- "sign/today_card",
+ IMAGE_PATH
+ / "sign"
+ / "today_card"
+ / f"{user_id}_{user.group_id}_view_{date}.png"
)
is_card_view = True
ava = BytesIO(await get_user_avatar(user_id))
@@ -244,7 +256,7 @@ def _generate_card(
)
today_data.text(
(0, 50),
- f"色图概率:{(default_setu_prob + user.impression if user.impression < 100 else 100):.2f}%",
+ f"色图概率:{(default_setu_prob + float(user.impression) if user.impression < 100 else 100):.2f}%",
)
today_data.text((0, 75), f"开箱次数:{(20 + int(user.impression / 3))}")
_type = "view"
@@ -285,7 +297,12 @@ def _generate_card(
bk.paste(today_data, (580, 220), True)
bk.paste(watermark, (15, 400), True)
bk.save(SIGN_TODAY_CARD_PATH / f"{user_id}_{user.group_id}_{_type}_{data}.png")
- return image(f"{user_id}_{user.group_id}_{_type}_{data}.png", "sign/today_card")
+ return image(
+ IMAGE_PATH
+ / "sign"
+ / "today_card"
+ / f"{user_id}_{user.group_id}_{_type}_{data}.png"
+ )
def generate_progress_bar_pic():
diff --git a/plugins/statistics/_model.py b/plugins/statistics/_model.py
index cc81fe1b..2de65d60 100644
--- a/plugins/statistics/_model.py
+++ b/plugins/statistics/_model.py
@@ -1,30 +1,23 @@
-from datetime import datetime
-from typing import Optional
-
-from services.db_context import db
-class Statistics(db.Model):
- __tablename__ = "statistics"
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.BigInteger())
- plugin_name = db.Column(db.String(), nullable=False)
- create_time = db.Column(db.DateTime(timezone=True), nullable=False)
+from tortoise import fields
- @classmethod
- async def add_statistic(cls, user_qq: int, group_id: Optional[int], plugin_name: str):
- """
- 说明:
- 添加记录
- 参数:
- :param user_qq: qq
- :param group_id: 群号
- :param plugin_name: 插件model
- """
- await cls.create(
- user_qq=user_qq,
- group_id=group_id,
- plugin_name=plugin_name,
- create_time=datetime.now(),
- )
+from services.db_context import Model
+
+
+class Statistics(Model):
+
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField(null=True)
+ """群聊id"""
+ plugin_name = fields.CharField(255)
+ """插件名称"""
+ create_time = fields.DatetimeField(auto_now=True)
+ """添加日期"""
+
+ class Meta:
+ table = "statistics"
+ table_description = "用户权限数据库"
diff --git a/plugins/statistics/statistics_handle.py b/plugins/statistics/statistics_handle.py
index f0b172fc..df151536 100755
--- a/plugins/statistics/statistics_handle.py
+++ b/plugins/statistics/statistics_handle.py
@@ -1,14 +1,16 @@
-from nonebot import on_command
-from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent, Message
-from models.group_info import GroupInfo
-from configs.path_config import DATA_PATH, IMAGE_PATH
-from nonebot.params import CommandArg, Command
-from utils.image_utils import BuildMat
-from utils.message_builder import image
-from utils.manager import plugins2settings_manager
-from typing import Tuple
import asyncio
import os
+from typing import Tuple
+
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Command, CommandArg
+
+from configs.path_config import DATA_PATH, IMAGE_PATH
+from models.group_info import GroupInfo
+from utils.image_utils import BuildMat
+from utils.manager import plugins2settings_manager
+from utils.message_builder import image
try:
import ujson as json
@@ -160,8 +162,8 @@ async def _(bot: Bot, event: MessageEvent, cmd: Tuple[str, ...] = Command(), arg
day_index = data["day_index"]
data = data[arg][key]
if _type == "group":
- name = await GroupInfo.get_group_info(event.group_id)
- name = name.group_name if name else str(event.group_id)
+ group = await GroupInfo.filter(group_id=event.group_id).first()
+ name = name.group_name if group else str(event.group_id)
else:
name = event.sender.card or event.sender.nickname
img = await generate_statistics_img(data, arg, name, plugin, day_index)
diff --git a/plugins/statistics/statistics_hook.py b/plugins/statistics/statistics_hook.py
index a0ca29ab..31250b2f 100755
--- a/plugins/statistics/statistics_hook.py
+++ b/plugins/statistics/statistics_hook.py
@@ -1,12 +1,14 @@
-from configs.path_config import DATA_PATH
+from datetime import datetime
+
+from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
from nonebot.matcher import Matcher
from nonebot.message import run_postprocessor
-from nonebot.typing import T_State
-from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, MessageEvent
-from datetime import datetime
+from nonebot.typing import Optional, T_State
+
+from configs.path_config import DATA_PATH
from utils.manager import plugins2settings_manager
from utils.utils import scheduler
-from nonebot.typing import Optional
+
from ._model import Statistics
try:
@@ -99,10 +101,11 @@ async def _(
and matcher.priority not in [1, 999]
and matcher.plugin_name not in ["update_info", "statistics_handle"]
):
- await Statistics.add_statistic(
- event.user_id,
- event.group_id if isinstance(event, GroupMessageEvent) else None,
- matcher.plugin_name,
+ await Statistics.create(
+ user_qq=event.user_id,
+ group_id=getattr(event, "group_id", None),
+ plugin_name=matcher.plugin_name,
+ create_time=datetime.now(),
)
module = matcher.plugin_name
day_index = _prefix_count_dict["day_index"]
diff --git a/plugins/update_picture.py b/plugins/update_picture.py
index f758e546..bdf7f552 100755
--- a/plugins/update_picture.py
+++ b/plugins/update_picture.py
@@ -1,20 +1,21 @@
-from nonebot import on_command
-from PIL import Image, ImageFilter
-from utils.message_builder import image
-from configs.path_config import TEMP_PATH, IMAGE_PATH
-from services.log import logger
-from nonebot.rule import to_me
-from nonebot.adapters.onebot.v11 import MessageEvent, GroupMessageEvent, Message
-from nonebot.typing import T_State
-from utils.utils import get_message_img, is_number
-from nonebot.params import CommandArg, Arg, ArgStr, Depends
-from utils.image_utils import BuildImage, pic2b64
-from configs.config import NICKNAME
-from utils.http_utils import AsyncHttpx
from typing import Union
+
import cv2
import numpy as np
+from nonebot import on_command
+from nonebot.adapters.onebot.v11 import GroupMessageEvent, Message, MessageEvent
+from nonebot.params import Arg, ArgStr, CommandArg, Depends
+from nonebot.rule import to_me
+from nonebot.typing import T_State
+from PIL import Image, ImageFilter
+from configs.config import NICKNAME
+from configs.path_config import IMAGE_PATH, TEMP_PATH
+from services.log import logger
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import BuildImage, pic2b64
+from utils.message_builder import image
+from utils.utils import get_message_img, is_number
__zx_plugin_name__ = "各种图片简易操作"
__plugin_usage__ = """
@@ -88,9 +89,7 @@ update_img_help.save(IMAGE_PATH / "update_img_help.png")
def parse_key(key: str):
- async def _key_parser(
- state: T_State, inp: Union[Message, str] = Arg(key)
- ):
+ async def _key_parser(state: T_State, inp: Union[Message, str] = Arg(key)):
if key != "img_list" and isinstance(inp, Message):
inp = inp.extract_plain_text().strip()
if inp in ["取消", "算了"]:
@@ -132,6 +131,7 @@ def parse_key(key: str):
if not get_message_img(inp):
await update_img.reject_arg("img_list", "没图?没图?没图?来图速来!")
state[key] = inp
+
return _key_parser
@@ -167,10 +167,18 @@ async def _(event: MessageEvent, state: T_State, arg: Message = CommandArg()):
state["img_list"] = event.message
-@update_img.got("method", prompt=f"要使用图片的什么操作呢?{method_str}", parameterless=[Depends(parse_key("method"))])
-@update_img.got("x", prompt="[宽度? 比率? 旋转角度? 底色?]", parameterless=[Depends(parse_key("x"))])
+@update_img.got(
+ "method",
+ prompt=f"要使用图片的什么操作呢?{method_str}",
+ parameterless=[Depends(parse_key("method"))],
+)
+@update_img.got(
+ "x", prompt="[宽度? 比率? 旋转角度? 底色?]", parameterless=[Depends(parse_key("x"))]
+)
@update_img.got("y", prompt="[长度? 0 0 底色?]", parameterless=[Depends(parse_key("y"))])
-@update_img.got("img_list", prompt="图呢图呢图呢图呢?GKD!", parameterless=[Depends(parse_key("img_list"))])
+@update_img.got(
+ "img_list", prompt="图呢图呢图呢图呢?GKD!", parameterless=[Depends(parse_key("img_list"))]
+)
async def _(
event: MessageEvent,
state: T_State,
@@ -285,7 +293,7 @@ async def _(
img[i, j] = color
cv2.imwrite(TEMP_PATH / f"{event.user_id}_{k}_ok_update.png", img)
for i in range(index):
- result += image(f"{event.user_id}_{i}_ok_update.png", "temp")
+ result += image(TEMP_PATH / f"{event.user_id}_{i}_ok_update.png")
if is_number(method):
method = method_list[int(method) - 1]
logger.info(
diff --git a/plugins/web_ui/api/request.py b/plugins/web_ui/api/request.py
index 54d93baf..02615304 100644
--- a/plugins/web_ui/api/request.py
+++ b/plugins/web_ui/api/request.py
@@ -1,7 +1,8 @@
-from utils.manager import requests_manager
-from ..auth import token_to_user, Depends, User
-from utils.utils import get_bot
from models.group_info import GroupInfo
+from utils.manager import requests_manager
+from utils.utils import get_bot
+
+from ..auth import Depends, User, token_to_user
from ..config import *
@@ -39,18 +40,21 @@ async def _(parma: RequestParma, user: User = Depends(token_to_user)) -> Result:
if bot := get_bot():
if parma.handle == "approve":
if parma.type == "group":
- rid = requests_manager.get_group_id(parma.id)
- if await GroupInfo.get_group_info(rid):
- await GroupInfo.set_group_flag(rid, 1)
- else:
- group_info = await bot.get_group_info(group_id=rid)
- await GroupInfo.add_group_info(
- rid,
- group_info["group_name"],
- group_info["max_member_count"],
- group_info["member_count"],
- 1,
- )
+ if rid := requests_manager.get_group_id(parma.id):
+ # await GroupInfo.update_or_create(defaults={"group_flag": 1}, )
+ if group := await GroupInfo.filter(group_id=rid).first():
+ await group.update_or_create(group_flag=1)
+ else:
+ group_info = await bot.get_group_info(group_id=rid)
+ await GroupInfo.update_or_create(
+ group_id=group_info["group_id"],
+ defaults={
+ "group_name": group_info["group_name"],
+ "max_member_count": group_info["max_member_count"],
+ "member_count": group_info["member_count"],
+ "group_flag": 1,
+ },
+ )
flag = await requests_manager.approve(bot, parma.id, parma.type)
elif parma.handle == "refuse":
flag = await requests_manager.refused(bot, parma.id, parma.type)
diff --git a/plugins/word_bank/_model.py b/plugins/word_bank/_model.py
index 12475f45..508ae67c 100644
--- a/plugins/word_bank/_model.py
+++ b/plugins/word_bank/_model.py
@@ -1,47 +1,63 @@
+import random
+import re
import time
-from nonebot.internal.adapter.template import MessageTemplate
+from datetime import datetime
+from typing import Any, List, Optional, Tuple, Union
+
from nonebot.adapters.onebot.v11 import (
+ GroupMessageEvent,
Message,
MessageEvent,
- GroupMessageEvent,
MessageSegment,
)
-from services.db_context import db
-from typing import Optional, List, Union, Tuple, Any
-from datetime import datetime
-from configs.path_config import DATA_PATH
-import random
-from ._config import int2type
-from utils.image_utils import get_img_hash
-from utils.http_utils import AsyncHttpx
-import re
+from nonebot.internal.adapter.template import MessageTemplate
+from tortoise import Tortoise, fields
+from tortoise.expressions import Q, RawSQL
-from utils.message_builder import image, face, at
+from configs.path_config import DATA_PATH
+from services.db_context import Model
+from utils.http_utils import AsyncHttpx
+from utils.image_utils import get_img_hash
+from utils.message_builder import at, face, image
from utils.utils import get_message_img
+from ._config import int2type
+
path = DATA_PATH / "word_bank"
-class WordBank(db.Model):
- __tablename__ = "word_bank2"
+class WordBank(Model):
- id = db.Column(db.Integer(), primary_key=True)
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.Integer())
- word_scope = db.Column(
- db.Integer(), nullable=False, default=0
- ) # 生效范围 0: 全局 1: 群聊 2: 私聊
- word_type = db.Column(
- db.Integer(), nullable=False, default=0
- ) # 词条类型 0: 完全匹配 1: 模糊 2: 正则 3: 图片
- status = db.Column(db.Boolean(), nullable=False, default=True) # 词条状态
- problem = db.Column(db.String(), nullable=False) # 问题,为图片时使用图片hash
- answer = db.Column(db.String(), nullable=False) # 回答
- placeholder = db.Column(db.String()) # 占位符
- image_path = db.Column(db.String()) # 使用图片作为问题时图片存储的路径
- to_me = db.Column(db.String()) # 使用图片作为问题时图片存储的路径
- create_time = db.Column(db.DateTime(), nullable=False)
- update_time = db.Column(db.DateTime(), nullable=False)
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+ user_qq = fields.BigIntField()
+ """用户id"""
+ group_id = fields.BigIntField(null=True)
+ """群聊id"""
+ word_scope = fields.IntField(default=0)
+ """生效范围 0: 全局 1: 群聊 2: 私聊"""
+ word_type = fields.IntField(default=0)
+ """词条类型 0: 完全匹配 1: 模糊 2: 正则 3: 图片"""
+ status = fields.BooleanField()
+ """词条状态"""
+ problem = fields.TextField()
+ """问题,为图片时使用图片hash"""
+ answer = fields.TextField()
+ """回答"""
+ placeholder = fields.TextField(null=True)
+ """占位符"""
+ image_path = fields.TextField(null=True)
+ """使用图片作为问题时图片存储的路径"""
+ to_me = fields.CharField(255, null=True)
+ """昵称开头时存储的昵称"""
+ create_time = fields.DatetimeField(auto_now=True)
+ """创建时间"""
+ update_time = fields.DatetimeField(auto_now_add=True)
+ """更新时间"""
+
+ class Meta:
+ table = "word_bank2"
+ table_description = "词条数据库"
@classmethod
async def exists(
@@ -64,18 +80,18 @@ class WordBank(db.Model):
:param word_scope: 词条范围
:param word_type: 词条类型
"""
- query = cls.query.where(cls.problem == problem)
+ query = cls.filter(problem=problem)
if user_id:
- query = query.where(cls.user_qq == user_id)
+ query = query.filter(user_qq=user_id)
if group_id:
- query = query.where(cls.group_id == group_id)
+ query = query.filter(group_id=group_id)
if answer:
- query = query.where(cls.answer == answer)
- if word_type:
- query = query.where(cls.word_type == word_type)
- if word_scope:
- query = query.where(cls.word_scope == word_scope)
- return bool(await query.gino.first())
+ query = query.filter(answer=answer)
+ if word_type is not None:
+ query = query.filter(word_type=word_type)
+ if word_scope is not None:
+ query = query.filter(word_scope=word_scope)
+ return bool(await query.first())
@classmethod
async def add_problem_answer(
@@ -86,7 +102,7 @@ class WordBank(db.Model):
word_type: int,
problem: Union[str, Message],
answer: Union[str, Message],
- to_me_nickname: str = None
+ to_me_nickname: Optional[str] = None,
):
"""
说明:
@@ -112,7 +128,9 @@ class WordBank(db.Model):
problem = str(get_img_hash(_file))
image_path = f"problem/{group_id}/{user_id}_{int(time.time())}.jpg"
answer, _list = await cls._answer2format(answer, user_id, group_id)
- if not await cls.exists(user_id, group_id, problem, answer, word_scope, word_type):
+ if not await cls.exists(
+ user_id, group_id, problem, answer, word_scope, word_type
+ ):
await cls.create(
user_qq=user_id,
group_id=group_id,
@@ -125,7 +143,7 @@ class WordBank(db.Model):
placeholder=",".join(_list),
create_time=datetime.now().replace(microsecond=0),
update_time=datetime.now().replace(microsecond=0),
- to_me=to_me_nickname
+ to_me=to_me_nickname,
)
@classmethod
@@ -152,7 +170,7 @@ class WordBank(db.Model):
text += seg.data["text"]
elif seg.type == "face":
text += f"[face:placeholder_{index}]"
- _list.append(seg.data['id'])
+ _list.append(seg.data["id"])
elif seg.type == "at":
text += f"[at:placeholder_{index}]"
_list.append(seg.data["qq"])
@@ -187,12 +205,12 @@ class WordBank(db.Model):
if query:
answer = query.answer
else:
- query = await cls.query.where(
- (cls.problem == problem)
- & (cls.user_qq == user_id)
- & (cls.group_id == group_id)
- & (cls.answer == answer)
- ).gino.first()
+ query = await cls.get_or_none(
+ problem=problem,
+ user_qq=user_id,
+ group_id=group_id,
+ answer=answer,
+ )
if query and query.placeholder:
type_list = re.findall(rf"\[(.*?):placeholder_.*?]", answer)
temp_answer = re.sub(rf"\[(.*?):placeholder_.*?]", "{}", answer)
@@ -208,7 +226,7 @@ class WordBank(db.Model):
return answer
@classmethod
- async def check(
+ async def check_problem(
cls,
event: MessageEvent,
problem: str,
@@ -224,60 +242,35 @@ class WordBank(db.Model):
:param word_scope: 词条范围
:param word_type: 词条类型
"""
- query = cls.query
- sql_text = "SELECT * FROM public.word_bank2 where 1 = 1"
- # 救命!!没找到gino的正则表达式方法,暂时使用sql语句
+ query = cls
if isinstance(event, GroupMessageEvent):
if word_scope:
- query = query.where(cls.word_scope == word_scope)
- sql_text += f" and word_scope = {word_scope}"
+ query = query.filter(word_scope=word_scope)
else:
- query = query.where(
- (cls.group_id == event.group_id) | (cls.word_scope == 0)
- )
- sql_text += f" and (group_id = {event.group_id} or word_scope = 0)"
+ query = query.filter(Q(group_id=event.group_id) | Q(word_scope=0))
else:
- query = query.where((cls.word_scope == 2) | (cls.word_scope == 0))
- sql_text += f" and (word_scope = 2 or word_scope = 0)"
+ query = query.filter(Q(cword_scope=2) | Q(word_scope=0))
if word_type:
- query = query.where(cls.word_scope == word_type)
- sql_text += f" and word_scope = {word_scope}"
+ query = query.filter(word_scope=word_type)
# 完全匹配
- if await query.where(
- ((cls.word_type == 0) | (cls.word_type == 3)) & (cls.problem == problem)
- ).gino.first():
- return query.where(
- ((cls.word_type == 0) | (cls.word_type == 3)) & (cls.problem == problem)
- )
+ if data_list := await query.filter(
+ Q(Q(word_type=0) | Q(word_type=3)), Q(problem=problem)
+ ).all():
+ return data_list
+ db = Tortoise.get_connection("default")
# 模糊匹配
- if await db.first(
- db.text(
- sql_text
- + f" and word_type = 1 and :problem like '%' || problem || '%';"
- ),
- problem=problem,
- ):
- return (
- sql_text
- + f" and word_type = 1 and :problem like '%' || problem || '%';"
- )
- # 正则匹配
- if await db.first(
- db.text(
- sql_text
- + f" and word_type = 2 and word_scope != 999 and :problem ~ problem;"
- ),
- problem=problem,
- ):
- return (
- sql_text
- + f" and word_type = 2 and word_scope != 999 and :problem ~ problem;"
- )
- # if await db.first(
- # db.text(sql_text + f" and word_type = 1 and word_scope != 999 and '{problem}' ~ problem;")
- # ):
- # return sql_text + f" and word_type = 1 and word_scope != 999 and '{problem}' ~ problem;"
- # return None
+ sql = query.filter(word_type=1).sql() + " and POSITION(problem in $1) > 0"
+ data_list = await db.execute_query_dict(sql, [problem])
+ if data_list:
+ return [cls(**data) for data in data_list]
+ # 正则
+ sql = (
+ query.filter(word_type=2, word_scope__not=999).sql() + " and $1 ~ problem;"
+ )
+ data_list = await db.execute_query_dict(sql, [problem])
+ if data_list:
+ return [cls(**data) for data in data_list]
+ return None
@classmethod
async def get_answer(
@@ -296,26 +289,16 @@ class WordBank(db.Model):
:param word_scope: 词条范围
:param word_type: 词条类型
"""
- query = await cls.check(event, problem, word_scope, word_type)
- if query is not None:
- if isinstance(query, str):
- answer_list = await db.all(db.text(query), problem=problem)
- answer = random.choice(answer_list)
- return (
- await cls._format2answer(answer[6], answer[7], answer[1], answer[2])
- if answer.placeholder
- else answer.answer
- )
- else:
- answer_list = await query.gino.all()
- answer = random.choice(answer_list)
- return (
- await cls._format2answer(
- problem, answer.answer, answer.user_qq, answer.group_id
- )
- if answer.placeholder
- else answer.answer
+ data_list = await cls.check_problem(event, problem, word_scope, word_type)
+ if data_list:
+ answer = random.choice(data_list)
+ return (
+ await cls._format2answer(
+ problem, answer.answer, answer.user_qq, answer.group_id
)
+ if answer.placeholder
+ else answer.answer
+ )
@classmethod
async def get_problem_all_answer(
@@ -336,22 +319,14 @@ class WordBank(db.Model):
"""
if index is not None:
if group_id:
- problem = (await cls.query.where(cls.group_id == group_id).gino.all())[
- index
- ]
+ problem_ = (await cls.filter(group_id=group_id).all())[index]
else:
- problem = (
- await cls.query.where(
- cls.word_scope == (word_scope or 0)
- ).gino.all()
- )[index]
- problem = problem.problem
- answer = cls.query.where(cls.problem == problem)
+ problem_ = (await cls.filter(word_scope=(word_scope or 0)).all())[index]
+ problem = problem_.problem
+ answer = cls.filter(problem=problem)
if group_id:
- answer = answer.where(cls.group_id == group_id)
- return [
- await cls._format2answer("", "", 0, 0, x) for x in (await answer.gino.all())
- ]
+ answer = answer.filter(group_id=group_id)
+ return [await cls._format2answer("", "", 0, 0, x) for x in (await answer.all())]
@classmethod
async def delete_group_problem(
@@ -373,23 +348,17 @@ class WordBank(db.Model):
if await cls.exists(None, group_id, problem, None, word_scope):
if index is not None:
if group_id:
- query = await cls.query.where(
- (cls.group_id == group_id) & (cls.problem == problem)
- ).gino.all()
+ query = await cls.filter(group_id=group_id, problem=problem).all()
else:
- query = await cls.query.where(
- (cls.word_scope == 0) & (cls.problem == problem)
- ).gino.all()
+ query = await cls.filter(word_scope=0, problem=problem).all()
await query[index].delete()
else:
if group_id:
- await WordBank.delete.where(
- (cls.group_id == group_id) & (cls.problem == problem)
- ).gino.status()
+ await WordBank.filter(group_id=group_id, problem=problem).delete()
else:
- await WordBank.delete.where(
- (cls.word_scope == word_scope) & (cls.problem == problem)
- ).gino.status()
+ await WordBank.filter(
+ word_scope=word_scope, problem=problem
+ ).delete()
return True
return False
@@ -414,23 +383,20 @@ class WordBank(db.Model):
"""
if index is not None:
if group_id:
- query = await cls.query.where(
- (cls.group_id == group_id) & (cls.problem == problem)
- ).gino.all()
+ query = await cls.filter(group_id=group_id, problem=problem).all()
else:
- query = await cls.query.where(
- (cls.word_scope == word_scope) & (cls.problem == problem)
- ).gino.all()
- await query[index].update(problem=replace_str).apply()
+ query = await cls.filter(word_scope=word_scope, problem=problem).all()
+ query[index].problem = replace_str
+ await query[index].save(update_fields=["problem"])
else:
if group_id:
- await WordBank.update.values(problem=replace_str).where(
- (cls.group_id == group_id) & (cls.problem == problem)
- ).gino.status()
+ await cls.filter(group_id=group_id, problem=problem).update(
+ problem=replace_str
+ )
else:
- await WordBank.update.values(problem=replace_str).where(
- (cls.word_scope == word_scope) & (cls.problem == problem)
- ).gino.status()
+ await cls.filter(word_scope=word_scope, problem=problem).update(
+ problem=replace_str
+ )
@classmethod
async def get_group_all_problem(
@@ -443,7 +409,7 @@ class WordBank(db.Model):
:param group_id: 群号
"""
return cls._handle_problem(
- await cls.query.where(cls.group_id == group_id).gino.all()
+ await cls.filter(group_id=group_id).all() # type: ignore
)
@classmethod
@@ -455,7 +421,7 @@ class WordBank(db.Model):
:param word_scope: 词条范围
"""
return cls._handle_problem(
- await cls.query.where(cls.word_scope == word_scope).gino.all()
+ await cls.filter(word_scope=word_scope).all() # type: ignore
)
@classmethod
@@ -467,13 +433,13 @@ class WordBank(db.Model):
:param word_type: 词条类型
"""
return cls._handle_problem(
- await cls.query.where(cls.word_type == word_type).gino.all()
+ await cls.filter(word_type=word_type).all() # type: ignore
)
@classmethod
- def _handle_problem(cls, msg_list: List[Union[str, MessageSegment]]):
+ def _handle_problem(cls, msg_list: List["WordBank"]):
"""
- 说明:
+ 说明:
格式化处理问题
参数:
:param msg_list: 消息列表
@@ -514,7 +480,9 @@ class WordBank(db.Model):
word_scope = 0
word_type = 0
# 对图片做额外处理
- if not await cls.exists(user_id, group_id, problem, answer, word_scope, word_type):
+ if not await cls.exists(
+ user_id, group_id, problem, answer, word_scope, word_type
+ ):
await cls.create(
user_qq=user_id,
group_id=group_id,
diff --git a/plugins/word_bank/_old_model.py b/plugins/word_bank/_old_model.py
deleted file mode 100644
index 84678def..00000000
--- a/plugins/word_bank/_old_model.py
+++ /dev/null
@@ -1,20 +0,0 @@
-from services.db_context import db
-from typing import List
-
-
-class WordBank(db.Model):
- __tablename__ = "word_bank"
-
- user_qq = db.Column(db.BigInteger(), nullable=False)
- group_id = db.Column(db.Integer())
- search_type = db.Column(db.Integer(), nullable=False, default=0)
- problem = db.Column(db.String(), nullable=False)
- answer = db.Column(db.String(), nullable=False)
- format = db.Column(db.String())
- create_time = db.Column(db.DateTime(), nullable=False)
- update_time = db.Column(db.DateTime(), nullable=False)
-
- @classmethod
- async def get_all(cls) -> List['WordBank']:
- return await cls.query.gino.all()
-
diff --git a/plugins/word_bank/_rule.py b/plugins/word_bank/_rule.py
index e82dd046..443184e7 100644
--- a/plugins/word_bank/_rule.py
+++ b/plugins/word_bank/_rule.py
@@ -1,14 +1,15 @@
-import imagehash
-from PIL import Image
from io import BytesIO
-from services.log import logger
+import imagehash
+from nonebot.adapters.onebot.v11 import Bot, MessageEvent
from nonebot.typing import T_State
-from nonebot.adapters.onebot.v11 import MessageEvent, Bot
+from PIL import Image
-from utils.utils import get_message_text, get_message_img, get_message_at
-from ._model import WordBank
+from services.log import logger
from utils.http_utils import AsyncHttpx
+from utils.utils import get_message_at, get_message_img, get_message_text
+
+from ._model import WordBank
async def check(bot: Bot, event: MessageEvent, state: T_State) -> bool:
@@ -23,11 +24,11 @@ async def check(bot: Bot, event: MessageEvent, state: T_State) -> bool:
except Exception as e:
logger.warning(f"word_bank rule 获取图片失败 {type(e)}:{e}")
if at:
- temp = ''
+ temp = ""
for seg in event.message:
- if seg.type == 'at':
+ if seg.type == "at":
temp += f"[at:{seg.data['qq']}]"
- elif seg.type == 'text':
+ elif seg.type == "text":
temp += seg.data["text"]
problem = temp
if event.to_me and bot.config.nickname:
@@ -35,9 +36,13 @@ async def check(bot: Bot, event: MessageEvent, state: T_State) -> bool:
problem = f"[at:{bot.self_id}]" + problem
else:
if problem and bot.config.nickname:
- nickname = [nk for nk in bot.config.nickname if str(event.original_message).startswith(nk)]
+ nickname = [
+ nk
+ for nk in bot.config.nickname
+ if str(event.original_message).startswith(nk)
+ ]
problem = nickname[0] + problem if nickname else problem
- if problem and (await WordBank.check(event, problem) is not None):
+ if problem and (await WordBank.check_problem(event, problem) is not None):
state["problem"] = problem
return True
return False
diff --git a/plugins/word_bank/word_handle.py b/plugins/word_bank/word_handle.py
index a56d4d91..04d48594 100644
--- a/plugins/word_bank/word_handle.py
+++ b/plugins/word_bank/word_handle.py
@@ -1,21 +1,29 @@
import re
-from typing import Tuple, Any, Optional
+from typing import Any, Optional, Tuple
+from nonebot import on_command, on_regex
+from nonebot.adapters.onebot.v11 import (
+ Bot,
+ GroupMessageEvent,
+ Message,
+ MessageEvent,
+ PrivateMessageEvent,
+ unescape,
+)
+from nonebot.exception import FinishedException
from nonebot.internal.params import Arg, ArgStr
+from nonebot.params import Command, CommandArg, RegexGroup
from nonebot.typing import T_State
-from utils.utils import get_message_at, is_number, get_message_img
-from nonebot.params import CommandArg, RegexGroup, Command
-from nonebot.exception import FinishedException
-from services.log import logger
-from configs.path_config import DATA_PATH
-from utils.message_builder import custom_forward_msg
-from ._model import WordBank
-from nonebot.adapters.onebot.v11 import Bot, GroupMessageEvent, Message, MessageEvent, PrivateMessageEvent, unescape
-from nonebot import on_command, on_regex
from configs.config import Config
-from ._data_source import delete_word, update_word, show_word
+from configs.path_config import DATA_PATH
+from services.log import logger
+from utils.message_builder import custom_forward_msg
+from utils.utils import get_message_at, get_message_img, is_number
+
from ._config import scope2int, type2int
+from ._data_source import delete_word, show_word, update_word
+from ._model import WordBank
__zx_plugin_name__ = "词库问答 [Admin]"
__plugin_usage__ = r"""
diff --git a/plugins/word_clouds/data_source.py b/plugins/word_clouds/data_source.py
index 5e05e45d..4f941fbf 100644
--- a/plugins/word_clouds/data_source.py
+++ b/plugins/word_clouds/data_source.py
@@ -1,21 +1,23 @@
import asyncio
import os
import random
-import jieba.analyse
import re
-from typing import List
-from PIL import Image as IMG
-import jieba
-from emoji import replace_emoji # type: ignore
-from wordcloud import WordCloud, ImageColorGenerator
-import numpy as np
-import matplotlib.pyplot as plt
from io import BytesIO
-from configs.path_config import IMAGE_PATH, FONT_PATH
+from typing import List
+
+import jieba
+import jieba.analyse
+import matplotlib.pyplot as plt
+import numpy as np
+from emoji import replace_emoji # type: ignore
+from PIL import Image as IMG
+from wordcloud import ImageColorGenerator, WordCloud
+
+from configs.config import Config
+from configs.path_config import FONT_PATH, IMAGE_PATH
+from models.chat_history import ChatHistory
from services import logger
from utils.http_utils import AsyncHttpx
-from models.chat_history import ChatHistory
-from configs.config import Config
async def pre_precess(msg: List[str], config) -> str:
@@ -117,10 +119,8 @@ async def draw_word_cloud(messages, config):
async def get_list_msg(user_id, group_id, days):
- messages_list = (
- await ChatHistory()
- ._get_msg(uid=user_id, gid=group_id, type_="group", days=days)
- .gino.all()
+ messages_list = await ChatHistory().get_message(
+ uid=user_id, gid=group_id, type_="group", days=days
)
if messages_list:
messages = [i.text for i in messages_list]
diff --git a/resources/image/sign/sign_res/bar.png b/resources/image/sign/sign_res/bar.png
index 105955c461cc7c8ea40b27dba2b909f5cc1a55c1..4fc99ec35a3c52cb1afac18e8baefa5efd3adcc6 100644
GIT binary patch
literal 2535
zcmX|DcU)6v7Y?Fjw6bIs%F-~j76_suG8M#tQ2|qt5mXRGHYh7JVOf?XkgyU$pvaO6
z1P6hDs0>*OX;1@PfwBw;1Vh3|2=I~6et*38cgK03^W5j0_xYW)%NHH?ORGtPK%o85
z^L8#EkofG*y@}*^JJ$gg+ZY6rs)gFwUWq0yjv^m|?KNJrL*Q%uwUs|5-igyG)s$6A
zGq`J9S)~I}lPoz`3Q_5lxNDK7wjz7n*{76^ms4t+Qgl|(jfPlVR`@#=5t+fERQho1J!x;CZNM!K(-}D-{6th!CkFJfFVRP
z#_-cq*zX-@F~4~?XdFTahT11*0*3XFY5HS&k0#;%IQHaAG^O45)jTfnz&TCmKVNcW0C$Eu`f}wnG>$X3Hr;ZA_c0p`#e)5=e
zU|aDC(=c;FkMxGoc5T9()HnJ>OYxH_G**=lJ^M#dN#z?W>FW;t?A~e=U*#*`3ve}$
z+KLr(*|?kkk#;TiqYw%@a!HZfZD*3b{mq~u!Voxh(wj8l{JA%##X3-$!SSWq;Hp%R
z+uaY|evJ#+7NbcRR#)RLu~_`!(;J(G4VCwTRM@$3j$07#FL$H~9;00s
z=qY+1@J-W#r`6_LT(4$U%i(fH4sCzdNLk!I8JLh#nfO&b7s#=~s_op$FP!D#Wng)j
z>yPD{em(m;c$TA|)LgyguDy$VuW`vx#8fg3OOSD0m`?G`@-Cn}#FZ^&mrw>yz7nFB
z!|%^1E<9&=iU{d`eU^zeq>vB4G7gzQ5fE%0A9|D%6_}25f`>Hjpb`>`esiOY+|Ls#
zI#+T9(yn;A=>aSz0`-1jft67JqX7^mrQDR0hgfT-turXGWv5q
zIaC+~uF0~P1-&XxnTcY)=_8^dlVIWD%z}_#Zz>=JqrRL!dtg(lYvw$30vM?`UJs
z)|bZk@pIvu&(X}dz~o*JKvx*!uA7i!ojpzs4LcgINiMG)Q`au{I~XPWgndq@YcpFD
zD4`OritjS*G4exsba6C(8Lv0H%c1l_SxMKn8MekkslbUQR$DXA{2}q~8F-FJ7MgK^
zv7vY2xXsPTte7Y9>R-7gAmqSq)?14~EZ|f|v%!c%Z6`83Gio}{eEoBTDDAIadJ2z+
zdYlEsLlS+d6lTlT7!f0rb%D0KRXohNLvY(d^G+;nJCDQPd#gYrPgG#+r!!kfl<$Vs
z7=i8z`Y-%YQrhIu+c}V3sxDXGO$33J@zQ;{TI16%dK!`KK={SdbF)OGvp!6TEdtS=
zKSU*B+;GBI{_lhS`LzVvTP!y@4y+xh5&axAC7pKRgQliB3q&Xr45_k^atqyZMLoL}
zJWlJML|LFg+BR|bBsaS{LOI$eZ1Y86FLWKv1^KvPF;mR7c~E8NB*E4b_7o-3Q-ga@
z3Ey4+xx1d*Z7OB{`jovu*(Nc(GnajOQ@5A>&222*hzWnxuQS`vHog!0w-!(B
zpk>lVQsd&|Xl1i^`SYZze{dA~<`2zdm-7l0axN;FK6Xg;LKttyznd&*m>
zHMl$jY8Go6jjIwc_bVE#etz4>C)Xyk{(r(?witqp!?%rZouOjcUrwx&nbpm@vp2}v
zd&Ub`En6Q{twSzRg{6S@U8Wbo`s=>eXPfbTl@~2<*LN;Pa}S;E9w)I{_&-8|=h~@z
zVy#fSCIxx!(~p^^Oi)7=D#N$Q9)L%N@{4CwE%`I8s93&$kvCJJX5JJN92){Zvg?cq
zhA#4tcX$tb{)AGzNQCugI2W?YwZ-PedG!7dx%rV57tJh^tr@hm%fpX$Ey|{>w8Wtl
z>>RGcOjd7GAGSdgr(1Zb@(=KSlZ`tm>Ox3(R9lRF{VChw)vA2j@oS>4(s0?6cHSPE
zZ*$PuWl*S7t*oq6v82agf0G#qHbOPKu<1XVWDhoiJ(V+MttFY9JzMtsk%e->
zkeT)S`1ym@k5bo&&iAbDA$zqpW4($6AE{R89jh9aawyl0s}LzIkxb|h4ztBfHIh^!
z!pu&`6%RIsj8T2o2m_QdUn)!xKp?FgxH(%S*XJz=uz|B)$*&m<=E`ttb@D0WrSX6#Nir~4m71q4IM8`y-h$Yc0a{N#AihyA~zKx
zD1%1J4_BIs76jhGkqx2DsV*^sIO3dz2gM?Gw7x+@VW239tc`GMz1;%TFZDGzJ#-*t
z>+$wE=boq?A=zg(7rIZILn#O
zy3>EH^whV`fZZMttI}{K`74Z>t-nl6YT1_UqCZ-(a?W+%8Q?%r`-^t9XRasy4{6#K
Ah5!Hn
literal 755
zcmeAS@N?(olHy`uVBq!ia0y~yV15B)8*#7!$@A|%8Za<0?ecVS45^s&_RiU$R}KOV
z7v)Z!{rY!)X!)5~UQwpWKL3_KnKM;)k%LZfe5uOQIgc}5J~wxFS#q&I%4m5<$JAo2
z`DZ@I-!8d->dz00OBr(a|5@4Fe%JjTYjJ*`Si0QgQ!%ygqTk&%*kAwd<=?kJfzF?w
zl8wyei+pZ9dwKtD$=mn8rXE*Gi#x9U|6kAZ(C@zb+vPv)npf$QmiGMCuQxH#^XF#Y
zetx?Dw$Pe}>)9doTKaHgoJ0W(I~2C)+;m
zQ@s|>zRQ4}fuSK?_1g88UymHbp8?ex+QcGy6y{c4uarP0QYKG$#(l54wlUTg`CD{7ngtkrmw4002=pUIihVM&K#m(Ij
iKpP)i&guNL@V{<)mHO$N>Kj1I7(8A5T-G@yGywoew=(De
diff --git a/resources/image/sign/sign_res/bar_white.png b/resources/image/sign/sign_res/bar_white.png
index e04bca9849eda05101a13727adca9dc7dbae59b3..c09c4635dc82360d7a0b27691d7c4ade713fe46f 100644
GIT binary patch
literal 1431
zcmW+$dr(qo9KEcowoaJS1~q~?ZV$~i%eB-rwA3CJWhD=_L|ZFYL)0+~Z%eot(o1Wm
zEH_cfU7sjun3joJOq%0cyJGktV|^@&u0!}DWWU=#ckY~XzVn^$ckcaepFD9GYh`N%
zK@c|ZNWf_bGMfbNzpSzVsxdT@Yl>2n;wtVGFdwjdw57?ONs*$o;Klo5fo#aHnsv
z@UB~VH>l?c1oLEE)vAK2qt$nK!YrOC75~$ro1gCdw#l~F>2Di{j6Z}K1s`!(=M4wQ
z?`^kA<@esn6e(8(f96JXo%hheZ{)ItA>B}ta*gU*XLv|N#H`H@T6_shG(xJWpf-B8
z9{_ni-QtwMHLw_d7Dk%J;H@2mDjMk|r`+pIuFs?y1_&(X7c>e)jWz$5OS80A7_gIf
z5kr}TX0N&&A2;q1s#Hv)KFyWA4|v6@@?w#M9z?>C4p75vL
zh54n|LuD@N=po}7n`MzC*U0RApu9oqJ
zzb?VJFF|zQBM1?Y^P0l+vCr!X{YA4Inyy++u5o8tc#v!WGmtZuUbg&BBlS)mauMc>
z^8!6BAt*KN>2p0#)1&o@!*vJIx@g79#mlxpUdavKV$9R@((G!iR4U1ga?}S!J&s`s
zEu>J{MUi!m*&+uiRt~H~LwUa3##K>C^;G^x`p|k&8#1hZrP&JzqBtx4#$rwxw`(LD
zJ33o2GV-6yeH4v49#yg2JKp@!YFUl&TQVIpSqy+CFv~MqCPcLqdNCn*KbMnS_zZRt
zm_bm}SF(3qV-4dFq%ZS=fdoLN-a5~kEM-{
z76VD@QYe$1X6#HK9x^G|*W|@W|JrV}cqj6)c9rWMGR7D{@NNYNbXXnN*ZOO+itQpq
zx9rItiS+dzOh|4M1G1^Ug6!D;EekfXs!pGk_dP&~!IIn)cu||%1S;uCfxSY@S6q|O
zDDA51Q-;FQb5(E^%-UD`(EA%k*=%ZK$`MWJT-biJfhF%#;W19xbi!?;qdHMv5{3ehyrRKHzbh7mvgpk}0MI6V;%yX?WJqU4umkV7^R
zk_LB%1odc_AN8MKNpu^ncXyto*3!B>>c<tjUTk^$HKqlerS!Mu>g-Y`Wv{
zAPmI6^uj@4Dmgw{FRlufSK;7-Zqpk
zazhZU*GzS=!5?`?=>=AizK;i2P0Ysd6Byp{-_YO|1
z$y8bUaQb(|uO^O)krD0dq$e3{aLFIsOf2@Jy;0^$a)g+>hL`G?8@qo4k^
zrZa8dY9L~*-HvT*vM;?(m9e`mH|`d8)fIXnmC#BDVisix(~rq*(Z(1URrzY&hi
zDr5MxW31hTv;Q2i0CP#*8=AcUU5P|L7(x>lPx#
literal 584
zcmeAS@N?(olHy`uVBq!ia0y~yV15B)8*#7!$@A|%8Za<0@q4;BhE&XXd&e=a*+9fK
zaK)zox|bbYS&m3Z=X?r17s-%T^_AzbiSJ?FJWCd!HY>?$`43rtY!vwz7!K4=d3{&y
z<2|Jdu9iS4|7~v`UEWxydZ87>TXS}8jO?p)rq~(G3=9r&r7Ql=u>lG*ScKiVxRiUB
z0XqXjLvh!&FOyhf=Kxh4D80GQj;o{)Xe`6qH)Umd7mk8V*)sjj+gtOGFanvfZ&-JI
zl>st-{e1B*WI=Z^kohA2>iu;)Ko&6EcGx}-WKQip**r&(;SAFn^K3zk-@b-*^n-+i)`Yw#&@%K
diff --git a/services/db_context.py b/services/db_context.py
index e67c8a74..8af0cc4f 100755
--- a/services/db_context.py
+++ b/services/db_context.py
@@ -1,28 +1,61 @@
+from typing import List
-from gino import Gino
-from .log import logger
+from tortoise import Tortoise, fields
+from tortoise.connection import connections
+from tortoise.models import Model as Model_
+from tortoise.queryset import RawSQLQuery
+
+from configs.config import address, bind, database, password, port, sql_name, user
from utils.text_utils import prompt2cn
-from configs.config import bind, sql_name, user, password, address, port, database
+
+from .log import logger
+
+MODELS: List[str] = []
+
+SCRIPT_METHOD = []
-# 全局数据库连接对象
-db = Gino()
+class Model(Model_):
+ """
+ 自动添加模块
+
+ Args:
+ Model_ (_type_): _description_
+ """
+
+ def __init_subclass__(cls, **kwargs):
+ MODELS.append(cls.__module__)
+
+ if func := getattr(cls, "_run_script", None):
+ SCRIPT_METHOD.append(func)
+
+
+class TestSQL(Model):
+
+ id = fields.IntField(pk=True, generated=True, auto_increment=True)
+ """自增id"""
+
+ class Meta:
+ table = "test_sql"
+ table_description = "执行SQL命令,不记录任何数据"
async def init():
- if not bind and (not user and not password and not address and not port and not database):
+ if not bind and not any([user, password, address, port, database]):
raise ValueError("\n" + prompt2cn("数据库配置未填写", 28))
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!')
+ await Tortoise.init(db_url=i_bind, modules={"models": MODELS})
+ await Tortoise.generate_schemas()
+ logger.info(f"Database loaded successfully!")
except Exception as e:
- raise Exception(f'数据库连接错误.... {type(e)}: {e}')
+ raise Exception(f"数据库连接错误.... {type(e)}: {e}")
+ if SCRIPT_METHOD:
+ for func in SCRIPT_METHOD:
+ await func()
async def disconnect():
- await db.pop_bind().close()
-
+ await connections.close_all()
diff --git a/services/log.py b/services/log.py
index ee757aec..7d52bbd5 100755
--- a/services/log.py
+++ b/services/log.py
@@ -1,24 +1,141 @@
from datetime import datetime, timedelta
-from configs.path_config import LOG_PATH
+from typing import Any, Dict, Optional
+
from loguru import logger as logger_
-from nonebot.log import default_format, default_filter
+from nonebot.log import default_filter, default_format
+from configs.path_config import LOG_PATH
-logger = logger_
-
-
-logger.add(
- LOG_PATH / f'{datetime.now().date()}.log',
- level='INFO',
- rotation='00:00',
+logger_.add(
+ LOG_PATH / f"{datetime.now().date()}.log",
+ level="INFO",
+ rotation="00:00",
format=default_format,
filter=default_filter,
- retention=timedelta(days=30))
+ retention=timedelta(days=30),
+)
-logger.add(
- LOG_PATH / f'error_{datetime.now().date()}.log',
- level='ERROR',
- rotation='00:00',
+logger_.add(
+ LOG_PATH / f"error_{datetime.now().date()}.log",
+ level="ERROR",
+ rotation="00:00",
format=default_format,
filter=default_filter,
- retention=timedelta(days=30))
\ No newline at end of file
+ retention=timedelta(days=30),
+)
+
+
+class logger:
+
+ TEMPLATE_A = "{}"
+ TEMPLATE_B = "[{}]: {}"
+ TEMPLATE_C = "用户[{}] 触发 [{}]: {}"
+ TEMPLATE_D = "群聊[{}] 用户[{}] 触发 [{}]: {}"
+ TEMPLATE_E = "群聊[{}] 用户[{}] 触发 [{}] [Target]({}): {}"
+
+ TEMPLATE_USER = "用户[{}] "
+ TEMPLATE_GROUP = "群聊[{}] "
+ TEMPLATE_COMMAND = "CMD[{}] "
+ TEMPLATE_TARGET = "[Target]([{}]) "
+
+ SUCCESS_TEMPLATE = "[{}]: {} | 参数[{}] 返回: [{}]"
+
+ WARNING_TEMPLATE = "[{}]: {}"
+
+ ERROR_TEMPLATE = "[{}]: {}"
+
+ @classmethod
+ def info(
+ cls,
+ info: str,
+ command: Optional[str] = None,
+ user_id: Optional[int] = None,
+ group_id: Optional[int] = None,
+ target: Optional[Any] = None,
+ ):
+ template = cls.__parser_template(info, command, user_id, group_id, target)
+ logger_.opt(colors=True).info(template)
+
+ @classmethod
+ def success(
+ cls,
+ info: str,
+ command: str,
+ param: Optional[Dict[str, Any]] = None,
+ result: Optional[str] = "",
+ ):
+ param_str = ""
+ if param:
+ param_str = ",".join([f"{k}:{v}" for k, v in param.items()])
+ logger_.opt(colors=True).success(
+ cls.SUCCESS_TEMPLATE.format(command, info, param_str, result)
+ )
+
+ @classmethod
+ def warning(
+ cls,
+ info: str,
+ command: Optional[str] = None,
+ user_id: Optional[int] = None,
+ group_id: Optional[int] = None,
+ target: Optional[Any] = None,
+ e: Optional[Exception] = None,
+ ):
+ template = cls.__parser_template(info, command, user_id, group_id, target)
+ if e:
+ template += f" || 错误{type(e)}: {e}"
+ logger_.opt(colors=True).warning(template)
+
+ @classmethod
+ def error(
+ cls,
+ info: str,
+ command: Optional[str] = None,
+ user_id: Optional[int] = None,
+ group_id: Optional[int] = None,
+ target: Optional[Any] = None,
+ e: Optional[Exception] = None,
+ ):
+ template = cls.__parser_template(info, command, user_id, group_id, target)
+ if e:
+ template += f" || 错误 {type(e)}: {e}"
+ logger_.opt(colors=True).error(template)
+
+ @classmethod
+ def debug(
+ cls,
+ info: str,
+ command: Optional[str] = None,
+ user_id: Optional[int] = None,
+ group_id: Optional[int] = None,
+ target: Optional[Any] = None,
+ ):
+ template = cls.__parser_template(info, command, user_id, group_id, target)
+ logger_.opt(colors=True).debug(template)
+
+ @classmethod
+ def __parser_template(
+ cls,
+ info: str,
+ command: Optional[str] = None,
+ user_id: Optional[int] = None,
+ group_id: Optional[int] = None,
+ target: Optional[Any] = None,
+ ) -> str:
+ arg_list = []
+ template = ""
+ if group_id is not None:
+ template += cls.TEMPLATE_GROUP
+ arg_list.append(group_id)
+ if user_id is not None:
+ template += cls.TEMPLATE_USER
+ arg_list.append(user_id)
+ if command is not None:
+ template += cls.TEMPLATE_COMMAND
+ arg_list.append(command)
+ if target is not None:
+ template += cls.TEMPLATE_TARGET
+ arg_list.append(target)
+ arg_list.append(info)
+ template += "{}"
+ return template.format(*arg_list)
diff --git a/utils/browser.py b/utils/browser.py
index d602968d..c7a15587 100755
--- a/utils/browser.py
+++ b/utils/browser.py
@@ -1,34 +1,45 @@
import asyncio
from typing import Optional
+
+from nonebot import get_driver
from nonebot.log import logger
-from playwright.async_api import Browser, async_playwright
+from playwright.async_api import Browser, Playwright, async_playwright
+
from services.log import logger
+driver = get_driver()
+_playwright: Optional[Playwright] = None
_browser: Optional[Browser] = None
-async def init(**kwargs) -> Optional[Browser]:
+@driver.on_startup
+async def start_browser():
+ global _playwright
global _browser
- browser = await async_playwright().start()
- try:
- _browser = await browser.chromium.launch(**kwargs)
- return _browser
- except Exception as e:
- # logger.warning(f"启动chromium发生错误 {type(e)}:{e}")
- await asyncio.get_event_loop().run_in_executor(None, install)
- _browser = await browser.chromium.launch(**kwargs)
- return None
+ _playwright = await async_playwright().start()
+ _browser = await _playwright.chromium.launch()
-async def get_browser(**kwargs) -> Browser:
- return _browser or await init(**kwargs)
+@driver.on_shutdown
+async def shutdown_browser():
+ if _browser:
+ await _browser.close()
+ if _playwright:
+ _playwright.stop()
+
+
+def get_browser() -> Browser:
+ if not _browser:
+ raise RuntimeError("playwright is not initalized")
+ return _browser
def install():
"""自动安装、更新 Chromium"""
logger.info("正在检查 Chromium 更新")
import sys
+
from playwright.__main__ import main
sys.argv = ["", "install", "chromium"]
diff --git a/utils/data_utils.py b/utils/data_utils.py
index 643415e8..1fcc0a9d 100755
--- a/utils/data_utils.py
+++ b/utils/data_utils.py
@@ -1,13 +1,18 @@
-from models.group_member_info import GroupInfoUser
-from utils.image_utils import BuildMat
-from configs.path_config import IMAGE_PATH
-from typing import List, Union
import asyncio
import os
+from typing import List, Union
+
+from configs.path_config import IMAGE_PATH
+from models.group_member_info import GroupInfoUser
+from utils.image_utils import BuildMat
async def init_rank(
- title: str, all_user_id: List[int], all_user_data: List[int], group_id: int, total_count: int = 10
+ title: str,
+ all_user_id: List[int],
+ all_user_data: List[int],
+ group_id: int,
+ total_count: int = 10,
) -> BuildMat:
"""
说明:
@@ -26,11 +31,11 @@ async def init_rank(
max_user_id = all_user_id[all_user_data.index(_max)]
all_user_id.remove(max_user_id)
all_user_data.remove(_max)
- try:
- user_name = (
- await GroupInfoUser.get_member_info(max_user_id, group_id)
- ).user_name
- except AttributeError:
+ if user := await GroupInfoUser.get_or_none(
+ user_qq=max_user_id, group_id=group_id
+ ):
+ user_name = user.user_name
+ else:
user_name = f"{max_user_id}"
_uname_lst.append(user_name)
_num_lst.append(_max)
diff --git a/utils/depends/__init__.py b/utils/depends/__init__.py
index a1927a9b..d1ccb88e 100644
--- a/utils/depends/__init__.py
+++ b/utils/depends/__init__.py
@@ -1,13 +1,18 @@
-from typing import Callable, List, Optional, Union
+from typing import Callable, List, Optional, Tuple, Union
-from configs.config import Config
-from models.bag_user import BagUser
-from models.level_user import LevelUser
-from models.user_shop_gold_log import UserShopGoldLog
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
from nonebot.internal.matcher import Matcher
from nonebot.internal.params import Depends
+from nonebot.params import Command
+from configs.config import Config
+from models.bag_user import BagUser
+
+# from models.bag_user import BagUser
+from models.level_user import LevelUser
+from models.user_shop_gold_log import UserShopGoldLog
+
+# from models.user_shop_gold_log import UserShopGoldLog
from utils.manager import admin_manager
from utils.message_builder import at
from utils.utils import (
@@ -18,6 +23,19 @@ from utils.utils import (
)
+def OneCommand():
+ """
+ 获取单个命令Command
+ """
+
+ async def dependency(
+ cmd: Tuple[str, ...] = Command(),
+ ):
+ return cmd[0] if cmd else None
+
+ return Depends(dependency)
+
+
def AdminCheck(level: Optional[int] = None):
"""
说明:
@@ -27,16 +45,19 @@ def AdminCheck(level: Optional[int] = None):
"""
async def dependency(matcher: Matcher, event: GroupMessageEvent):
- plugin_level = admin_manager.get_plugin_module(matcher.plugin_name)
- user_level = await LevelUser.get_user_level(event.user_id, event.group_id)
- if level is None:
- if user_level < plugin_level:
- await matcher.finish(
- at(event.user_id) + f"你的权限不足喔,该功能需要的权限等级:{plugin_level}"
- )
- else:
- if user_level < level:
- await matcher.finish(at(event.user_id) + f"你的权限不足喔,该功能需要的权限等级:{level}")
+ if name := matcher.plugin_name:
+ plugin_level = admin_manager.get_plugin_level(name)
+ user_level = await LevelUser.get_user_level(event.user_id, event.group_id)
+ if level is None:
+ if user_level < plugin_level:
+ await matcher.finish(
+ at(event.user_id) + f"你的权限不足喔,该功能需要的权限等级:{plugin_level}"
+ )
+ else:
+ if user_level < level:
+ await matcher.finish(
+ at(event.user_id) + f"你的权限不足喔,该功能需要的权限等级:{level}"
+ )
return Depends(dependency)
@@ -53,8 +74,13 @@ def CostGold(gold: int):
if (await BagUser.get_gold(event.user_id, event.group_id)) < gold:
await matcher.finish(at(event.user_id) + f"金币不足..该功能需要{gold}金币..")
await BagUser.spend_gold(event.user_id, event.group_id, gold)
- await UserShopGoldLog.add_shop_log(
- event.user_id, event.group_id, 2, matcher.plugin_name, gold, 1
+ await UserShopGoldLog.create(
+ user_qq=event.user_id,
+ group_id=event.group_id,
+ type=2,
+ name=matcher.plugin_name,
+ num=1,
+ spend_gold=gold,
)
return Depends(dependency)
@@ -78,10 +104,12 @@ def GetConfig(
async def dependency(matcher: Matcher):
module_ = module or matcher.plugin_name
- value = Config.get_config(module_, config, default_value)
- if value is None:
- await matcher.finish(prompt or f"配置项 {config} 未填写!")
- return value
+ if module_:
+ value = Config.get_config(module_, config, default_value)
+ if value is None and prompt:
+ # await matcher.finish(prompt or f"配置项 {config} 未填写!")
+ await matcher.finish(prompt)
+ return value
return Depends(dependency)
@@ -102,10 +130,11 @@ def CheckConfig(
async def dependency(matcher: Matcher):
module_ = module or matcher.plugin_name
- config_list = [config] if isinstance(config, str) else config
- for c in config_list:
- if Config.get_config(module_, c) is None:
- await matcher.finish(prompt or f"配置项 {c} 未填写!")
+ if module_:
+ config_list = [config] if isinstance(config, str) else config
+ for c in config_list:
+ if Config.get_config(module_, c) is None:
+ await matcher.finish(prompt or f"配置项 {c} 未填写!")
return Depends(dependency)
diff --git a/utils/game_utils.py b/utils/game_utils.py
new file mode 100644
index 00000000..2ce2eb86
--- /dev/null
+++ b/utils/game_utils.py
@@ -0,0 +1,192 @@
+from typing import Optional, Dict, Union
+
+from nonebot.adapters.onebot.v11 import Message, MessageSegment
+from pydantic import BaseModel
+import time
+
+
+class GameEntry(BaseModel):
+ game_name: str
+ module: str
+ default_msg: str
+ msg_data: Dict[int, Union[str, Message, MessageSegment]]
+ timeout: int # 超时时限
+ anti_concurrency: bool # 是否阻断
+
+
+class GroupGameStatus(BaseModel):
+ game: GameEntry
+ status: int
+ time: time.time() # 创建时间
+
+
+class GameManager:
+ def __init__(self):
+ self._data = {}
+ self._status = {}
+
+ def add_game(
+ self,
+ game_name: str,
+ module: str,
+ timeout: int,
+ default_msg: Optional[str] = "游戏还未结束!",
+ msg_data: Dict[int, Union[str, Message, MessageSegment]] = None,
+ anti_concurrency: bool = True,
+ **kwargs,
+ ):
+ """
+ 参数:
+ 将游戏添加到游戏管理器
+ 说明:
+ :param game_name: 游戏名称
+ :param module: 模块名
+ :param timeout: 超时时长
+ :param default_msg: 默认回复消息
+ :param msg_data: 不同状态回复的消息
+ :param anti_concurrency: 是否阻断反并发
+ """
+ self._data[module] = GameEntry(
+ game_name=game_name,
+ module=module,
+ timeout=timeout,
+ default_msg=default_msg,
+ msg_data=msg_data or {},
+ anti_concurrency=anti_concurrency,
+ **kwargs,
+ )
+
+ def start(self, group_id: int, module: str):
+ """
+ 说明:
+ 游戏开始标记
+ 参数:
+ :param group_id: 群号
+ :param module: 模块名
+ """
+ if not self._status.get(group_id):
+ self._status[group_id] = []
+ if module not in [x.game.module for x in self._status[module]]:
+ self._status[group_id].append(
+ GroupGameStatus(game=self._data[module], status=0)
+ )
+
+ def end(self, group_id: int, module: str):
+ """
+ 说明:
+ 游戏结束标记
+ 参数:
+ :param group_id: 群号
+ :param module: 模块名
+ """
+ if self._status.get(group_id) and module in [
+ x.game.module for x in self._status[group_id]
+ ]:
+ for x in self._status[group_id]:
+ if self._status[group_id][x].game.module == module:
+ self._status[group_id].remove(x)
+ break
+
+ def set_status(self, group_id: int, module: str, status: int):
+ """
+ 说明:
+ 设置游戏状态,根据状态发送不同的提示消息 msg_data
+ 参数:
+ :param group_id: 群号
+ :param module: 模块名
+ :param status: 状态码
+ """
+ if self._status.get(group_id) and module in [
+ x.game.module for x in self._status[group_id]
+ ]:
+ [x.game.module for x in self._status[group_id] if x.game.module == module][
+ 0
+ ].status = status
+
+ def check(self, group_id, module: str) -> Optional[str]:
+ """
+ 说明:
+ 检查群游戏当前状态并返回提示语句
+ 参数:
+ :param group_id: 群号
+ :param module: 模块名
+ """
+ if module in self._data and self._status.get(group_id):
+ for x in self._status[group_id]:
+ if x.game.anti_concurrency:
+ return f"{x.game.game_name} 还未结束,请等待 {x.game.game_name} 游戏结束!"
+ if self._status.get(group_id) and module in [
+ x.game.module for x in self._status[group_id]
+ ]:
+ group_game_status = [
+ x.game.module for x in self._status[group_id] if x.game.module == module
+ ][0]
+ if time.time() - group_game_status.time > group_game_status.game.timeout:
+ # 超时结束
+ self.end(group_id, module)
+ else:
+ return (
+ group_game_status.game.msg_data.get(group_game_status.status)
+ or group_game_status.game.default_msg
+ )
+
+
+game_manager = GameManager()
+
+
+class Game:
+ """
+ 反并发,游戏重复开始
+ """
+ def __init__(
+ self,
+ game_name: str,
+ module: str,
+ timeout: int = 60,
+ default_msg: Optional[str] = None,
+ msg_data: Dict[int, Union[str, Message, MessageSegment]] = None,
+ anti_concurrency: bool = True,
+ ):
+ """
+ 参数:
+ 将游戏添加到游戏管理器
+ 说明:
+ :param game_name: 游戏名称
+ :param module: 模块名
+ :param timeout: 超时时长
+ :param default_msg: 默认回复消息
+ :param msg_data: 不同状态回复的消息
+ :param anti_concurrency: 是否阻断反并发
+ """
+ self.module = module
+ game_manager.add_game(
+ game_name, module, timeout, default_msg, msg_data, anti_concurrency
+ )
+
+ def start(self, group_id: int):
+ """
+ 说明:
+ 游戏开始标记
+ 参数:
+ :param group_id: 群号
+ """
+ game_manager.start(group_id, self.module)
+
+ def end(self, group_id: int):
+ """
+ 说明:
+ 游戏结束标记
+ 参数:
+ :param group_id: 群号
+ """
+ game_manager.end(group_id, self.module)
+
+ def set_status(self, group_id: int, status: int):
+ """
+ 说明:
+ 设置游戏状态,根据状态发送不同的提示消息 msg_data
+ 参数:
+ :param group_id: 群号
+ :param status: 状态码
+ """
+ game_manager.set_status(group_id, self.module, status)
diff --git a/utils/http_utils.py b/utils/http_utils.py
index 20b3a959..06362ac1 100644
--- a/utils/http_utils.py
+++ b/utils/http_utils.py
@@ -1,20 +1,23 @@
-from typing import Dict, Union, Optional, List, Any, Literal
-from utils.user_agent import get_user_agent
-from .utils import get_local_proxy
-from services.log import logger
-from pathlib import Path
-from httpx import Response
-from asyncio.exceptions import TimeoutError
-from nonebot.adapters.onebot.v11 import MessageSegment
-from playwright.async_api import Page, BrowserContext
-from .message_builder import image
-from httpx import ConnectTimeout
-from .browser import get_browser
-from retrying import retry
import asyncio
+from asyncio.exceptions import TimeoutError
+from contextlib import asynccontextmanager
+from pathlib import Path
+from typing import Any, AsyncGenerator, Dict, List, Literal, Optional, Union
+
import aiofiles
import httpx
import rich
+from httpx import ConnectTimeout, Response
+from nonebot.adapters.onebot.v11 import MessageSegment
+from playwright.async_api import BrowserContext, Page
+from retrying import retry
+
+from services.log import logger
+from utils.user_agent import get_user_agent
+
+from .browser import get_browser
+from .message_builder import image
+from .utils import get_local_proxy
class AsyncHttpx:
@@ -32,7 +35,7 @@ class AsyncHttpx:
cookies: Optional[Dict[str, str]] = None,
verify: bool = True,
use_proxy: bool = True,
- proxy: Dict[str, str] = None,
+ proxy: Optional[Dict[str, str]] = None,
timeout: Optional[int] = 30,
**kwargs,
) -> Response:
@@ -59,7 +62,7 @@ class AsyncHttpx:
headers=headers,
cookies=cookies,
timeout=timeout,
- **kwargs
+ **kwargs,
)
@classmethod
@@ -174,7 +177,9 @@ class AsyncHttpx:
headers = get_user_agent()
proxy = proxy if proxy else cls.proxy if use_proxy else None
try:
- async with httpx.AsyncClient(proxies=proxy, verify=verify) as client:
+ async with httpx.AsyncClient(
+ proxies=proxy, verify=verify
+ ) as client:
async with client.stream(
"GET",
url,
@@ -182,9 +187,11 @@ class AsyncHttpx:
headers=headers,
cookies=cookies,
timeout=timeout,
- **kwargs
+ **kwargs,
) as response:
- logger.info(f"开始下载 {path.name}.. Path: {path.absolute()}")
+ logger.info(
+ f"开始下载 {path.name}.. Path: {path.absolute()}"
+ )
async with aiofiles.open(path, "wb") as wf:
total = int(response.headers["Content-Length"])
with rich.progress.Progress(
@@ -192,13 +199,18 @@ class AsyncHttpx:
"[progress.percentage]{task.percentage:>3.0f}%",
rich.progress.BarColumn(bar_width=None),
rich.progress.DownloadColumn(),
- rich.progress.TransferSpeedColumn()
+ rich.progress.TransferSpeedColumn(),
) as progress:
- download_task = progress.add_task("Download", total=total)
+ download_task = progress.add_task(
+ "Download", total=total
+ )
async for chunk in response.aiter_bytes():
await wf.write(chunk)
await wf.flush()
- progress.update(download_task, completed=response.num_bytes_downloaded)
+ progress.update(
+ download_task,
+ completed=response.num_bytes_downloaded,
+ )
logger.info(f"下载 {url} 成功.. Path:{path.absolute()}")
return True
except (TimeoutError, ConnectTimeout):
@@ -274,7 +286,7 @@ class AsyncHttpx:
use_proxy=use_proxy,
timeout=timeout,
proxy=proxy,
- ** kwargs,
+ **kwargs,
)
)
)
@@ -285,64 +297,23 @@ class AsyncHttpx:
class AsyncPlaywright:
-
@classmethod
- async def _new_page(cls, user_agent: Optional[str] = None, **kwargs) -> Page:
+ @asynccontextmanager
+ async def new_page(cls, **kwargs) -> AsyncGenerator[Page, None]:
"""
说明:
获取一个新页面
参数:
:param user_agent: 请求头
"""
- browser = await get_browser()
- if browser:
- return await browser.new_page(user_agent=user_agent, **kwargs)
- raise BrowserIsNone("获取Browser失败...")
-
- @classmethod
- async def new_context(cls, user_agent: Optional[str] = None, **kwargs) -> BrowserContext:
- """
- 说明:
- 获取一个新上下文
- 参数:
- :param user_agent: 请求头
- """
- browser = await get_browser()
- if browser:
- return await browser.new_context(user_agent=user_agent, **kwargs)
- raise BrowserIsNone("获取Browser失败...")
-
- @classmethod
- async def goto(
- cls,
- url: str,
- *,
- timeout: Optional[float] = 100000,
- wait_until: Optional[
- Literal["domcontentloaded", "load", "networkidle"]
- ] = "networkidle",
- referer: str = None,
- **kwargs
- ) -> Optional[Page]:
- """
- 说明:
- goto
- 参数:
- :param url: 网址
- :param timeout: 超时限制
- :param wait_until: 等待类型
- :param referer:
- """
- page = None
+ browser = get_browser()
+ ctx = await browser.new_context(**kwargs)
+ page = await ctx.new_page()
try:
- page = await cls._new_page(**kwargs)
- await page.goto(url, timeout=timeout, wait_until=wait_until, referer=referer)
- return page
- except Exception as e:
- logger.warning(f"Playwright 访问 url:{url} 发生错误 {type(e)}:{e}")
- if page:
- await page.close()
- return None
+ yield page
+ finally:
+ await page.close()
+ await ctx.close()
@classmethod
async def screenshot(
@@ -352,13 +323,13 @@ class AsyncPlaywright:
element: Union[str, List[str]],
*,
wait_time: Optional[int] = None,
- viewport_size: Dict[str, int] = None,
+ viewport_size: Optional[Dict[str, int]] = None,
wait_until: Optional[
Literal["domcontentloaded", "load", "networkidle"]
] = "networkidle",
- timeout: float = None,
- type_: Literal["jpeg", "png"] = None,
- **kwargs
+ timeout: Optional[float] = None,
+ type_: Optional[Literal["jpeg", "png"]] = None,
+ **kwargs,
) -> Optional[MessageSegment]:
"""
说明:
@@ -373,33 +344,25 @@ class AsyncPlaywright:
:param timeout: 超时限制
:param type_: 保存类型
"""
- page = None
if viewport_size is None:
viewport_size = dict(width=2560, height=1080)
if isinstance(path, str):
path = Path(path)
- try:
- page = await cls.goto(url, wait_until=wait_until, **kwargs)
- await page.set_viewport_size(viewport_size)
- if isinstance(element, str):
- if wait_time:
- card = await page.wait_for_selector(element, timeout=wait_time * 1000)
- else:
- card = await page.query_selector(element)
- else:
- card = page
- for e in element:
- if wait_time:
- card = await card.wait_for_selector(e, timeout=wait_time * 1000)
- else:
- card = await card.query_selector(e)
- await card.screenshot(path=path, timeout=timeout, type=type_)
- return image(path)
- except Exception as e:
- logger.warning(f"Playwright 截图 url:{url} element:{element} 发生错误 {type(e)}:{e}")
- finally:
- if page:
- await page.close()
+ wait_time = wait_time * 1000 if wait_time else None
+ if isinstance(element, str):
+ element_list = [element]
+ else:
+ element_list = element
+ async with cls.new_page(viewport=viewport_size) as page:
+ await page.goto(url, timeout=timeout, wait_until=wait_until)
+ card = page
+ for e in element_list:
+ if not card:
+ return None
+ card = await card.wait_for_selector(e, timeout=wait_time)
+ if card:
+ await card.screenshot(path=path, timeout=timeout, type=type_)
+ return image(path)
return None
diff --git a/utils/image_utils.py b/utils/image_utils.py
index a3087b44..f835aa2b 100755
--- a/utils/image_utils.py
+++ b/utils/image_utils.py
@@ -7,23 +7,28 @@ import uuid
from io import BytesIO
from math import ceil
from pathlib import Path
-from typing import List, Literal, Optional, Tuple, Union, Callable, Awaitable
-
-from PIL.ImageFont import FreeTypeFont
-from nonebot.utils import is_coroutine_callable
+from typing import Awaitable, Callable, List, Literal, Optional, Tuple, Union
import cv2
import imagehash
-from configs.path_config import FONT_PATH, IMAGE_PATH
from imagehash import ImageHash
from matplotlib import pyplot as plt
+from nonebot.utils import is_coroutine_callable
from PIL import Image, ImageDraw, ImageFile, ImageFilter, ImageFont
+from PIL.ImageFont import FreeTypeFont
+
+from configs.path_config import FONT_PATH, IMAGE_PATH
from services import logger
ImageFile.LOAD_TRUNCATED_IMAGES = True
Image.MAX_IMAGE_PIXELS = None
+ModeType = Literal[
+ "1", "CMYK", "F", "HSV", "I", "L", "LAB", "P", "RGB", "RGBA", "RGBX", "YCbCr"
+]
+
+
def compare_image_with_hash(
image_file1: str, image_file2: str, max_dif: int = 1.5
) -> bool:
@@ -154,7 +159,7 @@ class BuildImage:
paste_image_width: int = 0,
paste_image_height: int = 0,
color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = None,
- image_mode: str = "RGBA",
+ image_mode: ModeType = "RGBA",
font_size: int = 10,
background: Union[Optional[str], BytesIO, Path] = None,
font: str = "yz.ttf",
@@ -162,7 +167,7 @@ class BuildImage:
is_alpha: bool = False,
plain_text: Optional[str] = None,
font_color: Optional[Union[str, Tuple[int, int, int]]] = None,
- **kwargs
+ **kwargs,
):
"""
参数:
@@ -320,6 +325,19 @@ class BuildImage:
self.markImg.paste(img, pos)
self._current_w += self.paste_image_width
+ @classmethod
+ def get_text_size(cls, msg: str, font: str, font_size: int) -> Tuple[int, int]:
+ """
+ 说明:
+ 获取文字在该图片 font_size 下所需要的空间
+ 参数:
+ :param msg: 文字内容
+ :param font: 字体
+ :param font_size: 字体大小
+ """
+ font = cls.load_font(font, font_size)
+ return font.getsize(msg)
+
def getsize(self, msg: str) -> Tuple[int, int]:
"""
说明:
@@ -395,7 +413,7 @@ class BuildImage:
center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
font: Union[FreeTypeFont, str] = None,
font_size: Optional[int] = None,
- **kwargs
+ **kwargs,
):
"""
说明:
@@ -408,7 +426,9 @@ class BuildImage:
:param font: 字体
:param font_size: 字体大小
"""
- await self.loop.run_in_executor(None, self.text, pos, text, fill, center_type, font, font_size, **kwargs)
+ await self.loop.run_in_executor(
+ None, self.text, pos, text, fill, center_type, font, font_size, **kwargs
+ )
def text(
self,
@@ -418,7 +438,7 @@ class BuildImage:
center_type: Optional[Literal["center", "by_height", "by_width"]] = None,
font: Union[FreeTypeFont, str] = None,
font_size: Optional[int] = None,
- **kwargs
+ **kwargs,
):
"""
说明:
@@ -577,9 +597,9 @@ class BuildImage:
buf = BytesIO()
self.markImg.save(buf, format="PNG")
base64_str = base64.b64encode(buf.getvalue()).decode()
- return base64_str
+ return "base64://" + base64_str
- def convert(self, type_: str):
+ def convert(self, type_: ModeType):
"""
说明:
修改图片类型
@@ -792,7 +812,7 @@ class BuildImage:
"""
self.markImg = self.markImg.rotate(angle, expand=expand)
- async def atranspose(self, angle: int):
+ async def atranspose(self, angle: Literal[0, 1, 2, 3, 4, 5, 6]):
"""
说明:
异步 旋转图片(包括边框)
@@ -801,7 +821,7 @@ class BuildImage:
"""
await self.loop.run_in_executor(None, self.transpose, angle)
- def transpose(self, angle: int):
+ def transpose(self, angle: Literal[0, 1, 2, 3, 4, 5, 6]):
"""
说明:
旋转图片(包括边框)
@@ -1663,7 +1683,11 @@ async def build_sort_image(
image_group: List[List[BuildImage]],
h: Optional[int] = None,
padding_top: int = 200,
- color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = (255, 255, 255),
+ color: Union[str, Tuple[int, int, int], Tuple[int, int, int, int]] = (
+ 255,
+ 255,
+ 255,
+ ),
background_path: Optional[Path] = None,
background_handle: Callable[[BuildImage], Optional[Awaitable]] = None,
) -> BuildImage:
diff --git a/utils/manager/admin_manager.py b/utils/manager/admin_manager.py
index e2a7c77b..9576582d 100644
--- a/utils/manager/admin_manager.py
+++ b/utils/manager/admin_manager.py
@@ -1,6 +1,8 @@
-from .models import AdminSetting
+from typing import Dict, List, Optional
+
from utils.manager.data_class import StaticData
-from typing import List, Optional, Dict
+
+from .models import AdminSetting
class AdminManager(StaticData):
@@ -59,7 +61,7 @@ class AdminManager(StaticData):
def get_plugin_level(self, plugin: str) -> int:
"""
说明:
- 获取插件等级
+ 获取插件权限
参数:
:param plugin: 模块名
"""
@@ -75,6 +77,7 @@ class AdminManager(StaticData):
:param cmd: 命令
"""
for key in self._data.keys():
- if self._data[key].cmd and cmd in self._data[key].cmd:
- return key
+ if data := self._data.get(key):
+ if data.cmd and cmd in data.cmd:
+ return key
return None
diff --git a/utils/message_builder.py b/utils/message_builder.py
index f2331b7c..6c26d62d 100755
--- a/utils/message_builder.py
+++ b/utils/message_builder.py
@@ -1,46 +1,43 @@
import io
from pathlib import Path
-from typing import List, Union
+from typing import List, Optional, Union
+
+from nonebot.adapters.onebot.v11.message import Message, MessageSegment
from configs.config import NICKNAME
from configs.path_config import IMAGE_PATH, RECORD_PATH
-from nonebot.adapters.onebot.v11.message import MessageSegment, Message
from services.log import logger
+from utils.image_utils import BuildImage
def image(
- file: Union[str, Path, bytes] = None,
- path: str = None,
- b64: str = None,
-) -> Union[MessageSegment, str]:
+ file: Optional[Union[str, Path, bytes, BuildImage, io.BytesIO]] = None,
+ b64: Optional[str] = None,
+) -> MessageSegment:
"""
说明:
生成一个 MessageSegment.image 消息
生成顺序:绝对路径(abspath) > base64(b64) > img_name
参数:
- :param file: 图片文件名称,默认在 resource/img 目录下
- :param path: 图片所在路径,默认在 resource/img 目录下
- :param b64: 图片base64
+ :param file: 图片文件
+ :param b64: 图片base64(兼容旧方法)
"""
+ if b64:
+ file = b64 if b64.startswith("base64://") else ("base64://" + b64)
+ if isinstance(file, str):
+ if file.startswith(("http", "base64://")):
+ return MessageSegment.image(file)
+ else:
+ return MessageSegment.image(IMAGE_PATH / file)
if isinstance(file, Path):
if file.exists():
return MessageSegment.image(file)
logger.warning(f"图片 {file.absolute()}缺失...")
- return ""
- elif isinstance(file, (bytes, io.BytesIO)):
+ if isinstance(file, (bytes, io.BytesIO)):
return MessageSegment.image(file)
- elif b64:
- return MessageSegment.image(b64 if "base64://" in b64 else "base64://" + b64)
- else:
- if file.startswith("http"):
- return MessageSegment.image(file)
- if len(file.split(".")) == 1:
- file += ".jpg"
- if (file := IMAGE_PATH / path / file if path else IMAGE_PATH / file).exists():
- return MessageSegment.image(file)
- else:
- logger.warning(f"图片 {file} 缺失...")
- return ""
+ if isinstance(file, BuildImage):
+ return MessageSegment.image(file.pic2bs4())
+ return MessageSegment.image("")
def at(qq: Union[int, str]) -> MessageSegment:
@@ -53,29 +50,25 @@ def at(qq: Union[int, str]) -> MessageSegment:
return MessageSegment.at(qq)
-def record(voice_name: str, path: str = None) -> MessageSegment or str:
+def record(file: Union[Path, str, bytes, io.BytesIO]) -> Union[MessageSegment, str]:
"""
说明:
生成一个 MessageSegment.record 消息
参数:
- :param voice_name: 音频文件名称,默认在 resource/voice 目录下
- :param path: 音频文件路径,默认在 resource/voice 目录下
+ :param file: 音频文件名称,默认在 resource/voice 目录下
"""
- if len(voice_name.split(".")) == 1:
- voice_name += ".mp3"
- file = (
- Path(RECORD_PATH) / path / voice_name
- if path
- else Path(RECORD_PATH) / voice_name
- )
- if "http" in voice_name:
- return MessageSegment.record(voice_name)
- if file.exists():
- result = MessageSegment.record(f"file:///{file.absolute()}")
- return result
- else:
- logger.warning(f"语音{file.absolute()}缺失...")
- return ""
+ if isinstance(file, Path):
+ if file.exists():
+ return MessageSegment.record(file)
+ logger.warning(f"音频 {file.absolute()}缺失...")
+ if isinstance(file, (bytes, io.BytesIO)):
+ return MessageSegment.record(file)
+ if isinstance(file, str):
+ if "http" in file:
+ return MessageSegment.record(file)
+ else:
+ return MessageSegment.record(RECORD_PATH / file)
+ return ""
def text(msg: str) -> MessageSegment:
@@ -99,7 +92,7 @@ def contact_user(qq: int) -> MessageSegment:
def share(
- url: str, title: str, content: str = None, image_url: str = None
+ url: str, title: str, content: Optional[str] = None, image_url: Optional[str] = None
) -> MessageSegment:
"""
说明:
@@ -158,7 +151,9 @@ def music(type_: str, id_: int) -> MessageSegment:
def custom_forward_msg(
- msg_list: List[Union[str, Message]], uin: Union[int, str], name: str = f"这里是{NICKNAME}"
+ msg_list: List[Union[str, Message]],
+ uin: Union[int, str],
+ name: str = f"这里是{NICKNAME}",
) -> List[dict]:
"""
说明:
@@ -202,11 +197,10 @@ class MessageBuilder:
def image(
self,
- file: Union[str, Path, bytes] = None,
- path: str = None,
- b64: str = None,
+ file: Optional[Union[str, Path, bytes]] = None,
+ b64: Optional[str] = None,
):
- return MessageBuilder(self._msg + image(file, path, b64))
+ return MessageBuilder(self._msg + image(file, b64))
def at(self, qq: int):
return MessageBuilder(self._msg + at(qq))
diff --git a/utils/utils.py b/utils/utils.py
index f3e286c3..3e87e95e 100755
--- a/utils/utils.py
+++ b/utils/utils.py
@@ -1,17 +1,20 @@
-from datetime import datetime
+import time
from collections import defaultdict
-from nonebot import require
-from configs.config import SYSTEM_PROXY, Config
-from typing import List, Union, Optional, Type, Any
-from nonebot.adapters.onebot.v11 import Bot, Message
-from nonebot.matcher import matchers, Matcher
-from services.log import logger
+from datetime import datetime
from pathlib import Path
+from typing import Any, Callable, List, Optional, Set, Type, Union
+
import httpx
import nonebot
-import pytz
import pypinyin
-import time
+import pytz
+from nonebot import require
+from nonebot.adapters import Bot
+from nonebot.adapters.onebot.v11 import Message, MessageSegment
+from nonebot.matcher import Matcher, matchers
+
+from configs.config import SYSTEM_PROXY, Config
+from services.log import logger
try:
import ujson as json
@@ -25,9 +28,9 @@ scheduler = scheduler
# 全局字典
GDict = {
- "run_sql": [], # 需要启动前运行的sql语句
- "_shop_before_handle": {}, # 商品使用前函数
- "_shop_after_handle": {}, # 商品使用后函数
+ "run_sql": [], # 需要启动前运行的sql语句
+ "_shop_before_handle": {}, # 商品使用前函数
+ "_shop_after_handle": {}, # 商品使用后函数
}
@@ -119,8 +122,8 @@ class BanCheckLimiter:
self.mint[key] = 0
return False
if (
- self.mint[key] >= self.default_count
- and time.time() - self.mtime[key] < self.default_check_time
+ self.mint[key] >= self.default_count
+ and time.time() - self.mtime[key] < self.default_check_time
):
self.mtime[key] = time.time()
self.mint[key] = 0
@@ -157,13 +160,15 @@ class DailyNumberLimiter:
self.count[key] = 0
-def is_number(s: str) -> bool:
+def is_number(s: Union[int, str]) -> bool:
"""
说明:
检测 s 是否为数字
参数:
:param s: 文本
"""
+ if isinstance(s, int):
+ return True
try:
float(s)
return True
@@ -179,14 +184,14 @@ def is_number(s: str) -> bool:
return False
-def get_bot() -> Optional[Bot]:
+def get_bot(id_: Optional[str] = None) -> Optional[Bot]:
"""
说明:
获取 bot 对象
"""
try:
- return list(nonebot.get_bots().values())[0]
- except IndexError:
+ return nonebot.get_bot(id_)
+ except ValueError:
return None
@@ -213,14 +218,15 @@ def get_message_at(data: Union[str, Message]) -> List[int]:
说明:
获取消息中所有的 at 对象的 qq
参数:
- :param data: event.json()
+ :param data: event.json(), event.message
"""
qq_list = []
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "at":
- qq_list.append(int(msg["data"]["qq"]))
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg and msg.get("type") == "at":
+ qq_list.append(int(msg["data"]["qq"]))
else:
for seg in data:
if seg.type == "at":
@@ -237,10 +243,11 @@ def get_message_img(data: Union[str, Message]) -> List[str]:
"""
img_list = []
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "image":
- img_list.append(msg["data"]["url"])
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg["type"] == "image":
+ img_list.append(msg["data"]["url"])
else:
for seg in data["image"]:
img_list.append(seg.data["url"])
@@ -256,10 +263,11 @@ def get_message_face(data: Union[str, Message]) -> List[str]:
"""
face_list = []
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "face":
- face_list.append(msg["data"]["id"])
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg["type"] == "face":
+ face_list.append(msg["data"]["id"])
else:
for seg in data["face"]:
face_list.append(seg.data["id"])
@@ -275,10 +283,11 @@ def get_message_img_file(data: Union[str, Message]) -> List[str]:
"""
file_list = []
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "image":
- file_list.append(msg["data"]["file"])
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg["type"] == "image":
+ file_list.append(msg["data"]["file"])
else:
for seg in data["image"]:
file_list.append(seg.data["file"])
@@ -294,10 +303,13 @@ def get_message_text(data: Union[str, Message]) -> str:
"""
result = ""
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "text":
- result += msg["data"]["text"].strip() + " "
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ if isinstance(message, str):
+ return message.strip()
+ for msg in message:
+ if msg["type"] == "text":
+ result += msg["data"]["text"].strip() + " "
return result.strip()
else:
for seg in data["text"]:
@@ -314,10 +326,11 @@ def get_message_record(data: Union[str, Message]) -> List[str]:
"""
record_list = []
if isinstance(data, str):
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "record":
- record_list.append(msg["data"]["url"])
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg["type"] == "record":
+ record_list.append(msg["data"]["url"])
else:
for seg in data["record"]:
record_list.append(seg.data["url"])
@@ -333,21 +346,22 @@ def get_message_json(data: str) -> List[dict]:
"""
try:
json_list = []
- data = json.loads(data)
- for msg in data["message"]:
- if msg["type"] == "json":
- json_list.append(msg["data"])
+ event = json.loads(data)
+ if data and (message := event.get("message")):
+ for msg in message:
+ if msg["type"] == "json":
+ json_list.append(msg["data"])
return json_list
except KeyError:
return []
-def get_local_proxy():
+def get_local_proxy() -> Optional[str]:
"""
说明:
获取 config.py 中设置的代理
"""
- return SYSTEM_PROXY if SYSTEM_PROXY else None
+ return SYSTEM_PROXY or None
def is_chinese(word: str) -> bool:
@@ -411,7 +425,7 @@ def cn2py(word: str) -> str:
def change_pixiv_image_links(
- url: str, size: Optional[str] = None, nginx_url: Optional[str] = None
+ url: str, size: Optional[str] = None, nginx_url: Optional[str] = None
):
"""
说明:
@@ -431,8 +445,8 @@ def change_pixiv_image_links(
if nginx_url:
url = (
url.replace("i.pximg.net", nginx_url)
- .replace("i.pixiv.cat", nginx_url)
- .replace("_webp", "")
+ .replace("i.pixiv.cat", nginx_url)
+ .replace("_webp", "")
)
return url
@@ -449,5 +463,69 @@ def change_img_md5(path_file: Union[str, Path]) -> bool:
f.write(str(int(time.time() * 1000)))
return True
except Exception as e:
- logger.warning(f"改变图片MD5发生错误 {type(e)}:{e} Path:{path_file}")
+ logger.warning(f"改变图片MD5错误 Path:{path_file}", e=e)
return False
+
+
+async def broadcast_group(
+ message: Union[str, Message, MessageSegment],
+ bot: Optional[Union[Bot, List[Bot]]] = None,
+ bot_id: Optional[Union[str, Set[str]]] = None,
+ ignore_group: Optional[Set[int]] = None,
+ check_func: Optional[Callable[[int], bool]] = None,
+ log_cmd: Optional[str] = None,
+):
+ """获取所有Bot或指定Bot对象广播群聊
+
+ Args:
+ message (Any): 广播消息内容
+ bot (Optional[Bot], optional): 指定bot对象. Defaults to None.
+ bot_id (Optional[str], optional): 指定bot id. Defaults to None.
+ ignore_group (Optional[List[int]], optional): 忽略群聊列表. Defaults to None.
+ check_func (Optional[Callable[[int], bool]], optional): 发送前对群聊检测方法,判断是否发送. Defaults to None.
+ log_cmd (Optional[str], optional): 日志标记. Defaults to None.
+ """
+ if not message:
+ raise ValueError("群聊广播消息不能为空")
+ bot_dict = nonebot.get_bots()
+ bot_list: List[Bot] = []
+ if bot:
+ if isinstance(bot, list):
+ bot_list = bot
+ else:
+ bot_list.append(bot)
+ elif bot_id:
+ _bot_id_list = bot_id
+ if isinstance(bot_id, str):
+ _bot_id_list = [bot_id]
+ for id_ in _bot_id_list:
+ if bot_id in bot_dict:
+ bot_list.append(bot_dict[bot_id])
+ else:
+ logger.warning(f"Bot:{id_} 对象未连接或不存在")
+ else:
+ bot_list = list(bot_dict.values())
+ _used_group = []
+ for _bot in bot_list:
+ try:
+ if _group_list := await _bot.get_group_list():
+ group_id_list = [g["group_id"] for g in _group_list]
+ for group_id in set(group_id_list):
+ try:
+ if (
+ ignore_group and group_id in ignore_group
+ ) or group_id in _used_group:
+ continue
+ if check_func and not check_func(group_id):
+ continue
+ _used_group.append(group_id)
+ await _bot.send_group_msg(group_id=group_id, message=message)
+ except Exception as e:
+ logger.error(
+ f"广播群发消息失败: {message}",
+ command=log_cmd,
+ group_id=group_id,
+ e=e,
+ )
+ except Exception as e:
+ logger.error(f"Bot: {_bot.self_id} 获取群聊列表失败", command=log_cmd, e=e)
From 86ac7709713efed96835c50f6a2356fb3bdbbafb Mon Sep 17 00:00:00 2001
From: HibiKier <775757368@qq.com>
Date: Sat, 18 Feb 2023 18:48:36 +0800
Subject: [PATCH 5/5] modified: README.md
---
README.md | 330 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 189 insertions(+), 141 deletions(-)
diff --git a/README.md b/README.md
index 7cca7e8b..c1e7788b 100644
--- a/README.md
+++ b/README.md
@@ -5,22 +5,27 @@

# 绪山真寻Bot
+
****
此项目基于 Nonebot2 和 go-cqhttp 开发,以 postgresql 作为数据库的QQ群娱乐机器人
+
## 关于
+
用爱发电,某些功能学习借鉴了大佬们的代码,因为绪山真寻实在太可爱了因此开发了
绪山真寻bot,实现了一些对群友的娱乐功能和实用功能(大概)。
如果该项目的图片等等侵犯猫豆腐老师权益请联系我删除!
-是新手!希望有个地方讨论绪山真寻Bot,或者有问题或建议,可以发送issues或加入[ [是真寻酱哒](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) ]
+是新手!希望有个地方讨论绪山真寻Bot,或者有问题或建议,可以发送issues或加入[ [是真寻酱哒(萌新版)](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) ]
-更喜欢讨论可爱的真寻,讨论插件开发,nonebot2开发,可以加入[ [真寻酱的技术群](https://jq.qq.com/?_wv=1027&k=E6sUkMzo) ])
+[//]: # (是老手!讨论插件开发,nonebot2开发,可以加入[ [真寻酱的技术群](https://jq.qq.com/?_wv=1027&k=u8PgBkMZ) ])
## 声明
+
此项目仅用于学习交流,请勿用于非法用途
# Nonebot2
+
非常 [ **[NICE](https://github.com/nonebot/nonebot2)** ] 的OneBot框架
@@ -30,18 +35,23 @@
# [传送门](https://hibikier.github.io/zhenxun_bot/)
## 真寻的帮助
+
请对真寻说: '真寻帮助' or '管理员帮助' or '超级用户帮助' or '真寻帮助 指令'
## 普通帮助图片
+

## HTML版帮助图片
+

## Web UI
+
[zhenxun_bot_webui](https://github.com/HibiKier/zhenxun_bot_webui)
## 一键安装脚本
+
[zhenxun_bot-deploy](https://github.com/AkashiCoin/zhenxun_bot-deploy)
## 提供符合真寻标准的插件仓库
@@ -50,152 +60,164 @@
## 来点优点?
- * 实现了许多功能,且提供了大量功能管理命令
- * 通过Config配置项将所有插件配置统计保存至config.yaml,利于统一用户修改
- * 方便增删插件,原生nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
- * 提供了cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`__plugin_cd_limit__`
- * __..... 更多详细请通过`传送门`查看文档!__
-
+* 实现了许多功能,且提供了大量功能管理命令
+* 通过Config配置项将所有插件配置统计保存至config.yaml,利于统一用户修改
+* 方便增删插件,原生nonebot2 matcher,不需要额外修改,仅仅通过简单的配置属性就可以生成`帮助图片`和`帮助信息`
+* 提供了cd,阻塞,每日次数等限制,仅仅通过简单的属性就可以生成一个限制,例如:`__plugin_cd_limit__`
+* __..... 更多详细请通过`传送门`查看文档!__
## 功能列表
+
已实现的功能
### 已实现的常用功能
-- [x] 昵称系统(群与群与私聊分开.)
-- [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
-- [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
-- [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
-- [x] 色图(这不是基础功能嘛喂)
-- [x] coser
-- [x] 黑白草图生成器
-- [x] 鸡汤/语录
-- [x] 骂我(钉宫语音)
-- [x] 戳一戳(概率发送美图,钉宫语音或者戳回去)
-- [x] 模拟开箱/我的开箱/群开箱统计/我的金色/设置cookie(csgo,内置爬虫脚本,需要提前抓取数据和图片,需要session,可能需要代理,阿里云服务器等ip也许已经被ban了(我无代理访问失败),如果访问太多账号API调用可能被禁止访问api!)
-- [x] 鲁迅说过
-- [x] 构造假消息(自定义的分享链接)
-- [x] 商店/我的金币/购买道具/使用道具
-- [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
-- [x] 我有一个朋友想问问..(借鉴pcrbot插件)
-- [x] 原神黄历
-- [x] 原神今日素材
-- [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
-- [x] 原神便笺查询
-- [x] 原神玩家查询
-- [x] 原神树脂提醒
-- [x] 原神签到/自动签到
-- [x] 金币红包
-- [x] 微博热搜
-- [x] B站主播/UP/番剧订阅
-- [x] pil对图片的一些操作
-- [x] BUFF饰品底价查询(需要session)
-- [x] 天气查询
-- [x] 疫情查询
-- [x] bt磁力搜索(咳咳,这功能我想dddd)
-- [x] reimu搜索(上车) (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
-- [x] 靠图识番 (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
-- [x] 以图搜图 (使用[nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher)插件)
-- [x] 搜番
-- [x] 点歌 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)插件(删除了选歌和评论)
-- [x] epic免费游戏
-- [x] p站排行榜
-- [x] p站搜图
-- [x] 翻译(日英韩)
-- [x] pix图库(一个自己的图库,含有增删查改,黑名单等命令)
+* [x] 昵称系统(群与群与私聊分开.)
-- [x] 查看当前群欢迎消息
-- [x] 查看该群自己的权限
-- [x] 我的信息(只是为了看看什么时候入群)
-- [x] 更新信息(如果继续更新的话)
-- [x] go-cqhttp最新版下载和上传(不需要请删除)
-- [x] 撤回
-- [x] 滴滴滴-(用户对超级用户发送消息)
-- [x] 金币红包/金币排行
-- [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
-- [x] 网易云热评
-- [x] 念首古诗
-- [x] 获取b站视频封面
-- [x] 通过PID获取图片
-- [x] 功能统计可视化
-- [x] 词云
-- [x] 关于
+* [x] 图灵AI(会把'你'等关键字替换为你的昵称),且带有 [AnimeThesaurus](https://github.com/Kyomotoi/AnimeThesaurus),够味
+* [x] 签到/我的签到/好感度排行/好感度总排行(影响色图概率和开箱次数,支持配置)
+* [x] 发送某文件夹下的随机图片(支持自定义,默认:美图,萝莉,壁纸)
+* [x] 色图(这不是基础功能嘛喂)
+* [x] coser
+* [x] 黑白草图生成器
+* [x] 鸡汤/语录
+* [x] 骂我(钉宫语音)
+* [x] 戳一戳(概率发送美图,钉宫语音或者戳回去)
+* [x] 模拟开箱/我的开箱/群开箱统计/我的金色/设置cookie(csgo,内置爬虫脚本,需要提前抓取数据和图片,需要session,可能需要代理,阿里云服务器等ip也许已经被ban了(我无代理访问失败),如果访问太多账号API调用可能被禁止访问api!)
+* [x] 鲁迅说过
+* [x] 构造假消息(自定义的分享链接)
+* [x] 商店/我的金币/购买道具/使用道具
+* [x] 8种手游抽卡 (查看 [nonebot_plugin_gamedraw](https://github.com/HibiKier/nonebot_plugin_gamedraw))
+* [x] 我有一个朋友想问问..(借鉴pcrbot插件)
+* [x] 原神黄历
+* [x] 原神今日素材
+* [x] 原神资源查询 (借鉴[Genshin_Impact_bot](https://github.com/H-K-Y/Genshin_Impact_bot)插件)
+* [x] 原神便笺查询
+* [x] 原神玩家查询
+* [x] 原神树脂提醒
+* [x] 原神签到/自动签到
+* [x] 金币红包
+* [x] 微博热搜
+* [x] B站主播/UP/番剧订阅
+
+* [x] pil对图片的一些操作
+* [x] BUFF饰品底价查询(需要session)
+* [x] 天气查询
+* [x] 疫情查询
+* [x] bt磁力搜索(咳咳,这功能我想dddd)
+* [x] reimu搜索(上车) (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
+* [x] 靠图识番 (使用[XUN_Langskip](https://github.com/Angel-Hair/XUN_Bot)的插件)
+* [x] 以图搜图 (使用[nonebot_plugin_picsearcher](https://github.com/synodriver/nonebot_plugin_picsearcher)插件)
+* [x] 搜番
+* [x] 点歌 [nonebot_plugin_songpicker2](https://github.com/maxesisn/nonebot_plugin_songpicker2)插件(删除了选歌和评论)
+* [x] epic免费游戏
+* [x] p站排行榜
+* [x] p站搜图
+* [x] 翻译(日英韩)
+* [x] pix图库(一个自己的图库,含有增删查改,黑名单等命令)
+
+* [x] 查看当前群欢迎消息
+* [x] 查看该群自己的权限
+* [x] 我的信息(只是为了看看什么时候入群)
+* [x] 更新信息(如果继续更新的话)
+* [x] go-cqhttp最新版下载和上传(不需要请删除)
+* [x] 撤回
+* [x] 滴滴滴-(用户对超级用户发送消息)
+* [x] 金币红包/金币排行
+* [x] 俄罗斯轮盘/胜场排行/败场排行/欧洲人排行/慈善家排行
+* [x] 网易云热评
+* [x] 念首古诗
+* [x] 获取b站视频封面
+* [x] 通过PID获取图片
+* [x] 功能统计可视化
+* [x] 词云
+* [x] 关于
### 已实现的管理员功能
-- [x] 更新群组成员信息
-- [x] 95%的群功能开关
-- [x] 查看群内被动技能状态
-- [x] 自定义群欢迎消息(是真寻的不是管家的!)
-- [x] .ban/.unban(支持设置ban时长)= 黑白名单
-- [x] 刷屏禁言相关:刷屏检测设置/设置禁言时长/设置检测次数
-- [x] 上传图片/连续上传图片 (上传图片至指定图库)
-- [x] 移动图片 (同上)
-- [x] 删除图片 (同上)
-- [x] 群内B站订阅
-- [x] 词条设置
-- [x] 休息吧/醒来
+
+* [x] 更新群组成员信息
+
+* [x] 95%的群功能开关
+* [x] 查看群内被动技能状态
+* [x] 自定义群欢迎消息(是真寻的不是管家的!)
+* [x] .ban/.unban(支持设置ban时长)= 黑白名单
+* [x] 刷屏禁言相关:刷屏检测设置/设置禁言时长/设置检测次数
+* [x] 上传图片/连续上传图片 (上传图片至指定图库)
+* [x] 移动图片 (同上)
+* [x] 删除图片 (同上)
+* [x] 群内B站订阅
+* [x] 词条设置
+* [x] 休息吧/醒来
### 已实现的超级用户功能
-- [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
-- [x] 开启/关闭指定群的广播通知
-- [x] 广播
-- [x] 自检(检查系统状态)
-- [x] 所有群组/所有好友
-- [x] 退出指定群
-- [x] 更新好友信息/更新群信息
-- [x] /t(对用户进行回复或发送消息)
-- [x] 上传/删除/修改商品(需要编写对应的商品功能)
-- [x] 节日红包发送
-- [x] 修改群权限
-- [x] ban
-- [x] 更新色图
-- [x] 更新价格/更加图片(csgo开箱)
-- [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
-- [x] 更新原神今日素材/更新原神资源信息
-- [x] PIX相关操作
-- [x] 检查更新真寻
-- [x] 重启
-- [x] 添加/删除/查看群白名单
-- [x] 功能开关(更多设置)
-- [x] 功能状态
-- [x] b了
-- [x] 执行sql
-- [x] 重载配置
-- [x] 清理临时数据
-- [x] 增删群认证
-- [x] 同意/拒绝好友/群聊请求
-- [x] 配置重载
+
+* [x] 添加/删除权限(是真寻的管理员权限,不是群管理员)
+
+* [x] 开启/关闭指定群的广播通知
+* [x] 广播
+* [x] 自检(检查系统状态)
+* [x] 所有群组/所有好友
+* [x] 退出指定群
+* [x] 更新好友信息/更新群信息
+* [x] /t(对用户进行回复或发送消息)
+* [x] 上传/删除/修改商品(需要编写对应的商品功能)
+* [x] 节日红包发送
+* [x] 修改群权限
+* [x] ban
+* [x] 更新色图
+* [x] 更新价格/更加图片(csgo开箱)
+* [x] 重载原神/方舟/赛马娘/坎公骑冠剑卡池
+* [x] 更新原神今日素材/更新原神资源信息
+* [x] PIX相关操作
+* [x] 检查更新真寻
+* [x] 重启
+* [x] 添加/删除/查看群白名单
+* [x] 功能开关(更多设置)
+* [x] 功能状态
+* [x] b了
+* [x] 执行sql
+* [x] 重载配置
+* [x] 清理临时数据
+* [x] 增删群认证
+* [x] 同意/拒绝好友/群聊请求
+* [x] 配置重载
#### 超级用户的被动技能
-- [x] 邀请入群提醒(别人邀请真寻入群)
-- [x] 添加好友提醒(别人添加真寻好友)
+
+* [x] 邀请入群提醒(别人邀请真寻入群)
+
+* [x] 添加好友提醒(别人添加真寻好友)
### 已实现的被动技能
-- [x] 进群欢迎消息
-- [x] 群早晚安
-- [x] 每日开箱重置提醒
-- [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv),且5分钟内不解析相同url
-- [x] 丢人爬(爬表情包)
-- [x] epic通知(每日发送epic免费游戏链接)
-- [x] 原神黄历提醒
-- [x] 复读
-### 已实现的看不见的技能!
-- [x] 刷屏禁言检测
-- [x] 功能调用统计
-- [x] 检测恶意触发命令(将被最高权限ban掉30分钟,只有最高权限(9级)可以进行unban)
-- [x] 自动同意好友请求,加群请求将会提醒管理员,退群提示,加群欢迎等等
-- [x] 群聊时间检测(当群聊最后一人发言时间大于当前36小时后将关闭该群所有通知(即被动技能))
-- [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
-- [x] 群权限系统
-- [x] 定时更新权限
-- [x] 自动配置重载
+* [x] 进群欢迎消息
+
+* [x] 群早晚安
+* [x] 每日开箱重置提醒
+* [x] b站转发解析(解析b站分享信息,支持bv,bilibili链接,b站手机端转发卡片,cv,b23.tv),且5分钟内不解析相同url
+* [x] 丢人爬(爬表情包)
+* [x] epic通知(每日发送epic免费游戏链接)
+* [x] 原神黄历提醒
+* [x] 复读
+
+### 已实现的看不见的技能
+
+* [x] 刷屏禁言检测
+
+* [x] 功能调用统计
+* [x] 检测恶意触发命令(将被最高权限ban掉30分钟,只有最高权限(9级)可以进行unban)
+* [x] 自动同意好友请求,加群请求将会提醒管理员,退群提示,加群欢迎等等
+* [x] 群聊时间检测(当群聊最后一人发言时间大于当前36小时后将关闭该群所有通知(即被动技能))
+* [x] 群管理员监控,自动为新晋管理员增加权限,为失去群管理员的用户删除权限
+* [x] 群权限系统
+* [x] 定时更新权限
+* [x] 自动配置重载
+
## 详细配置请前往文档,以下为最简部署和配置,如果你有基础并学习过nonebot2的话
-
## 简单部署
```
@@ -238,26 +260,38 @@ python bot.py
```
-
## 使用Docker
-__Docker 单机版(仅真寻Bot)__
+
+**Docker 单机版(仅真寻Bot)**
**点击下方的 GitHub 徽标查看教程**
[](https://github.com/Sakuracio/zhenxun_bot_docker)
[](https://hub.docker.com/r/hibikier/zhenxun_bot)
-__Docker 全量版(包含 真寻Bot PostgreSQL数据库 go-cqhttp webui等)__
+**Docker 全量版(包含 真寻Bot PostgreSQL数据库 go-cqhttp webui等)**
[](https://github.com/SinKy-Yan/zhenxunbot-docker)
[](https://hub.docker.com/r/jyishit/zhenxun_bot)
**点击上方的 GitHub 徽标查看教程**
PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能无法正常启动全量版容器**
## [爱发电](https://afdian.net/@HibiKier)
+
爱发电 以及 感谢投喂
### 感谢名单
-(可以告诉我你的 __github__ 地址,我偷偷换掉0v|)
+(可以告诉我你的 **github** 地址,我偷偷换掉0v|)
+
+[shenqi](https://afdian.net/u/fa923a8cfe3d11eba61752540025c377)
+[A_Kyuu](https://afdian.net/u/b83954fc2c1211eba9eb52540025c377)
+[疯狂混沌](https://afdian.net/u/789a2f9200cd11edb38352540025c377)
+[投冥](https://afdian.net/a/144514mm)
+[茶喵](https://afdian.net/u/fd22382eac4d11ecbfc652540025c377)
+[AemokpaTNR](https://afdian.net/u/1169bb8c8a9611edb0c152540025c377)
+[爱发电用户_wrxn](https://afdian.net/u/4aa03d20db4311ecb1e752540025c377)
+[qqw](https://afdian.net/u/b71db4e2cc3e11ebb76652540025c377)
+[溫一壺月光下酒](https://afdian.net/u/ad667a5c650c11ed89bf52540025c377)
+[伝木](https://afdian.net/u/246b80683f9511edba7552540025c377)
[阿奎](https://afdian.net/u/da41f72845d511ed930d52540025c377)
[醉梦尘逸](https://afdian.net/u/bc11d2683cd011ed99b552540025c377)
[Abc](https://afdian.net/u/870dc10a3cd311ed828852540025c377)
@@ -280,25 +314,37 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
[ln](https://afdian.net/u/b51914ba1c6611ed8a4e52540025c377)
[爱发电用户_b9S4](https://afdian.net/u/3d8f30581a2911edba6d52540025c377)
[爱发电用户_c58s](https://afdian.net/u/a6ad8dda195e11ed9a4152540025c377)
-[爱发电用户_eNr9](https://afdian.net/u/05fdb41c0c9a11ed814952540025c377)
-[MangataAkihi](https://github.com/Sakuracio)
-[炀](https://afdian.net/u/69b76e9ec77b11ec874f52540025c377)
+[爱发电用户_eNr9](https://afdian.net/u/05fdb41c0c9a11ed814952540025c377)
+[MangataAkihi](https://github.com/Sakuracio)
+[炀](https://afdian.net/u/69b76e9ec77b11ec874f52540025c377)
[爱发电用户_Bc6j](https://afdian.net/u/8546be24f44111eca64052540025c377)
-[大魔王](https://github.com/xipesoy)
+[大魔王](https://github.com/xipesoy)
[CopilotLaLaLa](https://github.com/CopilotLaLaLa)
-[嘿小欧](https://afdian.net/u/daa4bec4f24911ec82e552540025c377)
+[嘿小欧](https://afdian.net/u/daa4bec4f24911ec82e552540025c377)
[回忆的秋千](https://afdian.net/u/e315d9c6f14f11ecbeef52540025c377)
[十年くん](https://github.com/shinianj)
[哇](https://afdian.net/u/9b266244f23911eca19052540025c377)
[yajiwa](https://github.com/yajiwa)
[爆金币](https://afdian.net/u/0d78879ef23711ecb22452540025c377)
-
-
## 更新
+### 2022/2/18
+
+* 数据库舍弃`gino`使用`tortoise`
+* 昵称提供命令`全局昵称设置`
+* `manager_group`群管理操作中`退群`,`修改群权限`,`添加/删除群白名单`,`添加/删除群认证`在群聊中使用命令时且未指定群聊时,默认指定当前群聊
+
+### 2022/1/31
+
+* 修复B站转发卡片BUG [@pull/1249](https://github.com/HibiKier/zhenxun_bot/pull/1249)
+
+### 2022/1/27
+
+* 替换pixiv反向代理地址 [@pull/1244](https://github.com/HibiKier/zhenxun_bot/pull/1244)
+
### 2022/12/31
* 修复epic报错,优化简介 [@pull/1226](https://github.com/HibiKier/zhenxun_bot/pull/1226)
@@ -457,7 +503,7 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
### 2022/9/27
-* 更新b站转发解析 [@pull/1117](https://github.com/HibiKier/zhenxun_bot/pull/1117)
+* 更新b站转发解析 [@pull/1117](https://github.com/HibiKier/zhenxun_bot/pull/1117)
### 2022/9/24
@@ -556,12 +602,14 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
-__..... 更多更新信息请查看文档__
+**..... 更多更新信息请查看文档**
## Todo
-- [x] web管理
+
+* [x] web管理
## 感谢
+
[botuniverse / onebot](https://github.com/botuniverse/onebot) :超棒的机器人协议
[Mrs4s / go-cqhttp](https://github.com/Mrs4s/go-cqhttp) :cqhttp的golang实现,轻量、原生跨平台.
[nonebot / nonebot2](https://github.com/nonebot/nonebot2) :跨平台Python异步机器人框架