您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
automatically runs a fandom-specific tag search over all your assigned fandoms, to find any canonicals with 'illegal' characters such as curly quotes or Chinese pipes
// ==UserScript== // @name AO3: [Wrangling] Search my canonicals for illegal characters // @namespace https://greasyfork.org/en/users/906106-escctrl // @version 3.0 // @description automatically runs a fandom-specific tag search over all your assigned fandoms, to find any canonicals with 'illegal' characters such as curly quotes or Chinese pipes // @author escctrl // @match https://archiveofourown.org/tags/search // @grant none // @license MIT // ==/UserScript== (function() { 'use strict'; const COPY_SEARCH_STRING = false; const DEBUG = false; var found = 0; // counting found results var node_ul = document.getElementById('wranglerbuttons') || document.querySelector('#main ul.navigation.actions'); const node_li = document.createElement('li'); node_li.id = 'checkillegal'; node_li.className = 'reindex'; node_li.innerHTML = "<a href='#'>Check Illegal Characters</a>"; if (COPY_SEARCH_STRING) node_li.addEventListener("click", copySearchString); else node_li.addEventListener("click", startBackgroundCheck); node_ul.appendChild(node_li); function copySearchString() { document.getElementById('tag_search_name').value = "*’* OR *‘* OR *“* OR *”* OR *|* OR *–* OR *—* OR *―* OR *(* OR *)* OR *\\'\\'*"; var tagtype = document.getElementById('tag_search_status'); if (tagtype !== null) tagtype.value = 'T'; // if the Smaller Tag Search script is enabled else document.getElementById('tag_search_canonical_t').checked = true; // for the plain New Tag Search form } function startBackgroundCheck() { // who am I logged in as? const user = document.querySelector('#greeting ul.user.navigation li.dropdown>a.dropdown-toggle[href*="/users/"]').href.match(/\/([A-Za-z0-9_]+)\/?$/i)[1]; if (DEBUG) console.log("Illegal Characters: Logged in as user "+user); window.ao3jail = false; // get a list of all my wrangled fandoms pageload('https://archiveofourown.org/tag_wranglers/'+user, 'fandoms'); } function retrieveFandomList(me) { // find all the assigned fandoms in the table (URL and name) const fandomlist = me.querySelectorAll('table tbody tr th a'); // add a tracker for how many open XHR there will be window.openXHR = fandomlist.length; if (DEBUG) console.log("Illegal Characters: There are "+window.openXHR+" fandoms assigned, to be checked"); document.getElementById('checkillegal').firstChild.innerText = "Checking " + window.openXHR + " fandoms"; fandomlist.forEach( (f, i) => { var url = 'https://archiveofourown.org/tags/search?tag_search%5Bname%5D=*%E2%80%99*+OR+*%E2%80%98*+OR+*%E2%80%9C*+OR+*%E2%80%9D*+OR+*%EF%BD%9C*+OR+*%E2%80%93*+OR+*%E2%80%94*+OR+*%E2%80%95*+OR+*%EF%BC%88*+OR+*%EF%BC%89*+OR+*%5C%27%5C%27*&tag_search%5Btype%5D=&tag_search%5Bcanonical%5D=T&tag_search%5Bsort_column%5D=name&tag_search%5Bsort_direction%5D=asc&commit=Search+Tags&tag_search%5Bfandoms%5D='; url += encodeURIComponent(f.innerText); if (DEBUG) console.log("Illegal Characters: Fandom "+f.innerText+" will be checked in "+3000*i+" second"); if (DEBUG) url = 'https://archiveofourown.org/tags/search?tag_search%5Bname%5D=*POV*&tag_search%5Btype%5D=&tag_search%5Bcanonical%5D=T&tag_search%5Bsort_column%5D=name&tag_search%5Bsort_direction%5D=asc&commit=Search+Tags&tag_search%5Bfandoms%5D='+ encodeURIComponent(f.innerText); // collect the search results for specifically those fandoms setTimeout(function() { pageload(url, 'search'); }, 3000*i); }); } function retrieveSearchResults(me) { window.openXHR--; // avoids updating the button by a slower (working) response after a page load was already jailed if (!window.ao3jail) document.getElementById('checkillegal').firstChild.innerText = "Checking " + window.openXHR + " fandoms"; const results = me.querySelectorAll('ol.tag.index li span'); const fandom = me.querySelector('#tag_search_fandoms').value; if (DEBUG) console.log("Illegal Characters: Fandom "+fandom+" has "+results.length+" tags with illegal characters"); if (DEBUG) console.log("Illegal Characters: There are "+window.openXHR+" fandoms remaining to be checked"); // adds the found nodelist to the object var printtext = ""; if (results.length > 0) { printtext = '<h4 class="heading">'+fandom+'</h4><ol class="tag index group">'; found = found + results.length; for (let n of results.values()) { printtext += '<li>'+n.outerHTML+'</li>'; } printtext += '</ol>'; const node_parent = document.querySelector('#main'); node_parent.innerHTML += printtext; // appending at the bottom of the list } if (window.openXHR == 0) { if (DEBUG) console.log("Illegal Characters: Last fandom was checked, tallying up the result tags"); // this was the last open XHR so we can print the total number found! printTotals(); } } function printTotals() { const heading = document.createElement('h3'); heading.className = "heading" heading.innerText = found+' Found'; const node_parent = document.querySelector('#new_tag_search'); node_parent.insertAdjacentElement('afterend', heading); if (DEBUG) console.log("Illegal Characters: Script completed."); document.getElementById('checkillegal').firstChild.innerText = "Check for illegal characters finished"; } function saySorry(me) { // this does not count down the checked fandoms so button can never show as "finished" when there were errors // user output only if this is the fist page that failed if (window.ao3jail == false) { // check if we received a retry-after value in the response if (DEBUG) console.log("Illegal Characters: 429 retry-after " + me.getResponseHeader('Retry-After')); var timeout = parseInt(me.getResponseHeader('Retry-After') || 0); timeout = (timeout > 0) ? ' You can try again in '+ Math.ceil(timeout / 60) +' minutes.' : ''; document.querySelector('#new_tag_search').outerHTML += "<h3 class='heading'>Sorry, the script stopped because it ran into the "+me.statusText+" error."+ timeout +"</h3>"; document.getElementById('checkillegal').firstChild.innerText = "Check stopped: error"; } window.ao3jail = true; // console output for every page that didn't load properly console.log("Illegal Characters: The background page load ran into an issue: "+me.status+" "+me.statusText); } function pageload(url, what) { if (DEBUG) console.log("Illegal Characters: Loading page "+url); if (window.ao3jail) { if (DEBUG) console.log("Illegal Characters: This page load was skipped due to previously encountered errors."); return false; } const xhr = new XMLHttpRequest(); xhr.onload = () => { if (xhr.status==200 && xhr.response != "") { if (what == 'fandoms') retrieveFandomList(xhr.response); else retrieveSearchResults(xhr.response); } else saySorry(xhr); }; xhr.onerror = () => { saySorry(xhr); }; xhr.open("GET", url); xhr.responseType = "document"; xhr.send(); } })();