mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
feat: cache user devices
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
"jimp": "^0.16.1",
|
"jimp": "^0.16.1",
|
||||||
"libsignal": "git+https://github.com/adiwajshing/libsignal-node",
|
"libsignal": "git+https://github.com/adiwajshing/libsignal-node",
|
||||||
"music-metadata": "^7.4.1",
|
"music-metadata": "^7.4.1",
|
||||||
|
"node-cache": "^5.1.2",
|
||||||
"pino": "^6.7.0",
|
"pino": "^6.7.0",
|
||||||
"protobufjs": "^6.10.1",
|
"protobufjs": "^6.10.1",
|
||||||
"ws": "^7.3.1"
|
"ws": "^7.3.1"
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ import got from "got"
|
|||||||
import { Boom } from "@hapi/boom"
|
import { Boom } from "@hapi/boom"
|
||||||
import { SocketConfig, MediaConnInfo, AnyMessageContent, MiscMessageGenerationOptions, WAMediaUploadFunction, MessageRelayOptions, WAMessageKey } from "../Types"
|
import { SocketConfig, MediaConnInfo, AnyMessageContent, MiscMessageGenerationOptions, WAMediaUploadFunction, MessageRelayOptions, WAMessageKey } from "../Types"
|
||||||
import { encodeWAMessage, generateMessageID, generateWAMessage, encryptSenderKeyMsgSignalProto, encryptSignalProto, extractDeviceJids, jidToSignalProtocolAddress, parseAndInjectE2ESession } from "../Utils"
|
import { encodeWAMessage, generateMessageID, generateWAMessage, encryptSenderKeyMsgSignalProto, encryptSignalProto, extractDeviceJids, jidToSignalProtocolAddress, parseAndInjectE2ESession } from "../Utils"
|
||||||
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET, BinaryNodeAttributes } from '../WABinary'
|
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, isJidGroup, jidDecode, jidEncode, jidNormalizedUser, S_WHATSAPP_NET, BinaryNodeAttributes, JidWithDevice } from '../WABinary'
|
||||||
import { proto } from "../../WAProto"
|
import { proto } from "../../WAProto"
|
||||||
import { WA_DEFAULT_EPHEMERAL, DEFAULT_ORIGIN, MEDIA_PATH_MAP } from "../Defaults"
|
import { WA_DEFAULT_EPHEMERAL, DEFAULT_ORIGIN, MEDIA_PATH_MAP } from "../Defaults"
|
||||||
import { makeGroupsSocket } from "./groups"
|
import { makeGroupsSocket } from "./groups"
|
||||||
|
import NodeCache from "node-cache"
|
||||||
|
|
||||||
export const makeMessagesSocket = (config: SocketConfig) => {
|
export const makeMessagesSocket = (config: SocketConfig) => {
|
||||||
const { logger } = config
|
const { logger } = config
|
||||||
@@ -21,6 +22,10 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
groupToggleEphemeral
|
groupToggleEphemeral
|
||||||
} = sock
|
} = sock
|
||||||
|
|
||||||
|
const userDevicesCache = config.userDevicesCache || new NodeCache({
|
||||||
|
stdTTL: 300, // 5 minutes
|
||||||
|
useClones: false
|
||||||
|
})
|
||||||
let privacySettings: { [_: string]: string } | undefined
|
let privacySettings: { [_: string]: string } | undefined
|
||||||
|
|
||||||
const fetchPrivacySettings = async(force: boolean = false) => {
|
const fetchPrivacySettings = async(force: boolean = false) => {
|
||||||
@@ -122,11 +127,22 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const getUSyncDevices = async(jids: string[], ignoreZeroDevices: boolean) => {
|
const getUSyncDevices = async(jids: string[], ignoreZeroDevices: boolean) => {
|
||||||
|
const deviceResults: JidWithDevice[] = []
|
||||||
|
|
||||||
|
const users: BinaryNode[] = []
|
||||||
jids = Array.from(new Set(jids))
|
jids = Array.from(new Set(jids))
|
||||||
const users = jids.map<BinaryNode>(jid => ({
|
for(let jid of jids) {
|
||||||
tag: 'user',
|
const user = jidDecode(jid).user
|
||||||
attrs: { jid: jidNormalizedUser(jid) }
|
jid = jidNormalizedUser(jid)
|
||||||
}))
|
if(userDevicesCache.has(user)) {
|
||||||
|
const devices: JidWithDevice[] = userDevicesCache.get(user)
|
||||||
|
deviceResults.push(...devices)
|
||||||
|
|
||||||
|
logger.trace({ user }, 'using cache for devices')
|
||||||
|
} else {
|
||||||
|
users.push({ tag: 'user', attrs: { jid } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const iq: BinaryNode = {
|
const iq: BinaryNode = {
|
||||||
tag: 'iq',
|
tag: 'iq',
|
||||||
@@ -163,7 +179,22 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
const result = await query(iq)
|
const result = await query(iq)
|
||||||
const { device } = jidDecode(authState.creds.me!.id)
|
const { device } = jidDecode(authState.creds.me!.id)
|
||||||
return extractDeviceJids(result, device, ignoreZeroDevices)
|
|
||||||
|
const extracted = extractDeviceJids(result, device, ignoreZeroDevices)
|
||||||
|
const deviceMap: { [_: string]: JidWithDevice[] } = {}
|
||||||
|
|
||||||
|
for(const item of extracted) {
|
||||||
|
deviceMap[item.user] = deviceMap[item.user] || []
|
||||||
|
deviceMap[item.user].push(item)
|
||||||
|
|
||||||
|
deviceResults.push(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const key in deviceMap) {
|
||||||
|
userDevicesCache.set(key, deviceMap[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceResults
|
||||||
}
|
}
|
||||||
|
|
||||||
const assertSession = async(jid: string, force: boolean) => {
|
const assertSession = async(jid: string, force: boolean) => {
|
||||||
@@ -245,8 +276,8 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
for(const {user, device, agent} of devices) {
|
for(const {user, device} of devices) {
|
||||||
const jid = jidEncode(user, 's.whatsapp.net', device, agent)
|
const jid = jidEncode(user, 's.whatsapp.net', device)
|
||||||
const participant = await createParticipantNode(jid, encSenderKeyMsg)
|
const participant = await createParticipantNode(jid, encSenderKeyMsg)
|
||||||
participants.push(participant)
|
participants.push(participant)
|
||||||
}
|
}
|
||||||
@@ -301,11 +332,11 @@ export const makeMessagesSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
logger.debug(`got ${devices.length} additional devices`)
|
logger.debug(`got ${devices.length} additional devices`)
|
||||||
|
|
||||||
for(const { user, device, agent } of devices) {
|
for(const { user, device } of devices) {
|
||||||
const isMe = user === meUser
|
const isMe = user === meUser
|
||||||
participants.push(
|
participants.push(
|
||||||
await createParticipantNode(
|
await createParticipantNode(
|
||||||
jidEncode(user, 's.whatsapp.net', device, agent),
|
jidEncode(user, 's.whatsapp.net', device),
|
||||||
isMe ? encodedMeMsg : encodedMsg
|
isMe ? encodedMeMsg : encodedMsg
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import type EventEmitter from "events"
|
|||||||
import type { Agent } from "https"
|
import type { Agent } from "https"
|
||||||
import type { Logger } from "pino"
|
import type { Logger } from "pino"
|
||||||
import type { URL } from "url"
|
import type { URL } from "url"
|
||||||
|
import type NodeCache from 'node-cache'
|
||||||
|
|
||||||
import { AuthenticationState } from './Auth'
|
import { AuthenticationState } from './Auth'
|
||||||
import { Chat, PresenceData } from './Chat'
|
import { Chat, PresenceData } from './Chat'
|
||||||
@@ -45,6 +46,8 @@ export type SocketConfig = {
|
|||||||
printQRInTerminal: boolean
|
printQRInTerminal: boolean
|
||||||
/** should events be emitted for actions done by this socket connection */
|
/** should events be emitted for actions done by this socket connection */
|
||||||
emitOwnEvents: boolean
|
emitOwnEvents: boolean
|
||||||
|
/** provide a cache to store a user's device list */
|
||||||
|
userDevicesCache?: NodeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DisconnectReason {
|
export enum DisconnectReason {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { encodeBigEndian } from "./generics"
|
|||||||
import { Curve } from "./crypto"
|
import { Curve } from "./crypto"
|
||||||
import { SenderKeyDistributionMessage, GroupSessionBuilder, SenderKeyRecord, SenderKeyName, GroupCipher } from '../../WASignalGroup'
|
import { SenderKeyDistributionMessage, GroupSessionBuilder, SenderKeyRecord, SenderKeyName, GroupCipher } from '../../WASignalGroup'
|
||||||
import { SignalIdentity, SignalKeyStore, SignedKeyPair, KeyPair, AuthenticationState } from "../Types/Auth"
|
import { SignalIdentity, SignalKeyStore, SignedKeyPair, KeyPair, AuthenticationState } from "../Types/Auth"
|
||||||
import { assertNodeErrorFree, BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildUInt, jidDecode } from "../WABinary"
|
import { assertNodeErrorFree, BinaryNode, getBinaryNodeChild, getBinaryNodeChildBuffer, getBinaryNodeChildUInt, jidDecode, JidWithDevice } from "../WABinary"
|
||||||
import { proto } from "../../WAProto"
|
import { proto } from "../../WAProto"
|
||||||
|
|
||||||
export const generateSignalPubKey = (pubKey: Uint8Array | Buffer) => {
|
export const generateSignalPubKey = (pubKey: Uint8Array | Buffer) => {
|
||||||
@@ -232,7 +232,7 @@ export const parseAndInjectE2ESession = async(node: BinaryNode, auth: Authentica
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const extractDeviceJids = (result: BinaryNode, myDeviceId: number, excludeZeroDevices: boolean) => {
|
export const extractDeviceJids = (result: BinaryNode, myDeviceId: number, excludeZeroDevices: boolean) => {
|
||||||
const extracted: { user: string, device?: number, agent?: number }[] = []
|
const extracted: JidWithDevice[] = []
|
||||||
for(const node of result.content as BinaryNode[]) {
|
for(const node of result.content as BinaryNode[]) {
|
||||||
const list = getBinaryNodeChild(node, 'list')?.content
|
const list = getBinaryNodeChild(node, 'list')?.content
|
||||||
if(list && Array.isArray(list)) {
|
if(list && Array.isArray(list)) {
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ export const STORIES_JID = 'status@broadcast'
|
|||||||
|
|
||||||
export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call'
|
export type JidServer = 'c.us' | 'g.us' | 'broadcast' | 's.whatsapp.net' | 'call'
|
||||||
|
|
||||||
|
export type JidWithDevice = {
|
||||||
|
user: string
|
||||||
|
device?: number
|
||||||
|
}
|
||||||
|
|
||||||
export const jidEncode = (user: string | number | null, server: JidServer, device?: number, agent?: number) => {
|
export const jidEncode = (user: string | number | null, server: JidServer, device?: number, agent?: number) => {
|
||||||
return `${user || ''}${!!agent ? `_${agent}` : ''}${!!device ? `:${device}` : ''}@${server}`
|
return `${user || ''}${!!agent ? `_${agent}` : ''}${!!device ? `:${device}` : ''}@${server}`
|
||||||
}
|
}
|
||||||
|
|||||||
12
yarn.lock
12
yarn.lock
@@ -1471,6 +1471,11 @@ clone-response@^1.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-response "^1.0.0"
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
|
clone@2.x:
|
||||||
|
version "2.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f"
|
||||||
|
integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=
|
||||||
|
|
||||||
co@^4.6.0:
|
co@^4.6.0:
|
||||||
version "4.6.0"
|
version "4.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
@@ -2897,6 +2902,13 @@ neo-async@^2.6.0:
|
|||||||
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
|
||||||
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
|
||||||
|
|
||||||
|
node-cache@^5.1.2:
|
||||||
|
version "5.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-5.1.2.tgz#f264dc2ccad0a780e76253a694e9fd0ed19c398d"
|
||||||
|
integrity sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==
|
||||||
|
dependencies:
|
||||||
|
clone "2.x"
|
||||||
|
|
||||||
node-int64@^0.4.0:
|
node-int64@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
|
||||||
|
|||||||
Reference in New Issue
Block a user