mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
Compare commits
6 Commits
2f661b5b4a
...
8b1e4525db
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8b1e4525db | ||
|
|
e93fc1463e | ||
|
|
61251ce137 | ||
|
|
30fe5a5393 | ||
|
|
3cf7c1d237 | ||
|
|
91f35ad63a |
3176
envs/pydantic-v1/poetry.lock
generated
3176
envs/pydantic-v1/poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@ nonebot-plugin-alconna = "^0.54.0"
|
||||
tenacity = "^9.0.0"
|
||||
nonebot-plugin-uninfo = ">0.4.1"
|
||||
pydantic = "1.10.18"
|
||||
alibabacloud-devops20210625 = "^5.0.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
nonebug = "^0.4"
|
||||
|
||||
3187
envs/pydantic-v2/poetry.lock
generated
3187
envs/pydantic-v2/poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -45,6 +45,7 @@ nonebot-plugin-alconna = "^0.54.0"
|
||||
tenacity = "^9.0.0"
|
||||
nonebot-plugin-uninfo = ">0.4.1"
|
||||
pydantic = "2.10.6"
|
||||
alibabacloud-devops20210625 = "^5.0.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
nonebug = "^0.4"
|
||||
|
||||
2910
poetry.lock
generated
2910
poetry.lock
generated
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@ multidict = ">=6.0.0,!=6.3.2"
|
||||
|
||||
redis = { version = ">=5", optional = true }
|
||||
asyncpg = { version = ">=0.20.0", optional = true }
|
||||
alibabacloud-devops20210625 = "^5.0.2"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
nonebug = "^0.4"
|
||||
|
||||
@ -2,6 +2,7 @@ aiocache==0.12.3 ; python_version >= "3.10" and python_version < "4.0"
|
||||
aiofiles==23.2.1 ; python_version >= "3.10" and python_version < "4.0"
|
||||
aiosqlite==0.17.0 ; python_version >= "3.10" and python_version < "4.0"
|
||||
annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "4.0"
|
||||
alibabacloud-devops20210625==5.0.2 ; python_version >= "3.10" and python_version < "4.0"
|
||||
anyio==4.8.0 ; python_version >= "3.10" and python_version < "4.0"
|
||||
apscheduler==3.11.0 ; python_version >= "3.10" and python_version < "4.0"
|
||||
arclet-alconna-tools==0.7.10 ; python_version >= "3.10" and python_version < "4.0"
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
from datetime import datetime
|
||||
import re
|
||||
|
||||
import nonebot
|
||||
from nonebot.adapters import Bot
|
||||
@ -32,7 +33,9 @@ class MemberUpdateManage:
|
||||
"""
|
||||
driver = nonebot.get_driver()
|
||||
default_auth = Config.get_config("admin_bot_manage", "ADMIN_DEFAULT_AUTH")
|
||||
nickname = member.nick or member.user.name or ""
|
||||
nickname = re.sub(
|
||||
r"[\x00-\x09\x0b-\x1f\x7f-\x9f]", "", member.nick or member.user.name or ""
|
||||
)
|
||||
role = member.role
|
||||
db_user_uid = [u.user_id for u in db_user]
|
||||
uid2name = {u.user_id: u.user_name for u in db_user}
|
||||
|
||||
@ -198,7 +198,9 @@ class StoreManager:
|
||||
except ValueError as e:
|
||||
return str(e)
|
||||
db_plugin_list = await cls.get_loaded_plugins("module")
|
||||
plugin_info = next(p for p in plugin_list if p.module == plugin_key)
|
||||
plugin_info = next((p for p in plugin_list if p.module == plugin_key), None)
|
||||
if plugin_info is None:
|
||||
return f"未找到插件 {plugin_key}"
|
||||
if plugin_info.module in [p[0] for p in db_plugin_list]:
|
||||
return f"插件 {plugin_info.name} 已安装,无需重复安装"
|
||||
is_external = True
|
||||
@ -307,7 +309,9 @@ class StoreManager:
|
||||
plugin_key = await cls._resolve_plugin_key(plugin_id)
|
||||
except ValueError as e:
|
||||
return str(e)
|
||||
plugin_info = next(p for p in plugin_list if p.module == plugin_key)
|
||||
plugin_info = next((p for p in plugin_list if p.module == plugin_key), None)
|
||||
if plugin_info is None:
|
||||
return f"未找到插件 {plugin_key}"
|
||||
path = BASE_PATH
|
||||
if plugin_info.github_url:
|
||||
path = BASE_PATH / "plugins"
|
||||
@ -383,7 +387,9 @@ class StoreManager:
|
||||
plugin_key = await cls._resolve_plugin_key(plugin_id)
|
||||
except ValueError as e:
|
||||
return str(e)
|
||||
plugin_info = next(p for p in plugin_list if p.module == plugin_key)
|
||||
plugin_info = next((p for p in plugin_list if p.module == plugin_key), None)
|
||||
if plugin_info is None:
|
||||
return f"未找到插件 {plugin_key}"
|
||||
logger.info(f"尝试更新插件 {plugin_info.name}", LOG_COMMAND)
|
||||
db_plugin_list = await cls.get_loaded_plugins("module", "version")
|
||||
suc_plugin = {p[0]: (p[1] or "Unknown") for p in db_plugin_list}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
class DbUrlIsNode(Exception):
|
||||
from zhenxun.utils.exception import HookPriorityException
|
||||
|
||||
|
||||
class DbUrlIsNode(HookPriorityException):
|
||||
"""
|
||||
数据库链接地址为空
|
||||
"""
|
||||
|
||||
@ -44,3 +44,33 @@ GIT_API_PROXY_COMMIT_FORMAT = (
|
||||
"https://git-api.zhenxun.org/repos/{owner}/{repo}/commits/{branch}"
|
||||
)
|
||||
"""git api commit地址格式 (代理)"""
|
||||
|
||||
ALIYUN_ORG_ID = "67a361cf556e6cdab537117a"
|
||||
"""阿里云 organization id"""
|
||||
|
||||
ALIYUN_ENDPOINT = "devops.cn-hangzhou.aliyuncs.com"
|
||||
"""阿里云 endpoint"""
|
||||
|
||||
ALIYUN_REGION = "cn-hangzhou"
|
||||
"""阿里云区域"""
|
||||
|
||||
Aliyun_AccessKey_ID = "LTAI5tNmf7KaTAuhcvRobAQs"
|
||||
"""阿里云AccessKey ID"""
|
||||
|
||||
Aliyun_Secret_AccessKey_encrypted = "NmJ3d2VNRU1MREY0T1RtRnBqMlFqdlBxN3pMUk1j"
|
||||
"""阿里云 Secret Access Key """
|
||||
|
||||
RDC_access_token_encrypted = (
|
||||
"cHQtYXp0allnQWpub0FYZWpqZm1RWGtneHk0XzBlMmYzZTZmLWQwOWItNDE4Mi1iZWUx"
|
||||
"LTQ1ZTFkYjI0NGRlMg=="
|
||||
)
|
||||
"""RDC Access Token """
|
||||
|
||||
ALIYUN_REPO_MAPPING = {
|
||||
"zhenxun-bot-resources": "4957431",
|
||||
"zhenxun_bot_plugins_index": "4957418",
|
||||
"zhenxun_bot_plugins": "4957429",
|
||||
"zhenxun_docs": "4957426",
|
||||
"zhenxun_bot": "4957428",
|
||||
}
|
||||
"""阿里云仓库ID映射"""
|
||||
|
||||
@ -1,8 +1,13 @@
|
||||
import base64
|
||||
import contextlib
|
||||
import sys
|
||||
from typing import Protocol
|
||||
|
||||
from aiocache import cached
|
||||
from alibabacloud_devops20210625 import models as devops_20210625_models
|
||||
from alibabacloud_devops20210625.client import Client as devops20210625Client
|
||||
from alibabacloud_tea_openapi import models as open_api_models
|
||||
from alibabacloud_tea_util import models as util_models
|
||||
from nonebot.compat import model_dump
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
@ -14,11 +19,18 @@ else:
|
||||
from strenum import StrEnum
|
||||
|
||||
from .const import (
|
||||
ALIYUN_ENDPOINT,
|
||||
ALIYUN_ORG_ID,
|
||||
ALIYUN_REGION,
|
||||
ALIYUN_REPO_MAPPING,
|
||||
CACHED_API_TTL,
|
||||
GIT_API_COMMIT_FORMAT,
|
||||
GIT_API_PROXY_COMMIT_FORMAT,
|
||||
GIT_API_TREES_FORMAT,
|
||||
JSD_PACKAGE_API_FORMAT,
|
||||
Aliyun_AccessKey_ID,
|
||||
Aliyun_Secret_AccessKey_encrypted,
|
||||
RDC_access_token_encrypted,
|
||||
)
|
||||
from .func import (
|
||||
get_fastest_archive_formats,
|
||||
@ -270,3 +282,239 @@ class GitHubStrategy:
|
||||
def get_files(self, module_path: str, is_dir: bool = True) -> list[str]:
|
||||
"""获取文件路径"""
|
||||
return self.export_files(module_path, is_dir)
|
||||
|
||||
|
||||
class AliyunTreeType(StrEnum):
|
||||
"""阿里云树类型"""
|
||||
|
||||
FILE = "blob"
|
||||
DIR = "tree"
|
||||
|
||||
|
||||
class AliyunTree(BaseModel):
|
||||
"""阿里云树节点"""
|
||||
|
||||
id: str
|
||||
is_lfs: bool = Field(alias="isLFS", default=False)
|
||||
mode: str
|
||||
name: str
|
||||
path: str
|
||||
type: AliyunTreeType
|
||||
|
||||
class Config:
|
||||
populate_by_name = True
|
||||
|
||||
|
||||
class AliyunFileInfo:
|
||||
"""阿里云策略"""
|
||||
|
||||
content: str
|
||||
"""文件内容"""
|
||||
file_path: str
|
||||
"""文件路径"""
|
||||
ref: str
|
||||
"""分支/标签/提交版本"""
|
||||
repository_id: str
|
||||
"""仓库ID"""
|
||||
|
||||
@classmethod
|
||||
async def get_file_content(
|
||||
cls, file_path: str, repo: str, ref: str = "main"
|
||||
) -> str:
|
||||
"""获取文件内容
|
||||
|
||||
参数:
|
||||
file_path: 文件路径
|
||||
repo: 仓库名称
|
||||
ref: 分支名称/标签名称/提交版本号
|
||||
|
||||
返回:
|
||||
str: 文件内容
|
||||
"""
|
||||
try:
|
||||
repository_id = ALIYUN_REPO_MAPPING.get(repo)
|
||||
if not repository_id:
|
||||
raise ValueError(f"未找到仓库 {repo} 对应的阿里云仓库ID")
|
||||
config = open_api_models.Config(
|
||||
access_key_id=Aliyun_AccessKey_ID,
|
||||
access_key_secret=base64.b64decode(
|
||||
Aliyun_Secret_AccessKey_encrypted.encode()
|
||||
).decode(),
|
||||
endpoint=ALIYUN_ENDPOINT,
|
||||
region_id=ALIYUN_REGION,
|
||||
)
|
||||
|
||||
client = devops20210625Client(config)
|
||||
|
||||
request = devops_20210625_models.GetFileBlobsRequest(
|
||||
organization_id=ALIYUN_ORG_ID,
|
||||
file_path=file_path,
|
||||
ref=ref,
|
||||
access_token=base64.b64decode(
|
||||
RDC_access_token_encrypted.encode()
|
||||
).decode(),
|
||||
)
|
||||
|
||||
runtime = util_models.RuntimeOptions()
|
||||
headers = {}
|
||||
|
||||
response = await client.get_file_blobs_with_options_async(
|
||||
repository_id,
|
||||
request,
|
||||
headers,
|
||||
runtime,
|
||||
)
|
||||
|
||||
if response and response.body and response.body.result:
|
||||
if not response.body.success:
|
||||
raise ValueError(
|
||||
f"阿里云请求失败: {response.body.error_code} - "
|
||||
f"{response.body.error_message}"
|
||||
)
|
||||
return response.body.result.content or ""
|
||||
|
||||
raise ValueError("获取阿里云文件内容失败")
|
||||
except Exception as e:
|
||||
raise ValueError(f"获取阿里云文件内容失败: {e}")
|
||||
|
||||
@classmethod
|
||||
async def get_repository_tree(
|
||||
cls,
|
||||
repo: str,
|
||||
path: str = "",
|
||||
ref: str = "main",
|
||||
search_type: str = "DIRECT",
|
||||
) -> list[AliyunTree]:
|
||||
"""获取仓库树信息
|
||||
|
||||
参数:
|
||||
repo: 仓库名称
|
||||
path: 代码仓库内的文件路径
|
||||
ref: 分支名称/标签名称/提交版本
|
||||
search_type: 查找策略
|
||||
"DIRECT" # 仅展示当前目录下的内容
|
||||
"RECURSIVE" # 递归查找当前路径下的所有文件
|
||||
"FLATTEN" # 扁平化展示
|
||||
|
||||
返回:
|
||||
list[AliyunTree]: 仓库树信息列表
|
||||
"""
|
||||
try:
|
||||
repository_id = ALIYUN_REPO_MAPPING.get(repo)
|
||||
if not repository_id:
|
||||
raise ValueError(f"未找到仓库 {repo} 对应的阿里云仓库ID")
|
||||
|
||||
config = open_api_models.Config(
|
||||
access_key_id=Aliyun_AccessKey_ID,
|
||||
access_key_secret=base64.b64decode(
|
||||
Aliyun_Secret_AccessKey_encrypted.encode()
|
||||
).decode(),
|
||||
endpoint=ALIYUN_ENDPOINT,
|
||||
region_id=ALIYUN_REGION,
|
||||
)
|
||||
|
||||
client = devops20210625Client(config)
|
||||
|
||||
request = devops_20210625_models.ListRepositoryTreeRequest(
|
||||
organization_id=ALIYUN_ORG_ID,
|
||||
path=path,
|
||||
access_token=base64.b64decode(
|
||||
RDC_access_token_encrypted.encode()
|
||||
).decode(),
|
||||
ref_name=ref,
|
||||
type=search_type,
|
||||
)
|
||||
|
||||
runtime = util_models.RuntimeOptions()
|
||||
headers = {}
|
||||
|
||||
response = await client.list_repository_tree_with_options_async(
|
||||
repository_id, request, headers, runtime
|
||||
)
|
||||
|
||||
if response and response.body:
|
||||
if not response.body.success:
|
||||
raise ValueError(
|
||||
f"阿里云请求失败: {response.body.error_code} - "
|
||||
f"{response.body.error_message}"
|
||||
)
|
||||
return [
|
||||
AliyunTree(**item.to_map()) for item in (response.body.result or [])
|
||||
]
|
||||
raise ValueError("获取仓库树信息失败")
|
||||
except Exception as e:
|
||||
raise ValueError(f"获取仓库树信息失败: {e}")
|
||||
|
||||
@classmethod
|
||||
async def get_newest_commit(cls, repo: str, branch: str = "main") -> str:
|
||||
"""获取最新提交
|
||||
参数:
|
||||
repo: 仓库名称
|
||||
branch: sha 分支名称/标签名称/提交版本号
|
||||
返回:
|
||||
commit: 最新提交信息
|
||||
"""
|
||||
try:
|
||||
repository_id = ALIYUN_REPO_MAPPING.get(repo)
|
||||
if not repository_id:
|
||||
raise ValueError(f"未找到仓库 {repo} 对应的阿里云仓库ID")
|
||||
|
||||
config = open_api_models.Config(
|
||||
access_key_id=Aliyun_AccessKey_ID,
|
||||
access_key_secret=base64.b64decode(
|
||||
Aliyun_Secret_AccessKey_encrypted.encode()
|
||||
).decode(),
|
||||
endpoint=ALIYUN_ENDPOINT,
|
||||
region_id=ALIYUN_REGION,
|
||||
)
|
||||
|
||||
client = devops20210625Client(config)
|
||||
|
||||
request = devops_20210625_models.GetRepositoryCommitRequest(
|
||||
organization_id=ALIYUN_ORG_ID,
|
||||
access_token=base64.b64decode(
|
||||
RDC_access_token_encrypted.encode()
|
||||
).decode(),
|
||||
)
|
||||
|
||||
runtime = util_models.RuntimeOptions()
|
||||
headers = {}
|
||||
|
||||
response = await client.get_repository_commit_with_options_async(
|
||||
repository_id, branch, request, headers, runtime
|
||||
)
|
||||
|
||||
if response and response.body:
|
||||
if not response.body.success:
|
||||
raise ValueError(
|
||||
f"阿里云请求失败: {response.body.error_code} - "
|
||||
f"{response.body.error_message}"
|
||||
)
|
||||
return response.body.result.id or ""
|
||||
raise ValueError("获取仓库commit信息失败")
|
||||
except Exception as e:
|
||||
raise ValueError(f"获取仓库commit信息失败: {e}")
|
||||
|
||||
def export_files(
|
||||
self, tree_list: list[AliyunTree], module_path: str, is_dir: bool
|
||||
) -> list[str]:
|
||||
"""导出文件路径"""
|
||||
return [
|
||||
file.path
|
||||
for file in tree_list
|
||||
if file.type == AliyunTreeType.FILE
|
||||
and file.path.startswith(module_path)
|
||||
and (not is_dir or file.path[len(module_path)] == "/" or not module_path)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
async def parse_repo_info(cls, repo: str) -> list[str]:
|
||||
"""解析仓库信息获取仓库树"""
|
||||
repository_id = ALIYUN_REPO_MAPPING.get(repo)
|
||||
if not repository_id:
|
||||
raise ValueError(f"未找到仓库 {repo} 对应的阿里云仓库ID")
|
||||
|
||||
tree_list = await cls.get_repository_tree(
|
||||
repo=repo,
|
||||
)
|
||||
return cls().export_files(tree_list, "", True)
|
||||
|
||||
@ -501,14 +501,12 @@ class PlatformUtils:
|
||||
user_id: 用户id
|
||||
group_id: 群组id
|
||||
"""
|
||||
try:
|
||||
await bot.call_api("poke", qq=user_id)
|
||||
except Exception:
|
||||
platform = PlatformUtils.get_platform(bot)
|
||||
if platform == "qq":
|
||||
await bot.call_api("send_poke", user_id=user_id, group_id=group_id)
|
||||
else:
|
||||
try:
|
||||
if group_id:
|
||||
await bot.call_api("group_poke", user_id=user_id, group_id=group_id)
|
||||
else:
|
||||
await bot.call_api("friend_poke", user_id=user_id)
|
||||
await bot.call_api("poke", qq=user_id)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"戳一戳发送失败,可能是协议端不支持...",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user