Browse Source

Merge pull request 'Updooting take 2' (#53) from araragi/lolipiss:updoots into 中出し

Reviewed-on: https://git.coom.tech/fuckjannies/lolipiss/pulls/53
pull/56/head
coomdev 1 year ago
parent
commit
3b351ce9c0
  1. 77
      README.md
  2. 5
      build-chrome.js
  3. 2
      build-ff.js
  4. 5357
      package-lock.json
  5. 44
      package.json
  6. 5
      src/Components/App.svelte
  7. 2
      src/background.ts
  8. 2
      src/filehosts.ts
  9. 3
      src/gif.ts
  10. 66
      src/main.ts
  11. 25
      src/platform.ts
  12. 2
      src/png.ts
  13. 10
      src/processor.worker.ts
  14. 46
      src/stores.ts
  15. 33
      src/websites/index.ts
  16. 6
      tsconfig.json

77
README.md

@ -11,40 +11,33 @@ Also supports desuarchive.
Kohlchan support is being worked on. Right now works barely on Chrome. Kohlchan support is being worked on. Right now works barely on Chrome.
There's no server-side caching for kohlchan. Buttons to embed will only be added to the quick reply form. There's no server-side caching for kohlchan. Buttons to embed will only be added to the quick reply form.
Supported boards:
- [x] 4chan
- [x] FoolFuuka (desuarchive, b4k, etc)
- [x] Kohlchan (WIP)
How to Install How to Install
============== ==============
Note: 4chanX isn't a hard requirement, just recommended because it's overall a nicer experience. If you don't want to use 4chanX, make sure the native 4chan extension is enabled in your settings. Note for 4chan: 4chanX isn't a hard requirement, just recommended because it's overall a nicer experience. If you don't want to use 4chanX, make sure the native 4chan extension is enabled in your settings.
## Teh olde way
- Make sure you're using a decent Webkit-based browser (Chromium derivatives) or Firefox.
- [Install ViolentMonkey](https://violentmonkey.github.io/get-it/) (it is preferable to TamperMonkey(closed source) and GreaseMonkey(abandonned shit)), use [ViolentMonkey Beta](https://violentmonkey.github.io/get-it/#beta-release) if you want to spite the b4k meanie admin (based & redpilled). Be sure to read the trouble shooting section to know how to set this up.
- [Install 4chanX (recommended)](https://www.4chan-x.net/builds/4chan-X.user.js)
- Use the prebuilt [main.user.js](https://git.coom.tech/coomdev/PEE/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/main.user.js)
- Reorder PEE and 4chanX in the dashboard so that PEE runs BEFORE 4chanX (or add blob: to your 4chanX JS whitelist)
## The newer way (WIP) ## PEE 4 Dummies
Please report any issue you have with those (only for mainstream browsers) Please report any issue you have with those (only for mainstream browsers)
Also, use this if you plan to use b4k's archive. Also, use this if you plan to use b4k's archive.
- [Install 4chanX (recommended)](https://www.4chan-x.net/builds/4chan-X.user.js) - [Install 4chanX (recommended)](https://www.4chan-x.net/builds/4chan-X.user.js)
- [Install JKCS (recommended)](https://git.coom.tech/araragi/JKCS/src/branch/master/README.md) - Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.325.xpi) or Chrome-based (See "Side Loading")
- Install the correct WebExtension for your Browser ([Firefox](https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.325.xpi) or Chrome-based (Down for "maintainance"))
For FF users, the extension is signed so you can just drag and drop it on your about:addons tab. For FF users, the extension is signed so you can just drag and drop it on your about:addons tab.
Chrom* users can now install directly from the chrome webstore.
Known bugs: Known bugs:
- JPEG embedding might not work with some very big files (> 1MB). - JPEG embedding might not work with some very big files (> 1MB).
- GIFs and WebMs got patched :( - 4chan: GIFs and WebMs got patched :(
### Side loading ### Side loading
Because publishing on the Chrome WebStore is slow, you should consider side loading the extension.
- [Download](https://git.coom.tech/fuckjannies/lolipiss/archive/%E4%B8%AD%E5%87%BA%E3%81%97.zip) this repo and extract it somewhere - [Download](https://git.coom.tech/fuckjannies/lolipiss/archive/%E4%B8%AD%E5%87%BA%E3%81%97.zip) this repo and extract it somewhere
- Type `chrome://extensions` in your address bar - Type `chrome://extensions` in your address bar
- Enable **Developer Mode** - Enable **Developer Mode**
@ -52,51 +45,7 @@ Because publishing on the Chrome WebStore is slow, you should consider side load
- Select the `chrome` folder from the zip you extracted earlier. - Select the `chrome` folder from the zip you extracted earlier.
- Optional: Do the same for the `pee-companion` folder instead of `chrome` if you plan to use b4k and/or desuarchive. - Optional: Do the same for the `pee-companion` folder instead of `chrome` if you plan to use b4k and/or desuarchive.
If none of the above works for you, switch back to the userscript version and open an issue here. If none of the above works for you, open an issue here.
### Third Eye setup
For compliance with CWS rules, PEE doesn't come with preconfigured domains for Third Eye. Here are the old settings in case you want to reproduce them. This shouldn't concern old time users as you already have those in your settings, unless explicitely removed.
Copy paste this and click "bulk-import"
```
[
{"name": "Gelbooru",
"domain": "gelbooru.com",
"endpoint": "/index.php?page=dapi&s=post&q=index&json=1&tags=md5:",
"view": "https://gelbooru.com/index.php?page=post&s=view&id="
},
{"name": "Yandere",
"domain": "yande.re",
"endpoint": "/post.json?tags=md5:",
"view": "https://yande.re/post/show/"
},
{"name": "Sankaku",
"domain": "capi-v2.sankakucomplex.com",
"endpoint": "/posts/keyset?tags=md5:",
"view": "https://chan.sankakucomplex.com/post/show/"
},
{"name": "Rule34",
"domain": "api.rule34.xxx",
"endpoint": "/index.php?page=dapi&s=post&q=index&json=1&tags=md5:",
"view": "https://rule34.xxx/index.php?page=post&s=view&id="
},
{"name": "Danbooru",
"domain": "danbooru.donmai.us",
"endpoint": "/posts.json?tags=md5:",
"view": "https://danbooru.donmai.us/posts/"
},
{"name": "Lolibooru",
"domain": "lolibooru.moe",
"endpoint": "/post.json?tags=md5:",
"view": "https://lolibooru.moe/post/show/"
},
{"name": "ATFbooru",
"domain": "booru.allthefallen.moe",
"endpoint": "/posts.json?tags=md5:",
"view": "https://booru.allthefallen.moe/posts/"
}]
```
How to Build How to Build
============ ============
@ -105,8 +54,10 @@ How to Build
`npm i` and `npm i` and
`npm run build` to build the userscript version. `npm run build` to build the userscript version. (!!! DEPRECIATED !!!)
`npm run build_chrome` to build the chromium webextension. `npm run build_chrome` to build the chromium webextension.
`npm run build_ff` to build the firefox webextension. (You'll have to do the signing yourself, though) `npm run build_ff` to build the firefox webextension. (You'll have to do the signing yourself, though)
How to use How to use
@ -238,4 +189,4 @@ We reached 1000+ downloads on the Chrome WebStore.
![ack](842173-2.png) ![ack](842173-2.png)
Original character drawn by monmon. Original character drawn by monmon.

5
build-chrome.js

@ -33,7 +33,8 @@ const domains = [
"https://fireden.net/*", "https://fireden.net/*",
"https://thebarchive.com/*", "https://thebarchive.com/*",
"https://archiveofsins.com/*", "https://archiveofsins.com/*",
"https://kohlchan.net/*" "https://kohlchan.net/*",
"https://*.kohlchan.net/*"
]; ];
const manif3 = { const manif3 = {
@ -107,7 +108,7 @@ const manif3 = {
minify: false, minify: false,
bundle: true, bundle: true,
treeShaking: true, treeShaking: true,
target: "es2021", target: "es2022",
loader: { loader: {
'.css': 'text', '.css': 'text',
'.png': 'binary' '.png': 'binary'

2
build-ff.js

@ -121,7 +121,7 @@ const manif = {
minify: false, minify: false,
bundle: true, bundle: true,
treeShaking: true, treeShaking: true,
target: "es2021", target: "es2022",
loader: { loader: {
'.css': 'text', '.css': 'text',
'.png': 'binary' '.png': 'binary'

5357
package-lock.json

File diff suppressed because it is too large

44
package.json

@ -15,7 +15,7 @@
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@astronautlabs/bitstream": "^4.1.2", "@astronautlabs/bitstream": "^4.1.3",
"assert-browserify": "^2.0.0", "assert-browserify": "^2.0.0",
"base58": "^2.0.1", "base58": "^2.0.1",
"blockhash": "^0.2.0", "blockhash": "^0.2.0",
@ -23,41 +23,41 @@
"browserify-zlib": "^0.2.0", "browserify-zlib": "^0.2.0",
"bs58": "^5.0.0", "bs58": "^5.0.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"crc-32": "^1.2.0", "crc-32": "^1.2.2",
"events": "^3.3.0", "events": "^3.3.0",
"f5stegojs": "^0.1.2", "f5stegojs": "^0.1.2",
"file-type": "^17.0.2", "file-type": "^18.0.0",
"hls.js": "^1.1.5", "hls.js": "^1.2.9",
"image-hash": "^5.0.1", "image-hash": "^5.3.1",
"jpeg-js": "^0.4.3", "jpeg-js": "^0.4.4",
"jsdom": "^19.0.0", "jsdom": "^20.0.3",
"linkify-string": "^3.0.4", "linkify-string": "^4.0.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mp4box": "^0.5.2", "mp4box": "^0.5.2",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"png-js": "^1.0.0", "png-js": "^1.0.0",
"readable-stream": "^3.6.0", "readable-stream": "^4.2.0",
"socks-proxy-agent": "^7.0.0", "socks-proxy-agent": "^7.0.0",
"ts-ebml": "^2.0.2", "ts-ebml": "^2.0.2",
"util": "^0.12.4" "util": "^0.12.5"
}, },
"devDependencies": { "devDependencies": {
"@tsconfig/svelte": "^3.0.0", "@tsconfig/svelte": "^3.0.0",
"@types/jsdom": "^16.2.14", "@types/jsdom": "^20.0.1",
"@types/lodash": "^4.14.181", "@types/lodash": "^4.14.191",
"@types/tampermonkey": "^4.0.5", "@types/tampermonkey": "^4.0.5",
"@typescript-eslint/eslint-plugin": "^5.9.0", "@typescript-eslint/eslint-plugin": "^5.47.0",
"crx": "^5.0.1", "crx": "^5.0.1",
"esbuild": "^0.14.48", "esbuild": "^0.16.10",
"esbuild-css-modules-plugin": "^2.0.9", "esbuild-css-modules-plugin": "^2.6.3",
"esbuild-plugin-inline-worker": "^0.1.1", "esbuild-plugin-inline-worker": "^0.1.1",
"esbuild-svelte": "^0.6.3", "esbuild-svelte": "^0.7.3",
"eslint": "^8.6.0", "eslint": "^8.30.0",
"svelte": "^3.44.3", "svelte": "^3.55.0",
"svelte-check": "^2.2.11", "svelte-check": "^2.10.3",
"svelte-preprocess": "^4.10.1", "svelte-preprocess": "^5.0.0",
"typescript": "^4.5.4", "typescript": "^4.9.4",
"web-ext": "^7.1.1", "web-ext": "^7.4.0",
"web-ext-types": "^3.2.1" "web-ext-types": "^3.2.1"
}, },
"browser": { "browser": {

5
src/Components/App.svelte

@ -134,10 +134,7 @@
<div class="content"> <div class="content">
<h1>PEE Settings 0.{rev}</h1> <h1>PEE Settings 0.{rev}</h1>
<h4> <h4>
<a href="https://2chen.moe/tech/">Join us on 2chen!</a> <a href="https://2chen.moe/tech/">Join us on 2chen!</a>
<a href="https://git.coom.tech/araragi/JKCS/src/branch/master/README.md"
>Install JKCS!</a
>
</h4> </h4>
<hr /> <hr />
<Tabs> <Tabs>

2
src/background.ts

@ -112,7 +112,7 @@ const bgCorsFetch = async (c: MessagePort,
} }
}; };
const reader = k.body?.getReader(); const reader = k.body?.getReader();
let res: ReadableStreamDefaultReadResult<Uint8Array>; let res: ReadableStreamReadResult<Uint8Array>;
for (; ;) { for (; ;) {
res = await reader!.read(); res = await reader!.read();
if (res.done) break; if (res.done) break;

2
src/filehosts.ts

@ -70,4 +70,4 @@ export const filehosts: API[] = [
catbox('pomf.moe', 'a.pomf.cat'), catbox('pomf.moe', 'a.pomf.cat'),
lolisafe('take-me-to.space'), lolisafe('take-me-to.space'),
lolisafe('zz.ht', 'z.zz.fo'), lolisafe('zz.ht', 'z.zz.fo'),
]; ];

3
src/gif.ts

@ -1,5 +1,6 @@
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import type { EmbeddedFile, ImageProcessor } from "./main"; import type { EmbeddedFile } from "./main";
import type { ImageProcessor } from "./processor.worker";
import { BufferWriteStream } from "./png"; import { BufferWriteStream } from "./png";
import { decodeCoom3Payload, uploadFiles } from "./utils"; import { decodeCoom3Payload, uploadFiles } from "./utils";

66
src/main.ts

@ -1,4 +1,4 @@
/// <reference lib="ES2021" /> /// <reference lib="ES2022" />
/// <reference lib="dom" /> /// <reference lib="dom" />
import { Buffer } from "buffer"; import { Buffer } from "buffer";
@ -22,11 +22,11 @@ import EyeButton from './Components/EyeButton.svelte';
import NotificationsHandler from './Components/NotificationsHandler.svelte'; import NotificationsHandler from './Components/NotificationsHandler.svelte';
import { fireNotification, getEmbedsFromCache, getSelectedFile } from "./utils"; import { fireNotification, getEmbedsFromCache, getSelectedFile } from "./utils";
import { getQueryProcessor, QueryProcessor } from "./websites"; import { getQueryProcessor, QueryProcessor, supportedAltDomain, supportedMainDomain } from "./websites";
import { ifetch, Platform, sendCmd, lqueue, supportedAltDomain, supportedMainDomain, genPort, initMainIPC } from "./platform"; import { ifetch, Platform, sendCmd, lqueue, genPort, initMainIPC } from "./platform";
import TextEmbeddingsSvelte from "./Components/TextEmbeddings.svelte"; import TextEmbeddingsSvelte from "./Components/TextEmbeddings.svelte";
import { HydrusClient } from "./hydrus"; import { HydrusClient } from "./hydrus";
import { registerPlugin } from 'linkifyjs'; import { registerPlugin, createTokenClass } from 'linkifyjs';
import ViewCountSvelte from "./Components/ViewCount.svelte"; import ViewCountSvelte from "./Components/ViewCount.svelte";
import type { ImageProcessor, WorkerEmbeddedFile } from './processor.worker'; import type { ImageProcessor, WorkerEmbeddedFile } from './processor.worker';
@ -93,60 +93,6 @@ type EmbeddedFileWithoutPreview = {
export type EmbeddedFile = EmbeddedFileWithPreview | EmbeddedFileWithoutPreview; export type EmbeddedFile = EmbeddedFileWithPreview | EmbeddedFileWithoutPreview;
/*
const processImage = async (srcs: AsyncGenerator<string, void, void>, fn: string, hex: string, prevurl: string) => {
const ret = await Promise.all(processors.filter(e => e.match(fn)).map(async proc => {
if (proc.skip) {
// skip file downloading, file is referenced from the filename
// basically does things like filtering out blacklisted tags
const md5 = Buffer.from(hex, 'base64');
if (await proc.has_embed(md5, fn, prevurl) === true) {
return [await proc.extract(md5, fn), true] as [EmbeddedFile[], boolean];
}
return;
}
let succ = false;
let cumul: Buffer;
do {
try {
const n = await srcs.next();
if (n.done)
return; // no more links to try
const iter = streamRemote(n.value);
if (!iter)
return;
cumul = Buffer.alloc(0);
let found: boolean | undefined;
let chunk: ReadableStreamDefaultReadResult<Buffer> = { done: true };
do {
const { value, done } = await iter.next(typeof found === "boolean");
if (done) {
chunk = { done: true } as ReadableStreamDefaultReadDoneResult;
} else {
chunk = { done: false, value } as ReadableStreamDefaultReadValueResult<Buffer>;
cumul = Buffer.concat([cumul, value!]);
const v = await proc.has_embed(cumul);
if (typeof v == "string") {
return [await proc.extract(cumul, v), false] as [EmbeddedFile[], boolean];
}
found = v;
}
} while (found !== false && !chunk.done);
succ = true;
await iter.next(true);
if (found !== true) {
//console.log(`Gave up on ${src} after downloading ${cumul.byteLength} bytes...`);
return;
}
return [await proc.extract(cumul), false] as [EmbeddedFile[], boolean];
} catch {
// ignore error and retry with another link
}
} while (!succ);
}));
return ret.filter(e => e).map(e => e!);
};*/
const textToElement = <T = HTMLElement>(s: string) => const textToElement = <T = HTMLElement>(s: string) =>
document.createRange().createContextualFragment(s).children[0] as any as T; document.createRange().createContextualFragment(s).children[0] as any as T;
@ -709,7 +655,7 @@ const startup = async (is4chanX = true) => {
const START_STATE = parser.start; const START_STATE = parser.start;
const pref = qp.getPostIdPrefix(); const pref = qp.getPostIdPrefix();
const endQuote = utils.createTokenClass('postQuote', { const endQuote = createTokenClass('postQuote', {
isLink: true, isLink: true,
toHref() { toHref() {
return `#${pref}${this.toString().substr(2)}`; return `#${pref}${this.toString().substr(2)}`;
@ -822,7 +768,7 @@ const startup = async (is4chanX = true) => {
} }
}; };
const obs = new MutationObserver(somethingChanged); const obs = new MutationObserver(somethingChanged);
if (location.host.includes("kohlchan.net")) { if (['kohlchan.net', 'nocsp.kohlchan.net'].includes(location.host)) {
// vanilla kohl, behaves a bit like a mix of the two // vanilla kohl, behaves a bit like a mix of the two
target = e.detail as HTMLDivElement; target = e.detail as HTMLDivElement;
a.style.display = "inline-block"; a.style.display = "inline-block";

25
src/platform.ts

@ -112,29 +112,6 @@ const Bridged = (ctor: any) => {
ctor[k] = bridge(k, ctor[k]); ctor[k] = bridge(k, ctor[k]);
}; };
const altdomains = [
"desuarchive.org",
"archived.moe",
"archive.nyafuu.org",
"arch.b4k.co",
"archive.4plebs.org",
"archive.wakarimasen.moe",
"b4k.co",
"fireden.net",
"thebarchive.com",
"archiveofsins.com",
"kohlchan.net",
"nocsp.kohlchan.net",
];
export function supportedAltDomain(s: string) {
return altdomains.includes(s);
}
export function supportedMainDomain(s: string) {
return ['boards.4channel.org', 'boards.4chan.org'].includes(s);
}
let popupport: browser.runtime.Port; let popupport: browser.runtime.Port;
const pendingcmds: Record<number, (v?: any) => void> = {}; const pendingcmds: Record<number, (v?: any) => void> = {};
@ -336,7 +313,7 @@ export const corsFetch = async (input: string, init?: RequestInit, lsn?: EventTa
const r = rs.getReader(); const r = rs.getReader();
await sendCmd({ name: 'fullyRead', fid: id }); await sendCmd({ name: 'fullyRead', fid: id });
const abs: Uint8Array[] = []; const abs: Uint8Array[] = [];
let res: ReadableStreamDefaultReadResult<Uint8Array>; let res: ReadableStreamReadResult<Uint8Array>;
do { do {
res = await r.read(); res = await r.read();
if (res.done) break; if (res.done) break;

2
src/png.ts

@ -1,6 +1,6 @@
import { buf } from "crc-32"; import { buf } from "crc-32";
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import type { ImageProcessor } from "./main"; import type { ImageProcessor } from "./processor.worker";
export type PNGChunk = [ export type PNGChunk = [
string, // name string, // name

10
src/processor.worker.ts

@ -1,4 +1,4 @@
/// <reference lib="ES2021" /> /// <reference lib="ES2022" />
/// <reference lib="webworker" /> /// <reference lib="webworker" />
import * as platform from './platform'; import * as platform from './platform';
@ -127,13 +127,13 @@ const processImage = async (srcs: AsyncGenerator<string, void, void>, fn: string
return; return;
cumul = Buffer.alloc(0); cumul = Buffer.alloc(0);
let found: boolean | undefined; let found: boolean | undefined;
let chunk: ReadableStreamDefaultReadResult<Buffer> = { done: true }; let chunk: ReadableStreamReadResult<Buffer> = { done: true };
do { do {
const { value, done } = await iter.next(typeof found === "boolean"); const { value, done } = await iter.next(typeof found === "boolean");
if (done) { if (done) {
chunk = { done: true } as ReadableStreamDefaultReadDoneResult; chunk = { done: true } as ReadableStreamReadDoneResult<Buffer>;
} else { } else {
chunk = { done: false, value } as ReadableStreamDefaultReadValueResult<Buffer>; chunk = { done: false, value } as ReadableStreamReadValueResult<Buffer>;
cumul = Buffer.concat([cumul, value!]); cumul = Buffer.concat([cumul, value!]);
const v = await proc.has_embed(cumul); const v = await proc.has_embed(cumul);
if (typeof v == "string") { if (typeof v == "string") {
@ -213,4 +213,4 @@ let init = false;
} }
} }
}; };
})(); })();

46
src/stores.ts

@ -49,7 +49,51 @@ export const initial_settings = {
conc: 8, conc: 8,
ho: false, ho: false,
blacklist: [] as string[], blacklist: [] as string[],
rsources: [] as (Omit<Booru, 'quirks'> & { view: string, disabled?: boolean })[], rsources: [
{
name: 'Gelbooru',
domain: 'gelbooru.com',
endpoint: '/index.php?page=dapi&s=post&q=index&json=1&tags=md5:',
view: "https://gelbooru.com/index.php?page=post&s=view&id="
},
{
name: 'Yandere',
domain: 'yande.re',
endpoint: '/post.json?tags=md5:',
view: `https://yande.re/post/show/`
},
{
name: 'Sankaku',
domain: 'capi-v2.sankakucomplex.com',
endpoint: '/posts/keyset?tags=md5:',
view: `https://chan.sankakucomplex.com/post/show/`
},
{
name: 'Rule34',
domain: 'api.rule34.xxx',
endpoint: '/index.php?page=dapi&s=post&q=index&json=1&tags=md5:',
// note: rule34 do not seem to give source in their API
view: "https://rule34.xxx/index.php?page=post&s=view&id="
},
{
name: 'Danbooru',
domain: 'danbooru.donmai.us',
endpoint: '/posts.json?tags=md5:',
view: 'https://danbooru.donmai.us/posts/'
},
{
name: 'Lolibooru',
domain: 'lolibooru.moe',
endpoint: '/post.json?tags=md5:',
view: 'https://lolibooru.moe/post/show/'
},
{
name: "ATFbooru",
domain: "booru.allthefallen.moe",
endpoint: "/posts.json?tags=md5:",
view: 'https://booru.allthefallen.moe/posts/'
}
] as (Omit<Booru, 'quirks'> & { view: string, disabled?: boolean })[],
}; };
export const settings = writable<Awaited<typeof initial_settings>>(); export const settings = writable<Awaited<typeof initial_settings>>();

33
src/websites/index.ts

@ -23,7 +23,7 @@ export const V4chan: QueryProcessor = {
postsWithFiles: (h) => [...(h || document).querySelectorAll('.file')].map(e => e.closest('.postContainer')) as any, postsWithFiles: (h) => [...(h || document).querySelectorAll('.file')].map(e => e.closest('.postContainer')) as any,
settingsHost: () => document.getElementById("navtopright") as any, settingsHost: () => document.getElementById("navtopright") as any,
catalogControlHost: () => document.getElementById("settings") as HTMLDivElement, catalogControlHost: () => document.getElementById("settings") as HTMLDivElement,
getImageLink: async function* (post: HTMLElement) { getImageLink: async function*(post: HTMLElement) {
yield post.querySelector('a[target="_blank"]')?.getAttribute('href') || ''; yield post.querySelector('a[target="_blank"]')?.getAttribute('href') || '';
}, },
@ -49,7 +49,7 @@ export const X4chan: QueryProcessor = {
postsWithFiles: (h) => [...(h || document).querySelectorAll('.postContainer:not([class*="noFile"])')] as HTMLElement[], postsWithFiles: (h) => [...(h || document).querySelectorAll('.postContainer:not([class*="noFile"])')] as HTMLElement[],
settingsHost: () => document.getElementById("shortcuts") as any, settingsHost: () => document.getElementById("shortcuts") as any,
catalogControlHost: () => document.getElementById("index-options") as HTMLDivElement, catalogControlHost: () => document.getElementById("index-options") as HTMLDivElement,
getImageLink: async function* (post: HTMLElement) { getImageLink: async function*(post: HTMLElement) {
yield post.querySelector('a[target="_blank"]')?.getAttribute('href') || ''; yield post.querySelector('a[target="_blank"]')?.getAttribute('href') || '';
}, },
getFilename: (post: HTMLElement) => { getFilename: (post: HTMLElement) => {
@ -72,7 +72,7 @@ export const FoolFuuka: QueryProcessor = {
postsWithFiles: (h) => [...(h || document).querySelectorAll('article[class*="thread"], article[class*="has_image"]')] as HTMLElement[], postsWithFiles: (h) => [...(h || document).querySelectorAll('article[class*="thread"], article[class*="has_image"]')] as HTMLElement[],
settingsHost: () => document.querySelector(".letters") as any, settingsHost: () => document.querySelector(".letters") as any,
catalogControlHost: () => document.getElementById("index-options") as HTMLDivElement, catalogControlHost: () => document.getElementById("index-options") as HTMLDivElement,
getImageLink: async function* (post: HTMLElement) { getImageLink: async function*(post: HTMLElement) {
if (location.host == "arch.b4k.co") { //get hecked if (location.host == "arch.b4k.co") { //get hecked
return; return;
} }
@ -103,7 +103,7 @@ export const KChan: QueryProcessor = {
postsWithFiles: (h) => ([...(h || document).querySelectorAll('.postCell')] as HTMLElement[]).filter(p => p.querySelector('figure')), postsWithFiles: (h) => ([...(h || document).querySelectorAll('.postCell')] as HTMLElement[]).filter(p => p.querySelector('figure')),
settingsHost: () => document.getElementById("navOptionsSpanThread") as any, settingsHost: () => document.getElementById("navOptionsSpanThread") as any,
catalogControlHost: () => document.getElementById("divTools") as HTMLDivElement, catalogControlHost: () => document.getElementById("divTools") as HTMLDivElement,
getImageLink: async function* (post: HTMLElement) { getImageLink: async function*(post: HTMLElement) {
yield (post.querySelector('a.imgLink[target="_blank"]') as HTMLAnchorElement)?.href || ''; yield (post.querySelector('a.imgLink[target="_blank"]') as HTMLAnchorElement)?.href || '';
}, },
@ -126,9 +126,32 @@ export const KChan: QueryProcessor = {
export const getQueryProcessor = (is4chanX: boolean) => { export const getQueryProcessor = (is4chanX: boolean) => {
if (['boards.4chan.org', 'boards.4channel.org'].includes(location.host)) if (['boards.4chan.org', 'boards.4channel.org'].includes(location.host))
return is4chanX ? X4chan : V4chan; return is4chanX ? X4chan : V4chan;
if (location.host.includes("kohlchan.net")) { if (['kohlchan.net', 'nocsp.kohlchan.net'].includes(location.host)) {
return KChan; return KChan;
} }
if (document.querySelector('meta[name="generator"]')?.getAttribute("content")?.startsWith("FoolFuuka")) if (document.querySelector('meta[name="generator"]')?.getAttribute("content")?.startsWith("FoolFuuka"))
return FoolFuuka; return FoolFuuka;
}; };
const altdomains = [
"desuarchive.org",
"archived.moe",
"archive.nyafuu.org",
"arch.b4k.co",
"archive.4plebs.org",
"archive.wakarimasen.moe",
"b4k.co",
"fireden.net",
"thebarchive.com",
"archiveofsins.com",
"kohlchan.net",
"nocsp.kohlchan.net",
];
export function supportedAltDomain(s: string) {
return altdomains.includes(s);
}
export function supportedMainDomain(s: string) {
return ['boards.4channel.org', 'boards.4chan.org'].includes(s);
}

6
tsconfig.json

@ -1,7 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"moduleResolution": "node", "moduleResolution": "node",
//"target": "es2017",
/** /**
Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript Svelte Preprocess cannot figure out whether you have a value or a type, so tell TypeScript
to enforce using `import type` instead of `import` for Types. to enforce using `import type` instead of `import` for Types.
@ -9,7 +8,8 @@
"importsNotUsedAsValues": "error", "importsNotUsedAsValues": "error",
"isolatedModules": true, "isolatedModules": true,
"lib": [ "lib": [
"dom" "dom",
"dom.iterable",
], ],
/** /**
To have warnings/errors of the Svelte compiler at the correct position, To have warnings/errors of the Svelte compiler at the correct position,
@ -19,7 +19,7 @@
/** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */ /** Requests the runtime types from the svelte modules by default. Needed for TS files or else you get errors. */
"types": ["svelte", "tampermonkey", "web-ext-types"], "types": ["svelte", "tampermonkey", "web-ext-types"],
"incremental": true, /* Enable incremental compilation */ "incremental": true, /* Enable incremental compilation */
"target": "es2021", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "target": "es2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
//"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ //"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"outDir": "./dist", /* Redirect output structure to the directory. */ "outDir": "./dist", /* Redirect output structure to the directory. */
"strict": true, /* Enable all strict type-checking options. */ "strict": true, /* Enable all strict type-checking options. */

Loading…
Cancel
Save