mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
implement chat modifications
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import { encodeSyncdPatch, decodePatches, extractSyncdPatches } from "../Utils/chat-utils";
|
import { encodeSyncdPatch, decodePatches, extractSyncdPatches, chatModificationToAppPatch } from "../Utils/chat-utils";
|
||||||
import { SocketConfig, WAPresence, PresenceData, Chat, WAPatchCreate, WAMediaUpload, ChatMutation, WAPatchName, LTHashState } from "../Types";
|
import { SocketConfig, WAPresence, PresenceData, Chat, WAPatchCreate, WAMediaUpload, ChatMutation, WAPatchName, LTHashState, ChatModification, Contact } from "../Types";
|
||||||
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, jidNormalizedUser, S_WHATSAPP_NET } from "../WABinary";
|
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, jidNormalizedUser, S_WHATSAPP_NET } from "../WABinary";
|
||||||
import { proto } from '../../WAProto'
|
import { proto } from '../../WAProto'
|
||||||
import { generateProfilePicture, toNumber } from "../Utils";
|
import { generateProfilePicture, toNumber } from "../Utils";
|
||||||
@@ -298,8 +298,12 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const processSyncActions = (actions: ChatMutation[]) => {
|
const processSyncActions = (actions: ChatMutation[]) => {
|
||||||
const updates: Partial<Chat>[] = []
|
|
||||||
for(const { action, index: [_, id] } of actions) {
|
const updates: { [jid: string]: Partial<Chat> } = {}
|
||||||
|
const contactUpdates: { [jid: string]: Partial<Contact> } = {}
|
||||||
|
const msgDeletes: proto.IMessageKey[] = []
|
||||||
|
|
||||||
|
for(const { action, index: [_, id, msgId, fromMe] } of actions) {
|
||||||
const update: Partial<Chat> = { id }
|
const update: Partial<Chat> = { id }
|
||||||
if(action?.muteAction) {
|
if(action?.muteAction) {
|
||||||
update.mute = action.muteAction?.muted ?
|
update.mute = action.muteAction?.muted ?
|
||||||
@@ -310,9 +314,17 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
} else if(action?.markChatAsReadAction) {
|
} else if(action?.markChatAsReadAction) {
|
||||||
update.unreadCount = !!action.markChatAsReadAction?.read ? 0 : -1
|
update.unreadCount = !!action.markChatAsReadAction?.read ? 0 : -1
|
||||||
} else if(action?.clearChatAction) {
|
} else if(action?.clearChatAction) {
|
||||||
console.log(action.clearChatAction)
|
msgDeletes.push({
|
||||||
|
remoteJid: id,
|
||||||
|
id: msgId,
|
||||||
|
fromMe: fromMe === '1'
|
||||||
|
})
|
||||||
} else if(action?.contactAction) {
|
} else if(action?.contactAction) {
|
||||||
ev.emit('contacts.update', [{ id, name: action.contactAction!.fullName }])
|
contactUpdates[id] = {
|
||||||
|
...(contactUpdates[id] || {}),
|
||||||
|
id,
|
||||||
|
name: action.contactAction!.fullName
|
||||||
|
}
|
||||||
} else if(action?.pushNameSetting) {
|
} else if(action?.pushNameSetting) {
|
||||||
authState.creds.me!.name = action?.pushNameSetting?.name!
|
authState.creds.me!.name = action?.pushNameSetting?.name!
|
||||||
ev.emit('auth-state.update', authState)
|
ev.emit('auth-state.update', authState)
|
||||||
@@ -320,10 +332,22 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
logger.warn({ action, id }, 'unprocessable update')
|
logger.warn({ action, id }, 'unprocessable update')
|
||||||
}
|
}
|
||||||
if(Object.keys(update).length > 1) {
|
if(Object.keys(update).length > 1) {
|
||||||
updates.push(update)
|
updates[update.id] = {
|
||||||
|
...(updates[update.id] || {}),
|
||||||
|
...update
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ev.emit('chats.update', updates)
|
|
||||||
|
if(Object.values(updates).length) {
|
||||||
|
ev.emit('chats.update', Object.values(updates))
|
||||||
|
}
|
||||||
|
if(Object.values(contactUpdates).length) {
|
||||||
|
ev.emit('contacts.update', Object.values(contactUpdates))
|
||||||
|
}
|
||||||
|
if(msgDeletes.length) {
|
||||||
|
ev.emit('messages.delete', { keys: msgDeletes })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const appPatch = async(patchCreate: WAPatchCreate) => {
|
const appPatch = async(patchCreate: WAPatchCreate) => {
|
||||||
@@ -336,7 +360,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
)
|
)
|
||||||
const initial = await authState.keys.getAppStateSyncVersion(name)
|
const initial = await authState.keys.getAppStateSyncVersion(name)
|
||||||
// temp: verify it was encoded correctly
|
// temp: verify it was encoded correctly
|
||||||
const result = await decodePatches({ syncds: [{ ...patch, version: { version: state.version }, }], name }, initial, authState)
|
await decodePatches({ syncds: [{ ...patch, version: { version: state.version }, }], name }, initial, authState)
|
||||||
|
|
||||||
const node: BinaryNode = {
|
const node: BinaryNode = {
|
||||||
tag: 'iq',
|
tag: 'iq',
|
||||||
@@ -375,6 +399,11 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
ev.emit('auth-state.update', authState)
|
ev.emit('auth-state.update', authState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const chatModify = (mod: ChatModification, jid: string, lastMessages: Pick<proto.IWebMessageInfo, 'key' | 'messageTimestamp'>[]) => {
|
||||||
|
const patch = chatModificationToAppPatch(mod, jid, lastMessages)
|
||||||
|
return appPatch(patch)
|
||||||
|
}
|
||||||
|
|
||||||
const fetchAppState = async(name: WAPatchName, fromVersion: number) => {
|
const fetchAppState = async(name: WAPatchName, fromVersion: number) => {
|
||||||
const result = await query({
|
const result = await query({
|
||||||
tag: 'iq',
|
tag: 'iq',
|
||||||
@@ -452,5 +481,6 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
updateProfilePicture,
|
updateProfilePicture,
|
||||||
updateBlockStatus,
|
updateBlockStatus,
|
||||||
resyncState,
|
resyncState,
|
||||||
|
chatModify,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,11 +10,11 @@ export interface PresenceData {
|
|||||||
lastSeen?: number
|
lastSeen?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChatMutation = { action: proto.ISyncActionValue, index: [string, string], indexMac: Uint8Array, valueMac: Uint8Array, operation: number }
|
export type ChatMutation = { action: proto.ISyncActionValue, index: string[], indexMac: Uint8Array, valueMac: Uint8Array, operation: number }
|
||||||
|
|
||||||
export type WAPatchCreate = {
|
export type WAPatchCreate = {
|
||||||
syncAction: proto.ISyncActionValue
|
syncAction: proto.ISyncActionValue
|
||||||
index: [string, string]
|
index: string[]
|
||||||
type: WAPatchName
|
type: WAPatchName
|
||||||
apiVersion: number
|
apiVersion: number
|
||||||
}
|
}
|
||||||
@@ -38,7 +38,7 @@ export type ChatModification =
|
|||||||
mute: number | null
|
mute: number | null
|
||||||
} |
|
} |
|
||||||
{
|
{
|
||||||
clear: 'all' | { messages: { id: string, fromMe?: boolean }[] }
|
clear: 'all' | { message: {id: string, fromMe?: boolean} }
|
||||||
} |
|
} |
|
||||||
{
|
{
|
||||||
star: {
|
star: {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import { Contact } from './Contact'
|
|||||||
import { ConnectionState } from './State'
|
import { ConnectionState } from './State'
|
||||||
|
|
||||||
import { GroupMetadata, ParticipantAction } from './GroupMetadata'
|
import { GroupMetadata, ParticipantAction } from './GroupMetadata'
|
||||||
import { MessageInfoUpdate, MessageUpdateType, WAMessage, WAMessageUpdate } from './Message'
|
import { MessageInfoUpdate, MessageUpdateType, WAMessage, WAMessageUpdate, WAMessageKey } from './Message'
|
||||||
|
|
||||||
export type WAVersion = [number, number, number]
|
export type WAVersion = [number, number, number]
|
||||||
export type WABrowserDescription = [string, string, string]
|
export type WABrowserDescription = [string, string, string]
|
||||||
@@ -103,7 +103,7 @@ export type BaileysEventMap = {
|
|||||||
'contacts.upsert': Contact[]
|
'contacts.upsert': Contact[]
|
||||||
'contacts.update': Partial<Contact>[]
|
'contacts.update': Partial<Contact>[]
|
||||||
|
|
||||||
'messages.delete': { jid: string, ids: string[] } | { jid: string, all: true }
|
'messages.delete': { keys: WAMessageKey[] } | { jid: string, all: true }
|
||||||
'messages.update': WAMessageUpdate[]
|
'messages.update': WAMessageUpdate[]
|
||||||
/**
|
/**
|
||||||
* add/update the given messages. If they were received while the connection was online,
|
* add/update the given messages. If they were received while the connection was online,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Boom } from '@hapi/boom'
|
import { Boom } from '@hapi/boom'
|
||||||
import { aesDecrypt, hmacSign, aesEncrypt, hkdf } from "./crypto"
|
import { aesDecrypt, hmacSign, aesEncrypt, hkdf } from "./crypto"
|
||||||
import { AuthenticationState, WAPatchCreate, ChatMutation, WAPatchName, LTHashState } from "../Types"
|
import { AuthenticationState, WAPatchCreate, ChatMutation, WAPatchName, LTHashState, ChatModification } from "../Types"
|
||||||
import { proto } from '../../WAProto'
|
import { proto } from '../../WAProto'
|
||||||
import { LT_HASH_ANTI_TAMPERING } from '../WABinary/LTHash'
|
import { LT_HASH_ANTI_TAMPERING } from '../WABinary/LTHash'
|
||||||
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren } from '../WABinary'
|
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren } from '../WABinary'
|
||||||
@@ -313,7 +313,6 @@ export const decodePatches = async(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const decodeResult = await decodeSyncdPatch(syncd, name, auth!, validateMacs)
|
const decodeResult = await decodeSyncdPatch(syncd, name, auth!, validateMacs)
|
||||||
console.log(currentVersion, decodeResult.mutations)
|
|
||||||
successfulMutations.push(...decodeResult.mutations)
|
successfulMutations.push(...decodeResult.mutations)
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -325,3 +324,76 @@ export const decodePatches = async(
|
|||||||
} as LTHashState
|
} as LTHashState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const chatModificationToAppPatch = (
|
||||||
|
mod: ChatModification,
|
||||||
|
jid: string,
|
||||||
|
lastMessages: Pick<proto.IWebMessageInfo, 'key' | 'messageTimestamp'>[]
|
||||||
|
) => {
|
||||||
|
const messageRange: proto.ISyncActionMessageRange = {
|
||||||
|
lastMessageTimestamp: lastMessages[lastMessages.length-1].messageTimestamp,
|
||||||
|
messages: lastMessages
|
||||||
|
}
|
||||||
|
const timestamp = Date.now()
|
||||||
|
let patch: WAPatchCreate
|
||||||
|
if('mute' in mod) {
|
||||||
|
patch = {
|
||||||
|
syncAction: {
|
||||||
|
timestamp,
|
||||||
|
muteAction: {
|
||||||
|
muted: !!mod.mute,
|
||||||
|
muteEndTimestamp: mod.mute || undefined
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: ['mute', jid],
|
||||||
|
type: 'regular_high',
|
||||||
|
apiVersion: 2
|
||||||
|
}
|
||||||
|
} else if('archive' in mod) {
|
||||||
|
patch = {
|
||||||
|
syncAction: {
|
||||||
|
timestamp,
|
||||||
|
archiveChatAction: {
|
||||||
|
archived: !!mod.archive,
|
||||||
|
messageRange
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: ['archive', jid],
|
||||||
|
type: 'regular_low',
|
||||||
|
apiVersion: 3
|
||||||
|
}
|
||||||
|
} else if('markRead' in mod) {
|
||||||
|
patch = {
|
||||||
|
syncAction: {
|
||||||
|
timestamp,
|
||||||
|
markChatAsReadAction: {
|
||||||
|
read: mod.markRead,
|
||||||
|
messageRange
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: ['markChatAsRead', jid],
|
||||||
|
type: 'regular_low',
|
||||||
|
apiVersion: 3
|
||||||
|
}
|
||||||
|
} else if('clear' in mod) {
|
||||||
|
if(mod.clear === 'all') {
|
||||||
|
throw new Boom('not supported')
|
||||||
|
} else {
|
||||||
|
const key = mod.clear.message
|
||||||
|
patch = {
|
||||||
|
syncAction: {
|
||||||
|
timestamp,
|
||||||
|
deleteMessageForMeAction: {
|
||||||
|
deleteMedia: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
index: ['deleteMessageForMe', jid, key.id, key.fromMe ? '1' : '0', '0'],
|
||||||
|
type: 'regular_high',
|
||||||
|
apiVersion: 3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new Boom('not supported')
|
||||||
|
}
|
||||||
|
return patch
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user