|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
17-Ноя-17 11:00
(7 лет назад)
Papant
Не получается, Ctrl-O так и делает, а Greasemonkey не видит открытого файла, его содержимое просто показывается в окне. Разработчик пишет, что теперь расширения не имеют доступа к файловой системе, видимо в этом причина.
|
|
Papant
Стаж: 17 лет 2 месяца Сообщений: 56369
|
Papant ·
17-Ноя-17 11:03
(спустя 2 мин.)
unchqua
А слеши вводил правые , и в нужном количестве?
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
17-Ноя-17 11:22
(спустя 19 мин.)
Papant
Ну вот так у меня сейчас:
Тренируюсь на старом скрипте.
|
|
Rugodiv
Стаж: 9 лет 7 месяцев Сообщений: 605
|
Rugodiv ·
17-Ноя-17 11:47
(спустя 25 мин., ред. 18-Ноя-17 14:44)
|
|
SergeyJD
Стаж: 16 лет 9 месяцев Сообщений: 4859
|
SergeyJD ·
17-Ноя-17 14:10
(спустя 2 часа 22 мин.)
Откатился до 56.
Буду ждать новостей.
|
|
порошков
Стаж: 15 лет 9 месяцев Сообщений: 24373
|
порошков ·
17-Ноя-17 16:45
(спустя 2 часа 35 мин.)
SergeyJD писал(а):
74249909Откатился до 56.
Тоже откатился, но обезьяна уже не хочет ставиться Хотя недавно все работало норм...
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
17-Ноя-17 17:09
(спустя 23 мин.)
порошков
Взял xpi из своего Фаерфокса. В нём написано, что это версия 4.0, но в Firefox 56 работает. Не помню только, не запрещена ли в браузере установка приложений не из AMO.
https://yadi.sk/d/nGYayQNx3PnmsH
|
|
порошков
Стаж: 15 лет 9 месяцев Сообщений: 24373
|
порошков ·
17-Ноя-17 17:16
(спустя 7 мин., ред. 17-Ноя-17 17:32)
unchqua Ничего не ставится(((
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
17-Ноя-17 17:22
(спустя 5 мин., ред. 09-Фев-18 11:49)
В общем, у меня получается запускать свои скрипты по-новому, изменения минимальны. Проблема сейчас в том, как их устанавливать на другие компы в свете этого:
Цитата:
Если раньше можно было установить скрипт с локального диска, открыв его про Ctrl-O, то теперь нужен веб-сервер, отдающий исходники скриптов, да ещё и с нужным Content-Type.
У кого есть подконтрольный веб-сервер, тот может ставить уже сейчас (исходники ниже), кладите под сервер файлы с расширением .user.js в кодировке UTF-8 и обращайтесь к ним по URL-у httр://...
Остальных прошу подождать до понедельника, когда появится нужный хостинг для скриптов.
Ссылка на страницу всех скриптов в моей подписи. Внимание! По последней информации, по какой-то причине накрылся API WebStorage, с помощью которого скрипты хранили свои настройки. Скрипты 16 и 21 пока работают неполноценно: хранят свои настройки только до закрытия закладки браузера. Ищу способ восстановления работы. Те скрипты, где настройки не нужны, переделать несложно.
|
|
Hannibal61
Стаж: 14 лет 8 месяцев Сообщений: 18111
|
Hannibal61 ·
17-Ноя-17 21:45
(спустя 4 часа)
порошков писал(а):
74250793Тоже откатился, но обезьяна уже не хочет ставиться
порошков
Там есть ссылка на старые версии, чуть ниже.
|
|
порошков
Стаж: 15 лет 9 месяцев Сообщений: 24373
|
порошков ·
17-Ноя-17 22:06
(спустя 20 мин.)
Hannibal61
Уфф...спасибо, сделал
|
|
Nataly-Lilly
Стаж: 16 лет 5 месяцев Сообщений: 9603
|
Nataly-Lilly ·
19-Ноя-17 21:28
(спустя 1 день 23 часа)
Откатилась на 56. Модскрипт не заработал. что делать?
|
|
Hannibal61
Стаж: 14 лет 8 месяцев Сообщений: 18111
|
Hannibal61 ·
19-Ноя-17 21:35
(спустя 6 мин.)
Nataly-Lilly
Попробуйте Greasemonkey переустановить.
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
20-Ноя-17 10:29
(спустя 12 часов)
У нас появился хостинг скриптов!
Надеюсь, он долго будет в строю, а мы с вами его наполним тем, что было написано для старых версий Firefox.
Вот что сейчас там лежит (их описание тут):
http://kotproxy.info/gmscripts/rto13.user.js
http://kotproxy.info/gmscripts/rto16.user.js
http://kotproxy.info/gmscripts/rto18.user.js
http://kotproxy.info/gmscripts/rto21.user.js
Это всё скрипты для FF 57+, а версии предыдущего формата есть в теме. Рутрекер 09. Дополнительные кнопки для текстового редактора сообщений. Это код-заготовка для показа того, как можно добавить свои кнопки, вставляющие какой-то текст в редактор, то есть каждый сам может дописать там свои и использовать их.
скрытый текст
Код:
// ==UserScript==
// @name Рутрекер 09. Дополнительные кнопки для текстового редактора сообщений.
// @namespace http://www.unchqua.ru/ns/greasemonkey
// @include *://rutr.life/forum/*
// @include *://rutracker.net/forum/*
// @include *://rutracker.cr/forum/*
// @include *://rutracker.nl/forum/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
// @version 1
// @grant none
// ==/UserScript== (function(){ var $ = jQuery.noConflict(true); // Панель системных кнопок редактора.
var editor_div = $("div#ped-editor-buttons");
if (editor_div.length !== 1) // Текстового редактора нет - тут делать нечего.
return; if ($("div#rto09_buttons").length!==0)
return; // Кнопки уже были добавлены - второй раз не надо. // Строка с новыми кнопками.
var new_buttons = $("<div id=\"rto09_buttons\" class=\"buttons-row\">"); // Наша кнопка 1:
var new_button_1 =
$("<input style=\"margin: 0 .3em;\" value=\"\u00a0Разметка 1\u00a0\" name=\"custom_button_1\" title=\"Сложная разметка 1\" type=\"button\"/>")
.click(function(){
unsafeWindow.bbcode.surround("[size=10][color=gray][i]","[/i][/color][/size]");
}); // Наша кнопка 2:
var new_button_2 =
$("<input style=\"margin: 0 .3em;\" value=\"\u00a0Разметка 2\u00a0\" name=\"custom_button_2\" title=\"Сложная разметка 2\" type=\"button\"/>")
.click(function(){
unsafeWindow.bbcode.surround("[size=6][color=orange][u]","[/u][/color][/size]");
}); // Наша кнопка 3:
var new_button_3 =
$("<input style=\"margin: 0 .3em;\" value=\"\u00a0Разметка 3\u00a0\" name=\"custom_button_3\" title=\"Сложная разметка 3\" type=\"button\"/>")
.click(function(){
unsafeWindow.bbcode.insertAtCursor("aaa\n[b]bbb[/b]\n[i]ccc[/i]");
}); // Помещаем в строку все наши кнопки, а её добавляем к панели системных кнопок.
editor_div.append(new_buttons.append(new_button_1, new_button_2, new_button_3)); })();
Этот скрипт будет там ближе к ночи, и страницу общего описания тоже сделаю. Какие скрипты ещё переносить?
|
|
RoxMarty
Стаж: 17 лет 7 месяцев Сообщений: 14622
|
RoxMarty ·
20-Ноя-17 11:26
(спустя 57 мин., ред. 20-Ноя-17 11:26)
При открытии соответствующих страничек в 57-м кодировка названия/описания сбитая
Цитата:
Какие скрипты ещё переносить?
Спасибо за портирование. Изучим. Потестим. Сообщим
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
20-Ноя-17 12:09
(спустя 42 мин., ред. 20-Ноя-17 18:39)
RoxMarty писал(а):
74270159При открытии соответствующих страничек в 57-м кодировка названия/описания сбитая
У меня то же самое, забей, будет работать, и название в списке потом тоже будет правильное. Это эвристика в браузере или расширении плохо работает, неверно определяет кодировку.
Автор Greasemonkey в своём форуме не пропадает, отвечает на вопросы, это хорошо. Глядишь, будем и дальше жить.
Сделал кое-какое описание скриптов и удобные ссылки на них, и с картинками!
Завтра продолжу, а то уже опух.
|
|
RoxMarty
Стаж: 17 лет 7 месяцев Сообщений: 14622
|
RoxMarty ·
20-Ноя-17 22:15
(спустя 10 часов)
unchqua
Отличное описание с картинками. Давно этого не хватало!
Ждём-с переделки автооткрытия новых комментов
|
|
maximus_lt
Стаж: 17 лет 5 месяцев Сообщений: 6144
|
maximus_lt ·
20-Ноя-17 23:30
(спустя 1 час 15 мин.)
unchqua, такими темпами мы доберемся до авто заполнения релизов с Discogs и Кинопоиска
|
|
Rugodiv
Стаж: 9 лет 7 месяцев Сообщений: 605
|
Rugodiv ·
21-Ноя-17 11:56
(спустя 12 часов)
Обновилось дополнение NoScript , теперь оно работает на Firefox 57+ https://addons.mozilla.org/ru/firefox/addon/noscript/
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
21-Ноя-17 18:53
(спустя 6 часов)
Забросил ещё пару скриптов и обновил список, ознакомьтесь. Какие скрипты ещё нужны?
Начинают вырисовываться неприятные моменты в связи с переходом на новый формат расширений, но пока как-то можно жить.
|
|
maximus_lt
Стаж: 17 лет 5 месяцев Сообщений: 6144
|
maximus_lt ·
21-Ноя-17 19:44
(спустя 51 мин., ред. 21-Ноя-17 19:44)
unchqua, вы можете глянуть YADG (1.4.38) под Violentmonkey 2.8.0 (под Maxthon 5.1.3.2000) перестал работать на Реде.
скрытый текст
Код:
// ==UserScript==
// @id pth-yadg
// @name RED YADG
// @description This script provides integration with online description generator YADG (http://yadg.cc) - Credit to Slack06
// @license https://github.com/SavageCore/yadg-pth-userscript/blob/master/LICENSE
// @version 1.4.38
// @namespace yadg
// @grant GM_xmlhttpRequest
// @grant GM.xmlHttpRequest
// @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @require https://yadg.cc/static/js/jsandbox.min.js
// @include http*://*redacted.ch/upload.php*
// @include http*://*redacted.ch/requests.php*
// @include http*://*redacted.ch/torrents.php*
// @include http*://*waffles.ch/upload.php*
// @include http*://*waffles.ch/requests.php*
// @downloadURL https://github.com/SavageCore/yadg-pth-userscript/raw/master/pth_yadg.user.js
// ==/UserScript== // --------- USER SETTINGS START --------- /* global window unsafeWindow document GM JSandbox formatName AddArtistField RemoveArtistField Blob alert $ Image */
/* eslint max-depth: ['off'], block-scoped-var: 'off', no-loop-func: 'off', no-alert: 'off' */ /*
Here you can set site specific default templates.
You can find a list of available templates at: https://yadg.cc/api/v2/templates/
*/
var defaultPTHFormat = 4;
var defaultWafflesFormat = 9;
var defaultPTHTarget = 'other';
var defaultPTHDescriptionTarget = 'album';
var yadg;
var factory;
var yadgRenderer;
var yadgTemplates; // --------- USER SETTINGS END --------- function fetchImage(target, callback) {
var imgElement = document.getElementById('image');
if (imgElement && imgElement.getAttribute('disabled') === 'disabled') {
return;
}
var link;
if (target === null) {
link = unsafeWindow.$('#yadg_input').val();
} else {
link = target;
}
switch (true) {
case (/discogs/.test(link)):
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: link,
onload: function (response) {
if (response.status === 200) {
var container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = response.responseText;
if (typeof callback === 'function') {
callback(JSON.parse(container.querySelectorAll('div.image_gallery.image_gallery_large')[0].getAttribute('data-images'))[0].full);
}
}
}
});
break;
case (/itunes/.test(link)):
var regex = /apple\.com\/(?:([a-z]{2,3})\/)?.*\/(?:(\d+)|id(\d*))/;
var res = regex.exec(link);
var id = res[2] | res[3];
var country = 'us';
if (res[1]) {
country = res[1];
}
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: 'https://itunes.apple.com/lookup?id=' + id + '&country=' + country,
onload: function (response) {
if (response.status === 200) {
var data = JSON.parse(response.responseText);
var hires = data.results[0].artworkUrl100.replace('100x100bb', '100000x100000-999');
if (typeof callback === 'function') {
callback(hires);
}
}
}
});
break;
case (/bandcamp/.test(link)):
case (factory.getScraperSelect().value === 'bandcamp'):
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: link,
onload: function (response) {
if (response.status === 200) {
var container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = response.responseText;
var scaledImg = container.querySelectorAll('#tralbumArt > a > img')[0].src;
var originalImg = scaledImg.replace(/_16/, '_0');
var tempImg = new Image();
tempImg.src = originalImg;
tempImg.onload = function () {
if (this.width === this.height) {
var img = originalImg;
} else {
img = scaledImg;
}
if (typeof callback === 'function') {
callback(img);
}
};
}
}
});
break;
case (/beatport/.test(link)):
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: link,
onload: function (response) {
if (response.status === 200) {
var container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = response.responseText;
if (typeof callback === 'function') {
callback(container.querySelectorAll('div.interior-release-chart-artwork-parent > img')[0].src);
}
}
}
});
break;
case (/musicbrainz/.test(link)):
var regex = /release\/(.*)/;
var id = regex.exec(link)[1];
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
headers: {
'User-Agent': 'YADG/1.3.17 (yadg.cc)'
},
method: 'GET',
url: 'http://coverartarchive.org/release/' + id + '/',
onload: function (response) {
if (response.status === 200) {
var data = JSON.parse(response.responseText);
if (typeof callback === 'function') {
callback(data.images[0].image);
}
}
}
});
break;
case (/junodownload/.test(link)):
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: link,
onload: function (response) {
if (response.status === 200) {
var container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = response.responseText;
if (typeof callback === 'function') {
callback(container.querySelectorAll('#product_image_front > a')[0].href);
}
}
}
});
break;
case (/metal-archives/.test(link)):
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: link,
onload: function (response) {
if (response.status === 200) {
var container = document.implementation.createHTMLDocument().documentElement;
container.innerHTML = response.responseText; var parser = document.createElement('a');
parser.href = container.querySelectorAll('#cover > img')[0].src;
var imgLink = parser.protocol + '//' + parser.hostname + parser.pathname;
if (typeof callback === 'function') {
callback(imgLink);
}
}
}
});
break;
default:
break;
}
} function pthImgIt() {
var pthImgIt = document.getElementsByClassName('rehost_it_cover')[0]; switch (window.location.href) {
case (window.location.href.match(/\/upload\.php/) || {}).input:
var imgElement = document.getElementById('image').value;
break;
case (window.location.href.match(/torrents\.php\?action=editgroup/) || {}).input:
var imgElement = document.querySelectorAll('#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)')[0].value;
break;
default:
break;
} if (pthImgIt && imgElement) {
pthImgIt.click();
}
} function insertImage(img, callback) {
switch (window.location.href) {
case (window.location.href.match(/\/upload\.php/) || {}).input:
var input = document.getElementById('image');
input.value = img;
if (input.getAttribute('autorehost') === 'true') {
var evt = document.createEvent('HTMLEvents');
evt.initEvent('keyup', false, true);
input.dispatchEvent(evt);
}
input.parentNode.parentNode.insertAdjacentHTML('beforebegin', '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="' + img + '" width="300px" /></tr></td>');
callback();
break;
case (window.location.href.match(/torrents\.php\?action=editgroup/) || {}).input:
var imageInputElement = document.querySelectorAll('#content > div > div:nth-child(2) > form > div > input[type="text"]:nth-child(5)')[0];
imageInputElement.value = img;
imageInputElement.parentNode.insertAdjacentHTML('beforebegin', '<div id="yadg_image_preview_div"><img id="yadg_image_preview" src="' + img + '" width="300px" /></div>');
callback();
break;
case (window.location.href.match(/requests\.php\?/) || {}).input:
var imageInputElement = document.querySelectorAll('#image_tr > td:nth-child(2) > input[type="text"]:nth-child(1)')[0];
imageInputElement.value = img;
imageInputElement.parentNode.parentNode.insertAdjacentHTML('beforebegin', '<tr id="yadg_image_preview_tr"><td class="label">Album Art Preview:</td><td><img id="yadg_image_preview" src="' + img + '" width="300px" /></tr></td>');
callback();
break;
default:
break;
}
} // --------- THIRD PARTY CODE AREA START --------- //
// Creates an object which gives some helper methods to
// Save/Load/Remove data to/from the localStorage
//
// Source from: https://github.com/gergob/localstoragewrapper
//
function LocalStorageWrapper(applicationPrefix) {
'use strict'; if (applicationPrefix === undefined) {
throw new Error('applicationPrefix parameter should be defined');
} var delimiter = '_'; // if the passed in value for prefix is not string, it should be converted
var keyPrefix = typeof (applicationPrefix) === 'string' ? applicationPrefix : JSON.stringify(applicationPrefix); var localStorage = window.localStorage || unsafeWindow.localStorage; var isLocalStorageAvailable = function () {
return typeof (localStorage) !== 'undefined';
}; var getKeyPrefix = function () {
return keyPrefix;
}; //
// validates if there is a prefix defined for the keys
// and checks if the localStorage functionality is available or not
//
var makeChecks = function (key) {
var prefix = getKeyPrefix();
if (prefix === undefined) {
throw new Error('No prefix was defined, data cannot be saved');
} if (!isLocalStorageAvailable()) {
throw new Error('LocalStorage is not supported by your browser, data cannot be saved');
} // keys are always strings
var checkedKey = typeof (key) === 'string' ? key : JSON.stringify(key); return checkedKey;
}; //
// saves the value associated to the key into the localStorage
//
var addItem = function (key, value) {
var that = this;
try {
var checkedKey = makeChecks(key);
var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
localStorage.setItem(combinedKey, JSON.stringify(value));
} catch (err) {
console.log(err);
throw err;
}
}; //
// gets the value of the object saved to the key passed as parameter
//
var getItem = function (key) {
var that = this;
var result;
try {
var checkedKey = makeChecks(key);
var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
var resultAsJSON = localStorage.getItem(combinedKey);
result = JSON.parse(resultAsJSON);
} catch (err) {
console.log(err);
throw err;
}
return result;
}; //
// returns all the keys from the localStorage
//
var getAllKeys = function () {
var prefix = getKeyPrefix();
var results = []; if (prefix === undefined) {
throw new Error('No prefix was defined, data cannot be saved');
} if (!isLocalStorageAvailable()) {
throw new Error('LocalStorage is not supported by your browser, data cannot be saved');
} for (var key in localStorage) {
if (key.indexOf(prefix) === 0) {
var keyParts = key.split(delimiter);
results.push(keyParts[1]);
}
} return results;
}; //
// removes the value associated to the key from the localStorage
//
var removeItem = function (key) {
var that = this;
var result = false;
try {
var checkedKey = makeChecks(key);
var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
localStorage.removeItem(combinedKey);
result = true;
} catch (err) {
console.log(err);
throw err;
}
return result;
}; //
// removes all the values from the localStorage
//
var removeAll = function () {
var that = this; try {
var allKeys = that.getAllKeys();
for (var i = 0; i < allKeys.length; ++i) {
var checkedKey = makeChecks(allKeys[i]);
var combinedKey = that.getKeyPrefix() + delimiter + checkedKey;
localStorage.removeItem(combinedKey);
}
} catch (err) {
console.log(err);
throw err;
}
}; // make some of the functionalities public
return {
isLocalStorageAvailable: isLocalStorageAvailable,
getKeyPrefix: getKeyPrefix,
addItem: addItem,
getItem: getItem,
getAllKeys: getAllKeys,
removeItem: removeItem,
removeAll: removeAll
};
} // --------- THIRD PARTY CODE AREA END --------- var yadgUtil = {
exec: function (fn) {
var script = document.createElement('script');
script.setAttribute('type', 'application/javascript');
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
document.body.removeChild(script); // clean up
}, // handle for updating page css, taken from one of hateradio's scripts
addCSS: function (style) {
if (!this.style) {
this.style = document.createElement('style');
this.style.type = 'text/css';
(document.head || document.getElementsByTagName('head')[0]).appendChild(this.style);
}
this.style.appendChild(document.createTextNode(style + '\n'));
}, setValueIfSet: function (value, input, cond) {
if (cond) {
input.value = value;
} else {
input.value = '';
}
}, // negative count will remove, positive count will add given number of artist boxes
addRemoveArtistBoxes: function (count) {
if (count !== 0) {
if (count < 0) {
for (var i = 0; i < -count; i++) {
yadgUtil.exec(function () {
RemoveArtistField(); // eslint-disable-line new-cap
});
}
} else {
for (i = 0; i < count; i++) {
yadgUtil.exec(function () {
AddArtistField(); // eslint-disable-line new-cap
});
}
}
}
}, getOptionOffsets: function (select) {
var optionOffsets = {};
for (var j = 0; j < select.options.length; j++) {
optionOffsets[select.options[j].value] = select.options[j].index;
}
return optionOffsets;
}, storage: new LocalStorageWrapper('yadg'), settings: new LocalStorageWrapper('yadgSettings')
}; // very simple wrapper for XmlHttpRequest
function requester(url, method, callback, data, errorCallback) { // eslint-disable-line max-params
this.data = data;
this.url = url;
this.method = method;
if (!errorCallback) {
errorCallback = yadg.failedCallback;
} this.send = function () {
var details = {
url: this.url,
method: this.method,
onload: function (response) {
if (response.status === 200) {
callback(JSON.parse(response.responseText));
} else if (response.status === 401) {
yadg.failedAuthenticationCallback();
} else {
errorCallback();
}
},
onerror: errorCallback
};
if (method === 'POST') {
details.data = JSON.stringify(this.data);
} var headers = {
Accept: 'application/json',
'Content-Type': 'application/json'
}; if (yadgUtil.settings.getItem(factory.KEY_API_TOKEN)) {
headers.Authorization = 'Token ' + yadgUtil.settings.getItem(factory.KEY_API_TOKEN);
} details.headers = headers; GM.xmlHttpRequest (details); // eslint-disable-line new-cap
};
} var yadgSandbox = { KEY_LAST_WARNING: 'templateLastWarning', init: function (callback) {
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: yadg.yadgHost + '/static/js/jsandbox-worker.js',
onload: function (response) {
var script;
var dataURL = null;
if (response.status === 200) {
script = response.responseText;
var blob = new Blob([script], {type: 'application/javascript'});
var URL = window.URL || window.webkitURL;
if (!URL || !URL.createObjectURL) {
throw new Error('No no valid implementation of window.URL.createObjectURL found.');
}
dataURL = URL.createObjectURL(blob);
yadgSandbox.initCallback(dataURL);
yadgSandbox.loadSwig(callback);
} else {
yadgSandbox.initCallbackError();
}
},
onerror: function () {
yadgSandbox.initCallbackError();
}
});
}, loadSwig: function (callback) {
// importScripts for the web worker will not work in Firefox with cross-domain requests
// see: https://bugzilla.mozilla.org/show_bug.cgi?id=756589
// so download the Swig files manually with GM.xmlHttpRequest
GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: yadg.yadgHost + '/static/js/swig.min.js',
onload: function (response) {
if (response.status === 200) {
yadgSandbox.swigScript = response.responseText; GM.xmlHttpRequest ({ // eslint-disable-line new-cap
method: 'GET',
url: yadg.yadgHost + '/static/js/swig.custom.js',
onload: function (response) {
if (response.status === 200) {
yadgSandbox.swigCustomScript = response.responseText;
callback();
}
}
});
}
}
});
}, initializeSwig: function (dependencies) {
if (!(this.swigScript && this.swigCustomScript)) {
yadg.failedCallback();
return;
} yadgSandbox.exec({data: this.swigScript, onerror: yadg.failedCallback});
yadgSandbox.exec({data: this.swigCustomScript, onerror: yadg.failedCallback});
yadgSandbox.exec({data: 'var myswig = new swig.Swig({ loader: swig.loaders.memory(input.templates), autoescape: false }), i=0; yadg_filters.register_filters(myswig);', input: {templates: dependencies}});
}, renderTemplate: function (template, data, callback, error) {
var evalString = 'myswig.render(input.template, { locals: input.data, filename: \'scratchpad\' + (i++) })';
this.eval({data: evalString, callback: function (out) {
callback(out);
}, input: {template: template, data: data}, onerror: function (err) {
error(err);
}});
}, initCallback: function (dataUrl) {
JSandbox.url = dataUrl;
this.jsandbox = new JSandbox();
this.initError = false;
}, resetSandbox: function () {
this.jsandbox.terminate();
this.jsandbox = new JSandbox();
}, load: function (options) {
this.jsandbox.load(options);
}, exec: function (options) {
this.jsandbox.exec(options);
}, eval: function (options) {
this.jsandbox.eval(options);
}, initCallbackError: function () {
this.initError = true; var lastWarning = yadgUtil.storage.getItem(this.KEY_LAST_WARNING);
var now = new Date();
if (lastWarning === null || now.getTime() - (new Date(lastWarning)).getTime() > factory.CACHE_TIMEOUT) {
console.log('Could not load the necessary script files for executing YADG. If this error persists you might need to update the user script. You will only get this message once a day.');
yadgUtil.storage.addItem(this.KEY_LAST_WARNING, now);
}
}
}; factory = {
// storage keys for cache
KEY_LAST_CHECKED: 'lastChecked',
KEY_SCRAPER_LIST: 'scraperList',
KEY_FORMAT_LIST: 'formatList', // storage keys for settings
KEY_API_TOKEN: 'apiToken',
KEY_DEFAULT_TEMPLATE: 'defaultTemplate',
KEY_DEFAULT_TARGET: 'defaultTarget',
KEY_DESCRIPTION_TARGET: 'descriptionTarget',
KEY_DEFAULT_SCRAPER: 'defaultScraper',
KEY_REPLACE_DESCRIPTION: 'replaceDescriptionOn',
KEY_SETTINGS_INIT_VER: 'settingsInitializedVer',
KEY_FETCH_IMAGE: 'fetchImage',
KEY_AUTO_PREVIEW: 'autoPreview',
KEY_AUTO_REHOST: 'autoRehost', CACHE_TIMEOUT: 1000 * 60 * 60 * 24, // 24 hours UPDATE_PROGRESS: 0,
locations: [
{
name: 'pth_upload',
regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/upload\.php.*/i
},
{
name: 'pth_edit',
regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?action=editgroup&groupid=.*/i
},
{
name: 'pth_request',
regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=new/i
},
{
name: 'pth_request_edit',
regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/requests\.php\?action=edit&id=.*/i
},
{
name: 'pth_torrent_overview',
regex: /http(s)?:\/\/(.*\.)?redacted\.ch\/torrents\.php\?id=.*/i
},
{
name: 'waffles_upload',
regex: /http(s)?:\/\/(.*\.)?waffles\.ch\/upload\.php.*/i
},
{
name: 'waffles_request',
regex: /http(s)?:\/\/(.*\.)?waffles\.ch\/requests\.php\?do=add/i
}
], determineLocation: function (uri) {
for (var i = 0; i < this.locations.length; i++) {
if (this.locations[i].regex.test(uri)) {
return this.locations[i].name;
}
}
return null;
}, init: function () {
this.currentLocation = this.determineLocation(document.URL);
// only continue with the initialization if we found a valid location
if (this.currentLocation === null) {
return false;
}
this.insertIntoPage(this.getInputElements()); // set the necessary styles
this.setStyles(); // make sure we initialize the settings to the most recent version
this.initializeSettings(); // populate settings inputs
this.populateSettings(); // add the appropriate action for the button
var button = document.getElementById('yadg_submit');
button.addEventListener('click', function (e) {
e.preventDefault();
yadg.makeRequest();
if (factory.getFetchImageCheckbox().checked) {
fetchImage(null, function (data) {
insertImage(data, function () {
if (factory.getAutoRehostCheckbox() && factory.getAutoRehostCheckbox().checked) {
pthImgIt();
}
});
});
}
}, false); // add the action for the options toggle
var toggleLink = document.getElementById('yadg_toggle_options');
if (toggleLink !== null) {
toggleLink.addEventListener('click', function (e) {
e.preventDefault(); var optionsDiv = document.getElementById('yadg_options');
var display = optionsDiv.style.display; if (display === 'none' || display === '') {
optionsDiv.style.display = 'block';
} else {
optionsDiv.style.display = 'none';
}
});
} // add the action for the template select
var formatSelect = this.getFormatSelect();
if (formatSelect !== null) {
formatSelect.addEventListener('change', function () {
if (yadgRenderer.hasCached()) {
yadgRenderer.renderCached(this.value, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue);
}
});
} // // add the action for the target select
// var targetSelect = this.getTargetSelect();
// if (targetSelect !== null) {
// targetSelect.addEventListener('change', function (e) {
// var target = this.value;
// });
// } // add the action to the save settings link
var saveSettingsLink = document.getElementById('yadg_save_settings');
if (saveSettingsLink !== null) {
saveSettingsLink.addEventListener('click', function (e) {
e.preventDefault(); factory.saveSettings(); alert('Settings saved successfully.');
});
} // add the action to the clear cache link
var clearCacheLink = document.getElementById('yadg_clear_cache');
if (clearCacheLink !== null) {
clearCacheLink.addEventListener('click', function (e) {
e.preventDefault(); yadgUtil.storage.removeAll(); alert('Cache cleared. Please reload the page for this to take effect.');
});
} var lastChecked = yadgUtil.storage.getItem(factory.KEY_LAST_CHECKED);
if (lastChecked === null || (new Date()).getTime() - (new Date(lastChecked)).getTime() > factory.CACHE_TIMEOUT) {
// update the scraper and formats list
factory.UPDATE_PROGRESS = 1;
yadg.getScraperList(factory.setScraperSelect);
yadg.getFormatsList(factory.setFormatSelect);
} else {
factory.setScraperSelect(yadgUtil.storage.getItem(factory.KEY_SCRAPER_LIST));
factory.setFormatSelect(yadgUtil.storage.getItem(factory.KEY_FORMAT_LIST));
} return true;
}, getApiTokenInput: function () {
return document.getElementById('yadg_api_token');
}, getReplaceDescriptionCheckbox: function () {
return document.getElementById('yadg_options_replace');
}, getFetchImageCheckbox: function () {
return document.getElementById('yadg_options_image');
}, getAutoRehostCheckbox: function () {
return document.getElementById('yadg_options_rehost');
}, getAutoPreviewCheckbox: function () {
return document.getElementById('yadg_options_preview');
}, getReplaceDescriptionSettingKey: function () {
return this.makeReplaceDescriptionSettingsKey(this.currentLocation);
}, makeReplaceDescriptionSettingsKey: function (subKey) {
return this.KEY_REPLACE_DESCRIPTION + subKey.replace(/_/g, '');
}, initializeSettings: function () {
var settingsVer = yadgUtil.settings.getItem(factory.KEY_SETTINGS_INIT_VER);
var currentVer = 1; if (!settingsVer) {
settingsVer = 0;
} if (settingsVer < currentVer) {
// replace descriptions on upload and new request pages
var locations = [
'pth_upload',
'pth_request',
'waffles_upload',
'waffles_upload_new',
'waffles_request'
];
for (var i = 0; i < locations.length; i++) {
var loc = locations[i];
var replaceDescSettingKey = factory.makeReplaceDescriptionSettingsKey(loc); yadgUtil.settings.addItem(replaceDescSettingKey, true);
}
} yadgUtil.settings.addItem(factory.KEY_SETTINGS_INIT_VER, currentVer);
}, populateSettings: function () {
var apiToken = yadgUtil.settings.getItem(factory.KEY_API_TOKEN);
var replaceDesc = yadgUtil.settings.getItem(factory.getReplaceDescriptionSettingKey());
var fetchImage = yadgUtil.settings.getItem(factory.KEY_FETCH_IMAGE);
var autoRehost = yadgUtil.settings.getItem(factory.KEY_AUTO_REHOST);
var autoPreview = yadgUtil.settings.getItem(factory.KEY_AUTO_PREVIEW);
var descriptionTarget = yadgUtil.settings.getItem(factory.KEY_AUTO_PREVIEW); if (apiToken) {
var apiTokenInput = factory.getApiTokenInput();
apiTokenInput.value = apiToken;
} if (replaceDesc) {
var replaceDescCheckbox = factory.getReplaceDescriptionCheckbox();
replaceDescCheckbox.checked = true;
} if (fetchImage) {
var fetchImageCheckbox = factory.getFetchImageCheckbox();
fetchImageCheckbox.checked = true;
} if (autoRehost) {
var autoRehostCheckbox = factory.getAutoRehostCheckbox();
if (autoRehostCheckbox) {
autoRehostCheckbox.checked = true;
}
} if (autoPreview && window.location.href.match(/\/upload\.php/)) {
var autoPreviewCheckbox = factory.getAutoPreviewCheckbox();
autoPreviewCheckbox.checked = true;
}
}, saveSettings: function () {
var scraperSelect = factory.getScraperSelect();
var templateSelect = factory.getFormatSelect();
var targetSelect = factory.getTargetSelect();
var descriptionTargetSelect = factory.getDescriptionTargetSelect();
var apiTokenInput = factory.getApiTokenInput();
var replaceDescCheckbox = factory.getReplaceDescriptionCheckbox();
var fetchImageCheckbox = factory.getFetchImageCheckbox();
var autoRehostCheckbox = factory.getAutoRehostCheckbox();
var autoPreviewCheckbox = factory.getAutoPreviewCheckbox(); var currentScraper = null;
var currentTemplate = null;
var currentTarget = null;
var currentDescriptionTarget = null;
var apiToken = apiTokenInput.value.trim();
var replaceDescription = replaceDescCheckbox.checked;
var fetchImage = fetchImageCheckbox.checked;
if (autoRehostCheckbox) {
var autoRehost = autoRehostCheckbox.checked;
}
if (window.location.href.match(/\/upload\.php/)) {
var autoPreview = autoPreviewCheckbox.checked;
} if (scraperSelect.options.length > 0) {
currentScraper = scraperSelect.options[scraperSelect.selectedIndex].value;
} if (templateSelect.options.length > 0) {
currentTemplate = templateSelect.options[templateSelect.selectedIndex].value;
} if (targetSelect.options.length > 0) {
currentTarget = targetSelect.options[targetSelect.selectedIndex].value;
} if (descriptionTargetSelect.options.length > 0) {
currentDescriptionTarget = descriptionTargetSelect.options[descriptionTargetSelect.selectedIndex].value;
} if (currentScraper !== null) {
yadgUtil.settings.addItem(factory.KEY_DEFAULT_SCRAPER, currentScraper);
} if (currentTemplate !== null) {
yadgUtil.settings.addItem(factory.KEY_DEFAULT_TEMPLATE, currentTemplate);
} if (currentTarget !== null) {
yadgUtil.settings.addItem(factory.KEY_DEFAULT_TARGET, currentTarget);
} if (currentDescriptionTarget !== null) {
yadgUtil.settings.addItem(factory.KEY_DESCRIPTION_TARGET, currentDescriptionTarget);
} if (apiToken === '') {
yadgUtil.settings.removeItem(factory.KEY_API_TOKEN);
} else {
yadgUtil.settings.addItem(factory.KEY_API_TOKEN, apiToken);
} var replaceDescSettingKey = factory.getReplaceDescriptionSettingKey();
if (replaceDescription) {
yadgUtil.settings.addItem(replaceDescSettingKey, true);
} else {
yadgUtil.settings.removeItem(replaceDescSettingKey);
} if (fetchImage) {
yadgUtil.settings.addItem(factory.KEY_FETCH_IMAGE, true);
} else {
yadgUtil.settings.removeItem(factory.KEY_FETCH_IMAGE);
} if (autoRehost) {
yadgUtil.settings.addItem(factory.KEY_AUTO_REHOST, true);
} else if (!autoRehost && autoRehostCheckbox) {
yadgUtil.settings.removeItem(factory.KEY_AUTO_REHOST);
} if (autoPreview) {
yadgUtil.settings.addItem(factory.KEY_AUTO_PREVIEW, true);
} else if (!autoPreview && window.location.href.match(/\/upload\.php/)) {
yadgUtil.settings.removeItem(factory.KEY_AUTO_PREVIEW);
}
}, setDescriptionBoxValue: function (value) {
var descBox = factory.getDescriptionBox();
var replaceDescCheckbox = factory.getReplaceDescriptionCheckbox();
var replaceDesc = false; if (replaceDescCheckbox !== null) {
replaceDesc = replaceDescCheckbox.checked;
} if (descBox !== null && !Array.isArray(descBox)) {
if (!replaceDesc && /\S/.test(descBox.value)) { // check if the current description contains more than whitespace
descBox.value += '\n\n' + value;
} else {
descBox.value = value;
}
if (descBox.parentNode.nextSibling.nextSibling) {
var previewBtn = descBox.parentNode.nextSibling.nextSibling.firstChild.nextSibling;
if (previewBtn && previewBtn.value === 'Preview' && factory.getAutoPreviewCheckbox().checked) {
previewBtn.click();
}
}
} else if (Array.isArray(descBox)) {
for (var i = 0; i < descBox.length; i++) {
descBox[i].value = value;
var previewBtn = descBox[i].parentNode.nextSibling.nextSibling.firstChild.nextSibling;
if (previewBtn && previewBtn.value === 'Preview' && factory.getAutoPreviewCheckbox().checked) {
previewBtn.click();
}
}
}
}, getFormatSelect: function () {
return document.getElementById('yadg_format');
}, setDefaultFormat: function () {
var formatSelect = factory.getFormatSelect();
var formatOffsets = yadgUtil.getOptionOffsets(formatSelect); var defaultFormat = yadgUtil.settings.getItem(factory.KEY_DEFAULT_TEMPLATE);
if (defaultFormat !== null && defaultFormat in formatOffsets) {
formatSelect.selectedIndex = formatOffsets[defaultFormat];
} else {
// we have no settings so fall back to the hard coded defaults
switch (this.currentLocation) {
case 'waffles_upload':
case 'waffles_upload_new':
case 'waffles_request':
formatSelect.selectedIndex = formatOffsets[defaultWafflesFormat];
break; default:
formatSelect.selectedIndex = formatOffsets[defaultPTHFormat];
break;
}
}
}, getTargetSelect: function () {
return document.getElementById('yadg_target');
}, getDescriptionTargetSelect: function () {
return document.getElementById('yadg_description_target');
}, setDefaultTarget: function () {
var targetSelect = factory.getTargetSelect();
var targetOffsets = yadgUtil.getOptionOffsets(targetSelect); var defaultTarget = yadgUtil.settings.getItem(factory.KEY_DEFAULT_TARGET);
if (defaultTarget !== null && defaultTarget in targetOffsets) {
targetSelect.selectedIndex = targetOffsets[defaultTarget];
} else {
targetSelect.selectedIndex = targetOffsets[defaultPTHTarget];
}
}, setDefaultDescriptionTarget: function () {
var targetDescriptionSelect = factory.getDescriptionTargetSelect();
var targetDescriptionOffsets = yadgUtil.getOptionOffsets(targetDescriptionSelect); var defaultDescriptionTarget = yadgUtil.settings.getItem(factory.KEY_DESCRIPTION_TARGET);
if (defaultDescriptionTarget !== null && defaultDescriptionTarget in targetDescriptionOffsets) {
targetDescriptionSelect.selectedIndex = targetDescriptionOffsets[defaultDescriptionTarget];
} else {
targetDescriptionSelect.selectedIndex = targetDescriptionOffsets[defaultPTHDescriptionTarget];
}
}, getScraperSelect: function () {
return document.getElementById('yadg_scraper');
}, setDefaultScraper: function () {
var defaultScraper = yadgUtil.settings.getItem(factory.KEY_DEFAULT_SCRAPER);
if (defaultScraper !== null) {
var scraperSelect = factory.getScraperSelect();
var scraperOffsets = yadgUtil.getOptionOffsets(scraperSelect); if (defaultScraper in scraperOffsets) {
scraperSelect.selectedIndex = scraperOffsets[defaultScraper];
}
}
}, setScraperSelect: function (scrapers) {
var scraperSelect = factory.getScraperSelect(); factory.setSelect(scraperSelect, scrapers);
factory.setDefaultScraper(); if (factory.UPDATE_PROGRESS > 0) {
yadgUtil.storage.addItem(factory.KEY_SCRAPER_LIST, scrapers);
factory.UPDATE_PROGRESS |= 1 << 1; if (factory.UPDATE_PROGRESS === 7) {
yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
}
}
}, setFormatSelect: function (templates) {
var formatSelect = factory.getFormatSelect(); var nonUtility = [];
var saveTemplates = [];
for (var i = 0; i < templates.length; i++) {
if (factory.UPDATE_PROGRESS > 0) {
if (templates[i].name === 'What') {
templates[i].name = 'RED';
templates[i].nameFormatted = 'RED';
} else if (templates[i].name === 'What (Tracks only)') {
templates[i].name = 'RED (Tracks only)';
templates[i].nameFormatted = 'RED (Tracks only)';
} yadgTemplates.addTemplate(templates[i]); saveTemplates.push({
id: templates[i].id,
url: templates[i].url,
name: templates[i].name,
nameFormatted: templates[i].nameFormatted,
owner: templates[i].owner,
default: templates[i].default,
isUtility: templates[i].isUtility
});
} else {
if (templates[i].name === 'What') {
templates[i].name = 'PTH';
templates[i].nameFormatted = 'PTH';
} else if (templates[i].name === 'What (Tracks only)') {
templates[i].name = 'PTH (Tracks only)';
templates[i].nameFormatted = 'PTH (Tracks only)';
} yadgTemplates.addTemplateUrl(templates[i].id, templates[i].url);
} if (!templates[i].isUtility) {
nonUtility.push(templates[i]);
}
} factory.setSelect(formatSelect, nonUtility);
factory.setDefaultFormat();
factory.setDefaultTarget();
factory.setDefaultDescriptionTarget(); if (factory.UPDATE_PROGRESS > 0) {
yadgUtil.storage.addItem(factory.KEY_FORMAT_LIST, saveTemplates);
factory.UPDATE_PROGRESS |= 1 << 2; if (factory.UPDATE_PROGRESS === 7) {
yadgUtil.storage.addItem(factory.KEY_LAST_CHECKED, new Date());
}
}
}, setSelect: function (select, data) {
select.options.length = data.length; for (var i = 0; i < data.length; i++) {
// we are not using the javascript constructor to create an Option instance because this will create an
// incompatibility with jQuery in Chrome which will make it impossible to add a new artist field on redacted.ch
var o = document.createElement('option');
if ('nameFormatted' in data[i]) {
o.text = data[i].nameFormatted;
} else {
o.text = data[i].name;
}
o.value = data[i].value || data[i].id;
o.selected = data[i].default;
select.options[i] = o;
if (data[i].default) {
select.selectedIndex = i;
}
if (data[i].url) {
o.setAttribute('data-url', data[i].url);
}
}
}, setStyles: function () {
// general styles
yadgUtil.addCSS('div#yadg_options{ display:none; margin-top:3px; } input#yadg_input,input#yadg_submit,label#yadg_format_label,a#yadg_scraper_info { margin-right: 5px } div#yadg_response { margin-top:3px; } select#yadg_scraper { margin-right: 2px } #yadg_options_template,#yadg_options_api_token,#yadg_options_replace_div { margin-bottom: 3px; } .add_form[name="yadg"] input,.add_form[name="yadg"] select { width: 90%; margin: 2px 0 !important; }'); // location specific styles will go here
switch (this.currentLocation) {
case 'waffles_upload':
yadgUtil.addCSS('div#yadg_response ul { margin-left: 0 !important; padding-left: 0 !important; }');
break; case 'waffles_request':
yadgUtil.addCSS('div#yadg_response ul { margin-left: 0 !important; padding-left: 0 !important; }');
break; default: break;
}
}, getInputElements: function () {
var buttonHTML = '<input type="submit" value="Fetch" id="yadg_submit"/>';
var scraperSelectHTML = '<select name="yadg_scraper" id="yadg_scraper"></select>';
var optionsHTML = '<div id="yadg_options"><div id="yadg_options_template"><label for="yadg_format" id="yadg_format_label">Template:</label><select name="yadg_format" id="yadg_format"></select></div><div id="yadg_options_target"><label for="yadg_target" id="yadg_target_label">Edition:</label><select name="yadg_target" id="yadg_target"><option value="original">Original</option><option value="other">Other</option></select></div><div id="yadg_options_description_target"><label for="yadg_description_target" id="yadg_description_target_label">Description:</label><select name="yadg_description_target" id="yadg_description_target"><option value="album">Album</option><option value="release">Release</option><option value="both">Both</option></select></div><div id="yadg_options_api_token"><label for="yadg_api_token" id="yadg_api_token_label">API token (<a href="https://yadg.cc/api/token" target="_blank">Get one here</a>):</label> <input type="text" name="yadg_api_token" id="yadg_api_token" size="50" /></div><div id="yadg_options_replace_div"><input type="checkbox" name="yadg_options_replace" id="yadg_options_replace" /> <label for="yadg_options_replace" id="yadg_options_replace_label">Replace descriptions on this page</label></div><div id="yadg_options_image_div"><input type="checkbox" name="yadg_options_image" id="yadg_options_image" /> <label for="yadg_options_image" id="yadg_options_image_label">Auto fetch Album Art (Bandcamp, Beatport, Discogs, iTunes, Junodownload, Metal-Archives, MusicBrainz)</label></div>';
if (document.getElementsByClassName('rehost_it_cover')[0]) {
optionsHTML += '<div id="yadg_options_rehost_div"><input type="checkbox" name="yadg_options_rehost" id="yadg_options_rehost" /> <label for="yadg_options_rehost" id="yadg_options_rehost_label">Auto rehost with <a href="https://redacted.ch/forums.php?action=viewthread&threadid=1992">[User Script] PTPIMG URL uploader</a></label></div>';
}
if (window.location.href.match(/\/upload\.php/)) {
optionsHTML += '<div id="yadg_options_preview_div"><input type="checkbox" name="yadg_options_preview" id="yadg_options_preview" /> <label for="yadg_options_preview" id="yadg_options_preview_label">Auto preview description</label></div>';
}
optionsHTML += '<div id="yadg_options_links"><a id="yadg_save_settings" href="#" title="Save the currently selected scraper and template as default for this site and save the given API token.">Save settings</a> <span class="yadg_separator">|</span> <a id="yadg_clear_cache" href="#">Clear cache</a></div></div>';
var inputHTML = '<input type="text" name="yadg_input" id="yadg_input" size="60" />';
var responseDivHTML = '<div id="yadg_response"></div>';
var toggleOptionsLinkHTML = '<a id="yadg_toggle_options" href="#">Toggle options</a>';
var scraperInfoLink = '<a id="yadg_scraper_info" href="https://yadg.cc/available-scrapers" target="_blank" title="Get additional information on the available scrapers">[?]</a>'; switch (this.currentLocation) {
case 'pth_upload':
var tr = document.createElement('tr');
tr.className = 'yadg_tr';
tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
return tr; case 'pth_edit':
var div = document.createElement('div');
div.className = 'yadg_div';
div.innerHTML = '<h3 class="label">YADG:</h3>\n' + inputHTML + '\n' + scraperSelectHTML + '\n' + scraperInfoLink + '\n' + buttonHTML + '\n' + toggleOptionsLinkHTML + '\n' + optionsHTML + '\n' + responseDivHTML;
return div; case 'pth_torrent_overview':
div = document.createElement('div');
div.id = 'yadg_div';
div.className = 'box';
div.innerHTML = '<div class="head"><strong>YADG</strong></div>\n<div class="body">\n<form class="add_form" name="yadg" method="post">\n<input type="text" name="yadg_input" id="yadg_input" />\n' + scraperSelectHTML + '\n' + scraperInfoLink + '\n' + buttonHTML + '\n' + toggleOptionsLinkHTML + '\n' + optionsHTML + '\n' + responseDivHTML;
return div; case 'pth_request':
case 'pth_request_edit':
tr = document.createElement('tr');
tr.className = 'yadg_tr';
tr.innerHTML = '<td class="label">YADG:</td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
return tr; case 'waffles_upload':
tr = document.createElement('tr');
tr.className = 'yadg_tr';
tr.innerHTML = '<td class="heading" valign="top" align="right"><label for="yadg_input">YADG:</label></td><td>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
return tr; case 'waffles_upload_new':
var p = document.createElement('p');
p.className = 'yadg_p';
p.innerHTML = '<label for="yadg_input">YADG:</label>' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML;
return p; case 'waffles_request':
tr = document.createElement('tr');
tr.className = 'yadg_tr';
tr.innerHTML = '<td style="text-align:left;width:100px;">YADG:</td><td style="text-align:left;">' + inputHTML + scraperSelectHTML + scraperInfoLink + buttonHTML + toggleOptionsLinkHTML + optionsHTML + responseDivHTML + '</td>';
return tr; default:
// this should actually never happen
return document.createElement('div');
}
}, insertIntoPage: function (element) {
switch (this.currentLocation) {
case 'pth_upload':
var yearTr = document.getElementById('year_tr');
yearTr.parentNode.insertBefore(element, yearTr);
break; case 'pth_edit':
var summaryInput = document.getElementsByName('summary')[0];
summaryInput.parentNode.insertBefore(element, summaryInput.nextSibling.nextSibling);
break; case 'pth_torrent_overview':
var addArtistsBox = document.getElementsByClassName('box_addartists')[0];
addArtistsBox.parentNode.insertBefore(element, addArtistsBox.nextSibling.nextSibling);
break; case 'pth_request':
case 'pth_request_edit':
var artistTr = document.getElementById('artist_tr');
artistTr.parentNode.insertBefore(element, artistTr);
break; case 'waffles_upload':
var submitButton = document.getElementsByName('submit')[0];
submitButton.parentNode.parentNode.parentNode.insertBefore(element, submitButton.parentNode.parentNode);
break; case 'waffles_upload_new':
var h4s = document.getElementsByTagName('h4');
var div;
for (var i = 0; i < h4s.length; i++) {
if (h4s[i].innerHTML.indexOf('read the rules') !== -1) {
div = h4s[i].parentNode;
break;
}
}
div.appendChild(element);
break; case 'waffles_request':
var categorySelect = document.getElementsByName('category')[0];
categorySelect.parentNode.parentNode.parentNode.insertBefore(element, categorySelect.parentNode.parentNode);
break; default:
break;
}
}, getDescriptionBox: function () {
switch (this.currentLocation) {
case 'pth_upload':
if (factory.getDescriptionTargetSelect().value === 'album') {
return document.getElementById('album_desc');
} else if (factory.getDescriptionTargetSelect().value === 'release') {
return document.getElementById('release_desc');
} else if (factory.getDescriptionTargetSelect().value === 'both') {
return [document.getElementById('album_desc'), document.getElementById('release_desc')];
}
break; case 'pth_edit':
return document.getElementsByName('body')[0]; case 'pth_torrent_overview':
if (!{}.hasOwnProperty.call(this, 'dummybox')) {
this.dummybox = document.createElement('div');
}
return this.dummybox; case 'pth_request':
case 'pth_request_edit':
return document.getElementsByName('description')[0]; case 'waffles_upload':
return document.getElementById('descr'); case 'waffles_upload_new':
return document.getElementById('id_descr'); case 'waffles_request':
return document.getElementsByName('information')[0]; default:
// that should actually never happen
return document.createElement('div');
}
}, getFormFillFunction: function () {
var currentTarget = factory.getTargetSelect().value;
switch (this.currentLocation) {
case 'pth_upload':
var f = function (rawData) {
if (currentTarget === 'other') {
var remaster = document.getElementById('remaster');
var albumTitleInput = document.getElementById('title');
var yearInput = document.getElementById('remaster_year');
var labelInput = document.getElementById('remaster_record_label');
var catalogInput = document.getElementById('remaster_catalogue_number');
remaster.checked = 'checked';
unsafeWindow.Remaster(); // eslint-disable-line new-cap
unsafeWindow.CheckYear(); // eslint-disable-line new-cap
} else {
albumTitleInput = document.getElementById('title');
yearInput = document.getElementById('year');
labelInput = document.getElementById('record_label');
catalogInput = document.getElementById('catalogue_number');
} if (/itunes/.test(rawData.url)) {
var releaseTypeInput = document.getElementById('releasetype');
switch (true) {
case /.+ - Single$/.test(rawData.title):
rawData.title = rawData.title.replace(/ - Single$/, '');
if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
releaseTypeInput.value = 9;
}
break;
case /.+ - EP$/.test(rawData.title):
rawData.title = rawData.title.replace(/ - EP$/, '');
if (releaseTypeInput.getAttribute('disabled') !== 'disabled') {
releaseTypeInput.value = 5;
}
break;
default:
break;
}
} var artistInputs = document.getElementsByName('artists[]');
var tagsInput = document.getElementById('tags');
var data = yadg.prepareRawResponse(rawData);
var nullArtistCount = 0; if (artistInputs[0].getAttribute('disabled') !== 'disabled') {
if (data.artists === false) {
for (var i = 0; i < artistInputs.length; i++) {
artistInputs[i].value = '';
}
} else {
var inputIdx = 0; yadgUtil.addRemoveArtistBoxes(data.effective_artist_count - artistInputs.length); artistInputs = document.getElementsByName('artists[]'); for (i = 0; i < data.artist_keys.length; i++) {
var artistKey = data.artist_keys[i];
if (artistKey === 'null') {
nullArtistCount++;
continue;
}
var artistTypes = data.artists[artistKey]; for (var j = 0; j < artistTypes.length; j++) {
var artistType = artistTypes[j];
var artistInput = artistInputs[inputIdx];
var typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') {
typeSelect = typeSelect.nextSibling;
} artistInput.value = artistKey; var optionOffsets = yadgUtil.getOptionOffsets(typeSelect); if (artistType === 'main') {
typeSelect.selectedIndex = optionOffsets[1];
} else if (artistType === 'guest') {
typeSelect.selectedIndex = optionOffsets[2];
} else if (artistType === 'remixer') {
typeSelect.selectedIndex = optionOffsets[3];
} else {
// we don't know this artist type, default to "main"
typeSelect.selectedIndex = optionOffsets[1];
}
// next artist input
inputIdx += 1;
}
}
if (nullArtistCount > 0) {
yadgUtil.addRemoveArtistBoxes(nullArtistCount *= -1);
}
}
} if (tagsInput.getAttribute('disabled') !== 'disabled') {
if (data.tags === false) {
tagsInput.value = '';
} else {
var tagsArray = data.tag_string.split(', ');
var tagsUnique = tagsArray.filter(function (elem, index, self) {
return index === self.indexOf(elem);
});
tagsInput.value = tagsUnique.join(',').toLowerCase();
}
} if (yearInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
}
if (albumTitleInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.title, albumTitleInput, data.title !== false);
}
if (labelInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.label, labelInput, data.label !== false);
}
if (catalogInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.catalog, catalogInput, data.catalog !== false);
}
};
return f; case 'pth_edit':
f = function (rawData) {
var summaryInput = document.getElementsByName('summary')[0];
var yearInput = document.getElementsByName('year')[0];
var labelInput = document.getElementsByName('record_label')[0];
var catalogInput = document.getElementsByName('catalogue_number')[0];
var data = yadg.prepareRawResponse(rawData); summaryInput.value = 'YADG Update';
if (yearInput && yearInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
}
if (labelInput && labelInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.label, labelInput, data.label !== false);
}
if (catalogInput && catalogInput.getAttribute('disabled') !== 'disabled') {
yadgUtil.setValueIfSet(data.catalog, catalogInput, data.catalog !== false);
}
};
return f; case 'pth_torrent_overview':
f = function (rawData) {
var artistInputs = document.getElementsByName('aliasname[]');
var data = yadg.prepareRawResponse(rawData); if (data.artists === false) {
for (var i = 0; i < artistInputs.length; i++) {
artistInputs[i].value = '';
}
} else {
var inputIdx = 0; yadgUtil.addRemoveArtistBoxes(data.effective_artist_count - artistInputs.length); artistInputs = document.getElementsByName('aliasname[]'); for (i = 0; i < data.artist_keys.length; i++) {
var artistKey = data.artist_keys[i];
var artistTypes = data.artists[artistKey]; for (var j = 0; j < artistTypes.length; j++) {
var artistType = artistTypes[j];
var artistInput = artistInputs[inputIdx];
var typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') {
typeSelect = typeSelect.nextSibling;
} artistInput.value = artistKey; var optionOffsets = yadgUtil.getOptionOffsets(typeSelect); if (artistType === 'main') {
typeSelect.selectedIndex = optionOffsets[1];
} else if (artistType === 'guest') {
typeSelect.selectedIndex = optionOffsets[2];
} else if (artistType === 'remixer') {
typeSelect.selectedIndex = optionOffsets[3];
} else {
// we don't know this artist type, default to "main"
typeSelect.selectedIndex = optionOffsets[1];
} // next artist input
inputIdx += 1;
}
}
}
};
return f; case 'pth_request':
case 'pth_request_edit':
f = function (rawData) {
var artistInputs = document.getElementsByName('artists[]');
var albumTitleInput = document.getElementsByName('title')[0];
var yearInput = document.getElementsByName('year')[0];
var labelInput = document.getElementsByName('recordlabel')[0];
var catalogInput = document.getElementsByName('cataloguenumber')[0];
var tagsInput = document.getElementById('tags');
var data = yadg.prepareRawResponse(rawData);
var nullArtistCount = 0; if (data.artists === false) {
for (var i = 0; i < artistInputs.length; i++) {
artistInputs[i].value = '';
}
} else {
var inputIdx = 0; yadgUtil.addRemoveArtistBoxes(data.effective_artist_count - artistInputs.length); artistInputs = document.getElementsByName('artists[]'); for (i = 0; i < data.artist_keys.length; i++) {
var artistKey = data.artist_keys[i];
var artistTypes = data.artists[artistKey];
if (artistKey === 'null') {
nullArtistCount++;
continue;
} for (var j = 0; j < artistTypes.length; j++) {
var artistType = artistTypes[j];
var artistInput = artistInputs[inputIdx];
var typeSelect = artistInput.nextSibling; while (typeSelect.tagName !== 'SELECT') {
typeSelect = typeSelect.nextSibling;
} artistInput.value = artistKey; var optionOffsets = yadgUtil.getOptionOffsets(typeSelect); if (artistType === 'main') {
typeSelect.selectedIndex = optionOffsets[1];
} else if (artistType === 'guest') {
typeSelect.selectedIndex = optionOffsets[2];
} else if (artistType === 'remixer') {
typeSelect.selectedIndex = optionOffsets[3];
} else {
// we don't know this artist type, default to "main"
typeSelect.selectedIndex = optionOffsets[1];
} // next artist input
inputIdx += 1;
}
}
if (nullArtistCount > 0) {
yadgUtil.addRemoveArtistBoxes(nullArtistCount *= -1);
}
} if (data.tags === false) {
tagsInput.value = '';
} else {
tagsInput.value = data.tag_string.toLowerCase();
} yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
yadgUtil.setValueIfSet(data.title, albumTitleInput, data.title !== false);
yadgUtil.setValueIfSet(data.label, labelInput, data.label !== false);
yadgUtil.setValueIfSet(data.catalog, catalogInput, data.catalog !== false);
};
return f; case 'waffles_upload':
f = function (rawData) {
var artistInput = document.getElementsByName('artist')[0];
var albumTitleInput = document.getElementsByName('album')[0];
var yearInput = document.getElementsByName('year')[0];
var vaCheckbox = document.getElementById('va');
var tagsInput = document.getElementById('tags');
var data = yadg.prepareRawResponse(rawData); if (data.artists === false) {
vaCheckbox.checked = false;
artistInput.value = '';
} else if (data.is_various) {
artistInput.value = '';
vaCheckbox.checked = true;
} else {
artistInput.value = data.flat_artistString;
vaCheckbox.checked = false;
} yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
yadgUtil.setValueIfSet(data.title, albumTitleInput, data.title !== false); if (data.tags === false) {
tagsInput.value = '';
} else {
tagsInput.value = data.tag_string_nodots.toLowerCase();
} yadgUtil.exec(function () {
formatName();
});
};
return f; case 'waffles_upload_new':
f = function (rawData) {
var artistInput = document.getElementById('id_artist');
var albumTitleInput = document.getElementById('id_album');
var yearInput = document.getElementById('id_year');
var vaCheckbox = document.getElementById('id_va');
var tagsInput = document.getElementById('id_tags');
var data = yadg.prepareRawResponse(rawData); if (data.artists === false) {
if (vaCheckbox.checked) {
vaCheckbox.click();
}
artistInput.value = '';
} else if (data.is_various) {
if (!vaCheckbox.checked) {
vaCheckbox.click();
}
} else {
if (vaCheckbox.checked) {
vaCheckbox.click();
}
artistInput.value = data.flat_artistString;
} yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
yadgUtil.setValueIfSet(data.title, albumTitleInput, data.title !== false); if (data.tags === false) {
tagsInput.value = '';
} else {
tagsInput.value = data.tag_string_nodots.toLowerCase();
}
};
return f; case 'waffles_request':
f = function (rawData) {
var artistInput = document.getElementsByName('artist')[0];
var albumTitleInput = document.getElementsByName('title')[0];
var yearInput = document.getElementsByName('year')[0];
var data = yadg.prepareRawResponse(rawData); if (data.artists === false) {
artistInput.value = '';
} else if (data.is_various) {
artistInput.value = 'Various Artists';
} else {
artistInput.value = data.flat_artistString;
} yadgUtil.setValueIfSet(data.year, yearInput, data.year !== false);
yadgUtil.setValueIfSet(data.title, albumTitleInput, data.title !== false);
};
return f; default:
// that should actually never happen
return function () {};
}
}
}; yadgTemplates = {
_templates: {},
_templateUrls: {}, getTemplate: function (id, callback) {
if (id in this._templates) {
callback(this._templates[id]);
} else if (id in this._templateUrls) {
var request = new requester(this._templateUrls[id], 'GET', function (template) { // eslint-disable-line new-cap
yadgTemplates.addTemplate(template);
callback(template);
}, null, yadgTemplates.errorTemplate);
request.send();
} else {
this.errorTemplate();
}
}, addTemplate: function (template) {
this._templates[template.id] = template;
}, addTemplateUrl: function (id, url) {
this._templateUrls[id] = url;
}, errorTemplate: function () {
yadg.printError('Could not get template. Please choose another one.', true);
}
}; yadgRenderer = {
_lastData: null,
_lastTemplateId: null, render: function (templateId, data, callback, errorCallback) {
this._lastData = data;
var newTemplate = this._lastTemplateId !== templateId;
this._lastTemplateId = templateId; yadgTemplates.getTemplate(templateId, function (template) {
// the new template might have different dependencies, so initialize Swig with those
if (newTemplate) {
yadgSandbox.resetSandbox();
yadgSandbox.initializeSwig(template.dependencies);
}
template.code = template.code.replace('https://what.cd', 'https://redacted.ch');
yadgSandbox.renderTemplate(template.code, data, callback, errorCallback);
});
}, renderCached: function (templateId, callback, errorCallback) {
if (this.hasCached()) {
this.render(templateId, this._lastData, callback, errorCallback);
}
}, hasCached: function () {
return this._lastData !== null;
}, clearCached: function () {
this._lastData = null;
}
}; yadg = {
yadgHost: 'https://yadg.cc',
baseURI: '/api/v2/', standardError: 'Sorry, an error occured. Please try again. If this error persists the user script might need updating.',
authenticationError: 'Your API token is invalid. Please provide a valid API token or remove the current one.',
lastStateError: false, isBusy: false, init: function () {
this.scraperSelect = document.getElementById('yadg_scraper');
this.formatSelect = document.getElementById('yadg_format');
this.input = document.getElementById('yadg_input');
this.targetSelect = document.getElementById('yadg_target');
this.targetDescriptionSelect = document.getElementById('yadg_description_target');
this.responseDiv = document.getElementById('yadg_response');
this.button = document.getElementById('yadg_submit');
}, getBaseURL: function () {
return this.yadgHost + this.baseURI;
}, getScraperList: function (callback) {
var url = this.getBaseURL() + 'scrapers/'; var request = new requester(url, 'GET', callback); // eslint-disable-line new-cap request.send();
}, getFormatsList: function (callback) {
var url = this.getBaseURL() + 'templates/'; this.getTemplates(url, [], callback);
}, getTemplates: function (url, templates, callback) {
var request = new requester(url, 'GET', function (data) { // eslint-disable-line new-cap
for (var i = 0; i < data.results.length; i++) {
templates.push(data.results[i]);
}
if (data.next === null) {
callback(templates);
} else {
yadg.getTemplates(data.next, templates, callback);
}
}); request.send();
}, makeRequest: function (params) {
if (this.isBusy) {
return;
} var data;
if (params) {
data = params;
} else {
data = {
scraper: this.scraperSelect.options[this.scraperSelect.selectedIndex].value,
input: this.input.value
};
}
var url = this.getBaseURL() + 'query/'; if (data.input !== '') {
var request = new requester(url, 'POST', function (result) { // eslint-disable-line new-cap
yadg.getResult(result.url);
}, data);
this.busyStart();
request.send();
}
}, getResult: function (resultUrl) {
var request = new requester(resultUrl, 'GET', function (response) { // eslint-disable-line new-cap
if (response.status === 'done') {
if (response.data.type === 'ReleaseResult') {
var templateId = yadg.formatSelect.options[yadg.formatSelect.selectedIndex].value;
yadgRenderer.render(templateId, response, factory.setDescriptionBoxValue, factory.setDescriptionBoxValue); if (yadg.lastStateError === true) {
yadg.responseDiv.innerHTML = '';
yadg.lastStateError = false;
} var fillFunc = factory.getFormFillFunction();
fillFunc(response.data);
} else if (response.data.type === 'ListResult') {
var ul = document.createElement('ul');
ul.id = 'yadg_release_list'; var releaseList = response.data.items;
for (var i = 0; i < releaseList.length; i++) {
var name = releaseList[i].name;
var info = releaseList[i].info;
var queryParams = releaseList[i].queryParams;
var releaseUrl = releaseList[i].url; var li = document.createElement('li');
var a = document.createElement('a'); a.textContent = name;
a.params = queryParams;
a.href = releaseUrl; a.addEventListener('click', function (e) {
e.preventDefault();
yadg.makeRequest(this.params);
if (factory.getFetchImageCheckbox().checked) {
fetchImage(this.href, function (data) {
insertImage(data, function () {
if (factory.getAutoRehostCheckbox() && factory.getAutoRehostCheckbox().checked) {
pthImgIt();
}
});
});
}
}, false); li.appendChild(a);
li.appendChild(document.createElement('br'));
li.appendChild(document.createTextNode(info)); ul.appendChild(li);
} if (ul.childNodes.length === 0) {
yadg.printError('Sorry, there were no matches.');
} else {
yadg.responseDiv.innerHTML = '';
yadg.responseDiv.appendChild(ul);
yadg.lastStateError = false; // we got a ListResult so clear the last ReleaseResult from the render cache
yadgRenderer.clearCached();
}
} else if (response.data.type === 'NotFoundResult') {
yadg.printError('I could not find the release with the given ID. You may want to try again with another one.');
} else {
yadg.printError('Something weird happened. Please try again');
}
yadg.busyStop();
} else if (response.status === 'failed') {
yadg.failedCallback();
} else {
var delay = function () {
yadg.getResult(response.url);
};
window.setTimeout(delay, 1000);
}
});
request.send();
}, printError: function (message, templateError) {
this.responseDiv.innerHTML = '';
this.responseDiv.appendChild(document.createTextNode(message));
if (!templateError) {
this.lastStateError = true; // there was a non template related error, so for consistencies sake clear the last ReleaseResult from the
// render cache
yadgRenderer.clearCached();
}
}, failedCallback: function () {
yadg.printError(yadg.standardError);
yadg.busyStop();
}, failedAuthenticationCallback: function () {
yadg.printError(yadg.authenticationError);
yadg.busyStop();
}, busyStart: function () {
this.isBusy = true;
this.button.setAttribute('disabled', true);
this.button.value = 'Please wait...';
this.input.setAttribute('disabled', true);
this.scraperSelect.setAttribute('disabled', true);
this.formatSelect.setAttribute('disabled', true);
this.targetSelect.setAttribute('disabled', true);
}, busyStop: function () {
this.button.removeAttribute('disabled');
this.button.value = 'Fetch';
this.input.removeAttribute('disabled');
this.scraperSelect.removeAttribute('disabled');
this.formatSelect.removeAttribute('disabled');
this.targetSelect.removeAttribute('disabled');
this.isBusy = false;
}, prepareRawResponse: function (rawData) { // eslint-disable-line complexity
var result = {}; result.artists = false;
result.year = false;
result.title = false;
result.label = false;
result.catalog = false;
result.genre = false;
result.style = false;
result.tags = false;
result.is_various = false; // eslint-disable-line camelcase
result.flat_artistString = false; // eslint-disable-line camelcase if (rawData.artists.length > 0) {
result.artists = {}; for (var i = 0; i < rawData.artists.length; i++) {
var artist = rawData.artists[i];
if (artist.isVarious) {
result.is_various = true; // eslint-disable-line camelcase
} else {
result.artists[artist.name] = artist.types;
}
}
}
if (rawData.discs.length > 0) {
for (var k = 0; k < rawData.discs.length; k++) {
var disc = rawData.discs[k];
for (var l = 0; l < disc.tracks.length; l++) {
var track = disc.tracks[l];
for (var m = 0; m < track.artists.length; m++) {
var name = track.artists[m].name;
var type = track.artists[m].types; var newTypes = null;
if (name in result.artists) {
newTypes = result.artists[name].concat(type);
// deduplicate new types array
for (i = 0; i < newTypes.length; ++i) {
for (var j = i + 1; j < newTypes.length; ++j) {
if (newTypes[i] === newTypes[j]) {
newTypes.splice(j--, 1);
}
}
}
} else {
newTypes = type;
} result.artists[name] = newTypes;
}
}
}
}
for (i = 0; i < rawData.releaseEvents.length; i++) {
var event = rawData.releaseEvents[i];
if (event.date) {
result.year = event.date.match(/\d{4}/)[0];
if (result.year.length === 4) {
break;
} else {
result.year = false;
}
}
}
if (rawData.title) {
result.title = rawData.title;
}
if (rawData.labelIds.length > 0) {
var labelId = rawData.labelIds[0];
if (labelId.label) {
result.label = labelId.label;
}
if (labelId.catalogueNrs.length > 0) {
result.catalog = labelId.catalogueNrs[0];
}
}
if (rawData.genres.length > 0) {
result.genre = rawData.genres;
}
if (rawData.styles.length > 0) {
result.style = rawData.styles;
}
if (result.genre !== false && result.style !== false) {
result.tags = rawData.genres.concat(rawData.styles);
} else if (result.genre !== false) {
result.tags = rawData.genres;
} else if (result.style !== false) {
result.tags = rawData.styles;
} if (result.tags !== false) {
result.tag_string = ''; // eslint-disable-line camelcase
result.tag_string_nodots = ''; // eslint-disable-line camelcase for (i = 0; i < result.tags.length; i++) {
result.tag_string += result.tags[i].replace(/\s+/g, '.'); // eslint-disable-line camelcase
result.tag_string_nodots += result.tags[i].replace(/\s+/g, ' '); // eslint-disable-line camelcase
if (i !== result.tags.length - 1) {
result.tag_string += ', '; // eslint-disable-line camelcase
result.tag_string_nodots += ', '; // eslint-disable-line camelcase
}
}
} if (result.artists !== false) {
// count the artists
result.artists_length = 0; // eslint-disable-line camelcase
result.artist_keys = []; // eslint-disable-line camelcase
result.effective_artist_count = 0; // eslint-disable-line camelcase for (i in result.artists) {
if ({}.hasOwnProperty.call(result.artists, i)) {
result.artists_length++;
result.artist_keys.push(i);
result.effective_artist_count += result.artists[i].length; // eslint-disable-line camelcase
}
}
} if (result.artists_length === 0) {
result.artists = false;
} else {
// create a flat string of all the main artists
var artistString = ''; for (i = 0; i < result.artists_length; i++) {
if (result.artists[result.artist_keys[i]].indexOf('main') !== -1) {
if (artistString !== '' && i < result.artists_length - 2) {
artistString += ', ';
} else if (artistString !== '' && i < result.artists_length - 1) {
artistString += ' & ';
}
artistString += result.artist_keys[i];
}
} result.flat_artistString = artistString; // eslint-disable-line camelcase
} return result;
}
}; yadgSandbox.init(function () {
if (factory.init()) { // returns true if we run on a valid location
yadg.init();
}
});
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
22-Ноя-17 00:27
(спустя 4 часа)
maximus_lt
Сейчас есть время только на свои скрипты, а этот на 2000+ строк не потяну, к тому же нет ни Violentmonkey, ни Maxthon.
|
|
RoxMarty
Стаж: 17 лет 7 месяцев Сообщений: 14622
|
RoxMarty ·
22-Ноя-17 00:51
(спустя 23 мин., ред. 22-Ноя-17 00:51)
unchqua
Спасибо за труды. Всё нужное отлично работает! P.S. Правда сейчас из 12 обновлённых тем (вкладок) - две открылись совершенно пустыми и даже обновление страницы не помогает. Возможно баг браузера... буду тестить дальше
|
|
maximus_lt
Стаж: 17 лет 5 месяцев Сообщений: 6144
|
maximus_lt ·
22-Ноя-17 03:43
(спустя 2 часа 52 мин.)
unchqua, будем надеяться, что решат проблему, т.к. скрипт BBCode, Gazelle Snatched работает, а этот отказался.
|
|
megane68
Стаж: 16 лет 6 месяцев Сообщений: 19966
|
megane68 ·
14-Дек-17 06:27
(спустя 22 дня)
|
|
Аndy
Стаж: 16 лет 3 месяца Сообщений: 52867
|
Аndy ·
14-Дек-17 07:48
(спустя 1 час 21 мин.)
Под Palemoon 27.6.2x64 на 3.30rc3 YADG перестал работать (
|
|
maximus_lt
Стаж: 17 лет 5 месяцев Сообщений: 6144
|
maximus_lt ·
30-Дек-17 21:54
(спустя 16 дней)
unchqua писал(а):
74251009Рутрекер 21. Чёрный список входящих сообщений ЛС. Либо скрытие и удаление, либо только скрытие. Подробнее.
скрытый текст
Код:
// ==UserScript==
// @name Рутрекер 21. Чёрный список входящих сообщений ЛС.
// @namespace http://www.unchqua.ru/ns/greasemonkey
// @include *://rutr.life/forum/*
// @include *://rutracker.net/forum/*
// @include *://rutracker.cr/forum/*
// @include *://rutracker.nl/forum/*
// @require https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js
// @version 1
// @grant none
// ==/UserScript== (function(){ var $ = jQuery.noConflict(true); // Заполнение элемента списка фильтруемых пользователей.
var update_list = function(blacklisted) {
var list = $("#rto21-list");
list.empty();
for (idx = 0; idx < blacklisted.length; idx++) {
var el_option = $("<option>");
el_option.text(blacklisted[idx]["nick"]+" ("+blacklisted[idx]["id"]+")");
el_option.val(blacklisted[idx]["id"]);
list.append(el_option);
}
$("#rto21-count").text(blacklisted.length);
}; // Мы на странице профиля - ведём список пользователей.
if (window.location.pathname === "/forum/profile.php") {
do { // Если это не мой профиль, не работаем.
if ($("#main_content_wrap > h1").text().indexOf("Мой профиль") === -1)
break; // Берём список заблокированных из хранилища.
var blacklisted_users = localStorage.getItem("rto21_blacklisted") || "[]";
blacklisted_users = JSON.parse(blacklisted_users); // Элемент списка фильтруемых пользователей.
var list = $("<select id=\"rto21-list\" multiple=\"multiple\" size=\"11\" style=\"width: 20em; float: left; margin-right: .5em; height: 17em;\">"); // Галочка включения-выключения фильтрации.
var enabled_checkbox = $("<input type=\"checkbox\" id=\"rto21-enabled\">").click(function(){
localStorage.setItem("rto21_enabled", this.checked);
});
enabled_checkbox
.css({"margin-left":".5em","margin-right":".5em"})
.prop("checked", localStorage.getItem("rto21_enabled") === "true"); // Переключатель способа работы: удаление сообщений или их сокрытие. По умолчанию - удаление.
if (!localStorage.getItem("rto21_method"))
localStorage.setItem("rto21_method", "delete");
var method_delete_radio = $("<input type=\"radio\" id=\"rto21-method-delete\" name=\"rto21-method\" value=\"delete\"/>").click(function(){
localStorage.setItem("rto21_method", "delete");
});
method_delete_radio
.css({"margin":".5em .5em 0 0","vertical-align":"top"})
.prop("checked", localStorage.getItem("rto21_method") === "delete");
var method_hide_radio = $("<input type=\"radio\" id=\"rto21-method-hide\" name=\"rto21-method\" value=\"hide\"/>").click(function(){
localStorage.setItem("rto21_method", "hide");
});
method_hide_radio
.css({"margin":".5em .5em 0 2em","vertical-align":"top"})
.prop("checked", localStorage.getItem("rto21_method") === "hide"); // Надпись с количеством записей в списке.
var count_text = $("<span>(<span id=\"rto21-count\"></span>)</span>").css({"margin-left":".5em","margin-right":".5em"}); // Добавляем список в интерфейс.
var container = $("table.user_profile > tbody > tr:eq(1) > td:eq(1)");
container.append($(
"<fieldset id=\"rto21-container\" style=\"margin: 0 8px 3px;\">" +
"<legend>Чёрный список входящих ЛС</legend>" +
"<div style=\"padding: 4px;\"></div>" +
"</fieldset>"
));
container.find("#rto21-container div").append(list);
container.find("#rto21-container legend").prepend(enabled_checkbox).append(count_text); // Кнопка добавления записи.
var add_button = $("<input type=\"button\">").val("Добавить").click(function(){
var el_newusernick_text = $("#rto21-newusernick");
var newuser_nick = el_newusernick_text.val();
var el_newuserid_text = $("#rto21-newuserid");
var newuser_id = parseInt(el_newuserid_text.val()); // Правильно ли введён id пользователя.
if (isNaN(newuser_id)) {
el_newuserid_text.css({
"background-color": "#FF7F7F"
}).delay(400).queue(function(){
$(this).css({
"background-color": "white"
}).dequeue();
});
return;
} // Если логин не задан, составляем его сами.
newuser_id = parseInt(newuser_id);
if (newuser_nick.length === 0) {
newuser_nick = "Пользователь " + newuser_id;
} // Ищем, нет ли уже такого пользователя в списке.
var found = blacklisted_users.findIndex(function(user){
return newuser_id === user["id"];
});
// Если такой есть, не работаем.
if (found >= 0) {
el_newuserid_text.css({
"background-color": "#FF7F7F"
}).delay(400).queue(function(){
$(this).css({
"background-color": "white"
}).dequeue();
});
return;
} // Ищем место, куда добавить новую запись. Записи должны быть отсортированы по алфавиту.
for (var idx = 0; idx < blacklisted_users.length; idx++) {
if (blacklisted_users[idx]["nick"].toUpperCase() > newuser_nick.toUpperCase())
break;
} // Добавляем в начало списка.
if (idx === 0) {
blacklisted_users.unshift({"nick":newuser_nick,"id":newuser_id});
}
// Добавляем в конец списка.
else if (idx >= blacklisted_users.length) {
blacklisted_users.push({"nick":newuser_nick,"id":newuser_id});
}
// Добавляем в середину списка.
else {
for (var idx1 = blacklisted_users.length-1; idx1 >= idx; idx1--) {
blacklisted_users[idx1+1] = blacklisted_users[idx1];
}
blacklisted_users[idx] = {"nick":newuser_nick,"id":newuser_id};
} // Обновляем список.
update_list(blacklisted_users); // Очищаем поля ввода id и логина пользователя.
el_newusernick_text.val("");
el_newuserid_text.val(""); // Сохраняем список в хранилище.
localStorage.setItem("rto21_blacklisted", JSON.stringify(blacklisted_users));
}); // Кнопка удаления записи.
var remove_button = $("<input type=\"button\">").val("Удалить").click(function(){
var el_list = $("#rto21-list"); // Если ничего не выбрано, не работаем.
if (el_list.find("option:selected").length === -1)
return; // Удаляем выбранное из списка.
blacklisted_users = blacklisted_users.filter(function(user){
return el_list.find("option[value='"+user["id"]+"']:selected").length === 0;
}); // Обновляем список.
update_list(blacklisted_users); // Сохраняем список в хранилище.
localStorage.setItem("rto21_blacklisted", JSON.stringify(blacklisted_users));
}); // Добавляем элементы управления списком.
container.find("#rto21-container div").append(
$("<p style=\"margin-bottom: 2em;\">")
.append("<p style=\"font-size: smaller;\"><span style=\"font-weight: bold;\">Для добавления записи</span> введите логин пользователя и его цифровой id и нажмите на кнопку.<br/>Логин не обязателен, поиск будет производиться по Id.</p>")
.append("<input type=\"text\" id=\"rto21-newusernick\" placeholder=\"Логин\" size=\"12\" style=\"margin-right: .5em;\"/>")
.append("<input type=\"text\" id=\"rto21-newuserid\" placeholder=\"Id\" size=\"8\" style=\"margin-right: .5em;\"/>")
.append(add_button),
$("<p style=\"margin-bottom: 2em;\">")
.append("<p style=\"font-size: smaller;\"><span style=\"font-weight: bold;\">Для удаления записей</span> выберите одну или несколько строк и нажмите на кнопку.<br/>Несколько строк можно выбрать с помощью Ctrl или Shift.</p>")
.append(remove_button),
$("<p style=\"margin-bottom: 2em;\">")
.append("<p>Способ действия:</p>")
.append(method_delete_radio, $("<label for=\"rto21-method-delete\" style=\"vertical-align: top;\"><p>Удаление<br/><span style=\"font-size: smaller;\">Скрывать, в фоне <span style=\"font-weight: bold;\">удалять</span>.</span></p></label>"))
.append(method_hide_radio, $("<label for=\"rto21-method-hide\" style=\"vertical-align: top;\"><p>Сокрытие<br/><span style=\"font-size: smaller;\">Только <span style=\"font-weight: bold;\">скрывать</span>.</span></p></label>"))
); // Заполняем список значениями.
update_list(blacklisted_users); } while (false);
} // Страница своего профиля. // Мы на странице входящих ЛС - фильтруем пользователей.
if (window.location.pathname === "/forum/privmsg.php" && window.location.search.indexOf("?folder=inbox") === 0) {
do { // Если фильтрация не включена, не работаем.
var enabled = localStorage.getItem("rto21_enabled") === "true";
if (!enabled)
break; // Способ действия.
var method = localStorage.getItem("rto21_method") || "delete"; // Берём список заблокированных из хранилища.
var blacklisted_users = localStorage.getItem("rto21_blacklisted") || "[]";
blacklisted_users = JSON.parse(blacklisted_users);
// Если списка нет, нечего фильтровать, выходим.
if (blacklisted_users.length === 0)
break; // Ищем фильтруемых пользователей и запоминаем id их сообщений.
var to_delete = "";
$("table.forumline td.pm-nick-td a.med").filter(function(idx,elem){
var el_nick = $(elem);
var user_id = parseInt(el_nick.attr("href").replace(/.+&u=(\d+)$/, "$1"));
var found = blacklisted_users.findIndex(function(blacklisted){
return user_id === blacklisted["id"];
});
return found > -1;
}).each(function(idx, elem){
var el_nick = $(elem);
var el_message_tr = el_nick.parentsUntil("tr").parent();
el_message_tr.hide();
var message_id = parseInt(el_message_tr.attr("id").replace(/^tr-(\d+)$/, "$1"));
to_delete += "&mark%5B"+idx+"%5D="+message_id;
});
// Если удалять нечего, выходим.
if (to_delete.length === 0)
break; // Удаление сообщений, если выбран такой способ работы.
if (method === "delete")
$.post({
url: "//" + window.location.hostname + "/forum/privmsg.php?folder=inbox",
data: "mode=&delete=1"+to_delete+"&confirm=%C4%E0&form_token="+window.BB.form_token,
success: function (data, status) {
//console.log("Удалено сообщение "+(idx+1)+ " (id="+message_id+")");
//window.location.reload();
}
, async: false
}); } while (false);
} // Страница входящих ЛС. })();
Надо доработать скрипт: он основан на удалении сообщений, т.е. по факту полученных. Надо сделать именно запрет, что бы отправитель получал сообщение аналогичное общим настройкам - "Пользователь отключил получение сообщений" либо "Вам запрещено писать пользователю".
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
30-Дек-17 22:07
(спустя 12 мин.)
maximus_lt
Мой скрипт удаляет сообщения не читая, то есть у отправителя не обозначается, что они открывались.
А эти перечисленные настройки серверные, со стороны клиента на них нельзя повлиять.
|
|
maximus_lt
Стаж: 17 лет 5 месяцев Сообщений: 6144
|
maximus_lt ·
30-Дек-17 22:14
(спустя 6 мин.)
unchqua, тогда можно эстетики ради сделать, что бы настройки "Чёрный список входящих ЛС" в профиле можно было свернуть ?
|
|
unchqua
Стаж: 16 лет 4 месяца Сообщений: 1060
|
unchqua ·
30-Дек-17 22:18
(спустя 4 мин.)
maximus_lt
Если вообще не хотите им пользоваться, скрипт можно отключить в Greasemonkey. А окно со списком да, могу сделать поменьше по высоте.
|
|
|