whatsapp-pi 1.0.56 → 1.0.58
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/src/i18n.ts +8 -10
- package/src/models/whatsapp.types.ts +0 -2
- package/src/services/session.manager.ts +27 -39
- package/src/services/whatsapp.service.ts +36 -30
- package/src/ui/menu.handler.ts +1 -32
- package/whatsapp-pi.ts +2 -2
package/package.json
CHANGED
package/src/i18n.ts
CHANGED
|
@@ -31,6 +31,8 @@ const fallback = {
|
|
|
31
31
|
"service.whatsapp.connecting": "| WhatsApp: Connecting...",
|
|
32
32
|
"service.whatsapp.typeToConnect": "| WhatsApp: type /whatsapp to connect",
|
|
33
33
|
"service.whatsapp.connected": "| WhatsApp: Connected",
|
|
34
|
+
"service.whatsapp.qrConnected": "WhatsApp connected",
|
|
35
|
+
"service.whatsapp.qrWelcomeMessage": "👋 To get started, send a message, enter in /whatsapp > Recents to Allow Contact with LID code, then add the whatsapp number in the Allowed Contact list.",
|
|
34
36
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Session Error (Bad MAC)",
|
|
35
37
|
"service.whatsapp.loggedOut": "| WhatsApp: Logged out",
|
|
36
38
|
"service.whatsapp.conflict": "| WhatsApp: Conflict (Another Instance)",
|
|
@@ -107,11 +109,6 @@ const fallback = {
|
|
|
107
109
|
"menu.allowedGroups.group.history": "History",
|
|
108
110
|
"menu.allowedGroups.group.sendMessage": "Send Message",
|
|
109
111
|
"menu.allowedGroups.group.printGroup": "Print Group JID",
|
|
110
|
-
"menu.allowedGroups.group.reactionMode": "Reaction Mode",
|
|
111
|
-
"menu.allowedGroups.group.reactionMode.title": "Reaction Mode • {displayName}",
|
|
112
|
-
"menu.allowedGroups.group.reactionMode.active": "Active",
|
|
113
|
-
"menu.allowedGroups.group.reactionMode.passive": "Passive",
|
|
114
|
-
"menu.allowedGroups.group.reactionMode.updated": "Reaction mode set to {mode} for {displayName}",
|
|
115
112
|
"menu.allowedGroups.group.removeAlias": "Remove Alias",
|
|
116
113
|
"menu.allowedGroups.group.addAlias": "Add Alias",
|
|
117
114
|
"menu.allowedGroups.group.removeGroup": "Remove Group",
|
|
@@ -247,6 +244,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
247
244
|
"service.whatsapp.connecting": "| WhatsApp: Conectando...",
|
|
248
245
|
"service.whatsapp.typeToConnect": "| WhatsApp: digite /whatsapp para conectar",
|
|
249
246
|
"service.whatsapp.connected": "| WhatsApp: Conectado",
|
|
247
|
+
"service.whatsapp.qrConnected": "WhatsApp conectado",
|
|
248
|
+
"service.whatsapp.qrWelcomeMessage": "👋 Para começar, envie uma mensagem, entre em /whatsapp > Recentes para Permitir o Contato com o código LID, depois adicione o número do whatsapp na lista de Contatos Permitidos.",
|
|
250
249
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Erro de sessão (Bad MAC)",
|
|
251
250
|
"service.whatsapp.loggedOut": "| WhatsApp: Desconectado",
|
|
252
251
|
"service.whatsapp.conflict": "| WhatsApp: Conflito (Outra instância)",
|
|
@@ -323,11 +322,6 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
323
322
|
"menu.allowedGroups.group.history": "Histórico",
|
|
324
323
|
"menu.allowedGroups.group.sendMessage": "Enviar mensagem",
|
|
325
324
|
"menu.allowedGroups.group.printGroup": "Mostrar JID do grupo",
|
|
326
|
-
"menu.allowedGroups.group.reactionMode": "Modo de reação",
|
|
327
|
-
"menu.allowedGroups.group.reactionMode.title": "Modo de reação • {displayName}",
|
|
328
|
-
"menu.allowedGroups.group.reactionMode.active": "Ativo",
|
|
329
|
-
"menu.allowedGroups.group.reactionMode.passive": "Passivo",
|
|
330
|
-
"menu.allowedGroups.group.reactionMode.updated": "Modo de reação definido como {mode} para {displayName}",
|
|
331
325
|
"menu.allowedGroups.group.removeAlias": "Remover apelido",
|
|
332
326
|
"menu.allowedGroups.group.addAlias": "Adicionar apelido",
|
|
333
327
|
"menu.allowedGroups.group.removeGroup": "Remover grupo",
|
|
@@ -429,6 +423,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
429
423
|
"service.whatsapp.connecting": "| WhatsApp: Conectando...",
|
|
430
424
|
"service.whatsapp.typeToConnect": "| WhatsApp: escribe /whatsapp para conectar",
|
|
431
425
|
"service.whatsapp.connected": "| WhatsApp: Conectado",
|
|
426
|
+
"service.whatsapp.qrConnected": "WhatsApp conectado",
|
|
427
|
+
"service.whatsapp.qrWelcomeMessage": "👋 Para empezar, envía un mensaje, entra en /whatsapp > Recientes para Permitir el Contacto con el código LID, luego añade el número de whatsapp en la lista de Contactos Permitidos.",
|
|
432
428
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Error de sesión (Bad MAC)",
|
|
433
429
|
"service.whatsapp.loggedOut": "| WhatsApp: Cerrado sesión",
|
|
434
430
|
"service.whatsapp.conflict": "| WhatsApp: Conflicto (Otra instancia)",
|
|
@@ -563,6 +559,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
563
559
|
"service.whatsapp.connecting": "| WhatsApp: Connexion...",
|
|
564
560
|
"service.whatsapp.typeToConnect": "| WhatsApp: tapez /whatsapp pour connecter",
|
|
565
561
|
"service.whatsapp.connected": "| WhatsApp: Connecté",
|
|
562
|
+
"service.whatsapp.qrConnected": "WhatsApp connecté",
|
|
563
|
+
"service.whatsapp.qrWelcomeMessage": "👋 Pour commencer, envoyez un message, allez dans /whatsapp > Récents pour Autoriser le Contact avec le code LID, puis ajoutez le numéro whatsapp dans la liste des Contacts Autorisés.",
|
|
566
564
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Erreur de session (Bad MAC)",
|
|
567
565
|
"service.whatsapp.loggedOut": "| WhatsApp: Déconnecté",
|
|
568
566
|
"service.whatsapp.conflict": "| WhatsApp: Conflit (Autre instance)",
|
|
@@ -2,14 +2,13 @@ import { useMultiFileAuthState } from 'baileys';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { readFile, writeFile, mkdir, rm, rename } from 'fs/promises';
|
|
4
4
|
import { homedir } from 'os';
|
|
5
|
-
import { SessionStatus
|
|
5
|
+
import { SessionStatus } from '../models/whatsapp.types.js';
|
|
6
6
|
import { t } from '../i18n.js';
|
|
7
7
|
|
|
8
8
|
export interface Contact {
|
|
9
9
|
number: string;
|
|
10
10
|
name?: string;
|
|
11
11
|
sendNumber?: string;
|
|
12
|
-
reactionMode?: ReactionMode;
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
export class SessionManager {
|
|
@@ -38,6 +37,7 @@ export class SessionManager {
|
|
|
38
37
|
private hasAuthState = false;
|
|
39
38
|
private openaiKey: string = '';
|
|
40
39
|
private visionModel: string = 'gpt-4o';
|
|
40
|
+
private operatorJid: string = '';
|
|
41
41
|
|
|
42
42
|
constructor(baseDir = join(homedir(), '.pi', 'whatsapp-pi')) {
|
|
43
43
|
this.baseDir = baseDir;
|
|
@@ -74,11 +74,8 @@ export class SessionManager {
|
|
|
74
74
|
num = num.number;
|
|
75
75
|
}
|
|
76
76
|
if (typeof num === 'string') {
|
|
77
|
-
const reactionMode = item.reactionMode === 'active' || item.reactionMode === 'passive'
|
|
78
|
-
? item.reactionMode
|
|
79
|
-
: undefined;
|
|
80
77
|
const sendNumber = typeof item.sendNumber === 'string' ? item.sendNumber : undefined;
|
|
81
|
-
return { number: num, name: item.name, sendNumber
|
|
78
|
+
return { number: num, name: item.name, sendNumber };
|
|
82
79
|
}
|
|
83
80
|
}
|
|
84
81
|
return null;
|
|
@@ -87,8 +84,6 @@ export class SessionManager {
|
|
|
87
84
|
const loadedAllowList = (config.allowList || []).map(cleanContact).filter(Boolean) as Contact[];
|
|
88
85
|
const loadedAllowedGroups = (config.allowedGroups || []).map(cleanContact).filter(Boolean) as Contact[];
|
|
89
86
|
const migratedGroups = loadedAllowList.filter(c => SessionManager.isGroupJid(c.number));
|
|
90
|
-
const needsReactionModeBackfill = loadedAllowedGroups.some(group => !group.reactionMode)
|
|
91
|
-
|| migratedGroups.some(group => !group.reactionMode);
|
|
92
87
|
this.allowList = loadedAllowList.filter(c => !SessionManager.isGroupJid(c.number));
|
|
93
88
|
this.allowedGroups = this.mergeContacts(loadedAllowedGroups, migratedGroups);
|
|
94
89
|
this.ignoredNumbers = (config.ignoredNumbers || []).map(cleanContact).filter(Boolean) as Contact[];
|
|
@@ -96,8 +91,9 @@ export class SessionManager {
|
|
|
96
91
|
this.hasAuthState = Boolean(config.hasAuthState);
|
|
97
92
|
this.openaiKey = config.openaiKey || '';
|
|
98
93
|
this.visionModel = config.visionModel || 'gpt-4o';
|
|
94
|
+
this.operatorJid = config.operatorJid || '';
|
|
99
95
|
|
|
100
|
-
if (recovered
|
|
96
|
+
if (recovered) {
|
|
101
97
|
await this.saveConfig();
|
|
102
98
|
}
|
|
103
99
|
} catch {
|
|
@@ -169,11 +165,19 @@ export class SessionManager {
|
|
|
169
165
|
status: this.status,
|
|
170
166
|
hasAuthState: this.hasAuthState,
|
|
171
167
|
openaiKey: this.openaiKey,
|
|
172
|
-
visionModel: this.visionModel
|
|
168
|
+
visionModel: this.visionModel,
|
|
169
|
+
operatorJid: this.operatorJid
|
|
173
170
|
};
|
|
174
171
|
await mkdir(this.baseDir, { recursive: true });
|
|
175
|
-
|
|
176
|
-
await
|
|
172
|
+
const serialized = JSON.stringify(config, null, 2);
|
|
173
|
+
await writeFile(tempPath, serialized);
|
|
174
|
+
try {
|
|
175
|
+
await rename(tempPath, this.configPath);
|
|
176
|
+
} catch {
|
|
177
|
+
// Windows EPERM: atomic rename failed (file locked). Fall back to direct write.
|
|
178
|
+
await writeFile(this.configPath, serialized);
|
|
179
|
+
await rm(tempPath, { force: true }).catch(() => {});
|
|
180
|
+
}
|
|
177
181
|
} catch (error) {
|
|
178
182
|
await rm(tempPath, { force: true }).catch(() => {});
|
|
179
183
|
console.error(t('session.manager.failedSaveConfig'), error);
|
|
@@ -248,7 +252,7 @@ export class SessionManager {
|
|
|
248
252
|
|
|
249
253
|
const existing = this.allowedGroups.find(c => c.number === groupJid);
|
|
250
254
|
if (!existing) {
|
|
251
|
-
this.allowedGroups.push({ number: groupJid, name
|
|
255
|
+
this.allowedGroups.push({ number: groupJid, name });
|
|
252
256
|
this.ignoredNumbers = this.ignoredNumbers.filter(c => c.number !== groupJid);
|
|
253
257
|
await this.saveConfig();
|
|
254
258
|
return;
|
|
@@ -258,11 +262,6 @@ export class SessionManager {
|
|
|
258
262
|
existing.name = name;
|
|
259
263
|
await this.saveConfig();
|
|
260
264
|
}
|
|
261
|
-
|
|
262
|
-
if (!existing.reactionMode) {
|
|
263
|
-
existing.reactionMode = 'active';
|
|
264
|
-
await this.saveConfig();
|
|
265
|
-
}
|
|
266
265
|
}
|
|
267
266
|
|
|
268
267
|
async removeAllowedGroup(groupJid: string) {
|
|
@@ -324,20 +323,6 @@ export class SessionManager {
|
|
|
324
323
|
await this.saveConfig();
|
|
325
324
|
}
|
|
326
325
|
|
|
327
|
-
getAllowedGroupReactionMode(groupJid: string): ReactionMode {
|
|
328
|
-
return this.getAllowedGroup(groupJid)?.reactionMode || 'active';
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
async setAllowedGroupReactionMode(groupJid: string, reactionMode: ReactionMode) {
|
|
332
|
-
const group = this.getAllowedGroup(groupJid);
|
|
333
|
-
if (!group) {
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
group.reactionMode = reactionMode;
|
|
338
|
-
await this.saveConfig();
|
|
339
|
-
}
|
|
340
|
-
|
|
341
326
|
async removeAllowedGroupAlias(groupJid: string) {
|
|
342
327
|
const group = this.getAllowedGroup(groupJid);
|
|
343
328
|
if (!group || !group.name) {
|
|
@@ -381,15 +366,9 @@ export class SessionManager {
|
|
|
381
366
|
if (!existing.name && contact.name) {
|
|
382
367
|
existing.name = contact.name;
|
|
383
368
|
}
|
|
384
|
-
if (!existing.reactionMode && contact.reactionMode) {
|
|
385
|
-
existing.reactionMode = contact.reactionMode;
|
|
386
|
-
}
|
|
387
369
|
}
|
|
388
370
|
}
|
|
389
|
-
return merged
|
|
390
|
-
...contact,
|
|
391
|
-
reactionMode: contact.reactionMode || 'active'
|
|
392
|
-
}));
|
|
371
|
+
return merged;
|
|
393
372
|
}
|
|
394
373
|
|
|
395
374
|
public async isRegistered(): Promise<boolean> {
|
|
@@ -470,6 +449,15 @@ export class SessionManager {
|
|
|
470
449
|
await this.saveConfig();
|
|
471
450
|
}
|
|
472
451
|
|
|
452
|
+
getOperatorJid(): string {
|
|
453
|
+
return this.operatorJid;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async setOperatorJid(jid: string) {
|
|
457
|
+
this.operatorJid = jid;
|
|
458
|
+
await this.saveConfig();
|
|
459
|
+
}
|
|
460
|
+
|
|
473
461
|
getAuthStateDir(): string {
|
|
474
462
|
return this.authStateDir;
|
|
475
463
|
}
|
|
@@ -46,12 +46,23 @@ interface IncomingMessageContextInfo {
|
|
|
46
46
|
mentionedJid?: string[];
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
interface IncomingMessageWithContext {
|
|
50
|
+
contextInfo?: IncomingMessageContextInfo;
|
|
51
|
+
}
|
|
52
|
+
|
|
49
53
|
interface IncomingMessageContent {
|
|
50
54
|
conversation?: string;
|
|
51
55
|
extendedTextMessage?: {
|
|
52
56
|
text?: string;
|
|
53
57
|
contextInfo?: IncomingMessageContextInfo;
|
|
54
58
|
};
|
|
59
|
+
imageMessage?: IncomingMessageWithContext;
|
|
60
|
+
videoMessage?: IncomingMessageWithContext;
|
|
61
|
+
documentMessage?: IncomingMessageWithContext;
|
|
62
|
+
audioMessage?: IncomingMessageWithContext;
|
|
63
|
+
stickerMessage?: IncomingMessageWithContext;
|
|
64
|
+
buttonsMessage?: IncomingMessageWithContext;
|
|
65
|
+
templateMessage?: IncomingMessageWithContext;
|
|
55
66
|
}
|
|
56
67
|
|
|
57
68
|
interface IncomingMessageLike {
|
|
@@ -112,6 +123,7 @@ export class WhatsAppService {
|
|
|
112
123
|
private onMessage?: (m: MessagesUpsertEvent) => void;
|
|
113
124
|
private onStatusUpdate?: (status: string) => void;
|
|
114
125
|
private lastRemoteJid: string | null = null;
|
|
126
|
+
private qrWasShown = false;
|
|
115
127
|
private boundGroupJid: string | null = null;
|
|
116
128
|
private groupMetadataCache: Map<string, { id: string; subject: string; participants: Array<{ id: string }> }> = new Map();
|
|
117
129
|
|
|
@@ -203,24 +215,6 @@ export class WhatsAppService {
|
|
|
203
215
|
return [...candidates];
|
|
204
216
|
}
|
|
205
217
|
|
|
206
|
-
private messageHasDirectMention(message: IncomingMessageLike): boolean {
|
|
207
|
-
const mentionedJids = message.message?.extendedTextMessage?.contextInfo?.mentionedJid || [];
|
|
208
|
-
if (mentionedJids.length === 0) {
|
|
209
|
-
return false;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
const agentCandidates = this.getAgentJidCandidates();
|
|
213
|
-
if (agentCandidates.length === 0) {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return mentionedJids.some(jid => {
|
|
218
|
-
const normalizedMention = this.normalizeJidForComparison(jid);
|
|
219
|
-
const mentionIdentity = this.normalizeJidIdentity(jid);
|
|
220
|
-
return agentCandidates.includes(normalizedMention) || agentCandidates.includes(mentionIdentity);
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
|
|
224
218
|
private getDisconnectStatusCode(error: unknown): number | undefined {
|
|
225
219
|
if (!error || typeof error !== 'object') {
|
|
226
220
|
return undefined;
|
|
@@ -406,6 +400,7 @@ export class WhatsAppService {
|
|
|
406
400
|
this.sessionManager.setStatus('pairing');
|
|
407
401
|
this.onQRCode?.(qr);
|
|
408
402
|
this.onStatusUpdate?.(t('service.whatsapp.typeToConnect'));
|
|
403
|
+
this.qrWasShown = true;
|
|
409
404
|
}
|
|
410
405
|
|
|
411
406
|
private async handleConnectionOpen() {
|
|
@@ -420,6 +415,29 @@ export class WhatsAppService {
|
|
|
420
415
|
await this.sessionManager.markAuthStateAvailable();
|
|
421
416
|
this.sessionManager.setStatus('connected');
|
|
422
417
|
this.onStatusUpdate?.(t('service.whatsapp.connected'));
|
|
418
|
+
|
|
419
|
+
if (this.qrWasShown) {
|
|
420
|
+
this.qrWasShown = false;
|
|
421
|
+
console.log(t('service.whatsapp.qrConnected'));
|
|
422
|
+
console.log(t('service.whatsapp.qrWelcomeMessage'));
|
|
423
|
+
void this.sendQrWelcome();
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
private async sendQrWelcome(): Promise<void> {
|
|
428
|
+
const rawId = this.socket?.user?.id;
|
|
429
|
+
if (!rawId) return;
|
|
430
|
+
const selfJid = this.normalizeJidForComparison(rawId);
|
|
431
|
+
await this.sessionManager.setOperatorJid(selfJid);
|
|
432
|
+
try {
|
|
433
|
+
await this.socket?.sendMessage(selfJid, { text: t('service.whatsapp.qrWelcomeMessage') });
|
|
434
|
+
} catch {
|
|
435
|
+
// Best-effort — welcome send failure must not abort the session.
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
public getOperatorJid(): string {
|
|
440
|
+
return this.sessionManager.getOperatorJid();
|
|
423
441
|
}
|
|
424
442
|
|
|
425
443
|
private isBadMacError(errorMessage: string): boolean {
|
|
@@ -564,10 +582,6 @@ export class WhatsAppService {
|
|
|
564
582
|
void this.recordIncomingMessage(message, remoteJid, text);
|
|
565
583
|
|
|
566
584
|
const pushName = message.pushName || undefined;
|
|
567
|
-
const groupAllowed = isGroup && this.sessionManager.isAllowedGroup(remoteJid);
|
|
568
|
-
const passiveGroupBlocked = groupAllowed
|
|
569
|
-
&& this.sessionManager.getAllowedGroupReactionMode(remoteJid) === 'passive'
|
|
570
|
-
&& !this.messageHasDirectMention(message);
|
|
571
585
|
|
|
572
586
|
if (this.boundGroupJid) {
|
|
573
587
|
if (!this.sessionManager.isAllowedGroup(this.boundGroupJid)) {
|
|
@@ -575,10 +589,6 @@ export class WhatsAppService {
|
|
|
575
589
|
return;
|
|
576
590
|
}
|
|
577
591
|
|
|
578
|
-
if (this.sessionManager.getAllowedGroupReactionMode(this.boundGroupJid) === 'passive' && !this.messageHasDirectMention(message)) {
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
|
|
582
592
|
this.lastRemoteJid = remoteJid;
|
|
583
593
|
this.onMessage?.(payload);
|
|
584
594
|
return;
|
|
@@ -592,10 +602,6 @@ export class WhatsAppService {
|
|
|
592
602
|
return;
|
|
593
603
|
}
|
|
594
604
|
|
|
595
|
-
if (passiveGroupBlocked) {
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
605
|
this.lastRemoteJid = remoteJid;
|
|
600
606
|
this.onMessage?.(payload);
|
|
601
607
|
}
|
package/src/ui/menu.handler.ts
CHANGED
|
@@ -291,12 +291,11 @@ export class MenuHandler {
|
|
|
291
291
|
const historyLabel = t('menu.allowedGroups.group.history');
|
|
292
292
|
const sendMessageLabel = t('menu.allowedGroups.group.sendMessage');
|
|
293
293
|
const printGroupLabel = t('menu.allowedGroups.group.printGroup');
|
|
294
|
-
const reactionModeLabel = t('menu.allowedGroups.group.reactionMode');
|
|
295
294
|
const removeAliasLabel = t('menu.allowedGroups.group.removeAlias');
|
|
296
295
|
const addAliasLabel = t('menu.allowedGroups.group.addAlias');
|
|
297
296
|
const removeGroupLabel = t('menu.allowedGroups.group.removeGroup');
|
|
298
297
|
const backLabel = t('menu.allowedGroups.group.back');
|
|
299
|
-
const options = [historyLabel, sendMessageLabel, printGroupLabel
|
|
298
|
+
const options = [historyLabel, sendMessageLabel, printGroupLabel];
|
|
300
299
|
if (group.name) {
|
|
301
300
|
options.push(removeAliasLabel);
|
|
302
301
|
} else {
|
|
@@ -324,12 +323,6 @@ export class MenuHandler {
|
|
|
324
323
|
return;
|
|
325
324
|
}
|
|
326
325
|
|
|
327
|
-
if (choice === reactionModeLabel) {
|
|
328
|
-
await this.manageAllowedGroupReactionMode(ctx, group);
|
|
329
|
-
await this.manageAllowedGroup(ctx, group);
|
|
330
|
-
return;
|
|
331
|
-
}
|
|
332
|
-
|
|
333
326
|
if (choice === addAliasLabel) {
|
|
334
327
|
const alias = await ctx.ui.input(t('menu.allowedGroups.enterAlias', { groupJid: group.number }));
|
|
335
328
|
const trimmedAlias = alias?.trim() || '';
|
|
@@ -514,30 +507,6 @@ export class MenuHandler {
|
|
|
514
507
|
});
|
|
515
508
|
}
|
|
516
509
|
|
|
517
|
-
private async manageAllowedGroupReactionMode(ctx: ExtensionCommandContext, group: Contact) {
|
|
518
|
-
const displayName = this.formatAllowedGroupOption(group);
|
|
519
|
-
const title = t('menu.allowedGroups.group.reactionMode.title', { displayName });
|
|
520
|
-
const activeLabel = t('menu.allowedGroups.group.reactionMode.active');
|
|
521
|
-
const passiveLabel = t('menu.allowedGroups.group.reactionMode.passive');
|
|
522
|
-
const backLabel = t('menu.allowedGroups.group.back');
|
|
523
|
-
const currentMode = this.sessionManager.getAllowedGroupReactionMode(group.number);
|
|
524
|
-
const options = [activeLabel, passiveLabel, backLabel];
|
|
525
|
-
|
|
526
|
-
const choice = await ctx.ui.select(title, options);
|
|
527
|
-
|
|
528
|
-
if (choice === backLabel || !choice) {
|
|
529
|
-
return;
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
if (choice === activeLabel || choice === passiveLabel) {
|
|
533
|
-
const nextMode = choice === activeLabel ? 'active' : 'passive';
|
|
534
|
-
if (currentMode !== nextMode) {
|
|
535
|
-
await this.sessionManager.setAllowedGroupReactionMode(group.number, nextMode);
|
|
536
|
-
}
|
|
537
|
-
ctx.ui.notify(t('menu.allowedGroups.group.reactionMode.updated', { displayName, mode: choice }), 'info');
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
510
|
private async sendPromptedMenuMessage(
|
|
542
511
|
ctx: ExtensionCommandContext,
|
|
543
512
|
options: {
|
package/whatsapp-pi.ts
CHANGED
|
@@ -268,8 +268,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
268
268
|
message: Type.String({ minLength: 1, description: "Plain-text message content to send" })
|
|
269
269
|
}),
|
|
270
270
|
async execute(_toolCallId, params, _signal, _onUpdate, _ctx) {
|
|
271
|
-
// Resolve JID: jid > recipient_jid > lastRemoteJid
|
|
272
|
-
const resolvedJid = params.jid || params.recipient_jid || whatsappService.getLastRemoteJid();
|
|
271
|
+
// Resolve JID: jid > recipient_jid > lastRemoteJid > operatorJid (QR-scanned number)
|
|
272
|
+
const resolvedJid = params.jid || params.recipient_jid || whatsappService.getLastRemoteJid() || whatsappService.getOperatorJid();
|
|
273
273
|
if (!resolvedJid) {
|
|
274
274
|
return {
|
|
275
275
|
isError: true,
|