mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
Slint fixes applied
This commit is contained in:
@@ -23,7 +23,7 @@ setInterval(() => {
|
||||
}, 10_000)
|
||||
|
||||
// start a connection
|
||||
const startSock = async () => {
|
||||
const startSock = async() => {
|
||||
const { state, saveCreds } = await useMultiFileAuthState('baileys_auth_info')
|
||||
// fetch latest version of WA Web
|
||||
const { version, isLatest } = await fetchLatestBaileysVersion()
|
||||
@@ -49,7 +49,7 @@ const startSock = async () => {
|
||||
|
||||
store?.bind(sock.ev)
|
||||
|
||||
const sendMessageWTyping = async (msg: AnyMessageContent, jid: string) => {
|
||||
const sendMessageWTyping = async(msg: AnyMessageContent, jid: string) => {
|
||||
await sock.presenceSubscribe(jid)
|
||||
await delay(500)
|
||||
|
||||
@@ -65,15 +65,15 @@ const startSock = async () => {
|
||||
// efficiently in a batch
|
||||
sock.ev.process(
|
||||
// events is a map for event name => event data
|
||||
async (events) => {
|
||||
async(events) => {
|
||||
// something about the connection changed
|
||||
// maybe it closed, or we received all offline message or connection opened
|
||||
if (events['connection.update']) {
|
||||
if(events['connection.update']) {
|
||||
const update = events['connection.update']
|
||||
const { connection, lastDisconnect } = update
|
||||
if (connection === 'close') {
|
||||
if(connection === 'close') {
|
||||
// reconnect if not logged out
|
||||
if ((lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut) {
|
||||
if((lastDisconnect?.error as Boom)?.output?.statusCode !== DisconnectReason.loggedOut) {
|
||||
startSock()
|
||||
} else {
|
||||
console.log('Connection closed. You are logged out.')
|
||||
@@ -84,37 +84,37 @@ const startSock = async () => {
|
||||
}
|
||||
|
||||
// credentials updated -- save them
|
||||
if (events['creds.update']) {
|
||||
if(events['creds.update']) {
|
||||
await saveCreds()
|
||||
}
|
||||
|
||||
if (events['labels.association']) {
|
||||
if(events['labels.association']) {
|
||||
console.log(events['labels.association'])
|
||||
}
|
||||
|
||||
|
||||
if (events['labels.edit']) {
|
||||
if(events['labels.edit']) {
|
||||
console.log(events['labels.edit'])
|
||||
}
|
||||
|
||||
if (events.call) {
|
||||
if(events.call) {
|
||||
console.log('recv call event', events.call)
|
||||
}
|
||||
|
||||
// history received
|
||||
if (events['messaging-history.set']) {
|
||||
if(events['messaging-history.set']) {
|
||||
const { chats, contacts, messages, isLatest } = events['messaging-history.set']
|
||||
console.log(`recv ${chats.length} chats, ${contacts.length} contacts, ${messages.length} msgs (is latest: ${isLatest})`)
|
||||
}
|
||||
|
||||
// received a new message
|
||||
if (events['messages.upsert']) {
|
||||
if(events['messages.upsert']) {
|
||||
const upsert = events['messages.upsert']
|
||||
console.log('recv messages ', JSON.stringify(upsert, undefined, 2))
|
||||
|
||||
if (upsert.type === 'notify') {
|
||||
for (const msg of upsert.messages) {
|
||||
if (!msg.key.fromMe && doReplies) {
|
||||
if(upsert.type === 'notify') {
|
||||
for(const msg of upsert.messages) {
|
||||
if(!msg.key.fromMe && doReplies) {
|
||||
console.log('replying to', msg.key.remoteJid)
|
||||
await sock!.readMessages([msg.key])
|
||||
await sendMessageWTyping({ text: 'Hello there!' }, msg.key.remoteJid!)
|
||||
@@ -124,15 +124,15 @@ const startSock = async () => {
|
||||
}
|
||||
|
||||
// messages updated like status delivered, message deleted etc.
|
||||
if (events['messages.update']) {
|
||||
if(events['messages.update']) {
|
||||
console.log(
|
||||
JSON.stringify(events['messages.update'], undefined, 2)
|
||||
)
|
||||
|
||||
for (const { key, update } of events['messages.update']) {
|
||||
if (update.pollUpdates) {
|
||||
for(const { key, update } of events['messages.update']) {
|
||||
if(update.pollUpdates) {
|
||||
const pollCreation = await getMessage(key)
|
||||
if (pollCreation) {
|
||||
if(pollCreation) {
|
||||
console.log(
|
||||
'got poll update, aggregation: ',
|
||||
getAggregateVotesInPollMessage({
|
||||
@@ -145,25 +145,25 @@ const startSock = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (events['message-receipt.update']) {
|
||||
if(events['message-receipt.update']) {
|
||||
console.log(events['message-receipt.update'])
|
||||
}
|
||||
|
||||
if (events['messages.reaction']) {
|
||||
if(events['messages.reaction']) {
|
||||
console.log(events['messages.reaction'])
|
||||
}
|
||||
|
||||
if (events['presence.update']) {
|
||||
if(events['presence.update']) {
|
||||
console.log(events['presence.update'])
|
||||
}
|
||||
|
||||
if (events['chats.update']) {
|
||||
if(events['chats.update']) {
|
||||
console.log(events['chats.update'])
|
||||
}
|
||||
|
||||
if (events['contacts.update']) {
|
||||
for (const contact of events['contacts.update']) {
|
||||
if (typeof contact.imgUrl !== 'undefined') {
|
||||
if(events['contacts.update']) {
|
||||
for(const contact of events['contacts.update']) {
|
||||
if(typeof contact.imgUrl !== 'undefined') {
|
||||
const newUrl = contact.imgUrl === null
|
||||
? null
|
||||
: await sock!.profilePictureUrl(contact.id!).catch(() => null)
|
||||
@@ -174,7 +174,7 @@ const startSock = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
if (events['chats.delete']) {
|
||||
if(events['chats.delete']) {
|
||||
console.log('chats deleted ', events['chats.delete'])
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ const startSock = async () => {
|
||||
return sock
|
||||
|
||||
async function getMessage(key: WAMessageKey): Promise<WAMessageContent | undefined> {
|
||||
if (store) {
|
||||
if(store) {
|
||||
const msg = await store.loadMessage(key.remoteJid!, key.id!)
|
||||
return msg?.message || undefined
|
||||
}
|
||||
|
||||
@@ -37,13 +37,13 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const processingMutex = makeMutex()
|
||||
|
||||
/** helper function to fetch the given app state sync key */
|
||||
const getAppStateSyncKey = async (keyId: string) => {
|
||||
const getAppStateSyncKey = async(keyId: string) => {
|
||||
const { [keyId]: key } = await authState.keys.get('app-state-sync-key', [keyId])
|
||||
return key
|
||||
}
|
||||
|
||||
const fetchPrivacySettings = async (force: boolean = false) => {
|
||||
if (!privacySettings || force) {
|
||||
const fetchPrivacySettings = async(force: boolean = false) => {
|
||||
if(!privacySettings || force) {
|
||||
const { content } = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -62,7 +62,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** helper function to run a privacy IQ query */
|
||||
const privacyQuery = async (name: string, value: string) => {
|
||||
const privacyQuery = async(name: string, value: string) => {
|
||||
await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -83,31 +83,31 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
})
|
||||
}
|
||||
|
||||
const updateLastSeenPrivacy = async (value: WAPrivacyValue) => {
|
||||
const updateLastSeenPrivacy = async(value: WAPrivacyValue) => {
|
||||
await privacyQuery('last', value)
|
||||
}
|
||||
|
||||
const updateOnlinePrivacy = async (value: WAPrivacyOnlineValue) => {
|
||||
const updateOnlinePrivacy = async(value: WAPrivacyOnlineValue) => {
|
||||
await privacyQuery('online', value)
|
||||
}
|
||||
|
||||
const updateProfilePicturePrivacy = async (value: WAPrivacyValue) => {
|
||||
const updateProfilePicturePrivacy = async(value: WAPrivacyValue) => {
|
||||
await privacyQuery('profile', value)
|
||||
}
|
||||
|
||||
const updateStatusPrivacy = async (value: WAPrivacyValue) => {
|
||||
const updateStatusPrivacy = async(value: WAPrivacyValue) => {
|
||||
await privacyQuery('status', value)
|
||||
}
|
||||
|
||||
const updateReadReceiptsPrivacy = async (value: WAReadReceiptsValue) => {
|
||||
const updateReadReceiptsPrivacy = async(value: WAReadReceiptsValue) => {
|
||||
await privacyQuery('readreceipts', value)
|
||||
}
|
||||
|
||||
const updateGroupsAddPrivacy = async (value: WAPrivacyValue) => {
|
||||
const updateGroupsAddPrivacy = async(value: WAPrivacyValue) => {
|
||||
await privacyQuery('groupadd', value)
|
||||
}
|
||||
|
||||
const updateDefaultDisappearingMode = async (duration: number) => {
|
||||
const updateDefaultDisappearingMode = async(duration: number) => {
|
||||
await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -125,7 +125,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** helper function to run a generic IQ query */
|
||||
const interactiveQuery = async (userNodes: BinaryNode[], queryNode: BinaryNode) => {
|
||||
const interactiveQuery = async(userNodes: BinaryNode[], queryNode: BinaryNode) => {
|
||||
const result = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -166,7 +166,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
return users
|
||||
}
|
||||
|
||||
const onWhatsApp = async (...jids: string[]) => {
|
||||
const onWhatsApp = async(...jids: string[]) => {
|
||||
const results = await interactiveQuery(
|
||||
[
|
||||
{
|
||||
@@ -190,12 +190,12 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}).filter(item => item.exists)
|
||||
}
|
||||
|
||||
const fetchStatus = async (jid: string) => {
|
||||
const fetchStatus = async(jid: string) => {
|
||||
const [result] = await interactiveQuery(
|
||||
[{ tag: 'user', attrs: { jid } }],
|
||||
{ tag: 'status', attrs: {} }
|
||||
)
|
||||
if (result) {
|
||||
if(result) {
|
||||
const status = getBinaryNodeChild(result, 'status')
|
||||
return {
|
||||
status: status?.content!.toString(),
|
||||
@@ -205,7 +205,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** update the profile picture for yourself or a group */
|
||||
const updateProfilePicture = async (jid: string, content: WAMediaUpload) => {
|
||||
const updateProfilePicture = async(jid: string, content: WAMediaUpload) => {
|
||||
const { img } = await generateProfilePicture(content)
|
||||
await query({
|
||||
tag: 'iq',
|
||||
@@ -225,7 +225,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** remove the profile picture for yourself or a group */
|
||||
const removeProfilePicture = async (jid: string) => {
|
||||
const removeProfilePicture = async(jid: string) => {
|
||||
await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -237,7 +237,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** update the profile status for yourself */
|
||||
const updateProfileStatus = async (status: string) => {
|
||||
const updateProfileStatus = async(status: string) => {
|
||||
await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -255,11 +255,11 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
})
|
||||
}
|
||||
|
||||
const updateProfileName = async (name: string) => {
|
||||
const updateProfileName = async(name: string) => {
|
||||
await chatModify({ pushNameSetting: name }, '')
|
||||
}
|
||||
|
||||
const fetchBlocklist = async () => {
|
||||
const fetchBlocklist = async() => {
|
||||
const result = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -274,7 +274,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
.map(n => n.attrs.jid)
|
||||
}
|
||||
|
||||
const updateBlockStatus = async (jid: string, action: 'block' | 'unblock') => {
|
||||
const updateBlockStatus = async(jid: string, action: 'block' | 'unblock') => {
|
||||
await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -294,7 +294,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
})
|
||||
}
|
||||
|
||||
const getBusinessProfile = async (jid: string): Promise<WABusinessProfile | void> => {
|
||||
const getBusinessProfile = async(jid: string): Promise<WABusinessProfile | void> => {
|
||||
const results = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -314,7 +314,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
|
||||
const profileNode = getBinaryNodeChild(results, 'business_profile')
|
||||
const profiles = getBinaryNodeChild(profileNode, 'profile')
|
||||
if (profiles) {
|
||||
if(profiles) {
|
||||
const address = getBinaryNodeChild(profiles, 'address')
|
||||
const description = getBinaryNodeChild(profiles, 'description')
|
||||
const website = getBinaryNodeChild(profiles, 'website')
|
||||
@@ -340,7 +340,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
}
|
||||
|
||||
const updateAccountSyncTimestamp = async (fromTimestamp: number | string) => {
|
||||
const updateAccountSyncTimestamp = async(fromTimestamp: number | string) => {
|
||||
logger.info({ fromTimestamp }, 'requesting account sync')
|
||||
await sendNode({
|
||||
tag: 'iq',
|
||||
@@ -376,30 +376,30 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
}
|
||||
|
||||
const resyncAppState = ev.createBufferedFunction(async (collections: readonly WAPatchName[], isInitialSync: boolean) => {
|
||||
const resyncAppState = ev.createBufferedFunction(async(collections: readonly WAPatchName[], isInitialSync: boolean) => {
|
||||
// we use this to determine which events to fire
|
||||
// otherwise when we resync from scratch -- all notifications will fire
|
||||
const initialVersionMap: { [T in WAPatchName]?: number } = {}
|
||||
const globalMutationMap: ChatMutationMap = {}
|
||||
|
||||
await authState.keys.transaction(
|
||||
async () => {
|
||||
async() => {
|
||||
const collectionsToHandle = new Set<string>(collections)
|
||||
// in case something goes wrong -- ensure we don't enter a loop that cannot be exited from
|
||||
const attemptsMap: { [T in WAPatchName]?: number } = {}
|
||||
// keep executing till all collections are done
|
||||
// sometimes a single patch request will not return all the patches (God knows why)
|
||||
// so we fetch till they're all done (this is determined by the "has_more_patches" flag)
|
||||
while (collectionsToHandle.size) {
|
||||
while(collectionsToHandle.size) {
|
||||
const states = {} as { [T in WAPatchName]: LTHashState }
|
||||
const nodes: BinaryNode[] = []
|
||||
|
||||
for (const name of collectionsToHandle) {
|
||||
for(const name of collectionsToHandle) {
|
||||
const result = await authState.keys.get('app-state-sync-version', [name])
|
||||
let state = result[name]
|
||||
|
||||
if (state) {
|
||||
if (typeof initialVersionMap[name] === 'undefined') {
|
||||
if(state) {
|
||||
if(typeof initialVersionMap[name] === 'undefined') {
|
||||
initialVersionMap[name] = state.version
|
||||
}
|
||||
} else {
|
||||
@@ -439,11 +439,11 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
|
||||
// extract from binary node
|
||||
const decoded = await extractSyncdPatches(result, config?.options)
|
||||
for (const key in decoded) {
|
||||
for(const key in decoded) {
|
||||
const name = key as WAPatchName
|
||||
const { patches, hasMorePatches, snapshot } = decoded[name]
|
||||
try {
|
||||
if (snapshot) {
|
||||
if(snapshot) {
|
||||
const { state: newState, mutationMap } = await decodeSyncdSnapshot(
|
||||
name,
|
||||
snapshot,
|
||||
@@ -460,7 +460,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
// only process if there are syncd patches
|
||||
if (patches.length) {
|
||||
if(patches.length) {
|
||||
const { state: newState, mutationMap } = await decodePatches(
|
||||
name,
|
||||
patches,
|
||||
@@ -480,12 +480,12 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
Object.assign(globalMutationMap, mutationMap)
|
||||
}
|
||||
|
||||
if (hasMorePatches) {
|
||||
if(hasMorePatches) {
|
||||
logger.info(`${name} has more patches...`)
|
||||
} else { // collection is done with sync
|
||||
collectionsToHandle.delete(name)
|
||||
}
|
||||
} catch (error) {
|
||||
} catch(error) {
|
||||
// if retry attempts overshoot
|
||||
// or key not found
|
||||
const isIrrecoverableError = attemptsMap[name]! >= MAX_SYNC_ATTEMPTS
|
||||
@@ -499,7 +499,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
// increment number of retries
|
||||
attemptsMap[name] = (attemptsMap[name] || 0) + 1
|
||||
|
||||
if (isIrrecoverableError) {
|
||||
if(isIrrecoverableError) {
|
||||
// stop retrying
|
||||
collectionsToHandle.delete(name)
|
||||
}
|
||||
@@ -510,7 +510,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
)
|
||||
|
||||
const { onMutation } = newAppStateChunkHandler(isInitialSync)
|
||||
for (const key in globalMutationMap) {
|
||||
for(const key in globalMutationMap) {
|
||||
onMutation(globalMutationMap[key])
|
||||
}
|
||||
})
|
||||
@@ -520,7 +520,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
* type = "preview" for a low res picture
|
||||
* type = "image for the high res picture"
|
||||
*/
|
||||
const profilePictureUrl = async (jid: string, type: 'preview' | 'image' = 'preview', timeoutMs?: number) => {
|
||||
const profilePictureUrl = async(jid: string, type: 'preview' | 'image' = 'preview', timeoutMs?: number) => {
|
||||
jid = jidNormalizedUser(jid)
|
||||
const result = await query({
|
||||
tag: 'iq',
|
||||
@@ -537,10 +537,10 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
return child?.attrs?.url
|
||||
}
|
||||
|
||||
const sendPresenceUpdate = async (type: WAPresence, toJid?: string) => {
|
||||
const sendPresenceUpdate = async(type: WAPresence, toJid?: string) => {
|
||||
const me = authState.creds.me!
|
||||
if (type === 'available' || type === 'unavailable') {
|
||||
if (!me!.name) {
|
||||
if(type === 'available' || type === 'unavailable') {
|
||||
if(!me!.name) {
|
||||
logger.warn('no name present, ignoring presence update request...')
|
||||
return
|
||||
}
|
||||
@@ -600,23 +600,23 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const jid = attrs.from
|
||||
const participant = attrs.participant || attrs.from
|
||||
|
||||
if (shouldIgnoreJid(jid)) {
|
||||
if(shouldIgnoreJid(jid)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (tag === 'presence') {
|
||||
if(tag === 'presence') {
|
||||
presence = {
|
||||
lastKnownPresence: attrs.type === 'unavailable' ? 'unavailable' : 'available',
|
||||
lastSeen: attrs.last && attrs.last !== 'deny' ? +attrs.last : undefined
|
||||
}
|
||||
} else if (Array.isArray(content)) {
|
||||
} else if(Array.isArray(content)) {
|
||||
const [firstChild] = content
|
||||
let type = firstChild.tag as WAPresence
|
||||
if (type === 'paused') {
|
||||
if(type === 'paused') {
|
||||
type = 'available'
|
||||
}
|
||||
|
||||
if (firstChild.attrs?.media === 'audio') {
|
||||
if(firstChild.attrs?.media === 'audio') {
|
||||
type = 'recording'
|
||||
}
|
||||
|
||||
@@ -625,15 +625,15 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
logger.error({ tag, attrs, content }, 'recv invalid presence node')
|
||||
}
|
||||
|
||||
if (presence) {
|
||||
if(presence) {
|
||||
ev.emit('presence.update', { id: jid, presences: { [participant]: presence } })
|
||||
}
|
||||
}
|
||||
|
||||
const appPatch = async (patchCreate: WAPatchCreate) => {
|
||||
const appPatch = async(patchCreate: WAPatchCreate) => {
|
||||
const name = patchCreate.type
|
||||
const myAppStateKeyId = authState.creds.myAppStateKeyId
|
||||
if (!myAppStateKeyId) {
|
||||
if(!myAppStateKeyId) {
|
||||
throw new Boom('App state key not present!', { statusCode: 400 })
|
||||
}
|
||||
|
||||
@@ -641,9 +641,9 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
let encodeResult: { patch: proto.ISyncdPatch, state: LTHashState }
|
||||
|
||||
await processingMutex.mutex(
|
||||
async () => {
|
||||
async() => {
|
||||
await authState.keys.transaction(
|
||||
async () => {
|
||||
async() => {
|
||||
logger.debug({ patch: patchCreate }, 'applying app patch')
|
||||
|
||||
await resyncAppState([name], false)
|
||||
@@ -698,7 +698,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
)
|
||||
|
||||
if (config.emitOwnEvents) {
|
||||
if(config.emitOwnEvents) {
|
||||
const { onMutation } = newAppStateChunkHandler(false)
|
||||
const { mutationMap } = await decodePatches(
|
||||
name,
|
||||
@@ -709,14 +709,14 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
undefined,
|
||||
logger,
|
||||
)
|
||||
for (const key in mutationMap) {
|
||||
for(const key in mutationMap) {
|
||||
onMutation(mutationMap[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** sending abt props may fix QR scan fail if server expects */
|
||||
const fetchAbt = async () => {
|
||||
const fetchAbt = async() => {
|
||||
const abtNode = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -732,7 +732,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const propsNode = getBinaryNodeChild(abtNode, 'props')
|
||||
|
||||
let props: { [_: string]: string } = {}
|
||||
if (propsNode) {
|
||||
if(propsNode) {
|
||||
props = reduceBinaryNodeToDictionary(propsNode, 'prop')
|
||||
}
|
||||
|
||||
@@ -742,7 +742,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
/** sending non-abt props may fix QR scan fail if server expects */
|
||||
const fetchProps = async () => {
|
||||
const fetchProps = async() => {
|
||||
const resultNode = await query({
|
||||
tag: 'iq',
|
||||
attrs: {
|
||||
@@ -758,7 +758,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
const propsNode = getBinaryNodeChild(resultNode, 'props')
|
||||
|
||||
let props: { [_: string]: string } = {}
|
||||
if (propsNode) {
|
||||
if(propsNode) {
|
||||
props = reduceBinaryNodeToDictionary(propsNode, 'prop')
|
||||
}
|
||||
|
||||
@@ -827,7 +827,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
* queries need to be fired on connection open
|
||||
* help ensure parity with WA Web
|
||||
* */
|
||||
const executeInitQueries = async () => {
|
||||
const executeInitQueries = async() => {
|
||||
await Promise.all([
|
||||
fetchAbt(),
|
||||
fetchProps(),
|
||||
@@ -836,19 +836,19 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
])
|
||||
}
|
||||
|
||||
const upsertMessage = ev.createBufferedFunction(async (msg: WAMessage, type: MessageUpsertType) => {
|
||||
const upsertMessage = ev.createBufferedFunction(async(msg: WAMessage, type: MessageUpsertType) => {
|
||||
ev.emit('messages.upsert', { messages: [msg], type })
|
||||
|
||||
if (!!msg.pushName) {
|
||||
if(!!msg.pushName) {
|
||||
let jid = msg.key.fromMe ? authState.creds.me!.id : (msg.key.participant || msg.key.remoteJid)
|
||||
jid = jidNormalizedUser(jid!)
|
||||
|
||||
if (!msg.key.fromMe) {
|
||||
if(!msg.key.fromMe) {
|
||||
ev.emit('contacts.update', [{ id: jid, notify: msg.pushName, verifiedName: msg.verifiedBizName! }])
|
||||
}
|
||||
|
||||
// update our pushname too
|
||||
if (msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
|
||||
if(msg.key.fromMe && msg.pushName && authState.creds.me?.name !== msg.pushName) {
|
||||
ev.emit('creds.update', { me: { ...authState.creds.me!, name: msg.pushName! } })
|
||||
}
|
||||
}
|
||||
@@ -861,14 +861,14 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
)
|
||||
: false
|
||||
|
||||
if (historyMsg && !authState.creds.myAppStateKeyId) {
|
||||
if(historyMsg && !authState.creds.myAppStateKeyId) {
|
||||
logger.warn('skipping app state sync, as myAppStateKeyId is not set')
|
||||
pendingAppStateSync = true
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
(async () => {
|
||||
if (
|
||||
(async() => {
|
||||
if(
|
||||
historyMsg
|
||||
&& authState.creds.myAppStateKeyId
|
||||
) {
|
||||
@@ -890,7 +890,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
)
|
||||
])
|
||||
|
||||
if (
|
||||
if(
|
||||
msg.message?.protocolMessage?.appStateSyncKeyShare
|
||||
&& pendingAppStateSync
|
||||
) {
|
||||
@@ -899,14 +899,14 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
}
|
||||
|
||||
async function doAppStateSync() {
|
||||
if (!authState.creds.accountSyncCounter) {
|
||||
if(!authState.creds.accountSyncCounter) {
|
||||
logger.info('doing initial app state sync')
|
||||
await resyncAppState(ALL_WA_PATCH_NAMES, true)
|
||||
|
||||
const accountSyncCounter = (authState.creds.accountSyncCounter || 0) + 1
|
||||
ev.emit('creds.update', { accountSyncCounter })
|
||||
|
||||
if (needToFlushWithAppStateSync) {
|
||||
if(needToFlushWithAppStateSync) {
|
||||
logger.debug('flushing with app state sync')
|
||||
ev.flush()
|
||||
}
|
||||
@@ -917,31 +917,31 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
ws.on('CB:presence', handlePresenceUpdate)
|
||||
ws.on('CB:chatstate', handlePresenceUpdate)
|
||||
|
||||
ws.on('CB:ib,,dirty', async (node: BinaryNode) => {
|
||||
ws.on('CB:ib,,dirty', async(node: BinaryNode) => {
|
||||
const { attrs } = getBinaryNodeChild(node, 'dirty')!
|
||||
const type = attrs.type
|
||||
switch (type) {
|
||||
case 'account_sync':
|
||||
if (attrs.timestamp) {
|
||||
let { lastAccountSyncTimestamp } = authState.creds
|
||||
if (lastAccountSyncTimestamp) {
|
||||
await updateAccountSyncTimestamp(lastAccountSyncTimestamp)
|
||||
}
|
||||
|
||||
lastAccountSyncTimestamp = +attrs.timestamp
|
||||
ev.emit('creds.update', { lastAccountSyncTimestamp })
|
||||
case 'account_sync':
|
||||
if(attrs.timestamp) {
|
||||
let { lastAccountSyncTimestamp } = authState.creds
|
||||
if(lastAccountSyncTimestamp) {
|
||||
await updateAccountSyncTimestamp(lastAccountSyncTimestamp)
|
||||
}
|
||||
|
||||
break
|
||||
default:
|
||||
logger.info({ node }, 'received unknown sync')
|
||||
break
|
||||
lastAccountSyncTimestamp = +attrs.timestamp
|
||||
ev.emit('creds.update', { lastAccountSyncTimestamp })
|
||||
}
|
||||
|
||||
break
|
||||
default:
|
||||
logger.info({ node }, 'received unknown sync')
|
||||
break
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('connection.update', ({ connection, receivedPendingNotifications }) => {
|
||||
if (connection === 'open') {
|
||||
if (fireInitQueries) {
|
||||
if(connection === 'open') {
|
||||
if(fireInitQueries) {
|
||||
executeInitQueries()
|
||||
.catch(
|
||||
error => onUnexpectedError(error, 'init queries')
|
||||
@@ -954,11 +954,11 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
)
|
||||
}
|
||||
|
||||
if (receivedPendingNotifications) {
|
||||
if(receivedPendingNotifications) {
|
||||
// if we don't have the app state key
|
||||
// we keep buffering events until we finally have
|
||||
// the key and can sync the messages
|
||||
if (!authState.creds?.myAppStateKeyId) {
|
||||
if(!authState.creds?.myAppStateKeyId) {
|
||||
ev.buffer()
|
||||
needToFlushWithAppStateSync = true
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ export default (
|
||||
const labelAssociations = new KeyedDB<LabelAssociation, string>(labelAssociationKey, labelAssociationKey.key)
|
||||
|
||||
const assertMessageList = (jid: string) => {
|
||||
if (!messages[jid]) {
|
||||
if(!messages[jid]) {
|
||||
messages[jid] = makeMessagesDictionary()
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ export default (
|
||||
|
||||
const contactsUpsert = (newContacts: Contact[]) => {
|
||||
const oldContacts = new Set(Object.keys(contacts))
|
||||
for (const contact of newContacts) {
|
||||
for(const contact of newContacts) {
|
||||
oldContacts.delete(contact.id)
|
||||
contacts[contact.id] = Object.assign(
|
||||
contacts[contact.id] || {},
|
||||
@@ -112,7 +112,7 @@ export default (
|
||||
}
|
||||
|
||||
const labelsUpsert = (newLabels: Label[]) => {
|
||||
for (const label of newLabels) {
|
||||
for(const label of newLabels) {
|
||||
labels.upsertById(label.id, label)
|
||||
}
|
||||
}
|
||||
@@ -134,10 +134,10 @@ export default (
|
||||
messages: newMessages,
|
||||
isLatest
|
||||
}) => {
|
||||
if (isLatest) {
|
||||
if(isLatest) {
|
||||
chats.clear()
|
||||
|
||||
for (const id in messages) {
|
||||
for(const id in messages) {
|
||||
delete messages[id]
|
||||
}
|
||||
}
|
||||
@@ -146,13 +146,13 @@ export default (
|
||||
logger.debug({ chatsAdded }, 'synced chats')
|
||||
|
||||
const oldContacts = contactsUpsert(newContacts)
|
||||
for (const jid of oldContacts) {
|
||||
for(const jid of oldContacts) {
|
||||
delete contacts[jid]
|
||||
}
|
||||
|
||||
logger.debug({ deletedContacts: oldContacts.size, newContacts }, 'synced contacts')
|
||||
|
||||
for (const msg of newMessages) {
|
||||
for(const msg of newMessages) {
|
||||
const jid = msg.key.remoteJid!
|
||||
const list = assertMessageList(jid)
|
||||
list.upsert(msg, 'prepend')
|
||||
@@ -162,8 +162,8 @@ export default (
|
||||
})
|
||||
|
||||
ev.on('contacts.update', updates => {
|
||||
for (const update of updates) {
|
||||
if (contacts[update.id!]) {
|
||||
for(const update of updates) {
|
||||
if(contacts[update.id!]) {
|
||||
Object.assign(contacts[update.id!], update)
|
||||
} else {
|
||||
logger.debug({ update }, 'got update for non-existant contact')
|
||||
@@ -174,28 +174,28 @@ export default (
|
||||
chats.upsert(...newChats)
|
||||
})
|
||||
ev.on('chats.update', updates => {
|
||||
for (let update of updates) {
|
||||
for(let update of updates) {
|
||||
const result = chats.update(update.id!, chat => {
|
||||
if (update.unreadCount! > 0) {
|
||||
if(update.unreadCount! > 0) {
|
||||
update = { ...update }
|
||||
update.unreadCount = (chat.unreadCount || 0) + update.unreadCount!
|
||||
}
|
||||
|
||||
Object.assign(chat, update)
|
||||
})
|
||||
if (!result) {
|
||||
if(!result) {
|
||||
logger.debug({ update }, 'got update for non-existant chat')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('labels.edit', (label: Label) => {
|
||||
if (label.deleted) {
|
||||
if(label.deleted) {
|
||||
return labels.deleteById(label.id)
|
||||
}
|
||||
|
||||
// WhatsApp can store only up to 20 labels
|
||||
if (labels.count() < 20) {
|
||||
if(labels.count() < 20) {
|
||||
return labels.upsertById(label.id, label)
|
||||
}
|
||||
|
||||
@@ -204,14 +204,14 @@ export default (
|
||||
|
||||
ev.on('labels.association', ({ type, association }) => {
|
||||
switch (type) {
|
||||
case 'add':
|
||||
labelAssociations.upsert(association)
|
||||
break
|
||||
case 'remove':
|
||||
labelAssociations.delete(association)
|
||||
break
|
||||
default:
|
||||
console.error(`unknown operation type [${type}]`)
|
||||
case 'add':
|
||||
labelAssociations.upsert(association)
|
||||
break
|
||||
case 'remove':
|
||||
labelAssociations.delete(association)
|
||||
break
|
||||
default:
|
||||
console.error(`unknown operation type [${type}]`)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -220,52 +220,52 @@ export default (
|
||||
Object.assign(presences[id], update)
|
||||
})
|
||||
ev.on('chats.delete', deletions => {
|
||||
for (const item of deletions) {
|
||||
for(const item of deletions) {
|
||||
chats.deleteById(item)
|
||||
}
|
||||
})
|
||||
ev.on('messages.upsert', ({ messages: newMessages, type }) => {
|
||||
switch (type) {
|
||||
case 'append':
|
||||
case 'notify':
|
||||
for (const msg of newMessages) {
|
||||
const jid = jidNormalizedUser(msg.key.remoteJid!)
|
||||
const list = assertMessageList(jid)
|
||||
list.upsert(msg, 'append')
|
||||
case 'append':
|
||||
case 'notify':
|
||||
for(const msg of newMessages) {
|
||||
const jid = jidNormalizedUser(msg.key.remoteJid!)
|
||||
const list = assertMessageList(jid)
|
||||
list.upsert(msg, 'append')
|
||||
|
||||
if (type === 'notify') {
|
||||
if (!chats.get(jid)) {
|
||||
ev.emit('chats.upsert', [
|
||||
{
|
||||
id: jid,
|
||||
conversationTimestamp: toNumber(msg.messageTimestamp),
|
||||
unreadCount: 1
|
||||
}
|
||||
])
|
||||
}
|
||||
if(type === 'notify') {
|
||||
if(!chats.get(jid)) {
|
||||
ev.emit('chats.upsert', [
|
||||
{
|
||||
id: jid,
|
||||
conversationTimestamp: toNumber(msg.messageTimestamp),
|
||||
unreadCount: 1
|
||||
}
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
break
|
||||
}
|
||||
})
|
||||
ev.on('messages.update', updates => {
|
||||
for (const { update, key } of updates) {
|
||||
for(const { update, key } of updates) {
|
||||
const list = assertMessageList(key.remoteJid!)
|
||||
const result = list.updateAssign(key.id!, update)
|
||||
if (!result) {
|
||||
if(!result) {
|
||||
logger.debug({ update }, 'got update for non-existent message')
|
||||
}
|
||||
}
|
||||
})
|
||||
ev.on('messages.delete', item => {
|
||||
if ('all' in item) {
|
||||
if('all' in item) {
|
||||
const list = messages[item.jid]
|
||||
list?.clear()
|
||||
} else {
|
||||
const jid = item.keys[0].remoteJid!
|
||||
const list = messages[jid]
|
||||
if (list) {
|
||||
if(list) {
|
||||
const idSet = new Set(item.keys.map(k => k.id))
|
||||
list.filter(m => !idSet.has(m.key.id))
|
||||
}
|
||||
@@ -273,9 +273,9 @@ export default (
|
||||
})
|
||||
|
||||
ev.on('groups.update', updates => {
|
||||
for (const update of updates) {
|
||||
for(const update of updates) {
|
||||
const id = update.id!
|
||||
if (groupMetadata[id]) {
|
||||
if(groupMetadata[id]) {
|
||||
Object.assign(groupMetadata[id], update)
|
||||
} else {
|
||||
logger.debug({ update }, 'got update for non-existant group metadata')
|
||||
@@ -285,42 +285,42 @@ export default (
|
||||
|
||||
ev.on('group-participants.update', ({ id, participants, action }) => {
|
||||
const metadata = groupMetadata[id]
|
||||
if (metadata) {
|
||||
if(metadata) {
|
||||
switch (action) {
|
||||
case 'add':
|
||||
metadata.participants.push(...participants.map(id => ({ id, isAdmin: false, isSuperAdmin: false })))
|
||||
break
|
||||
case 'demote':
|
||||
case 'promote':
|
||||
for (const participant of metadata.participants) {
|
||||
if (participants.includes(participant.id)) {
|
||||
participant.isAdmin = action === 'promote'
|
||||
}
|
||||
case 'add':
|
||||
metadata.participants.push(...participants.map(id => ({ id, isAdmin: false, isSuperAdmin: false })))
|
||||
break
|
||||
case 'demote':
|
||||
case 'promote':
|
||||
for(const participant of metadata.participants) {
|
||||
if(participants.includes(participant.id)) {
|
||||
participant.isAdmin = action === 'promote'
|
||||
}
|
||||
}
|
||||
|
||||
break
|
||||
case 'remove':
|
||||
metadata.participants = metadata.participants.filter(p => !participants.includes(p.id))
|
||||
break
|
||||
break
|
||||
case 'remove':
|
||||
metadata.participants = metadata.participants.filter(p => !participants.includes(p.id))
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('message-receipt.update', updates => {
|
||||
for (const { key, receipt } of updates) {
|
||||
for(const { key, receipt } of updates) {
|
||||
const obj = messages[key.remoteJid!]
|
||||
const msg = obj?.get(key.id!)
|
||||
if (msg) {
|
||||
if(msg) {
|
||||
updateMessageWithReceipt(msg, receipt)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ev.on('messages.reaction', (reactions) => {
|
||||
for (const { key, reaction } of reactions) {
|
||||
for(const { key, reaction } of reactions) {
|
||||
const obj = messages[key.remoteJid!]
|
||||
const msg = obj?.get(key.id!)
|
||||
if (msg) {
|
||||
if(msg) {
|
||||
updateMessageWithReaction(msg, reaction)
|
||||
}
|
||||
}
|
||||
@@ -335,20 +335,14 @@ export default (
|
||||
labelAssociations
|
||||
})
|
||||
|
||||
const fromJSON = (json: {
|
||||
chats: Chat[],
|
||||
contacts: { [id: string]: Contact },
|
||||
messages: { [id: string]: WAMessage[] },
|
||||
labels: { [labelId: string]: Label },
|
||||
labelAssociations: LabelAssociation[]
|
||||
}) => {
|
||||
const fromJSON = (json: {chats: Chat[], contacts: { [id: string]: Contact }, messages: { [id: string]: WAMessage[] }, labels: { [labelId: string]: Label }, labelAssociations: LabelAssociation[]}) => {
|
||||
chats.upsert(...json.chats)
|
||||
labelAssociations.upsert(...json.labelAssociations || [])
|
||||
contactsUpsert(Object.values(json.contacts))
|
||||
labelsUpsert(Object.values(json.labels || {}))
|
||||
for (const jid in json.messages) {
|
||||
for(const jid in json.messages) {
|
||||
const list = assertMessageList(jid)
|
||||
for (const msg of json.messages[jid]) {
|
||||
for(const msg of json.messages[jid]) {
|
||||
list.upsert(proto.WebMessageInfo.fromObject(msg), 'append')
|
||||
}
|
||||
}
|
||||
@@ -366,15 +360,15 @@ export default (
|
||||
labelAssociations,
|
||||
bind,
|
||||
/** loads messages from the store, if not found -- uses the legacy connection */
|
||||
loadMessages: async (jid: string, count: number, cursor: WAMessageCursor) => {
|
||||
loadMessages: async(jid: string, count: number, cursor: WAMessageCursor) => {
|
||||
const list = assertMessageList(jid)
|
||||
const mode = !cursor || 'before' in cursor ? 'before' : 'after'
|
||||
const cursorKey = !!cursor ? ('before' in cursor ? cursor.before : cursor.after) : undefined
|
||||
const cursorValue = cursorKey ? list.get(cursorKey.id!) : undefined
|
||||
|
||||
let messages: WAMessage[]
|
||||
if (list && mode === 'before' && (!cursorKey || cursorValue)) {
|
||||
if (cursorValue) {
|
||||
if(list && mode === 'before' && (!cursorKey || cursorValue)) {
|
||||
if(cursorValue) {
|
||||
const msgIdx = list.array.findIndex(m => m.key.id === cursorKey?.id)
|
||||
messages = list.array.slice(0, msgIdx)
|
||||
} else {
|
||||
@@ -382,7 +376,7 @@ export default (
|
||||
}
|
||||
|
||||
const diff = count - messages.length
|
||||
if (diff < 0) {
|
||||
if(diff < 0) {
|
||||
messages = messages.slice(-count) // get the last X messages
|
||||
}
|
||||
} else {
|
||||
@@ -423,27 +417,27 @@ export default (
|
||||
return associations.map(({ labelId }) => labelId)
|
||||
|
||||
},
|
||||
loadMessage: async (jid: string, id: string) => messages[jid]?.get(id),
|
||||
mostRecentMessage: async (jid: string) => {
|
||||
loadMessage: async(jid: string, id: string) => messages[jid]?.get(id),
|
||||
mostRecentMessage: async(jid: string) => {
|
||||
const message: WAMessage | undefined = messages[jid]?.array.slice(-1)[0]
|
||||
return message
|
||||
},
|
||||
fetchImageUrl: async (jid: string, sock: WASocket | undefined) => {
|
||||
fetchImageUrl: async(jid: string, sock: WASocket | undefined) => {
|
||||
const contact = contacts[jid]
|
||||
if (!contact) {
|
||||
if(!contact) {
|
||||
return sock?.profilePictureUrl(jid)
|
||||
}
|
||||
|
||||
if (typeof contact.imgUrl === 'undefined') {
|
||||
if(typeof contact.imgUrl === 'undefined') {
|
||||
contact.imgUrl = await sock?.profilePictureUrl(jid)
|
||||
}
|
||||
|
||||
return contact.imgUrl
|
||||
},
|
||||
fetchGroupMetadata: async (jid: string, sock: WASocket | undefined) => {
|
||||
if (!groupMetadata[jid]) {
|
||||
fetchGroupMetadata: async(jid: string, sock: WASocket | undefined) => {
|
||||
if(!groupMetadata[jid]) {
|
||||
const metadata = await sock?.groupMetadata(jid)
|
||||
if (metadata) {
|
||||
if(metadata) {
|
||||
groupMetadata[jid] = metadata
|
||||
}
|
||||
}
|
||||
@@ -460,7 +454,7 @@ export default (
|
||||
|
||||
// return groupMetadata[jid]
|
||||
// },
|
||||
fetchMessageReceipts: async ({ remoteJid, id }: WAMessageKey) => {
|
||||
fetchMessageReceipts: async({ remoteJid, id }: WAMessageKey) => {
|
||||
const list = messages[remoteJid!]
|
||||
const msg = list?.get(id!)
|
||||
return msg?.userReceipt
|
||||
@@ -475,7 +469,7 @@ export default (
|
||||
readFromFile: (path: string) => {
|
||||
// require fs here so that in case "fs" is not available -- the app does not crash
|
||||
const { readFileSync, existsSync } = require('fs')
|
||||
if (existsSync(path)) {
|
||||
if(existsSync(path)) {
|
||||
logger.debug({ path }, 'reading from file')
|
||||
const jsonStr = readFileSync(path, { encoding: 'utf-8' })
|
||||
const json = JSON.parse(jsonStr)
|
||||
|
||||
@@ -1,31 +1,32 @@
|
||||
export class ObjectRepository<T extends object> {
|
||||
readonly entityMap: Map<string, T>
|
||||
readonly entityMap: Map<string, T>
|
||||
|
||||
constructor(entities: Record<string, T> = {}) {
|
||||
this.entityMap = new Map(Object.entries(entities))
|
||||
}
|
||||
constructor(entities: Record<string, T> = {}) {
|
||||
this.entityMap = new Map(Object.entries(entities))
|
||||
}
|
||||
|
||||
findById(id: string) {
|
||||
return this.entityMap.get(id)
|
||||
}
|
||||
findById(id: string) {
|
||||
return this.entityMap.get(id)
|
||||
}
|
||||
|
||||
findAll() {
|
||||
return Array.from(this.entityMap.values())
|
||||
}
|
||||
findAll() {
|
||||
return Array.from(this.entityMap.values())
|
||||
}
|
||||
|
||||
upsertById(id: string, entity: T) {
|
||||
return this.entityMap.set(id, { ...entity })
|
||||
}
|
||||
upsertById(id: string, entity: T) {
|
||||
return this.entityMap.set(id, { ...entity })
|
||||
}
|
||||
|
||||
deleteById(id: string) {
|
||||
return this.entityMap.delete(id)
|
||||
}
|
||||
deleteById(id: string) {
|
||||
return this.entityMap.delete(id)
|
||||
}
|
||||
|
||||
count() {
|
||||
return this.entityMap.size
|
||||
}
|
||||
count() {
|
||||
return this.entityMap.size
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.findAll()
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return this.findAll()
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,7 @@ export type WAReadReceiptsValue = 'all' | 'none'
|
||||
/** set of statuses visible to other people; see updatePresence() in WhatsAppWeb.Send */
|
||||
export type WAPresence = 'unavailable' | 'available' | 'composing' | 'recording' | 'paused'
|
||||
|
||||
export const ALL_WA_PATCH_NAMES = [
|
||||
'critical_block',
|
||||
'critical_unblock_low',
|
||||
'regular_high',
|
||||
'regular_low',
|
||||
'regular'
|
||||
] as const
|
||||
export const ALL_WA_PATCH_NAMES = ['critical_block', 'critical_unblock_low', 'regular_high', 'regular_low', 'regular'] as const
|
||||
|
||||
export type WAPatchName = typeof ALL_WA_PATCH_NAMES[number]
|
||||
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
/** Association type */
|
||||
export enum LabelAssociationType {
|
||||
Chat = 'label_jid',
|
||||
Message = 'label_message'
|
||||
}
|
||||
Chat = 'label_jid',
|
||||
Message = 'label_message'
|
||||
}
|
||||
|
||||
export type LabelAssociationTypes = `${LabelAssociationType}`
|
||||
export type LabelAssociationTypes = `${LabelAssociationType}`
|
||||
|
||||
/** Association for chat */
|
||||
export interface ChatLabelAssociation {
|
||||
type: LabelAssociationType.Chat
|
||||
chatId: string
|
||||
labelId: string
|
||||
}
|
||||
/** Association for chat */
|
||||
export interface ChatLabelAssociation {
|
||||
type: LabelAssociationType.Chat
|
||||
chatId: string
|
||||
labelId: string
|
||||
}
|
||||
|
||||
/** Association for message */
|
||||
export interface MessageLabelAssociation {
|
||||
type: LabelAssociationType.Message
|
||||
chatId: string
|
||||
messageId: string
|
||||
labelId: string
|
||||
}
|
||||
/** Association for message */
|
||||
export interface MessageLabelAssociation {
|
||||
type: LabelAssociationType.Message
|
||||
chatId: string
|
||||
messageId: string
|
||||
labelId: string
|
||||
}
|
||||
|
||||
export type LabelAssociation = ChatLabelAssociation | MessageLabelAssociation
|
||||
export type LabelAssociation = ChatLabelAssociation | MessageLabelAssociation
|
||||
|
||||
/** Body for add/remove chat label association action */
|
||||
export interface ChatLabelAssociationActionBody {
|
||||
labelId: string
|
||||
}
|
||||
/** Body for add/remove chat label association action */
|
||||
export interface ChatLabelAssociationActionBody {
|
||||
labelId: string
|
||||
}
|
||||
|
||||
/** body for add/remove message label association action */
|
||||
export interface MessageLabelAssociationActionBody {
|
||||
labelId: string
|
||||
messageId: string
|
||||
}
|
||||
/** body for add/remove message label association action */
|
||||
export interface MessageLabelAssociationActionBody {
|
||||
labelId: string
|
||||
messageId: string
|
||||
}
|
||||
@@ -29,12 +29,12 @@ const generateMac = (operation: proto.SyncdMutation.SyncdOperation, data: Buffer
|
||||
const getKeyData = () => {
|
||||
let r: number
|
||||
switch (operation) {
|
||||
case proto.SyncdMutation.SyncdOperation.SET:
|
||||
r = 0x01
|
||||
break
|
||||
case proto.SyncdMutation.SyncdOperation.REMOVE:
|
||||
r = 0x02
|
||||
break
|
||||
case proto.SyncdMutation.SyncdOperation.SET:
|
||||
r = 0x01
|
||||
break
|
||||
case proto.SyncdMutation.SyncdOperation.REMOVE:
|
||||
r = 0x02
|
||||
break
|
||||
}
|
||||
|
||||
const buff = Buffer.from([r])
|
||||
@@ -69,8 +69,8 @@ const makeLtHashGenerator = ({ indexValueMap, hash }: Pick<LTHashState, 'hash' |
|
||||
mix: ({ indexMac, valueMac, operation }: Mac) => {
|
||||
const indexMacBase64 = Buffer.from(indexMac).toString('base64')
|
||||
const prevOp = indexValueMap[indexMacBase64]
|
||||
if (operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
||||
if (!prevOp) {
|
||||
if(operation === proto.SyncdMutation.SyncdOperation.REMOVE) {
|
||||
if(!prevOp) {
|
||||
throw new Boom('tried remove, but no previous op', { data: { indexMac, valueMac } })
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ const makeLtHashGenerator = ({ indexValueMap, hash }: Pick<LTHashState, 'hash' |
|
||||
indexValueMap[indexMacBase64] = { valueMac }
|
||||
}
|
||||
|
||||
if (prevOp) {
|
||||
if(prevOp) {
|
||||
subBuffs.push(new Uint8Array(prevOp.valueMac).buffer)
|
||||
}
|
||||
},
|
||||
@@ -120,14 +120,14 @@ const generatePatchMac = (snapshotMac: Uint8Array, valueMacs: Uint8Array[], vers
|
||||
|
||||
export const newLTHashState = (): LTHashState => ({ version: 0, hash: Buffer.alloc(128), indexValueMap: {} })
|
||||
|
||||
export const encodeSyncdPatch = async (
|
||||
export const encodeSyncdPatch = async(
|
||||
{ type, index, syncAction, apiVersion, operation }: WAPatchCreate,
|
||||
myAppStateKeyId: string,
|
||||
state: LTHashState,
|
||||
getAppStateSyncKey: FetchAppStateSyncKey
|
||||
) => {
|
||||
const key = !!myAppStateKeyId ? await getAppStateSyncKey(myAppStateKeyId) : undefined
|
||||
if (!key) {
|
||||
if(!key) {
|
||||
throw new Boom(`myAppStateKey ("${myAppStateKeyId}") not present`, { statusCode: 404 })
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ export const encodeSyncdPatch = async (
|
||||
return { patch, state }
|
||||
}
|
||||
|
||||
export const decodeSyncdMutations = async (
|
||||
export const decodeSyncdMutations = async(
|
||||
msgMutations: (proto.ISyncdMutation | proto.ISyncdRecord)[],
|
||||
initialState: LTHashState,
|
||||
getAppStateSyncKey: FetchAppStateSyncKey,
|
||||
@@ -196,7 +196,7 @@ export const decodeSyncdMutations = async (
|
||||
// indexKey used to HMAC sign record.index.blob
|
||||
// valueEncryptionKey used to AES-256-CBC encrypt record.value.blob[0:-32]
|
||||
// the remaining record.value.blob[0:-32] is the mac, it the HMAC sign of key.keyId + decoded proto data + length of bytes in keyId
|
||||
for (const msgMutation of msgMutations!) {
|
||||
for(const msgMutation of msgMutations!) {
|
||||
// if it's a syncdmutation, get the operation property
|
||||
// otherwise, if it's only a record -- it'll be a SET mutation
|
||||
const operation = 'operation' in msgMutation ? msgMutation.operation : proto.SyncdMutation.SyncdOperation.SET
|
||||
@@ -206,9 +206,9 @@ export const decodeSyncdMutations = async (
|
||||
const content = Buffer.from(record.value!.blob!)
|
||||
const encContent = content.slice(0, -32)
|
||||
const ogValueMac = content.slice(-32)
|
||||
if (validateMacs) {
|
||||
if(validateMacs) {
|
||||
const contentHmac = generateMac(operation!, encContent, record.keyId!.id!, key.valueMacKey)
|
||||
if (Buffer.compare(contentHmac, ogValueMac) !== 0) {
|
||||
if(Buffer.compare(contentHmac, ogValueMac) !== 0) {
|
||||
throw new Boom('HMAC content verification failed')
|
||||
}
|
||||
}
|
||||
@@ -216,9 +216,9 @@ export const decodeSyncdMutations = async (
|
||||
const result = aesDecrypt(encContent, key.valueEncryptionKey)
|
||||
const syncAction = proto.SyncActionData.decode(result)
|
||||
|
||||
if (validateMacs) {
|
||||
if(validateMacs) {
|
||||
const hmac = hmacSign(syncAction.index, key.indexKey)
|
||||
if (Buffer.compare(hmac, record.index!.blob!) !== 0) {
|
||||
if(Buffer.compare(hmac, record.index!.blob!) !== 0) {
|
||||
throw new Boom('HMAC index verification failed')
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ export const decodeSyncdMutations = async (
|
||||
async function getKey(keyId: Uint8Array) {
|
||||
const base64Key = Buffer.from(keyId!).toString('base64')
|
||||
const keyEnc = await getAppStateSyncKey(base64Key)
|
||||
if (!keyEnc) {
|
||||
if(!keyEnc) {
|
||||
throw new Boom(`failed to find key "${base64Key}" to decode mutation`, { statusCode: 404, data: { msgMutations } })
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ export const decodeSyncdMutations = async (
|
||||
}
|
||||
}
|
||||
|
||||
export const decodeSyncdPatch = async (
|
||||
export const decodeSyncdPatch = async(
|
||||
msg: proto.ISyncdPatch,
|
||||
name: WAPatchName,
|
||||
initialState: LTHashState,
|
||||
@@ -254,10 +254,10 @@ export const decodeSyncdPatch = async (
|
||||
onMutation: (mutation: ChatMutation) => void,
|
||||
validateMacs: boolean
|
||||
) => {
|
||||
if (validateMacs) {
|
||||
if(validateMacs) {
|
||||
const base64Key = Buffer.from(msg.keyId!.id!).toString('base64')
|
||||
const mainKeyObj = await getAppStateSyncKey(base64Key)
|
||||
if (!mainKeyObj) {
|
||||
if(!mainKeyObj) {
|
||||
throw new Boom(`failed to find key "${base64Key}" to decode patch`, { statusCode: 404, data: { msg } })
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ export const decodeSyncdPatch = async (
|
||||
const mutationmacs = msg.mutations!.map(mutation => mutation.record!.value!.blob!.slice(-32))
|
||||
|
||||
const patchMac = generatePatchMac(msg.snapshotMac!, mutationmacs, toNumber(msg.version!.version!), name, mainKey.patchMacKey)
|
||||
if (Buffer.compare(patchMac, msg.patchMac!) !== 0) {
|
||||
if(Buffer.compare(patchMac, msg.patchMac!) !== 0) {
|
||||
throw new Boom('Invalid patch mac')
|
||||
}
|
||||
}
|
||||
@@ -274,7 +274,7 @@ export const decodeSyncdPatch = async (
|
||||
return result
|
||||
}
|
||||
|
||||
export const extractSyncdPatches = async (
|
||||
export const extractSyncdPatches = async(
|
||||
result: BinaryNode,
|
||||
options: AxiosRequestConfig<any>
|
||||
) => {
|
||||
@@ -296,8 +296,8 @@ export const extractSyncdPatches = async (
|
||||
const hasMorePatches = collectionNode.attrs.has_more_patches === 'true'
|
||||
|
||||
let snapshot: proto.ISyncdSnapshot | undefined = undefined
|
||||
if (snapshotNode && !!snapshotNode.content) {
|
||||
if (!Buffer.isBuffer(snapshotNode)) {
|
||||
if(snapshotNode && !!snapshotNode.content) {
|
||||
if(!Buffer.isBuffer(snapshotNode)) {
|
||||
snapshotNode.content = Buffer.from(Object.values(snapshotNode.content))
|
||||
}
|
||||
|
||||
@@ -308,14 +308,14 @@ export const extractSyncdPatches = async (
|
||||
snapshot = proto.SyncdSnapshot.decode(data)
|
||||
}
|
||||
|
||||
for (let { content } of patches) {
|
||||
if (content) {
|
||||
if (!Buffer.isBuffer(content)) {
|
||||
for(let { content } of patches) {
|
||||
if(content) {
|
||||
if(!Buffer.isBuffer(content)) {
|
||||
content = Buffer.from(Object.values(content))
|
||||
}
|
||||
|
||||
const syncd = proto.SyncdPatch.decode(content! as Uint8Array)
|
||||
if (!syncd.version) {
|
||||
if(!syncd.version) {
|
||||
syncd.version = { version: +collectionNode.attrs.version + 1 }
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ export const extractSyncdPatches = async (
|
||||
}
|
||||
|
||||
|
||||
export const downloadExternalBlob = async (
|
||||
export const downloadExternalBlob = async(
|
||||
blob: proto.IExternalBlobReference,
|
||||
options: AxiosRequestConfig<any>
|
||||
) => {
|
||||
@@ -345,7 +345,7 @@ export const downloadExternalBlob = async (
|
||||
return Buffer.concat(bufferArray)
|
||||
}
|
||||
|
||||
export const downloadExternalPatch = async (
|
||||
export const downloadExternalPatch = async(
|
||||
blob: proto.IExternalBlobReference,
|
||||
options: AxiosRequestConfig<any>
|
||||
) => {
|
||||
@@ -354,7 +354,7 @@ export const downloadExternalPatch = async (
|
||||
return syncData
|
||||
}
|
||||
|
||||
export const decodeSyncdSnapshot = async (
|
||||
export const decodeSyncdSnapshot = async(
|
||||
name: WAPatchName,
|
||||
snapshot: proto.ISyncdSnapshot,
|
||||
getAppStateSyncKey: FetchAppStateSyncKey,
|
||||
@@ -383,16 +383,16 @@ export const decodeSyncdSnapshot = async (
|
||||
newState.hash = hash
|
||||
newState.indexValueMap = indexValueMap
|
||||
|
||||
if (validateMacs) {
|
||||
if(validateMacs) {
|
||||
const base64Key = Buffer.from(snapshot.keyId!.id!).toString('base64')
|
||||
const keyEnc = await getAppStateSyncKey(base64Key)
|
||||
if (!keyEnc) {
|
||||
if(!keyEnc) {
|
||||
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
||||
}
|
||||
|
||||
const result = mutationKeys(keyEnc.keyData!)
|
||||
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
||||
if (Buffer.compare(snapshot.mac!, computedSnapshotMac) !== 0) {
|
||||
if(Buffer.compare(snapshot.mac!, computedSnapshotMac) !== 0) {
|
||||
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name} from snapshot`)
|
||||
}
|
||||
}
|
||||
@@ -403,7 +403,7 @@ export const decodeSyncdSnapshot = async (
|
||||
}
|
||||
}
|
||||
|
||||
export const decodePatches = async (
|
||||
export const decodePatches = async(
|
||||
name: WAPatchName,
|
||||
syncds: proto.ISyncdPatch[],
|
||||
initial: LTHashState,
|
||||
@@ -420,10 +420,10 @@ export const decodePatches = async (
|
||||
|
||||
const mutationMap: ChatMutationMap = {}
|
||||
|
||||
for (let i = 0; i < syncds.length; i++) {
|
||||
for(let i = 0; i < syncds.length; i++) {
|
||||
const syncd = syncds[i]
|
||||
const { version, keyId, snapshotMac } = syncd
|
||||
if (syncd.externalMutations) {
|
||||
if(syncd.externalMutations) {
|
||||
logger?.trace({ name, version }, 'downloading external patch')
|
||||
const ref = await downloadExternalPatch(syncd.externalMutations, options)
|
||||
logger?.debug({ name, version, mutations: ref.mutations.length }, 'downloaded external patch')
|
||||
@@ -452,16 +452,16 @@ export const decodePatches = async (
|
||||
newState.hash = decodeResult.hash
|
||||
newState.indexValueMap = decodeResult.indexValueMap
|
||||
|
||||
if (validateMacs) {
|
||||
if(validateMacs) {
|
||||
const base64Key = Buffer.from(keyId!.id!).toString('base64')
|
||||
const keyEnc = await getAppStateSyncKey(base64Key)
|
||||
if (!keyEnc) {
|
||||
if(!keyEnc) {
|
||||
throw new Boom(`failed to find key "${base64Key}" to decode mutation`)
|
||||
}
|
||||
|
||||
const result = mutationKeys(keyEnc.keyData!)
|
||||
const computedSnapshotMac = generateSnapshotMac(newState.hash, newState.version, name, result.snapshotMacKey)
|
||||
if (Buffer.compare(snapshotMac!, computedSnapshotMac) !== 0) {
|
||||
if(Buffer.compare(snapshotMac!, computedSnapshotMac) !== 0) {
|
||||
throw new Boom(`failed to verify LTHash at ${newState.version} of ${name}`)
|
||||
}
|
||||
}
|
||||
@@ -480,25 +480,25 @@ export const chatModificationToAppPatch = (
|
||||
const OP = proto.SyncdMutation.SyncdOperation
|
||||
const getMessageRange = (lastMessages: LastMessageList) => {
|
||||
let messageRange: proto.SyncActionValue.ISyncActionMessageRange
|
||||
if (Array.isArray(lastMessages)) {
|
||||
if(Array.isArray(lastMessages)) {
|
||||
const lastMsg = lastMessages[lastMessages.length - 1]
|
||||
messageRange = {
|
||||
lastMessageTimestamp: lastMsg?.messageTimestamp,
|
||||
messages: lastMessages?.length ? lastMessages.map(
|
||||
m => {
|
||||
if (!m.key?.id || !m.key?.remoteJid) {
|
||||
if(!m.key?.id || !m.key?.remoteJid) {
|
||||
throw new Boom('Incomplete key', { statusCode: 400, data: m })
|
||||
}
|
||||
|
||||
if (isJidGroup(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
|
||||
if(isJidGroup(m.key.remoteJid) && !m.key.fromMe && !m.key.participant) {
|
||||
throw new Boom('Expected not from me message to have participant', { statusCode: 400, data: m })
|
||||
}
|
||||
|
||||
if (!m.messageTimestamp || !toNumber(m.messageTimestamp)) {
|
||||
if(!m.messageTimestamp || !toNumber(m.messageTimestamp)) {
|
||||
throw new Boom('Missing timestamp in last message list', { statusCode: 400, data: m })
|
||||
}
|
||||
|
||||
if (m.key.participant) {
|
||||
if(m.key.participant) {
|
||||
m.key.participant = jidNormalizedUser(m.key.participant)
|
||||
}
|
||||
|
||||
@@ -514,7 +514,7 @@ export const chatModificationToAppPatch = (
|
||||
}
|
||||
|
||||
let patch: WAPatchCreate
|
||||
if ('mute' in mod) {
|
||||
if('mute' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
muteAction: {
|
||||
@@ -527,7 +527,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 2,
|
||||
operation: OP.SET
|
||||
}
|
||||
} else if ('archive' in mod) {
|
||||
} else if('archive' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
archiveChatAction: {
|
||||
@@ -540,7 +540,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 3,
|
||||
operation: OP.SET
|
||||
}
|
||||
} else if ('markRead' in mod) {
|
||||
} else if('markRead' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
markChatAsReadAction: {
|
||||
@@ -553,8 +553,8 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 3,
|
||||
operation: OP.SET
|
||||
}
|
||||
} else if ('clear' in mod) {
|
||||
if (mod.clear === 'all') {
|
||||
} else if('clear' in mod) {
|
||||
if(mod.clear === 'all') {
|
||||
throw new Boom('not supported')
|
||||
} else {
|
||||
const key = mod.clear.messages[0]
|
||||
@@ -571,7 +571,7 @@ export const chatModificationToAppPatch = (
|
||||
operation: OP.SET
|
||||
}
|
||||
}
|
||||
} else if ('pin' in mod) {
|
||||
} else if('pin' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
pinAction: {
|
||||
@@ -583,7 +583,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 5,
|
||||
operation: OP.SET
|
||||
}
|
||||
} else if ('delete' in mod) {
|
||||
} else if('delete' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
deleteChatAction: {
|
||||
@@ -595,7 +595,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 6,
|
||||
operation: OP.SET
|
||||
}
|
||||
} else if ('pushNameSetting' in mod) {
|
||||
} else if('pushNameSetting' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
pushNameSetting: {
|
||||
@@ -607,7 +607,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 1,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if ('addChatLabel' in mod) {
|
||||
} else if('addChatLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
@@ -619,7 +619,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if ('removeChatLabel' in mod) {
|
||||
} else if('removeChatLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
@@ -631,7 +631,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if ('addMessageLabel' in mod) {
|
||||
} else if('addMessageLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
@@ -650,7 +650,7 @@ export const chatModificationToAppPatch = (
|
||||
apiVersion: 3,
|
||||
operation: OP.SET,
|
||||
}
|
||||
} else if ('removeMessageLabel' in mod) {
|
||||
} else if('removeMessageLabel' in mod) {
|
||||
patch = {
|
||||
syncAction: {
|
||||
labelAssociationAction: {
|
||||
@@ -695,7 +695,7 @@ export const processSyncAction = (
|
||||
index: [type, id, msgId, fromMe]
|
||||
} = syncAction
|
||||
|
||||
if (action?.muteAction) {
|
||||
if(action?.muteAction) {
|
||||
ev.emit(
|
||||
'chats.update',
|
||||
[
|
||||
@@ -708,7 +708,7 @@ export const processSyncAction = (
|
||||
}
|
||||
]
|
||||
)
|
||||
} else if (action?.archiveChatAction || type === 'archive' || type === 'unarchive') {
|
||||
} else if(action?.archiveChatAction || type === 'archive' || type === 'unarchive') {
|
||||
// okay so we've to do some annoying computation here
|
||||
// when we're initially syncing the app state
|
||||
// there are a few cases we need to handle
|
||||
@@ -737,7 +737,7 @@ export const processSyncAction = (
|
||||
archived: isArchived,
|
||||
conditional: getChatUpdateConditional(id, msgRange)
|
||||
}])
|
||||
} else if (action?.markChatAsReadAction) {
|
||||
} else if(action?.markChatAsReadAction) {
|
||||
const markReadAction = action.markChatAsReadAction
|
||||
// basically we don't need to fire an "read" update if the chat is being marked as read
|
||||
// because the chat is read by default
|
||||
@@ -749,7 +749,7 @@ export const processSyncAction = (
|
||||
unreadCount: isNullUpdate ? null : !!markReadAction?.read ? 0 : -1,
|
||||
conditional: getChatUpdateConditional(id, markReadAction?.messageRange)
|
||||
}])
|
||||
} else if (action?.deleteMessageForMeAction || type === 'deleteMessageForMe') {
|
||||
} else if(action?.deleteMessageForMeAction || type === 'deleteMessageForMe') {
|
||||
ev.emit('messages.delete', {
|
||||
keys: [
|
||||
{
|
||||
@@ -759,30 +759,30 @@ export const processSyncAction = (
|
||||
}
|
||||
]
|
||||
})
|
||||
} else if (action?.contactAction) {
|
||||
} else if(action?.contactAction) {
|
||||
ev.emit('contacts.upsert', [{ id, name: action.contactAction!.fullName! }])
|
||||
} else if (action?.pushNameSetting) {
|
||||
} else if(action?.pushNameSetting) {
|
||||
const name = action?.pushNameSetting?.name
|
||||
if (name && me?.name !== name) {
|
||||
if(name && me?.name !== name) {
|
||||
ev.emit('creds.update', { me: { ...me, name } })
|
||||
}
|
||||
} else if (action?.pinAction) {
|
||||
} else if(action?.pinAction) {
|
||||
ev.emit('chats.update', [{
|
||||
id,
|
||||
pinned: action.pinAction?.pinned ? toNumber(action.timestamp!) : null,
|
||||
conditional: getChatUpdateConditional(id, undefined)
|
||||
}])
|
||||
} else if (action?.unarchiveChatsSetting) {
|
||||
} else if(action?.unarchiveChatsSetting) {
|
||||
const unarchiveChats = !!action.unarchiveChatsSetting.unarchiveChats
|
||||
ev.emit('creds.update', { accountSettings: { unarchiveChats } })
|
||||
|
||||
logger?.info(`archive setting updated => '${action.unarchiveChatsSetting.unarchiveChats}'`)
|
||||
if (accountSettings) {
|
||||
if(accountSettings) {
|
||||
accountSettings.unarchiveChats = unarchiveChats
|
||||
}
|
||||
} else if (action?.starAction || type === 'star') {
|
||||
} else if(action?.starAction || type === 'star') {
|
||||
let starred = action?.starAction?.starred
|
||||
if (typeof starred !== 'boolean') {
|
||||
if(typeof starred !== 'boolean') {
|
||||
starred = syncAction.index[syncAction.index.length - 1] === '1'
|
||||
}
|
||||
|
||||
@@ -792,11 +792,11 @@ export const processSyncAction = (
|
||||
update: { starred }
|
||||
}
|
||||
])
|
||||
} else if (action?.deleteChatAction || type === 'deleteChat') {
|
||||
if (!isInitialSync) {
|
||||
} else if(action?.deleteChatAction || type === 'deleteChat') {
|
||||
if(!isInitialSync) {
|
||||
ev.emit('chats.delete', [id])
|
||||
}
|
||||
} else if (action?.labelEditAction) {
|
||||
} else if(action?.labelEditAction) {
|
||||
const { name, color, deleted, predefinedId } = action.labelEditAction!
|
||||
|
||||
ev.emit('labels.edit', {
|
||||
@@ -806,7 +806,7 @@ export const processSyncAction = (
|
||||
deleted: deleted!,
|
||||
predefinedId: predefinedId ? String(predefinedId) : undefined
|
||||
})
|
||||
} else if (action?.labelAssociationAction) {
|
||||
} else if(action?.labelAssociationAction) {
|
||||
ev.emit('labels.association', {
|
||||
type: action.labelAssociationAction.labeled
|
||||
? 'add'
|
||||
@@ -832,7 +832,7 @@ export const processSyncAction = (
|
||||
return isInitialSync
|
||||
? (data) => {
|
||||
const chat = data.historySets.chats[id] || data.chatUpserts[id]
|
||||
if (chat) {
|
||||
if(chat) {
|
||||
return msgRange ? isValidPatchBasedOnMessageRange(chat, msgRange) : true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user