@ryuu-reinzz/haruka-lib 2.3.0-beta.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,100 +11,104 @@ import Database from "better-sqlite3";
11
11
  * @param {string} dbPath - Lokasi file SQLite (contoh: "./auth.db")
12
12
  */
13
13
  export default async function useSQLiteAuthState(dbPath = "./auth.db", baileys) {
14
- const { proto, BufferJSON, initAuthCreds } = baileys;
15
- const db = new Database(dbPath);
16
- db.pragma("journal_mode = WAL");
14
+ const {
15
+ proto,
16
+ BufferJSON,
17
+ initAuthCreds
18
+ } = baileys;
19
+ const db = new Database(dbPath);
20
+ db.pragma("journal_mode = WAL");
17
21
 
18
- db.prepare(`
22
+ db.prepare(`
19
23
  CREATE TABLE IF NOT EXISTS baileys_state (
20
24
  key TEXT PRIMARY KEY,
21
25
  value BLOB
22
26
  )
23
27
  `).run();
24
28
 
25
- const load = (key) => {
26
- const row = db.prepare("SELECT value FROM baileys_state WHERE key = ?").get(key);
27
- if (!row) return null;
28
- try {
29
- return JSON.parse(row.value.toString(), BufferJSON.reviver);
30
- } catch {
31
- return null;
32
- }
33
- };
29
+ const load = (key) => {
30
+ const row = db.prepare("SELECT value FROM baileys_state WHERE key = ?").get(key);
31
+ if (!row) return null;
32
+ try {
33
+ return JSON.parse(row.value.toString(), BufferJSON.reviver);
34
+ } catch {
35
+ return null;
36
+ }
37
+ };
34
38
 
35
- const save = (key, data) => {
36
- const json = JSON.stringify(data, BufferJSON.replacer);
37
- const buf = Buffer.from(json, "utf8");
38
- db.prepare("REPLACE INTO baileys_state (key, value) VALUES (?, ?)").run(key, buf);
39
- };
39
+ const save = (key, data) => {
40
+ const json = JSON.stringify(data, BufferJSON.replacer);
41
+ const buf = Buffer.from(json, "utf8");
42
+ db.prepare("REPLACE INTO baileys_state (key, value) VALUES (?, ?)").run(key, buf);
43
+ };
40
44
 
41
- const creds = load("creds") || initAuthCreds();
45
+ const creds = load("creds") || initAuthCreds();
42
46
 
43
- const keys = {};
44
- const categories = [
45
- "pre-key",
46
- "session",
47
- "sender-key",
48
- "app-state-sync-key",
49
- "app-state-sync-version"
50
- ];
47
+ const keys = {};
48
+ const categories = [
49
+ "pre-key",
50
+ "session",
51
+ "sender-key",
52
+ "app-state-sync-key",
53
+ "app-state-sync-version"
54
+ ];
51
55
 
52
- for (const category of categories) {
53
- keys[category] = {};
54
- const rows = db
55
- .prepare("SELECT key, value FROM baileys_state WHERE key LIKE ?")
56
- .all(`${category}:%`);
57
- for (const row of rows) {
58
- try {
59
- keys[category][row.key.slice(category.length + 1)] = JSON.parse(row.value.toString());
60
- } catch {}
56
+ for (const category of categories) {
57
+ keys[category] = {};
58
+ const rows = db
59
+ .prepare("SELECT key, value FROM baileys_state WHERE key LIKE ?")
60
+ .all(`${category}:%`);
61
+ for (const row of rows) {
62
+ try {
63
+ keys[category][row.key.slice(category.length + 1)] = JSON.parse(row.value.toString());
64
+ } catch {}
65
+ }
61
66
  }
62
- }
63
67
 
64
- async function saveCreds() {
65
- save("creds", creds);
66
- }
68
+ async function saveCreds() {
69
+ save("creds", creds);
70
+ }
67
71
 
68
- const set = (category, id, value) => {
69
- const key = `${category}:${id}`;
70
- save(key, value);
71
- };
72
+ const set = (category, id, value) => {
73
+ const key = `${category}:${id}`;
74
+ save(key, value);
75
+ };
72
76
 
73
- const get = (category, id) => {
74
- const key = `${category}:${id}`;
75
- return load(key);
76
- };
77
+ const get = (category, id) => {
78
+ const key = `${category}:${id}`;
79
+ return load(key);
80
+ };
77
81
 
78
- const del = (category, id) => {
79
- const key = `${category}:${id}`;
80
- db.prepare("DELETE FROM baileys_state WHERE key = ?").run(key);
81
- };
82
+ const del = (category, id) => {
83
+ const key = `${category}:${id}`;
84
+ db.prepare("DELETE FROM baileys_state WHERE key = ?").run(key);
85
+ };
82
86
 
83
- return {
84
- state: {
85
- creds,
86
- keys: {
87
- get: async (type, ids) => {
88
- const data = {};
89
- for (const id of ids) {
90
- const value = load(`${type}:${id}`);
91
- if (value) data[id] = value;
92
- }
93
- return data;
94
- },
95
- set: async (data) => {
96
- for (const category in data) {
97
- for (const id in data[category]) {
98
- const value = data[category][id];
99
- save(`${category}:${id}`, value);
100
- }
101
- }
102
- }
103
- }
104
- },
105
- saveCreds: async () => save("creds", creds)
87
+ return {
88
+ state: {
89
+ creds,
90
+ keys: {
91
+ get: async (type, ids) => {
92
+ const data = {};
93
+ for (const id of ids) {
94
+ const value = load(`${type}:${id}`);
95
+ if (value) data[id] = value;
96
+ }
97
+ return data;
98
+ },
99
+ set: async (data) => {
100
+ for (const category in data) {
101
+ for (const id in data[category]) {
102
+ const value = data[category][id];
103
+ save(`${category}:${id}`, value);
104
+ }
105
+ }
106
+ }
107
+ }
108
+ },
109
+ saveCreds: async () => save("creds", creds)
106
110
  };
107
111
  setInterval(async () => {
108
- await save("creds", creds);
109
- }, 30_000);
110
- }
112
+ await save("creds", creds);
113
+ }, 30_000);
114
+ }
@@ -3,55 +3,57 @@ import path from 'path'
3
3
  import webp from 'node-webpmux'
4
4
  import ffmpeg from 'fluent-ffmpeg'
5
5
  import Crypto from 'crypto'
6
- import { tmpdir } from 'os'
6
+ import {
7
+ tmpdir
8
+ } from 'os'
7
9
 
8
10
  async function imageToWebp(media) {
9
- const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
10
- const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.jpg`);
11
- fs.writeFile(tmpFileIn, media);
11
+ const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
12
+ const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.jpg`);
13
+ fs.writeFile(tmpFileIn, media);
12
14
 
13
- await new Promise((resolve, reject) => {
14
- ffmpeg(tmpFileIn)
15
- .on('error', reject)
16
- .on('end', () => resolve(true))
17
- .addOutputOptions([
18
- '-vcodec',
19
- 'libwebp',
20
- '-vf',
21
- "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse"
22
- ])
23
- .toFormat('webp')
24
- .save(tmpFileOut);
25
- });
15
+ await new Promise((resolve, reject) => {
16
+ ffmpeg(tmpFileIn)
17
+ .on('error', reject)
18
+ .on('end', () => resolve(true))
19
+ .addOutputOptions([
20
+ '-vcodec',
21
+ 'libwebp',
22
+ '-vf',
23
+ "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse"
24
+ ])
25
+ .toFormat('webp')
26
+ .save(tmpFileOut);
27
+ });
26
28
 
27
- const buff = fs.readFile(tmpFileOut);
28
- fs.unlink(tmpFileOut);
29
- fs.unlink(tmpFileIn);
30
- return buff;
29
+ const buff = fs.readFile(tmpFileOut);
30
+ fs.unlink(tmpFileOut);
31
+ fs.unlink(tmpFileIn);
32
+ return buff;
31
33
  }
32
34
 
33
35
  export async function stickerImg(media, metadata) {
34
- const wMedia = await imageToWebp(media);
35
- const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
36
- const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
37
- fs.writeFile(tmpFileIn, wMedia);
36
+ const wMedia = await imageToWebp(media);
37
+ const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
38
+ const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
39
+ fs.writeFile(tmpFileIn, wMedia);
38
40
 
39
- if (metadata.packname || metadata.author) {
40
- const img = new webp.Image();
41
- const json = {
42
- 'sticker-pack-id': 'https://github.com/DikaArdnt/Hisoka-Morou',
43
- 'sticker-pack-name': metadata.packname,
44
- 'sticker-pack-publisher': metadata.author,
45
- 'emojis': metadata.categories ?? ['']
46
- };
47
- const 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]);
48
- const jsonBuff = Buffer.from(JSON.stringify(json), 'utf-8');
49
- const exif = Buffer.concat([exifAttr, jsonBuff]);
50
- exif.writeUIntLE(jsonBuff.length, 14, 4);
51
- await img.load(tmpFileIn);
52
- fs.unlink(tmpFileIn);
53
- img.exif = exif;
54
- await img.save(tmpFileOut);
55
- return tmpFileOut;
56
- }
57
- }
41
+ if (metadata.packname || metadata.author) {
42
+ const img = new webp.Image();
43
+ const json = {
44
+ 'sticker-pack-id': 'https://github.com/DikaArdnt/Hisoka-Morou',
45
+ 'sticker-pack-name': metadata.packname,
46
+ 'sticker-pack-publisher': metadata.author,
47
+ 'emojis': metadata.categories ?? ['']
48
+ };
49
+ const 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]);
50
+ const jsonBuff = Buffer.from(JSON.stringify(json), 'utf-8');
51
+ const exif = Buffer.concat([exifAttr, jsonBuff]);
52
+ exif.writeUIntLE(jsonBuff.length, 14, 4);
53
+ await img.load(tmpFileIn);
54
+ fs.unlink(tmpFileIn);
55
+ img.exif = exif;
56
+ await img.save(tmpFileOut);
57
+ return tmpFileOut;
58
+ }
59
+ }
@@ -1,6 +1,13 @@
1
1
  import Sticker from './main-sticker.js';
2
- import { stickerVid } from './video-to-webp.js'
3
- import { stickerImg } from './image-to-webp.js'
2
+ import {
3
+ stickerVid
4
+ } from './video-to-webp.js'
5
+ import {
6
+ stickerImg
7
+ } from './image-to-webp.js'
4
8
 
5
9
  export default Sticker;
6
- export { stickerVid, stickerImg };
10
+ export {
11
+ stickerVid,
12
+ stickerImg
13
+ };
@@ -2,103 +2,109 @@ import fs from 'fs-extra';
2
2
  import ffmpeg from "fluent-ffmpeg";
3
3
  import ffmpegPath from "ffmpeg-static";
4
4
  import ffprobePath from "ffprobe-static";
5
- import { stickerVid } from './video-to-webp.js';
6
- import { stickerImg } from './image-to-webp.js';
5
+ import {
6
+ stickerVid
7
+ } from './video-to-webp.js';
8
+ import {
9
+ stickerImg
10
+ } from './image-to-webp.js';
7
11
  import path from 'path';
8
- import { tmpdir } from 'os';
12
+ import {
13
+ tmpdir
14
+ } from 'os';
9
15
  import Crypto from 'crypto';
10
16
 
11
17
  ffmpeg.setFfmpegPath(ffmpegPath);
12
18
  ffmpeg.setFfprobePath(ffprobePath.path);
19
+
13
20
  function isVideo(input) {
14
- return new Promise((resolve) => {
15
- ffmpeg.ffprobe(input, (err, metadata) => {
16
- if (err) {
17
- console.log("ffprobe error:", err);
18
- return resolve(false);
19
- }
21
+ return new Promise((resolve) => {
22
+ ffmpeg.ffprobe(input, (err, metadata) => {
23
+ if (err) {
24
+ console.log("ffprobe error:", err);
25
+ return resolve(false);
26
+ }
20
27
 
21
- const isVideo = metadata.streams.some(
22
- (s) => s.codec_type === "video"
23
- );
28
+ const isVideo = metadata.streams.some(
29
+ (s) => s.codec_type === "video"
30
+ );
24
31
 
25
- resolve(isVideo);
32
+ resolve(isVideo);
33
+ });
26
34
  });
27
- });
28
35
  }
29
36
 
30
37
  async function bufferToTmp(buffer, ext = '.bin') {
31
- const tmp = path.join(
32
- tmpdir(),
33
- Crypto.randomBytes(6).toString('hex') + ext
34
- )
35
- await fs.writeFile(tmp, buffer)
36
- return tmp
38
+ const tmp = path.join(
39
+ tmpdir(),
40
+ Crypto.randomBytes(6).toString('hex') + ext
41
+ )
42
+ await fs.writeFile(tmp, buffer)
43
+ return tmp
37
44
  }
38
45
 
39
46
  class Sticker {
40
- constructor(media, options = {}) {
41
- this.media = media
42
- this.pack = options.pack || 'Made By'
43
- this.author = options.author || 'Unknown'
44
- this.categories = options.categories ?? ['']
45
- }
47
+ constructor(media, options = {}) {
48
+ this.media = media
49
+ this.pack = options.pack || 'Made By'
50
+ this.author = options.author || 'Unknown'
51
+ this.categories = options.categories ?? ['']
52
+ }
46
53
 
47
- async toStickerImg() {
48
- let buff =
49
- Buffer.isBuffer(this.media)
50
- ? this.media
51
- : /^data:.*?\/.*?;base64,/i.test(this.media)
52
- ? Buffer.from(this.media.split(',')[1], 'base64')
53
- : /^https?:\/\//.test(this.media)
54
- ? Buffer.from(await (await fetch(this.media)).arrayBuffer())
55
- : fs.existsSync(this.media)
56
- ? await fs.readFile(this.media)
57
- : Buffer.alloc(0)
58
-
59
- let buffer = await stickerImg(buff, {
60
- packname: this.pack,
61
- author: this.author
62
- });
63
- return await fs.readFile(buffer)
64
- }
54
+ async toStickerImg() {
55
+ let buff =
56
+ Buffer.isBuffer(this.media) ?
57
+ this.media :
58
+ /^data:.*?\/.*?;base64,/i.test(this.media) ?
59
+ Buffer.from(this.media.split(',')[1], 'base64') :
60
+ /^https?:\/\//.test(this.media) ?
61
+ Buffer.from(await (await fetch(this.media)).arrayBuffer()) :
62
+ fs.existsSync(this.media) ?
63
+ await fs.readFile(this.media) :
64
+ Buffer.alloc(0)
65
65
 
66
- async toStickerVid() {
67
- let buff =
68
- Buffer.isBuffer(this.media)
69
- ? this.media
70
- : /^data:.*?\/.*?;base64,/i.test(this.media)
71
- ? Buffer.from(this.media.split(',')[1], 'base64')
72
- : /^https?:\/\//.test(this.media)
73
- ? Buffer.from(await (await fetch(this.media)).arrayBuffer())
74
- : fs.existsSync(this.media)
75
- ? await fs.readFile(this.media)
76
- : Buffer.alloc(0)
77
-
78
- let buffer = await stickerVid(buff, {
79
- packname: this.pack,
80
- author: this.author
81
- });
66
+ let buffer = await stickerImg(buff, {
67
+ packname: this.pack,
68
+ author: this.author
69
+ });
70
+ return await fs.readFile(buffer)
71
+ }
82
72
 
83
- return await fs.readFile(buffer)
84
- }
73
+ async toStickerVid() {
74
+ let buff =
75
+ Buffer.isBuffer(this.media) ?
76
+ this.media :
77
+ /^data:.*?\/.*?;base64,/i.test(this.media) ?
78
+ Buffer.from(this.media.split(',')[1], 'base64') :
79
+ /^https?:\/\//.test(this.media) ?
80
+ Buffer.from(await (await fetch(this.media)).arrayBuffer()) :
81
+ fs.existsSync(this.media) ?
82
+ await fs.readFile(this.media) :
83
+ Buffer.alloc(0)
85
84
 
86
- async build() {
87
- const buff =
88
- Buffer.isBuffer(this.media)
89
- ? this.media
90
- : fs.existsSync(this.media)
91
- ? await fs.readFile(this.media)
92
- : Buffer.alloc(0);
85
+ let buffer = await stickerVid(buff, {
86
+ packname: this.pack,
87
+ author: this.author
88
+ });
93
89
 
94
- const tmpPath = await bufferToTmp(buff);
95
- const thisVideo = await isVideo(tmpPath);
90
+ return await fs.readFile(buffer)
91
+ }
96
92
 
97
- return thisVideo
98
- ? await this.toStickerVid()
99
- : await this.toStickerImg()
100
- }
101
- }
93
+ async build() {
94
+ const buff =
95
+ Buffer.isBuffer(this.media) ?
96
+ this.media :
97
+ fs.existsSync(this.media) ?
98
+ await fs.readFile(this.media) :
99
+ Buffer.alloc(0);
102
100
 
103
- export default Sticker
101
+ const tmpPath = await bufferToTmp(buff);
102
+ const thisVideo = await isVideo(tmpPath);
103
+
104
+ return thisVideo ?
105
+ await this.toStickerVid() :
106
+ await this.toStickerImg()
107
+ }
108
+ }
104
109
 
110
+ export default Sticker
@@ -3,66 +3,68 @@ import path from 'path'
3
3
  import webp from 'node-webpmux'
4
4
  import ffmpeg from 'fluent-ffmpeg'
5
5
  import Crypto from 'crypto'
6
- import { tmpdir } from 'os'
6
+ import {
7
+ tmpdir
8
+ } from 'os'
7
9
 
8
10
  async function videoToWebp(media) {
9
- const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
10
- const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.mp4`);
11
- fs.writeFile(tmpFileIn, media);
11
+ const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
12
+ const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.mp4`);
13
+ fs.writeFile(tmpFileIn, media);
12
14
 
13
- await new Promise((resolve, reject) => {
14
- ffmpeg(tmpFileIn)
15
- .on('error', reject)
16
- .on('end', () => resolve(true))
17
- .addOutputOptions([
18
- '-vcodec',
19
- 'libwebp',
20
- '-vf',
21
- "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse",
22
- '-loop',
23
- '0',
24
- '-ss',
25
- '00:00:00',
26
- '-t',
27
- '00:00:05',
28
- '-preset',
29
- 'default',
30
- '-an',
31
- '-vsync',
32
- '0'
33
- ])
34
- .toFormat('webp')
35
- .save(tmpFileOut);
36
- });
15
+ await new Promise((resolve, reject) => {
16
+ ffmpeg(tmpFileIn)
17
+ .on('error', reject)
18
+ .on('end', () => resolve(true))
19
+ .addOutputOptions([
20
+ '-vcodec',
21
+ 'libwebp',
22
+ '-vf',
23
+ "scale='min(320,iw)':min'(320,ih)':force_original_aspect_ratio=decrease,fps=15, pad=320:320:-1:-1:color=white@0.0, split [a][b]; [a] palettegen=reserve_transparent=on:transparency_color=ffffff [p]; [b][p] paletteuse",
24
+ '-loop',
25
+ '0',
26
+ '-ss',
27
+ '00:00:00',
28
+ '-t',
29
+ '00:00:05',
30
+ '-preset',
31
+ 'default',
32
+ '-an',
33
+ '-vsync',
34
+ '0'
35
+ ])
36
+ .toFormat('webp')
37
+ .save(tmpFileOut);
38
+ });
37
39
 
38
- const buff = fs.readFile(tmpFileOut);
39
- fs.unlink(tmpFileOut);
40
- fs.unlink(tmpFileIn);
41
- return buff;
40
+ const buff = fs.readFile(tmpFileOut);
41
+ fs.unlink(tmpFileOut);
42
+ fs.unlink(tmpFileIn);
43
+ return buff;
42
44
  };
43
45
 
44
46
  export async function stickerVid(media, metadata) {
45
- const wMedia = await videoToWebp(media);
46
- const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
47
- const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
48
- fs.writeFile(tmpFileIn, wMedia);
47
+ const wMedia = await videoToWebp(media);
48
+ const tmpFileIn = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
49
+ const tmpFileOut = path.join(tmpdir(), `${Crypto.randomBytes(6).readUIntLE(0, 6).toString(36)}.webp`);
50
+ fs.writeFile(tmpFileIn, wMedia);
49
51
 
50
- if (metadata.packname || metadata.author) {
51
- const img = new webp.Image();
52
- const json = {
53
- 'sticker-pack-id': 'https://github.com/DikaArdnt/Hisoka-Morou',
54
- 'sticker-pack-name': metadata.packname,
55
- 'sticker-pack-publisher': metadata.author,
56
- 'emojis': metadata.categories ?? ['']
57
- };
58
- const 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]);
59
- const jsonBuff = Buffer.from(JSON.stringify(json), 'utf-8');
60
- const exif = Buffer.concat([exifAttr, jsonBuff]);
61
- exif.writeUIntLE(jsonBuff.length, 14, 4);
62
- await img.load(tmpFileIn);
63
- fs.unlink(tmpFileIn);
64
- img.exif = exif;
65
- await img.save(tmpFileOut);
66
- return tmpFileOut;
67
- }
52
+ if (metadata.packname || metadata.author) {
53
+ const img = new webp.Image();
54
+ const json = {
55
+ 'sticker-pack-id': 'https://github.com/DikaArdnt/Hisoka-Morou',
56
+ 'sticker-pack-name': metadata.packname,
57
+ 'sticker-pack-publisher': metadata.author,
58
+ 'emojis': metadata.categories ?? ['']
59
+ };
60
+ const 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]);
61
+ const jsonBuff = Buffer.from(JSON.stringify(json), 'utf-8');
62
+ const exif = Buffer.concat([exifAttr, jsonBuff]);
63
+ exif.writeUIntLE(jsonBuff.length, 14, 4);
64
+ await img.load(tmpFileIn);
65
+ fs.unlink(tmpFileIn);
66
+ img.exif = exif;
67
+ await img.save(tmpFileOut);
68
+ return tmpFileOut;
69
+ }
68
70
  };