Can embed any file in a PNG/WebM/GIF/JPEG and upload it to a third-party host through 4chan
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

93 lines
2.5 KiB

import type { ImageProcessor, WorkerEmbeddedFile } from './processor.worker';
import { Buffer } from "buffer";
import thumbnail from "./assets/hasembed.png";
import { settings } from "./stores";
import { getHeaders, ifetch, Platform } from "./platform";
const sources = [
{ host: 'Catbox', prefix: 'files.catbox.moe/' },
{ host: 'Litter', prefix: 'litter.catbox.moe/' },
{ host: 'Zzzz', prefix: 'z.zz.fo/' }
];
export let csettings: Parameters<typeof settings['set']>[0];
settings.subscribe(b => {
csettings = b;
});
const getExt = (fn: string) => {
// const isDum = fn!.match(/^[a-z0-9]{6}\./i);
const isB64 = fn!.match(/^((?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=))?\.(gif|jpe?g|png|webm)/);
const isExt = fn!.match(/\[.*=(.*)\]/);
let ext;
let source: string | undefined;
try {
if (isB64) {
ext = atob(isB64[1]);
} else if (isExt) {
ext = decodeURIComponent(isExt[1]);
if (ext.startsWith('https://'))
ext = ext.slice('https://'.length);
for (const cs of sources)
if (ext.startsWith(cs.prefix)) {
source = cs.prefix;
ext = ext.slice(cs.prefix.length);
break;
}
}
} catch {
/**/
}
return { ext, source };
};
const extract = async (b: Buffer, fn?: string) => {
if (!csettings)
throw new Error("Settings uninit");
const { ext, source } = getExt(fn!);
let rsource: string;
for (const cs of sources) {
if (source && cs.prefix != source)
continue;
try {
await getHeaders('https://' + cs.prefix + ext);
rsource = 'https://' + cs.prefix + ext;
break;
} catch {
// 404
}
}
return [{
filename: ext,
data: csettings.hotlink ? rsource! : { url: rsource! },
thumbnail: Buffer.from(thumbnail)
} as WorkerEmbeddedFile];
};
const has_embed = async (b: Buffer, fn?: string) => {
const { ext, source } = getExt(fn!);
if (!ext)
return false;
for (const cs of sources) {
if (source && cs.prefix != source)
continue;
try {
const e = await getHeaders('https://' + cs.prefix + ext);
return true;
} catch {
// 404
}
}
return false;
};
export default {
skip: true,
extract,
has_embed,
match: fn => !!getExt(fn)
} as ImageProcessor;