@vielhuber/wahelper 1.3.6 → 1.3.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/README.MD +26 -27
- package/package.json +6 -7
- package/{WhatsApp.js → wahelper.js} +81 -159
package/README.MD
CHANGED
|
@@ -37,6 +37,9 @@ npx wahelper \
|
|
|
37
37
|
--device "xxxxxxxxxxxx" \
|
|
38
38
|
...
|
|
39
39
|
|
|
40
|
+
--action "fetch_messages" \
|
|
41
|
+
--limit 42
|
|
42
|
+
|
|
40
43
|
--action "send_user" \
|
|
41
44
|
--number "xxxxxxxxxxxx" \
|
|
42
45
|
--message "This is a test! 🚀"
|
|
@@ -48,7 +51,7 @@ npx wahelper \
|
|
|
48
51
|
--action "send_user" \
|
|
49
52
|
--number "xxxxxxxxxxxx" \
|
|
50
53
|
--message "This is a test! 🚀" \
|
|
51
|
-
--attachments
|
|
54
|
+
--attachments "/full/path/to/file.pdf,/full/path/to/image.png"
|
|
52
55
|
|
|
53
56
|
sqlite3 \
|
|
54
57
|
-header \
|
|
@@ -62,45 +65,41 @@ sqlite3 \
|
|
|
62
65
|
|
|
63
66
|
```php
|
|
64
67
|
require_once __DIR__ . '/vendor/autoload.php';
|
|
65
|
-
use vielhuber\wahelper\
|
|
68
|
+
use vielhuber\wahelper\wahelper;
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
WhatsApp::run([
|
|
69
|
-
'device' => 'xxxxxxxxxxxx',
|
|
70
|
-
'action' => 'fetch_messages'
|
|
71
|
-
]);
|
|
70
|
+
$wahelper = new wahelper();
|
|
72
71
|
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'
|
|
72
|
+
// fetch messages
|
|
73
|
+
$wahelper->fetchMessages(
|
|
74
|
+
device: 'xxxxxxxxxxxx',
|
|
75
|
+
limit: 42
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// send message to user
|
|
79
|
+
$wahelper->sendUser(
|
|
80
|
+
device: 'xxxxxxxxxxxx',
|
|
81
|
+
number: 'xxxxxxxxxxxx',
|
|
82
|
+
message => 'This is a test! 🚀',
|
|
83
|
+
attachments: ['/full/path/to/file.pdf', '/full/path/to/image.png']
|
|
85
84
|
]);
|
|
86
85
|
|
|
87
|
-
// send
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
'
|
|
91
|
-
|
|
92
|
-
|
|
86
|
+
// send message to group
|
|
87
|
+
$wahelper->sendGroup(
|
|
88
|
+
device: 'xxxxxxxxxxxx',
|
|
89
|
+
name: 'Group name',
|
|
90
|
+
message: 'This is a test! 🚀',
|
|
91
|
+
attachments: ['/full/path/to/file.pdf', '/full/path/to/image.png']
|
|
93
92
|
]);
|
|
94
93
|
```
|
|
95
94
|
|
|
96
95
|
### mcp
|
|
97
96
|
|
|
98
|
-
```
|
|
97
|
+
```json
|
|
99
98
|
{
|
|
100
99
|
"mcpServers": {
|
|
101
100
|
"whatsapp": {
|
|
102
101
|
"command": "/root/.nvm/versions/node/v22.20.0/bin/node",
|
|
103
|
-
"args": ["/var/www/project/node_modules/@vielhuber/wahelper/
|
|
102
|
+
"args": ["/var/www/project/node_modules/@vielhuber/wahelper/mcp.js"]
|
|
104
103
|
}
|
|
105
104
|
}
|
|
106
105
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vielhuber/wahelper",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.7",
|
|
4
4
|
"description": "Lightweight whatsapp integration layer.",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "wahelper.js",
|
|
6
6
|
"files": [
|
|
7
|
-
"
|
|
7
|
+
"wahelper.js"
|
|
8
8
|
],
|
|
9
9
|
"bin": {
|
|
10
|
-
"wahelper": "
|
|
10
|
+
"wahelper": "wahelper.js"
|
|
11
11
|
},
|
|
12
12
|
"publishConfig": {
|
|
13
13
|
"access": "public"
|
|
@@ -20,11 +20,10 @@
|
|
|
20
20
|
"author": "David Vielhuber <david@vielhuber.de>",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"
|
|
24
|
-
"baileys": "^7.0.0-rc.6"
|
|
23
|
+
"baileys": "^7.0.0-rc.9"
|
|
25
24
|
},
|
|
26
25
|
"devDependencies": {
|
|
27
26
|
"@prettier/plugin-php": "^0.24.0",
|
|
28
|
-
"prettier": "^3.
|
|
27
|
+
"prettier": "^3.7.4"
|
|
29
28
|
}
|
|
30
29
|
}
|
|
@@ -1,20 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import makeWASocket, {
|
|
6
|
-
useMultiFileAuthState,
|
|
7
|
-
DisconnectReason,
|
|
8
|
-
downloadMediaMessage,
|
|
9
|
-
processSyncAction
|
|
10
|
-
} from 'baileys';
|
|
1
|
+
import makeWASocket, { useMultiFileAuthState, DisconnectReason, downloadMediaMessage } from 'baileys';
|
|
11
2
|
import P from 'pino';
|
|
12
3
|
import { fileURLToPath } from 'url';
|
|
13
4
|
import { dirname } from 'path';
|
|
14
5
|
import fs from 'fs';
|
|
15
6
|
import { DatabaseSync } from 'node:sqlite';
|
|
16
7
|
|
|
17
|
-
export default class
|
|
8
|
+
export default class wahelper {
|
|
18
9
|
constructor() {
|
|
19
10
|
this.args = this.parseArgs();
|
|
20
11
|
this.dirname = this.getDirname();
|
|
@@ -28,7 +19,6 @@ export default class WhatsApp {
|
|
|
28
19
|
this.dbIsOpen = false;
|
|
29
20
|
this.shutdown = false;
|
|
30
21
|
this.isFirstRun = false;
|
|
31
|
-
this.isMcp = this.args.mcp === true;
|
|
32
22
|
this.inactivityTimeMaxOrig = 10;
|
|
33
23
|
this.inactivityTimeMax = this.inactivityTimeMaxOrig;
|
|
34
24
|
this.inactivityTimeCur = 0;
|
|
@@ -61,64 +51,55 @@ export default class WhatsApp {
|
|
|
61
51
|
this.setLock('init', true);
|
|
62
52
|
this.write({ success: false, message: 'loading_state', data: null }, false);
|
|
63
53
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
54
|
+
this.log('cli start');
|
|
55
|
+
this.log(this.args);
|
|
56
|
+
if (
|
|
57
|
+
this.args.device === undefined ||
|
|
58
|
+
(this.args.action === 'send_user' && (this.args.number === undefined || this.args.message === undefined)) ||
|
|
59
|
+
(this.args.action === 'send_group' && (this.args.name === undefined || this.args.message === undefined)) ||
|
|
60
|
+
(this.args.action === 'fetch_messages' &&
|
|
61
|
+
this.args.limit !== undefined &&
|
|
62
|
+
typeof this.args.limit !== 'number') ||
|
|
63
|
+
!['fetch_messages', 'send_user', 'send_group'].includes(this.args.action)
|
|
64
|
+
) {
|
|
65
|
+
console.error('input missing or unknown action!');
|
|
66
|
+
this.log('⛔input missing or unknown action!');
|
|
67
|
+
this.write(
|
|
68
|
+
{
|
|
69
|
+
success: false,
|
|
70
|
+
message: 'error',
|
|
71
|
+
public_message: 'input missing or unknown action!',
|
|
72
|
+
data: null
|
|
73
|
+
},
|
|
74
|
+
true
|
|
75
|
+
);
|
|
76
|
+
this.removeLocks();
|
|
77
|
+
} else {
|
|
78
|
+
this.initDatabase();
|
|
79
|
+
this.initInactivityTimer();
|
|
80
|
+
this.initExitHooks();
|
|
81
|
+
if (this.args.reset === true) {
|
|
82
|
+
this.resetFolder();
|
|
83
|
+
}
|
|
84
|
+
let response = null;
|
|
85
|
+
if (this.args.action === 'fetch_messages') {
|
|
86
|
+
response = await this.authAndRun(() => this.fetchMessages(this.args.limit));
|
|
87
|
+
}
|
|
88
|
+
if (this.args.action === 'send_user') {
|
|
89
|
+
response = await this.authAndRun(() =>
|
|
90
|
+
this.sendMessageToUser(this.args.number, this.args.message, this.args.attachments)
|
|
85
91
|
);
|
|
86
|
-
this.removeLocks();
|
|
87
|
-
} else {
|
|
88
|
-
this.initDatabase();
|
|
89
|
-
this.initInactivityTimer();
|
|
90
|
-
this.initExitHooks();
|
|
91
|
-
if (this.args.reset === true) {
|
|
92
|
-
this.resetFolder();
|
|
93
|
-
}
|
|
94
|
-
let response = null;
|
|
95
|
-
if (this.args.action === 'fetch_messages') {
|
|
96
|
-
response = await this.authAndRun(() => this.fetchMessages());
|
|
97
|
-
}
|
|
98
|
-
if (this.args.action === 'send_user') {
|
|
99
|
-
response = await this.authAndRun(() =>
|
|
100
|
-
this.sendMessageToUser(this.args.number, this.args.message, this.args.attachments)
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
if (this.args.action === 'send_group') {
|
|
104
|
-
response = await this.authAndRun(() =>
|
|
105
|
-
this.sendMessageToGroup(this.args.name, this.args.message, this.args.attachments)
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
console.log(response);
|
|
109
|
-
await this.endSession();
|
|
110
92
|
}
|
|
111
|
-
this.
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.
|
|
118
|
-
let transport = new StdioServerTransport();
|
|
119
|
-
await server.connect(transport);
|
|
120
|
-
this.log('mcp stop');
|
|
93
|
+
if (this.args.action === 'send_group') {
|
|
94
|
+
response = await this.authAndRun(() =>
|
|
95
|
+
this.sendMessageToGroup(this.args.name, this.args.message, this.args.attachments)
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
console.log(response);
|
|
99
|
+
await this.endSession();
|
|
121
100
|
}
|
|
101
|
+
this.log('cli stop');
|
|
102
|
+
//process.exit();
|
|
122
103
|
}
|
|
123
104
|
|
|
124
105
|
async endSession() {
|
|
@@ -194,45 +175,35 @@ export default class WhatsApp {
|
|
|
194
175
|
// increase inactivity timer on pairing
|
|
195
176
|
this.restartInactivityTimer();
|
|
196
177
|
this.setInactivityTimeMax(60);
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
this.write({ success: false, message: 'pairing_code_required', data: code }, true);
|
|
206
|
-
}
|
|
207
|
-
if (this.isMcp) {
|
|
208
|
-
resolve({
|
|
209
|
-
content: [{ type: 'text', text: 'QR Code muss gescannt werden.' }]
|
|
210
|
-
});
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
178
|
+
//let code = await QRCode.toString(qr, { type: 'utf8' });
|
|
179
|
+
//console.log(code);
|
|
180
|
+
let code = await this.sock.requestPairingCode(this.formatNumber(this.args.device));
|
|
181
|
+
// format code XXXXXXX => XXXX-XXXX
|
|
182
|
+
code = code.match(/.{1,4}/g).join('-');
|
|
183
|
+
console.log('Bitte verknüpfe das neue Gerät und gib diesen Code ein:');
|
|
184
|
+
console.log(code);
|
|
185
|
+
this.write({ success: false, message: 'pairing_code_required', data: code }, true);
|
|
213
186
|
} else {
|
|
214
187
|
if (connection === 'close') {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
console.log('reset authentication. try again!');
|
|
228
|
-
}
|
|
229
|
-
resolve(await this.authAndRun(fn));
|
|
230
|
-
return;
|
|
231
|
-
} else {
|
|
232
|
-
this.log('⚠️close: 3');
|
|
233
|
-
resolve();
|
|
234
|
-
return;
|
|
188
|
+
// reconnect after pairing (needed!)
|
|
189
|
+
if (statusCode === DisconnectReason.restartRequired) {
|
|
190
|
+
// again: reset inactivity timer after pairing
|
|
191
|
+
this.restartInactivityTimer();
|
|
192
|
+
this.setInactivityTimeMax(this.inactivityTimeMaxOrig);
|
|
193
|
+
this.log('⚠️close: reconnect');
|
|
194
|
+
resolve(await this.authAndRun(fn));
|
|
195
|
+
return;
|
|
196
|
+
} else if (statusCode === 401) {
|
|
197
|
+
this.log('⚠️close: 2');
|
|
198
|
+
if (this.resetFolder() === true) {
|
|
199
|
+
console.log('reset authentication. try again!');
|
|
235
200
|
}
|
|
201
|
+
resolve(await this.authAndRun(fn));
|
|
202
|
+
return;
|
|
203
|
+
} else {
|
|
204
|
+
this.log('⚠️close: 3');
|
|
205
|
+
resolve();
|
|
206
|
+
return;
|
|
236
207
|
}
|
|
237
208
|
}
|
|
238
209
|
|
|
@@ -354,7 +325,7 @@ export default class WhatsApp {
|
|
|
354
325
|
return;
|
|
355
326
|
}
|
|
356
327
|
|
|
357
|
-
async fetchMessages() {
|
|
328
|
+
async fetchMessages(limit = null) {
|
|
358
329
|
// wait for inactivity
|
|
359
330
|
await this.awaitInactivityTimer();
|
|
360
331
|
|
|
@@ -365,6 +336,7 @@ export default class WhatsApp {
|
|
|
365
336
|
SELECT id, \`from\`, \`to\`, content, media_filename, timestamp
|
|
366
337
|
FROM messages
|
|
367
338
|
ORDER BY timestamp DESC
|
|
339
|
+
${limit !== null ? 'LIMIT ' + limit : ''}
|
|
368
340
|
`
|
|
369
341
|
)
|
|
370
342
|
.all();
|
|
@@ -493,60 +465,6 @@ export default class WhatsApp {
|
|
|
493
465
|
};
|
|
494
466
|
}
|
|
495
467
|
|
|
496
|
-
registerMcp() {
|
|
497
|
-
let server = new McpServer({
|
|
498
|
-
name: 'whatsapp-mcp',
|
|
499
|
-
version: '1.0.0'
|
|
500
|
-
});
|
|
501
|
-
|
|
502
|
-
server.registerTool(
|
|
503
|
-
'fetch_messages',
|
|
504
|
-
{
|
|
505
|
-
title: 'Fetch messages',
|
|
506
|
-
description: 'Fetch all messages',
|
|
507
|
-
inputSchema: {},
|
|
508
|
-
outputSchema: { result: z.string().describe('Result of fetching messages') }
|
|
509
|
-
},
|
|
510
|
-
async ({}) => {
|
|
511
|
-
let response = await this.authAndRun(() => fetchMessages());
|
|
512
|
-
return response;
|
|
513
|
-
}
|
|
514
|
-
);
|
|
515
|
-
|
|
516
|
-
server.registerTool(
|
|
517
|
-
'send_group',
|
|
518
|
-
{
|
|
519
|
-
title: 'Send message to group',
|
|
520
|
-
description: 'Send message to group',
|
|
521
|
-
inputSchema: { group: z.string().describe('Group name'), text: z.string().describe('Message text') },
|
|
522
|
-
outputSchema: { result: z.string().describe('Result of sending message') }
|
|
523
|
-
},
|
|
524
|
-
async ({ group, text }) => {
|
|
525
|
-
this.log([group, text]);
|
|
526
|
-
let response = await this.authAndRun(() => sendMessageToGroup(group, text));
|
|
527
|
-
return response;
|
|
528
|
-
}
|
|
529
|
-
);
|
|
530
|
-
|
|
531
|
-
server.registerTool(
|
|
532
|
-
'send_message',
|
|
533
|
-
{
|
|
534
|
-
title: 'Send message to person',
|
|
535
|
-
description: 'Send message to person',
|
|
536
|
-
inputSchema: {
|
|
537
|
-
number: z.string().describe('Person number'),
|
|
538
|
-
text: z.string().describe('Message text')
|
|
539
|
-
},
|
|
540
|
-
outputSchema: { result: z.string().describe('Result of sending message') }
|
|
541
|
-
},
|
|
542
|
-
async ({ number, text }) => {
|
|
543
|
-
this.log([number, text]);
|
|
544
|
-
let response = await this.authAndRun(() => sendMessageToPerson(number, text));
|
|
545
|
-
return response;
|
|
546
|
-
}
|
|
547
|
-
);
|
|
548
|
-
}
|
|
549
|
-
|
|
550
468
|
formatNumber(number) {
|
|
551
469
|
// replace leading zero with 49
|
|
552
470
|
number = number.replace(/^0+/, '49');
|
|
@@ -587,6 +505,10 @@ export default class WhatsApp {
|
|
|
587
505
|
value = value.split(',');
|
|
588
506
|
}
|
|
589
507
|
|
|
508
|
+
if (key === 'limit') {
|
|
509
|
+
value = parseInt(value);
|
|
510
|
+
}
|
|
511
|
+
|
|
590
512
|
args[key] = value;
|
|
591
513
|
}
|
|
592
514
|
}
|
|
@@ -831,5 +753,5 @@ export default class WhatsApp {
|
|
|
831
753
|
}
|
|
832
754
|
}
|
|
833
755
|
|
|
834
|
-
let wa = new
|
|
756
|
+
let wa = new wahelper();
|
|
835
757
|
wa.init();
|