// ==UserScript== // @name qB WebUI 加PT站名标签 // @version 0.1.0 // @author cO_ob // @description qBittorrent WebUI 根据tracker中的关键字给种子增加标签 // @license MIT // @match http://127.0.0.1:8080/ // @namespace https://greasyfork.org/users/1270887 // @require https://cdn.bootcdn.net/ajax/libs/jquery/3.6.3/jquery.min.js // @downloadURL none // ==/UserScript== //require qB API v2.3.0 + const host = window.location.href; const baseURL = host + 'api/v2/torrents/'; let trackerMappings = [ { url: 'agsvpt', tags: 'agsv' }, { url: 'btschool', tags: 'BTSCHOOL' }, { url: 'chdbits', tags: 'CHDBits' }, { url: 'daydream', tags: 'U2' }, { url: 'eastgame', tags: 'TLFBits' }, { url: 'et8.org', tags: 'TorrentCCF' }, { url: 'hdatmos', tags: 'HDATMOS' }, { url: 'hd4fans', tags: 'HD4FANS' }, { url: 'hdarea', tags: 'HDArea' }, { url: 'hdfans', tags: 'HDFans' }, { url: 'hdhome', tags: 'HDHome' }, { url: 'hdsky', tags: 'HDSky' }, { url: 'hdkyl', tags: 'HDKylin-麒麟' }, { url: 'leaves', tags: '红叶' }, { url: 'm-team', tags: 'M-Team' }, { url: 'open.cd', tags: 'OpenCD' }, { url: 'ourbits', tags: 'OurBits' }, { url: 'pttime', tags: 'pttime' }, { url: 'sharkpt', tags: 'SharkPT' }, { url: 'totheglory', tags: 'TTG' } ]; function loadConfig() { const savedMappings = localStorage.getItem('trackerMappings'); if (savedMappings) { trackerMappings = JSON.parse(savedMappings); } } function saveConfig() { localStorage.setItem('trackerMappings', JSON.stringify(trackerMappings)); } async function getFetch(route) { try { const response = await fetch(baseURL + route); if (!response.ok) { throw new Error('Error fetching info!'); } const data = await response.json(); return data; } catch (error) { console.error(error); return null; } } loadConfig(); async function processTorrents() { try { const torrentList = await getFetch('info'); let totalTorrents = 0; let currentProcessed = 0; totalTorrents = torrentList.length; for (const torrent of torrentList) { currentProcessed++; jQuery(".js-modal").text(`加标签 ${currentProcessed}/${totalTorrents}`); const trackers = await getFetch(`trackers?hash=${torrent.hash}`); for (let i = 0; i < trackers.length; i++) { const tracker = trackers[i]; if (tracker.status != 0) { let torrentTags = []; let foundMapping = false; for (const mapping of trackerMappings) { if (tracker.url.includes(mapping.url)) { torrentTags = [mapping.tags]; foundMapping = true; break; } } if (!foundMapping) { const newMappingUrl = prompt(`输入新的关键字:\n${tracker.url}`); if (newMappingUrl !== null) { const newMappingTags = prompt(`新关键字要使用的标签:\n${tracker.url}`); if (newMappingTags !== null) { trackerMappings.push({ url: newMappingUrl, tags: newMappingTags }); torrentTags = [newMappingTags]; } } } const tags = torrentTags.join(","); //const response = await fetch(`${baseURL}addTags?hashes=${torrent.hash}&tags=${tags}`); //GET method. only for qb version under v4.5.0 const url = `${baseURL}addTags`; const data = new URLSearchParams(); data.append('hashes', torrent.hash); data.append('tags', tags); fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: data }) .then(response => { console.log(response); }) .catch(error => { console.error('Error:', error); }); break; } } } console.log('Done.'); } catch (error) { console.error('Error:', error.message); } jQuery(".js-modal").text(`加标签 完成`); } jQuery("#desktopNavbar > ul").append( "
  • 加标签
  • ", ); jQuery(".js-modal").click(async function () { await processTorrents(); saveConfig(); });