whatsapp-pi 1.0.56 → 1.0.57
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 -0
- package/src/services/session.manager.ts +22 -3
- package/src/services/whatsapp.service.ts +25 -0
- 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)",
|
|
@@ -247,6 +249,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
247
249
|
"service.whatsapp.connecting": "| WhatsApp: Conectando...",
|
|
248
250
|
"service.whatsapp.typeToConnect": "| WhatsApp: digite /whatsapp para conectar",
|
|
249
251
|
"service.whatsapp.connected": "| WhatsApp: Conectado",
|
|
252
|
+
"service.whatsapp.qrConnected": "WhatsApp conectado",
|
|
253
|
+
"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
254
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Erro de sessão (Bad MAC)",
|
|
251
255
|
"service.whatsapp.loggedOut": "| WhatsApp: Desconectado",
|
|
252
256
|
"service.whatsapp.conflict": "| WhatsApp: Conflito (Outra instância)",
|
|
@@ -429,6 +433,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
429
433
|
"service.whatsapp.connecting": "| WhatsApp: Conectando...",
|
|
430
434
|
"service.whatsapp.typeToConnect": "| WhatsApp: escribe /whatsapp para conectar",
|
|
431
435
|
"service.whatsapp.connected": "| WhatsApp: Conectado",
|
|
436
|
+
"service.whatsapp.qrConnected": "WhatsApp conectado",
|
|
437
|
+
"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
438
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Error de sesión (Bad MAC)",
|
|
433
439
|
"service.whatsapp.loggedOut": "| WhatsApp: Cerrado sesión",
|
|
434
440
|
"service.whatsapp.conflict": "| WhatsApp: Conflicto (Otra instancia)",
|
|
@@ -563,6 +569,8 @@ const translations: Record<Locale, Partial<Record<Key, string>>> = {
|
|
|
563
569
|
"service.whatsapp.connecting": "| WhatsApp: Connexion...",
|
|
564
570
|
"service.whatsapp.typeToConnect": "| WhatsApp: tapez /whatsapp pour connecter",
|
|
565
571
|
"service.whatsapp.connected": "| WhatsApp: Connecté",
|
|
572
|
+
"service.whatsapp.qrConnected": "WhatsApp connecté",
|
|
573
|
+
"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
574
|
"service.whatsapp.sessionErrorBadMac": "| WhatsApp: Erreur de session (Bad MAC)",
|
|
567
575
|
"service.whatsapp.loggedOut": "| WhatsApp: Déconnecté",
|
|
568
576
|
"service.whatsapp.conflict": "| WhatsApp: Conflit (Autre instance)",
|
|
@@ -38,6 +38,7 @@ export class SessionManager {
|
|
|
38
38
|
private hasAuthState = false;
|
|
39
39
|
private openaiKey: string = '';
|
|
40
40
|
private visionModel: string = 'gpt-4o';
|
|
41
|
+
private operatorJid: string = '';
|
|
41
42
|
|
|
42
43
|
constructor(baseDir = join(homedir(), '.pi', 'whatsapp-pi')) {
|
|
43
44
|
this.baseDir = baseDir;
|
|
@@ -96,6 +97,7 @@ export class SessionManager {
|
|
|
96
97
|
this.hasAuthState = Boolean(config.hasAuthState);
|
|
97
98
|
this.openaiKey = config.openaiKey || '';
|
|
98
99
|
this.visionModel = config.visionModel || 'gpt-4o';
|
|
100
|
+
this.operatorJid = config.operatorJid || '';
|
|
99
101
|
|
|
100
102
|
if (recovered || needsReactionModeBackfill) {
|
|
101
103
|
await this.saveConfig();
|
|
@@ -169,11 +171,19 @@ export class SessionManager {
|
|
|
169
171
|
status: this.status,
|
|
170
172
|
hasAuthState: this.hasAuthState,
|
|
171
173
|
openaiKey: this.openaiKey,
|
|
172
|
-
visionModel: this.visionModel
|
|
174
|
+
visionModel: this.visionModel,
|
|
175
|
+
operatorJid: this.operatorJid
|
|
173
176
|
};
|
|
174
177
|
await mkdir(this.baseDir, { recursive: true });
|
|
175
|
-
|
|
176
|
-
await
|
|
178
|
+
const serialized = JSON.stringify(config, null, 2);
|
|
179
|
+
await writeFile(tempPath, serialized);
|
|
180
|
+
try {
|
|
181
|
+
await rename(tempPath, this.configPath);
|
|
182
|
+
} catch {
|
|
183
|
+
// Windows EPERM: atomic rename failed (file locked). Fall back to direct write.
|
|
184
|
+
await writeFile(this.configPath, serialized);
|
|
185
|
+
await rm(tempPath, { force: true }).catch(() => {});
|
|
186
|
+
}
|
|
177
187
|
} catch (error) {
|
|
178
188
|
await rm(tempPath, { force: true }).catch(() => {});
|
|
179
189
|
console.error(t('session.manager.failedSaveConfig'), error);
|
|
@@ -470,6 +480,15 @@ export class SessionManager {
|
|
|
470
480
|
await this.saveConfig();
|
|
471
481
|
}
|
|
472
482
|
|
|
483
|
+
getOperatorJid(): string {
|
|
484
|
+
return this.operatorJid;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
async setOperatorJid(jid: string) {
|
|
488
|
+
this.operatorJid = jid;
|
|
489
|
+
await this.saveConfig();
|
|
490
|
+
}
|
|
491
|
+
|
|
473
492
|
getAuthStateDir(): string {
|
|
474
493
|
return this.authStateDir;
|
|
475
494
|
}
|
|
@@ -112,6 +112,7 @@ export class WhatsAppService {
|
|
|
112
112
|
private onMessage?: (m: MessagesUpsertEvent) => void;
|
|
113
113
|
private onStatusUpdate?: (status: string) => void;
|
|
114
114
|
private lastRemoteJid: string | null = null;
|
|
115
|
+
private qrWasShown = false;
|
|
115
116
|
private boundGroupJid: string | null = null;
|
|
116
117
|
private groupMetadataCache: Map<string, { id: string; subject: string; participants: Array<{ id: string }> }> = new Map();
|
|
117
118
|
|
|
@@ -406,6 +407,7 @@ export class WhatsAppService {
|
|
|
406
407
|
this.sessionManager.setStatus('pairing');
|
|
407
408
|
this.onQRCode?.(qr);
|
|
408
409
|
this.onStatusUpdate?.(t('service.whatsapp.typeToConnect'));
|
|
410
|
+
this.qrWasShown = true;
|
|
409
411
|
}
|
|
410
412
|
|
|
411
413
|
private async handleConnectionOpen() {
|
|
@@ -420,6 +422,29 @@ export class WhatsAppService {
|
|
|
420
422
|
await this.sessionManager.markAuthStateAvailable();
|
|
421
423
|
this.sessionManager.setStatus('connected');
|
|
422
424
|
this.onStatusUpdate?.(t('service.whatsapp.connected'));
|
|
425
|
+
|
|
426
|
+
if (this.qrWasShown) {
|
|
427
|
+
this.qrWasShown = false;
|
|
428
|
+
console.log(t('service.whatsapp.qrConnected'));
|
|
429
|
+
console.log(t('service.whatsapp.qrWelcomeMessage'));
|
|
430
|
+
void this.sendQrWelcome();
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
private async sendQrWelcome(): Promise<void> {
|
|
435
|
+
const rawId = this.socket?.user?.id;
|
|
436
|
+
if (!rawId) return;
|
|
437
|
+
const selfJid = this.normalizeJidForComparison(rawId);
|
|
438
|
+
await this.sessionManager.setOperatorJid(selfJid);
|
|
439
|
+
try {
|
|
440
|
+
await this.socket?.sendMessage(selfJid, { text: t('service.whatsapp.qrWelcomeMessage') });
|
|
441
|
+
} catch {
|
|
442
|
+
// Best-effort — welcome send failure must not abort the session.
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
public getOperatorJid(): string {
|
|
447
|
+
return this.sessionManager.getOperatorJid();
|
|
423
448
|
}
|
|
424
449
|
|
|
425
450
|
private isBadMacError(errorMessage: string): boolean {
|
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,
|