Skip to content

Commit b1d34de

Browse files
committed
add: create issue script
1 parent 28440de commit b1d34de

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed

add_issue.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const axios = require('axios');
2+
3+
// GitHub API 配置
4+
const API_URL = "https://api.github.com";
5+
const REPO_OWNER = "SwiftGGTeam";
6+
const REPO_NAME = "the-swift-programming-language-in-chinese";
7+
const BRANCH = "swift-6-beta-translation";
8+
9+
// TODO: 请在运行脚本之前设置您的个人访问令牌
10+
const TOKEN = process.env.GITHUB_TOKEN;
11+
12+
// 设置请求头
13+
const headers = {
14+
"Authorization": `token ${TOKEN}`,
15+
"Accept": "application/vnd.github.v3+json"
16+
};
17+
18+
async function getExistingIssues() {
19+
const issues = new Set();
20+
let page = 1;
21+
while (true) {
22+
const url = `${API_URL}/repos/${REPO_OWNER}/${REPO_NAME}/issues?state=all&per_page=100&page=${page}`;
23+
const response = await axios.get(url, { headers });
24+
if (response.data.length === 0) break;
25+
response.data.forEach(issue => issues.add(issue.title));
26+
page++;
27+
}
28+
return issues;
29+
}
30+
31+
async function createIssue(title, body, labels, retries = 3) {
32+
for (let i = 0; i < retries; i++) {
33+
try {
34+
const url = `${API_URL}/repos/${REPO_OWNER}/${REPO_NAME}/issues`;
35+
const data = { title, body, labels };
36+
const response = await axios.post(url, data, { headers });
37+
38+
if (response.status === 201) {
39+
console.log(`Issue created successfully: ${title}`);
40+
return response.data;
41+
}
42+
} catch (error) {
43+
console.error(`Error creating issue (attempt ${i + 1}):`, error.message);
44+
if (i === retries - 1) throw error;
45+
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); // 等待时间递增
46+
}
47+
}
48+
return null;
49+
}
50+
51+
async function getFilesInDirectory(path) {
52+
try {
53+
const url = `${API_URL}/repos/${REPO_OWNER}/${REPO_NAME}/contents/${path}?ref=${BRANCH}`;
54+
const response = await axios.get(url, { headers });
55+
if (response.status === 200) {
56+
return response.data.filter(item => item.type === "file" && item.name.endsWith('.md'));
57+
} else {
58+
console.log(`Failed to get directory contents: ${response.status}`);
59+
return [];
60+
}
61+
} catch (error) {
62+
console.error("Error getting directory contents:", error.message);
63+
return [];
64+
}
65+
}
66+
67+
function formatIssueTitle(filePath) {
68+
const parts = filePath.split('/');
69+
const fileName = parts.pop().toLowerCase().replace('.md', '');
70+
const folderName = parts[parts.length - 1];
71+
return `${folderName} / ${fileName}.md`;
72+
}
73+
74+
function formatIssueBody(filePath) {
75+
const fileUrl = `https://github.com/${REPO_OWNER}/${REPO_NAME}/blob/${BRANCH}/${filePath}`;
76+
return `翻译文件:${fileUrl}\n请在认领任务前查看 Markdown 文件内容,并了解对应的 Swift 原文档链接和翻译预估时长`;
77+
}
78+
79+
async function processDirectory(path, existingIssues) {
80+
const files = await getFilesInDirectory(path);
81+
for (const file of files) {
82+
const issueTitle = formatIssueTitle(file.path);
83+
if (!existingIssues.has(issueTitle)) {
84+
const issueBody = formatIssueBody(file.path);
85+
await createIssue(issueTitle, issueBody, ["Swift 6 beta translation"]);
86+
} else {
87+
console.log(`Issue already exists: ${issueTitle}`);
88+
}
89+
}
90+
}
91+
92+
async function main() {
93+
const existingIssues = await getExistingIssues();
94+
console.log(`Found ${existingIssues.size} existing issues.`);
95+
96+
const directories = [
97+
"swift-6-beta.docc/GuidedTour",
98+
"swift-6-beta.docc/LanguageGuide",
99+
"swift-6-beta.docc/ReferenceManual"
100+
];
101+
102+
for (const dir of directories) {
103+
await processDirectory(dir, existingIssues);
104+
}
105+
}
106+
107+
main().catch(console.error);

0 commit comments

Comments
 (0)