akiraa-scrape
Version:
Module & tools for bot whatsApp
250 lines (240 loc) • 6.43 kB
JavaScript
const fs = require("fs");
const path = require("path");
const crypto = require("crypto");
const fetch = require("node-fetch");
const { ffmpeg } = require("./converter");
const { spawn } = require("child_process");
const uploadFile = require("./uploadFile");
const { fromBuffer } = require("file-type");
const uploadImage = require("./uploadImage");
const tmp = path.join(__dirname, "../tmp");
/**
* Image to Sticker
* @param {Buffer} img Image Buffer
* @param {String} url Image URL
*/
function sticker2(img, url) {
return new Promise(async (resolve, reject) => {
try {
if (url) {
let res = await fetch(url);
if (res.status !== 200) throw await res.text();
img = await res.buffer();
}
let inp = path.join(tmp, +new Date() + ".jpeg");
await fs.promises.writeFile(inp, img);
let ff = spawn("ffmpeg", [
"-y",
"-i",
inp,
"-vf",
"scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1",
"-f",
"png",
"-",
]);
ff.on("error", reject);
ff.on("close", async () => {
await fs.promises.unlink(inp);
});
let bufs = [];
const [_spawnprocess, ..._spawnargs] = [
...(module.exports.support.gm
? ["gm"]
: module.exports.magick
? ["magick"]
: []),
"convert",
"png:-",
"webp:-",
];
let im = spawn(_spawnprocess, _spawnargs);
im.on("error", (e) => conn.reply(m.chat, util.format(e), m));
im.stdout.on("data", (chunk) => bufs.push(chunk));
ff.stdout.pipe(im.stdin);
im.on("exit", () => {
resolve(Buffer.concat(bufs));
});
} catch (e) {
reject(e);
}
});
}
async function canvas(code, type = "png", quality = 0.92) {
let res = await fetch(
"https://nurutomo.herokuapp.com/api/canvas?" +
queryURL({
type,
quality,
}),
{
method: "POST",
headers: {
"Content-Type": "text/plain",
"Content-Length": code.length,
},
body: code,
},
);
let image = await res.buffer();
return image;
}
function queryURL(queries) {
return new URLSearchParams(Object.entries(queries));
}
/**
* Image to Sticker
* @param {Buffer} img Image Buffer
* @param {String} url Image URL
*/
async function sticker1(img, url) {
url = url ? url : await uploadImage(img);
let { mime } = url ? { mime: "image/jpeg" } : await fromBuffer(img);
let sc = `let im = await loadImg('data:${mime};base64,'+(await window.loadToDataURI('${url}')))
c.width = c.height = 512
let max = Math.max(im.width, im.height)
let w = 512 * im.width / max
let h = 512 * im.height / max
ctx.drawImage(im, 256 - w / 2, 256 - h / 2, w, h)
`;
return await canvas(sc, "webp");
}
/**
* Image/Video to Sticker
* @param {Buffer} img Image/Video Buffer
* @param {String} url Image/Video URL
* @param {String} packname EXIF Packname
* @param {String} author EXIF Author
*/
async function sticker3(img, url, packname, author) {
url = url ? url : await uploadFile(img);
let res = await fetch(
"https://api.xteam.xyz/sticker/wm?" +
new URLSearchParams(
Object.entries({
url,
packname,
author,
}),
),
);
return await res.buffer();
}
/**
* Image to Sticker
* @param {Buffer} img Image/Video Buffer
* @param {String} url Image/Video URL
*/
async function sticker4(img, url) {
if (url) {
let res = await fetch(url);
if (res.status !== 200) throw await res.text();
img = await res.buffer();
}
return await ffmpeg(
img,
[
"-vf",
"scale=512:512:flags=lanczos:force_original_aspect_ratio=decrease,format=rgba,pad=512:512:(ow-iw)/2:(oh-ih)/2:color=#00000000,setsar=1",
],
"jpeg",
"webp",
);
}
async function sticker5(img, url, packname, author, categories = [""]) {
const WSF = require("wa-sticker-formatter");
const stickerMetadata = {
type: "full",
pack: packname,
author,
categories,
};
return await new WSF.Sticker(img ? img : url, stickerMetadata).build();
}
/**
* Add WhatsApp JSON Exif Metadata
* Taken from https://github.com/pedroslopez/whatsapp-web.js/pull/527/files
* @param {Buffer} webpSticker
* @param {String} packname
* @param {String} author
* @param {String} categories
* @param {Object} extra
* @returns
*/
async function addExif(
webpSticker,
packname,
author,
categories = [""],
extra = {},
) {
const webp = require("node-webpmux"); // Optional Feature
const img = new webp.Image();
const stickerPackId = crypto.randomBytes(32).toString("hex");
const json = {
"sticker-pack-id": stickerPackId,
"sticker-pack-name": packname,
"sticker-pack-publisher": author,
emojis: categories,
...extra,
};
let exifAttr = Buffer.from([
0x49, 0x49, 0x2a, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x41, 0x57,
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
]);
let jsonBuffer = Buffer.from(JSON.stringify(json), "utf8");
let exif = Buffer.concat([exifAttr, jsonBuffer]);
exif.writeUIntLE(jsonBuffer.length, 14, 4);
await img.loadBuffer(webpSticker);
img.exif = exif;
return await img.saveBuffer();
}
module.exports = {
/**
* Image/Video to Sticker
* @param {Buffer} img Image/Video Buffer
* @param {String} url Image/Video URL
* @param {...String}
*/
async sticker(img, url, ...args) {
let lastError;
for (let func of [
sticker3, // sticker5,
this.support.ffmpeg && this.support.ffmpegWebp && sticker4,
this.support.ffmpeg &&
(this.support.convert || this.support.magick || this.support.gm) &&
sticker2,
sticker1,
].filter((f) => f)) {
try {
let stiker = await func(img, url, ...args);
if (stiker.includes("RIFF")) {
try {
return await addExif(stiker, ...args);
} catch (e) {
return stiker;
}
}
throw stiker.toString();
} catch (err) {
lastError = err;
}
}
return lastError;
},
sticker1,
sticker2,
sticker3,
sticker4,
sticker5,
addExif,
support: {
ffmpeg: true,
ffprobe: true,
ffmpegWebp: true,
convert: true,
magick: false,
gm: false,
find: false,
},
};