feat(chats): sincroniza chats fixados (pin/arquivo) via app-state
Pin/arquivo/mute não vêm no history sync nem em chats.upsert — vivem no app-state do WhatsApp. Adiciona syncChatStates() que faz resyncAppState das collections critical_unblock_low/regular_high/regular (isoladas: uma falha não derruba as outras); os pins chegam como chats.update e já são aplicados em isPinned, subindo os fixados ao topo (ordenação já existente). Roda no pós-conexão e reexecuta (3s/15s/40s) pois as app-state keys chegam após parear. Obs.: depende da engine 'official' (a InfiniteAPI não sincroniza app-state). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+5
@@ -620,6 +620,11 @@ export class WhatsAppConnectionManager {
|
|||||||
})
|
})
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
|
|
||||||
|
// FIXADOS PRIMEIRO: puxa pin/arquivo/mute (app-state) logo e reexecuta,
|
||||||
|
// pois as app-state keys podem chegar alguns segundos após o pareamento.
|
||||||
|
setTimeout(() => handler.syncChatStates().catch(() => {}), 3000)
|
||||||
|
setTimeout(() => handler.syncChatStates().catch(() => {}), 15_000)
|
||||||
|
setTimeout(() => handler.syncChatStates().catch(() => {}), 40_000)
|
||||||
// Busca avatares ausentes após 5s (dá tempo para o sync inicial)
|
// Busca avatares ausentes após 5s (dá tempo para o sync inicial)
|
||||||
setTimeout(() => handler.syncMissingAvatars().catch(() => {}), 5000)
|
setTimeout(() => handler.syncMissingAvatars().catch(() => {}), 5000)
|
||||||
// Renova avatares próximos de expirar após 30s (não compete com syncMissing)
|
// Renova avatares próximos de expirar após 30s (não compete com syncMissing)
|
||||||
|
|||||||
+31
@@ -385,6 +385,37 @@ export class ContactHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puxa o estado de PIN / ARQUIVO / MUTE dos chats via app-state do WhatsApp.
|
||||||
|
*
|
||||||
|
* Esses estados NÃO vêm no history sync comum nem em chats.upsert — vivem na
|
||||||
|
* collection 'regular_high' do app-state. O resyncAppState força o telefone a
|
||||||
|
* reenviá-los; chegam como chats.update {pinned/archived} e são aplicados por
|
||||||
|
* handleChatsUpdate. Sem isto, os chats fixados nunca sobem ao topo da lista.
|
||||||
|
*/
|
||||||
|
async syncChatStates(): Promise<void> {
|
||||||
|
if (!this.sock) return
|
||||||
|
// Pin/arquivo/mute podem viver em diferentes collections do app-state.
|
||||||
|
// Tenta cada uma ISOLADAMENTE: algumas falham com "tried remove, but no
|
||||||
|
// previous op" (estado parcial) — isolar evita que uma derrube as demais.
|
||||||
|
// 'regular_high' é a principal para pin/mute; as outras cobrem variações.
|
||||||
|
const collections = ['critical_unblock_low', 'regular_high', 'regular']
|
||||||
|
let ok = 0
|
||||||
|
for (const collection of collections) {
|
||||||
|
try {
|
||||||
|
await this.sock.resyncAppState([collection] as any, false)
|
||||||
|
ok++
|
||||||
|
logger.info({ instanceId: this.instanceId, collection },
|
||||||
|
'[ContactHandler] app-state sincronizado (pin/arquivo/mute)')
|
||||||
|
} catch (err) {
|
||||||
|
logger.warn({ err, instanceId: this.instanceId, collection },
|
||||||
|
'[ContactHandler] Falha ao sincronizar collection do app-state (não-fatal)')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info({ instanceId: this.instanceId, collectionsOk: ok },
|
||||||
|
'[ContactHandler] Sync de pin/arquivo dos chats concluído')
|
||||||
|
}
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════
|
||||||
// SYNC PÓS-CONEXÃO: AVATARES AUSENTES
|
// SYNC PÓS-CONEXÃO: AVATARES AUSENTES
|
||||||
// ═══════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════
|
||||||
|
|||||||
Reference in New Issue
Block a user