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.
 
 
 

52 lines
2.1 KiB

import { Buffer } from "buffer";
import { GM_fetch, headerStringToObject } from "./requests";
import thumbnail from "./assets/hasembed.png";
import { EmbeddedFile, EMBED_TYPES } from './main';
/*
header (must be < 2k): [1 byte bitfield](if hasfilename: null terminated string)(if has tags: [X null terminated string, tags are whitespace-separated])
(if has thumbnail: [thumbnail size X]
rest: [X bytes of thumbnail data])[file bytes]
&1 => has filename
&2 => has tags
&4 => has thumbnail
*/
export const decodeCoom3Payload = async (buff: Buffer) : Promise<EmbeddedFile[]> => {
const pees = buff.toString().split('\0');
return Promise.all(pees.map(async pee => {
const res = await GM_fetch(pee, { headers: { ranges: 'bytes=0-2048' } });
const size = +(res.headers.get('content-size') || 0);
const header = Buffer.from(await res.arrayBuffer());
const flags = header[0];
const hasFn = flags & 1;
const hasTags = flags & 2;
const hasThumbnail = flags & 4;
let [ptr, ptr2] = [1, 1];
let fn = 'embedded';
let tags = [];
let thumb: EmbeddedFile['thumbnail'] = Buffer.from(thumbnail);
if (hasFn) {
while (buff[ptr2] != 0)
ptr2++;
fn = header.slice(ptr, ptr2).toString();
ptr = ++ptr2;
}
if (hasTags) {
while (buff[ptr2] != 0)
ptr2++;
tags = header.slice(ptr, ptr2).toString().split(/\s+/);
}
let thumbsize = 0;
if (hasThumbnail) {
thumbsize = header.readInt32LE(ptr);
thumb = Buffer.from(await (await GM_fetch(pee, { headers: { range: `bytes: ${ptr + 4}-${ptr + 4 + thumbsize}` } })).arrayBuffer());
}
return {
embed_type: EMBED_TYPES.MEDIA_EMBED,
filename: fn,
data: async (lsn) =>
Buffer.from(await (await GM_fetch(pee, { headers: { range: `bytes: ${ptr + 4 + thumbsize}-${size-1}` } }, lsn)).arrayBuffer()),
thumbnail: thumb,
} as EmbeddedFile;
}));
};