@vielhuber/wahelper 1.6.5 → 1.6.7
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/package.json +1 -1
- package/wahelper-daemon.js +37 -0
- package/wahelper.js +36 -7
package/package.json
CHANGED
package/wahelper-daemon.js
CHANGED
|
@@ -508,6 +508,35 @@ export default class wahelperDaemon {
|
|
|
508
508
|
}
|
|
509
509
|
}
|
|
510
510
|
|
|
511
|
+
async markChatsRead(updates) {
|
|
512
|
+
// baileys fires chats.update with `unreadCount: 0` when an EXISTING chat
|
|
513
|
+
// is opened on the phone. unlike messages.update (status=4 read receipt),
|
|
514
|
+
// this also covers GROUPS, which usually ship no read receipts — without
|
|
515
|
+
// it their incoming messages would stay `read = 0` forever even after the
|
|
516
|
+
// user has clearly seen them (e.g. reacted with an emoji).
|
|
517
|
+
if (!Array.isArray(updates) || updates.length === 0) {
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
let chats = updates.filter(c => c?.unreadCount === 0);
|
|
521
|
+
if (chats.length === 0) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
while (this.dbLock) {
|
|
525
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
526
|
+
}
|
|
527
|
+
this.dbLock = true;
|
|
528
|
+
try {
|
|
529
|
+
if (this.dbIsOpen === false) {
|
|
530
|
+
this.initDatabase();
|
|
531
|
+
}
|
|
532
|
+
this.applyReadFlags([], chats);
|
|
533
|
+
} catch (error) {
|
|
534
|
+
this.log('⛔ markChatsRead failed: ' + error.message);
|
|
535
|
+
} finally {
|
|
536
|
+
this.dbLock = false;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
511
540
|
async sendMessageToUser(number = null, message = null, attachments = null) {
|
|
512
541
|
if (!this.connected || !this.sock) {
|
|
513
542
|
throw new Error('not_connected');
|
|
@@ -624,6 +653,14 @@ export default class wahelperDaemon {
|
|
|
624
653
|
}
|
|
625
654
|
});
|
|
626
655
|
|
|
656
|
+
this.sock.ev.on('chats.update', async updates => {
|
|
657
|
+
try {
|
|
658
|
+
await this.markChatsRead(updates);
|
|
659
|
+
} catch (error) {
|
|
660
|
+
this.log('⛔ chats.update handler failed: ' + error.message);
|
|
661
|
+
}
|
|
662
|
+
});
|
|
663
|
+
|
|
627
664
|
this.sock.ev.on('creds.update', saveCreds);
|
|
628
665
|
|
|
629
666
|
this.sock.ev.on('connection.update', async update => {
|
package/wahelper.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env -S NODE_NO_WARNINGS=1 node
|
|
2
2
|
|
|
3
3
|
import http from 'http';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import path from 'path';
|
|
4
6
|
import { fileURLToPath } from 'url';
|
|
5
7
|
import { dirname } from 'path';
|
|
6
8
|
import fs from 'fs';
|
|
@@ -206,22 +208,49 @@ export default class wahelper {
|
|
|
206
208
|
async viewMessage(id = null) {
|
|
207
209
|
// lookup directly from database — no connection to daemon needed
|
|
208
210
|
try {
|
|
209
|
-
let
|
|
211
|
+
let row =
|
|
210
212
|
this.db
|
|
211
213
|
.prepare(
|
|
212
214
|
`
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
215
|
+
SELECT id, \`from\`, \`to\`, content, media_data, media_filename, timestamp, \`read\`
|
|
216
|
+
FROM messages
|
|
217
|
+
WHERE id = ?
|
|
218
|
+
LIMIT 1
|
|
219
|
+
`
|
|
218
220
|
)
|
|
219
221
|
.get(id) || null;
|
|
220
|
-
if (
|
|
222
|
+
if (row === null) {
|
|
221
223
|
console.log('Message not found: ' + id);
|
|
222
224
|
this.write({ success: false, message: 'message_not_found', data: null }, true);
|
|
223
225
|
return { content: [{ type: 'text', text: 'Message not found: ' + id }], structuredContent: null };
|
|
224
226
|
}
|
|
227
|
+
// media: write base64 payload to disk and return path — mirrors
|
|
228
|
+
// mailhelper.view_mail so downstream tools (pdfreader, excel, …)
|
|
229
|
+
// can read attachments by file path without a separate decode
|
|
230
|
+
let mediaPath = null;
|
|
231
|
+
if (row.media_data && row.media_filename) {
|
|
232
|
+
let outBase = path.join(os.tmpdir(), 'wahelper-output');
|
|
233
|
+
let slot = crypto
|
|
234
|
+
.createHash('md5')
|
|
235
|
+
.update(this.formatNumber(this.args.device) + '|' + row.id)
|
|
236
|
+
.digest('hex')
|
|
237
|
+
.slice(0, 16);
|
|
238
|
+
let outDir = path.join(outBase, slot);
|
|
239
|
+
fs.mkdirSync(outDir, { recursive: true });
|
|
240
|
+
let safeName = String(row.media_filename).replace(/[^A-Za-z0-9._-]+/g, '_') || 'attachment';
|
|
241
|
+
mediaPath = path.join(outDir, safeName);
|
|
242
|
+
fs.writeFileSync(mediaPath, Buffer.from(row.media_data, 'base64'));
|
|
243
|
+
}
|
|
244
|
+
let message = {
|
|
245
|
+
id: row.id,
|
|
246
|
+
from: row.from,
|
|
247
|
+
to: row.to,
|
|
248
|
+
content: row.content,
|
|
249
|
+
media_filename: row.media_filename,
|
|
250
|
+
media_path: mediaPath,
|
|
251
|
+
timestamp: row.timestamp,
|
|
252
|
+
read: row.read
|
|
253
|
+
};
|
|
225
254
|
console.log('Fetched message ' + id + ' from database.');
|
|
226
255
|
this.write({ success: true, message: 'message_fetched', data: message }, true);
|
|
227
256
|
return {
|