mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
✨ feat(aliyun): 添加阿里云相关配置和文件操作功能 (#1985)
* ✨ feat(aliyun): 添加阿里云相关配置和文件操作功能 * 🐛 fix bug * 🎨 更新requirements * ⬆️ Update poetry.lock * ✨ feat(aliyun): 添加阿里云获取commit方法 * 更新env pyproject --------- Co-authored-by: HibiKier <775757368@qq.com> Co-authored-by: HibiKier <45528451+HibiKier@users.noreply.github.com>
This commit is contained in:
parent
3cf7c1d237
commit
30fe5a5393
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"
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user