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
|
||||
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
|
||||
} = 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
|
||||
|
||||
@@ -659,13 +669,18 @@ export const makeChatsSocket = (config: SocketConfig) => {
|
||||
|
||||
const sendPresenceUpdate = async (type: WAPresence, toJid?: string) => {
|
||||
const me = authState.creds.me!
|
||||
if (type === 'available' || type === 'unavailable') {
|
||||
const isAvailableType = type === 'available'
|
||||
if (isAvailableType || type === 'unavailable') {
|
||||
if (!me.name) {
|
||||
logger.warn('no name present, ignoring presence update request...')
|
||||
return
|
||||
}
|
||||
|
||||
ev.emit('connection.update', { isOnline: type === 'available' })
|
||||
ev.emit('connection.update', { isOnline: isAvailableType })
|
||||
|
||||
if (isAvailableType) {
|
||||
void sendUnifiedSession()
|
||||
}
|
||||
|
||||
await sendNode({
|
||||
tag: 'presence',
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
MIN_UPLOAD_INTERVAL,
|
||||
NOISE_WA_HEADER,
|
||||
PROCESSABLE_HISTORY_TYPES,
|
||||
TimeMs,
|
||||
UPLOAD_TIMEOUT
|
||||
} from '../Defaults'
|
||||
import type { LIDMapping, SocketConfig } from '../Types'
|
||||
@@ -77,6 +78,8 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
|
||||
const publicWAMBuffer = new BinaryInfo()
|
||||
|
||||
let serverTimeOffsetMs = 0
|
||||
|
||||
const uqTagId = generateMdTagPrefix()
|
||||
const generateMessageTag = () => `${uqTagId}${epoch++}`
|
||||
|
||||
@@ -895,6 +898,7 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
ws.on('CB:iq,,pair-success', async (stanza: BinaryNode) => {
|
||||
logger.debug('pair success recv')
|
||||
try {
|
||||
updateServerTimeOffset(stanza)
|
||||
const { reply, creds: updatedCreds } = configureSuccessfulPairing(stanza, creds)
|
||||
|
||||
logger.info(
|
||||
@@ -906,6 +910,7 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
ev.emit('connection.update', { isNewLogin: true, qr: undefined })
|
||||
|
||||
await sendNode(reply)
|
||||
void sendUnifiedSession()
|
||||
} catch (error: any) {
|
||||
logger.info({ trace: error.stack }, 'error in pairing')
|
||||
void end(error)
|
||||
@@ -914,6 +919,7 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
// login complete
|
||||
ws.on('CB:success', async (node: BinaryNode) => {
|
||||
try {
|
||||
updateServerTimeOffset(node)
|
||||
await uploadPreKeysToServerIfRequired()
|
||||
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('connection.update', { connection: 'open' })
|
||||
void sendUnifiedSession()
|
||||
|
||||
if (node.attrs.lid && authState.creds.me?.id) {
|
||||
const myLID = node.attrs.lid
|
||||
@@ -1041,6 +1048,54 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
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 {
|
||||
type: 'md' as 'md',
|
||||
ws,
|
||||
@@ -1064,6 +1119,8 @@ export const makeSocket = (config: SocketConfig) => {
|
||||
digestKeyBundle,
|
||||
rotateSignedPreKey,
|
||||
requestPairingCode,
|
||||
updateServerTimeOffset,
|
||||
sendUnifiedSession,
|
||||
wamBuffer: publicWAMBuffer,
|
||||
/** Waits for the connection to WA to reach a state */
|
||||
waitForConnectionUpdate: bindWaitForConnectionUpdate(ev),
|
||||
|
||||
Reference in New Issue
Block a user