分享一次我github被封的经历以及迁移指南

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

前言

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

image.png

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

image.png

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

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

缘由

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

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

image.png

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

image.png

迁移

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

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

备份star

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

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

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

image.png

批量备份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 tokenconst token = '';// GitHub repository informationconst 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 tokenconst token = '';// GitHub repository informationconst owner = 'LQ-vic';const repo = 'code-interview';// Directory path of the docs folderconst docsDirectory = './docs/CSS3';// Labels to be added to each issueconst labelColors = [  { name: 'CSS3', color: '#FBCA033' }];const excludedDirectories = ['.vuepress', '.git', 'node_modules'];// File path to store the uploaded files recordconst recordFilePath = './uploaded_files.txt';// Initialize Octokitconst octokit = new Octokit({ auth: token });// Function to read all Markdown files in the given directoryasync 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 issueasync 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 uploadedfunction 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 recordfunction addUploadedFile(filename) {  fs.appendFileSync(recordFilePath, filename + '/n', 'utf8');}// Read all Markdown files in the docs directory (excluding specified directories) and create issuesreadMarkdownFiles(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 filefunction 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);  }})();

也许您对下面的内容还感兴趣: