mirror of
https://github.com/cheveguerra/whatsapp-web.js.git
synced 2026-04-17 19:26:20 +00:00
241 lines
8.6 KiB
HTML
241 lines
8.6 KiB
HTML
<!doctype html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta name="generator" content="JSDoc 3.6.7">
|
|
<meta charset="utf-8">
|
|
<title>whatsapp-web.js 1.16.4 » Source: util/Util.js</title>
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Karla:400,400i,700,700i" type="text/css">
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Noto+Serif:400,400i,700,700i" type="text/css">
|
|
<link rel="stylesheet" href="https://brick.a.ssl.fastly.net/Inconsolata:500" type="text/css">
|
|
<link href="css/baseline.css" rel="stylesheet">
|
|
</head>
|
|
|
|
<body onload="prettyPrint()">
|
|
<nav id="jsdoc-navbar" role="navigation" class="jsdoc-navbar">
|
|
<div id="jsdoc-navbar-container">
|
|
<div id="jsdoc-navbar-content">
|
|
<a href="index.html" class="jsdoc-navbar-package-name">whatsapp-web.<wbr>js 1.<wbr>16.<wbr>4</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div id="jsdoc-body-container">
|
|
<div id="jsdoc-content">
|
|
<div id="jsdoc-content-container">
|
|
<div id="jsdoc-banner" role="banner">
|
|
</div>
|
|
<div id="jsdoc-main" role="main">
|
|
<header class="page-header">
|
|
<h1>Source: util/Util.js</h1>
|
|
</header>
|
|
<article>
|
|
<pre class="prettyprint linenums"><code>'use strict';
|
|
|
|
const path = require('path');
|
|
const Crypto = require('crypto');
|
|
const { tmpdir } = require('os');
|
|
const ffmpeg = require('fluent-ffmpeg');
|
|
const webp = require('node-webpmux');
|
|
const fs = require('fs').promises;
|
|
|
|
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
|
|
|
/**
|
|
* Utility methods
|
|
*/
|
|
class Util {
|
|
constructor() {
|
|
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
|
|
}
|
|
|
|
static generateHash(length) {
|
|
var result = '';
|
|
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
var charactersLength = characters.length;
|
|
for (var i = 0; i &lt; length; i++) {
|
|
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Sets default properties on an object that aren't already specified.
|
|
* @param {Object} def Default properties
|
|
* @param {Object} given Object to assign defaults to
|
|
* @returns {Object}
|
|
* @private
|
|
*/
|
|
static mergeDefault(def, given) {
|
|
if (!given) return def;
|
|
for (const key in def) {
|
|
if (!has(given, key) || given[key] === undefined) {
|
|
given[key] = def[key];
|
|
} else if (given[key] === Object(given[key])) {
|
|
given[key] = Util.mergeDefault(def[key], given[key]);
|
|
}
|
|
}
|
|
|
|
return given;
|
|
}
|
|
|
|
/**
|
|
* Formats a image to webp
|
|
* @param {MessageMedia} media
|
|
*
|
|
* @returns {Promise&lt;MessageMedia>} media in webp format
|
|
*/
|
|
static async formatImageToWebpSticker(media, pupPage) {
|
|
if (!media.mimetype.includes('image'))
|
|
throw new Error('media is not a image');
|
|
|
|
if (media.mimetype.includes('webp')) {
|
|
return media;
|
|
}
|
|
|
|
return pupPage.evaluate((media) => {
|
|
return window.WWebJS.toStickerData(media);
|
|
}, media);
|
|
}
|
|
|
|
/**
|
|
* Formats a video to webp
|
|
* @param {MessageMedia} media
|
|
*
|
|
* @returns {Promise&lt;MessageMedia>} media in webp format
|
|
*/
|
|
static async formatVideoToWebpSticker(media) {
|
|
if (!media.mimetype.includes('video'))
|
|
throw new Error('media is not a video');
|
|
|
|
const videoType = media.mimetype.split('/')[1];
|
|
|
|
const tempFile = path.join(
|
|
tmpdir(),
|
|
`${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`
|
|
);
|
|
|
|
const stream = new (require('stream').Readable)();
|
|
const buffer = Buffer.from(
|
|
media.data.replace(`data:${media.mimetype};base64,`, ''),
|
|
'base64'
|
|
);
|
|
stream.push(buffer);
|
|
stream.push(null);
|
|
|
|
await new Promise((resolve, reject) => {
|
|
ffmpeg(stream)
|
|
.inputFormat(videoType)
|
|
.on('error', reject)
|
|
.on('end', () => resolve(true))
|
|
.addOutputOptions([
|
|
'-vcodec',
|
|
'libwebp',
|
|
'-vf',
|
|
// eslint-disable-next-line no-useless-escape
|
|
'scale=\'iw*min(300/iw\,300/ih)\':\'ih*min(300/iw\,300/ih)\',format=rgba,pad=300:300:\'(300-iw)/2\':\'(300-ih)/2\':\'#00000000\',setsar=1,fps=10',
|
|
'-loop',
|
|
'0',
|
|
'-ss',
|
|
'00:00:00.0',
|
|
'-t',
|
|
'00:00:05.0',
|
|
'-preset',
|
|
'default',
|
|
'-an',
|
|
'-vsync',
|
|
'0',
|
|
'-s',
|
|
'512:512',
|
|
])
|
|
.toFormat('webp')
|
|
.save(tempFile);
|
|
});
|
|
|
|
const data = await fs.readFile(tempFile, 'base64');
|
|
await fs.unlink(tempFile);
|
|
|
|
return {
|
|
mimetype: 'image/webp',
|
|
data: data,
|
|
filename: media.filename,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Sticker metadata.
|
|
* @typedef {Object} StickerMetadata
|
|
* @property {string} [name]
|
|
* @property {string} [author]
|
|
* @property {string[]} [categories]
|
|
*/
|
|
|
|
/**
|
|
* Formats a media to webp
|
|
* @param {MessageMedia} media
|
|
* @param {StickerMetadata} metadata
|
|
*
|
|
* @returns {Promise&lt;MessageMedia>} media in webp format
|
|
*/
|
|
static async formatToWebpSticker(media, metadata, pupPage) {
|
|
let webpMedia;
|
|
|
|
if (media.mimetype.includes('image'))
|
|
webpMedia = await this.formatImageToWebpSticker(media, pupPage);
|
|
else if (media.mimetype.includes('video'))
|
|
webpMedia = await this.formatVideoToWebpSticker(media);
|
|
else
|
|
throw new Error('Invalid media format');
|
|
|
|
if (metadata.name || metadata.author) {
|
|
const img = new webp.Image();
|
|
const hash = this.generateHash(32);
|
|
const stickerPackId = hash;
|
|
const packname = metadata.name;
|
|
const author = metadata.author;
|
|
const categories = metadata.categories || [''];
|
|
const json = { 'sticker-pack-id': stickerPackId, 'sticker-pack-name': packname, 'sticker-pack-publisher': author, 'emojis': categories };
|
|
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.load(Buffer.from(webpMedia.data, 'base64'));
|
|
img.exif = exif;
|
|
webpMedia.data = (await img.save(null)).toString('base64');
|
|
}
|
|
|
|
return webpMedia;
|
|
}
|
|
|
|
/**
|
|
* Configure ffmpeg path
|
|
* @param {string} path
|
|
*/
|
|
static setFfmpegPath(path) {
|
|
ffmpeg.setFfmpegPath(path);
|
|
}
|
|
}
|
|
|
|
module.exports = Util;
|
|
</code></pre>
|
|
</article>
|
|
</div>
|
|
</div>
|
|
<nav id="jsdoc-toc-nav" role="navigation"></nav>
|
|
</div>
|
|
</div>
|
|
<footer id="jsdoc-footer" class="jsdoc-footer">
|
|
<div id="jsdoc-footer-container">
|
|
<p>
|
|
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc</a> 3.6.7 on March 9, 2022.
|
|
</p>
|
|
</div>
|
|
</footer>
|
|
<script src="scripts/jquery.min.js"></script>
|
|
<script src="scripts/tree.jquery.js"></script>
|
|
<script src="scripts/prettify.js"></script>
|
|
<script src="scripts/jsdoc-toc.js"></script>
|
|
<script src="scripts/linenumber.js"></script>
|
|
<script src="scripts/scrollanchor.js"></script>
|
|
</body>
|
|
|
|
</html> |