@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.
- package/main/audio-to-opus.js +40 -0
- package/main/index.js +17 -4
- package/main/socket.js +602 -581
- package/main/sqliteAuth.js +82 -78
- package/main/sticker-engine/image-to-webp.js +46 -44
- package/main/sticker-engine/index.js +10 -3
- package/main/sticker-engine/main-sticker.js +83 -77
- package/main/sticker-engine/video-to-webp.js +56 -54
- package/package.json +30 -30
package/main/sqliteAuth.js
CHANGED
|
@@ -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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
45
|
+
const creds = load("creds") || initAuthCreds();
|
|
42
46
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
async function saveCreds() {
|
|
69
|
+
save("creds", creds);
|
|
70
|
+
}
|
|
67
71
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
const set = (category, id, value) => {
|
|
73
|
+
const key = `${category}:${id}`;
|
|
74
|
+
save(key, value);
|
|
75
|
+
};
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
+
const get = (category, id) => {
|
|
78
|
+
const key = `${category}:${id}`;
|
|
79
|
+
return load(key);
|
|
80
|
+
};
|
|
77
81
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
-
|
|
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 {
|
|
6
|
+
import {
|
|
7
|
+
tmpdir
|
|
8
|
+
} from 'os'
|
|
7
9
|
|
|
8
10
|
async function imageToWebp(media) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
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 {
|
|
3
|
-
|
|
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 {
|
|
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 {
|
|
6
|
-
|
|
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 {
|
|
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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
const isVideo = metadata.streams.some(
|
|
29
|
+
(s) => s.codec_type === "video"
|
|
30
|
+
);
|
|
24
31
|
|
|
25
|
-
|
|
32
|
+
resolve(isVideo);
|
|
33
|
+
});
|
|
26
34
|
});
|
|
27
|
-
});
|
|
28
35
|
}
|
|
29
36
|
|
|
30
37
|
async function bufferToTmp(buffer, ext = '.bin') {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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
|
-
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
95
|
-
|
|
90
|
+
return await fs.readFile(buffer)
|
|
91
|
+
}
|
|
96
92
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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 {
|
|
6
|
+
import {
|
|
7
|
+
tmpdir
|
|
8
|
+
} from 'os'
|
|
7
9
|
|
|
8
10
|
async function videoToWebp(media) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
};
|