Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 修复添加插件依赖更新 #1837

Merged
merged 11 commits into from
Feb 3, 2025
28 changes: 24 additions & 4 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ python-jose = { extras = ["cryptography"], version = "^3.3.0" }
python-multipart = "^0.0.9"
aiocache = "^0.12.2"
py-cpuinfo = "^9.0.0"
nonebot-plugin-uninfo = "^0.4.1"
nonebot-plugin-alconna = "^0.54.0"
tenacity = "^9.0.0"
nonebot-plugin-uninfo = ">0.4.1"

[tool.poetry.group.dev.dependencies]
nonebug = "^0.4"
Expand Down
33 changes: 32 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from pytest_mock import MockerFixture
from respx import MockRouter

from tests.config import BotId, UserId
from tests.config import BotId, GroupId, UserId

nonebot.load_plugin("nonebot_plugin_session")

Expand Down Expand Up @@ -64,6 +64,37 @@ def _init_bot(nonebug_init: None):
nonebot.load_plugins("zhenxun/builtin_plugins")
nonebot.load_plugins("zhenxun/plugins")

# 手动缓存 uninfo 所需信息
from nonebot_plugin_uninfo import (
Scene,
SceneType,
Session,
SupportAdapter,
SupportScope,
User,
)
from nonebot_plugin_uninfo.adapters.onebot11.main import fetcher as onebot11_fetcher
from nonebot_plugin_uninfo.adapters.onebot12.main import fetcher as onebot12_fetcher

onebot11_fetcher.session_cache = {
f"group_{GroupId.GROUP_ID_LEVEL_5}_{UserId.SUPERUSER}": Session(
self_id="test",
adapter=SupportAdapter.onebot11,
scope=SupportScope.qq_client,
scene=Scene(str(GroupId.GROUP_ID_LEVEL_0), SceneType.GROUP),
user=User(str(UserId.SUPERUSER)),
),
}
onebot12_fetcher.session_cache = {
f"group_{GroupId.GROUP_ID_LEVEL_5}_{UserId.SUPERUSER}": Session(
self_id="test",
adapter=SupportAdapter.onebot12,
scope=SupportScope.qq_client,
scene=Scene(str(GroupId.GROUP_ID_LEVEL_0), SceneType.GROUP),
user=User(str(UserId.SUPERUSER)),
),
}


@pytest.fixture
async def app(app: App, tmp_path: Path, mocker: MockerFixture):
Expand Down
2 changes: 2 additions & 0 deletions zhenxun/builtin_plugins/admin/welcome_message/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ def migrate(path: Path):
path: 路径
"""
text_file = path / "text.json"
if not text_file.exists():
return
with text_file.open(encoding="utf8") as f:
json_data = json.load(f)
new_data = {}
Expand Down
14 changes: 7 additions & 7 deletions zhenxun/builtin_plugins/platform/qq/group_handle/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@
group_decrease_handle = on_notice(
priority=1,
block=False,
rule=notice_rule([GroupMemberDecreaseEvent, GroupMemberIncreaseEvent]),
rule=notice_rule([GroupMemberDecreaseEvent, GroupDecreaseNoticeEvent]),
)
"""群员减少处理"""
add_group = on_request(priority=1, block=False)
Expand All @@ -116,19 +116,19 @@ async def _(
session: Uninfo,
event: GroupIncreaseNoticeEvent | GroupMemberIncreaseEvent,
):
user_id = str(event.user_id)
group_id = str(event.group_id)
if user_id == bot.self_id:
if session.user.id == bot.self_id:
"""新成员为bot本身"""
group, _ = await GroupConsole.get_or_create(
group_id=group_id, channel_id__isnull=True
group_id=str(event.group_id), channel_id__isnull=True
)
try:
await GroupManager.add_bot(bot, str(event.operator_id), group_id, group)
await GroupManager.add_bot(
bot, str(event.operator_id), str(event.group_id), group
)
except ForceAddGroupError as e:
await PlatformUtils.send_superuser(bot, e.get_info())
else:
await GroupManager.add_user(session, bot, user_id, group_id)
await GroupManager.add_user(session, bot)


@group_decrease_handle.handle()
Expand Down
58 changes: 37 additions & 21 deletions zhenxun/builtin_plugins/platform/qq/group_handle/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import random

from nonebot.adapters import Bot
from nonebot.exception import ActionFailed
from nonebot_plugin_alconna import At, UniMessage
from nonebot_plugin_uninfo import Uninfo
import ujson as json
Expand Down Expand Up @@ -54,7 +55,7 @@ async def __handle_add_group(
if plugin_list := await PluginInfo.filter(default_status=False).all():
for plugin in plugin_list:
block_plugin += f"<{plugin.module},"
group_info = await bot.get_group_info(group_id=group_id)
group_info = await bot.get_group_info(group_id=group_id, no_cache=True)
await GroupConsole.create(
group_id=group_info["group_id"],
group_name=group_info["group_name"],
Expand Down Expand Up @@ -215,33 +216,45 @@ async def __send_welcome_message(cls, session: Uninfo, user_id: str):
msg_list.insert(0, At("user", user_id))
logger.info("发送群欢迎消息...", "入群检测", session=session)
if msg_list:
await MessageUtils.build_message(msg_list).send() # type: ignore
else:
image = DEFAULT_IMAGE_PATH / random.choice(
os.listdir(DEFAULT_IMAGE_PATH)
)
await MessageUtils.build_message(
[
"新人快跑啊!!本群现状↓(快使用自定义群欢迎消息!)",
image,
]
).send()
await MessageUtils.build_message(msg_list).finish() # type: ignore
image = DEFAULT_IMAGE_PATH / random.choice(os.listdir(DEFAULT_IMAGE_PATH))
await MessageUtils.build_message(
[
"新人快跑啊!!本群现状↓(快使用自定义群欢迎消息!)",
image,
]
).send()

@classmethod
async def add_user(cls, session: Uninfo, bot: Bot, user_id: str, group_id: str):
async def add_user(cls, session: Uninfo, bot: Bot):
"""拉入用户
参数:
session: Uninfo
bot: Bot
user_id: 用户id
group_id: 群组id
"""
user_id = session.user.id
group_id = ""
if session.group:
if session.group.parent:
group_id = session.group.parent.id
else:
group_id = session.group.id
join_time = datetime.now()
user_info = await bot.get_group_member_info(group_id=group_id, user_id=user_id)
try:
user_info = await bot.get_group_member_info(
group_id=int(group_id), user_id=int(user_id), no_cache=True
)
except ActionFailed as e:
logger.warning("获取用户信息识别...", e=e)
user_info = {"user_id": user_id, "group_id": group_id, "nickname": ""}
await GroupInfoUser.update_or_create(
user_id=str(user_info["user_id"]),
group_id=str(user_info["group_id"]),
defaults={"user_name": user_info["nickname"], "user_join_time": join_time},
defaults={
"user_name": user_info["nickname"],
"user_join_time": join_time,
},
)
logger.info(f"用户{user_info['user_id']} 所属{user_info['group_id']} 更新成功")
if not await CommonUtils.task_is_block(
Expand Down Expand Up @@ -310,10 +323,13 @@ async def run_user(
group_id=group_id,
)
if sub_type == "kick":
operator = await bot.get_group_member_info(
user_id=int(operator_id), group_id=int(group_id)
)
operator_name = operator["card"] or operator["nickname"]
if operator_id != "0":
operator = await bot.get_group_member_info(
user_id=int(operator_id), group_id=int(group_id)
)
operator_name = operator["card"] or operator["nickname"]
else:
operator_name = ""
return f"{user_name}{operator_name} 送走了."
elif sub_type == "leave":
return f"{user_name}离开了我们..."
Expand Down
4 changes: 2 additions & 2 deletions zhenxun/builtin_plugins/plugin_store/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@
)

_matcher.shortcut(
r"添加插件",
r"(添加|安装)插件",
command="插件商店",
arguments=["add", "{%0}"],
prefix=True,
)

_matcher.shortcut(
r"移除插件",
r"(移除|卸载)插件",
command="插件商店",
arguments=["remove", "{%0}"],
prefix=True,
Expand Down
46 changes: 27 additions & 19 deletions zhenxun/builtin_plugins/plugin_store/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def install_requirement(plugin_path: Path):

try:
result = subprocess.run(
["pip", "install", "-r", str(existing_requirements)],
["poetry", "run", "pip", "install", "-r", str(existing_requirements)],
check=True,
capture_output=True,
text=True,
Expand Down Expand Up @@ -232,8 +232,9 @@ async def install_plugin_with_repo(
raise ValueError("所有API获取插件文件失败,请检查网络连接")
if module_path == ".":
module_path = ""
replace_module_path = module_path.replace(".", "/")
files = repo_api.get_files(
module_path=module_path.replace(".", "/") + ("" if is_dir else ".py"),
module_path=replace_module_path + ("" if is_dir else ".py"),
is_dir=is_dir,
)
download_urls = [await repo_info.get_raw_download_urls(file) for file in files]
Expand All @@ -248,25 +249,32 @@ async def install_plugin_with_repo(
else:
# 安装依赖
plugin_path = base_path / "/".join(module_path.split("."))
req_files = repo_api.get_files(REQ_TXT_FILE_STRING, False)
req_files.extend(repo_api.get_files("requirement.txt", False))
logger.debug(f"获取插件依赖文件列表: {req_files}", "插件管理")
req_download_urls = [
await repo_info.get_raw_download_urls(file) for file in req_files
]
req_paths: list[Path | str] = [plugin_path / file for file in req_files]
logger.debug(f"插件依赖文件下载路径: {req_paths}", "插件管理")
if req_files:
result = await AsyncHttpx.gather_download_file(
req_download_urls, req_paths
try:
req_files = repo_api.get_files(
f"{replace_module_path}/{REQ_TXT_FILE_STRING}", False
)
req_files.extend(
repo_api.get_files(f"{replace_module_path}/requirement.txt", False)
)
for success in result:
if not success:
raise Exception("插件依赖文件下载失败")
logger.debug(f"插件依赖文件列表: {req_paths}", "插件管理")
install_requirement(plugin_path)
logger.debug(f"获取插件依赖文件列表: {req_files}", "插件管理")
req_download_urls = [
await repo_info.get_raw_download_urls(file) for file in req_files
]
req_paths: list[Path | str] = [plugin_path / file for file in req_files]
logger.debug(f"插件依赖文件下载路径: {req_paths}", "插件管理")
if req_files:
result = await AsyncHttpx.gather_download_file(
req_download_urls, req_paths
)
for success in result:
if not success:
raise Exception("插件依赖文件下载失败")
logger.debug(f"插件依赖文件列表: {req_paths}", "插件管理")
install_requirement(plugin_path)
except ValueError as e:
logger.warning("未获取到依赖文件路径...", e=e)
return True
raise Exception("插件下载失败")
raise Exception("插件下载失败...")

@classmethod
async def remove_plugin(cls, plugin_id: str) -> str:
Expand Down
5 changes: 4 additions & 1 deletion zhenxun/builtin_plugins/sign_in/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from zhenxun.models.sign_user import SignUser
from zhenxun.utils.http_utils import AsyncHttpx
from zhenxun.utils.image_utils import BuildImage
from zhenxun.utils.platform import PlatformUtils

from .config import (
SIGN_BACKGROUND_PATH,
Expand Down Expand Up @@ -430,7 +431,9 @@ async def _generate_html_card(
)
now = datetime.now()
data = {
"ava_url": session.user.avatar,
"ava_url": PlatformUtils.get_user_avatar_url(
user.user_id, PlatformUtils.get_platform(session), session.self_id
),
"name": nickname,
"uid": uid,
"sign_count": f"{user.sign_count}",
Expand Down
26 changes: 22 additions & 4 deletions zhenxun/builtin_plugins/web_ui/api/tabs/main/data_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,13 +248,31 @@ def __get_query(
if bot_id:
query = query.filter(bot_id=bot_id)
if date_type == QueryDateType.DAY:
query = query.filter(create_time__gte=now - timedelta(hours=now.hour))
query = query.filter(
create_time__gte=now
- timedelta(hours=now.hour, minutes=now.minute, seconds=now.second)
)
if date_type == QueryDateType.WEEK:
query = query.filter(create_time__gte=now - timedelta(days=7))
query = query.filter(
create_time__gte=now
- timedelta(
days=7, hours=now.hour, minutes=now.minute, seconds=now.second
)
)
if date_type == QueryDateType.MONTH:
query = query.filter(create_time__gte=now - timedelta(days=30))
query = query.filter(
create_time__gte=now
- timedelta(
days=30, hours=now.hour, minutes=now.minute, seconds=now.second
)
)
if date_type == QueryDateType.YEAR:
query = query.filter(create_time__gte=now - timedelta(days=365))
query = query.filter(
create_time__gte=now
- timedelta(
days=365, hours=now.hour, minutes=now.minute, seconds=now.second
)
)
return query

@classmethod
Expand Down
2 changes: 2 additions & 0 deletions zhenxun/configs/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

from .utils import ConfigsManager

__all__ = ["BotConfig", "Config"]


class BotSetting(BaseModel):
self_nickname: str = ""
Expand Down
Loading
Loading