您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button that compares the anime list of a hummingbird user against yours
当前为
// ==UserScript== // @name Hummingbird User Compare // @version 3.0 // @description Adds a button that compares the anime list of a hummingbird user against yours // @author fuzetsu // @match https://hummingbird.me/* // @match https://forums.hummingbird.me/* // @grant none // @require https://gf.qytechs.cn/scripts/5679-wait-for-elements/code/Wait%20For%20Elements.js?version=46106 // @noframes // @namespace https://gf.qytechs.cn/users/649 // ==/UserScript== var SCRIPT_NAME = 'Hummingbird User Compare'; var BTN_ID = 'us-compare-button'; var COMPAT_ID = 'us-compat-table'; var USERNAME_SELECTOR = 'h2.username,h1.username'; var Util = { log: function() { var args = [].slice.call(arguments); args.unshift('%c' + SCRIPT_NAME + ':', 'font-weight: bold'); console.log.apply(console, args); }, q: function(query, context) { return (context || document).querySelector(query); }, qq: function(query, context) { return [].slice.call((context || document).querySelectorAll(query)); }, shallowTextContent: function(elem) { var child = elem.firstChild, texts = []; while (child) { if (child.nodeType == 3) { texts.push(child.data); } child = child.nextSibling; } return texts.join(""); }, arrToTable: function(arr, opts) { // takes an object and converts to an html compliant list of attributes var makeAttrs = function(obj) { var str = ''; var key; for(key in obj) { if(obj.hasOwnProperty(key)) { str += key + '="' + obj[key] + '" '; } } return str; }; // creates an object of the specified type // either takes a config object with attributes and a value, or just the value directly var createElement = function(type, data) { if(typeof data === 'object') { return '<' + type +' ' + makeAttrs(data.attrs || {}) + '>' + data.value + '</' + type + '>'; } return '<' + type + '>' + data + '</' + type + '>'; }; opts = opts || {}; var headers = ''; // if the table is going to have a head use the first row if(opts.hasHead) { headers = arr[0].map(function(header) { return createElement('th', header); }).join(''); headers = '<thead>' + headers + '</thead>'; arr = arr.slice(1); } // create the body of the array var rows = arr.map(function(row) { return '<tr>' + row.map(function(cell) { return createElement('td', cell); }).join('') + '</tr>'; }).join(''); // create and return the actual table all put together return createElement('table', { attrs: opts.attrs, value: (headers + '<tbody>' + rows + '</tbody>') }); }, getJSON: function(url, load, error) { var xhr = new XMLHttpRequest(); xhr.open('get', url); xhr.responseType = 'json'; xhr.onload = function() { load(xhr.response); }; xhr.onerror = error; xhr.send(); } }; var hb = { getCompareUrl: function() { var profileUrl = Util.q('.dropdown-menu > li > a').href; var you = profileUrl.slice(profileUrl.lastIndexOf('/') + 1); var them = Util.shallowTextContent(Util.q(USERNAME_SELECTOR)).trim(); return { you: you, them: them, url: 'http://fuzetsu.github.io/hummingbird-user-compare/?user1=' + you + '&user2=' + them }; }, getCompatibility: function(callback) { var buffer = []; var process = function(data) { buffer.push(data); if(buffer.length === 2) { var anime, manga; if (buffer[0].type === 'anime') { anime = buffer[0]; manga = buffer[1]; } else { anime = buffer[1]; manga = buffer[0]; } callback(anime, manga); } }; var profileUrl = Util.q('.dropdown-menu > li > a').href; var you = profileUrl.slice(profileUrl.lastIndexOf('/') + 1); var them = Util.shallowTextContent(Util.q(USERNAME_SELECTOR)).trim(); // get anime compat $.getJSON('https://hbird-cmp-node.herokuapp.com/compatibility/anime?user1=' + you + '&user2=' + them, process); // get manga compat $.getJSON('https://hbird-cmp-node.herokuapp.com/compatibility/manga?user1=' + you + '&user2=' + them, process); } }; var lastUser; Util.log('Started, waiting for user page...'); waitForUrl(/https:\/\/(forums\.)?hummingbird\.me\/users\/.+/, function() { Util.log('Found user page, waiting for button area...'); waitForElems('.user-cover-options .follow-button:not(.' + BTN_ID + ')', function(btnFollow) { var forumButton = Util.q('.account-info .inline-list a'); var btn = Util.q('#' + BTN_ID); var compatTable = Util.q('#' + COMPAT_ID); var compare = hb.getCompareUrl(); var compatibilityCallback = function(anime, manga) { var animeMessage = anime.phrase; if (anime.percent) { animeMessage += ' (' + anime.percent + ')'; } var mangaMessage = manga.phrase; if (manga.percent) { mangaMessage += ' (' + manga.percent + ')'; } var table = []; table.push([{value: 'Anime Compatability:', attrs: {style: 'text-align: right; padding-right: 5px;'}}, {value: animeMessage, attrs: {style: 'font-weight:bold'}}]); table.push([{value: 'Manga Compatability:', attrs: {style: 'text-align: right; padding-right: 5px;'}}, {value: mangaMessage, attrs: {style: 'font-weight:bold'}}]); btnFollow.parentNode.innerHTML += Util.arrToTable(table, { hasHead: false, attrs: { style: 'position: absolute; bottom: -25px; right: 0;', id: COMPAT_ID } }); }; // exit early if you're on your own profile if(compare.them === compare.you) return; Util.log('Found button area, inserting compare button'); if(forumButton) { forumButton.title = ''; forumButton.target = '_blank'; forumButton.href = compare.url; } else { if(btn) { btn.remove(); } btn = document.createElement('a'); btn.className = btnFollow.className; btn.id = BTN_ID; btn.textContent = 'Compare'; btn.target = '_blank'; btn.setAttribute('style', 'right: ' + (btnFollow.clientWidth + 10) + 'px; background: rgb(236, 134, 97); color: white;'); if(compare.them === lastUser && location.href.indexOf("/users/" + lastUser) === -1) { if (compatTable) { compatTable.remove(); } Util.q(USERNAME_SELECTOR).addEventListener('DOMSubtreeModified', function(e) { this.removeEventListener('DOMSubtreeModified', arguments.callee); compare = hb.getCompareUrl(); btn.href = compare.url; btnFollow.parentNode.appendChild(btn); hb.getCompatibility(compatibilityCallback); }); } else { var found = false; if (compatTable) { found = true; if (compare.them !== lastUser) { compatTable.remove(); } } btn.href = compare.url; btnFollow.parentNode.appendChild(btn); if (!found || compare.them !== lastUser) { hb.getCompatibility(compatibilityCallback); } } } lastUser = compare.them; }, true); });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址