您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Automatically sort teaser images on /videos, /images, /subscriptions, /users, /playlist, and sidebars using customizable sort function. Can load and sort multiple pages at once.
当前为
// ==UserScript== // @name Iwara Custom Sort // @version 1.0.7 // @description Automatically sort teaser images on /videos, /images, /subscriptions, /users, /playlist, and sidebars using customizable sort function. Can load and sort multiple pages at once. // @match http://ecchi.iwara.tv/* // @match https://ecchi.iwara.tv/* // @match http://www.iwara.tv/* // @match https://www.iwara.tv/* // @name:ja Iwara Custom ソート // @run-at document-end // @grant GM.setValue // @grant GM.getValue // @grant GM.deleteValue // @grant GM.listValues // @license AGPL-3.0-or-later // @description:ja /videos、/images、/subscriptions、/users、/playlistとサイドバーのサムネイルを自動的にソートします。ソート方法はカスタマイズすることができます、一度に複数のページを読み込んでソートすることができます。 // @require https://cdn.jsdelivr.net/npm/[email protected]/dist/sweetalert2.all.min.js#sha384-hmoGfyRv5Xg6BFqj6C1jQJ0y5HEpsJSc6VpsKkj0NgyiPevl9FNVNxEFpxKFNUaX // @require https://unpkg.com/[email protected]/dist/loglevel.min.js#sha384-7gGuWfek8Ql6j/uNDFrS0BCe4x2ZihD4B68w9Eu580OVHJBV+bl3rZmEWC7q5/Gj // @require https://unpkg.com/[email protected]/bundles/rxjs.umd.min.js#sha384-+VJt6dSQYKxS5YwAGX+zSPDqOcLAUx2tCjV8jSWnyJH8hWTgrHSZAt1106u1VmLn // @require https://unpkg.com/[email protected]/mithril.min.js#sha384-vo9crXih40MlEv6JWHqS7SsPiFp+76csaWQFOF2UU0/xI58Jm/ZvK/1UtpaicJT9 // @namespace https://gf.qytechs.cn/users/245195 // ==/UserScript== /* jshint esversion: 6 */ (() => { const __webpack_modules__ = { 923(module, exports, __webpack_require__) { let __WEBPACK_AMD_DEFINE_RESULT__; !(function (globals) { let messages; let predicates; let functions; let assert; let not; let maybe; let collections; let hasOwnProperty; let toString; let keys; let slice; let isArray; let neginf; let posinf; let haveSymbols; let haveMaps; let haveSets; function assigned(data) { return data != null; } function number(data) { return typeof data === 'number' && data > neginf && data < posinf; } function integer(data) { return typeof data === 'number' && data % 1 == 0; } function greater(lhs, rhs) { return number(lhs) && lhs > rhs; } function less(lhs, rhs) { return number(lhs) && lhs < rhs; } function greaterOrEqual(lhs, rhs) { return number(lhs) && lhs >= rhs; } function lessOrEqual(lhs, rhs) { return number(lhs) && lhs <= rhs; } function string(data) { return typeof data === 'string'; } function nonEmptyString(data) { return string(data) && data !== ''; } function object(data) { return toString.call(data) === '[object Object]'; } function some(data, predicate) { for (const key in data) if (hasOwnProperty.call(data, key) && predicate(key, data[key])) return !0; return !1; } function instanceStrict(data, prototype) { try { return data instanceof prototype; } catch (error) { return !1; } } function like(data, archetype) { let name; for (name in archetype) { if (hasOwnProperty.call(archetype, name)) { if (!1 === hasOwnProperty.call(data, name) || typeof data[name] !== typeof archetype[name]) return !1; if (object(data[name]) && !1 === like(data[name], archetype[name])) return !1; } } return !0; } function arrayLike(data) { return assigned(data) && data.length >= 0; } function iterable(data) { return haveSymbols ? assigned(data) && isFunction(data[Symbol.iterator]) : arrayLike(data); } function contains(data, value) { let iterator; let iteration; if (!assigned(data)) return !1; if (haveSets && instanceStrict(data, Set)) return data.has(value); if (string(data)) return data.indexOf(value) !== -1; if (haveSymbols && data[Symbol.iterator] && isFunction(data.values)) { iterator = data.values(); do { if ((iteration = iterator.next()).value === value) return !0; } while (!iteration.done); return !1; } return some(data, ((key, dataValue) => dataValue === value)); } function containsKey(data, key) { return !!assigned(data) && (haveMaps && instanceStrict(data, Map) ? data.has(key) : !(iterable(data) && !number(+key)) && !!data[key]); } function isFunction(data) { return typeof data === 'function'; } function forEach(object, action) { for (const key in object)hasOwnProperty.call(object, key) && action(key, object[key]); } function testArray(data, result) { let i; for (i = 0; i < data.length; i += 1) if (data[i] === result) return result; return !result; } function testObject(data, result) { let key; let value; for (key in data) { if (hasOwnProperty.call(data, key)) { if (object(value = data[key]) && testObject(value, result) === result) return result; if (value === result) return result; } } return !result; } function mixin(target, source) { return forEach(source, ((key, value) => { target[key] = value; })), target; } function assertModifier(predicate, defaultMessage) { return function () { const args = arguments; const argCount = predicate.l || predicate.length; const message = args[argCount]; const ErrorType = args[argCount + 1]; return assertImpl(predicate.apply(null, args), nonEmptyString(message) ? message : defaultMessage.replace('{a}', messageFormatter(args[0])).replace('{e}', messageFormatter(args[1])).replace('{e2}', messageFormatter(args[2])).replace('{t}', (() => { const arg = args[1]; return arg && arg.name ? arg.name : arg; })), isFunction(ErrorType) ? ErrorType : TypeError), args[0]; }; } function messageFormatter(arg) { return function () { return string(arg) ? `"${arg.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` : arg && !0 !== arg && arg.constructor && !instanceStrict(arg, RegExp) && typeof arg !== 'number' ? arg.constructor.name : arg; }; } function assertImpl(value, message, ErrorType) { if (value) return value; throw new (ErrorType || Error)(message || 'assert failed'); } function notModifier(predicate) { const modifiedPredicate = function () { return notImpl(predicate.apply(null, arguments)); }; return modifiedPredicate.l = predicate.length, modifiedPredicate; } function notImpl(value) { return !value; } function ofModifier(target, type, predicate) { const modifiedPredicate = function () { let collection; let args; if (collection = arguments[0], target === 'maybe' && not.assigned(collection)) return !0; if (!type(collection)) return !1; collection = coerceCollection(type, collection), args = slice.call(arguments, 1); try { collection.forEach(((item) => { if ((target !== 'maybe' || assigned(item)) && !predicate.apply(null, [item].concat(args))) throw 0; })); } catch (ignore) { return !1; } return !0; }; return modifiedPredicate.l = predicate.length, modifiedPredicate; } function coerceCollection(type, collection) { switch (type) { case arrayLike: return slice.call(collection); case object: return keys(collection).map(((key) => collection[key])); default: return collection; } } function createModifiedPredicates(modifier, object) { return createModifiedFunctions([modifier, predicates, object, '']); } function createModifiedFunctions(args) { let modifier; let messageModifier; let object; return modifier = args.shift(), messageModifier = args.pop(), object = args.pop(), forEach(args.pop(), ((key, fn) => { let message = messages[key]; message && messageModifier && (message = message.replace('to', `${messageModifier}to`)), Object.defineProperty(object, key, { configurable: !1, enumerable: !0, writable: !1, value: modifier.apply(null, args.concat(fn, message)), }); })), object; } function createModifiedModifier(modifier, modified, messageModifier) { return createModifiedFunctions([modifier, modified, {}, messageModifier]); } function createOfModifiers(base, modifier) { collections.forEach(((key) => { base[key].of = createModifiedModifier(modifier, predicates[key].of); })); } messages = {}, predicates = {}, [ { n: 'equal', f(lhs, rhs) { return lhs === rhs; }, s: 'equal {e}', }, { n: 'undefined', f(data) { return void 0 === data; }, s: 'be undefined', }, { n: 'null', f(data) { return data === null; }, s: 'be null', }, { n: 'assigned', f: assigned, s: 'be assigned', }, { n: 'primitive', f(data) { let type; switch (data) { case null: case void 0: case !1: case !0: return !0; } return (type = typeof data) === 'string' || type === 'number' || haveSymbols && type === 'symbol'; }, s: 'be primitive type', }, { n: 'contains', f: contains, s: 'contain {e}', }, { n: 'in', f(value, data) { return contains(data, value); }, s: 'be in {e}', }, { n: 'containsKey', f: containsKey, s: 'contain key {e}', }, { n: 'keyIn', f(key, data) { return containsKey(data, key); }, s: 'be key in {e}', }, { n: 'zero', f(data) { return data === 0; }, s: 'be 0', }, { n: 'one', f(data) { return data === 1; }, s: 'be 1', }, { n: 'infinity', f(data) { return data === neginf || data === posinf; }, s: 'be infinity', }, { n: 'number', f: number, s: 'be Number', }, { n: 'integer', f: integer, s: 'be integer', }, { n: 'float', f(data) { return number(data) && data % 1 != 0; }, s: 'be non-integer number', }, { n: 'even', f(data) { return typeof data === 'number' && data % 2 == 0; }, s: 'be even number', }, { n: 'odd', f(data) { return integer(data) && data % 2 != 0; }, s: 'be odd number', }, { n: 'greater', f: greater, s: 'be greater than {e}', }, { n: 'less', f: less, s: 'be less than {e}', }, { n: 'between', f(data, x, y) { if (x < y) return greater(data, x) && data < y; return less(data, x) && data > y; }, s: 'be between {e} and {e2}', }, { n: 'greaterOrEqual', f: greaterOrEqual, s: 'be greater than or equal to {e}', }, { n: 'lessOrEqual', f: lessOrEqual, s: 'be less than or equal to {e}', }, { n: 'inRange', f(data, x, y) { if (x < y) return greaterOrEqual(data, x) && data <= y; return lessOrEqual(data, x) && data >= y; }, s: 'be in the range {e} to {e2}', }, { n: 'positive', f(data) { return greater(data, 0); }, s: 'be positive number', }, { n: 'negative', f(data) { return less(data, 0); }, s: 'be negative number', }, { n: 'string', f: string, s: 'be String', }, { n: 'emptyString', f(data) { return data === ''; }, s: 'be empty string', }, { n: 'nonEmptyString', f: nonEmptyString, s: 'be non-empty string', }, { n: 'match', f(data, regex) { return string(data) && !!data.match(regex); }, s: 'match {e}', }, { n: 'boolean', f(data) { return !1 === data || !0 === data; }, s: 'be Boolean', }, { n: 'object', f: object, s: 'be Object', }, { n: 'emptyObject', f(data) { return object(data) && !some(data, (() => !0)); }, s: 'be empty object', }, { n: 'nonEmptyObject', f(data) { return object(data) && some(data, (() => !0)); }, s: 'be non-empty object', }, { n: 'instanceStrict', f: instanceStrict, s: 'be instanceof {t}', }, { n: 'thenable', f(data) { return assigned(data) && isFunction(data.then); }, s: 'be promise-like', }, { n: 'instance', f(data, prototype) { try { return instanceStrict(data, prototype) || data.constructor.name === prototype.name || toString.call(data) === `[object ${prototype.name}]`; } catch (error) { return !1; } }, s: 'be {t}', }, { n: 'like', f: like, s: 'be like {e}', }, { n: 'array', f(data) { return isArray(data); }, s: 'be Array', }, { n: 'emptyArray', f(data) { return isArray(data) && data.length === 0; }, s: 'be empty array', }, { n: 'nonEmptyArray', f(data) { return isArray(data) && data.length > 0; }, s: 'be non-empty array', }, { n: 'arrayLike', f: arrayLike, s: 'be array-like', }, { n: 'iterable', f: iterable, s: 'be iterable', }, { n: 'date', f(data) { return instanceStrict(data, Date) && integer(data.getTime()); }, s: 'be valid Date', }, { n: 'function', f: isFunction, s: 'be Function', }, { n: 'hasLength', f(data, length) { return assigned(data) && data.length === length; }, s: 'have length {e}', }, { n: 'throws', f(data) { if (!isFunction(data)) return !1; try { data(); } catch (error) { return !0; } return !1; }, s: 'throw', }, ].map(((data) => { const { n, } = data; messages[n] = `assert failed: expected {a} to ${data.s}`, predicates[n] = data.f; })), functions = { map: function map(data, predicates) { let result; result = isArray(data) ? [] : {}; if (isFunction(predicates))forEach(data, ((key, value) => { result[key] = predicates(value); })); else { isArray(predicates) || assert.object(predicates); const dataKeys = keys(data || {}); forEach(predicates, ((key, predicate) => { dataKeys.some(((dataKey, index) => dataKey === key && (dataKeys.splice(index, 1), !0))), isFunction(predicate) ? not.assigned(data) ? result[key] = !!predicate.m : result[key] = predicate(data[key]) : result[key] = map(data[key], predicate); })); } return result; }, all(data) { if (isArray(data)) return testArray(data, !1); return assert.object(data), testObject(data, !1); }, any(data) { if (isArray(data)) return testArray(data, !0); return assert.object(data), testObject(data, !0); }, }, collections = ['array', 'arrayLike', 'iterable', 'object'], hasOwnProperty = Object.prototype.hasOwnProperty, toString = Object.prototype.toString, keys = Object.keys, slice = Array.prototype.slice, isArray = Array.isArray, neginf = Number.NEGATIVE_INFINITY, posinf = Number.POSITIVE_INFINITY, haveSymbols = typeof Symbol === 'function', haveMaps = typeof Map === 'function', haveSets = typeof Set === 'function', functions = mixin(functions, predicates), assert = createModifiedPredicates(assertModifier, assertImpl), not = createModifiedPredicates(notModifier, notImpl), maybe = createModifiedPredicates(((predicate) => { const modifiedPredicate = function () { return !!not.assigned(arguments[0]) || predicate.apply(null, arguments); }; return modifiedPredicate.l = predicate.length, modifiedPredicate.m = !0, modifiedPredicate; }), ((value) => { if (!1 === assigned(value)) return !0; return value; })), assert.not = createModifiedModifier(assertModifier, not, 'not '), assert.maybe = createModifiedModifier(assertModifier, maybe, 'maybe '), collections.forEach(((key) => { predicates[key].of = createModifiedFunctions([ofModifier.bind(null, null), predicates[key], predicates, {}, '']); })), createOfModifiers(assert, assertModifier), createOfModifiers(not, notModifier), collections.forEach(((key) => { maybe[key].of = createModifiedFunctions([ofModifier.bind(null, 'maybe'), predicates[key], predicates, {}, '']), assert.maybe[key].of = createModifiedModifier(assertModifier, maybe[key].of), assert.not[key].of = createModifiedModifier(assertModifier, not[key].of); })), (function (functions) { void 0 === (__WEBPACK_AMD_DEFINE_RESULT__ = function () { return functions; }.call(exports, __webpack_require__, exports, module)) || (module.exports = __WEBPACK_AMD_DEFINE_RESULT__); }(mixin(functions, { assert, not, maybe, }))); }()); }, 780: (module) => { const createAbortError = () => { const error = new Error('Delay aborted'); return error.name = 'AbortError', error; }; const createDelay = ({ clearTimeout: defaultClear, setTimeout: set, willResolve, }) => (ms, { value, signal, } = {}) => { if (signal && signal.aborted) return Promise.reject(createAbortError()); let timeoutId; let settle; let rejectFn; const clear = defaultClear || clearTimeout; const signalListener = () => { clear(timeoutId), rejectFn(createAbortError()); }; const delayPromise = new Promise((resolve, reject) => { settle = () => { signal && signal.removeEventListener('abort', signalListener), willResolve ? resolve(value) : reject(value); }, rejectFn = reject, timeoutId = (set || setTimeout)(settle, ms); }); return signal && signal.addEventListener('abort', signalListener, { once: !0, }), delayPromise.clear = () => { clear(timeoutId), timeoutId = null, settle(); }, delayPromise; }; const delay = createDelay({ willResolve: !0, }); delay.reject = createDelay({ willResolve: !1, }), delay.range = (minimum, maximum, options) => delay(((minimum, maximum) => Math.floor(Math.random() * (maximum - minimum + 1) + minimum))(minimum, maximum), options), delay.createWithTimers = ({ clearTimeout, setTimeout, }) => { const delay = createDelay({ clearTimeout, setTimeout, willResolve: !0, }); return delay.reject = createDelay({ clearTimeout, setTimeout, willResolve: !1, }), delay; }, module.exports = delay, module.exports.default = delay; }, }; const __webpack_module_cache__ = {}; function __webpack_require__(moduleId) { if (__webpack_module_cache__[moduleId]) return __webpack_module_cache__[moduleId].exports; const module = __webpack_module_cache__[moduleId] = { exports: {}, }; return __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__), module.exports; } __webpack_require__.n = (module) => { const getter = module && module.__esModule ? () => module.default : () => module; return __webpack_require__.d(getter, { a: getter, }), getter; }, __webpack_require__.d = (exports, definition) => { for (const key in definition) { __webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key) && Object.defineProperty(exports, key, { enumerable: !0, get: definition[key], }); } }, __webpack_require__.o = (obj, prop) => Object.prototype.hasOwnProperty.call(obj, prop), (() => { const external_log_namespaceObject = log; const delay = __webpack_require__(780); const delay_default = __webpack_require__.n(delay); const check_types = __webpack_require__(923); const getTeaserContainers = (node) => Array.from(node.querySelectorAll('.views-responsive-grid, .node-playlist .field-name-field-videos')).filter((grid) => grid.querySelector('.node-teaser, .node-sidebar_teaser, .node-wide_teaser')); const src_assert = (value, message) => { (0, check_types.assert)(value, message); }; const tapNonNull = (x) => (src_assert(x), x); function function_pipe(a, ab, bc, cd, de, ef, fg, gh, hi, ij, jk, kl, lm, mn, no, op, pq, qr, rs, st) { switch (arguments.length) { case 1: return a; case 2: return ab(a); case 3: return bc(ab(a)); case 4: return cd(bc(ab(a))); case 5: return de(cd(bc(ab(a)))); case 6: return ef(de(cd(bc(ab(a))))); case 7: return fg(ef(de(cd(bc(ab(a)))))); case 8: return gh(fg(ef(de(cd(bc(ab(a))))))); case 9: return hi(gh(fg(ef(de(cd(bc(ab(a)))))))); case 10: return ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))); case 11: return jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))); case 12: return kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))); case 13: return lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))); case 14: return mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))); case 15: return no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))); case 16: return op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))); case 17: return pq(op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))))); case 18: return qr(pq(op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))))); case 19: return rs(qr(pq(op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a)))))))))))))))))); case 20: return st(rs(qr(pq(op(no(mn(lm(kl(jk(ij(hi(gh(fg(ef(de(cd(bc(ab(a))))))))))))))))))); } } const isNone = function (fa) { return fa._tag === 'None'; }; const Option_none = { _tag: 'None', }; const Option_some = function (a) { return { _tag: 'Some', value: a, }; }; function fromNullable(a) { return a == null ? Option_none : Option_some(a); } const getOrElse = function (onNone) { return function (ma) { return isNone(ma) ? onNone() : ma.value; }; }; const map_ = function (fa, f) { return isNone(fa) ? Option_none : Option_some(f(fa.value)); }; const map = function (f) { return function (fa) { return map_(fa, f); }; }; function compare(x, y) { return x < y ? -1 : x > y ? 1 : 0; } function strictEqual(a, b) { return a === b; } const ordNumber = { equals: strictEqual, compare, }; function fromCompare(compare) { const optimizedCompare = function (x, y) { return x === y ? 0 : compare(x, y); }; return { equals(x, y) { return optimizedCompare(x, y) === 0; }, compare: optimizedCompare, }; } const contramap = function (f) { return function (fa) { return fromCompare(((x, y) => fa.compare(f(x), f(y)))); }; }; contramap(((date) => date.valueOf())); const ReadonlyArray_filter = function (predicate) { return function (fa) { return fa.filter(predicate); }; }; const Array_filter = ReadonlyArray_filter; const external_m_namespaceObject = m; const external_m_default = __webpack_require__.n(external_m_namespaceObject); const external_rxjs_namespaceObject = rxjs; const external_rxjs_operators_namespaceObject = rxjs.operators; const external_Swal_namespaceObject = Swal; const external_Swal_default = __webpack_require__.n(external_Swal_namespaceObject); const classAttr = (classNames) => classNames.map((x) => `.${x}`).join(''); const conditionPresets = { 'Default Condition': '(Math.asinh(ratio * 15) / 15 / (private * 1.8 + 1) + Math.log(likes) / 230) / (image + 8)', Newest: '-index', Oldest: 'index', 'Likes / Views': 'ratio', 'Most Liked': 'likes', 'Most Viewed': 'views', }; const forwardTo = (observer) => (value) => { observer.next(value); }; const partial = (f, ...headArgs) => (...restArgs) => f(...headArgs, ...restArgs); const tapIs = (constructor, x) => (src_assert(x instanceof constructor), x); const getInputValue = (event$) => event$.pipe((0, external_rxjs_operators_namespaceObject.pluck)('currentTarget'), (0, external_rxjs_operators_namespaceObject.map)(partial(tapIs, HTMLInputElement)), (0, external_rxjs_operators_namespaceObject.pluck)('value')); const getPageParam = (URL_) => ((URL_, name) => { const param = URL_.searchParams.get(name); return param ? Number.parseInt(param, 10) : 0; })(URL_, 'page'); const reloadImage = (image) => { const { src, } = image; image.src = '', image.src = src; }; const removeEmbeddedPage = (page) => { page.src = '', page.remove(); }; const getTeaserValue = (info, condition) => { const sortParamPairs = [['index', info.initialIndex], ['views', info.viewCount], ['likes', info.likeCount], ['ratio', Math.min(info.likeCount / Math.max(1, info.viewCount), 1)], ['image', info.imageFactor], ['gallery', info.galleryFactor], ['private', info.privateFactor]]; return new Function(...sortParamPairs.map(([name]) => name), `return (${condition})`)(...sortParamPairs.map((pair) => pair[1])); }; const changeAnchorPageParam = (anchor, value) => ((anchor, key, value) => { const newURL = new URL(anchor.href, window.location.href); newURL.searchParams.set(key, value), anchor.href = newURL.href; })(anchor, 'page', value.toString()); const groupPageItems = (pageItems) => { const group = document.createElement('li'); pageItems[0].before(group), pageItems[0].style.marginLeft = '0', pageItems.forEach((item) => { item.classList.replace('pager-item', 'pager-current'); }); const groupList = external_m_default()('ul', { style: { display: 'inline', backgroundColor: 'hsla(0, 0%, 75%, 50%)', }, oncreate(vnode) { vnode.dom.append(...pageItems); }, }); external_m_default().render(group, groupList); }; const adjustPager = (adjust$) => adjust$.pipe((0, external_rxjs_operators_namespaceObject.tap)(({ container, pageCount, }) => { const currentPage = getPageParam(new URL(window.location.href)); const nextPage = currentPage + pageCount; let predicate; [ ...[() => [tapNonNull(container.querySelector('.pager-previous a')), Math.max(0, currentPage - pageCount)]].filter(() => currentPage > 0), ...(() => { const nextPageAnchor = container.querySelector('.pager-next a'); const lastPageAnchor = container.querySelector('.pager-last a'); if (lastPageAnchor) { const reachedLastPage = getPageParam(new URL(lastPageAnchor.href, window.location.href)) < nextPage; const display = reachedLastPage ? 'none' : ''; if (lastPageAnchor.style.display = display, src_assert(nextPageAnchor), nextPageAnchor.style.display = display, !reachedLastPage) return [() => [nextPageAnchor, nextPage]]; } else if (nextPageAnchor) return [() => [nextPageAnchor, nextPage]]; return []; })(), ].forEach((getArgs) => changeAnchorPageParam(...getArgs())), function_pipe(Array.from(container.querySelectorAll('.pager-item a')), Array_filter((anchor) => { const page = getPageParam(new URL(anchor.href, window.location.href)); return page >= currentPage && page < nextPage; }), (predicate = (currentPageAnchors) => currentPageAnchors.length > 0, function (a) { return predicate(a) ? Option_some(a) : Option_none; }), map((anchors) => [...Array.from(container.querySelectorAll('.pager-current')), ...anchors.map((anchor) => tapNonNull(anchor.parentElement))]), map(groupPageItems)); })); const getBrokenImages = () => getTeaserContainers(document).flatMap((container) => Array.from(container.querySelectorAll('img'))).filter((img) => img.complete && img.naturalWidth === 0); const createPreloadPage = (createContainer, parentPageId, url) => { const container = createContainer(); return container.src = url.toString(), container.style.display = 'none', container.classList.add(parentPageId), container; }; const createPreloadUrl = (startURL, page) => { const preloadURL = new URL('', startURL); return preloadURL.searchParams.set('page', page.toString()), preloadURL; }; const preloadUrlStream = (startURL, pageCount$) => pageCount$.pipe((0, external_rxjs_operators_namespaceObject.scan)((max, value) => Math.max(max, value), 1), (0, external_rxjs_operators_namespaceObject.scan)(([, last], current) => [last, current], [1, 1]), (0, external_rxjs_operators_namespaceObject.mergeMap)(([last, current]) => (0, external_rxjs_namespaceObject.from)([...Array(current - last).keys()].map((i) => getPageParam(startURL) + last + i))), (0, external_rxjs_operators_namespaceObject.map)(partial(createPreloadUrl, startURL))); const trySortTeasers = (condition$) => condition$.pipe((0, external_rxjs_operators_namespaceObject.map)((condition) => [getTeaserContainers(document), condition]), (0, external_rxjs_operators_namespaceObject.mergeMap)((x) => (0, external_rxjs_namespaceObject.of)(x).pipe((0, external_rxjs_operators_namespaceObject.tap)(([containers, condition]) => containers.forEach((container) => ((container, condition) => { const teaserDivs = Array.from(container.querySelectorAll('.node-teaser, .node-sidebar_teaser, .node-wide_teaser')); const sortedTeaserCount = container.dataset.sortedTeaserCount ? parseInt(container.dataset.sortedTeaserCount, 10) : 0; teaserDivs.filter(({ dataset, }) => !dataset.initialIndex).forEach(({ dataset, }, index) => { dataset.initialIndex = (sortedTeaserCount + index).toString(); }), container.dataset.sortedTeaserCount = teaserDivs.length.toString(); const getNearbyNumber = (element) => { return str = tapIs(Text, element.nextSibling).wholeText.replace(/,/g, ''), Number.parseFloat(str) * (str.includes('k') ? 1e3 : 1); }; const nearbyNumberOrZero = (element) => function_pipe(fromNullable(element), map(getNearbyNumber), getOrElse(() => 0)); const divValuePairs = teaserDivs.map((div) => ({ initialIndex: parseInt(tapNonNull(div.dataset.initialIndex), 10), viewCount: nearbyNumberOrZero(div.querySelector('.glyphicon-eye-open')), likeCount: nearbyNumberOrZero(div.querySelector('.glyphicon-heart')), imageFactor: div.querySelector('.field-type-image') ? 1 : 0, galleryFactor: div.querySelector('.glyphicon-th-large') ? 1 : 0, privateFactor: div.querySelector('.private-video') ? 1 : 0, })).map((info, index) => [teaserDivs[index], getTeaserValue(info, condition)]); divValuePairs.sort((itemA, itemB) => itemB[1] - itemA[1]), teaserDivs.forEach((div) => div.after(document.createElement('span'))), teaserDivs.map((div) => tapNonNull(div.nextSibling)).forEach((anchor, index) => anchor.replaceWith(divValuePairs[index][0])); })(container, condition))), (0, external_rxjs_operators_namespaceObject.catchError)((error) => (external_Swal_default().fire('Sorting Failed', `An error accured while sorting: ${error.toString()}`), external_log_namespaceObject.error(error), external_rxjs_namespaceObject.EMPTY)))), (0, external_rxjs_operators_namespaceObject.map)(([containers]) => ({ containersCount: containers.length, }))); const initParent = async () => { if (getTeaserContainers(document).length === 0) return; const initialCondition = tapNonNull(await GM.getValue('sortValue', conditionPresets['Default Condition'])); const pageCount = tapNonNull(await GM.getValue('pageCount', 1)); const haveMorePages = document.querySelector('.pager') && !document.querySelector('#comments'); const sortComponent = new class { constructor(initialCondition, initialPageCount) { this.conditionInputInput$ = new external_rxjs_namespaceObject.Subject(), this.conditionInputChange$ = new external_rxjs_namespaceObject.Subject(), this.conditionInputKeydown$ = new external_rxjs_namespaceObject.Subject(), this.sortButtonClick$ = new external_rxjs_namespaceObject.Subject(), this.presetSelectChange$ = new external_rxjs_namespaceObject.Subject(), this.pageCountInputInput$ = new external_rxjs_namespaceObject.Subject(), this.pageCountInputChange$ = new external_rxjs_namespaceObject.Subject(), this.conditionInputEnterDown$ = this.conditionInputKeydown$.pipe((0, external_rxjs_operators_namespaceObject.filter)((e) => e.key === 'Enter')), this.conditionChange$ = (0, external_rxjs_namespaceObject.merge)(this.conditionInputEnterDown$, this.presetSelectChange$, this.conditionInputChange$), this.sort$ = (0, external_rxjs_namespaceObject.merge)(this.sortButtonClick$, this.conditionInputEnterDown$, this.presetSelectChange$).pipe((0, external_rxjs_operators_namespaceObject.map)(() => this.state.condition)), this.condition$ = this.conditionChange$.pipe((0, external_rxjs_operators_namespaceObject.startWith)(void 0), (0, external_rxjs_operators_namespaceObject.map)(() => this.state.condition)), this.pageCount$ = this.pageCountInputChange$.pipe((0, external_rxjs_operators_namespaceObject.startWith)(void 0), (0, external_rxjs_operators_namespaceObject.map)(() => this.state.pageCount)), this.state = { condition: initialCondition, pageCount: initialPageCount, loadedPageCount: 0, }, (0, external_rxjs_namespaceObject.merge)(this.conditionInputInput$.pipe(getInputValue, (0, external_rxjs_operators_namespaceObject.tap)((value) => { this.state.condition = value; })), (0, external_rxjs_namespaceObject.merge)(this.conditionChange$, this.presetSelectChange$.pipe((0, external_rxjs_operators_namespaceObject.tap)((e) => { this.state.condition = tapIs(HTMLSelectElement, e.target).value; }))).pipe((0, external_rxjs_operators_namespaceObject.map)(() => this.state.condition), (0, external_rxjs_operators_namespaceObject.tap)((value) => GM.setValue('sortValue', value))), this.pageCountInputInput$.pipe(getInputValue, (0, external_rxjs_operators_namespaceObject.map)((value) => Number.parseInt(value, 10)), (0, external_rxjs_operators_namespaceObject.tap)((pageCount) => { this.state.pageCount = pageCount; })), this.pageCountInputChange$.pipe((0, external_rxjs_operators_namespaceObject.tap)(() => GM.setValue('pageCount', this.state.pageCount)))).subscribe(); } view() { const commonStyle = { margin: '5px 2px', }; const presetOptions = Object.entries(conditionPresets).map(([name, value]) => external_m_default()('option', { value, }, name)); const uiChildren = { conditionInput: external_m_default()(`input${classAttr(['form-control', 'input-sm'])}`, { size: 60, value: this.state.condition, style: commonStyle, list: 'iwara-custom-sort-conditions', oninput: forwardTo(this.conditionInputInput$), onchange: forwardTo(this.conditionInputChange$), onkeydown: forwardTo(this.conditionInputKeydown$), }), conditionDatalist: external_m_default()('datalist', { id: 'iwara-custom-sort-conditions', }, presetOptions), presetSelect: external_m_default()(`select${classAttr(['btn', 'btn-sm', 'btn-info'])}`, { onupdate: (vnode) => { tapIs(HTMLSelectElement, vnode.dom).selectedIndex = 0; }, style: { width: '95px', ...commonStyle, }, onchange: forwardTo(this.presetSelectChange$), }, [ external_m_default()('option', { hidden: !0, }, 'Presets'), ...presetOptions, ]), sortButton: external_m_default()(`button${classAttr(['btn', 'btn-sm', 'btn-primary'])}`, { style: commonStyle, onclick: forwardTo(this.sortButtonClick$), }, 'Sort'), label1: external_m_default()(`label${classAttr(['text-primary'])}`, { style: commonStyle, }, 'load'), pageCountInput: external_m_default()(`input${classAttr(['form-control', 'input-sm'])}`, { type: 'number', value: this.state.pageCount, min: 1, max: 500, step: 1, style: { width: '7rem', ...commonStyle, }, oninput: forwardTo(this.pageCountInputInput$), onchange: forwardTo(this.pageCountInputChange$), }), label2: external_m_default()(`label${classAttr(['text-primary'])}`, { style: commonStyle, }, 'pages. '), statusLabel: external_m_default()(`label${classAttr(['text-primary'])}`, { style: commonStyle, }, this.state.loadedPageCount < this.state.pageCount ? `${this.state.loadedPageCount} of ${this.state.pageCount} pages done` : 'All pages done'), }; return external_m_default()(`div${classAttr(['form-inline', 'container'])}`, { style: { display: 'inline-block', }, }, Object.values(uiChildren)); } addLoadedPageCount() { this.state.loadedPageCount += 1, external_m_default().redraw(); } }(initialCondition, pageCount); const preloadUrl$ = (haveMorePages ? sortComponent.pageCount$ : (0, external_rxjs_namespaceObject.of)(1)).pipe(partial(preloadUrlStream, new URL(window.location.href))); const channel = new BroadcastChannel('iwara-custom-sort'); const parentPageId = `t-${performance.now().toString()}`; const pageLoad$ = (0, external_rxjs_namespaceObject.fromEvent)(channel, 'message').pipe((0, external_rxjs_operators_namespaceObject.pluck)('data'), (0, external_rxjs_operators_namespaceObject.filter)((data) => data.parentPageId === parentPageId)); const teaserPageLoad$ = pageLoad$.pipe((0, external_rxjs_operators_namespaceObject.filter)((message) => message.hasTeasers)); const pageFromUrl = new Map(); const unsortedTeasers$ = teaserPageLoad$.pipe((0, external_rxjs_operators_namespaceObject.mapTo)(void 0), (0, external_rxjs_operators_namespaceObject.startWith)(void 0)); const clonedClass = 'iwara-custom-sort-cloned'; const allStreams = { adjustPager$: sortComponent.pageCount$.pipe((0, external_rxjs_operators_namespaceObject.mergeMap)((count) => (0, external_rxjs_namespaceObject.from)(document.querySelectorAll(`.pager:not(.${clonedClass})`)).pipe((0, external_rxjs_operators_namespaceObject.tap)((pager) => { pager.style.display = 'none'; }), (0, external_rxjs_operators_namespaceObject.map)((pager) => { const clonedPager = tapIs(HTMLElement, pager.cloneNode(!0)); return clonedPager.style.display = '', [pager, clonedPager]; }), (0, external_rxjs_operators_namespaceObject.tap)(([pager, clonedPager]) => { const sibling = pager.previousElementSibling; sibling && sibling.matches(`.${clonedClass}`) ? sibling.replaceWith(clonedPager) : pager.before(clonedPager); }), (0, external_rxjs_operators_namespaceObject.tap)(([, clonedPager]) => { clonedPager.classList.add(clonedClass); }), (0, external_rxjs_operators_namespaceObject.map)(([, clonedPager]) => ({ container: clonedPager, pageCount: count, })))), adjustPager), logPageLoad$: pageLoad$.pipe((0, external_rxjs_operators_namespaceObject.tap)(external_log_namespaceObject.info)), reloadBrokenImages$: unsortedTeasers$.pipe((0, external_rxjs_operators_namespaceObject.mergeMap)(() => (0, external_rxjs_namespaceObject.timer)(0, 8e3).pipe((0, external_rxjs_operators_namespaceObject.take)(2))), (0, external_rxjs_operators_namespaceObject.auditTime)(6e3), (0, external_rxjs_operators_namespaceObject.map)(getBrokenImages), (0, external_rxjs_operators_namespaceObject.tap)((images) => images.forEach(reloadImage)), (0, external_rxjs_operators_namespaceObject.map)((images) => `Reload ${images.length} broken image(s)`), (0, external_rxjs_operators_namespaceObject.tap)(external_log_namespaceObject.info)), sortTeasers$: (0, external_rxjs_namespaceObject.merge)(unsortedTeasers$.pipe((0, external_rxjs_operators_namespaceObject.withLatestFrom)(sortComponent.condition$), (0, external_rxjs_operators_namespaceObject.map)(([, condition]) => condition), (0, external_rxjs_operators_namespaceObject.tap)(() => sortComponent.addLoadedPageCount())), sortComponent.sort$).pipe(trySortTeasers, (0, external_rxjs_operators_namespaceObject.map)((result) => `${result.containersCount} containers sorted`), (0, external_rxjs_operators_namespaceObject.tap)(external_log_namespaceObject.info)), removeLoadedPage$: pageLoad$.pipe((0, external_rxjs_operators_namespaceObject.map)(({ url, }) => ({ url, container: pageFromUrl.get(url), })), (0, external_rxjs_operators_namespaceObject.tap)(({ url, }) => pageFromUrl.delete(url)), (0, external_rxjs_operators_namespaceObject.pluck)('container'), (0, external_rxjs_operators_namespaceObject.map)(tapNonNull), (0, external_rxjs_operators_namespaceObject.tap)(removeEmbeddedPage)), addHiddenPreload$: (0, external_rxjs_namespaceObject.zip)(preloadUrl$, teaserPageLoad$.pipe((0, external_rxjs_operators_namespaceObject.scan)((countDown) => (countDown > 0 ? countDown - 1 : countDown), 5), (0, external_rxjs_operators_namespaceObject.map)((countDown) => (countDown > 0 ? 2 : 1)), (0, external_rxjs_operators_namespaceObject.startWith)(2), (0, external_rxjs_operators_namespaceObject.mergeMap)((createPageCount) => (0, external_rxjs_namespaceObject.of)(...Array.from({ length: createPageCount, }, () => {}))))).pipe((0, external_rxjs_operators_namespaceObject.map)(([url]) => [ url, () => { return userAgent = window.navigator.userAgent, document.createElement(userAgent.indexOf('Firefox') > -1 ? 'embed' : 'iframe'); }, ]), (0, external_rxjs_operators_namespaceObject.map)(([url, createContainer]) => [url.toString(), createPreloadPage(createContainer, parentPageId, url)]), (0, external_rxjs_operators_namespaceObject.tap)((entry) => pageFromUrl.set(...entry)), (0, external_rxjs_operators_namespaceObject.tap)(([, container]) => document.body.append(container))), }; (0, external_rxjs_namespaceObject.merge)(...Object.values(allStreams)).subscribe(); const sortComponentContainer = document.createElement('div'); tapNonNull(document.querySelector('#user-links')).after(sortComponentContainer), external_m_default().mount(sortComponentContainer, sortComponent), external_log_namespaceObject.debug(await GM.listValues()); }; const initialize = async () => { const isParent = window === window.parent; external_log_namespaceObject.debug(`${isParent ? 'Parent' : 'Child'}: ${window.location.href}`), await (isParent ? initParent() : (async () => { const teaserContainers = getTeaserContainers(document); const channel = new BroadcastChannel('iwara-custom-sort'); const hasTeasers = teaserContainers.length > 0; const message = { url: window.location.href, parentPageId: Array.from(tapNonNull(window.frameElement).classList).filter((x) => x.startsWith('t-'))[0], hasTeasers, }; hasTeasers && (await delay_default()(500), ((children, parents) => { for (let i = 0, j = 0; i < parents.length && j < children.length; i += 1) { const parent = parents[i]; const child = children[j]; parent.className === child.className && (child.className = '', parent.append(child), j += 1); } })(teaserContainers, getTeaserContainers(window.parent.document))), channel.postMessage(message); })()); }; (async () => { external_log_namespaceObject.setLevel('debug'); try { await initialize(); } catch (error) { external_log_namespaceObject.error(error); } })(); })(); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址