diff --git a/main.meta.js b/main.meta.js index bbe5850..addb86e 100644 --- a/main.meta.js +++ b/main.meta.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.98 +// @version 0.99 // @description uhh // @author You // @match https://boards.4channel.org/* diff --git a/main.user.js b/main.user.js index 94a84bc..85d283f 100644 --- a/main.user.js +++ b/main.user.js @@ -1,7 +1,7 @@ // ==UserScript== // @name PNGExtraEmbed // @namespace https://coom.tech/ -// @version 0.98 +// @version 0.99 // @description uhh // @author You // @match https://boards.4channel.org/* @@ -10924,6 +10924,7 @@ })); var appState = writable({ isCatalog: false, + is4chanX: false, foundPosts: [] }); appState.subscribe((v) => { @@ -11426,6 +11427,19 @@ preview_url: e.preview_url, tags: e.tags.split(" ") })) + }, + { + name: "ATFbooru", + domain: "booru.allthefallen.moe", + endpoint: "/posts.json?tags=md5:", + quirks: (a) => a.map((e) => ({ + source: e.source, + page: `https://booru.allthefallen.moe/posts/${e.id}`, + ext: e.file_url.substr(e.file_url.lastIndexOf(".") + 1), + full_url: e.file_url, + preview_url: e.preview_url, + tags: e.tag_string.split(" ") + })) } ]; var black = /* @__PURE__ */ new Set(); @@ -12050,7 +12064,8 @@ "capi-v2.sankakucomplex.com", "api.rule34.xxx", "danbooru.donmai.us", - "lolibooru.moe" + "lolibooru.moe", + "boory.allthefallen.moe" ]; let selectobj; let selectobj2; @@ -15560,14 +15575,9 @@ post.setAttribute("data-processed", "true"); }; var startup = async () => { + if (typeof window["FCX"] != "undefined") + appState.set({ ...cappState, is4chanX: true }); await Promise.all([...document.querySelectorAll(".postContainer")].filter((e) => e.textContent?.includes("191 KB")).map((e) => processPost(e))); - document.addEventListener("ThreadUpdate", async (e) => { - const newPosts = e.detail.newPosts; - for (const post of newPosts) { - const postContainer = document.getElementById("pc" + post.substring(post.indexOf(".") + 1)); - processPost(postContainer); - } - }); const mo = new MutationObserver((reco) => { for (const rec of reco) if (rec.type == "childList") @@ -15599,7 +15609,7 @@ document.body.append(scrollHost); appState.set({ ...cappState, - isCatalog: !!document.querySelector(".catalog-small") + isCatalog: !!document.querySelector(".catalog-small") || !!location.pathname.match(/\/catalog$/) }); await Promise.all(posts.map((e) => processPost(e))); }; @@ -15610,15 +15620,38 @@ }); }; document.addEventListener("4chanXInitFinished", startup); + document.addEventListener("ThreadUpdate", async (e) => { + const newPosts = e.detail.newPosts; + for (const post of newPosts) { + const postContainer = document.getElementById("pc" + post.substring(post.indexOf(".") + 1)); + processPost(postContainer); + } + }); + if (cappState.is4chanX) { + const qr = window["QR"]; + const show = qr.show.bind(qr); + qr.show = (...args) => { + show(...args); + document.dispatchEvent(new CustomEvent("QRDialogCreation", { + detail: document.getElementById("quickReply") + })); + }; + } document.addEventListener("QRDialogCreation", (e) => { - const target = e.target; - const bts = target.querySelector("#qr-filename-container"); + const a = document.createElement("a"); const i = document.createElement("i"); i.className = "fa fa-magnet"; - const a = document.createElement("a"); a.appendChild(i); a.title = "Embed File (Select a file before...)"; - bts?.appendChild(a); + let target; + if (cappState.is4chanX) { + i.innerText = "\u{1F9F2}"; + target = e.detail; + target.querySelector("input[type=submit]")?.insertAdjacentElement("beforebegin", a); + } else { + target = e.target; + target.querySelector("#qr-filename-container")?.appendChild(a); + } a.onclick = async (e2) => { const file = await getSelectedFile(); if (!file) @@ -15659,7 +15692,7 @@ }; input.click(); }; - }, { once: true }); + }, { once: !cappState.is4chanX }); var customStyles = document.createElement("style"); customStyles.appendChild(document.createTextNode(global_default)); document.documentElement.insertBefore(customStyles, null); diff --git a/src/App.svelte b/src/App.svelte index 4a0030b..adc4d57 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -18,6 +18,7 @@ 'api.rule34.xxx', 'danbooru.donmai.us', 'lolibooru.moe', + 'boory.allthefallen.moe' ] let selectobj: HTMLSelectElement diff --git a/src/main.ts b/src/main.ts index 7565e52..24bdc5d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -65,7 +65,7 @@ async function* streamRemote(url: string, chunkSize = 16 * 1024, fetchRestOnNonC } type EmbeddedFileWithPreview = { - page?: {title: string, url: string}; // can be a booru page + page?: { title: string, url: string }; // can be a booru page source?: string; // can be like a twitter post this was posted in originally thumbnail: Buffer; filename: string; @@ -205,18 +205,11 @@ const processPost = async (post: HTMLDivElement) => { }; const startup = async () => { + if (typeof (window as any)['FCX'] != "undefined") + appState.set({ ...cappState, is4chanX: true }); await Promise.all([...document.querySelectorAll('.postContainer')].filter(e => e.textContent?.includes("191 KB")).map(e => processPost(e as any))); - // Basically this is a misnommer: fires even when inlining existings posts, also posts are inlined through some kind of dom projection - document.addEventListener('ThreadUpdate', (async (e: CustomEvent) => { - const newPosts = e.detail.newPosts; - for (const post of newPosts) { - const postContainer = document.getElementById("pc" + post.substring(post.indexOf(".") + 1)) as HTMLDivElement; - processPost(postContainer); - } - })); - // keep this to handle posts getting inlined const mo = new MutationObserver(reco => { for (const rec of reco) @@ -255,7 +248,7 @@ const startup = async () => { appState.set({ ...cappState, - isCatalog: !!document.querySelector('.catalog-small'), + isCatalog: !!document.querySelector('.catalog-small') || !!location.pathname.match(/\/catalog$/), }); await Promise.all(posts.map(e => processPost(e as any))); }; @@ -267,17 +260,54 @@ const getSelectedFile = () => { }); }; -document.addEventListener('4chanXInitFinished', startup); +//if (cappState!.is4chanX) + document.addEventListener('4chanXInitFinished', startup); +/*else { + document.addEventListener("QRGetFile", (e) => { + const qr = document.getElementById('qrFile') as HTMLInputElement | null; + document.dispatchEvent(new CustomEvent("QRFile", { detail: (qr?.files || [])[0] })); + }); + startup(); +}*/ + +// Basically this is a misnommer: fires even when inlining existings posts, also posts are inlined through some kind of dom projection +document.addEventListener('ThreadUpdate', (async (e: CustomEvent) => { + const newPosts = e.detail.newPosts; + for (const post of newPosts) { + const postContainer = document.getElementById("pc" + post.substring(post.indexOf(".") + 1)) as HTMLDivElement; + processPost(postContainer); + } +})); + +if (cappState!.is4chanX) { + const qr = (window as any)['QR']; + const show = qr.show.bind(qr); + qr.show = (...args: any[]) => { + show(...args); + document.dispatchEvent(new CustomEvent("QRDialogCreation", { + detail: document.getElementById('quickReply') + })); + }; +} -document.addEventListener('QRDialogCreation', ((e: CustomEvent) => { - const target = e.target as HTMLDivElement; - const bts = target.querySelector('#qr-filename-container'); +document.addEventListener('QRDialogCreation', ((e: CustomEvent) => { + const a = document.createElement('a'); const i = document.createElement('i'); i.className = "fa fa-magnet"; - const a = document.createElement('a'); a.appendChild(i); a.title = "Embed File (Select a file before...)"; - bts?.appendChild(a); + + let target; + if (cappState.is4chanX) { + i.innerText = "🧲"; + target = e.detail; + target.querySelector("input[type=submit]")?.insertAdjacentElement("beforebegin", a); + } + else { + target = e.target as HTMLDivElement; + target.querySelector('#qr-filename-container')?.appendChild(a); + } + a.onclick = async (e) => { const file = await getSelectedFile(); if (!file) @@ -319,7 +349,7 @@ document.addEventListener('QRDialogCreation', ((e: CustomEvent) => }); input.click(); }; -}), { once: true }); +}), { once: !cappState!.is4chanX }); // 4chan's normal extension destroys the QR form everytime const customStyles = document.createElement('style'); diff --git a/src/stores.ts b/src/stores.ts index 4bd49f0..8d17d5e 100644 --- a/src/stores.ts +++ b/src/stores.ts @@ -31,6 +31,7 @@ export const settings = writable(localLoad('settings', { export const appState = writable({ isCatalog: false, + is4chanX: false, foundPosts: [] as HTMLElement[] }); diff --git a/src/thirdeye.ts b/src/thirdeye.ts index cdef92f..a774c03 100644 --- a/src/thirdeye.ts +++ b/src/thirdeye.ts @@ -26,7 +26,7 @@ function firstThatFor(promises: Promise[], pred: (v: T) => boolean) { if (pred(v)) return v; throw v; - })) + })); } const gelquirk: (s: string) => tran = prefix => (a => @@ -109,7 +109,34 @@ export const boorus: Booru[] = [ preview_url: e.preview_url, tags: e.tags.split(' ') } as BooruMatch)) - } + }, + { + name: "ATFbooru", + domain: "booru.allthefallen.moe", + endpoint: "/posts.json?tags=md5:", + quirks: a => + a.map((e: any) => ({ + source: e.source, + page: `https://booru.allthefallen.moe/posts/${e.id}`, + ext: e.file_url.substr(e.file_url.lastIndexOf('.') + 1), + full_url: e.file_url, + preview_url: e.preview_url, + tags: e.tag_string.split(' ') + } as BooruMatch)) + }, + // { + // name: "Rule34Paheal", domain: "rule34.paheal.net", + // endpoint: "/posts.json?tags=md5:", + // quirks: a => + // a.map((e: any) => ({ + // source: e.source, + // page: `https://rule34.paheal.net/post/view/${e.id}`, + // ext: e.file_url.substr(e.file_url.lastIndexOf('.') + 1), + // full_url: e.file_url, + // preview_url: e.preview_url, + // tags: e.tag_string.split(' ') + // } as BooruMatch)) + // } ]; let black = new Set();