1093 lines
67 KiB
JavaScript
1093 lines
67 KiB
JavaScript
|
// ==UserScript==
|
||
|
// @name Old Twitter Image Search
|
||
|
// @namespace vite-plugin-monkey
|
||
|
// @version 1.0.0
|
||
|
// @author SoberOatmeal
|
||
|
// @description otis
|
||
|
// @license MIT
|
||
|
// @match https://twitter.com/*
|
||
|
// @connect donmai.us
|
||
|
// @connect saucenao.com
|
||
|
// @connect twimg.com
|
||
|
// @connect api.twitter.com
|
||
|
// @grant GM.getValue
|
||
|
// @grant GM.setValue
|
||
|
// @grant GM.xmlHttpRequest
|
||
|
// @grant GM_getValue
|
||
|
// @grant GM_setValue
|
||
|
// @grant GM_xmlhttpRequest
|
||
|
// @run-at document-end
|
||
|
// ==/UserScript==
|
||
|
|
||
|
(t=>{const i=document.createElement("style");i.dataset.source="vite-plugin-monkey",i.textContent=t,document.head.append(i)})(" .otis-icon{width:16px;vertical-align:middle;margin-right:20px;margin-left:6px;margin-bottom:4px}.otis-icon:hover{opacity:.8}.otis-icon-loading{opacity:.6!important;animation-name:icon-spin;animation-duration:2s;animation-iteration-count:infinite;animation-timing-function:linear}.otis-icon-noresult{opacity:.3!important}.otis-danbo-icon{width:18px;vertical-align:middle;margin-bottom:2px}.danbo-text-link{color:var(--light-gray);font-weight:700;font-size:12px}.danbo-more-results{margin-left:250px}.danbo-item>img,.danbo-item>div{vertical-align:middle;display:inline-block}.danbo-item>div{margin-left:10px}@keyframes icon-spin{0%{transform:rotate(0)}to{transform:rotate(360deg)}} ");
|
||
|
|
||
|
(function () {
|
||
|
'use strict';
|
||
|
|
||
|
const equalFn = (a, b) => a === b;
|
||
|
const $TRACK = Symbol("solid-track");
|
||
|
const signalOptions = {
|
||
|
equals: equalFn
|
||
|
};
|
||
|
let runEffects = runQueue;
|
||
|
const STALE = 1;
|
||
|
const PENDING = 2;
|
||
|
const UNOWNED = {
|
||
|
owned: null,
|
||
|
cleanups: null,
|
||
|
context: null,
|
||
|
owner: null
|
||
|
};
|
||
|
var Owner = null;
|
||
|
let Transition = null;
|
||
|
let Listener = null;
|
||
|
let Updates = null;
|
||
|
let Effects = null;
|
||
|
let ExecCount = 0;
|
||
|
function createRoot(fn, detachedOwner) {
|
||
|
const listener = Listener, owner = Owner, unowned = fn.length === 0, root = unowned ? UNOWNED : {
|
||
|
owned: null,
|
||
|
cleanups: null,
|
||
|
context: null,
|
||
|
owner: detachedOwner === void 0 ? owner : detachedOwner
|
||
|
}, updateFn = unowned ? fn : () => fn(() => untrack(() => cleanNode(root)));
|
||
|
Owner = root;
|
||
|
Listener = null;
|
||
|
try {
|
||
|
return runUpdates(updateFn, true);
|
||
|
} finally {
|
||
|
Listener = listener;
|
||
|
Owner = owner;
|
||
|
}
|
||
|
}
|
||
|
function createSignal(value, options) {
|
||
|
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
|
||
|
const s = {
|
||
|
value,
|
||
|
observers: null,
|
||
|
observerSlots: null,
|
||
|
comparator: options.equals || void 0
|
||
|
};
|
||
|
const setter = (value2) => {
|
||
|
if (typeof value2 === "function") {
|
||
|
value2 = value2(s.value);
|
||
|
}
|
||
|
return writeSignal(s, value2);
|
||
|
};
|
||
|
return [readSignal.bind(s), setter];
|
||
|
}
|
||
|
function createRenderEffect(fn, value, options) {
|
||
|
const c = createComputation(fn, value, false, STALE);
|
||
|
updateComputation(c);
|
||
|
}
|
||
|
function createMemo(fn, value, options) {
|
||
|
options = options ? Object.assign({}, signalOptions, options) : signalOptions;
|
||
|
const c = createComputation(fn, value, true, 0);
|
||
|
c.observers = null;
|
||
|
c.observerSlots = null;
|
||
|
c.comparator = options.equals || void 0;
|
||
|
updateComputation(c);
|
||
|
return readSignal.bind(c);
|
||
|
}
|
||
|
function untrack(fn) {
|
||
|
if (Listener === null)
|
||
|
return fn();
|
||
|
const listener = Listener;
|
||
|
Listener = null;
|
||
|
try {
|
||
|
return fn();
|
||
|
} finally {
|
||
|
Listener = listener;
|
||
|
}
|
||
|
}
|
||
|
function onCleanup(fn) {
|
||
|
if (Owner === null)
|
||
|
;
|
||
|
else if (Owner.cleanups === null)
|
||
|
Owner.cleanups = [fn];
|
||
|
else
|
||
|
Owner.cleanups.push(fn);
|
||
|
return fn;
|
||
|
}
|
||
|
function readSignal() {
|
||
|
if (this.sources && this.state) {
|
||
|
if (this.state === STALE)
|
||
|
updateComputation(this);
|
||
|
else {
|
||
|
const updates = Updates;
|
||
|
Updates = null;
|
||
|
runUpdates(() => lookUpstream(this), false);
|
||
|
Updates = updates;
|
||
|
}
|
||
|
}
|
||
|
if (Listener) {
|
||
|
const sSlot = this.observers ? this.observers.length : 0;
|
||
|
if (!Listener.sources) {
|
||
|
Listener.sources = [this];
|
||
|
Listener.sourceSlots = [sSlot];
|
||
|
} else {
|
||
|
Listener.sources.push(this);
|
||
|
Listener.sourceSlots.push(sSlot);
|
||
|
}
|
||
|
if (!this.observers) {
|
||
|
this.observers = [Listener];
|
||
|
this.observerSlots = [Listener.sources.length - 1];
|
||
|
} else {
|
||
|
this.observers.push(Listener);
|
||
|
this.observerSlots.push(Listener.sources.length - 1);
|
||
|
}
|
||
|
}
|
||
|
return this.value;
|
||
|
}
|
||
|
function writeSignal(node, value, isComp) {
|
||
|
let current = node.value;
|
||
|
if (!node.comparator || !node.comparator(current, value)) {
|
||
|
node.value = value;
|
||
|
if (node.observers && node.observers.length) {
|
||
|
runUpdates(() => {
|
||
|
for (let i = 0; i < node.observers.length; i += 1) {
|
||
|
const o = node.observers[i];
|
||
|
const TransitionRunning = Transition && Transition.running;
|
||
|
if (TransitionRunning && Transition.disposed.has(o))
|
||
|
;
|
||
|
if (TransitionRunning ? !o.tState : !o.state) {
|
||
|
if (o.pure)
|
||
|
Updates.push(o);
|
||
|
else
|
||
|
Effects.push(o);
|
||
|
if (o.observers)
|
||
|
markDownstream(o);
|
||
|
}
|
||
|
if (!TransitionRunning)
|
||
|
o.state = STALE;
|
||
|
}
|
||
|
if (Updates.length > 1e6) {
|
||
|
Updates = [];
|
||
|
if (false)
|
||
|
;
|
||
|
throw new Error();
|
||
|
}
|
||
|
}, false);
|
||
|
}
|
||
|
}
|
||
|
return value;
|
||
|
}
|
||
|
function updateComputation(node) {
|
||
|
if (!node.fn)
|
||
|
return;
|
||
|
cleanNode(node);
|
||
|
const owner = Owner, listener = Listener, time = ExecCount;
|
||
|
Listener = Owner = node;
|
||
|
runComputation(node, node.value, time);
|
||
|
Listener = listener;
|
||
|
Owner = owner;
|
||
|
}
|
||
|
function runComputation(node, value, time) {
|
||
|
let nextValue;
|
||
|
try {
|
||
|
nextValue = node.fn(value);
|
||
|
} catch (err) {
|
||
|
if (node.pure) {
|
||
|
{
|
||
|
node.state = STALE;
|
||
|
node.owned && node.owned.forEach(cleanNode);
|
||
|
node.owned = null;
|
||
|
}
|
||
|
}
|
||
|
node.updatedAt = time + 1;
|
||
|
return handleError(err);
|
||
|
}
|
||
|
if (!node.updatedAt || node.updatedAt <= time) {
|
||
|
if (node.updatedAt != null && "observers" in node) {
|
||
|
writeSignal(node, nextValue);
|
||
|
} else
|
||
|
node.value = nextValue;
|
||
|
node.updatedAt = time;
|
||
|
}
|
||
|
}
|
||
|
function createComputation(fn, init, pure, state = STALE, options) {
|
||
|
const c = {
|
||
|
fn,
|
||
|
state,
|
||
|
updatedAt: null,
|
||
|
owned: null,
|
||
|
sources: null,
|
||
|
sourceSlots: null,
|
||
|
cleanups: null,
|
||
|
value: init,
|
||
|
owner: Owner,
|
||
|
context: null,
|
||
|
pure
|
||
|
};
|
||
|
if (Owner === null)
|
||
|
;
|
||
|
else if (Owner !== UNOWNED) {
|
||
|
{
|
||
|
if (!Owner.owned)
|
||
|
Owner.owned = [c];
|
||
|
else
|
||
|
Owner.owned.push(c);
|
||
|
}
|
||
|
}
|
||
|
return c;
|
||
|
}
|
||
|
function runTop(node) {
|
||
|
if (node.state === 0)
|
||
|
return;
|
||
|
if (node.state === PENDING)
|
||
|
return lookUpstream(node);
|
||
|
if (node.suspense && untrack(node.suspense.inFallback))
|
||
|
return node.suspense.effects.push(node);
|
||
|
const ancestors = [node];
|
||
|
while ((node = node.owner) && (!node.updatedAt || node.updatedAt < ExecCount)) {
|
||
|
if (node.state)
|
||
|
ancestors.push(node);
|
||
|
}
|
||
|
for (let i = ancestors.length - 1; i >= 0; i--) {
|
||
|
node = ancestors[i];
|
||
|
if (node.state === STALE) {
|
||
|
updateComputation(node);
|
||
|
} else if (node.state === PENDING) {
|
||
|
const updates = Updates;
|
||
|
Updates = null;
|
||
|
runUpdates(() => lookUpstream(node, ancestors[0]), false);
|
||
|
Updates = updates;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function runUpdates(fn, init) {
|
||
|
if (Updates)
|
||
|
return fn();
|
||
|
let wait = false;
|
||
|
if (!init)
|
||
|
Updates = [];
|
||
|
if (Effects)
|
||
|
wait = true;
|
||
|
else
|
||
|
Effects = [];
|
||
|
ExecCount++;
|
||
|
try {
|
||
|
const res = fn();
|
||
|
completeUpdates(wait);
|
||
|
return res;
|
||
|
} catch (err) {
|
||
|
if (!wait)
|
||
|
Effects = null;
|
||
|
Updates = null;
|
||
|
handleError(err);
|
||
|
}
|
||
|
}
|
||
|
function completeUpdates(wait) {
|
||
|
if (Updates) {
|
||
|
runQueue(Updates);
|
||
|
Updates = null;
|
||
|
}
|
||
|
if (wait)
|
||
|
return;
|
||
|
const e = Effects;
|
||
|
Effects = null;
|
||
|
if (e.length)
|
||
|
runUpdates(() => runEffects(e), false);
|
||
|
}
|
||
|
function runQueue(queue) {
|
||
|
for (let i = 0; i < queue.length; i++)
|
||
|
runTop(queue[i]);
|
||
|
}
|
||
|
function lookUpstream(node, ignore) {
|
||
|
node.state = 0;
|
||
|
for (let i = 0; i < node.sources.length; i += 1) {
|
||
|
const source = node.sources[i];
|
||
|
if (source.sources) {
|
||
|
const state = source.state;
|
||
|
if (state === STALE) {
|
||
|
if (source !== ignore && (!source.updatedAt || source.updatedAt < ExecCount))
|
||
|
runTop(source);
|
||
|
} else if (state === PENDING)
|
||
|
lookUpstream(source, ignore);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function markDownstream(node) {
|
||
|
for (let i = 0; i < node.observers.length; i += 1) {
|
||
|
const o = node.observers[i];
|
||
|
if (!o.state) {
|
||
|
o.state = PENDING;
|
||
|
if (o.pure)
|
||
|
Updates.push(o);
|
||
|
else
|
||
|
Effects.push(o);
|
||
|
o.observers && markDownstream(o);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function cleanNode(node) {
|
||
|
let i;
|
||
|
if (node.sources) {
|
||
|
while (node.sources.length) {
|
||
|
const source = node.sources.pop(), index = node.sourceSlots.pop(), obs = source.observers;
|
||
|
if (obs && obs.length) {
|
||
|
const n = obs.pop(), s = source.observerSlots.pop();
|
||
|
if (index < obs.length) {
|
||
|
n.sourceSlots[s] = index;
|
||
|
obs[index] = n;
|
||
|
source.observerSlots[index] = s;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
if (node.owned) {
|
||
|
for (i = node.owned.length - 1; i >= 0; i--)
|
||
|
cleanNode(node.owned[i]);
|
||
|
node.owned = null;
|
||
|
}
|
||
|
if (node.cleanups) {
|
||
|
for (i = node.cleanups.length - 1; i >= 0; i--)
|
||
|
node.cleanups[i]();
|
||
|
node.cleanups = null;
|
||
|
}
|
||
|
node.state = 0;
|
||
|
node.context = null;
|
||
|
}
|
||
|
function castError(err) {
|
||
|
if (err instanceof Error)
|
||
|
return err;
|
||
|
return new Error(typeof err === "string" ? err : "Unknown error", {
|
||
|
cause: err
|
||
|
});
|
||
|
}
|
||
|
function handleError(err, owner = Owner) {
|
||
|
const error = castError(err);
|
||
|
throw error;
|
||
|
}
|
||
|
const FALLBACK = Symbol("fallback");
|
||
|
function dispose(d) {
|
||
|
for (let i = 0; i < d.length; i++)
|
||
|
d[i]();
|
||
|
}
|
||
|
function mapArray(list, mapFn, options = {}) {
|
||
|
let items = [], mapped = [], disposers = [], len = 0, indexes = mapFn.length > 1 ? [] : null;
|
||
|
onCleanup(() => dispose(disposers));
|
||
|
return () => {
|
||
|
let newItems = list() || [], i, j;
|
||
|
newItems[$TRACK];
|
||
|
return untrack(() => {
|
||
|
let newLen = newItems.length, newIndices, newIndicesNext, temp, tempdisposers, tempIndexes, start, end, newEnd, item;
|
||
|
if (newLen === 0) {
|
||
|
if (len !== 0) {
|
||
|
dispose(disposers);
|
||
|
disposers = [];
|
||
|
items = [];
|
||
|
mapped = [];
|
||
|
len = 0;
|
||
|
indexes && (indexes = []);
|
||
|
}
|
||
|
if (options.fallback) {
|
||
|
items = [FALLBACK];
|
||
|
mapped[0] = createRoot((disposer) => {
|
||
|
disposers[0] = disposer;
|
||
|
return options.fallback();
|
||
|
});
|
||
|
len = 1;
|
||
|
}
|
||
|
} else if (len === 0) {
|
||
|
mapped = new Array(newLen);
|
||
|
for (j = 0; j < newLen; j++) {
|
||
|
items[j] = newItems[j];
|
||
|
mapped[j] = createRoot(mapper);
|
||
|
}
|
||
|
len = newLen;
|
||
|
} else {
|
||
|
temp = new Array(newLen);
|
||
|
tempdisposers = new Array(newLen);
|
||
|
indexes && (tempIndexes = new Array(newLen));
|
||
|
for (start = 0, end = Math.min(len, newLen); start < end && items[start] === newItems[start]; start++)
|
||
|
;
|
||
|
for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && items[end] === newItems[newEnd]; end--, newEnd--) {
|
||
|
temp[newEnd] = mapped[end];
|
||
|
tempdisposers[newEnd] = disposers[end];
|
||
|
indexes && (tempIndexes[newEnd] = indexes[end]);
|
||
|
}
|
||
|
newIndices = /* @__PURE__ */ new Map();
|
||
|
newIndicesNext = new Array(newEnd + 1);
|
||
|
for (j = newEnd; j >= start; j--) {
|
||
|
item = newItems[j];
|
||
|
i = newIndices.get(item);
|
||
|
newIndicesNext[j] = i === void 0 ? -1 : i;
|
||
|
newIndices.set(item, j);
|
||
|
}
|
||
|
for (i = start; i <= end; i++) {
|
||
|
item = items[i];
|
||
|
j = newIndices.get(item);
|
||
|
if (j !== void 0 && j !== -1) {
|
||
|
temp[j] = mapped[i];
|
||
|
tempdisposers[j] = disposers[i];
|
||
|
indexes && (tempIndexes[j] = indexes[i]);
|
||
|
j = newIndicesNext[j];
|
||
|
newIndices.set(item, j);
|
||
|
} else
|
||
|
disposers[i]();
|
||
|
}
|
||
|
for (j = start; j < newLen; j++) {
|
||
|
if (j in temp) {
|
||
|
mapped[j] = temp[j];
|
||
|
disposers[j] = tempdisposers[j];
|
||
|
if (indexes) {
|
||
|
indexes[j] = tempIndexes[j];
|
||
|
indexes[j](j);
|
||
|
}
|
||
|
} else
|
||
|
mapped[j] = createRoot(mapper);
|
||
|
}
|
||
|
mapped = mapped.slice(0, len = newLen);
|
||
|
items = newItems.slice(0);
|
||
|
}
|
||
|
return mapped;
|
||
|
});
|
||
|
function mapper(disposer) {
|
||
|
disposers[j] = disposer;
|
||
|
if (indexes) {
|
||
|
const [s, set] = createSignal(j);
|
||
|
indexes[j] = set;
|
||
|
return mapFn(newItems[j], s);
|
||
|
}
|
||
|
return mapFn(newItems[j]);
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
function createComponent(Comp, props) {
|
||
|
return untrack(() => Comp(props || {}));
|
||
|
}
|
||
|
const narrowedError = (name) => `Stale read from <${name}>.`;
|
||
|
function For(props) {
|
||
|
const fallback = "fallback" in props && {
|
||
|
fallback: () => props.fallback
|
||
|
};
|
||
|
return createMemo(mapArray(() => props.each, props.children, fallback || void 0));
|
||
|
}
|
||
|
function Show(props) {
|
||
|
const keyed = props.keyed;
|
||
|
const condition = createMemo(() => props.when, void 0, {
|
||
|
equals: (a, b) => keyed ? a === b : !a === !b
|
||
|
});
|
||
|
return createMemo(() => {
|
||
|
const c = condition();
|
||
|
if (c) {
|
||
|
const child = props.children;
|
||
|
const fn = typeof child === "function" && child.length > 0;
|
||
|
return fn ? untrack(() => child(keyed ? c : () => {
|
||
|
if (!untrack(condition))
|
||
|
throw narrowedError("Show");
|
||
|
return props.when;
|
||
|
})) : child;
|
||
|
}
|
||
|
return props.fallback;
|
||
|
}, void 0, void 0);
|
||
|
}
|
||
|
function reconcileArrays(parentNode, a, b) {
|
||
|
let bLength = b.length, aEnd = a.length, bEnd = bLength, aStart = 0, bStart = 0, after = a[aEnd - 1].nextSibling, map = null;
|
||
|
while (aStart < aEnd || bStart < bEnd) {
|
||
|
if (a[aStart] === b[bStart]) {
|
||
|
aStart++;
|
||
|
bStart++;
|
||
|
continue;
|
||
|
}
|
||
|
while (a[aEnd - 1] === b[bEnd - 1]) {
|
||
|
aEnd--;
|
||
|
bEnd--;
|
||
|
}
|
||
|
if (aEnd === aStart) {
|
||
|
const node = bEnd < bLength ? bStart ? b[bStart - 1].nextSibling : b[bEnd - bStart] : after;
|
||
|
while (bStart < bEnd)
|
||
|
parentNode.insertBefore(b[bStart++], node);
|
||
|
} else if (bEnd === bStart) {
|
||
|
while (aStart < aEnd) {
|
||
|
if (!map || !map.has(a[aStart]))
|
||
|
a[aStart].remove();
|
||
|
aStart++;
|
||
|
}
|
||
|
} else if (a[aStart] === b[bEnd - 1] && b[bStart] === a[aEnd - 1]) {
|
||
|
const node = a[--aEnd].nextSibling;
|
||
|
parentNode.insertBefore(b[bStart++], a[aStart++].nextSibling);
|
||
|
parentNode.insertBefore(b[--bEnd], node);
|
||
|
a[aEnd] = b[bEnd];
|
||
|
} else {
|
||
|
if (!map) {
|
||
|
map = /* @__PURE__ */ new Map();
|
||
|
let i = bStart;
|
||
|
while (i < bEnd)
|
||
|
map.set(b[i], i++);
|
||
|
}
|
||
|
const index = map.get(a[aStart]);
|
||
|
if (index != null) {
|
||
|
if (bStart < index && index < bEnd) {
|
||
|
let i = aStart, sequence = 1, t;
|
||
|
while (++i < aEnd && i < bEnd) {
|
||
|
if ((t = map.get(a[i])) == null || t !== index + sequence)
|
||
|
break;
|
||
|
sequence++;
|
||
|
}
|
||
|
if (sequence > index - bStart) {
|
||
|
const node = a[aStart];
|
||
|
while (bStart < index)
|
||
|
parentNode.insertBefore(b[bStart++], node);
|
||
|
} else
|
||
|
parentNode.replaceChild(b[bStart++], a[aStart++]);
|
||
|
} else
|
||
|
aStart++;
|
||
|
} else
|
||
|
a[aStart++].remove();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
const $$EVENTS = "_$DX_DELEGATE";
|
||
|
function template(html, isCE, isSVG) {
|
||
|
let node;
|
||
|
const create = () => {
|
||
|
const t = document.createElement("template");
|
||
|
t.innerHTML = html;
|
||
|
return isSVG ? t.content.firstChild.firstChild : t.content.firstChild;
|
||
|
};
|
||
|
const fn = isCE ? () => untrack(() => document.importNode(node || (node = create()), true)) : () => (node || (node = create())).cloneNode(true);
|
||
|
fn.cloneNode = fn;
|
||
|
return fn;
|
||
|
}
|
||
|
function delegateEvents(eventNames, document2 = window.document) {
|
||
|
const e = document2[$$EVENTS] || (document2[$$EVENTS] = /* @__PURE__ */ new Set());
|
||
|
for (let i = 0, l = eventNames.length; i < l; i++) {
|
||
|
const name = eventNames[i];
|
||
|
if (!e.has(name)) {
|
||
|
e.add(name);
|
||
|
document2.addEventListener(name, eventHandler);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
function setAttribute(node, name, value) {
|
||
|
if (value == null)
|
||
|
node.removeAttribute(name);
|
||
|
else
|
||
|
node.setAttribute(name, value);
|
||
|
}
|
||
|
function addEventListener(node, name, handler, delegate) {
|
||
|
if (delegate) {
|
||
|
if (Array.isArray(handler)) {
|
||
|
node[`$$${name}`] = handler[0];
|
||
|
node[`$$${name}Data`] = handler[1];
|
||
|
} else
|
||
|
node[`$$${name}`] = handler;
|
||
|
} else if (Array.isArray(handler)) {
|
||
|
const handlerFn = handler[0];
|
||
|
node.addEventListener(name, handler[0] = (e) => handlerFn.call(node, handler[1], e));
|
||
|
} else
|
||
|
node.addEventListener(name, handler);
|
||
|
}
|
||
|
function use(fn, element2, arg) {
|
||
|
return untrack(() => fn(element2, arg));
|
||
|
}
|
||
|
function insert(parent, accessor, marker, initial) {
|
||
|
if (marker !== void 0 && !initial)
|
||
|
initial = [];
|
||
|
if (typeof accessor !== "function")
|
||
|
return insertExpression(parent, accessor, initial, marker);
|
||
|
createRenderEffect((current) => insertExpression(parent, accessor(), current, marker), initial);
|
||
|
}
|
||
|
function eventHandler(e) {
|
||
|
const key = `$$${e.type}`;
|
||
|
let node = e.composedPath && e.composedPath()[0] || e.target;
|
||
|
if (e.target !== node) {
|
||
|
Object.defineProperty(e, "target", {
|
||
|
configurable: true,
|
||
|
value: node
|
||
|
});
|
||
|
}
|
||
|
Object.defineProperty(e, "currentTarget", {
|
||
|
configurable: true,
|
||
|
get() {
|
||
|
return node || document;
|
||
|
}
|
||
|
});
|
||
|
while (node) {
|
||
|
const handler = node[key];
|
||
|
if (handler && !node.disabled) {
|
||
|
const data = node[`${key}Data`];
|
||
|
data !== void 0 ? handler.call(node, data, e) : handler.call(node, e);
|
||
|
if (e.cancelBubble)
|
||
|
return;
|
||
|
}
|
||
|
node = node._$host || node.parentNode || node.host;
|
||
|
}
|
||
|
}
|
||
|
function insertExpression(parent, value, current, marker, unwrapArray) {
|
||
|
while (typeof current === "function")
|
||
|
current = current();
|
||
|
if (value === current)
|
||
|
return current;
|
||
|
const t = typeof value, multi = marker !== void 0;
|
||
|
parent = multi && current[0] && current[0].parentNode || parent;
|
||
|
if (t === "string" || t === "number") {
|
||
|
if (t === "number")
|
||
|
value = value.toString();
|
||
|
if (multi) {
|
||
|
let node = current[0];
|
||
|
if (node && node.nodeType === 3) {
|
||
|
node.data = value;
|
||
|
} else
|
||
|
node = document.createTextNode(value);
|
||
|
current = cleanChildren(parent, current, marker, node);
|
||
|
} else {
|
||
|
if (current !== "" && typeof current === "string") {
|
||
|
current = parent.firstChild.data = value;
|
||
|
} else
|
||
|
current = parent.textContent = value;
|
||
|
}
|
||
|
} else if (value == null || t === "boolean") {
|
||
|
current = cleanChildren(parent, current, marker);
|
||
|
} else if (t === "function") {
|
||
|
createRenderEffect(() => {
|
||
|
let v = value();
|
||
|
while (typeof v === "function")
|
||
|
v = v();
|
||
|
current = insertExpression(parent, v, current, marker);
|
||
|
});
|
||
|
return () => current;
|
||
|
} else if (Array.isArray(value)) {
|
||
|
const array = [];
|
||
|
const currentArray = current && Array.isArray(current);
|
||
|
if (normalizeIncomingArray(array, value, current, unwrapArray)) {
|
||
|
createRenderEffect(() => current = insertExpression(parent, array, current, marker, true));
|
||
|
return () => current;
|
||
|
}
|
||
|
if (array.length === 0) {
|
||
|
current = cleanChildren(parent, current, marker);
|
||
|
if (multi)
|
||
|
return current;
|
||
|
} else if (currentArray) {
|
||
|
if (current.length === 0) {
|
||
|
appendNodes(parent, array, marker);
|
||
|
} else
|
||
|
reconcileArrays(parent, current, array);
|
||
|
} else {
|
||
|
current && cleanChildren(parent);
|
||
|
appendNodes(parent, array);
|
||
|
}
|
||
|
current = array;
|
||
|
} else if (value.nodeType) {
|
||
|
if (Array.isArray(current)) {
|
||
|
if (multi)
|
||
|
return current = cleanChildren(parent, current, marker, value);
|
||
|
cleanChildren(parent, current, null, value);
|
||
|
} else if (current == null || current === "" || !parent.firstChild) {
|
||
|
parent.appendChild(value);
|
||
|
} else
|
||
|
parent.replaceChild(value, parent.firstChild);
|
||
|
current = value;
|
||
|
} else
|
||
|
;
|
||
|
return current;
|
||
|
}
|
||
|
function normalizeIncomingArray(normalized, array, current, unwrap) {
|
||
|
let dynamic = false;
|
||
|
for (let i = 0, len = array.length; i < len; i++) {
|
||
|
let item = array[i], prev = current && current[i], t;
|
||
|
if (item == null || item === true || item === false)
|
||
|
;
|
||
|
else if ((t = typeof item) === "object" && item.nodeType) {
|
||
|
normalized.push(item);
|
||
|
} else if (Array.isArray(item)) {
|
||
|
dynamic = normalizeIncomingArray(normalized, item, prev) || dynamic;
|
||
|
} else if (t === "function") {
|
||
|
if (unwrap) {
|
||
|
while (typeof item === "function")
|
||
|
item = item();
|
||
|
dynamic = normalizeIncomingArray(normalized, Array.isArray(item) ? item : [item], Array.isArray(prev) ? prev : [prev]) || dynamic;
|
||
|
} else {
|
||
|
normalized.push(item);
|
||
|
dynamic = true;
|
||
|
}
|
||
|
} else {
|
||
|
const value = String(item);
|
||
|
if (prev && prev.nodeType === 3 && prev.data === value)
|
||
|
normalized.push(prev);
|
||
|
else
|
||
|
normalized.push(document.createTextNode(value));
|
||
|
}
|
||
|
}
|
||
|
return dynamic;
|
||
|
}
|
||
|
function appendNodes(parent, array, marker = null) {
|
||
|
for (let i = 0, len = array.length; i < len; i++)
|
||
|
parent.insertBefore(array[i], marker);
|
||
|
}
|
||
|
function cleanChildren(parent, current, marker, replacement) {
|
||
|
if (marker === void 0)
|
||
|
return parent.textContent = "";
|
||
|
const node = replacement || document.createTextNode("");
|
||
|
if (current.length) {
|
||
|
let inserted = false;
|
||
|
for (let i = current.length - 1; i >= 0; i--) {
|
||
|
const el = current[i];
|
||
|
if (node !== el) {
|
||
|
const isParent = el.parentNode === parent;
|
||
|
if (!inserted && !i)
|
||
|
isParent ? parent.replaceChild(node, el) : parent.insertBefore(node, marker);
|
||
|
else
|
||
|
isParent && el.remove();
|
||
|
} else
|
||
|
inserted = true;
|
||
|
}
|
||
|
} else
|
||
|
parent.insertBefore(node, marker);
|
||
|
return [node];
|
||
|
}
|
||
|
function click_out_directive(el, accessor) {
|
||
|
const onClick = (e) => {
|
||
|
var _a;
|
||
|
return !el.contains(e.target) && ((_a = accessor()) == null ? void 0 : _a());
|
||
|
};
|
||
|
document.body.addEventListener("click", onClick);
|
||
|
onCleanup(() => document.body.removeEventListener("click", onClick));
|
||
|
}
|
||
|
var _GM_getValue = /* @__PURE__ */ (() => typeof GM_getValue != "undefined" ? GM_getValue : void 0)();
|
||
|
var _GM_setValue = /* @__PURE__ */ (() => typeof GM_setValue != "undefined" ? GM_setValue : void 0)();
|
||
|
var _GM_xmlhttpRequest = /* @__PURE__ */ (() => typeof GM_xmlhttpRequest != "undefined" ? GM_xmlhttpRequest : void 0)();
|
||
|
const DANBOORU_API = "https://danbooru.donmai.us";
|
||
|
async function tweet_search(id, username) {
|
||
|
const posts_api = `${DANBOORU_API}/posts.json`;
|
||
|
const tweet_url = `https://twitter.com/${username}/status/${id}`;
|
||
|
const posts_url = new URL(posts_api);
|
||
|
posts_url.searchParams.append("tags", `status:any source:${tweet_url}`);
|
||
|
posts_url.searchParams.append("limit", `5`);
|
||
|
const booru_request = new Promise((res, rej) => {
|
||
|
_GM_xmlhttpRequest({
|
||
|
url: posts_url.toString(),
|
||
|
method: "GET",
|
||
|
responseType: "json",
|
||
|
anonymous: true,
|
||
|
onload: (response2) => res(response2.responseText),
|
||
|
onerror: (error) => rej(error)
|
||
|
});
|
||
|
});
|
||
|
const response = await booru_request;
|
||
|
const posts = JSON.parse(response);
|
||
|
const result = posts.map((post) => {
|
||
|
var _a;
|
||
|
const preview = (_a = post.media_asset.variants) == null ? void 0 : _a.find((v) => v.type == "preview" || v.type == "180x180");
|
||
|
const source_domain = new URL(post.source).hostname;
|
||
|
return {
|
||
|
id: post.id,
|
||
|
timestamp: post.created_at,
|
||
|
source_domain,
|
||
|
thumbnail: preview == null ? void 0 : preview.url,
|
||
|
img_width: post.image_width,
|
||
|
img_height: post.image_height
|
||
|
};
|
||
|
});
|
||
|
return result;
|
||
|
}
|
||
|
async function iqdb_search(media_url) {
|
||
|
const iqdb_api = `${DANBOORU_API}/iqdb_queries.json`;
|
||
|
const iqdb_url = new URL(iqdb_api);
|
||
|
iqdb_url.searchParams.append("url", media_url);
|
||
|
iqdb_url.searchParams.append("similarity", "80");
|
||
|
iqdb_url.searchParams.append("limit", "5");
|
||
|
const booru_request = new Promise((res, rej) => {
|
||
|
_GM_xmlhttpRequest({
|
||
|
url: iqdb_url.toString(),
|
||
|
method: "GET",
|
||
|
responseType: "json",
|
||
|
anonymous: true,
|
||
|
onload: (response2) => res(response2.responseText),
|
||
|
onerror: (error) => rej(error)
|
||
|
});
|
||
|
});
|
||
|
const response = await booru_request;
|
||
|
const iqdb_res = JSON.parse(response);
|
||
|
const result = iqdb_res.map((i) => {
|
||
|
var _a;
|
||
|
const post = i.post;
|
||
|
const preview = (_a = post.media_asset.variants) == null ? void 0 : _a.find((v) => v.type == "preview" || v.type == "180x180");
|
||
|
const source_domain = new URL(post.source).hostname;
|
||
|
return {
|
||
|
id: post.id,
|
||
|
timestamp: post.created_at,
|
||
|
source_domain,
|
||
|
thumbnail: preview == null ? void 0 : preview.url,
|
||
|
img_width: post.image_width,
|
||
|
img_height: post.image_height
|
||
|
};
|
||
|
});
|
||
|
return result;
|
||
|
}
|
||
|
async function saucenao_search(media_url) {
|
||
|
const saucenao_key = _GM_getValue("DunkOatmeal_SNKey", "");
|
||
|
if (!saucenao_key) {
|
||
|
alert("SauceNAO API required. \nGo to Profile Menu > Settings to add it.");
|
||
|
return [];
|
||
|
}
|
||
|
const danbo_bm = 512;
|
||
|
const bitmask = danbo_bm;
|
||
|
const min_similarity = 80;
|
||
|
const sauce_api = `http://saucenao.com/search.php`;
|
||
|
const sauce_url = new URL(sauce_api);
|
||
|
sauce_url.searchParams.append("numres", "5");
|
||
|
sauce_url.searchParams.append("output_type", "2");
|
||
|
sauce_url.searchParams.append("dbmask", String(bitmask));
|
||
|
sauce_url.searchParams.append("api_key", saucenao_key);
|
||
|
sauce_url.searchParams.append("url", media_url);
|
||
|
const booru_request = new Promise((res, rej) => {
|
||
|
_GM_xmlhttpRequest({
|
||
|
url: sauce_url.toString(),
|
||
|
method: "GET",
|
||
|
responseType: "json",
|
||
|
anonymous: true,
|
||
|
onload: (response2) => res(response2.responseText),
|
||
|
onerror: (error) => rej(error)
|
||
|
});
|
||
|
});
|
||
|
const response = await booru_request;
|
||
|
const sauce_res = JSON.parse(response);
|
||
|
const result = sauce_res.results.filter((x) => Number(x.header.similarity) >= min_similarity).map((s) => {
|
||
|
const danbo = s.data;
|
||
|
const preview = s.header.thumbnail;
|
||
|
const source_domain = new URL(danbo.source).hostname;
|
||
|
return {
|
||
|
id: danbo.danbooru_id,
|
||
|
timestamp: "",
|
||
|
source_domain,
|
||
|
thumbnail: preview,
|
||
|
img_width: -1,
|
||
|
img_height: -1
|
||
|
};
|
||
|
});
|
||
|
return result;
|
||
|
}
|
||
|
const _tmpl$$1 = /* @__PURE__ */ template(`<hr>`), _tmpl$2$1 = /* @__PURE__ */ template(`<h1>Old Twitter Image Search Settings`), _tmpl$3$1 = /* @__PURE__ */ template(`<br>`), _tmpl$4$1 = /* @__PURE__ */ template(`<span> Userscript made by SoberOatmeal `), _tmpl$5$1 = /* @__PURE__ */ template(`<span> SauceNAO API Key `), _tmpl$6$1 = /* @__PURE__ */ template(`<span>Can be acquired by signing up to SauceNAO then go to <b>Account > api </b> and then grab the generated api key.`), _tmpl$7$1 = /* @__PURE__ */ template(`<div class="setting"><input type="text" placeholder="Put SauceNAO API key here">`);
|
||
|
function OTISSettingsPage() {
|
||
|
const settingsElement = document.getElementById("settings");
|
||
|
const ot_settings = settingsElement.getElementsByTagName("hr").item(0);
|
||
|
const OTISSettings = () => {
|
||
|
const [SauceKey, setSauceKey] = createSignal(_GM_getValue("DunkOatmeal_SNKey", ""));
|
||
|
return [_tmpl$$1(), _tmpl$2$1(), _tmpl$3$1(), _tmpl$4$1(), _tmpl$3$1(), _tmpl$3$1(), _tmpl$5$1(), _tmpl$3$1(), _tmpl$6$1(), (() => {
|
||
|
const _el$10 = _tmpl$7$1(), _el$11 = _el$10.firstChild;
|
||
|
_el$11.$$input = (i) => _GM_setValue("DunkOatmeal_SNKey", i.target.value);
|
||
|
_el$11.style.setProperty("height", "25px");
|
||
|
_el$11.style.setProperty("width", "550px");
|
||
|
createRenderEffect(() => _el$11.value = SauceKey());
|
||
|
return _el$10;
|
||
|
})(), _tmpl$3$1()];
|
||
|
};
|
||
|
ot_settings.before(...createComponent(OTISSettings, {}));
|
||
|
}
|
||
|
delegateEvents(["input"]);
|
||
|
const iqdb_icon = "data:image/x-icon;base64,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
|
||
|
const sauce_icon = "data:image/x-icon;base64,Qk02AwAAAAAAADYAAAAoAAAAEAAAABAAAAABABgAAAAAAAADAADEDgAAxA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////////////////////////////////////AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA////AAAA////////AAAAAAAAAAAAAAAAAAAAAAAA////////AAAA////AAAAAAAAAAAAAAAA////////////AAAAAAAAAAAAAAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AAAAAAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AAAAAAAA////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AAAAAAAAAAAAAAAA////////////AAAAAAAAAAAAAAAA////AAAA////////AAAAAAAAAAAAAAAAAAAAAAAA////////AAAA////AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAA////////////////////////////////////////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||
|
const grape_icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAABxCAYAAAAd8Kt3AAAsTElEQVR4nO2deXxeVZ3/399z7r3Pkq0tbYFSCpRNKKJSBBGEln1HxETEZcTRoui4MO6jJhnHWdR5iT91GHAcdVzQFEG2iiAkLAJqy06FFsrSfUua5Vnvvef7++M+T5q0SZu2aUM1n1efJnnuee5z7vl+z3c/58A4/qYhY92BoaCqwnwMXYsMs4FlyxyNTU4EHeu+jWM3Q9vUqupWjKltanWh+tqsZiz69dcKb6w7MBCqzUZE4oXX4/fc+ecTjNMjsCUJUgufkDPkMSAG0Hb1mIMTETfGXd7r8ZpRAaoqIqLddzx3bm3q0C/kivFM1eJ0I4jT6GUhflaUJ/C9X9Sdv8/i/s+hIsi4athJvCYYQNvarDQ1xbnbfn1ckDr5Xs/uO6FYhjBKrqd8CAIolqAcxSut9D5r7Iof3fGj189vmp9IBVBRBZFxZtgRjDkDaLUPz+D3vfzEdbXZN3ywp1dLCD5auZaQVkFM2keMgVLoQmX1i5635GtrUvfffMjc1iJAW1ubbWxsdOOMMDKMPQNURH/frX3HptKZJ/NFE4uoHbprimriCVgrYgSsiSlHrywyUmou1/zuDxPnfnoTgLa3ezJ3brQnn2VvxJgzACQWfk8m/71skP1IoeQcmBFb+qqo7yHpQMmXX71P4p7vZjn2brmYvLa1BTzbFEkr48biMHhtMMBvF+/fF89cri5ld+rz6lSMidMenh9EFMOX20L95Xfrz/vKQwDa1milaX687XuoMH++oWumYTY8u2yZzNqizbPArJkzddGiRcyeONHxV6BqxtQNrIr/vEYXGUmZbVJoGxAxguIVQheXIs/VZg9r0tL7Tiv99sjvBXVN/yunzF+lqkZEnKoKTU1m0ZkTzexVXcKso2HKHIdILImbuUPdUFVDR4vhxtXCbGDe/sr8Wbq3MMeYSoCqC9d9W/eiwNa9KYxlFPqkgISexQ/8PhwLn+kL/++Lky740R3afponc+8f0i5Y87s1NTWRm20wR7jY7Gsw9ZGSBaxiRMQoGpeNR5do+RWx3c/m0pP+MnXu1L7t9EZQ2B1RzMSArt528LBJf5NtY8wYoN/4u0P3i2OeDzzqwzhx5Ebn/rFDrGYCrOd19pbCRVenzz3754Xb8wfG/qPHi/onitQciZu4X+wmN0BtRtU1GMgCgbUGI4N74xSiWAEtqdIHkkPjEBM5xZVFy91C6RU8/zktNTxF1j7nNnSvnXDFhE0MYABVFVoQWkVlG0Tqb9eC7oo0qY71UNfGkgGMiLi+2wvvcZr6kTHiu1E31RRF4sDDhnHRQalHyKYUE1ix1lr6iawKsUteqskr6edmAokk/GBM8rJmAINoQsnYQRxDrBoLGkIpJ6b8eKDBD3OF4sOF9PwNB1x8Vb7yEaG93TJnTlwlUFtbm53y7BSZ2zonZogAlyqG337H31CuDTydacX3BBqAbjTcoBNqa7WLiWgY6ST+WJLzP1kaON5b3m/sGKBdPZkrUffthflpL/3OUrgbv0tVrRExZjNxtUKwhMADxlkG/BvufoPYYjBERKTyaZEBLyByRTBr7hb2+Z6Vp5akzz1lSVUy6DPPBCxeHEtTU78N0rvgsSlipk6L4glTRYL9bZSfJqYwTSnPcC6eacSfrOIHqtYYCWMIS6iJHSkEU4D4L4rcbuMVd9W8/bhV2qxGWgczwZgxQFtjm21sa3SbbnVP1WfNMX1FdYL8VSZ6KjymIKQCJJWB3r5VOSPRDZgNv6vpnf2ANFEA2HjbQ7MCe8wsQ82RzhXOQvWk2pp6r3KjzRLGgXOD9UfVgqoS1bMQpKFQ2LiwLBu/MOG8I+8FlYGSZUwYoCqOum/VwxDuywQcWCglimos+rMnoTgnYmJ1ePX1SKm0iTjOzVd1j0Su/gAjXFJX23AYBsICFEqoSOKZiIBTFVBJoqRbCKqq3kKosIaKmDibwg9d5ybh4ctT5154d0dHi507tzWCsXIDOzCAs7b4FueCKWFkXiMRid0PwRgUA057e02oTDD1NRMasTTioFSE3l7CisgwgAHxIKGvJMpl6PEaNH+q8kBNvijlurpJE/r63nx1WuR3C69XUW0REdGxYYD1GADnSm9IB+n038rsH4gkkI0PTntzEiGiAjjnrIj4VVLv+sQQjMHEsTqV7HR94FP7y6myWuepAca2uEIlONBPgRHZ2RjQXg9J/BAPVV8VPzFVR3cuxOpMuSxGpG96MWw4CoCOFgOJiNmj0CTDFyuIGNMwXuRVxW4UgIo4BVWXdVG2PnlzDjAGDEBLs0iTxJt+e9VBxMUDohAcW5eAjWOUoQAixN6gsd7zDHDRNAuQ0rOPNxIfWioDfzMm4NhCQK3VQTJ3DGyAeQDE0VFHZrIN2dgR/7X6/689OBUNx5YBFi2q/CKTphrPqsh4rn63Q1BjAAlD1SXF5M0OYA8zgCpy+6pKUMNQh6v6OuPY3UhKbIp9JnNPJwDrFyvscQmgtLaKU0XUaWZzQeA4di9EAw+MZFf7mRXLAHj26LFggAo6qBEhg1ZSnuPY7RADUVTXLSeysblZDS0tY8AA8+eb5mY15P5tqnPm0DAEVWeEJC1bTc0axiXDaMJUUs0iGgPMmrU5lrzHGCCZ6Y20torbFH/kokww8Zh8SZ1gjFSqIhxJvNtVw92Vn+PYNTingoAxvWWARugf1yFyAZUFFgCjXNMmTRLnbonOC9L2c1FMLKJSrZUa5J0OyND3ZwhkizbjGCEqRVYK1luZA6ALU6l/HMQAlRyi6O5Iy4iI9t3Ud6yk7P+qsl8pVGdFzBblGFt3f4ChKONMsHNQTBjmUFm8CoDZi/ov9TOANjeLtLbqt39yx1GpQE4Po+jF9IN33nvVDTeEsO26spGg79a+fZ1J3Ziy7JcrVog/4v7Tv4SoP9M9jhFBFfUsUo568ja18HEAem/vH0IPoL2yiua6tts/7tn0N8vlcuB5qZgz3/HL/z3z/H+vpfy8iMTNzc0GoLW1dcTBG21u9qS1NQrVfqPG947Ol9QZEVOtS9kRYioJAxhJCjTHsX2IJAtnSqG/Lm0e/AMAHZuDbx7A+vXrDYDGMr1un4nprvXriw6XNl76fWGkl/X56e/8b9udN36w6YKnIWGYuSNYdqXN7Z60zo16b+19h9jgXeVIqzTcYeL335OqWnBJXcWYw7EztnS1ZrA6BrtLtSlSKV7VbjnjL69osxpaRGlNrld7Hjc3N5tJQfybng2rH0tns2kQDUvFMIo1I17NF53Y+3746wWfWrBgQWru3LlRW1tbsC0fvq1NLXSQb390ujPRN1O+ScWuYvVRmc07aWuoKg6H7Ngajt2E7RN/oIs70LFRpZ8D+otIR7l3qlWjfv1aAOZgBq5RMABNlUrUyy+75NEpkzNNYbnvOt+aUiZb64tIVMz1lkMnkzGpby/PeT/9yU2/mdvU1FQWEW3WrYtKFJWZXTcYWlrict9+X80E9TPzRZxsMVqqlYGpDICqI3bbJ6qIIHio6mg7KjuNKjMPJGT1d6fJq78SecuXDpBso8wBRkTCSBGzJokAVnIA/derv7S2tjpVNZeeccaL8955/tVBVL4wLBd+UVtX52O8wLk4LhbLcSqdaSxL9pfXz7/j2y8uvKehVcQ1t7cPcic72jvs8VddFRbuXnFZTXpaUxybqOLdb4UqEyjgW0Nt2lbeHwFhxev3EswYxAsGEbtKPNmC0DvAn7vDyzECkZZjzJrnADo6OgZfH9wBcc3NzQZV+cC7L7pXO0sfLpd6m3xxi7LZWisiNpfrjWLHVC+o+dTdy6J7/ueW3729dYA9oG1tds6cOXHnbdfOcKH7osVvKIWxVGrgtoICkYOUrzy3+iZ+eO//UI5iUoFUrm9vRKrtKlHE3cgIVUbrF9WV7xoYxNolAvZbSKMF1WQthCuq5B8CmNPSMkjEVkZPpRmElhZaW1tVVWlp6bCtrQlhFyxYUL+uaC8qxO7fPZOaHkVlFCJrPU+dFtCoo74u809XnD/n8eqNN92
|
||
|
const danbo_icon = "data:image/png;base64,UklGRkgDAABXRUJQVlA4WAoAAAAQAAAAXwAAXwAAQUxQSC4AAAABDzD/ERECTSSp+RkEIAnrSEIAJFUqrkoV0f8JEOl92ramqAuR9x9xQYQotI0TVlA4IPQCAAAwGwCdASpgAGAAAAAAJYwDQFcD+k/jNt2fd/xA/IDkwu++840v/Jfyc/ru8Af1X7RuEB+gH8r9rDpAP6r/APU8/nfWAfpX6Dv+w/0fwj+gb+jH/R1jTy7/Sfwi/RT+Kfk4mzhm4gHswfQB/AK//0/0Tn+k6uj+ifgnyAHwAIn56AK4Ax4C8Nbq5KG6JLjN2dCB0Cot5bIh0jB3mKg8kvOCrgVqWcXENUemgUKGhZOoChhuwKLDmT7JlieTrTsuQMWHg6B/dTygFoUUC6XJl4V5/IDLWcYcGB+fm5TBzQkXsnEAAP7/3t0Uf+HR//pd6v9U91+l/9HrPPdc3//OZoyGl2sChOzeKf//5wX6DVMWAanet5+MwFJaYpt/RRcjyP/3/0u9X/FaH+o5v2s98GQzdFhTjdoryChWWGMOC4/xD/X7vyb/6gyqLL3/6+BsJ8ehd8U/XB3DFl8RwTxpDSqzDIuPz+FZ1Xxyy/MwzLb9i+JRJNKUYM7xHyYlD+pnP2pZ9Et02TVVNaytC7Zf6lIzT/92e/93ZjDzY2HXLG83xZOxxmaJCZ5MFk1H/sXMBHecqL/jBpxDOMMLv1hmL4VsnBs6S8jgcdvKyl67v62fcarL2dAZD9A3/a5m41SpuVOrsxrhKXyGfkSd07RIOsKz+Pn19/3oIow6YbHgYXZWrXA6ke5ZROMD308wNO9oNwLdxxiBfGE30Ixfb3lxoeagTdGF2DMxpilpEjNWVqc103bGQgB02y6c1bzRFyROks+wde2zZSWG+9mRuwihJO2JXp/FuoA3ERDhqTeg9xm+y+iPM59Kmzoqw7LJ0D2CuXa9/1RnY/JN//8DlLO6YfJjj4j+aX3M//EyEYXIMn02hq2rcV7c93Y0DdS6go32KbGZroTe0X/6WnwfnOXiIWvPbIlcsoeIMeOxAyrE13hFvDNqctyEKjAR9kBgOmB2CrID/0tZohex6Ilc1SsqLhRh1v6fxNufEBtNLt6Vf/vlCAAAAAA=";
|
||
|
const _tmpl$ = /* @__PURE__ */ template(`<img class="otis-icon" title="Tweet Search">`), _tmpl$2 = /* @__PURE__ */ template(`<img class="otis-icon" title="Danbooru IQDB Search">`), _tmpl$3 = /* @__PURE__ */ template(`<img class="otis-icon" title="SauceNAO Search">`), _tmpl$4 = /* @__PURE__ */ template(`<img class="otis-danbo-icon">`), _tmpl$5 = /* @__PURE__ */ template(`<a rel="noopener" target="_blank" class="danbo-text-link">`), _tmpl$6 = /* @__PURE__ */ template(`<span>`), _tmpl$7 = /* @__PURE__ */ template(`<div class="dropdown-menu danbo-more-results">`), _tmpl$8 = /* @__PURE__ */ template(`<span class="danbo-item"><img width="80px"><div><div> #<!> </div><div> <!> </div><div> <!> `);
|
||
|
const clickOutside = click_out_directive;
|
||
|
const GrapeCatIcon = ({
|
||
|
onClick
|
||
|
}) => (() => {
|
||
|
const _el$ = _tmpl$();
|
||
|
addEventListener(_el$, "click", onClick, true);
|
||
|
setAttribute(_el$, "src", grape_icon);
|
||
|
_el$.style.setProperty("width", "20px");
|
||
|
_el$.style.setProperty("margin-bottom", "2px");
|
||
|
return _el$;
|
||
|
})();
|
||
|
const IqdbIcon = ({
|
||
|
onClick
|
||
|
}) => (() => {
|
||
|
const _el$2 = _tmpl$2();
|
||
|
addEventListener(_el$2, "click", onClick, true);
|
||
|
setAttribute(_el$2, "src", iqdb_icon);
|
||
|
return _el$2;
|
||
|
})();
|
||
|
const SauceIcon = ({
|
||
|
onClick
|
||
|
}) => (() => {
|
||
|
const _el$3 = _tmpl$3();
|
||
|
addEventListener(_el$3, "click", onClick, true);
|
||
|
setAttribute(_el$3, "src", sauce_icon);
|
||
|
_el$3.style.setProperty("margin-right", "unset");
|
||
|
return _el$3;
|
||
|
})();
|
||
|
const DanboIcon = ({
|
||
|
onClick
|
||
|
}) => (() => {
|
||
|
const _el$4 = _tmpl$4();
|
||
|
addEventListener(_el$4, "click", onClick, true);
|
||
|
setAttribute(_el$4, "src", danbo_icon);
|
||
|
return _el$4;
|
||
|
})();
|
||
|
async function main() {
|
||
|
const settings_page = document.URL.endsWith("/old/settings");
|
||
|
if (settings_page)
|
||
|
return OTISSettingsPage();
|
||
|
const GrapeSearch = ({
|
||
|
media_url,
|
||
|
id,
|
||
|
username
|
||
|
}) => {
|
||
|
const [showTooltip, setShowTooltip] = createSignal(false);
|
||
|
const [ShowDanboResult, setShowDanboResult] = createSignal(false);
|
||
|
createSignal(0);
|
||
|
const [posts, setPosts] = createSignal([]);
|
||
|
const booru_check = async (e) => {
|
||
|
const ico = e.target;
|
||
|
ico.classList.add("otis-icon-loading");
|
||
|
ico.classList.remove("otis-icon-noresult");
|
||
|
const res = await tweet_search(id, username);
|
||
|
ico.classList.remove("otis-icon-loading");
|
||
|
if (res.length == 0) {
|
||
|
ico.classList.add("otis-icon-noresult");
|
||
|
ico.title = "Can't find any post based on Tweet ID.";
|
||
|
return void 0;
|
||
|
}
|
||
|
setPosts(res);
|
||
|
if (res.length === 1)
|
||
|
setShowDanboResult(true);
|
||
|
else
|
||
|
setShowTooltip(true);
|
||
|
};
|
||
|
const iqdb_check = async (e) => {
|
||
|
const ico = e.target;
|
||
|
ico.classList.add("otis-icon-loading");
|
||
|
ico.classList.remove("otis-icon-noresult");
|
||
|
const res = await iqdb_search(media_url[0]);
|
||
|
ico.classList.remove("otis-icon-loading");
|
||
|
if (res.length == 0) {
|
||
|
ico.classList.add("otis-icon-noresult");
|
||
|
ico.title = "No relevant image search results from IQDB";
|
||
|
return void 0;
|
||
|
}
|
||
|
setPosts(res);
|
||
|
if (res.length === 1)
|
||
|
setShowDanboResult(true);
|
||
|
else
|
||
|
setShowTooltip(true);
|
||
|
};
|
||
|
const sauce_check = async (e) => {
|
||
|
const ico = e.target;
|
||
|
ico.classList.add("otis-icon-loading");
|
||
|
ico.classList.remove("otis-icon-noresult");
|
||
|
const res = await saucenao_search(media_url[0]);
|
||
|
ico.classList.remove("otis-icon-loading");
|
||
|
if (res.length == 0) {
|
||
|
ico.classList.add("otis-icon-noresult");
|
||
|
ico.title = "No relevant image search results from IQDB";
|
||
|
return void 0;
|
||
|
}
|
||
|
setPosts(res);
|
||
|
if (res.length === 1)
|
||
|
setShowDanboResult(true);
|
||
|
else
|
||
|
setShowTooltip(true);
|
||
|
};
|
||
|
const DanboPostsResult = () => [createComponent(DanboIcon, {}), (() => {
|
||
|
const _el$5 = _tmpl$5();
|
||
|
_el$5.$$mouseover = () => setShowTooltip(true);
|
||
|
insert(_el$5, () => {
|
||
|
var _a;
|
||
|
return `#${(_a = posts()[0]) == null ? void 0 : _a.id}`;
|
||
|
});
|
||
|
createRenderEffect(() => {
|
||
|
var _a;
|
||
|
return setAttribute(_el$5, "href", `${DANBOORU_API}/posts/${(_a = posts()[0]) == null ? void 0 : _a.id}`);
|
||
|
});
|
||
|
return _el$5;
|
||
|
})()];
|
||
|
return [(() => {
|
||
|
const _el$6 = _tmpl$6();
|
||
|
insert(_el$6, createComponent(Show, {
|
||
|
get when() {
|
||
|
return !ShowDanboResult();
|
||
|
},
|
||
|
get fallback() {
|
||
|
return createComponent(DanboPostsResult, {});
|
||
|
},
|
||
|
get children() {
|
||
|
return [createComponent(GrapeCatIcon, {
|
||
|
onClick: booru_check
|
||
|
}), createComponent(IqdbIcon, {
|
||
|
onClick: iqdb_check
|
||
|
}), createComponent(SauceIcon, {
|
||
|
onClick: sauce_check
|
||
|
})];
|
||
|
}
|
||
|
}));
|
||
|
return _el$6;
|
||
|
})(), (() => {
|
||
|
const _el$7 = _tmpl$7();
|
||
|
use(clickOutside, _el$7, () => () => setShowTooltip(false));
|
||
|
insert(_el$7, createComponent(For, {
|
||
|
get each() {
|
||
|
return posts();
|
||
|
},
|
||
|
children: (post) => (() => {
|
||
|
const _el$8 = _tmpl$8(), _el$9 = _el$8.firstChild, _el$10 = _el$9.nextSibling, _el$11 = _el$10.firstChild, _el$12 = _el$11.firstChild, _el$14 = _el$12.nextSibling;
|
||
|
_el$14.nextSibling;
|
||
|
const _el$15 = _el$11.nextSibling, _el$16 = _el$15.firstChild, _el$18 = _el$16.nextSibling;
|
||
|
_el$18.nextSibling;
|
||
|
const _el$19 = _el$15.nextSibling, _el$20 = _el$19.firstChild, _el$22 = _el$20.nextSibling;
|
||
|
_el$22.nextSibling;
|
||
|
_el$8.$$click = () => window.open(`${DANBOORU_API}/posts/${post.id}`, "_blank");
|
||
|
insert(_el$11, () => post.id, _el$14);
|
||
|
insert(_el$15, () => post.source_domain, _el$18);
|
||
|
insert(_el$19, () => post.img_width >= 0 ? `${post.img_width} x ${post.img_height}` : "", _el$22);
|
||
|
createRenderEffect(() => setAttribute(_el$9, "src", post.thumbnail));
|
||
|
return _el$8;
|
||
|
})()
|
||
|
}));
|
||
|
createRenderEffect(() => _el$7.hidden = !showTooltip());
|
||
|
return _el$7;
|
||
|
})()];
|
||
|
};
|
||
|
const callback = (mutationList, observer) => {
|
||
|
for (const mutation of mutationList) {
|
||
|
if (mutation.type !== "childList")
|
||
|
return;
|
||
|
mutation.addedNodes.forEach((node) => {
|
||
|
const tweet = node;
|
||
|
const media = tweet.getElementsByClassName("tweet-media").item(0);
|
||
|
if (!media)
|
||
|
return;
|
||
|
const imgs = media.getElementsByTagName("img");
|
||
|
if (!imgs)
|
||
|
return;
|
||
|
const twt_interact = tweet.getElementsByClassName("tweet-interact").item(0);
|
||
|
const twt_avatar = tweet.getElementsByClassName("tweet-avatar-link").item(0);
|
||
|
const twt_child_elipsis = twt_interact == null ? void 0 : twt_interact.getElementsByClassName("tweet-interact-more").item(0);
|
||
|
const tweet_id = tweet.dataset.tweetId || "0";
|
||
|
const tweet_user = twt_avatar.href.split("/").pop() || "*";
|
||
|
let img_urls = [];
|
||
|
for (const img of imgs) {
|
||
|
img_urls.push(img.src);
|
||
|
}
|
||
|
const grape = createComponent(GrapeSearch, {
|
||
|
media_url: img_urls,
|
||
|
id: tweet_id,
|
||
|
username: tweet_user
|
||
|
});
|
||
|
twt_child_elipsis == null ? void 0 : twt_child_elipsis.before(...grape);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
const tweet_observer = new MutationObserver(callback);
|
||
|
const timeline = document.getElementById("timeline");
|
||
|
if (!timeline)
|
||
|
return;
|
||
|
const config = {
|
||
|
subtree: false,
|
||
|
childList: true,
|
||
|
attributes: false
|
||
|
};
|
||
|
tweet_observer.observe(timeline, config);
|
||
|
}
|
||
|
const element = document.getElementById("center-cell");
|
||
|
if (element) {
|
||
|
main();
|
||
|
}
|
||
|
delegateEvents(["click", "mouseover"]);
|
||
|
|
||
|
})();
|