2024-09-17 14:37:45 +08:00
|
|
|
|
"""
|
|
|
|
|
Module docs
|
|
|
|
|
"""
|
|
|
|
|
import requests # type: ignore
|
|
|
|
|
import zipfile
|
|
|
|
|
|
|
|
|
|
from github import Github, InputGitTreeElement, GitTree
|
|
|
|
|
from github.Issue import Issue
|
|
|
|
|
from github.Repository import Repository
|
|
|
|
|
import json
|
|
|
|
|
import yaml
|
|
|
|
|
|
2024-09-17 16:14:08 +08:00
|
|
|
|
from liteyuki_flow.const import OPENED, EDITED, CLOSED, REOPENED, RESOURCE_JSON, bot_id, edit_tip
|
2024-09-17 14:37:45 +08:00
|
|
|
|
from liteyuki_flow.markdown_parser import MarkdownParser
|
|
|
|
|
from liteyuki_flow.typ import err, nil
|
|
|
|
|
|
2024-09-17 15:45:43 +08:00
|
|
|
|
user_agent = "liteyuki-flow"
|
2024-09-17 14:55:05 +08:00
|
|
|
|
|
|
|
|
|
headers = {
|
2024-09-17 14:57:27 +08:00
|
|
|
|
"User-Agent": user_agent
|
2024-09-17 14:55:05 +08:00
|
|
|
|
}
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
2024-09-17 14:57:27 +08:00
|
|
|
|
|
2024-09-17 16:14:08 +08:00
|
|
|
|
def push_check_result(issue: Issue, result: str):
|
|
|
|
|
cid = None
|
|
|
|
|
for cm in issue.get_comments():
|
|
|
|
|
if cm.body.startswith("检查结果") and cm.user.login == bot_id:
|
|
|
|
|
cid = cm.id
|
|
|
|
|
break
|
|
|
|
|
if cid is not None:
|
|
|
|
|
issue.get_comment(cid).edit("检查结果: " + result)
|
|
|
|
|
else:
|
|
|
|
|
issue.create_comment("检查结果: " + result)
|
|
|
|
|
|
2024-09-18 01:22:08 +08:00
|
|
|
|
|
2024-09-18 01:04:37 +08:00
|
|
|
|
def push_publish_result(issue: Issue, result: str):
|
|
|
|
|
cid = None
|
|
|
|
|
for cm in issue.get_comments():
|
|
|
|
|
if cm.body.startswith("发布结果") and cm.user.login == bot_id:
|
|
|
|
|
cid = cm.id
|
|
|
|
|
break
|
|
|
|
|
if cid is not None:
|
|
|
|
|
issue.get_comment(cid).edit("发布结果: " + result)
|
|
|
|
|
else:
|
|
|
|
|
issue.create_comment("发布结果: " + result)
|
|
|
|
|
|
2024-09-17 16:14:08 +08:00
|
|
|
|
|
2024-09-17 14:37:45 +08:00
|
|
|
|
# opened: 创建新的资源包,预审核
|
|
|
|
|
# edited: 编辑资源包信息,需重新审核
|
|
|
|
|
# closed: 审核通过,修改json并提交
|
|
|
|
|
# reopened: 重新打开,无操作
|
2024-09-17 14:59:49 +08:00
|
|
|
|
def on_first_open(github: Github, issue: Issue, repo: Repository):
|
2024-09-17 15:33:32 +08:00
|
|
|
|
issue.create_comment("已收到资源包发布请求,我会马上开始预检. " + edit_tip)
|
2024-09-17 16:14:08 +08:00
|
|
|
|
push_check_result(issue, "请等待")
|
2024-09-17 15:26:21 +08:00
|
|
|
|
issue.add_to_labels("Resource")
|
2024-09-17 14:59:49 +08:00
|
|
|
|
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
|
|
|
|
# opened | edited
|
|
|
|
|
def pre_check(github: Github, issue: Issue, repo: Repository) -> err:
|
|
|
|
|
parser = MarkdownParser(issue.body)
|
|
|
|
|
parser.parse_front_matters()
|
|
|
|
|
name = parser.front_matters.get("name")
|
|
|
|
|
desc = parser.front_matters.get("desc")
|
2024-09-17 14:48:48 +08:00
|
|
|
|
link = parser.front_matters.get("link")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
homepage = parser.front_matters.get("homepage") # optional
|
|
|
|
|
author = parser.front_matters.get("author")
|
2024-09-17 16:14:08 +08:00
|
|
|
|
|
2024-09-17 14:48:48 +08:00
|
|
|
|
if not all((name, desc, link, author)):
|
2024-09-17 16:14:08 +08:00
|
|
|
|
push_check_result(issue, "❌ name, desc, link, homepage 及 author 为必填字段.")
|
2024-09-17 14:52:26 +08:00
|
|
|
|
return ValueError("name, desc, link, homepage 及 author 为必填字段.")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
|
|
|
|
# 下载并解析资源包
|
2024-09-17 14:55:05 +08:00
|
|
|
|
r = requests.get(link, headers=headers)
|
2024-09-17 14:37:45 +08:00
|
|
|
|
if r.status_code != 200:
|
2024-09-17 16:14:08 +08:00
|
|
|
|
push_check_result(issue, "❌ 下载失败.")
|
2024-09-17 14:52:26 +08:00
|
|
|
|
return ValueError("下载失败.")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
try:
|
2024-09-17 15:50:10 +08:00
|
|
|
|
with open(f"{name}.zip", "wb") as f:
|
2024-09-17 14:52:26 +08:00
|
|
|
|
f.write(r.content)
|
|
|
|
|
# 解压
|
2024-09-17 15:50:10 +08:00
|
|
|
|
with zipfile.ZipFile(f"{name}.zip", "r") as z:
|
|
|
|
|
z.extractall(f"{name}")
|
2024-09-17 14:52:26 +08:00
|
|
|
|
# 检测包内metadata.yml文件
|
2024-09-17 15:50:10 +08:00
|
|
|
|
data = yaml.load(open(f"{name}/metadata.yml"), Loader=yaml.SafeLoader)
|
2024-09-17 15:48:02 +08:00
|
|
|
|
except Exception as e:
|
2024-09-17 16:14:08 +08:00
|
|
|
|
push_check_result(issue, "❌ 解析资源包失败,可能是格式问题或metadata.yml不存在: " + str(e))
|
2024-09-17 15:48:02 +08:00
|
|
|
|
return e
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
|
|
|
|
# 检测必要字段 name,description,version
|
|
|
|
|
if not all((data.get("name"), data.get("description"), data.get("version"))):
|
2024-09-17 16:14:08 +08:00
|
|
|
|
push_check_result(issue, "❌ 元数据中缺少必要字段 name, description 或 version.")
|
2024-09-17 14:52:26 +08:00
|
|
|
|
return ValueError("元数据中缺少必要字段 name, description 或 version.")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
|
|
|
|
# 不检测重复资源包,因为资源包可能有多个版本
|
|
|
|
|
# 检测通过,编辑原issue
|
|
|
|
|
metadata_markdown = f"**名称**: {data.get('name')}\n**描述**: {data.get('description')}\n**版本**: {data.get('version')}\n"
|
|
|
|
|
for k, v in data.items():
|
|
|
|
|
if k not in ("name", "description", "version"):
|
|
|
|
|
metadata_markdown += f"**{k}**: {v}\n"
|
|
|
|
|
|
2024-09-17 14:48:48 +08:00
|
|
|
|
new_issue_body = f"---\nname: {name}\ndesc: {desc}\nlink: {link}\nhomepage: {homepage}\nauthor: {author}\n---\n"
|
2024-09-17 16:19:47 +08:00
|
|
|
|
|
2024-09-17 16:21:45 +08:00
|
|
|
|
publish_info = f"## 发布信息\n"
|
2024-09-17 16:19:47 +08:00
|
|
|
|
publish_info += f"**名称**: {name}\n"
|
|
|
|
|
publish_info += f"**描述**: {desc}\n"
|
|
|
|
|
publish_info += f"**作者**: {author}\n"
|
|
|
|
|
publish_info += f"**主页**: {homepage}\n"
|
|
|
|
|
publish_info += f"**下载**: {link}\n"
|
2024-09-17 14:37:45 +08:00
|
|
|
|
# 遍历其他字段
|
|
|
|
|
for k, v in data.items():
|
|
|
|
|
if k not in ("name", "description", "version"):
|
|
|
|
|
new_issue_body += f"**{k}**: {v}\n"
|
|
|
|
|
|
2024-09-17 16:21:18 +08:00
|
|
|
|
issue.edit(title=f"Resource: {name}")
|
2024-09-17 15:26:21 +08:00
|
|
|
|
issue.add_to_labels("pre-checked")
|
2024-09-17 16:19:47 +08:00
|
|
|
|
push_check_result(issue, f"✅ 预检查通过,等待管理员人工审核\n{publish_info}\n## 元数据\n{metadata_markdown}")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
return nil
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# closed
|
2024-09-18 01:04:37 +08:00
|
|
|
|
def add_resource(github: Github, issue: Issue, repo: Repository) -> err:
|
2024-09-18 01:22:08 +08:00
|
|
|
|
# 检测关闭时是否有管理员发布的通过评论
|
2024-09-18 01:04:37 +08:00
|
|
|
|
try:
|
2024-09-18 01:22:08 +08:00
|
|
|
|
# closed_by = issue.closed_by
|
|
|
|
|
# if closed_by is None:
|
|
|
|
|
# print(issue.closed_by)
|
|
|
|
|
# push_publish_result(issue, "❌ 无法获取关闭者信息。")
|
|
|
|
|
# return ValueError("无法获取关闭者信息。")
|
|
|
|
|
# if not any([True for u in repo.get_collaborators() if u.login == closed_by.login]):
|
|
|
|
|
# push_publish_result(issue, "❌ 你不是仓库管理员,无法发布资源包。")
|
|
|
|
|
# return ValueError("你不是仓库管理员,无法发布资源包。")
|
|
|
|
|
if "pre-checked" not in issue.labels:
|
|
|
|
|
issue.edit(state="open")
|
|
|
|
|
push_publish_result(issue, "❌ 请先通过预检查。")
|
|
|
|
|
return ValueError("请先进行预检查。")
|
|
|
|
|
|
|
|
|
|
# 检测评论
|
|
|
|
|
for cm in issue.get_comments():
|
|
|
|
|
if cm.body.startswith(("通过", "pass",)):
|
|
|
|
|
# 检测用户是否是管理员
|
|
|
|
|
if cm.user.login not in [u.login for u in repo.get_collaborators()]:
|
|
|
|
|
push_publish_result(issue, "❌ 你不是仓库管理员,无法发布资源包。")
|
|
|
|
|
return ValueError("你不是仓库管理员,无法发布资源包。")
|
|
|
|
|
break
|
|
|
|
|
else:
|
|
|
|
|
push_publish_result(issue, "❌ 管理员未审核。")
|
|
|
|
|
return ValueError("管理员未审核。")
|
2024-09-18 01:04:37 +08:00
|
|
|
|
|
|
|
|
|
parser = MarkdownParser(issue.body)
|
|
|
|
|
parser.parse_front_matters()
|
|
|
|
|
name = parser.front_matters.get("name")
|
|
|
|
|
desc = parser.front_matters.get("desc")
|
|
|
|
|
link = parser.front_matters.get("link")
|
|
|
|
|
homepage = parser.front_matters.get("homepage") # optional
|
|
|
|
|
author = parser.front_matters.get("author")
|
|
|
|
|
|
|
|
|
|
# 编辑仓库内的json文件
|
|
|
|
|
resources = json.load(open(RESOURCE_JSON))
|
|
|
|
|
resources.append({
|
|
|
|
|
"name" : name,
|
|
|
|
|
"description": desc,
|
|
|
|
|
"link" : link,
|
|
|
|
|
"homepage" : homepage,
|
|
|
|
|
"author" : author
|
|
|
|
|
})
|
|
|
|
|
ref = repo.get_git_ref("heads/main")
|
|
|
|
|
tree = repo.create_git_tree(
|
|
|
|
|
base_tree=repo.get_git_commit(ref.object.sha).tree,
|
|
|
|
|
tree=[
|
|
|
|
|
InputGitTreeElement(
|
|
|
|
|
path=RESOURCE_JSON,
|
|
|
|
|
mode="100644",
|
|
|
|
|
type="blob",
|
|
|
|
|
content=json.dumps(resources, indent=4, ensure_ascii=False)
|
|
|
|
|
)
|
|
|
|
|
]
|
|
|
|
|
)
|
|
|
|
|
commit = repo.create_git_commit(
|
|
|
|
|
message=f":package: 发布资源: {name}",
|
|
|
|
|
tree=tree,
|
|
|
|
|
parents=[repo.get_git_commit(ref.object.sha)]
|
|
|
|
|
)
|
|
|
|
|
ref.edit(commit.sha)
|
|
|
|
|
if "pre-checked" in issue.labels:
|
|
|
|
|
issue.remove_from_labels("pre-checked")
|
|
|
|
|
push_publish_result(issue, f"✅ 资源包 {name} 已发布!商店页面稍后就会更新。")
|
2024-09-18 01:22:08 +08:00
|
|
|
|
return nil
|
2024-09-18 01:04:37 +08:00
|
|
|
|
except Exception as e:
|
|
|
|
|
push_publish_result(issue, f"❌ 发布失败: {str(e)}")
|
|
|
|
|
return e
|
2024-09-17 14:37:45 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def handle_resource(github: Github, issue: Issue, repo: Repository, act_type: str):
|
|
|
|
|
if act_type in (OPENED, EDITED):
|
2024-09-17 15:03:48 +08:00
|
|
|
|
if act_type == OPENED:
|
|
|
|
|
on_first_open(github, issue, repo)
|
2024-09-17 14:37:45 +08:00
|
|
|
|
pre_check(github, issue, repo)
|
|
|
|
|
elif act_type == CLOSED:
|
2024-09-18 01:04:37 +08:00
|
|
|
|
e = add_resource(github, issue, repo)
|
|
|
|
|
if e != nil:
|
|
|
|
|
print(f"Error: {e}")
|
2024-09-17 14:37:45 +08:00
|
|
|
|
else:
|
|
|
|
|
print("No operation found for the issue: ", act_type)
|