点击在线阅读,体验更好链接现代JavaScript高级小册链接深入浅出Dart链接现代TypeScript高级小册链接linwu的算法笔记链接

前言

上星期四,我像往常一样起床上班,地铁上收到了微信消息

这时候就感觉到不对劲了,到了公司我登录了自己的github,发现被封了

毫无征兆,我的gmail也没有收到github邮箱。

因为这个github账号我一直用来存放我的网站资料以及blog,所以很多issue都在里面,另外还有部分图床和博客示例,这个被封禁,所有资料都迁移不了

缘由

网上查了一圈,发现github被封,很少能申诉成功的,所以我给官方发了一封邮件,想看看是什么原因导致的,避免后续再出现类似的问题

给官方回了一个邮件后,过了半个小时我收到了回复

原来问题是这样,因为我之前找某宝开通了copilot学生认证,导致被github查到封禁了,至于之所以找某宝,是因为我没有visa卡支付起来麻烦,又想体验copilot,没办法才出此下策,所以copilot学生认证还是不要绑定自己的github账号吧

迁移

封都已经封了,这时候就得统计损失了,尽量挽回

所幸我很多仓库本地都有备份,重新注册了一个github账号上传就行,为此我还专门写了些脚本

备份star

很多同学都会把star当做书签收集

这时候可以通过访问github api进行备份

https://api.github.com/users/[username]/starred

批量备份issue到本地

const fs = require('fs');

const axios = require('axios');

const sanitize = require('sanitize-filename');

const { githubRepoOwner, githubRepoName, githubAccessToken } = require('./config');

async function getIssues() {

let allIssues = [];

let page = 1;

let perPage = 300; // 每页返回100个issue,根据实际情况可以适当调整

try {

while (true) {

const response = await axios.get(`https://api.github.com/repos/${githubRepoOwner}/${githubRepoName}/issues`, {

params: {

page,

per_page: perPage

},

headers: {

Authorization: `Bearer ${githubAccessToken}`

}

});

const issues = response.data;

if (issues.length === 0) {

break; // 退出循环,表示已获取所有issue数据

}

allIssues = allIssues.concat(issues);

page++;

}

return allIssues;

} catch (error) {

throw new Error(`Error fetching issues: ${error.message}`);

}

}

async function saveIssueAsMarkdown(issue, directory) {

const markdownContent = issue.body;

const fileName = `${directory}/${sanitize(issue.title)}.md`;

fs.writeFileSync(fileName, markdownContent);

}

async function main() {

try {

const issues = await getIssues();

// Create a directory for each label

issues.forEach(issue => {

issue.labels.forEach(label => {

const directory = `./docs/${sanitize(label.name)}`;

if (!fs.existsSync(directory)) {

fs.mkdirSync(directory, { recursive: true });

}

saveIssueAsMarkdown(issue, directory);

});

});

console.log('Markdown files saved successfully!');

} catch (error) {

console.error(error.message);

}

}

main();

批量更新issue标题

const { Octokit } = require('@octokit/rest');

// GitHub personal access token

const token = '';

// GitHub repository information

const owner = 'LQ-vic';

const repo = 'code-interview';

const labelToFilter = 'image'; // 请替换为你想筛选的标签

const octokit = new Octokit({ auth: token });

async function updateIssueTitlesByLabel() {

try {

// 根据标签获取仓库的所有 issues

const issues = await octokit.issues.listForRepo({

owner,

repo,

state: 'open', // 只获取打开的 issues

labels: labelToFilter,

per_page: 100, // 每页获取 100 个 issues,你可以根据需要调整

});

for (const issue of issues.data) {

if (issue.title.startsWith('xx:xx:')) {

const newTitle = issue.title.replace('xx:xx:', 'xx:');

await octokit.issues.update({

owner,

repo,

issue_number: issue.number,

title: newTitle,

});

console.log(`Updated issue #${issue.number} title to: ${newTitle}`);

}

}

} catch (error) {

console.error('Error updating issue titles:', error.message);

}

}

updateIssueTitlesByLabel();

批量上传issue

const fs = require('fs');

const path = require('path');

const { Octokit } = require('@octokit/rest');

// GitHub personal access token

const token = '';

// GitHub repository information

const owner = 'LQ-vic';

const repo = 'code-interview';

// Directory path of the docs folder

const docsDirectory = './docs/CSS3';

// Labels to be added to each issue

const labelColors = [

{ name: 'CSS3', color: '#FBCA033' }

];

const excludedDirectories = ['.vuepress', '.git', 'node_modules'];

// File path to store the uploaded files record

const recordFilePath = './uploaded_files.txt';

// Initialize Octokit

const octokit = new Octokit({ auth: token });

// Function to read all Markdown files in the given directory

async function readMarkdownFiles(directory) {

const files = fs.readdirSync(directory);

for (const file of files) {

// console.log('file',file)

const filePath = path.join(directory, file);

const stat = fs.statSync(filePath);

if (stat.isDirectory() && !excludedDirectories.includes(file)) {

await readMarkdownFiles(filePath); // Recursively read files in non-excluded subdirectories

} else if (stat.isFile() && path.extname(file) === '.md') {

const content = fs.readFileSync(filePath, 'utf8');

const title = extractTitleFromContent(content);

if (!isFileUploaded(title)) {

await createIssue(title, content, labelColors);

addUploadedFile(title);

}

}

}

}

// Function to create GitHub issue

async function createIssue(title, body, labels) {

try {

const response = await octokit.issues.create({

owner: owner,

repo: repo,

title: `${title}`,

body: body,

labels: labels

});

console.log(`Successfully created issue: ${title}`);

} catch (error) {

console.log(`Failed to create issue: 面试官:${title}`);

console.log(`Error: ${error.message}`);

}

}

// Function to extract title from the content (first heading)

function extractTitleFromContent(content) {

const match = content.match(/^#\s*(.+)/);

if (match) {

return match[1];

}

return '';

}

// Function to check if a file has been uploaded

function isFileUploaded(filename) {

if (fs.existsSync(recordFilePath)) {

const uploadedFiles = fs.readFileSync(recordFilePath, 'utf8').split('\n');

return uploadedFiles.includes(filename);

}

return false;

}

// Function to add uploaded file to the record

function addUploadedFile(filename) {

fs.appendFileSync(recordFilePath, filename + '\n', 'utf8');

}

// Read all Markdown files in the docs directory (excluding specified directories) and create issues

readMarkdownFiles(docsDirectory)

.then(() => {

console.log('All issues created.');

})

.catch((error) => {

console.log('Error:', error);

});

批量导出issue目录

const axios = require('axios');

const fs = require('fs');

async function getGitHubIssues(owner, repo, labels, token) {

const baseUrl = `https://api.github.com/repos/${owner}/${repo}/issues`;

const headers = token ? { Authorization: `token ${token}` } : {};

const params = { state: 'all', per_page: 100 };

const issuesByLabel = {};

let nextPage = true;

while (nextPage) {

try {

const response = await axios.get(baseUrl, { headers, params });

const data = response.data;

if (!data.length) break;

data.forEach((issue) => {

if (!issue.pull_request) {

issue.labels.forEach((label) => {

if (labels.includes(label.name)) {

if (!issuesByLabel[label.name]) {

issuesByLabel[label.name] = [];

}

issuesByLabel[label.name].push(issue);

}

});

}

});

if (response.headers.link) {

const links = response.headers.link.split(', ');

nextPage = links.some((link) => link.endsWith('rel="next"'));

if (nextPage) {

const nextPageNum = parseInt(links[links.length - 1].match(/&page=(\d+)/)[1], 10);

params.page = nextPageNum;

}

} else {

nextPage = false;

}

} catch (error) {

throw new Error(`Failed to fetch issues. Error: ${error.message}`);

}

}

return issuesByLabel;

}

// Output to Markdown file

function writeIssuesToMarkdown(issues, outputPath) {

let content = '';

Object.entries(issues).forEach(([label, issuesList]) => {

content += `## ${label}\n\n`;

issuesList.forEach((issue) => {

content += `- [${issue.title}](${issue.html_url})\n`;

});

content += '\n';

});

fs.writeFile(outputPath, content, (err) => {

if (err) {

console.error('Error writing the file:', err);

} else {

console.log('Markdown file generated successfully!');

}

});

}

// 使用示例

const owner = 'LQ-vic';

const repo = 'code-interview';

const labels = ['JavaScript', 'TypeScript','vue','vue3','react','HTTP','webpack','nodejs','Linux','git','CSS','CSS3','组件库','小程序'];

const token = '';

const outputPath = 'dirname.md';

(async () => {

try {

const issues = await getGitHubIssues(owner, repo, labels, token);

writeIssuesToMarkdown(issues, outputPath);

} catch (error) {

console.error(error.message);

}

})();

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: