您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Sync your GitHub fork repo within one click
// ==UserScript== // @name GitHub one-click sync fork // @namespace https://blog.maple3142.net/ // @version 0.5 // @description Sync your GitHub fork repo within one click // @author maple3142 // @match https://github.com/* // @require https://unpkg.com/[email protected]/xfetch.min.js // @grant GM_setValue // @grant GM_getValue // @compatible firefox >=52 // @compatible chrome >=55 // ==/UserScript== ;(function () { 'use strict' const $ = s => document.querySelector(s) const $$ = s => [...document.querySelectorAll(s)] const gh = xf.extend({ baseURI: 'https://api.github.com/' }) const oauthurl = // eslint-disable-next-line max-len 'https://github.com/login/oauth/authorize?client_id=5c0954a832a0f2bb68f2&scope=repo&redirect_uri=https://github.com/' // eslint-disable-next-line max-len const confirmmsg = 'Are you sure?\nAll the changes you have made will be DELETED!\nIT CANNOT BE RECOVERED!' const search = new URL(location.href).searchParams if (search.has('code')) { const code = search.get('code') xf.post('https://github.com/login/oauth/access_token', { json: { client_id: '5c0954a832a0f2bb68f2', client_secret: '799a5a49ef0ebde906f8bedc2e3327a99cd0d92a', code } }).text(str => { const search = new URLSearchParams(str) GM_setValue('token', search.get('access_token')) window.close() }) } const addBtn = () => { const currentUser = $('.user-profile-link>strong').textContent const currentRepoOwner = location.pathname.split('/')[1] const isUserMatch = currentUser === currentRepoOwner const forkText = $('.flex-auto>.text-small') const isFork = !!forkText && forkText.textContent.includes('forked from') if (!isUserMatch || !isFork) return $$('#one-click-sync-fork').forEach(btn => btn.remove()) const repo = location.pathname.split('/').slice(1, 3).join('/') const upstream = forkText.querySelector('a').textContent.trim() const fnav = $('.file-navigation') const branch = $('link[href$=atom]').href.split('/').pop().split('.')[0] const el = document.createElement('a') el.classList.add('btn') el.classList.add('btn-primary') el.textContent = `Update fork from ${upstream}/${branch}` el.onclick = async () => { const token = GM_getValue('token') if (!token) { window.open(oauthurl, '_target') return } if (!confirm(confirmmsg)) return const sha = await gh .get(`/repos/${upstream}/branches/${branch}`) .json(b => b.commit.sha) await gh .patch(`/repos/${repo}/git/refs/heads/${branch}`, { headers: { Authorization: `token ${token}` }, json: { sha, force: true } }) .json() location.reload() } const wrapper = document.createElement('div') wrapper.style.marginLeft = '6px' wrapper.id = 'one-click-sync-fork' wrapper.appendChild(el) const branchbtn = $('#branch-select-menu') branchbtn.insertAdjacentElement('afterend', wrapper) } addBtn() new MutationObserver(addBtn).observe(document.body, { childList: true }) })()