Browse Source

Use Extension API to save settings

pull/46/head
coomdev 2 years ago
parent
commit
bcce361c49
  1. 2
      README.md
  2. 1
      build-chrome.js
  3. 578
      chrome/dist/main.js
  4. 6
      chrome/manifest.json
  5. 578
      dist/main.js
  6. 578
      firefox/dist/main.js
  7. 2
      firefox/manifest.json
  8. 2
      firefox_update.json
  9. 2
      main.meta.js
  10. 580
      main.user.js
  11. BIN
      pngextraembedder-0.275.xpi
  12. 8
      src/jpg.ts
  13. 25
      src/main.ts
  14. 2
      src/pomf.ts
  15. 43
      src/stores.ts
  16. 11
      src/thirdeye.ts
  17. 6
      src/utils.ts

2
README.md

@ -25,7 +25,7 @@ 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 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.273.xpi) or [Chrome-based](https://chrome.google.com/webstore/detail/pngextraembedder/bfhpobiikighljcapcfmfganodihbicj)) - 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.275.xpi) or [Chrome-based](https://chrome.google.com/webstore/detail/pngextraembedder/bfhpobiikighljcapcfmfganodihbicj))
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.

1
build-chrome.js

@ -44,6 +44,7 @@ const manif3 = {
64: "1449696017588.png" 64: "1449696017588.png"
}, },
permissions: [ permissions: [
"storage"
], ],
"host_permissions":["<all_urls>"], "host_permissions":["<all_urls>"],
web_accessible_resources: [{ web_accessible_resources: [{

578
chrome/dist/main.js

File diff suppressed because it is too large

6
chrome/manifest.json

@ -2,11 +2,13 @@
"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.273", "version": "0.275",
"icons": { "icons": {
"64": "1449696017588.png" "64": "1449696017588.png"
}, },
"permissions": [], "permissions": [
"storage"
],
"host_permissions": [ "host_permissions": [
"<all_urls>" "<all_urls>"
], ],

578
dist/main.js

File diff suppressed because it is too large

578
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.273", "version": "0.275",
"icons": { "icons": {
"64": "1449696017588.png" "64": "1449696017588.png"
}, },

2
firefox_update.json

@ -1 +1 @@
{"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.273","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.273.xpi"}]}}} {"addons":{"{34ac4994-07f2-44d2-8599-682516a6c6a6}":{"updates":[{"version":"0.275","update_link":"https://git.coom.tech/fuckjannies/lolipiss/raw/branch/%E4%B8%AD%E5%87%BA%E3%81%97/pngextraembedder-0.275.xpi"}]}}}

2
main.meta.js

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

580
main.user.js

File diff suppressed because it is too large

BIN
pngextraembedder-0.275.xpi

Binary file not shown.

8
src/jpg.ts

@ -1,15 +1,9 @@
import { Buffer } from "buffer"; import { Buffer } from "buffer";
import type { ImageProcessor } from "./main"; import type { ImageProcessor } from "./main";
import {f5stego} from './f5stego'; import { f5stego } from './f5stego';
import { settings } from "./stores"; import { settings } from "./stores";
import { decodeCoom3Payload } from "./utils"; import { decodeCoom3Payload } from "./utils";
export let csettings: Parameters<typeof settings['set']>[0];
settings.subscribe(b => {
csettings = b;
});
const key = Buffer.from("CUNNYCUNNYCUNNY"); const key = Buffer.from("CUNNYCUNNYCUNNY");
const f5inst = new f5stego(key); const f5inst = new f5stego(key);

25
src/main.ts

@ -38,12 +38,13 @@ export interface ImageProcessor {
} }
let qp: QueryProcessor; let qp: QueryProcessor;
export let csettings: Parameters<typeof settings['set']>[0] = initial_settings; export let csettings: Parameters<typeof settings['set']>[0];
let processors: ImageProcessor[] = let processors: ImageProcessor[] =
[thirdeye, pomf, pngv3, jpg, webm, gif]; [thirdeye, pomf, pngv3, jpg, webm, gif];
let cappState: Parameters<typeof appState['set']>[0]; let cappState: Parameters<typeof appState['set']>[0];
settings.subscribe(async b => { settings.subscribe(async b => {
if (!b) return;
if (b.hyd) { if (b.hyd) {
// transition from disable to enabled // transition from disable to enabled
if (b.ak) { if (b.ak) {
@ -164,6 +165,8 @@ let pendingPosts: { id: number, op: number }[] = [];
// should be equivalent to buildCumFun(signalNewEmbeds, 5000, {trailing: true}) // should be equivalent to buildCumFun(signalNewEmbeds, 5000, {trailing: true})
const signalNewEmbeds = debounce(async () => { const signalNewEmbeds = debounce(async () => {
// ensure user explicitely enabled telemetry // ensure user explicitely enabled telemetry
if (!csettings)
return;
if (!csettings.tm) if (!csettings.tm)
return; return;
try { try {
@ -190,6 +193,8 @@ const signalNewEmbeds = debounce(async () => {
const shouldUseCache = () => { const shouldUseCache = () => {
if (cappState.isCatalog) if (cappState.isCatalog)
return false; return false;
if (!csettings)
return false;
return typeof csettings.cache == "boolean" return typeof csettings.cache == "boolean"
? csettings.cache ? csettings.cache
: location.hostname.includes('b4k'); : location.hostname.includes('b4k');
@ -205,6 +210,8 @@ const processPost = async (post: HTMLDivElement) => {
let res2: [EmbeddedFile[], boolean][] | undefined = undefined; let res2: [EmbeddedFile[], boolean][] | undefined = undefined;
const reportEmbed = () => { const reportEmbed = () => {
if (!csettings)
return false;
if (csettings.tm) { if (csettings.tm) {
// dont report results from archive, only live threads // dont report results from archive, only live threads
if (['boards.4chan.org', 'boards.4channel.org'].includes(location.host)) { if (['boards.4chan.org', 'boards.4channel.org'].includes(location.host)) {
@ -261,6 +268,8 @@ function copyTextToClipboard(text: string) {
} }
const scrapeBoard = async (self: HTMLButtonElement) => { const scrapeBoard = async (self: HTMLButtonElement) => {
if (!csettings)
return false;
if (csettings.tm) { if (csettings.tm) {
fireNotification("success", "Scrapping board with telemetry on! Thank you for your service, selfless stranger ;_;7"); fireNotification("success", "Scrapping board with telemetry on! Thank you for your service, selfless stranger ;_;7");
} }
@ -451,6 +460,16 @@ const startup = async (is4chanX = true) => {
else else
qp = lqp; qp = lqp;
await new Promise<void>(_ => {
settings.subscribe(val => {
if (val)
_();
});
});
if (!csettings)
return false;
if (csettings.vercheck) if (csettings.vercheck)
versionCheck(); versionCheck();
@ -513,6 +532,8 @@ const startup = async (is4chanX = true) => {
rec.addedNodes.forEach(e => { rec.addedNodes.forEach(e => {
if (!(e instanceof HTMLElement)) if (!(e instanceof HTMLElement))
return; return;
if (!csettings)
return false;
if (cappState.isCatalog && csettings.notcata) if (cappState.isCatalog && csettings.notcata)
return; return;
// apparently querySelector cannot select the root element if it matches // apparently querySelector cannot select the root element if it matches
@ -528,7 +549,7 @@ const startup = async (is4chanX = true) => {
mo.observe(e!, { childList: true, subtree: true }); mo.observe(e!, { childList: true, subtree: true });
}); });
} }
if (!document.body) { if (!document.body) {
let bodyRes: any; let bodyRes: any;
const bodyInit = new Promise(r => bodyRes = r); const bodyInit = new Promise(r => bodyRes = r);

2
src/pomf.ts

@ -42,6 +42,8 @@ const getExt = (fn: string) => {
}; };
const extract = async (b: Buffer, fn?: string) => { const extract = async (b: Buffer, fn?: string) => {
if (!csettings)
throw new Error("Settings uninit");
const { ext, source } = getExt(fn!); const { ext, source } = getExt(fn!);
let rsource: string; let rsource: string;

43
src/stores.ts

@ -2,18 +2,40 @@ import { writable } from "svelte/store";
import type { HydrusClient } from "./hydrus"; import type { HydrusClient } from "./hydrus";
import type { Booru } from "./thirdeye"; import type { Booru } from "./thirdeye";
export const localLoad = <T>(key: string, def: T) => // Todo: use GM get/setValue instead?
('__pee__' + key) in localStorage export const localLoad = async <T>(key: string, def: T) => {
? JSON.parse(localStorage.getItem('__pee__' + key)!) as T const isinls = ('__pee__' + key) in localStorage;
const ret = isinls
? { ...def, ...JSON.parse(localStorage.getItem('__pee__' + key)!) } as T
: def; : def;
const localSet = (key: string, value: any) => if (execution_mode != "userscript") {
localStorage.setItem('__pee__' + key, JSON.stringify(value)); if (isinls) {
delete localStorage[('__pee__' + key)];
await chrome.storage.local.set({
[key]: JSON.stringify(ret)
});
} else {
const d = await chrome.storage.local.get([key]);
if (typeof d[key] == "string")
return { ...def, ...(await JSON.parse('' + d[key] || '{}')) } as T;
}
}
return ret;
};
const localSet = (key: string, value: any) => {
if (execution_mode != "userscript")
chrome.storage.local.set({ [key]: JSON.stringify(value) });
else
localStorage.setItem('__pee__' + key, JSON.stringify(value));
};
export const initial_settings = localLoad('settingsv2', { export const initial_settings = localLoad('settingsv2', {
...localLoad('settings', {}),
loop: true, loop: true,
dh: false, dh: false,
pmeth: 4,
xpv: false, xpv: false,
xpi: false, xpi: false,
hyd: false, hyd: false,
@ -42,11 +64,14 @@ export const initial_settings = localLoad('settingsv2', {
conc: 8, conc: 8,
ho: false, ho: false,
blacklist: [] as string[], blacklist: [] as string[],
rsources: [] as (Omit<Booru, 'quirks'> & {view: string, disabled?: boolean})[], rsources: [] as (Omit<Booru, 'quirks'> & { view: string, disabled?: boolean })[],
...localLoad('settingsv2', {}),
}); });
export const settings = writable(initial_settings); export const settings = writable<Awaited<typeof initial_settings>>();
initial_settings.then(v => {
settings.set(v);
});
export const appState = writable({ export const appState = writable({
isCatalog: false, isCatalog: false,

11
src/thirdeye.ts

@ -60,6 +60,8 @@ let black = new Set<string>();
let phashEn = false; let phashEn = false;
let mindist = 5; let mindist = 5;
settings.subscribe(s => { settings.subscribe(s => {
if (!s)
return;
experimentalApi = s.expte; experimentalApi = s.expte;
boorus = s.rsources.map(e => ({ boorus = s.rsources.map(e => ({
...e, ...e,
@ -70,12 +72,7 @@ settings.subscribe(s => {
phashEn = s.phash; phashEn = s.phash;
}); });
export let boorus: Booru[] = export let boorus: Booru[] = [];
localLoad('settingsv2', { rsources: [] as (Omit<Booru, 'quirks'> & { view: string, disabled?: boolean })[] })
.rsources.map(e => ({
...e,
quirks: gelquirk(e.view)
}));
const bufferingTime = 2000; const bufferingTime = 2000;
let expired: number | NodeJS.Timeout | undefined = undefined; let expired: number | NodeJS.Timeout | undefined = undefined;
@ -151,6 +148,8 @@ const findFileFrom = async (b: Booru, hex: string, abort?: EventTarget) => {
}; };
const extract = async (b: Buffer, fn?: string) => { const extract = async (b: Buffer, fn?: string) => {
if (!csettings)
throw new Error("Settings uninit");
let result!: BooruMatch[]; let result!: BooruMatch[];
let booru!: string; let booru!: string;
for (const e of Object.values(boorus)) { for (const e of Object.values(boorus)) {

6
src/utils.ts

@ -168,6 +168,8 @@ export const getThreadDataCache = async (board: string, op: number) => {
Semantic difference: Empty array means there is nothing, undefined means it wasn't found in the cache Semantic difference: Empty array means there is nothing, undefined means it wasn't found in the cache
*/ */
export const getEmbedsFromCache = async (board: string, op: number, pid: string): Promise<[EmbeddedFile[], boolean][] | undefined> => { export const getEmbedsFromCache = async (board: string, op: number, pid: string): Promise<[EmbeddedFile[], boolean][] | undefined> => {
if (!csettings)
throw new Error("Settings uninit");
await getThreadDataCache(board, op); await getThreadDataCache(board, op);
const target = +pid.slice(pid.match(/\d/)!.index); const target = +pid.slice(pid.match(/\d/)!.index);
const cachedData = cthreadDataCache![target]; const cachedData = cthreadDataCache![target];
@ -217,6 +219,8 @@ rest: [X bytes of thumbnail data])[file bytes]
&4 => has thumbnail &4 => has thumbnail
*/ */
export const decodeCoom3Payload = async (buff: Buffer) => { export const decodeCoom3Payload = async (buff: Buffer) => {
if (!csettings)
throw new Error("Settings uninit");
const allowed_domains = filehosts.map(e => e.serving.replaceAll('.', '\\.')); const allowed_domains = filehosts.map(e => e.serving.replaceAll('.', '\\.'));
const pees = buff const pees = buff
.toString() .toString()
@ -313,6 +317,8 @@ export const uploadFiles = async (injs: File[]) => {
let total = 0; let total = 0;
fireNotification('info', `Uploading ${injs.length} files...`); fireNotification('info', `Uploading ${injs.length} files...`);
return await Promise.all(injs.map(async inj => { return await Promise.all(injs.map(async inj => {
if (!csettings)
throw new Error("Settings uninit");
const peefile = await buildPeeFile(inj); const peefile = await buildPeeFile(inj);
const ret = await filehosts[csettings.fhost || 0].uploadFile(peefile); const ret = await filehosts[csettings.fhost || 0].uploadFile(peefile);
fireNotification('info', `Uploaded files [${++total}/${injs.length}] ${ret}`); fireNotification('info', `Uploaded files [${++total}/${injs.length}] ${ret}`);

Loading…
Cancel
Save