Reposting music torrents on sites built on Gazelle and other frameworks
// ==UserScript==
// @name ostrich
// @namespace https://dvxg.de/
// @version 0.3.3
// @author davidxuang
// @description Reposting music torrents on sites built on Gazelle and other frameworks
// @description:zh-CN 适用于Gazelle等架构站点的音乐转种工具
// @license AGPL-3.0-only
// @icon https://cdn.jsdelivr.net/gh/microsoft/fluentui-emoji/assets/Musical%20score/3D/musical_score_3d.png
// @homepage https://github.com/davidxuang/ostrich
// @homepageURL https://github.com/davidxuang/ostrich
// @match https://logs.musichoarders.xyz/
// @match https://*.dicmusic.com/torrents.php*
// @match https://*.dicmusic.com/artist.php*
// @match https://*.dicmusic.com/collages.php*
// @match https://*.dicmusic.com/upload.php*
// @match https://*.jpopsuki.eu/torrents.php*
// @match https://*.jpopsuki.eu/artist.php*
// @match https://*.jpopsuki.eu/collages.php*
// @match https://*.jpopsuki.eu/upload.php*
// @match https://*.orpheus.network/torrents.php*
// @match https://*.orpheus.network/artist.php*
// @match https://*.orpheus.network/collages.php*
// @match https://*.orpheus.network/upload.php*
// @match https://*.redacted.sh/torrents.php*
// @match https://*.redacted.sh/artist.php*
// @match https://*.redacted.sh/collages.php*
// @match https://*.redacted.sh/upload.php*
// @match https://*.open.cd/plugin_details.php*
// @match https://*.open.cd/plugin_upload.php*
// @match https://*.tjupt.org/details.php*
// @match https://*.tjupt.org/upload.php*
// @resource brotli_wasm_bg https://cdn.jsdelivr.net/npm/brotli-wasm@3/pkg.web/brotli_wasm_bg.wasm
// @grant GM_getResourceURL
// @grant GM_xmlhttpRequest
// ==/UserScript==
(async function () {
'use strict';
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
const version = "3.7.8";
const VERSION = version;
const _hasBuffer = typeof Buffer === "function";
const _TD = typeof TextDecoder === "function" ? new TextDecoder() : void 0;
const _TE = typeof TextEncoder === "function" ? new TextEncoder() : void 0;
const b64ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
const b64chs = Array.prototype.slice.call(b64ch);
const b64tab = ((a) => {
let tab = {};
a.forEach((c, i) => tab[c] = i);
return tab;
})(b64chs);
const b64re = /^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/;
const _fromCC = String.fromCharCode.bind(String);
const _U8Afrom = typeof Uint8Array.from === "function" ? Uint8Array.from.bind(Uint8Array) : (it) => new Uint8Array(Array.prototype.slice.call(it, 0));
const _mkUriSafe = (src) => src.replace(/=/g, "").replace(/[+\/]/g, (m0) => m0 == "+" ? "-" : "_");
const _tidyB64 = (s) => s.replace(/[^A-Za-z0-9\+\/]/g, "");
const btoaPolyfill = (bin) => {
let u32, c0, c1, c2, asc = "";
const pad = bin.length % 3;
for (let i = 0; i < bin.length; ) {
if ((c0 = bin.charCodeAt(i++)) > 255 || (c1 = bin.charCodeAt(i++)) > 255 || (c2 = bin.charCodeAt(i++)) > 255)
throw new TypeError("invalid character found");
u32 = c0 << 16 | c1 << 8 | c2;
asc += b64chs[u32 >> 18 & 63] + b64chs[u32 >> 12 & 63] + b64chs[u32 >> 6 & 63] + b64chs[u32 & 63];
}
return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc;
};
const _btoa = typeof btoa === "function" ? (bin) => btoa(bin) : _hasBuffer ? (bin) => Buffer.from(bin, "binary").toString("base64") : btoaPolyfill;
const _fromUint8Array = _hasBuffer ? (u8a) => Buffer.from(u8a).toString("base64") : (u8a) => {
const maxargs = 4096;
let strs = [];
for (let i = 0, l = u8a.length; i < l; i += maxargs) {
strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs)));
}
return _btoa(strs.join(""));
};
const fromUint8Array = (u8a, urlsafe = false) => urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a);
const cb_utob = (c) => {
if (c.length < 2) {
var cc = c.charCodeAt(0);
return cc < 128 ? c : cc < 2048 ? _fromCC(192 | cc >>> 6) + _fromCC(128 | cc & 63) : _fromCC(224 | cc >>> 12 & 15) + _fromCC(128 | cc >>> 6 & 63) + _fromCC(128 | cc & 63);
} else {
var cc = 65536 + (c.charCodeAt(0) - 55296) * 1024 + (c.charCodeAt(1) - 56320);
return _fromCC(240 | cc >>> 18 & 7) + _fromCC(128 | cc >>> 12 & 63) + _fromCC(128 | cc >>> 6 & 63) + _fromCC(128 | cc & 63);
}
};
const re_utob = /[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g;
const utob = (u) => u.replace(re_utob, cb_utob);
const _encode = _hasBuffer ? (s) => Buffer.from(s, "utf8").toString("base64") : _TE ? (s) => _fromUint8Array(_TE.encode(s)) : (s) => _btoa(utob(s));
const encode = (src, urlsafe = false) => urlsafe ? _mkUriSafe(_encode(src)) : _encode(src);
const encodeURI = (src) => encode(src, true);
const re_btou = /[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g;
const cb_btou = (cccc) => {
switch (cccc.length) {
case 4:
var cp = (7 & cccc.charCodeAt(0)) << 18 | (63 & cccc.charCodeAt(1)) << 12 | (63 & cccc.charCodeAt(2)) << 6 | 63 & cccc.charCodeAt(3), offset = cp - 65536;
return _fromCC((offset >>> 10) + 55296) + _fromCC((offset & 1023) + 56320);
case 3:
return _fromCC((15 & cccc.charCodeAt(0)) << 12 | (63 & cccc.charCodeAt(1)) << 6 | 63 & cccc.charCodeAt(2));
default:
return _fromCC((31 & cccc.charCodeAt(0)) << 6 | 63 & cccc.charCodeAt(1));
}
};
const btou = (b) => b.replace(re_btou, cb_btou);
const atobPolyfill = (asc) => {
asc = asc.replace(/\s+/g, "");
if (!b64re.test(asc))
throw new TypeError("malformed base64.");
asc += "==".slice(2 - (asc.length & 3));
let u24, r1, r2;
let binArray = [];
for (let i = 0; i < asc.length; ) {
u24 = b64tab[asc.charAt(i++)] << 18 | b64tab[asc.charAt(i++)] << 12 | (r1 = b64tab[asc.charAt(i++)]) << 6 | (r2 = b64tab[asc.charAt(i++)]);
if (r1 === 64) {
binArray.push(_fromCC(u24 >> 16 & 255));
} else if (r2 === 64) {
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255));
} else {
binArray.push(_fromCC(u24 >> 16 & 255, u24 >> 8 & 255, u24 & 255));
}
}
return binArray.join("");
};
const _atob = typeof atob === "function" ? (asc) => atob(_tidyB64(asc)) : _hasBuffer ? (asc) => Buffer.from(asc, "base64").toString("binary") : atobPolyfill;
const _toUint8Array = _hasBuffer ? (a) => _U8Afrom(Buffer.from(a, "base64")) : (a) => _U8Afrom(_atob(a).split("").map((c) => c.charCodeAt(0)));
const toUint8Array = (a) => _toUint8Array(_unURI(a));
const _decode = _hasBuffer ? (a) => Buffer.from(a, "base64").toString("utf8") : _TD ? (a) => _TD.decode(_toUint8Array(a)) : (a) => btou(_atob(a));
const _unURI = (a) => _tidyB64(a.replace(/[-_]/g, (m0) => m0 == "-" ? "+" : "/"));
const decode = (src) => _decode(_unURI(src));
const isValid = (src) => {
if (typeof src !== "string")
return false;
const s = src.replace(/\s+/g, "").replace(/={0,2}$/, "");
return !/[^\s0-9a-zA-Z\+/]/.test(s) || !/[^\s0-9a-zA-Z\-_]/.test(s);
};
const _noEnum = (v) => {
return {
value: v,
enumerable: false,
writable: true,
configurable: true
};
};
const extendString = function() {
const _add = (name, body) => Object.defineProperty(String.prototype, name, _noEnum(body));
_add("fromBase64", function() {
return decode(this);
});
_add("toBase64", function(urlsafe) {
return encode(this, urlsafe);
});
_add("toBase64URI", function() {
return encode(this, true);
});
_add("toBase64URL", function() {
return encode(this, true);
});
_add("toUint8Array", function() {
return toUint8Array(this);
});
};
const extendUint8Array = function() {
const _add = (name, body) => Object.defineProperty(Uint8Array.prototype, name, _noEnum(body));
_add("toBase64", function(urlsafe) {
return fromUint8Array(this, urlsafe);
});
_add("toBase64URI", function() {
return fromUint8Array(this, true);
});
_add("toBase64URL", function() {
return fromUint8Array(this, true);
});
};
const extendBuiltins = () => {
extendString();
extendUint8Array();
};
const gBase64 = {
version,
VERSION,
atob: _atob,
atobPolyfill,
btoa: _btoa,
btoaPolyfill,
fromBase64: decode,
toBase64: encode,
encode,
encodeURI,
encodeURL: encodeURI,
utob,
btou,
decode,
isValid,
fromUint8Array,
toUint8Array,
extendString,
extendUint8Array,
extendBuiltins
};
var _GM_getResourceURL = (() => typeof GM_getResourceURL != "undefined" ? GM_getResourceURL : void 0)();
var _GM_xmlhttpRequest = (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
let wasm;
const heap = new Array(32).fill(void 0);
heap.push(void 0, null, true, false);
function getObject(idx) {
return heap[idx];
}
const cachedTextDecoder = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });
cachedTextDecoder.decode();
let cachegetUint8Memory0 = null;
function getUint8Memory0() {
if (cachegetUint8Memory0 === null || cachegetUint8Memory0.buffer !== wasm.memory.buffer) {
cachegetUint8Memory0 = new Uint8Array(wasm.memory.buffer);
}
return cachegetUint8Memory0;
}
function getStringFromWasm0(ptr, len) {
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
}
let heap_next = heap.length;
function addHeapObject(obj) {
if (heap_next === heap.length) heap.push(heap.length + 1);
const idx = heap_next;
heap_next = heap[idx];
heap[idx] = obj;
return idx;
}
let WASM_VECTOR_LEN = 0;
const cachedTextEncoder = new TextEncoder("utf-8");
const encodeString = typeof cachedTextEncoder.encodeInto === "function" ? function(arg, view) {
return cachedTextEncoder.encodeInto(arg, view);
} : function(arg, view) {
const buf = cachedTextEncoder.encode(arg);
view.set(buf);
return {
read: arg.length,
written: buf.length
};
};
function passStringToWasm0(arg, malloc, realloc) {
if (realloc === void 0) {
const buf = cachedTextEncoder.encode(arg);
const ptr2 = malloc(buf.length);
getUint8Memory0().subarray(ptr2, ptr2 + buf.length).set(buf);
WASM_VECTOR_LEN = buf.length;
return ptr2;
}
let len = arg.length;
let ptr = malloc(len);
const mem = getUint8Memory0();
let offset = 0;
for (; offset < len; offset++) {
const code = arg.charCodeAt(offset);
if (code > 127) break;
mem[ptr + offset] = code;
}
if (offset !== len) {
if (offset !== 0) {
arg = arg.slice(offset);
}
ptr = realloc(ptr, len, len = offset + arg.length * 3);
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
const ret = encodeString(arg, view);
offset += ret.written;
}
WASM_VECTOR_LEN = offset;
return ptr;
}
let cachegetInt32Memory0 = null;
function getInt32Memory0() {
if (cachegetInt32Memory0 === null || cachegetInt32Memory0.buffer !== wasm.memory.buffer) {
cachegetInt32Memory0 = new Int32Array(wasm.memory.buffer);
}
return cachegetInt32Memory0;
}
function dropObject(idx) {
if (idx < 36) return;
heap[idx] = heap_next;
heap_next = idx;
}
function takeObject(idx) {
const ret = getObject(idx);
dropObject(idx);
return ret;
}
function passArray8ToWasm0(arg, malloc) {
const ptr = malloc(arg.length * 1);
getUint8Memory0().set(arg, ptr / 1);
WASM_VECTOR_LEN = arg.length;
return ptr;
}
let stack_pointer = 32;
function addBorrowedObject(obj) {
if (stack_pointer == 1) throw new Error("out of js stack");
heap[--stack_pointer] = obj;
return stack_pointer;
}
function getArrayU8FromWasm0(ptr, len) {
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
}
function compress(buf, raw_options) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passArray8ToWasm0(buf, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.compress(retptr, ptr0, len0, addBorrowedObject(raw_options));
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r2 = getInt32Memory0()[retptr / 4 + 2];
var r3 = getInt32Memory0()[retptr / 4 + 3];
if (r3) {
throw takeObject(r2);
}
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
heap[stack_pointer++] = void 0;
}
}
function decompress(buf) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passArray8ToWasm0(buf, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.decompress(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r2 = getInt32Memory0()[retptr / 4 + 2];
var r3 = getInt32Memory0()[retptr / 4 + 3];
if (r3) {
throw takeObject(r2);
}
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v1;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
function isLikeNone(x) {
return x === void 0 || x === null;
}
const BrotliStreamResultCode = Object.freeze({ ResultSuccess: 1, "1": "ResultSuccess", NeedsMoreInput: 2, "2": "NeedsMoreInput", NeedsMoreOutput: 3, "3": "NeedsMoreOutput" });
class BrotliStreamResult {
static __wrap(ptr) {
const obj = Object.create(BrotliStreamResult.prototype);
obj.ptr = ptr;
return obj;
}
__destroy_into_raw() {
const ptr = this.ptr;
this.ptr = 0;
return ptr;
}
free() {
const ptr = this.__destroy_into_raw();
wasm.__wbg_brotlistreamresult_free(ptr);
}
get code() {
const ret = wasm.__wbg_get_brotlistreamresult_code(this.ptr);
return ret >>> 0;
}
set code(arg0) {
wasm.__wbg_set_brotlistreamresult_code(this.ptr, arg0);
}
get buf() {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.__wbg_get_brotlistreamresult_buf(retptr, this.ptr);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v0 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1);
return v0;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
set buf(arg0) {
const ptr0 = passArray8ToWasm0(arg0, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.__wbg_set_brotlistreamresult_buf(this.ptr, ptr0, len0);
}
get input_offset() {
const ret = wasm.__wbg_get_brotlistreamresult_input_offset(this.ptr);
return ret >>> 0;
}
set input_offset(arg0) {
wasm.__wbg_set_brotlistreamresult_input_offset(this.ptr, arg0);
}
}
class CompressStream {
static __wrap(ptr) {
const obj = Object.create(CompressStream.prototype);
obj.ptr = ptr;
return obj;
}
__destroy_into_raw() {
const ptr = this.ptr;
this.ptr = 0;
return ptr;
}
free() {
const ptr = this.__destroy_into_raw();
wasm.__wbg_compressstream_free(ptr);
}
constructor(quality) {
const ret = wasm.compressstream_new(!isLikeNone(quality), isLikeNone(quality) ? 0 : quality);
return CompressStream.__wrap(ret);
}
compress(input_opt, output_size) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
var ptr0 = isLikeNone(input_opt) ? 0 : passArray8ToWasm0(input_opt, wasm.__wbindgen_malloc);
var len0 = WASM_VECTOR_LEN;
wasm.compressstream_compress(retptr, this.ptr, ptr0, len0, output_size);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r2 = getInt32Memory0()[retptr / 4 + 2];
if (r2) {
throw takeObject(r1);
}
return BrotliStreamResult.__wrap(r0);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
total_out() {
const ret = wasm.compressstream_total_out(this.ptr);
return ret >>> 0;
}
}
class DecompressStream {
static __wrap(ptr) {
const obj = Object.create(DecompressStream.prototype);
obj.ptr = ptr;
return obj;
}
__destroy_into_raw() {
const ptr = this.ptr;
this.ptr = 0;
return ptr;
}
free() {
const ptr = this.__destroy_into_raw();
wasm.__wbg_decompressstream_free(ptr);
}
constructor() {
const ret = wasm.decompressstream_new();
return DecompressStream.__wrap(ret);
}
decompress(input, output_size) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passArray8ToWasm0(input, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.decompressstream_decompress(retptr, this.ptr, ptr0, len0, output_size);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var r2 = getInt32Memory0()[retptr / 4 + 2];
if (r2) {
throw takeObject(r1);
}
return BrotliStreamResult.__wrap(r0);
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
}
total_out() {
const ret = wasm.decompressstream_total_out(this.ptr);
return ret >>> 0;
}
}
async function load(module, imports) {
if (typeof Response === "function" && module instanceof Response) {
if (typeof WebAssembly.instantiateStreaming === "function") {
try {
return await WebAssembly.instantiateStreaming(module, imports);
} catch (e) {
if (module.headers.get("Content-Type") != "application/wasm") {
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
} else {
throw e;
}
}
}
const bytes = await module.arrayBuffer();
return await WebAssembly.instantiate(bytes, imports);
} else {
const instance = await WebAssembly.instantiate(module, imports);
if (instance instanceof WebAssembly.Instance) {
return { instance, module };
} else {
return instance;
}
}
}
async function init(input) {
const imports = {};
imports.wbg = {};
imports.wbg.__wbindgen_is_undefined = function(arg0) {
const ret = getObject(arg0) === void 0;
return ret;
};
imports.wbg.__wbindgen_is_object = function(arg0) {
const val = getObject(arg0);
const ret = typeof val === "object" && val !== null;
return ret;
};
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
const ret = getStringFromWasm0(arg0, arg1);
return addHeapObject(ret);
};
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
const ret = new Error(getStringFromWasm0(arg0, arg1));
return addHeapObject(ret);
};
imports.wbg.__wbindgen_json_serialize = function(arg0, arg1) {
const obj = getObject(arg1);
const ret = JSON.stringify(obj === void 0 ? null : obj);
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_new_693216e109162396 = function() {
const ret = new Error();
return addHeapObject(ret);
};
imports.wbg.__wbg_stack_0ddaca5d1abfb52f = function(arg0, arg1) {
const ret = getObject(arg1).stack;
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
getInt32Memory0()[arg0 / 4 + 1] = len0;
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
};
imports.wbg.__wbg_error_09919627ac0992f5 = function(arg0, arg1) {
try {
console.error(getStringFromWasm0(arg0, arg1));
} finally {
wasm.__wbindgen_free(arg0, arg1);
}
};
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
takeObject(arg0);
};
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
throw new Error(getStringFromWasm0(arg0, arg1));
};
if (typeof input === "string" || typeof Request === "function" && input instanceof Request || typeof URL === "function" && input instanceof URL) {
input = fetch(input);
}
const { instance, module } = await load(await input, imports);
wasm = instance.exports;
init.__wbindgen_wasm_module = module;
return wasm;
}
const _brotli = Object.freeze( Object.defineProperty({
__proto__: null,
BrotliStreamResult,
BrotliStreamResultCode,
CompressStream,
DecompressStream,
compress,
decompress,
default: init
}, Symbol.toStringTag, { value: "Module" }));
const brotli = await (async () => {
const url = _GM_getResourceURL("brotli_wasm_bg");
await init(
gBase64.toUint8Array(url.slice(url.indexOf(","))).buffer
);
return _brotli;
})();
const base64url = {
decode: gBase64.decode,
encode: (v) => gBase64.encode(v, true),
decodeBytes: (v) => gBase64.toUint8Array(v),
encodeBytes: (v) => gBase64.fromUint8Array(v, true)
};
function marshal(object) {
return base64url.encodeBytes(
brotli.compress(new TextEncoder().encode(JSON.stringify(object)))
);
}
function unmarshal(str) {
return JSON.parse(
new TextDecoder().decode(brotli.decompress(base64url.decodeBytes(str)))
);
}
function xmlHttpRequest(details) {
return new Promise((resolve, reject) => {
_GM_xmlhttpRequest({
...details,
onabort() {
reject("Aborted");
},
onload(event) {
if (event.status !== 200) {
reject(event.statusText);
}
resolve(event);
},
onerror(event) {
reject(event);
},
ontimeout() {
reject("Timeout");
}
});
});
}
function parseHeaders(value) {
return Object.fromEntries(
value.split("\r\n").map((line) => {
var c = line.indexOf(":");
return [line.substring(0, c), line.substring(c + 1).trimStart()];
})
);
}
function toDataTransfer(file) {
const data2 = new DataTransfer();
if (file instanceof Array) {
file.forEach((f) => {
data2.items.add(f);
});
} else {
data2.items.add(file);
}
return data2;
}
function unescapeHtml(value) {
const textarea = document.createElement("textarea");
textarea.innerHTML = value;
return textarea.value;
}
async function nextMutation(target, type, subtree, timeout, sender) {
try {
console.debug(
`Waiting for mutations with timeout of ${timeout ?? (timeout = 3e4)}.`
);
return await Promise.race([
new Promise((_, reject) => {
setTimeout(() => reject("Timeout"), timeout);
}),
new Promise((resolve) => {
const observer = new MutationObserver((mutations) => {
if (mutations.some((m) => m.type === type)) {
observer.disconnect();
resolve();
}
});
observer.observe(target, { [type]: true, subtree });
sender?.dispatchEvent(new Event("change"));
})
]);
} catch (reason) {
console.warn(reason);
}
}
function onDescendantAdded(target, subtree, callback) {
new MutationObserver((mutations) => {
mutations.filter((m) => m.type === "childList" && m.addedNodes.length).flatMap((m) => [...m.addedNodes]).forEach(callback);
}).observe(target, { childList: true, subtree });
}
const _reSplit = /^((?:\p{L}|\p{P}|\s)+)\s+[(()]((?:\p{L}|\p{P}|\s)+)[))]$/u;
function trySelect(select, name) {
name = name.toLowerCase();
let options = [...select.options].map((option) => ({
name: option.textContent?.toLowerCase(),
key: option.value
})).filter((p) => p.name);
let seq = options.filter((p) => p.name === name);
if (seq.length) {
return seq.length === 1 && (select.value = seq.at(0).key);
}
seq = options.filter(
(p) => (p.name?.indexOf(name) ?? NaN) >= 0 || p.name && (name?.indexOf(p.name) ?? NaN) >= 0
);
if (seq.length) {
return seq.length === 1 && (select.value = seq.at(0).key);
}
const match = name.match(_reSplit);
const names = match ? [match[1], match[2]] : [name];
options = options.flatMap((p) => {
const m = p.name.match(_reSplit);
return m ? [
{ name: m[1], key: p.key },
{ name: m[2], key: p.key }
] : p;
}).filter((p) => p.name);
seq = options.filter(
(p) => names.some(
(n) => (p.name?.indexOf(n) ?? NaN) >= 0 || p.name && (n?.indexOf(p.name) ?? NaN) >= 0
)
);
return seq.length === 1 && (select.value = seq.at(0).key);
}
const l10n = {
parse: function(val) {
val = val.trim().normalize();
const match = val.match(/^(.+?)\s*\((.+)\)$/);
if (!match) return val;
let [latin, native] = match.slice(1);
const trilingual = native.trim().match(/^(.+?)(?:\s+\/\s+|\s*/\s*)(.*\p{Script=Han}.*)$/u);
if (trilingual) {
return {
latin,
native: trilingual[1]
};
}
let l = match[1].match(/[^\P{L}\p{Script=Latin}]/gu)?.length ?? 0;
let r = match[2].match(/[^\P{L}\p{Script=Latin}]/gu)?.length ?? 0;
if (l === r) {
l = match[1].match(/[^\P{L}a-zA-Z]/gu)?.length ?? 0;
r = match[2].match(/[^\P{L}a-zA-Z]/gu)?.length ?? 0;
}
if (l > r) {
[latin, native] = [native, latin];
} else if (l === r && latin.length < native.length) {
[latin, native] = [native, latin];
}
return {
latin,
native
};
},
format: function(val, prefer = "latin") {
if (typeof val === "string") return val;
switch (prefer) {
default:
return `${val.latin} (${val.native})`;
case "native":
return `${val.native} (${val.latin})`;
case "cjk":
return this.format(
val,
/\p{Script=Han}|\p{Script=Hiragana}|\p{Script=Katakana}|\p{Script=Hangul}/u.test(
val.native
) ? "native" : "latin"
);
case "zh":
const z = /\p{Script=Han}/u.test(val.native) && !/\p{Script=Hiragana}|\p{Script=Katakana}|\p{Script=Hangul}/u.test(
val.native
);
return this.format(val, z ? "native" : "latin");
}
},
select: function(val, prefer = "latin") {
if (typeof val === "string") return val;
return prefer === "latin" ? val.latin : val.native;
}
};
function _throw(ex) {
throw ex;
}
const base = { "gazelle": { "include": { "source": ["/torrents.php", "/artist.php", "/collages.php"], "target": "/upload.php" }, "exclude": { "download": "/torrents.php" }, "actions": { "log": "viewlog" } }, "nexusphp": { "include": { "source": "/plugin_details.php", "target": "/plugin_upload.php" }, "exclude": { "download": "/download.php" } } };
const override = { "gazelle": { "DIC": { "hostname": "dicmusic.com", "selects": { "releaseType": { "1": "Album", "3": "Soundtrack", "5": "EP", "6": "Anthology", "7": "Compilation", "9": "Single", "11": "Live album", "13": "Remix", "14": "Bootleg", "15": "Interview", "16": "Mixtape", "17": "Demo", "18": "Concert recording", "19": "DJ Mix", "21": "Unknown" } } }, "JPopsuki": { "hostname": "jpopsuki.eu", "selects": { "releaseType": { "Album": "Album", "Single": "Single", "PV": "PV", "DVD": "DVD", "TV-Music": "TV-Music", "TV-Variety": "TV-Variety", "TV-Drama": "TV-Drama", "Fansubs": "Fansubs", "Pictures": "Pictures", "Misc": "Misc" } }, "actions": { "log": null } }, "OPS": { "hostname": "orpheus.network", "selects": { "releaseType": { "1": "Album", "3": "Soundtrack", "5": "EP", "6": "Anthology", "7": "Compilation", "9": "Single", "11": "Live album", "13": "Remix", "14": "Bootleg", "15": "Interview", "16": "Mixtape", "17": "DJ Mix", "18": "Concert recording", "21": "Unknown" } } }, "Redacted": { "hostname": "redacted.sh", "selects": { "releaseType": { "1": "Album", "3": "Soundtrack", "5": "EP", "6": "Anthology", "7": "Compilation", "9": "Single", "11": "Live album", "13": "Remix", "14": "Bootleg", "15": "Interview", "16": "Mixtape", "17": "Demo", "18": "Concert Recording", "19": "DJ Mix", "21": "Unknown" } }, "actions": { "log": "loglist" } } }, "nexusphp": { "OpenCD": { "hostname": "open.cd" }, "TJUPT": { "hostname": "tjupt.org", "include": { "source": "/details.php", "target": "/upload.php" } } } };
const _data = {
base,
override
};
let data = {};
Object.keys(_data.override).forEach(
(fw2) => ((fw22) => {
data[fw22] = {};
Object.keys(_data.override[fw22]).forEach((st) => {
const base2 = _data.base[fw22];
let site2 = _data.override[fw22][st];
site2.include = {
...base2.include,
...site2.include
};
site2.exclude = {
...base2.exclude,
...site2.exclude
};
site2.actions = {
...base2.actions,
...site2.actions
};
data[fw22][st] = site2;
});
})(fw2)
);
class VoidElement {
constructor(tag) {
__publicField(this, "#");
this["#"] = tag;
}
}
function Void(tag) {
return () => new VoidElement(tag);
}
class ValueVoidElement {
constructor(tag, value) {
__publicField(this, "#");
__publicField(this, "$");
this["#"] = tag;
this.$ = value;
}
}
class ViewElement {
constructor(tag, children) {
__publicField(this, "#");
__publicField(this, "$$");
this["#"] = tag;
this.$$ = children;
}
}
function View(tag) {
return (children) => new ViewElement(tag, children);
}
class ValueViewElement {
constructor(tag, value, children) {
__publicField(this, "#");
__publicField(this, "$");
__publicField(this, "$$");
this["#"] = tag;
this.$$ = children;
this.$ = value;
}
}
function ValueView(tag) {
return (value, children) => new ValueViewElement(tag, value, children);
}
const Bold = View("b");
const Italic = View("i");
const Underline = View("u");
const Strikethrough = View("s");
const Font = ValueView("font");
const Size = ValueView("size");
const Color = ValueView("color");
const Heading = ValueView("h");
const Sub = View("sub");
const Sup = View("sup");
const Anchor = ValueView("url");
class ImageElement extends ValueVoidElement {
constructor(value, alt) {
super("img", value);
__publicField(this, "alt");
this.alt = alt;
}
}
const Image = (value, alt) => new ImageElement(value, alt);
const Code = View("code");
const Spoiler = View("#spoiler");
const HorizontalRule = Void("hr");
const Align = ValueView("align");
const Quote = ValueView("quote");
const Pre = ValueView("pre");
const Collapse = ValueView("#collapse");
const ListItem = View("li");
const UList = View("ul");
const OList = View("ol");
const Table = View("table");
const TableRow = View("tr");
const TableCell = View("td");
const is = {
void: (node) => ( (() => {
return (input) => "hr" === input;
})())(node["#"]),
valueVoid: (node) => ( (() => {
return (input) => "img" === input;
})())(node["#"]),
view: (node) => ( (() => {
const _iv1 = new Set(["b", "i", "u", "s", "sub", "sup", "code", "#spoiler", "li", "ul", "ol", "table", "tr", "td"]);
return (input) => true === _iv1.has(input);
})())(node["#"]),
valueView: (node) => ( (() => {
return (input) => "font" === input || "size" === input || "color" === input || "h" === input || "url" === input || "align" === input || "quote" === input || "pre" === input || "#collapse" === input;
})())(node["#"])
};
class BBText {
constructor(value) {
__publicField(this, "#", "#text");
__publicField(this, "$");
this.$ = value;
}
}
function _clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
function _wrapNewline(nodes, position) {
if (position === 2 || position === 3) {
let f = nodes.at(0);
if (f instanceof BBText) {
f.$ = f.$.replace(/^ */, "\n");
} else {
nodes.unshift(new BBText("\n"));
}
}
if (position === 1 || position === 3) {
let l = nodes.at(-1);
if (l instanceof BBText) {
l.$ = l.$.replace(/ *$/, "\n");
} else {
nodes.push(new BBText("\n"));
}
}
return nodes;
}
function _fromHTML(parent, baseURL, raw = false) {
let index = -1;
const origin = [...parent.childNodes];
const result = [];
while (++index < origin.length) {
const n = origin[index];
if (n instanceof globalThis.Text) {
let last = result.at(-1);
if (raw) {
result.push(new BBText(n.textContent ?? ""));
} else if (last instanceof BBText) {
last.$ = last.$ + (last.$.match(/\s$/) ? n.textContent?.trimStart() ?? "" : n.textContent ?? "").replace(/\s+/g, " ");
} else {
result.push(new BBText(n.textContent?.replace(/\s+/g, " ") ?? ""));
}
} else if (n instanceof HTMLBRElement) {
_wrapNewline(result, 1);
} else if (n instanceof HTMLUListElement) {
result.push(UList([...n.children].map((item) => ListItem(_fromHTML(item, baseURL)))));
} else if (n instanceof HTMLOListElement) {
result.push(OList([...n.children].map((item) => ListItem(_fromHTML(item, baseURL)))));
} else if (n instanceof HTMLTableElement) {
if (n.classList.contains("hide")) {
result.push(Collapse(n.tBodies.item(0)?.rows?.item(0)?.cells?.item(0)?.textContent?.trim() ?? _throw(n), _fromHTML(n.tBodies.item(0)?.rows?.item(1)?.cells?.item(0) ?? _throw(n), baseURL)));
} else {
const caption = [...n.children].at(0);
if (caption instanceof HTMLTableCaptionElement) {
result.push(Align("center", _fromHTML(caption, baseURL)));
}
result.push(Table([n.tHead, ...n.tBodies].filter((sec) => sec).flatMap((sec) => [...sec.rows]).map((row) => TableRow([...row.cells].map((cell) => TableCell(_fromHTML(cell, baseURL)))))));
}
} else if (n instanceof HTMLQuoteElement) {
result.push(Quote("", _fromHTML(n, baseURL)));
} else if (n instanceof HTMLPreElement) {
result.push(Pre("", _fromHTML(n, baseURL, true)));
} else if (n instanceof HTMLFieldSetElement) {
const firstChild = [...n.children].at(0);
if (firstChild instanceof HTMLLegendElement) {
n.removeChild(firstChild);
result.push(Quote(firstChild.textContent?.trim() ?? "", _fromHTML(n, baseURL)));
} else {
result.push(Quote("", _fromHTML(n, baseURL)));
}
} else if (n instanceof HTMLFontElement) {
let outer;
const children = _fromHTML(n, baseURL);
if (n.face) {
outer = Font(n.face, children);
}
if (n.size) {
outer = Font(n.size, outer ? [outer] : children);
}
if (n.color) {
outer = Font(n.color, outer ? [outer] : children);
}
if (outer) {
result.push(outer);
} else {
result.push(...children);
}
} else if (n instanceof HTMLHeadingElement) {
result.push(Heading(parseInt(n.tagName.slice(1)), _fromHTML(n, baseURL)));
} else if (n instanceof HTMLAnchorElement) {
let href = n.href;
if (!href.match(/^[a-z+]+:\/\//)) {
href = new URL(href, baseURL).toString();
}
if (n.attributes.getNamedItem("onclick")?.value?.startsWith("QuoteJump")) {
let offset = 0;
while (offset++ < origin.length) {
if (origin.at(index + offset) instanceof HTMLQuoteElement)
break;
}
if (index + offset === origin.length)
throw n;
result.push(Quote([...n.children].at(0)?.textContent?.trim() ?? "", _fromHTML(origin.at(index + offset), baseURL)));
index += offset;
} else {
result.push(Anchor(href, _fromHTML(n, baseURL)));
}
} else if (n instanceof HTMLImageElement) {
if (n.classList.contains("listicon")) {
result.push(ListItem([]));
} else {
result.push(Image(n.src, n.alt));
}
} else if (n instanceof HTMLHRElement) {
result.push(HorizontalRule());
} else if (n instanceof HTMLElement) {
if (n.classList.contains("mature")) {
continue;
}
const tagName = n.tagName.toLowerCase();
const nextElement = origin.slice(index).filter((node) => node instanceof HTMLElement && !(node instanceof HTMLBRElement)).at(1);
if (n.classList.contains("quoteheader")) {
let offset = 0;
while (offset++ < origin.length) {
if (origin.at(index + offset) instanceof HTMLQuoteElement)
break;
}
if (index + offset === origin.length)
throw n;
result.push(Quote(n.textContent?.trim() ?? "", _fromHTML(origin.at(index + offset), baseURL)));
index += offset;
} else if (tagName === "strong" && nextElement instanceof HTMLAnchorElement && (nextElement.attributes.getNamedItem("onclick")?.value?.indexOf("spoiler") ?? NaN) >= 0) {
let offset = 0;
while (offset++ < origin.length) {
if (origin.at(index + offset) instanceof HTMLQuoteElement)
break;
}
if (index + offset === origin.length)
throw n;
result.push(Collapse(n.textContent?.trim() ?? "", _fromHTML(origin.at(index + offset), baseURL)));
index += offset;
index += 3;
} else if (n.classList.contains("codetop")) {
let nextElement2;
do {
nextElement2 = origin[++index];
if (nextElement2 === void 0) {
throw n;
}
} while (!(nextElement2 instanceof HTMLElement));
result.push(..._fromHTML(nextElement2, baseURL));
let offset = 1;
nextElement2 = origin[index + offset];
while (!(nextElement2 instanceof HTMLElement) && nextElement2) {
nextElement2 = origin[index + ++offset];
}
if (nextElement2 instanceof HTMLElement) {
if (nextElement2.children.item(0)?.classList?.contains("codemain")) {
result.push(..._fromHTML(nextElement2.children.item(0), baseURL));
index += offset;
}
}
} else if (tagName === "b" || tagName === "strong") {
result.push(Bold(_fromHTML(n, baseURL)));
} else if (tagName === "i" || tagName === "i") {
result.push(Italic(_fromHTML(n, baseURL)));
} else if (tagName === "u" || tagName === "ins") {
result.push(Underline(_fromHTML(n, baseURL)));
} else if (tagName === "s" || tagName === "strike" || tagName === "del") {
result.push(Strikethrough(_fromHTML(n, baseURL)));
} else if (tagName === "code" || tagName === "tt") {
result.push(Code(_fromHTML(n, baseURL)));
} else if (tagName === "sub") {
result.push(Sub(_fromHTML(n, baseURL)));
} else if (tagName === "sup") {
result.push(Sup(_fromHTML(n, baseURL)));
} else if (tagName === "center" || tagName === "marquee") {
result.push(Align("center", _fromHTML(n, baseURL)));
} else {
let outer;
let allowUnwrap = false;
const children = _fromHTML(n, baseURL);
const classes = [...n.classList];
const fontWeight = n.style.fontWeight.toLowerCase();
if (parseFloat(fontWeight) >= 550 || fontWeight === "bold" || fontWeight === "bolder") {
outer = Bold(children);
}
const fontStyle = n.style.fontStyle.toLowerCase();
if (fontStyle === "italic" || fontStyle.startsWith("oblique")) {
outer = Italic(outer ? [outer] : children);
}
const textDecoration = n.style.textDecoration.toLowerCase().split(" ");
const textDecorationLine = n.style.textDecorationLine.toLowerCase();
if (textDecorationLine === "underline" || textDecoration.indexOf("underline") >= 0) {
outer = Underline(outer ? [outer] : children);
} else if (textDecorationLine === "line-through" || textDecoration.indexOf("line-through") >= 0) {
outer = Strikethrough(outer ? [outer] : children);
}
const fontFamily = n.style.fontFamily.toLowerCase().split(";").at(0);
if (fontFamily) {
if (n.children.item(0) instanceof HTMLPreElement) {
allowUnwrap = true;
} else {
outer = Font(fontFamily, outer ? [outer] : children);
}
}
const fontSize = n.style.fontSize.toLowerCase();
const sizeClasses = classes.filter((x) => x.startsWith("size"));
if (sizeClasses.length) {
outer = Size(_clamp(parseInt(sizeClasses.at(0).slice(4)), 0, 7), outer ? [outer] : children);
} else if (fontSize) {
console.warn(fontSize);
}
const color = n.style.color.toLowerCase();
if (color) {
outer = Color(color, outer ? [outer] : children);
}
const align = n.style.textAlign.toLowerCase();
if (( (() => {
return (input) => "left" === input || "center" === input || "right" === input;
})())(align)) {
outer = Align(align, outer ? [outer] : children);
}
if (tagName === "span") {
if (!(n.attributes.getNamedItem("class")?.value || n.attributes.getNamedItem("style")?.value)) {
allowUnwrap = true;
} else if (n.classList.contains("mask")) {
outer = Spoiler(children);
}
}
if (tagName === "p") {
if (n.classList.contains("sub")) {
result.push(Heading(2, children));
} else {
result.push(..._wrapNewline(outer ? [outer] : children, 3));
}
} else if (outer) {
if (tagName === "p") ;
else {
result.push(outer);
}
} else if (allowUnwrap) {
result.push(...children);
} else {
console.warn(n);
console.log(n.outerHTML);
if (tagName === "span") {
result.push(...children);
}
}
}
} else {
throw n;
}
}
return result;
}
function fromHTML(parent, baseURL) {
return _fromHTML(parent, baseURL);
}
const bb = {
fromHTML,
is
};
const _isBigEndian = (() => {
const u32 = new Uint32Array([1464816196]);
const u8 = new Uint8Array(u32.buffer);
switch (u8[0]) {
case 87:
return true;
case 68:
return false;
default:
throw u8;
}
})();
const _bomUtf16LE = new Uint8Array([255, 254]);
function toFile(logs, title) {
if (logs.recovered) {
console.warn(logs);
}
return logs.encoded ? logs.encoded.map(
(log2, l) => new File(
[base64url.decodeBytes(log2)],
logs.encoded.length > 1 ? `${title}.${l + 1}.log` : `${title}.log`,
{
type: "text/plain"
}
)
) : logs.plain.map((log2, l) => {
log2 = log2.trim();
const name = logs.plain.length > 1 ? `${title}.${l + 1}.log` : `${title}.log`;
if (log2.startsWith("Exact Audio Copy")) {
const array = new Uint16Array(log2.length);
let c = log2.length;
while (c >= 0) {
const ch = log2.charCodeAt(--c);
array[c] = ch;
}
if (_isBigEndian) {
c = array.length;
while (c >= 0) {
const ch = array[--c];
array[c] = (ch >> 8) + ((ch & 255) << 8);
}
}
return new File([_bomUtf16LE, array.buffer], name, {
type: "text/plain"
});
} else if (log2.startsWith("X Lossless Decoder")) {
return new File([new TextEncoder().encode(`${log2}
`).buffer], name, {
type: "text/plain"
});
} else {
throw log2;
}
});
}
const utf8 = new TextDecoder("utf-8", { ignoreBOM: true, fatal: true });
const utf16BE = new TextDecoder("utf-16be", { ignoreBOM: true, fatal: true });
const utf16LE = new TextDecoder("utf-16le", { ignoreBOM: true, fatal: true });
function toString(logs) {
return logs.encoded ? logs.encoded.map((log2) => {
const array = base64url.decodeBytes(log2);
if (array[0] === 255 && array[1] === 254) {
return utf16LE.decode(array);
} else if (array[0] === 255 && array[1] === 254) {
return utf16BE.decode(array);
} else {
return utf8.decode(array);
}
}) : logs.plain;
}
const log = { toFile, toString };
function _dump$1(n, ordered = false) {
let tag = n["#"];
switch (n["#"]) {
case "#text":
return n.$.match(/\[(\/?(?:\w+(?:=.+?)?|\*|#))\]/g) ? `[plain]${n.$}[/plain]` : n.$;
case "li":
tag = ordered ? "#" : "*";
return `[${tag}]${n.$$.map((n2) => _dump$1(n2)).join("")}`;
case "img":
return `[${tag}=${n.$}]${n.alt}[/${tag}]`;
case "ul":
return n.$$.map((n2) => _dump$1(n2)).join("\n");
case "ol":
return n.$$.map((n2) => _dump$1(n2, true)).join("\n");
case "#collapse":
case "#spoiler":
tag = "hide";
break;
}
if (bb.is.void(n)) {
return `[${tag}]`;
} else if (bb.is.valueVoid(n)) {
return n;
} else if (bb.is.view(n)) {
return `[${tag}]${n.$$.map((x) => _dump$1(x)).join("")}[/${tag}]`;
} else if (bb.is.valueView(n)) {
return n.$ ? `[${tag}=${n.$}]${n.$$.map((x) => _dump$1(x)).join("")}[/${tag}]` : `[${tag}]${n.$$.map((x) => _dump$1(x)).join("")}[/${tag}]`;
} else {
throw n;
}
}
function dump$1(root) {
return root.map((node) => _dump$1(node)).join("").trim();
}
const bbcode$1 = { ...bb, dump: dump$1 };
function dic(def) {
def.lang = "zh";
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const gazelle2 = await getGazelle(site2, payload);
if (gazelle2) {
await adaptAuto(gazelle2);
await new Promise((resolve) => setTimeout(resolve, 1e3));
await adaptDescriptions(payload.record, callback);
} else {
await adaptUniversal(site2, payload.record, callback);
}
if (record.item.logs) {
await adaptLogs(record.item.logs, record.group.name);
}
};
return true;
}
function jpopsuki(def) {
def.lang = "native";
def.validate = void 0;
def.extract = async (site2, callback) => {
$(".group_torrent:not(.edition)").each((_, header) => {
let initialised = false;
let busy = false;
const details = header.nextElementSibling;
if (details?.classList?.contains("pad") !== true) return;
const header_buttons = $(header).find("> td > span");
const repost_button = $("<a>RE</a>").attr("href", "#repost")[0];
header_buttons.find("> a").last().after(document.createTextNode(" | "), repost_button);
repost_button.onclick = async () => {
const torrent_url = header_buttons.children().filter((_2, e) => e instanceof HTMLAnchorElement).map((_2, e) => new URL(e.href, location.href)).filter((_2, url) => url.searchParams.get("action") === "download")[0];
const links_container = $(details).removeClass("hide").find("blockquote + blockquote").first();
if (!links_container.hasClass("ostrich")) {
links_container.addClass("ostrich").append($("<br>"), $("<br>"));
}
if (initialised || busy) return;
busy = true;
try {
const links = $(`<span>`).text("Repost to...").appendTo(links_container);
const h2 = $("h2").single();
const h3 = $("h3").get(0);
const header_info = header_buttons[0].nextElementSibling;
const type = h2.firstChild?.textContent?.match(/\[([^\]]+)\]/)?.[1] ?? "";
const latin_artist = h2.querySelector("a")?.textContent?.trim() ?? "";
const [, latin_title = "", date = ""] = h2.lastChild?.textContent?.trim()?.match(/^-\s*(.+?)\s*\[([\d.]+)\]$/) ?? [];
let native_artist = h3.querySelector("a")?.textContent?.trim();
let [, native_title = void 0] = h3.lastChild?.textContent?.trim().match(/^-\s*(.+?)\s*\)$/) ?? [];
if (native_artist == latin_artist) native_artist = void 0;
if (native_title == latin_title) native_title = void 0;
const [, format = "", encoding = "", media = ""] = header_info?.textContent?.match(
/(\w.+?)\s*\/\s*(\w.+?)\s*\/\s*(\w.+?)\s*$/
) ?? [];
const record = {
site: site2.name,
group: {
type,
name: native_title ? {
latin: latin_title,
native: native_title
} : latin_title,
artists: [
native_artist ? {
latin: latin_artist,
native: native_artist
} : latin_artist
],
guests: $(
'.box:has(.head:contains("Contributing Artists")) .stats.nobullet'
).first().find("li a:first-of-type").toArray().map((a) => a.textContent).filter((t) => t !== void 0),
composers: [],
conductor: [],
producer: [],
dj: [],
remixer: [],
label: "",
catalogue: "",
year: parseInt(date.slice(0, 4)),
image: $(".sidebar a:has(img)").get(0)?.href ?? "",
description_tree: bbcode$1.fromHTML(
$(".torrent_table + .box .body").single(),
new URL(location.href)
)
},
item: {
media,
encoding,
format,
scene: false,
uploaded_by: "",
description_tree: $(details).find("blockquote + blockquote + blockquote").first().map((_2, bq) => bbcode$1.fromHTML(bq, new URL(location.href))).toArray() ?? []
}
};
await callback(links, {
torrent: torrent_url.toString(),
record
});
initialised = true;
} finally {
busy = false;
}
};
});
};
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const gazelle2 = await getGazelle(site2, payload);
trySelect($("#categories").single(), record.group.type);
const artist = record.group.artists[0];
if (typeof artist === "string") {
$("#artist").single().value = artist;
} else {
$("#artist").single().value = artist.latin;
$("#artistjp").single().value = artist.native;
}
if (typeof record.group.name === "string") {
$("#title").single().value = record.group.name;
} else {
$("#title").single().value = record.group.name.latin;
$("#titlejp").single().value = record.group.name.native;
}
$("#releasedate").single().value = record.group.year?.toString() ?? "";
if (record.item.name || record.item.year && record.item.year !== record.group.year) {
$("#remaster").single().click();
await new Promise((resolve) => setTimeout(resolve, 1e3));
$("#remaster_year").single().value = record.item.year?.toString() ?? "";
$("#remaster_title").single().value = record.item.name ?? "";
}
await adaptUniversalCore(record, callback);
if (gazelle2) {
$("#tags").single().value = gazelle2.group.tags.join(",");
}
};
}
function ops(def) {
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const gazelle2 = await getGazelle(site2, payload);
if (gazelle2) {
await adaptAuto(gazelle2);
} else {
await adaptUniversal(site2, payload.record, callback);
}
if (record.item.logs) {
await adaptLogs(record.item.logs, record.group.name);
}
};
}
function redacted(def) {
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const gazelle2 = await getGazelle(site2, payload);
await adaptUniversal(site2, record, callback);
if (record.item.logs) {
await adaptLogs(record.item.logs, record.group.name);
}
if (gazelle2) {
adaptGazelle(site2, gazelle2);
}
};
}
const encoder = new TextEncoder();
function _toRecord(site2, e, base2, logs) {
const group_bb = e.group.bbBody ?? e.group.wikiBBcode;
return {
site: site2.name,
group: {
type: site2.selects?.releaseType[e.group.releaseType.toString()] ?? e.group.releaseType.toString(),
name: l10n.parse(unescapeHtml(e.group.name)),
artists: e.group.musicInfo.artists.map((a) => l10n.parse(a.name)),
guests: e.group.musicInfo.with.map((a) => l10n.parse(a.name)),
composers: e.group.musicInfo.composers.map((a) => l10n.parse(a.name)),
conductor: e.group.musicInfo.conductor.map((a) => l10n.parse(a.name)),
producer: e.group.musicInfo.producer.map((a) => l10n.parse(a.name)),
dj: e.group.musicInfo.dj.map((a) => l10n.parse(a.name)),
remixer: e.group.musicInfo.remixedBy.map((a) => l10n.parse(a.name)),
description: group_bb ? unescapeHtml(group_bb) : void 0,
description_tree: bb.fromHTML(new DOMParser().parseFromString(`<html><body>${e.group.wikiBody}</body></html>`, "text/html").body, base2),
label: unescapeHtml(e.group.recordLabel),
catalogue: unescapeHtml(e.group.catalogueNumber),
year: e.group.year,
image: e.group.wikiImage
},
item: {
name: unescapeHtml(e.torrent.remasterTitle),
description: unescapeHtml(e.torrent.description),
label: unescapeHtml(e.torrent.remasterRecordLabel),
catalogue: unescapeHtml(e.torrent.remasterCatalogueNumber),
year: e.torrent.remasterYear,
media: e.torrent.media,
encoding: e.torrent.encoding,
format: e.torrent.format,
scene: e.torrent.scene,
uploaded_by: e.torrent.username,
logs
}
};
}
function _mostCommon(array, invalid) {
let compare = 0;
let common = invalid;
array.reduce((acc, val) => {
if (val in acc) {
acc[val]++;
} else {
acc[val] = 1;
}
if (acc[val] > compare) {
compare = acc[val];
common = val;
}
return acc;
}, {});
return common;
}
function _recoverLog(log2) {
if (log2.startsWith("Exact Audio Copy") || log2.startsWith("EAC extraction logfile")) {
return log2.replace("\r\n", "\n").replace(/^Used [Dd]rive( +: .+?)(?: \(not found in database\))?$/m, "Used drive$1").replace(/Additional command line options +: .+(\n.+)+/m, (sub) => sub.replace("\n", "")).split("\n\n").map((block) => {
let lines = block.split("\n");
if (lines.some((line) => line.startsWith("Delete leading and trailing silent blocks"))) {
const common_pos = _mostCommon(lines.map((line) => line.indexOf(":")), -1);
lines = lines.map((line) => {
const pos = line.indexOf(":");
return line.slice(0, pos).padEnd(common_pos) + line.slice(pos);
});
}
return lines.join("\n");
}).join("\n\n").replace("\n", "\r\n");
} else if (log2.startsWith("X Lossless Decoder") || log2.startsWith("XLD extraction logfile")) {
return log2.replace("\r\n", "\n").replace(/^Used [Dd]rive( +: .+?)(?: \(not found in database\))?$/m, "Used drive$1").replace(/(Absolute +\| +Relative +\| +Confidence)$/m, "$1 ").replace(/(?<!\n)\n(\n\nAccurateRip)/, "$1");
} else {
console.warn(log2);
return log2;
}
}
async function extract(site2, callback) {
$("tr.torrent_row, .group_torrent:not(.edition)").each((_, header) => {
let initialised = false;
let busy = false;
const header_buttons = $(header).find(".torrent_action_buttons, .td_info > span");
const repost_button = $("<a>RE</a>").attr("href", "#repost")[0];
header_buttons.find("> a").last().after(document.createTextNode(" | "), repost_button);
repost_button.onclick = async () => {
const torrent_url = header_buttons.children().filter((_2, e) => e instanceof HTMLAnchorElement).map((_2, e) => new URL(e.href, location.href)).filter((_2, url) => url.searchParams.get("action") === "download")[0];
const torrent_id = torrent_url.searchParams.get("id");
let links_container;
if (header.id) {
links_container = $(`#torrent_${torrent_id}`).removeClass("hidden").find("blockquote").first();
if (!links_container.hasClass("ostrich")) {
links_container.addClass("ostrich").append($("<br>"), $("<br>"));
}
} else {
links_container = $(header).next();
if (links_container.length === 0 || !links_container.hasClass("torrentdetails")) {
links_container = $(`<td>`).attr("colspan", 9).appendTo($(`<tr>`).addClass("torrentdetails").addClass("pad").insertAfter(header));
}
}
if (initialised || busy)
return;
busy = true;
try {
const links = $(`<span>`).text("Repost to...").appendTo(links_container);
const gazelle_url = new URL(`/ajax.php?action=torrent&id=${torrent_id}`, location.href).toString();
const record = await xmlHttpRequest({
method: "GET",
url: gazelle_url,
responseType: "json"
}).then(async (event) => {
let r = event.response;
if (r.status !== "success") {
throw r.error;
}
let logs;
if (r.response.torrent.hasLog) {
logs = await xmlHttpRequest({
method: "GET",
url: `${site2.exclude.download}?action=${site2.actions?.log || _throw(site2)}&torrentid=${torrent_id}`,
responseType: "document"
}).then(async (event2) => {
const body = $(event2.response?.body);
const sections = body.find(".log_section");
if (sections.length) {
return {
encoded: await Promise.all(sections.toArray().map(async (section) => {
const event3 = await xmlHttpRequest({
method: "GET",
url: new URL(($(section).find("a.brackets")[0] ?? _throw(section)).href, location.href).toString(),
responseType: "arraybuffer"
});
return base64url.encodeBytes(new Uint8Array(event3.response));
})),
score: r.response.torrent.logScore
};
} else {
return {
plain: body.find("pre").map((_2, pre) => pre.textContent).toArray().map(_recoverLog),
recovered: true,
score: r.response.torrent.logScore
};
}
});
} else {
logs = void 0;
}
return _toRecord(site2, r.response, new URL(location.href), logs);
});
links.text("Repost to: ");
await callback(links, {
torrent: torrent_url.toString(),
record,
gazelle: gazelle_url
});
initialised = true;
} finally {
busy = false;
}
};
});
}
async function validate(callback) {
await callback($("#upload_logs .label"), "#file[name^=logfiles], #logfile_1[name^=logfile]");
const form = $("#dynamic_form")[0];
if (form) {
onDescendantAdded($(form).single(), false, async (node) => {
const label = $(node).find("#upload_logs .label");
if (label.length) {
await callback(label, "#file[name^=logfiles], #logfile_1[name^=logfile]");
}
});
}
}
async function getJson(gazelle2, type) {
return xmlHttpRequest({
method: "GET",
url: gazelle2,
responseType: type
}).then((event) => event.response);
}
async function getGazelle(site2, payload) {
if (payload["gazelle"]) {
const json = await getJson(payload["gazelle"], "json");
if (json.status === "failure") {
throw json;
}
json.response.group.name = l10n.format(l10n.parse(json.response.group.name), site2.lang);
json.response.group.musicInfo.artists = json.response.group.musicInfo.artists.map((a) => ({
...a,
name: l10n.format(l10n.parse(a.name), site2.lang)
}));
return json.response;
}
return void 0;
}
async function adaptAuto(gazelle2) {
const json_input = $("#torrent-json-file").single();
const response = {
status: "success",
response: gazelle2
};
json_input.files = toDataTransfer(new File([encoder.encode(JSON.stringify(response)).buffer], "gazelle.json", {
type: "application/json"
})).files;
await nextMutation($("#dynamic_form").single(), "childList", void 0, void 0, json_input);
}
function _adaptArtistRole(role) {
switch (role) {
case "artists":
return "1";
case "with":
case "guests":
return "2";
case "composers":
return "3";
case "conductor":
return "4";
case "dj":
return "5";
case "remixedBy":
case "remixer":
return "6";
case "producer":
return "7";
default:
throw role;
}
}
async function adaptDescriptions(record, callback) {
await callback($("tr:has(#album_desc) > .label"), $("#album_desc"), dumpDescriptions([record.group], bbcode$1.dump));
await callback($("tr:has(#release_desc) > .label"), $("#release_desc"), dumpDescriptions([record.item], bbcode$1.dump));
}
function adaptNames(name, artists) {
$("#title").single().value = name;
const [artist_add, artist_rm] = $("#artistfields .brackets").toArray();
while ($(`#artist_1`).length > 0) {
artist_rm.click();
}
artists.forEach(([artist, role], i) => {
let input;
if (i === 0) {
input = $("#artist").single();
} else {
artist_add.click();
input = $(`#artist_${i}`).single();
}
input.value = artist;
input.nextElementSibling.value = _adaptArtistRole(role);
});
}
async function adaptUniversalCore(record, callback) {
const format_select = $("#format").single();
trySelect(format_select, record.item.format);
$(format_select).trigger("change");
const encoding_select = $("#bitrate").single();
if (!trySelect(encoding_select, record.item.encoding)) {
trySelect(encoding_select, "Other");
$(encoding_select).trigger("change");
$("#other_bitrate").single().value = record.item.encoding;
}
trySelect($("#media, select[name=media]").single(), record.item.media);
$("#image").single().value = record.group.image;
await adaptDescriptions(record, callback);
}
async function adaptUniversal(site2, record, callback) {
const artists = Object.keys(record.group).filter((k) => ( (() => {
return (input) => "artists" === input || "composers" === input || "conductor" === input || "dj" === input || "producer" === input || "guests" === input || "remixer" === input;
})())(k)).flatMap((role) => record.group[role].map((artist) => [
l10n.format(artist, site2.lang),
role
]));
adaptNames(l10n.format(record.group.name, site2.lang), artists);
$("#year").single().value = record.group.year.toString();
$("#remaster_year").single().value = record.item.year?.toString() ?? "";
$("#remaster_title").single().value = record.item.name ?? "";
$("#remaster_record_label").single().value = record.item.label ?? "";
$("#remaster_catalogue_number").single().value = record.item.catalogue ?? "";
await adaptUniversalCore(record, callback);
}
function _adaptReleaseType(select, value, source, target) {
const name = Object.entries(data.gazelle[source].selects.releaseType).find(([k, _v]) => k === value)?.[1]?.toLowerCase();
if (!name)
return;
const mapped = Object.entries(data.gazelle[target].selects.releaseType).find(([_, v]) => v.toLowerCase() === name)?.[0];
if (mapped === void 0)
return;
select.value = mapped;
}
async function adaptGazelle(site2, gazelle2) {
const group = gazelle2.group;
const release = gazelle2.torrent;
const artists = Object.entries(group.musicInfo).flatMap(([role, artists2]) => {
return artists2.map((artist) => [artist.name, role]);
});
adaptNames(group.name, artists);
if (( (() => {
return (input) => "DIC" === input || "JPopsuki" === input || "OPS" === input || "Redacted" === input;
})())(site2.name)) {
_adaptReleaseType($("#releasetype").single(), group.releaseType.toString(), site2.name, "Redacted");
} else {
console.warn(site2.name);
}
if (release.scene) {
$("#scene").single().click();
}
$("#tags").single().value = group.tags.join(",");
}
async function adaptLogs(logs, name) {
const log_input = $("#file[name^=logfiles], #logfile_1[name^=logfile]").single();
log_input.files = toDataTransfer(log.toFile(logs, l10n.select(name, "native"))).files;
}
function gazelle(framework) {
Object.entries(framework).forEach(([st, site2]) => {
site2.extract = extract;
site2.validate = validate;
switch (st) {
case "DIC":
return dic(site2);
case "JPopsuki":
return jpopsuki(site2);
case "OPS":
return ops(site2);
case "Redacted":
return redacted(site2);
}
});
}
const _is = {
void: (node) => ( (() => {
return (input) => "hr" === input;
})())(node["#"]),
valueVoid: (node) => ( (() => {
return (input) => "img" === input;
})())(node["#"]),
view: (node) => ( (() => {
const _iv1 = new Set(["b", "i", "u", "s", "center", "sup", "sub", "mask", "pre", "*", "table", "tr", "td"]);
return (input) => true === _iv1.has(input);
})())(node["#"]),
valueView: (node) => ( (() => {
return (input) => "color" === input || "font" === input || "url" === input || "quote" === input || "hide" === input || "code" === input || "size" === input;
})())(node["#"])
};
function _dump(n, depth = -1) {
let np = (() => {
switch (n["#"]) {
case "h":
return ValueView("size")(8 - n.$, n.$$);
case "code":
return ValueView("font")("monospace", n.$$);
case "#spoiler":
return { ...n, "#": "mask" };
case "align":
if (n.$ === "center") {
return View("center")(n.$$);
} else {
console.warn(n);
return n.$$.map((c) => _dump(c, depth)).join("");
}
case "#collapse":
return { ...n, "#": "hide" };
case "li":
console.warn(n);
return { ...n, "#": "*" };
case "ul":
++depth;
return n.$$.map((li) => `${" ".repeat(depth)}[*] ${li.$$.map((c) => _dump(c, depth)).join()}`).join("\n");
case "ol":
++depth;
return n.$$.map((li, i) => `${" ".repeat(depth)}[*] ${i + 1}. ${li.$$.map((c) => _dump(c, depth)).join()}`).join("\n");
default:
return n;
}
})();
if (typeof np === "string") {
return np;
}
switch (np["#"]) {
case "#text":
return np.$.replace(/\[(\/?(?:\w+(?:=.+?)?|\*|#))\]/g, "[$1]");
case "*":
return `[${np["#"]}]${np.$$.map((n2) => _dump(n2)).join("")}`;
}
if (_is.void(np)) {
return `[${np["#"]}]`;
} else if (_is.valueVoid(np)) {
return np.$ ? `[${np["#"]}=${np.$}]` : `[${np["#"]}]`;
} else if (_is.view(np)) {
return `[${np["#"]}]${np.$$.map((c) => _dump(c)).join("")}[/${np["#"]}]`;
} else if (_is.valueView(np)) {
return np.$ ? `[${np["#"]}=${np.$}]${np.$$.map((c) => _dump(c)).join("")}[/${np["#"]}]` : `[${np["#"]}]${np.$$.map((c) => _dump(c)).join("")}[/${np["#"]}]`;
} else {
throw n;
}
}
function dump(root) {
return root.map((node) => _dump(node)).join("").trim();
}
const bbcode = { dump };
function opencd(def) {
def.lang = "native";
def.validate = async (callback) => {
await callback($(".rowhead[msg^=NFO]"), "input[name^=nfo1]");
};
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const cover_task = xmlHttpRequest({
method: "GET",
url: record.group.image,
responseType: "arraybuffer"
}).then((event) => {
const transfer = toDataTransfer(
new File(
[event.response],
new URL(event.finalUrl).pathname.split("/").filter((x) => x).at(-1)?.substring(1) ?? _throw(event),
{
type: parseHeaders(event.responseHeaders)["content-type"].split(
";"
)[0]
}
)
);
$("td:has(> #cover) iframe").single().contentDocument.querySelector("#file").files = transfer.files;
});
const desc_parent = $("#editer_description").single();
if (desc_parent.children.length === 0) {
await nextMutation(desc_parent, "childList");
}
$("#browsecat").single().value = "408";
$("#artist").single().value = record.group.artists.map((a) => l10n.format(a, site2.lang)).join(" / ");
$("#resource_name").single().value = l10n.format(
record.group.name,
site2.lang
);
const year = $("#year").single();
year.value = record.group.year.toString();
year.dispatchEvent(new Event("change"));
trySelect($("#standard").single(), record.item.format);
trySelect($("#medium").single(), record.item.media);
const repost_input = $("#boardid1").single();
repost_input.checked = true;
$(repost_input).trigger("change");
$("#small_descr").single().value = [
record.item.name,
record.group.year !== record.item.year && record.item.year,
record.item.label ? record.item.label : record.group.label,
record.item.catalogue ? record.item.catalogue : record.group.catalogue
].filter((i) => i).join(" / ");
if (record.item.logs) {
const log_add = $("#nfoadd").single();
log.toFile(record.item.logs, l10n.select(record.group.name, "native")).forEach(async (f, i) => {
if (i > 0) {
log_add.click();
}
$(`[name=nfo${"1".repeat(i + 1)}]`).single().files = toDataTransfer(f).files;
});
}
await callback(
$("tr:has(#descr) > .rowhead"),
$("#descr"),
dumpDescriptions([record.group, record.item], bbcode.dump)
);
await cover_task;
};
}
function tjupt(def) {
def.lang = "native";
def.adapt = async (site2, payload, callback) => {
const record = payload.record;
const select_cat = $("#browsecat").single();
select_cat.value = "406";
$(select_cat).trigger("change");
const form_div = select_cat.nextElementSibling ?? _throw(select_cat);
while (form_div.children.length <= 1)
await nextMutation(
select_cat.nextElementSibling ?? _throw(select_cat),
"childList"
);
$("#hqname").single().value = l10n.format(
record.group.name,
site2.lang
);
$("#artist").single().value = record.group.artists.map((a) => l10n.format(a, site2.lang)).join(" / ");
$("#issuedate").single().value = record.group.year.toString();
$("#specificcat").single().value = record.item.media;
$("#format").single().value = record.item.format;
$("#hqtone").single().value = record.item.encoding;
$("input[name=small_descr]").single().value = [
record.item.name,
record.group.year !== record.item.year && record.item.year,
record.item.label ? record.item.label : record.group.label,
record.item.catalogue ? record.item.catalogue : record.group.catalogue,
record.item.logs?.score && `Log (${record.item.logs.score}%)`
].filter((i) => i).join(" / ");
const logs = record.item.logs ? log.toString(record.item.logs).map((log2) => `[hide=Log][code]${log2}[/code][/hide]`).join("\n") : void 0;
await callback(
$("tr:has(#descr) > .rowhead"),
$("#descr"),
dumpDescriptions([record.group, record.item], bbcode.dump).map(
(s) => [`[img]${record.group.image}[/img]`, s, logs].filter((i) => i).join("\n[hr]\n")
)
);
};
}
function nexusphp(framework) {
Object.entries(framework).forEach(([st, site2]) => {
switch (st) {
case "OpenCD":
return opencd(site2);
case "TJUPT":
return tjupt(site2);
}
});
}
gazelle(data.gazelle);
nexusphp(data.nexusphp);
function parseSites(location2) {
if (location2.hostname.toLowerCase() === "logs.musichoarders.xyz") {
return ["gazelle", {}, "validate"];
}
const [fw2, st, site2] = Object.entries(data).flatMap(
([fw22, framework]) => Object.entries(framework).map(
([st2, site22]) => [fw22, st2, site22]
)
).find(([_f, _s, site22]) => location2.hostname.endsWith(site22.hostname)) ?? _throw(location2);
const [cat2] = Object.entries(site2.include).find(([cat22, fw_path]) => {
const path = site2.include?.[cat22] ?? fw_path;
return path instanceof Array ? path.filter((path2) => path2 === location2.pathname).length > 0 : path === location2.pathname;
}) ?? _throw(location2);
return [fw2, { ...site2, name: st }, cat2];
}
function dumpDescriptions(descriptions, dump2) {
const array = descriptions.map((d) => [
d.description,
d.description_tree ? dump2(d.description_tree) : void 0
]);
function* _join() {
if (array[0][0] !== void 0) {
yield [array[0][0], ...array.slice(1).map((p) => p[0] ?? p[1] ?? "")].filter((d) => d).join("\n[hr]\n");
}
if (array[0][1] !== void 0) {
yield [array[0][1], ...array.slice(1).map((p) => p[1] ?? p[0] ?? "")].filter((d) => d).join("\n[hr]\n");
}
}
return Array.from(_join());
}
const [fw, site, cat] = parseSites(location);
if (cat === "validate") {
const psuedo_url = new URL(
new URL(location.href).hash.substring(1),
location.origin
);
if (psuedo_url.pathname === "/ostrich") {
const input = document.querySelector("#cursorfiles");
if (input) {
input.files = toDataTransfer(
new File(
[base64url.decodeBytes(psuedo_url.hash.slice(1))],
"text.log",
{
type: "text/plain"
}
)
).files;
await( new Promise((resolve) => setTimeout(resolve, 1e3)));
input.dispatchEvent(new Event("change"));
}
}
} else {
if ($?.fn?.jquery == void 0) {
$ = jQuery?.fn?.jquery ? jQuery : await( import(
"https://cdn.jsdelivr.net/npm/jquery@3/dist/jquery.slim.min.js"
));
}
$.fn.extend({
single() {
return this.length === 1 ? this[0] : _throw(this);
}
});
if (cat === "source") {
if (site.extract) {
await( site.extract(site, async (container, payload) => {
console.debug(payload);
const params = new URLSearchParams();
Object.entries(payload).forEach(([k, v]) => {
params.set(k, marshal(v));
});
const p = params.toString();
Object.entries(data).flatMap(([_fw, framework]) => Object.entries(framework)).filter(
([_st, site2]) => site2.adapt && !location.hostname.endsWith(site2.hostname)
).forEach(([st, site2], s) => {
if (s !== 0) {
container.append(document.createTextNode(" · "));
}
$(`<a>`).appendTo(container).text(st).attr("target", "_blank").attr(
"href",
`https://${site2.hostname}${site2.include.target}#ostrich?${p}`
);
});
}));
}
} else if (cat === "target") {
const psuedo_url = new URL(
new URL(location.href).hash.substring(1),
location.origin
);
if (site.validate) {
await( site.validate(async (container, selector) => {
const anchor = $("<a>").appendTo(container.append($("<br>"))).text("Validate").attr("href", "#_ostrich").single();
anchor.onclick = async () => {
await Promise.all(
$(selector).toArray().filter((input) => input.files).flatMap((input) => [...input.files]).map(async (file) => {
window.open(
`https://logs.musichoarders.xyz#ostrich#${base64url.encodeBytes(new Uint8Array(await file.arrayBuffer()))}`,
"_blank"
);
})
);
};
}));
}
if (psuedo_url.pathname === "/ostrich") {
const payload = Object.fromEntries(
[...psuedo_url.searchParams.entries()].map(([k, v]) => [
k,
unmarshal(v)
])
);
const record = payload.record;
console.debug(payload);
const torrent_task = xmlHttpRequest({
method: "GET",
url: payload.torrent,
responseType: "arraybuffer"
}).then((event) => {
return toDataTransfer(
new File(
[event.response],
`${encodeURIComponent(l10n.select(record.group.name, "native"))}.torrent`,
{ type: "application/x-bittorrent" }
)
);
});
if (site.adapt) {
switch (fw) {
case "gazelle":
await( torrent_task.then((data2) => {
$("#file[name=file_input]").single().files = data2.files;
}));
break;
case "nexusphp":
await( torrent_task.then((data2) => {
$("#torrent").single().files = data2.files;
}));
break;
}
await( site.adapt(
site,
payload,
async (container, input, selections) => {
selections = selections.filter((s) => s);
if (selections.length >= 1) {
input.single().value = selections[0];
if (selections.length > 1) {
const anchor = $("<a>").appendTo(container.append($("<br>"))).text("Toggle").attr("href", "#_ostrich").single();
anchor.onclick = () => {
selections.push(selections.shift());
input.single().value = selections[0];
};
}
}
}
));
}
}
}
}
})();