您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Click on collage size = browse through this collage; Alt + click on collage name = remove from this collage
当前为
- // ==UserScript==
- // @name Torrent Collage Extensions for Gazelle
- // @version 1.04
- // @description Click on collage size = browse through this collage; Alt + click on collage name = remove from this collage
- // @author Anakunda
- // @license GPL-3.0-or-later
- // @copyright 2020, Anakunda (https://openuserjs.org/users/Anakunda)
- // @namespace https://greasyfork.org/users/321857-anakunda
- // @match https://*/torrents.php?id=*
- // @grant GM_getValue
- // ==/UserScript==
- 'use strict';
- const searchforcollage = document.getElementById('searchforcollage');
- if (searchforcollage != null) {
- if (typeof SearchCollage == 'function') SearchCollage = () => {
- const searchTerm = $('#searchforcollage').val(),
- personalCollages = $('#personalcollages');
- ajax.get(`ajax.php?action=collages&search=${escape(searchTerm)}`, responseText => {
- const { response, status } = JSON.parse(responseText);
- if (status !== 'success') return;
- const categories = response.reduce((accumulator, item) => {
- const { collageCategoryName } = item;
- accumulator[collageCategoryName] = (accumulator[collageCategoryName] || []).concat(item);
- return accumulator;
- }, {});
- personalCollages.children().remove();
- Object.entries(categories).forEach(([category, collages]) => {
- console.log(collages);
- personalCollages.append(`
- <optgroup label="${category}">
- ${collages.reduce((accumulator, { id, name }) =>
- `${accumulator}<option value="${id}">${name}</option>`
- ,'')}
- </optgroup>
- `);
- });
- });
- };
- function inputHandler(evt, key) {
- const data = evt[key].getData('text/plain').trim();
- if (!data) return true;
- evt.target.value = data;
- SearchCollage();
- // setTimeout(function() {
- // const add_to_collage_select = document.querySelector('select.add_to_collage_select');
- // if (add_to_collage_select != null && add_to_collage_select.getElementsByTagName('option').length == 1)
- // AddToCollage();
- // }, 2000);
- return false;
- }
- searchforcollage.onpaste = evt => inputHandler(evt, 'clipboardData');
- searchforcollage.ondrop = evt => inputHandler(evt, 'dataTransfer');
- }
- if (!/\b(?:id)=(\d+)\b/i.test(document.location.search)) throw 'Unexpected URL format';
- var torrentId = parseInt(RegExp.$1), auth = document.querySelector('input[name="auth"]');
- if (auth == null) {
- auth = document.querySelector('li#nav_logout > a.user-info-bar__link');
- if (auth == null || !/\b(?:auth)=(\w+)\b/.test(auth.search)) throw 'Auth not found';
- auth = RegExp.$1;
- } else auth = auth.value;
- const siteApiTimeframeStorageKey = document.location.hostname + ' API time frame';
- const gazelleApiFrame = 10500;
- if (typeof GM_getValue == 'function') var redacted_api_key = GM_getValue('redacted_api_key');
- try { var collages = JSON.parse(window.sessionStorage.collages) } catch(e) { collages = {} }
- if (!collages[document.domain]) collages[document.domain] = {};
- document.querySelectorAll('table[id$="collages"] > tbody > tr > td > a').forEach(function(link) {
- if (!link.pathname.startsWith('/collages.php') || !/\b(?:id)=(\d+)\b/.test(link.search)) return;
- var collageId = parseInt(RegExp.$1), toggle, navLinks = [],
- numberColumn = link.parentNode.parentNode.querySelector('td.number_column');
- link.onclick = evt => evt.button == 0 && evt.altKey ? removeFromCollage(collageId, link) : true;
- link.title = 'Use Alt + left click to remove from this collage';
- if (numberColumn != null) {
- numberColumn.style.cursor = 'pointer';
- numberColumn.onclick = loadCollage;
- numberColumn.title = collages[document.domain][collageId] ? 'Refresh' : 'Load collage for direct browsing';
- }
- if (collages[document.domain][collageId]) {
- expandSection();
- addCollageLinks(collages[document.domain][collageId]);
- }
- function addCollageLinks(collage) {
- var index = collage.torrentgroups.findIndex(group => group.id == torrentId);
- if (index < 0) {
- console.warn('Assertion failed: torrent', torrentId, 'not found in the collage', collage);
- return false;
- }
- link.style.color = 'white';
- link.parentNode.parentNode.style = 'color:white; background-color: darkgoldenrod;';
- var stats = document.createElement('span');
- stats.textContent = `${index + 1} / ${collage.torrentgroups.length}`;
- stats.style = 'font-size: 8pt; color: antiquewhite; font-weight: 100; margin-left: 10px;';
- navLinks.push(stats);
- link.parentNode.append(stats);
- if (collage.torrentgroups[index - 1]) {
- var a = document.createElement('a');
- a.href = '/torrents.php?id=' + collage.torrentgroups[index - 1].id;
- a.textContent = '[\xA0<\xA0]';
- a.title = getTitle(index - 1);
- a.style = 'color: chartreuse; margin-right: 10px;';
- navLinks.push(a);
- link.parentNode.prepend(a);
- a = document.createElement('a');
- a.href = '/torrents.php?id=' + collage.torrentgroups[0].id;
- a.textContent = '[\xA0<<\xA0]';
- a.title = getTitle(0);
- a.style = 'color: chartreuse; margin-right: 5px;';
- navLinks.push(a);
- link.parentNode.prepend(a);
- }
- if (collage.torrentgroups[index + 1]) {
- a = document.createElement('a');
- a.href = '/torrents.php?id=' + collage.torrentgroups[index + 1].id;
- a.textContent = '[\xA0>\xA0]';
- a.title = getTitle(index + 1);
- a.style = 'color: chartreuse; margin-left: 10px;';
- navLinks.push(a);
- link.parentNode.append(a);
- a = document.createElement('a');
- a.href = '/torrents.php?id=' + collage.torrentgroups[collage.torrentgroups.length - 1].id;
- a.textContent = '[\xA0>>\xA0]';
- a.title = getTitle(collage.torrentgroups.length - 1);
- a.style = 'color: chartreuse; margin-left: 5px;';
- navLinks.push(a);
- link.parentNode.append(a);
- }
- return true;
- function getTitle(index) {
- if (typeof index != 'number' || index < 0 || index >= collage.torrentgroups.length) return undefined;
- var title = collage.torrentgroups[index].musicInfo && Array.isArray(collage.torrentgroups[index].musicInfo.artists) ?
- collage.torrentgroups[index].musicInfo.artists.map(artist => artist.name).join(', ') + ' - ' : '';
- if (collage.torrentgroups[index].name) title += collage.torrentgroups[index].name;
- if (collage.torrentgroups[index].year) title += ' (' + collage.torrentgroups[index].year + ')';
- return title;
- }
- }
- function expandSection() {
- if (toggle === undefined) toggle = link.parentNode.parentNode.parentNode.querySelector('td > a[href="#"][onclick]');
- if (toggle === null || toggle.dataset.expanded) return false;
- toggle.dataset.expanded = true;
- toggle.click();
- return true;
- }
- function loadCollage(evt) {
- evt.target.disabled = true;
- navLinks.forEach(a => { a.remove() });
- navLinks = [];
- var span = document.createElement('span');
- span.textContent = '[\xA0loading...\xA0]';
- span.style = 'color: red; background-color: white; margin-left: 10px;';
- link.parentNode.append(span);
- queryAjaxAPI('collage', { id: collageId }).then(function(collage) {
- span.remove();
- cacheCollage(collage);
- addCollageLinks(collage);
- evt.target.disabled = false;
- }, function(reason) {
- span.remove();
- evt.target.disabled = false;
- });
- return false;
- }
- });
- function cacheCollage(collage) {
- collages[document.domain][collage.id] = {
- id: collage.id,
- name: collage.name,
- torrentgroups: collage.torrentgroups.map(group => ({
- id: group.id,
- musicInfo: group.musicInfo ? {
- artists: Array.isArray(group.musicInfo.artists) ?
- group.musicInfo.artists.map(artist => ({ name: artist.name })) : undefined,
- } : undefined,
- name: group.name,
- year: group.year,
- })),
- };
- window.sessionStorage.collages = JSON.stringify(collages);
- }
- function removeFromCollage(collageId, node = null) {
- if (!confirm('Are you sure to remove from collage "' + node.textContent.trim() + '"?')) return false;
- let xhr = new XMLHttpRequest, params = new URLSearchParams({
- action: 'manage_handle',
- collageid: collageId,
- groupid: torrentId,
- auth: auth,
- submit: 'Remove',
- });
- xhr.open('POST', '/collages.php', true);
- xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
- xhr.onreadystatechange = function() {
- if (xhr.readyState != XMLHttpRequest.HEADERS_RECEIVED) return;
- if (xhr.status >= 200 && xhr.status < 400) {
- if (node instanceof HTMLElement) node.parentNode.parentNode.remove(); else document.location.reload();
- } else errorHandler();
- xhr.abort();
- };
- xhr.onerror = errorHandler;
- xhr.send(params);
- return false;
- function errorHandler() { console.error('Failed to remove', torrentId, 'from collage', collageId, xhr) }
- }
- function queryAjaxAPI(action, params) {
- if (!action) return Promise.reject('Action missing');
- var retryCount = 0;
- return new Promise(function(resolve, reject) {
- params = new URLSearchParams(params || undefined);
- params.set('action', action);
- var url = '/ajax.php?' + params, xhr = new XMLHttpRequest;
- queryInternal();
- function queryInternal() {
- var now = Date.now();
- try { var apiTimeFrame = JSON.parse(window.localStorage[siteApiTimeframeStorageKey]) } catch(e) { apiTimeFrame = {} }
- if (!apiTimeFrame.timeStamp || now > apiTimeFrame.timeStamp + gazelleApiFrame) {
- apiTimeFrame.timeStamp = now;
- apiTimeFrame.requestCounter = 1;
- } else ++apiTimeFrame.requestCounter;
- window.localStorage[siteApiTimeframeStorageKey] = JSON.stringify(apiTimeFrame);
- if (apiTimeFrame.requestCounter <= 5) {
- xhr.open('GET', url, true);
- xhr.setRequestHeader('Accept', 'application/json');
- if (redacted_api_key) xhr.setRequestHeader('Authorization', redacted_api_key);
- xhr.responseType = 'json';
- //xhr.timeout = 5 * 60 * 1000;
- xhr.onload = function() {
- if (xhr.status == 404) return reject('not found');
- if (xhr.status < 200 || xhr.status >= 400) return reject(defaultErrorHandler(xhr));
- if (xhr.response.status == 'success') return resolve(xhr.response.response);
- if (xhr.response.error == 'not found') return reject(xhr.response.error);
- console.warn('queryAjaxAPI.queryInternal(...) response:', xhr, xhr.response);
- if (xhr.response.error == 'rate limit exceeded') {
- console.warn('queryAjaxAPI.queryInternal(...) ' + xhr.response.error + ':', apiTimeFrame, now, retryCount);
- if (retryCount++ <= 10) return setTimeout(queryInternal, apiTimeFrame.timeStamp + gazelleApiFrame - now);
- }
- reject('API ' + xhr.response.status + ': ' + xhr.response.error);
- };
- xhr.onerror = function() { reject(defaultErrorHandler(xhr)) };
- xhr.ontimeout = function() { reject(defaultTimeoutHandler(xhr)) };
- xhr.send();
- } else {
- setTimeout(queryInternal, apiTimeFrame.timeStamp + gazelleApiFrame - now);
- console.debug('AJAX API request quota exceeded: /ajax.php?action=' +
- action + ' (' + apiTimeFrame.requestCounter + ')');
- }
- }
- });
- }
- function defaultErrorHandler(response) {
- console.error('HTTP error:', response);
- var e = 'HTTP error ' + response.status;
- if (response.statusText) e += ' (' + response.statusText + ')';
- if (response.error) e += ' (' + response.error + ')';
- return e;
- }
- function defaultTimeoutHandler(response) {
- console.error('HTTP timeout:', response);
- const e = 'HTTP timeout';
- return e;
- }