diff --git a/src/Socket/messages-recv.ts b/src/Socket/messages-recv.ts index b8b1244..e4a27b6 100644 --- a/src/Socket/messages-recv.ts +++ b/src/Socket/messages-recv.ts @@ -154,15 +154,13 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => { } const processMessageLocal = async(msg: proto.IWebMessageInfo) => { - const meId = authState.creds.me!.id // process message and emit events const newEvents = await processMessage( msg, { downloadHistory, historyCache, - meId, - accountSettings: authState.creds.accountSettings, + creds: authState.creds, keyStore: authState.keys, logger, treatCiphertextMessagesAsReal diff --git a/src/Types/Auth.ts b/src/Types/Auth.ts index 015f5d5..68db080 100644 --- a/src/Types/Auth.ts +++ b/src/Types/Auth.ts @@ -1,5 +1,6 @@ import type { proto } from '../../WAProto' import type { Contact } from './Contact' +import type { MinimalMessage } from './Message' export type KeyPair = { public: Uint8Array, private: Uint8Array } export type SignedKeyPair = { keyPair: KeyPair, signature: Uint8Array, keyId: number } @@ -45,6 +46,8 @@ export type AuthenticationCreds = SignalCreds & { lastAccountSyncTimestamp?: number platform?: string + + processedHistoryMessages: MinimalMessage[] accountSettings: AccountSettings } diff --git a/src/Types/Chat.ts b/src/Types/Chat.ts index c8fd072..2cf5f85 100644 --- a/src/Types/Chat.ts +++ b/src/Types/Chat.ts @@ -1,4 +1,5 @@ import type { proto } from '../../WAProto' +import type { MinimalMessage } from './Message' /** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */ export type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused' @@ -32,11 +33,12 @@ export type Chat = Omit & { pin?: number | null archive?: boolean } + /** * the last messages in a chat, sorted reverse-chronologically. That is, the latest message should be first in the chat * for MD modifications, the last message in the array (i.e. the earlist message) must be the last message recv in the chat * */ -export type LastMessageList = Pick[] | proto.ISyncActionMessageRange +export type LastMessageList = MinimalMessage[] | proto.ISyncActionMessageRange export type ChatModification = { diff --git a/src/Types/Message.ts b/src/Types/Message.ts index e2e5cdd..df0f87a 100644 --- a/src/Types/Message.ts +++ b/src/Types/Message.ts @@ -188,4 +188,6 @@ export type MediaDecryptionKeyInfo = { iv: Buffer cipherKey: Buffer macKey?: Buffer -} \ No newline at end of file +} + +export type MinimalMessage = Pick \ No newline at end of file diff --git a/src/Utils/auth-utils.ts b/src/Utils/auth-utils.ts index e9e9ca0..0c1bd01 100644 --- a/src/Utils/auth-utils.ts +++ b/src/Utils/auth-utils.ts @@ -121,7 +121,7 @@ export const initAuthCreds = (): AuthenticationCreds => { signedPreKey: signedKeyPair(identityKey, 1), registrationId: generateRegistrationId(), advSecretKey: randomBytes(32).toString('base64'), - + processedHistoryMessages: [], nextPreKeyId: 1, firstUnuploadedPreKeyId: 1, accountSettings: { diff --git a/src/Utils/history.ts b/src/Utils/history.ts index e0510b4..f26a583 100644 --- a/src/Utils/history.ts +++ b/src/Utils/history.ts @@ -22,10 +22,10 @@ export const downloadHistory = async(msg: proto.IHistorySyncNotification) => { } export const processHistoryMessage = (item: proto.IHistorySync, historyCache: Set) => { - const isLatest = historyCache.size === 0 const messages: proto.IWebMessageInfo[] = [] const contacts: Contact[] = [] const chats: Chat[] = [] + switch (item.syncType) { case proto.HistorySync.HistorySyncHistorySyncType.INITIAL_BOOTSTRAP: case proto.HistorySync.HistorySyncHistorySyncType.RECENT: @@ -71,11 +71,13 @@ export const processHistoryMessage = (item: proto.IHistorySync, historyCache: Se break } + const didProcess = !!(chats.length || messages.length || contacts.length) + return { chats, contacts, messages, - isLatest, + didProcess, } } diff --git a/src/Utils/process-message.ts b/src/Utils/process-message.ts index 23a1d80..95135ec 100644 --- a/src/Utils/process-message.ts +++ b/src/Utils/process-message.ts @@ -1,15 +1,14 @@ import type { Logger } from 'pino' import { proto } from '../../WAProto' -import { AccountSettings, BaileysEventMap, Chat, GroupMetadata, ParticipantAction, SignalKeyStoreWithTransaction, WAMessageStubType } from '../Types' +import { AuthenticationCreds, BaileysEventMap, Chat, GroupMetadata, ParticipantAction, SignalKeyStoreWithTransaction, WAMessageStubType } from '../Types' import { downloadAndProcessHistorySyncNotification, normalizeMessageContent, toNumber } from '../Utils' import { areJidsSameUser, jidNormalizedUser } from '../WABinary' type ProcessMessageContext = { historyCache: Set downloadHistory: boolean - meId: string + creds: AuthenticationCreds keyStore: SignalKeyStoreWithTransaction - accountSettings: AccountSettings logger?: Logger treatCiphertextMessagesAsReal?: boolean } @@ -39,8 +38,10 @@ export const cleanMessage = (message: proto.IWebMessageInfo, meId: string) => { const processMessage = async( message: proto.IWebMessageInfo, - { downloadHistory, historyCache, meId, keyStore, accountSettings, logger, treatCiphertextMessagesAsReal }: ProcessMessageContext + { downloadHistory, historyCache, creds, keyStore, logger, treatCiphertextMessagesAsReal }: ProcessMessageContext ) => { + const meId = creds.me!.id + const { accountSettings } = creds const map: Partial> = { } const chat: Partial = { id: jidNormalizedUser(message.key.remoteJid) } @@ -77,7 +78,8 @@ const processMessage = async( logger?.info({ histNotification, id: message.key.id }, 'got history notification') if(downloadHistory) { - const { chats, contacts, messages, isLatest } = await downloadAndProcessHistorySyncNotification(histNotification, historyCache) + const { chats, contacts, messages, didProcess } = await downloadAndProcessHistorySyncNotification(histNotification, historyCache) + const isLatest = historyCache.size === 0 && !creds.processedHistoryMessages?.length if(chats.length) { map['chats.set'] = { chats, isLatest } @@ -90,6 +92,16 @@ const processMessage = async( if(contacts.length) { map['contacts.set'] = { contacts } } + + if(didProcess) { + map['creds.update'] = { + ...(map['creds.update'] || {}), + processedHistoryMessages: [ + ...(creds.processedHistoryMessages || []), + { key: message.key, timestamp: message.messageTimestamp } + ] + } + } } break