mbcp/ts_bs4.py

260 lines
11 KiB
Python
Raw Permalink Normal View History

"""
Module docs
"""
import os
os.system("pip install PyGithub")
import json
from github.GitTree import GitTree
from github import Github, InputGitTreeElement
COMMAND_HEAD = "Friend Link Request"
FRIEND_LINKS_JSON = ".vitepress/data/friend-links.json"
FRIEND_LINKS_I18N_JSON = ".vitepress/sugarat/theme/data/i18n/friend-links-i18n.json"
i18n_text = {
"zh": {
"pre_check_finished" : "✅ 预检查通过,一切工作已就绪,等待仓库所有者审核",
"pre_check_failed" : "❌ 预检查未通过:{COMMENT}请修改issue",
"failed_not_a_https_url": "URL不是HTTPS链接请以https://开头",
"check_passed" : "✅ 审核通过,已添加友链,页面稍后就会构建好",
"if_add_i18n_data" : "🌐 是否添加国际化数据如需添加请修改issue添加`name_en`、`des_en`字段。",
"about_edit" : "📑 如需修改信息请直接编辑issue不要新建issue。",
"link_already_exists" : "该友链已存在或存在同名友链",
"delete_success" : "✅ 友链已删除",
"site_title" : "标题",
"site_description" : "描述",
"site_ping" : "延迟",
"site_url" : "链接",
"apply_info" : "申请信息",
"query_result" : "查询结果",
"site_name" : "站点名称",
"json_parse_error" : "JSON解析错误",
},
"en": {
"pre_check_finished" : "✅ Pre-check passed, ready to go, waiting for the repository owner to review",
"pre_check_failed" : "❌ Pre-check failed: {COMMENT}please modify the issue",
"failed_not_a_https_url": "URL is not a HTTPS link, please start with https://",
"check_passed" : "✅ Check passed, the friend link has been added, and the page will be built soon.",
"if_add_i18n_data" : "🌐 Do you want to add internationalization data? If you want, please modify the issue to add `name_en` and `des_en` "
"fields.",
"about_edit" : "📑 If you need to modify the information, please edit the issue directly instead of creating a new issue.",
"link_already_exists" : "The friend link already exists",
"delete_success" : "✅ The friend link has been deleted",
"site_title" : "Title",
"site_description" : "Description",
"site_ping" : "Ping",
"site_url" : "URL",
"apply_info" : "Apply Info",
"query_result" : "Query Result",
"site_name" : "Site Name",
"json_parse_error" : "JSON parse error",
}
}
def get_text(key: str) -> str:
return i18n_text[creator_lang].get(key, key)
# closed触发
def run_add():
"""审核通过 关闭时触发"""
closer = issue.closed_by
if closer.login != repo.owner.login and not issue.title.startswith(COMMAND_HEAD):
issue.create_comment(get_text("about_edit"))
# 修改友链信息
with open(FRIEND_LINKS_JSON, 'r') as f:
friend_link_data = json.load(f)
# 检查url相同并删除
for i, friend in enumerate(friend_link_data):
if friend["url"] == friend_link_url:
friend_link_data.pop(i)
break
friend_link_data.append(
{
"nickname": f'partnerLink.{friend_link_name}.nickname',
"des" : f'partnerLink.{friend_link_name}.des',
"avatar" : friend_link_icon,
"url" : friend_link_url,
}
)
# 修改友链国际化信息
with open(FRIEND_LINKS_I18N_JSON, 'r') as f:
friend_i18n_data = json.load(f)
friend_i18n_data['zh'][f'partnerLink.{friend_link_name}.nickname'] = friend_link_name
friend_i18n_data['zh'][f'partnerLink.{friend_link_name}.des'] = friend_link_des
friend_i18n_data['en'][f'partnerLink.{friend_link_name}.nickname'] = friend_link_name_en or f"{creator_name}'s site"
friend_i18n_data['en'][f'partnerLink.{friend_link_name}.des'] = friend_link_des_en or f"{creator_name}'s site"
tree = repo.create_git_tree(
base_tree=repo.get_git_tree("main"),
tree=[
InputGitTreeElement(
path=FRIEND_LINKS_JSON,
mode="100644",
type="blob",
content=json.dumps(friend_link_data, indent=4, ensure_ascii=False)
),
InputGitTreeElement(
path=FRIEND_LINKS_I18N_JSON,
mode="100644",
type="blob",
content=json.dumps(friend_i18n_data, indent=4, ensure_ascii=False)
)
]
)
# 提交修改
commit = repo.create_git_commit(
message=f":busts_in_silhouette: Add friend link: {friend_link_url}({creator_name})",
tree=tree,
parents=[repo.get_git_commit(ref.object.sha)]
)
ref.edit(commit.sha)
issue.create_comment(get_text("check_passed"))
# opened触发
def run_pre_check(typ: str):
try:
import re
os.system("pip install requests beautifulsoup4")
import requests
from bs4 import BeautifulSoup
def get_site_metadata(url) -> tuple[str, str, int]:
response = requests.get(url)
response.raise_for_status() # Ensure we notice bad responses
response.encoding = 'utf-8'
soup = BeautifulSoup(response.text, 'html.parser')
title = soup.title.string if soup.title else "No title found"
description = "No description found"
# Look for meta description tag
description_tag = soup.find('meta', attrs={
'name': 'description'
})
if description_tag and 'content' in description_tag.attrs:
description = description_tag['content']
return title, description, int(response.elapsed.microseconds / 1000)
# 检查链接是否合法
if not re.match(r"^https?://", friend_link_url) and not re.match(r"^https?://", friend_link_icon):
issue.create_comment(get_text("pre_check_failed").format(COMMENT=get_text("failed_not_a_https_url")))
return
else:
# 若是opened则第一次检查是否存在友链
if typ == "opened":
for friend in json.load(open(FRIEND_LINKS_JSON)):
if friend["url"] == friend_link_url or friend["nickname"] == friend_link_name:
issue.create_comment(get_text("pre_check_failed").format(COMMENT=get_text("link_already_exists")))
return
print("checking site metadata...")
title, description, ping_ms = get_site_metadata(friend_link_url)
site_meta = f"""\n
# {get_text("apply_info")}\n
**{get_text("site_url")}**: [{friend_link_url}]({friend_link_url})\n
**{get_text("site_name")}**: {friend_link_name} / {friend_link_name_en or "No English name"}\n
**{get_text("site_description")}**: {friend_link_des} / {friend_link_des_en or "No English description"}\n
# {get_text("query_result")}\n
**{get_text("site_title")}**: {title}\n
**{get_text("site_description")}**: {description}\n
**{get_text("site_ping")}**: {ping_ms:.2f}ms\n"""
issue.create_comment(get_text("pre_check_finished") + site_meta + get_text("if_add_i18n_data"))
except Exception as e:
issue.create_comment(f"{get_text('pre_check_failed').format(COMMENT=str(e))}")
def run_delete():
"""删除友链"""
with open(FRIEND_LINKS_JSON, 'r') as f:
friend_link_data = json.load(f)
for i, friend in enumerate(friend_link_data):
if friend["url"] == friend_link_url:
friend_link_data.pop(i)
break
with open(FRIEND_LINKS_I18N_JSON, 'r') as f:
friend_i18n_data = json.load(f)
for language in friend_i18n_data:
for key in list(friend_i18n_data[language]):
if key.startswith(f'partnerLink.{creator_name}.'):
friend_i18n_data[language].pop(key)
tree = repo.create_git_tree(
base_tree=repo.get_git_tree("main"),
tree=[
InputGitTreeElement(
path=FRIEND_LINKS_JSON,
mode="100644",
type="blob",
content=json.dumps(friend_link_data, indent=4, ensure_ascii=False)
),
InputGitTreeElement(
path=FRIEND_LINKS_I18N_JSON,
mode="100644",
type="blob",
content=json.dumps(friend_i18n_data, indent=4, ensure_ascii=False)
)
]
)
# 提交修改
commit = repo.create_git_commit(
message=f":busts_in_silhouette: Delete friend link: {friend_link_url}({creator_name})",
tree=tree,
parents=[repo.get_git_commit(ref.object.sha)]
)
ref.edit(commit.sha)
print("✅ 友链已删除")
if __name__ == "__main__":
g = Github(os.getenv('TOKEN'))
repo = g.get_repo(os.getenv('REPOSITORY'))
issue_number = int(os.getenv('ISSUE_NUMBER'))
act_type = os.getenv('ACT_TYPE') # opened, edited, closed, deleted 对应事件类型
creator_lang = "zh"
"""
opened: 添加友链
edited: 修改友链
closed: 审核通过
deleted: 删除友链
"""
issue = repo.get_issue(number=issue_number)
issue_title = issue.title
try:
issue_body = json.loads(issue.body)
friend_link_name = issue_body["name"]
friend_link_name_en = issue_body.get("name_en", "")
friend_link_des = issue_body["des"]
friend_link_des_en = issue_body.get("des_en", "")
friend_link_url = issue_body["url"]
friend_link_icon = issue_body["icon"]
creator_lang = issue_body.get("lang", "zh")
creator_name = issue.user.login
ref = repo.get_git_ref("heads/main")
if creator_lang not in i18n_text:
lang = "zh"
# 开始检查
if issue_title.startswith(COMMAND_HEAD):
if act_type in ["opened", "edited"]:
run_pre_check(act_type)
elif act_type == "closed":
run_add()
elif act_type == "deleted":
run_delete()
else:
print("nothing to do")
else:
print("Not a friend link request issue, passed.")
except Exception as e:
print(f"Error: {str(e)}")
if act_type not in ["closed"]:
issue.create_comment(get_text("pre_check_failed").format(COMMENT=str(e)))