您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Show download count for releases on Github
当前为
// ==UserScript== // @name GitHub Release Downloads // @namespace https://github.com/Hibi-10000/GitHubReleaseDownloads // @version 1.0.1 // @author Hibi_10000 // @license MIT // @description Show download count for releases on Github // @source https://github.com/Hibi-10000/GitHubReleaseDownloads // @icon https://github.githubassets.com/favicons/favicon-dark.png // @grant GM_getValue // @grant GM_setValue // @match https://github.com/* // ==/UserScript== 'use strict'; const observer = new MutationObserver(observerFunc) const initObserver = () => { const body = document.querySelector("body"); if (body != null) { observer.observe(body, {childList: true, subtree: true}); } else { window.setTimeout(initObserver, 1000); } } function observerFunc() { if (/https?:\/\/github.com\/.+?\/.+?\/releases.*/.test(document.URL)) { run(); } } const getRepo = () => { //return document.querySelector('meta[name="octolytics-dimension-repository_nwo"]').content; return document.URL.match(/(?<=^https?:\/\/github.com\/).+?\/.+?(?=\/releases)/)[0]; } const getReleaseTag = () => { const ifEmpty = document.URL.replace(/^https?:\/\/github.com\/.+?\/.+?\/releases/, ""); return ifEmpty === "" || ifEmpty === "/" || ifEmpty.startsWith("?") ? null : ifEmpty.match(/(?<=^\/tag\/)[^/?#]+/)[0]; } const getHeader = () => { const PAT = GM_getValue("GITHUB_PAT"); if (PAT == undefined || PAT == "") { return null; } else { const userAgent = navigator.userAgent; return { headers: { 'User-Agent': userAgent, 'Authorization': `Bearer ${PAT}`, } }; } } const getLinks = () => { /** @type {NodeListOf<HTMLAnchorElement>} */ const links = document.querySelectorAll(`a[href^="/${getRepo()}/releases/download/"]`); return links; } let isRunning = false; function run() { for (const link of getLinks()) { const assetDataElem = link.parentNode.parentNode.children[1]; if (assetDataElem == null) continue; //grdcounterがない場所が存在するか確認する if (assetDataElem.querySelector('#grdcounter') == null && !isRunning) { isRunning = true; const tag = getReleaseTag(); const response = fetch(`https://api.github.com/repos/${getRepo()}/releases${tag !== null ? `/tags/${tag}` : ""}`, getHeader()); response.then(res => { if (res.ok) { res.json().then(json => { isRunning = false; setDLCount(json, tag !== null); }); } }).catch(error => { console.error('Error:', error); });; } } } function setDLCount(json, /** @type {boolean} */ isTag) { for (const link of getLinks()) { const name = link.href.match(/(?<=\/)[^/?#]+$/)[0]; const assets = tag => { return createElement(tag.assets, name, link); } if (isTag) { assets(json); } else { const tagName = link.href.match(/(?<=\/download\/)[^/?#]+(?=\/[^/?#]+$)/)[0]; for (const tag of json) { if (tag.tag_name === tagName && assets(tag)) break; } } } } function createElement(assets, name, /** @type {Element} */ link) { for (const asset of assets) { if (asset.name === name) { const assetDataElem = link.parentNode.parentNode.children[1]; if (assetDataElem == null) continue; //grdcounterが既に存在するか確認する if (assetDataElem.querySelector('#grdcounter') != null) continue; const assetDownloads = document.createElement('span'); assetDownloads.id = 'grdcounter'; assetDownloads.className = 'color-fg-muted text-sm-right ml-md-3'; assetDownloads.textContent = `${asset.download_count} Downloads`; assetDownloads.style.whiteSpace = 'nowrap'; const fileSize = assetDataElem.firstElementChild; if (fileSize == null) continue; assetDataElem.insertBefore(assetDownloads, fileSize); fileSize.classList.remove('flex-auto'); return true; } } return false; } function initPAT() { if (GM_getValue("GITHUB_PAT") == undefined) GM_setValue("GITHUB_PAT", ""); } (function() { initPAT(); initObserver(); })();