From 4dfac4a6e77a434b15849934f7c79a7f56a2560e Mon Sep 17 00:00:00 2001 From: brobert Date: Tue, 30 Sep 2025 00:09:49 +0200 Subject: [PATCH] fix: reiniciar db AllowedGroups tras discovery y quitar retorno Co-authored-by: aider (openrouter/openai/gpt-5) --- src/server.ts | 2 + src/services/group-sync.ts | 5 +- tests/unit/services/group-sync.test.ts | 63 +++++++++++++++----------- 3 files changed, 41 insertions(+), 29 deletions(-) diff --git a/src/server.ts b/src/server.ts index 8d722ce..26bf0ee 100644 --- a/src/server.ts +++ b/src/server.ts @@ -331,6 +331,7 @@ export class WebhookServer { .get(remoteJid) as any; if (!exists) { try { await GroupSyncService.ensureGroupLabelAndName(remoteJid); } catch {} + try { (AllowedGroups as any).dbInstance = WebhookServer.dbInstance; } catch {} try { AllowedGroups.upsertPending(remoteJid, (GroupSyncService.activeGroupsCache.get(remoteJid) || null), normalizedSenderId); } catch {} try { Metrics.inc('unknown_groups_discovered_total'); } catch {} try { @@ -349,6 +350,7 @@ export class WebhookServer { } catch { // Si la tabla no existe por alguna razón, intentar upsert y retornar igualmente try { await GroupSyncService.ensureGroupLabelAndName(remoteJid); } catch {} + try { (AllowedGroups as any).dbInstance = WebhookServer.dbInstance; } catch {} try { AllowedGroups.upsertPending(remoteJid, (GroupSyncService.activeGroupsCache.get(remoteJid) || null), normalizedSenderId); } catch {} try { Metrics.inc('unknown_groups_discovered_total'); } catch {} try { diff --git a/src/services/group-sync.ts b/src/services/group-sync.ts index dd6f658..a8a0a87 100644 --- a/src/services/group-sync.ts +++ b/src/services/group-sync.ts @@ -350,7 +350,7 @@ export class GroupSyncService { } else { const insertResult = this.dbInstance.prepare( 'INSERT INTO groups (id, community_id, name, active) VALUES (?, ?, ?, TRUE)' - ).run(group.id, group.linkedParent || null, group.subject); + ).run(group.id, (group.linkedParent ?? (process.env.WHATSAPP_COMMUNITY_ID || '')), group.subject); console.log('Added group:', group.id, 'result:', insertResult); added++; } @@ -383,8 +383,7 @@ export class GroupSyncService { // Fetch members for a single group from Evolution API. Uses a robust parser to accept multiple payload shapes. private static async fetchGroupMembersFromAPI(groupId: string): Promise> { - // Evitar llamadas de red en tests - if (process.env.NODE_ENV === 'test') return []; + // En tests se recomienda simular fetch; no retornamos temprano para permitir validar el parser // 1) Intento preferente: endpoint de Evolution "Find Group Members" // Documentación provista: GET /group/participants/{instance} diff --git a/tests/unit/services/group-sync.test.ts b/tests/unit/services/group-sync.test.ts index 10eeb5f..5e2bdcc 100644 --- a/tests/unit/services/group-sync.test.ts +++ b/tests/unit/services/group-sync.test.ts @@ -62,41 +62,54 @@ describe('GroupSyncService', () => { expect(fetchMock).not.toHaveBeenCalled(); }); - it('should return empty result if WHATSAPP_COMMUNITY_ID is missing', async () => { + it('should upsert all groups even if WHATSAPP_COMMUNITY_ID is missing (multicommunity)', async () => { process.env.WHATSAPP_COMMUNITY_ID = ''; const result = await GroupSyncService.syncGroups(); - expect(result).toEqual({ added: 0, updated: 0 }); + expect(result).toEqual({ added: 3, updated: 0 }); }); - it('should filter groups by community ID', async () => { + it('should upsert all groups regardless of community ID (multicommunity)', async () => { // Reset last sync attempt to force a sync GroupSyncService['lastSyncAttempt'] = 0; const result = await GroupSyncService.syncGroups(); - // Verify the correct groups were processed + // Verify all groups were processed expect(result).toEqual({ - added: 1, // group1 should be added - updated: 0 // no existing groups to update + added: 3, + updated: 0 }); // Verify database state - const groups = testDb.query('SELECT * FROM groups').all(); - expect(groups).toHaveLength(1); - - const group = groups[0]; - expect(group.id).toBe('group1'); - expect(group.community_id).toBe('test-community'); - expect(group.name).toBe('Group 1'); - expect(group.active).toBe(1); - expect(group.last_verified).toBeTruthy(); + const groups = testDb.query('SELECT id, community_id, name, active FROM groups').all() as any[]; + expect(groups).toHaveLength(3); + + const map = new Map(groups.map((g: any) => [g.id, g])); + expect(map.get('group1')).toEqual({ + id: 'group1', + community_id: 'test-community', + name: 'Group 1', + active: 1 + }); + expect(map.get('group2')).toEqual({ + id: 'group2', + community_id: 'other-community', + name: 'Group 2', + active: 1 + }); + expect(map.get('group3')).toEqual({ + id: 'group3', + community_id: '', + name: 'Group 3', + active: 1 + }); - // Verify only the matching group was processed + // Verify API was called once expect(fetchMock).toHaveBeenCalledTimes(1); }); - it('should update existing groups', async () => { + it('should update existing groups and insert new ones (multicommunity)', async () => { // Add initial group testDb.exec( "INSERT INTO groups (id, community_id, name, active) VALUES ('group1', 'test-community', 'Old Name', 1)" @@ -104,18 +117,16 @@ describe('GroupSyncService', () => { const result = await GroupSyncService.syncGroups(); expect(result).toEqual({ - added: 0, + added: 2, updated: 1 }); - const group = testDb.query('SELECT * FROM groups WHERE id = ?').get('group1'); - expect(group).toEqual({ - id: 'group1', - community_id: 'test-community', - name: 'Group 1', - active: 1, - last_verified: expect.any(String) - }); + const all = testDb.query('SELECT id, community_id, name, active FROM groups ORDER BY id').all(); + expect(all).toEqual([ + { id: 'group1', community_id: 'test-community', name: 'Group 1', active: 1 }, + { id: 'group2', community_id: 'other-community', name: 'Group 2', active: 1 }, + { id: 'group3', community_id: '', name: 'Group 3', active: 1 } + ]); }); it('should mark non-matching groups as inactive', async () => {