feat: send unified session (#2294)
* fix: improve message resend logic by adding checks for message IDs * Revert "fix: improve message resend logic by adding checks for message IDs" This reverts commit c03f9d8e6fc6cbfbb9d1f8f67c169700e704213d. * feat: add unified session handling and time constants * refactor: improve socket variable destructuring and presence update logic * fix: remove unnecessary semicolons in socket and time constants definitions * fix: handle invalid server time offset parsing in makeSocket function
This commit is contained in:
@@ -137,3 +137,10 @@ export const DEFAULT_CACHE_TTLS = {
|
|||||||
CALL_OFFER: 5 * 60, // 5 minutes
|
CALL_OFFER: 5 * 60, // 5 minutes
|
||||||
USER_DEVICES: 5 * 60 // 5 minutes
|
USER_DEVICES: 5 * 60 // 5 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TimeMs = {
|
||||||
|
Minute: 60 * 1000,
|
||||||
|
Hour: 60 * 60 * 1000,
|
||||||
|
Day: 24 * 60 * 60 * 1000,
|
||||||
|
Week: 7 * 24 * 60 * 60 * 1000
|
||||||
|
}
|
||||||
|
|||||||
+18
-3
@@ -68,7 +68,17 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
getMessage
|
getMessage
|
||||||
} = config
|
} = config
|
||||||
const sock = makeSocket(config)
|
const sock = makeSocket(config)
|
||||||
const { ev, ws, authState, generateMessageTag, sendNode, query, signalRepository, onUnexpectedError } = sock
|
const {
|
||||||
|
ev,
|
||||||
|
ws,
|
||||||
|
authState,
|
||||||
|
generateMessageTag,
|
||||||
|
sendNode,
|
||||||
|
query,
|
||||||
|
signalRepository,
|
||||||
|
onUnexpectedError,
|
||||||
|
sendUnifiedSession
|
||||||
|
} = sock
|
||||||
|
|
||||||
let privacySettings: { [_: string]: string } | undefined
|
let privacySettings: { [_: string]: string } | undefined
|
||||||
|
|
||||||
@@ -659,13 +669,18 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
const sendPresenceUpdate = async (type: WAPresence, toJid?: string) => {
|
const sendPresenceUpdate = async (type: WAPresence, toJid?: string) => {
|
||||||
const me = authState.creds.me!
|
const me = authState.creds.me!
|
||||||
if (type === 'available' || type === 'unavailable') {
|
const isAvailableType = type === 'available'
|
||||||
|
if (isAvailableType || type === 'unavailable') {
|
||||||
if (!me.name) {
|
if (!me.name) {
|
||||||
logger.warn('no name present, ignoring presence update request...')
|
logger.warn('no name present, ignoring presence update request...')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ev.emit('connection.update', { isOnline: type === 'available' })
|
ev.emit('connection.update', { isOnline: isAvailableType })
|
||||||
|
|
||||||
|
if (isAvailableType) {
|
||||||
|
void sendUnifiedSession()
|
||||||
|
}
|
||||||
|
|
||||||
await sendNode({
|
await sendNode({
|
||||||
tag: 'presence',
|
tag: 'presence',
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
MIN_UPLOAD_INTERVAL,
|
MIN_UPLOAD_INTERVAL,
|
||||||
NOISE_WA_HEADER,
|
NOISE_WA_HEADER,
|
||||||
PROCESSABLE_HISTORY_TYPES,
|
PROCESSABLE_HISTORY_TYPES,
|
||||||
|
TimeMs,
|
||||||
UPLOAD_TIMEOUT
|
UPLOAD_TIMEOUT
|
||||||
} from '../Defaults'
|
} from '../Defaults'
|
||||||
import type { LIDMapping, SocketConfig } from '../Types'
|
import type { LIDMapping, SocketConfig } from '../Types'
|
||||||
@@ -77,6 +78,8 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
|
|
||||||
const publicWAMBuffer = new BinaryInfo()
|
const publicWAMBuffer = new BinaryInfo()
|
||||||
|
|
||||||
|
let serverTimeOffsetMs = 0
|
||||||
|
|
||||||
const uqTagId = generateMdTagPrefix()
|
const uqTagId = generateMdTagPrefix()
|
||||||
const generateMessageTag = () => `${uqTagId}${epoch++}`
|
const generateMessageTag = () => `${uqTagId}${epoch++}`
|
||||||
|
|
||||||
@@ -895,6 +898,7 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
ws.on('CB:iq,,pair-success', async (stanza: BinaryNode) => {
|
ws.on('CB:iq,,pair-success', async (stanza: BinaryNode) => {
|
||||||
logger.debug('pair success recv')
|
logger.debug('pair success recv')
|
||||||
try {
|
try {
|
||||||
|
updateServerTimeOffset(stanza)
|
||||||
const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds)
|
const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds)
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
@@ -906,6 +910,7 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
ev.emit('connection.update', { isNewLogin: true, qr: undefined })
|
ev.emit('connection.update', { isNewLogin: true, qr: undefined })
|
||||||
|
|
||||||
await sendNode(reply)
|
await sendNode(reply)
|
||||||
|
void sendUnifiedSession()
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
logger.info({ trace: error.stack }, 'error in pairing')
|
logger.info({ trace: error.stack }, 'error in pairing')
|
||||||
void end(error)
|
void end(error)
|
||||||
@@ -914,6 +919,7 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
// login complete
|
// login complete
|
||||||
ws.on('CB:success', async (node: BinaryNode) => {
|
ws.on('CB:success', async (node: BinaryNode) => {
|
||||||
try {
|
try {
|
||||||
|
updateServerTimeOffset(node)
|
||||||
await uploadPreKeysToServerIfRequired()
|
await uploadPreKeysToServerIfRequired()
|
||||||
await sendPassiveIq('active')
|
await sendPassiveIq('active')
|
||||||
|
|
||||||
@@ -933,6 +939,7 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
ev.emit('creds.update', { me: { ...authState.creds.me!, lid: node.attrs.lid } })
|
ev.emit('creds.update', { me: { ...authState.creds.me!, lid: node.attrs.lid } })
|
||||||
|
|
||||||
ev.emit('connection.update', { connection: 'open' })
|
ev.emit('connection.update', { connection: 'open' })
|
||||||
|
void sendUnifiedSession()
|
||||||
|
|
||||||
if (node.attrs.lid && authState.creds.me?.id) {
|
if (node.attrs.lid && authState.creds.me?.id) {
|
||||||
const myLID = node.attrs.lid
|
const myLID = node.attrs.lid
|
||||||
@@ -1041,6 +1048,54 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
Object.assign(creds, update)
|
Object.assign(creds, update)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const updateServerTimeOffset = ({ attrs }: BinaryNode) => {
|
||||||
|
const tValue = attrs?.t
|
||||||
|
if (!tValue) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const parsed = Number(tValue)
|
||||||
|
if (Number.isNaN(parsed) || parsed <= 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const localMs = Date.now()
|
||||||
|
serverTimeOffsetMs = parsed * 1000 - localMs
|
||||||
|
logger.debug({ offset: serverTimeOffsetMs }, 'calculated server time offset')
|
||||||
|
}
|
||||||
|
|
||||||
|
const getUnifiedSessionId = () => {
|
||||||
|
const offsetMs = 3 * TimeMs.Day
|
||||||
|
const now = Date.now() + serverTimeOffsetMs
|
||||||
|
const id = (now + offsetMs) % TimeMs.Week
|
||||||
|
return id.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
const sendUnifiedSession = async () => {
|
||||||
|
if (!ws.isOpen) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
tag: 'ib',
|
||||||
|
attrs: {},
|
||||||
|
content: [
|
||||||
|
{
|
||||||
|
tag: 'unified_session',
|
||||||
|
attrs: {
|
||||||
|
id: getUnifiedSessionId()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendNode(node)
|
||||||
|
} catch (error) {
|
||||||
|
logger.debug({ error }, 'failed to send unified_session telemetry')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: 'md' as 'md',
|
type: 'md' as 'md',
|
||||||
ws,
|
ws,
|
||||||
@@ -1064,6 +1119,8 @@ export const makeSocket = (config: SocketConfig) => {
|
|||||||
digestKeyBundle,
|
digestKeyBundle,
|
||||||
rotateSignedPreKey,
|
rotateSignedPreKey,
|
||||||
requestPairingCode,
|
requestPairingCode,
|
||||||
|
updateServerTimeOffset,
|
||||||
|
sendUnifiedSession,
|
||||||
wamBuffer: publicWAMBuffer,
|
wamBuffer: publicWAMBuffer,
|
||||||
/** Waits for the connection to WA to reach a state */
|
/** Waits for the connection to WA to reach a state */
|
||||||
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
|
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
|
||||||
|
|||||||
Reference in New Issue
Block a user