Browse Source

Add news system

pull/46/head
coomdev 2 years ago
parent
commit
719f143969
  1. 4
      chrome/b4k-csp.json
  2. 135
      chrome/dist/background.js
  3. 4432
      chrome/dist/main.js
  4. 2
      chrome/manifest.json
  5. 135
      firefox/dist/background.js
  6. 4432
      firefox/dist/main.js
  7. 2
      firefox/manifest.json
  8. 74
      main.d.ts
  9. 2
      main.meta.js
  10. 4393
      main.user.js
  11. 36
      src/Components/App.svelte
  12. 29
      src/gif.ts
  13. 2
      src/main.ts
  14. 41
      src/pngv3.ts
  15. 15
      src/webm.ts
  16. 2
      src/websites/index.ts

4
chrome/b4k-csp.json

@ -12,10 +12,10 @@
}, },
"condition": { "condition": {
"requestDomains": [ "requestDomains": [
"arch.b4k.co" "arch.b4k.co", "desuarchive.org"
], ],
"resourceTypes": [ "resourceTypes": [
"main_frame" "main_frame"
] ]
} }
}] }]

135
chrome/dist/background.js

@ -1,3 +1,4 @@
"use strict";
(() => { (() => {
var __defProp = Object.defineProperty; var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@ -1852,6 +1853,7 @@
var Buffer2; var Buffer2;
var init_esbuild_inject = __esm({ var init_esbuild_inject = __esm({
"esbuild.inject.js"() { "esbuild.inject.js"() {
"use strict";
Buffer2 = require_buffer().Buffer; Buffer2 = require_buffer().Buffer;
} }
}); });
@ -1986,70 +1988,81 @@
input = "https:" + input; input = "https:" + input;
if (init?.body && true) if (init?.body && true)
init.body = await deserialize(init.body); init.body = await deserialize(init.body);
const k = await fetch(input, init); try {
let headersStr = ""; const k = await fetch(input, init);
const headerObj = {}; let headersStr = "";
k.headers.forEach((v, k2) => { const headerObj = {};
headerObj[k2] = v; k.headers.forEach((v, k2) => {
headersStr += `${k2}: ${v} headerObj[k2] = v;
headersStr += `${k2}: ${v}
`; `;
}); });
c.postMessage({ c.postMessage({
id, id,
setRes: true, setRes: true,
ok: k.ok, ok: k.ok,
headers: headerObj, headers: headerObj,
responseHeaders: headersStr, responseHeaders: headersStr,
redirected: k.redirected, redirected: k.redirected,
type: k.type, type: k.type,
url: k.url, url: k.url,
status: k.status, status: k.status,
bodyUsed: k.bodyUsed, bodyUsed: k.bodyUsed,
statusText: k.statusText statusText: k.statusText
}); });
pendingFetches.set(c, { pendingFetches.set(c, {
[id]: { [id]: {
fetchFully: false fetchFully: false
}, },
...pendingFetches.get(c) || {} ...pendingFetches.get(c) || {}
}); });
let buff = []; let buff = [];
const ctotal = +headerObj["content-length"] || 0; const ctotal = +headerObj["content-length"] || 0;
let ltotal = 0; let ltotal = 0;
let s = 0; let s = 0;
const e = { const e = {
write(chunk) { write(chunk) {
ltotal += chunk.byteLength; ltotal += chunk.byteLength;
c.postMessage({ id, progress: [ltotal, ctotal] }); c.postMessage({ id, progress: [ltotal, ctotal] });
if (!pendingFetches.get(c)[id].fetchFully) { if (!pendingFetches.get(c)[id].fetchFully) {
c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]);
} else { } else {
buff.push(Buffer2.from(chunk)); buff.push(Buffer2.from(chunk));
} }
}, },
close() { close() {
if (buff.length > 0) { if (buff.length > 0) {
const chunk = Buffer2.concat(buff); const chunk = Buffer2.concat(buff);
c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]);
buff = []; buff = [];
}
const obj2 = pendingFetches.get(c);
delete obj2[id];
if (Object.keys(obj2).length == 0)
pendingFetches.delete(c);
c.postMessage({ id, s: s++, pushData: {} });
} }
const obj2 = pendingFetches.get(c); };
delete obj2[id]; const reader = k.body?.getReader();
if (Object.keys(obj2).length == 0) let res;
pendingFetches.delete(c); for (; ; ) {
c.postMessage({ id, s: s++, pushData: {} }); res = await reader.read();
} if (res.done)
}; break;
const reader = k.body?.getReader(); e.write(res.value);
let res; }
for (; ; ) { e.close();
res = await reader.read(); reader?.releaseLock();
if (res.done) } catch (e) {
break; const err = e;
e.write(res.value); c.postMessage({
id,
setRes: true,
ok: false,
url: input,
status: err.message
});
} }
e.close();
reader?.releaseLock();
}; };
var meself = new URL(obj.runtime.getURL("")).origin; var meself = new URL(obj.runtime.getURL("")).origin;
var waitConnect = (cb) => { var waitConnect = (cb) => {

4432
chrome/dist/main.js

File diff suppressed because it is too large

2
chrome/manifest.json

@ -2,7 +2,7 @@
"manifest_version": 3, "manifest_version": 3,
"name": "PngExtraEmbedder", "name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!", "description": "Discover embedded files on 4chan and archives!",
"version": "0.245", "version": "0.247",
"icons": { "icons": {
"64": "1449696017588.png" "64": "1449696017588.png"
}, },

135
firefox/dist/background.js

@ -1,3 +1,4 @@
"use strict";
(() => { (() => {
var __defProp = Object.defineProperty; var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@ -1852,6 +1853,7 @@
var Buffer2; var Buffer2;
var init_esbuild_inject = __esm({ var init_esbuild_inject = __esm({
"esbuild.inject.js"() { "esbuild.inject.js"() {
"use strict";
Buffer2 = require_buffer().Buffer; Buffer2 = require_buffer().Buffer;
} }
}); });
@ -1953,70 +1955,81 @@
input = "https:" + input; input = "https:" + input;
if (init?.body && false) if (init?.body && false)
init.body = await deserialize(init.body); init.body = await deserialize(init.body);
const k = await fetch(input, init); try {
let headersStr = ""; const k = await fetch(input, init);
const headerObj = {}; let headersStr = "";
k.headers.forEach((v, k2) => { const headerObj = {};
headerObj[k2] = v; k.headers.forEach((v, k2) => {
headersStr += `${k2}: ${v} headerObj[k2] = v;
headersStr += `${k2}: ${v}
`; `;
}); });
c.postMessage({ c.postMessage({
id, id,
setRes: true, setRes: true,
ok: k.ok, ok: k.ok,
headers: headerObj, headers: headerObj,
responseHeaders: headersStr, responseHeaders: headersStr,
redirected: k.redirected, redirected: k.redirected,
type: k.type, type: k.type,
url: k.url, url: k.url,
status: k.status, status: k.status,
bodyUsed: k.bodyUsed, bodyUsed: k.bodyUsed,
statusText: k.statusText statusText: k.statusText
}); });
pendingFetches.set(c, { pendingFetches.set(c, {
[id]: { [id]: {
fetchFully: false fetchFully: false
}, },
...pendingFetches.get(c) || {} ...pendingFetches.get(c) || {}
}); });
let buff = []; let buff = [];
const ctotal = +headerObj["content-length"] || 0; const ctotal = +headerObj["content-length"] || 0;
let ltotal = 0; let ltotal = 0;
let s = 0; let s = 0;
const e = { const e = {
write(chunk) { write(chunk) {
ltotal += chunk.byteLength; ltotal += chunk.byteLength;
c.postMessage({ id, progress: [ltotal, ctotal] }); c.postMessage({ id, progress: [ltotal, ctotal] });
if (!pendingFetches.get(c)[id].fetchFully) { if (!pendingFetches.get(c)[id].fetchFully) {
c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]);
} else { } else {
buff.push(Buffer2.from(chunk)); buff.push(Buffer2.from(chunk));
} }
}, },
close() { close() {
if (buff.length > 0) { if (buff.length > 0) {
const chunk = Buffer2.concat(buff); const chunk = Buffer2.concat(buff);
c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]); c.postMessage({ id, s: s++, pushData: { data: chunk } }, [chunk.buffer]);
buff = []; buff = [];
}
const obj2 = pendingFetches.get(c);
delete obj2[id];
if (Object.keys(obj2).length == 0)
pendingFetches.delete(c);
c.postMessage({ id, s: s++, pushData: {} });
} }
const obj2 = pendingFetches.get(c); };
delete obj2[id]; const reader = k.body?.getReader();
if (Object.keys(obj2).length == 0) let res;
pendingFetches.delete(c); for (; ; ) {
c.postMessage({ id, s: s++, pushData: {} }); res = await reader.read();
} if (res.done)
}; break;
const reader = k.body?.getReader(); e.write(res.value);
let res; }
for (; ; ) { e.close();
res = await reader.read(); reader?.releaseLock();
if (res.done) } catch (e) {
break; const err = e;
e.write(res.value); c.postMessage({
id,
setRes: true,
ok: false,
url: input,
status: err.message
});
} }
e.close();
reader?.releaseLock();
}; };
var meself = new URL(obj.runtime.getURL("")).origin; var meself = new URL(obj.runtime.getURL("")).origin;
var waitConnect = (cb) => { var waitConnect = (cb) => {

4432
firefox/dist/main.js

File diff suppressed because it is too large

2
firefox/manifest.json

@ -7,7 +7,7 @@
}, },
"name": "PngExtraEmbedder", "name": "PngExtraEmbedder",
"description": "Discover embedded files on 4chan and archives!", "description": "Discover embedded files on 4chan and archives!",
"version": "0.245", "version": "0.247",
"icons": { "icons": {
"64": "1449696017588.png" "64": "1449696017588.png"
}, },

74
main.d.ts

@ -6,6 +6,80 @@ declare module '*.png' {
export default new Uint8Array; export default new Uint8Array;
} }
declare module 'mp4box' {
type BaseTrackInfo = {
id: number,
created: string,
modified: string,
movie_duration: number,
layer: number,
alternate_group: number,
volume: number,
track_width: number,
track_height: number,
timescale: number,
duration: number,
bitrate: number,
codec: string,
language: string,
nb_samples: number
};
type VideoTrackInfo = BaseTrackInfo & {
type: 'video';
movie_duration: number;
video: {
width: number,
height: number
},
};
type AudioTrackInfo = BaseTrackInfo & {
type: 'audio';
audio: {
sample_rate: number,
channel_count: number,
sample_size: number
},
};
type InfoType = {
duration: number,
fragment_duration: number;
timescale: number,
isFragmented: boolean,
isProgressive: boolean,
hasIOD: boolean,
brands: string[],
created: string,
modified: string,
mime?: string;
tracks: (VideoTrackInfo | AudioTrackInfo)[]
};
export function createFile(): {
onError(e: Error): void;
onReady(info: InfoType): void;
appendBuffer(a: ArrayBuffer, end?: boolean): void;
start(): void;
seek(time: number, useRap: boolean): {offset: number};
stop(): void;
flush(): void;
setSegmentOptions(id: number, user?: any, options?: {
nbSamples?: number;
rapAlignement?: boolean;
}): void;
unsetSegmentOptions(id: number): void;
onSegment(id: number, user: any, buffer: ArrayBuffer, sampleNumber: number, last: boolean): void;
initializeSegmentation(): {
id: number;
user: any;
buffer: ArrayBuffer;
}[];
releaseUsedSamples(id: number, lsampleid: number): void;
};
}
declare module 'blockhash' { declare module 'blockhash' {
export const hammingDistance: (a: string, b: string) => number; export const hammingDistance: (a: string, b: string) => number;
export const blockhash: () => void; export const blockhash: () => void;

2
main.meta.js

@ -1,7 +1,7 @@
// ==UserScript== // ==UserScript==
// @name PNGExtraEmbed // @name PNGExtraEmbed
// @namespace https://coom.tech/ // @namespace https://coom.tech/
// @version 0.245 // @version 0.247
// @description uhh // @description uhh
// @author You // @author You
// @match https://boards.4channel.org/* // @match https://boards.4channel.org/*

4393
main.user.js

File diff suppressed because it is too large

36
src/Components/App.svelte

@ -19,6 +19,17 @@
let newbooru: Partial<Omit<Booru, "quirks"> & { view: string }> = {}; let newbooru: Partial<Omit<Booru, "quirks"> & { view: string }> = {};
let dial: Dialog; let dial: Dialog;
export let rev: number;
let news: {
title: string;
content: string;
}[] = [];
const updateNews = async () => {
const res = await fetch("https://shoujo.coom.tech/news");
news = await res.json();
};
function appendBooru() { function appendBooru() {
$settings.rsources = [...$settings.rsources, newbooru as any]; $settings.rsources = [...$settings.rsources, newbooru as any];
@ -93,7 +104,7 @@
{#if visible} {#if visible}
<div class="backpanel" transition:slide> <div class="backpanel" transition:slide>
<div class="content"> <div class="content">
<h1>PEE Settings</h1> <h1>PEE Settings 0.{rev}</h1>
<hr /> <hr />
<Tabs> <Tabs>
<TabList> <TabList>
@ -101,6 +112,7 @@
<Tab>External</Tab> <Tab>External</Tab>
<Tab>File Host</Tab> <Tab>File Host</Tab>
<Tab on:select={() => updateThreads()}>Thread Watcher</Tab> <Tab on:select={() => updateThreads()}>Thread Watcher</Tab>
<Tab on:select={() => updateNews()}>Reminder</Tab>
{#if $appState.akValid} {#if $appState.akValid}
<Tab>Hydrus</Tab> <Tab>Hydrus</Tab>
{/if} {/if}
@ -358,6 +370,23 @@
<HydrusSearch /> <HydrusSearch />
</TabPanel> </TabPanel>
{/if} {/if}
<TabPanel>
<p>
Reminder to report issues to <a
href="https://git.coom.tech/coomdev/PEE">the main repo</a
>
</p>
<div class="newsbox">
{#if news.length == 0}
<p>There are no news yet.</p>
{:else}
{#each news as anew}
<h3>{anew.title}</h3>
<p>{anew.content}</p>
{/each}
{/if}
</div>
</TabPanel>
</Tabs> </Tabs>
</div> </div>
</div> </div>
@ -414,6 +443,11 @@
gap: 10px; gap: 10px;
} }
.newsbox {
max-height: 300px;
overflow-y: scroll;
}
.backpanel { .backpanel {
position: absolute; position: absolute;
right: 32px; right: 32px;

29
src/gif.ts

@ -5,6 +5,7 @@ import { decodeCoom3Payload, uploadFiles } from "./utils";
const netscape = Buffer.from("!\xFF\x0BNETSCAPE2.0", 'ascii'); const netscape = Buffer.from("!\xFF\x0BNETSCAPE2.0", 'ascii');
const magic = Buffer.from("!\xFF\x0B" + "DOOMTECH1.1", 'ascii'); const magic = Buffer.from("!\xFF\x0B" + "DOOMTECH1.1", 'ascii');
const magic2 = Buffer.from("!\xFF\x0B" + "VOOMTECH1.1", 'ascii');
const read_section = (gif: Buffer, pos: number) => { const read_section = (gif: Buffer, pos: number) => {
const begin = pos; const begin = pos;
@ -25,6 +26,17 @@ const read_section = (gif: Buffer, pos: number) => {
}; };
}; };
const password = Buffer.from("NOA");
const xor = (a: Buffer, p: Buffer) => {
let n = 0;
for (let i = 0; i < a.byteLength; ++i) {
a[i] ^= p[n];
n++;
n %= p.byteLength;
}
};
const extractBuff = (gif: Buffer) => { const extractBuff = (gif: Buffer) => {
const field = gif.readUInt8(10); const field = gif.readUInt8(10);
const gcte = !!(field & (1 << 7)); const gcte = !!(field & (1 << 7));
@ -43,9 +55,22 @@ const extractBuff = (gif: Buffer) => {
sec.data.copy(ret, ptr); sec.data.copy(ret, ptr);
ptr += sec.data.byteLength; ptr += sec.data.byteLength;
end = sec.end; end = sec.end;
// v wtf did i mean by this
} while (sec.appname == "DOOMTECH" && gif[end] == '!'.charCodeAt(0)); } while (sec.appname == "DOOMTECH" && gif[end] == '!'.charCodeAt(0));
return decodeCoom3Payload(ret); return decodeCoom3Payload(ret);
} }
if (sec.appname == "VOOMTECH") {
const ret = Buffer.alloc(sec.data.readInt32LE(0));
let ptr = 0;
do {
sec = read_section(gif, sec.end);
sec.data.copy(ret, ptr);
ptr += sec.data.byteLength;
end = sec.end;
} while (sec.appname == "VOOMTECH" && gif[end] == '!'.charCodeAt(0));
xor(ret, password);
return decodeCoom3Payload(ret);
}
end = sec.end; end = sec.end;
} }
throw new Error("Shouldn't happen"); throw new Error("Shouldn't happen");
@ -91,7 +116,7 @@ const inject = async (container: File, links: string[]) => {
const writer = writestream.getWriter(); const writer = writestream.getWriter();
const inj = Buffer.from(links.join(' ')); const inj = Buffer.from(links.join(' '));
xor(inj, password);
const contbuff = Buffer.from(await container.arrayBuffer()); const contbuff = Buffer.from(await container.arrayBuffer());
const field = contbuff.readUInt8(10); const field = contbuff.readUInt8(10);
@ -117,7 +142,7 @@ const has_embed = (gif: Buffer) => {
} }
// skip beeg blocks // skip beeg blocks
while (end < gif.byteLength && gif.readUInt8(end) == '!'.charCodeAt(0)) { while (end < gif.byteLength && gif.readUInt8(end) == '!'.charCodeAt(0)) {
if (magic.compare(gif, end, end + magic.byteLength) != 0) { if ([magic, magic2].every(m => m.compare(gif, end, end + m.byteLength) != 0)) {
end += 3 + gif.readUInt8(end + 2); end += 3 + gif.readUInt8(end + 2);
// eslint-disable-next-line no-constant-condition // eslint-disable-next-line no-constant-condition
while (true) { // skip sub blocks while (true) { // skip sub blocks

2
src/main.ts

@ -536,7 +536,7 @@ const startup = async (is4chanX = true) => {
} }
const appHost = textToElement(`<div class="peee-settings"></div>`); const appHost = textToElement(`<div class="peee-settings"></div>`);
const appInstance = new App({ target: appHost }); const appInstance = new App({ target: appHost, props: {rev: BUILD_VERSION[1]} });
document.body.append(appHost); document.body.append(appHost);
const scrollHost = textToElement(`<div></div>`); const scrollHost = textToElement(`<div></div>`);

41
src/pngv3.ts

@ -3,6 +3,7 @@ import type { EmbeddedFile, ImageProcessor } from "./main";
import { PNGDecoder, PNGEncoder } from "./png"; import { PNGDecoder, PNGEncoder } from "./png";
import { decodeCoom3Payload } from "./utils"; import { decodeCoom3Payload } from "./utils";
import { settings } from "./stores"; import { settings } from "./stores";
import { filehosts } from "./filehosts";
export let csettings: Parameters<typeof settings['set']>[0]; export let csettings: Parameters<typeof settings['set']>[0];
@ -11,6 +12,7 @@ settings.subscribe(b => {
}); });
const CUM3 = Buffer.from("doo\0" + "m"); const CUM3 = Buffer.from("doo\0" + "m");
const CUM4 = Buffer.from("voo\0" + "m"); const CUM4 = Buffer.from("voo\0" + "m");
const CUM5 = Buffer.from("boo\0");
const BufferReadStream = (b: Buffer) => { const BufferReadStream = (b: Buffer) => {
const ret = new ReadableStream<Buffer>({ const ret = new ReadableStream<Buffer>({
@ -33,6 +35,20 @@ const xor = (a: Buffer, p: Buffer) => {
} }
}; };
const prefs: any = {
'files.catbox.moe': 'c',
'a.pomf.cat': 'p',
'take-me-to.space': 't',
'z.zz.fo': 'z'
};
const rprefs: any = {
'c': 'files.catbox.moe',
'p': 'a.pomf.cat',
't': 'take-me-to.space',
'z': 'z.zz.fo',
};
const extract = async (png: Buffer) => { const extract = async (png: Buffer) => {
const reader = BufferReadStream(png).getReader(); const reader = BufferReadStream(png).getReader();
const sneed = new PNGDecoder(reader); const sneed = new PNGDecoder(reader);
@ -55,6 +71,14 @@ const extract = async (png: Buffer) => {
const k = await decodeCoom3Payload(passed); const k = await decodeCoom3Payload(passed);
ret.push(...k.filter(e => e).map(e => e as EmbeddedFile)); ret.push(...k.filter(e => e).map(e => e as EmbeddedFile));
} }
if (buff.slice(4, 4 + CUM5.length).equals(CUM5)) {
const passed = buff.slice(4 + CUM5.length);
const decoded = Buffer.from(passed.toString(), 'base64').toString().split(' ').map(e => {
return `https://${rprefs[e[0]]}/${e.slice(1)}`;
}).join(' ');
const k = await decodeCoom3Payload(Buffer.from(decoded));
ret.push(...k.filter(e => e).map(e => e as EmbeddedFile));
}
break; break;
case 'IDAT': case 'IDAT':
// eslint-disable-next-line no-fallthrough // eslint-disable-next-line no-fallthrough
@ -100,8 +124,8 @@ export const inject_data = async (container: File, injb: Buffer) => {
break; break;
if (!magic && name == "IDAT") { if (!magic && name == "IDAT") {
const passed = Buffer.from(injb); const passed = Buffer.from(injb);
xor(passed, password); //xor(passed, password2);
await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM4, passed])), () => Promise.resolve(0), 0]); await encoder.insertchunk(["tEXt", async () => buildChunk("tEXt", Buffer.concat([CUM5, passed])), () => Promise.resolve(0), 0]);
magic = true; magic = true;
} }
await encoder.insertchunk([name, chunk, crc, offset]); await encoder.insertchunk([name, chunk, crc, offset]);
@ -115,7 +139,16 @@ export const inject_data = async (container: File, injb: Buffer) => {
}; };
const inject = async (container: File, links: string[]) => { const inject = async (container: File, links: string[]) => {
const injb = Buffer.from(links.join(' ')); links = links.map(link => {
for (const h of filehosts) {
if (link.includes(h.serving)) {
const end = link.split('/').slice(-1)[0];
return `${prefs[h.serving]}${end}`;
}
}
return '';
});
const injb = Buffer.from(Buffer.from(links.join(' ')).toString("base64"));
return inject_data(container, injb); return inject_data(container, injb);
}; };
@ -133,6 +166,8 @@ const has_embed = async (png: Buffer) => {
return true; return true;
if (buff.slice(4, 4 + CUM4.length).equals(CUM4)) if (buff.slice(4, 4 + CUM4.length).equals(CUM4))
return true; return true;
if (buff.slice(4, 4 + CUM5.length).equals(CUM5))
return true;
break; break;
case 'IDAT': case 'IDAT':
// eslint-disable-next-line no-fallthrough // eslint-disable-next-line no-fallthrough

15
src/webm.ts

@ -91,7 +91,7 @@ const embed = (webm: Buffer, data: Buffer) => {
type: "8", type: "8",
isEnd: false, isEnd: false,
name: 'TagName', name: 'TagName',
data: Buffer.from('DOOM') data: Buffer.from('VOOM')
}, },
{ {
type: "8", type: "8",
@ -113,19 +113,26 @@ const extract = (webm: Buffer) => {
const dec = new ebml.Decoder(); const dec = new ebml.Decoder();
const chunks = dec.decode(webm); const chunks = dec.decode(webm);
const embed = chunks.findIndex(e => e.name == "TagName" && e.type == '8' && e.value == "DOOM"); const embed = chunks.findIndex(e => e.name == "TagName" && e.type == '8' && (e.value == "DOOM" || e.value == "VOOM"));
const cl = chunks.find(e => e.name == "Cluster"); const cl = chunks.find(e => e.name == "Cluster");
if (cl && embed == -1) if (cl && embed == -1)
return; return;
if (embed == -1) if (embed == -1)
return; return;
const echk = chunks[embed];
const chk = chunks[embed + 1]; const chk = chunks[embed + 1];
if (chk.type == "b" && chk.name == "TagBinary") if (chk.type == "b" && chk.name == "TagBinary") {
if (echk.type == "8" && echk.value == "VOOM") {
xor(chk.data, password);
}
return decodeCoom3Payload(chk.data); return decodeCoom3Payload(chk.data);
}
}; };
const inject = async (container: File, links: string[]): Promise<Buffer> => { const inject = async (container: File, links: string[]): Promise<Buffer> => {
return embed(Buffer.from(await container.arrayBuffer()), Buffer.from(links.join(' '))); const buff = Buffer.from(links.join(' '));
xor(buff, password);
return embed(Buffer.from(await container.arrayBuffer()), buff);
}; };
const has_embed = (webm: Buffer) => { const has_embed = (webm: Buffer) => {

2
src/websites/index.ts

@ -69,7 +69,7 @@ export const X4chan: QueryProcessor = {
export const FoolFuuka: QueryProcessor = { export const FoolFuuka: QueryProcessor = {
getFileThumbnail: post => post.classList.contains('post_is_op') ? post.querySelector('.thread_image_link')! : post.querySelector('.thread_image_box')!, getFileThumbnail: post => post.classList.contains('post_is_op') ? post.querySelector('.thread_image_link')! : post.querySelector('.thread_image_box')!,
getPost: (post) => post.querySelector('.post_wrapper')!, getPost: (post) => post.querySelector('.post_wrapper')!,
postsWithFiles: (h) => [...(h || document).querySelectorAll('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) {

Loading…
Cancel
Save