feat: add desktop + full history sync opts

This commit is contained in:
Adhiraj Singh
2022-07-26 13:29:29 +05:30
parent 9aa9006236
commit d04718e27a
6 changed files with 58 additions and 33 deletions

View File

@@ -103,35 +103,44 @@ The entire `SocketConfig` structure is mentioned here with default values:
``` ts ``` ts
type SocketConfig = { type SocketConfig = {
/** provide an auth state object to maintain the auth state */ /** provide an auth state object to maintain the auth state */
auth?: AuthenticationState auth: AuthenticationState
/** the WS url to connect to WA */ /** By default true, should history messages be downloaded and processed */
waWebSocketUrl: string | URL downloadHistory: boolean
/** Fails the connection if the connection times out in this time interval or no data is received */ /** transaction capability options for SignalKeyStore */
connectTimeoutMs: number transactionOpts: TransactionCapabilityOptions
/** Default timeout for queries, undefined for no timeout */ /** provide a cache to store a user's device list */
defaultQueryTimeoutMs: number | undefined userDevicesCache?: NodeCache
/** ping-pong interval for WS connection */ /** marks the client as online whenever the socket successfully connects */
keepAliveIntervalMs: number markOnlineOnConnect: boolean
/** proxy agent */ /**
agent?: Agent * map to store the retry counts for failed messages;
/** pino logger */ * used to determine whether to retry a message or not */
logger: Logger msgRetryCounterMap?: MessageRetryMap
/** version to connect with */ /** width for link preview images */
version: WAVersion linkPreviewImageThumbnailWidth: number
/** override browser config */ /** Should Baileys ask the phone for full history, will be received async */
browser: WABrowserDescription syncFullHistory: boolean
/** agent used for fetch requests -- uploading/downloading media */ /**
fetchAgent?: Agent * fetch a message from your store
/** should the QR be printed in the terminal */ * implement this so that messages failed to send (solves the "this message can take a while" issue) can be retried
printQRInTerminal: boolean
/**
* fetch a message from your store
* implement this so that messages that failed to send (solves the "this message can take a while" issue) can be retried
* */ * */
getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined> getMessage: (key: proto.IMessageKey) => Promise<proto.IMessage | undefined>
} }
``` ```
### Emulating the Desktop app instead of the web
1. Baileys, by default, emulates a chrome web session
2. If you'd like to emulate a desktop connection (and receive more message history), add this to your Socket config:
``` ts
const conn = makeWASocket({
...otherOpts,
// can use Windows, Ubuntu here too
browser: Browsers.macOS('Desktop'),
syncFullHistory: true
})
```
## Saving & Restoring Sessions ## Saving & Restoring Sessions
You obviously don't want to keep scanning the QR code every time you want to connect. You obviously don't want to keep scanning the QR code every time you want to connect.

View File

@@ -45,6 +45,7 @@ export const DEFAULT_CONNECTION_CONFIG: SocketConfig = {
auth: undefined as any, auth: undefined as any,
downloadHistory: true, downloadHistory: true,
markOnlineOnConnect: true, markOnlineOnConnect: true,
syncFullHistory: false,
linkPreviewImageThumbnailWidth: 192, linkPreviewImageThumbnailWidth: 192,
transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 }, transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 3000 },
getMessage: async() => undefined getMessage: async() => undefined

View File

@@ -25,6 +25,7 @@ export const makeSocket = ({
auth: authState, auth: authState,
printQRInTerminal, printQRInTerminal,
defaultQueryTimeoutMs, defaultQueryTimeoutMs,
syncFullHistory,
transactionOpts transactionOpts
}: SocketConfig) => { }: SocketConfig) => {
const ws = new WebSocket(waWebSocketUrl, undefined, { const ws = new WebSocket(waWebSocketUrl, undefined, {
@@ -178,12 +179,14 @@ export const makeSocket = ({
const keyEnc = noise.processHandshake(handshake, creds.noiseKey) const keyEnc = noise.processHandshake(handshake, creds.noiseKey)
const config = { version, browser, syncFullHistory }
let node: proto.IClientPayload let node: proto.IClientPayload
if(!creds.me) { if(!creds.me) {
node = generateRegistrationNode(creds, { version, browser }) node = generateRegistrationNode(creds, config)
logger.info({ node }, 'not logged in, attempting registration...') logger.info({ node }, 'not logged in, attempting registration...')
} else { } else {
node = generateLoginNode(creds.me!.id, { version, browser }) node = generateLoginNode(creds.me!.id, config)
logger.info({ node }, 'logging in...') logger.info({ node }, 'logging in...')
} }

View File

@@ -34,6 +34,8 @@ export type SocketConfig = CommonSocketConfig & {
msgRetryCounterMap?: MessageRetryMap msgRetryCounterMap?: MessageRetryMap
/** width for link preview images */ /** width for link preview images */
linkPreviewImageThumbnailWidth: number linkPreviewImageThumbnailWidth: number
/** Should Baileys ask the phone for full history, will be received async */
syncFullHistory: boolean
/** /**
* fetch a message from your store * fetch a message from your store
* implement this so that messages failed to send (solves the "this message can take a while" issue) can be retried * implement this so that messages failed to send (solves the "this message can take a while" issue) can be retried

View File

@@ -52,7 +52,7 @@ export const processHistoryMessage = (
const curItem = recvChats[message.key.remoteJid!] const curItem = recvChats[message.key.remoteJid!]
const timestamp = toNumber(message.messageTimestamp) const timestamp = toNumber(message.messageTimestamp)
if(!message.key.fromMe && (!curItem || timestamp > curItem.lastMsgRecvTimestamp)) { if(!message.key.fromMe && (!curItem || timestamp > curItem.lastMsgRecvTimestamp)) {
recvChats[message.key.remoteJid!] = { lastMsgRecvTimestamp: timestamp } recvChats[chat.id] = { lastMsgRecvTimestamp: timestamp }
// keep only the most recent message in the chat array // keep only the most recent message in the chat array
chat.messages = [{ message }] chat.messages = [{ message }]
} }

View File

@@ -8,7 +8,7 @@ import { Curve, hmacSign } from './crypto'
import { encodeBigEndian } from './generics' import { encodeBigEndian } from './generics'
import { createSignalIdentity } from './signal' import { createSignalIdentity } from './signal'
type ClientPayloadConfig = Pick<SocketConfig, 'version' | 'browser'> type ClientPayloadConfig = Pick<SocketConfig, 'version' | 'browser' | 'syncFullHistory'>
const getUserAgent = ({ version }: ClientPayloadConfig): proto.IUserAgent => { const getUserAgent = ({ version }: ClientPayloadConfig): proto.IUserAgent => {
const osVersion = '0.1' const osVersion = '0.1'
@@ -31,16 +31,26 @@ const getUserAgent = ({ version }: ClientPayloadConfig): proto.IUserAgent => {
} }
} }
const getWebInfo = (): proto.IWebInfo => ({ const PLATFORM_MAP = {
webSubPlatform: proto.WebInfo.WebInfoWebSubPlatform.WEB_BROWSER 'Mac OS': proto.WebInfo.WebInfoWebSubPlatform.DARWIN,
}) 'Windows': proto.WebInfo.WebInfoWebSubPlatform.WIN32
}
const getWebInfo = (config: ClientPayloadConfig): proto.IWebInfo => {
let webSubPlatform = proto.WebInfo.WebInfoWebSubPlatform.WEB_BROWSER
if(config.syncFullHistory && PLATFORM_MAP[config.browser[0]]) {
webSubPlatform = PLATFORM_MAP[config.browser[0]]
}
return { webSubPlatform }
}
const getClientPayload = (config: ClientPayloadConfig): proto.IClientPayload => { const getClientPayload = (config: ClientPayloadConfig): proto.IClientPayload => {
return { return {
connectType: proto.ClientPayload.ClientPayloadConnectType.WIFI_UNKNOWN, connectType: proto.ClientPayload.ClientPayloadConnectType.WIFI_UNKNOWN,
connectReason: proto.ClientPayload.ClientPayloadConnectReason.USER_ACTIVATED, connectReason: proto.ClientPayload.ClientPayloadConnectReason.USER_ACTIVATED,
userAgent: getUserAgent(config), userAgent: getUserAgent(config),
webInfo: getWebInfo(), webInfo: getWebInfo(config),
} }
} }
@@ -75,7 +85,7 @@ export const generateRegistrationNode = (
}, },
platformType: proto.DeviceProps.DevicePropsPlatformType[config.browser[1].toUpperCase()] platformType: proto.DeviceProps.DevicePropsPlatformType[config.browser[1].toUpperCase()]
|| proto.DeviceProps.DevicePropsPlatformType.UNKNOWN, || proto.DeviceProps.DevicePropsPlatformType.UNKNOWN,
requireFullSync: false, requireFullSync: config.syncFullHistory,
} }
const companionProto = proto.DeviceProps.encode(companion).finish() const companionProto = proto.DeviceProps.encode(companion).finish()