feat: functional legacy socket

This commit is contained in:
Adhiraj Singh
2021-12-17 20:58:33 +05:30
parent d8b415a075
commit c803e22e8a
15 changed files with 695 additions and 66 deletions

View File

@@ -16,7 +16,7 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
} = config
const ev = new EventEmitter() as LegacyBaileysEventEmitter
let authInfo = initialAuthInfo || newLegacyAuthCreds()
const authInfo = initialAuthInfo || newLegacyAuthCreds()
const state: ConnectionState = {
legacy: {
@@ -73,7 +73,6 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
socket?.end(
new Boom('Logged Out', { statusCode: DisconnectReason.loggedOut })
)
authInfo = undefined
}
/** Waits for the connection to WA to open up */
const waitForConnection = async(waitInfinitely: boolean = false) => {
@@ -221,11 +220,13 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
const {user, auth} = validateNewConnection(response[1], authInfo, curveKeys)// validate the connection
const isNewLogin = user.id !== state.legacy!.user?.id
authInfo = auth
Object.assign(authInfo, auth)
updateEncKeys()
logger.info({ user }, 'logged in')
ev.emit('creds.update', auth)
updateState({
connection: 'open',
legacy: {
@@ -235,7 +236,6 @@ const makeAuthSocket = (config: LegacySocketConfig) => {
isNewLogin,
qr: undefined
})
ev.emit('creds.update', auth)
}
ws.once('open', async() => {
try {

View File

@@ -152,7 +152,7 @@ const makeChatsSocket = (config: LegacySocketConfig) => {
const chats = data.map(({ attrs }): Chat => {
return {
id: jidNormalizedUser(attrs.jid),
conversationTimestamp: +attrs.t,
conversationTimestamp: attrs.t ? +attrs.t : undefined,
unreadCount: +attrs.count,
archive: attrs.archive === 'true' ? true : undefined,
pin: attrs.pin ? +attrs.pin : undefined,
@@ -353,7 +353,7 @@ const makeChatsSocket = (config: LegacySocketConfig) => {
* @param jid the ID of the person/group who you are updating
* @param type your presence
*/
updatePresence: (jid: string | undefined, type: WAPresence) => (
sendPresenceUpdate: ( type: WAPresence, jid: string | undefined) => (
sendMessage({
binaryTag: [WAMetric.presence, WAFlag[type]], // weird stuff WA does
json: {
@@ -372,7 +372,7 @@ const makeChatsSocket = (config: LegacySocketConfig) => {
* Request updates on the presence of a user
* this returns nothing, you'll receive updates in chats.update event
* */
requestPresenceUpdate: async (jid: string) => (
presenceSubscribe: async (jid: string) => (
sendMessage({ json: ['action', 'presence', 'subscribe', jid] })
),
/** Query the status of the person (see groupMetadata() for groups) */

View File

@@ -1,14 +1,12 @@
import { LegacySocketConfig } from '../Types'
import { DEFAULT_LEGACY_CONNECTION_CONFIG } from '../Defaults'
import _makeConnection from './groups'
import _makeLegacySocket from './groups'
// export the last socket layer
const makeConnection = (config: Partial<LegacySocketConfig>) => (
_makeConnection({
const makeLegacySocket = (config: Partial<LegacySocketConfig>) => (
_makeLegacySocket({
...DEFAULT_LEGACY_CONNECTION_CONFIG,
...config
})
)
export type Connection = ReturnType<typeof makeConnection>
export default makeConnection
export default makeLegacySocket

View File

@@ -1,10 +1,9 @@
import { BinaryNode, getBinaryNodeMessages, isJidGroup, jidNormalizedUser, areJidsSameUser } from "../WABinary";
import { Boom } from '@hapi/boom'
import { Chat, WAPresence, WAMessageCursor, WAMessage, LegacySocketConfig, WAMessageKey, ParticipantAction, WAMessageStatus, WAMessageStubType, GroupMetadata, AnyMessageContent, MiscMessageGenerationOptions, WAFlag, WAMetric, WAUrlInfo, MediaConnInfo, MessageUpdateType, MessageInfo, MessageInfoUpdate, WAMediaUploadFunction, MediaType, WAMessageUpdate } from "../Types";
import { Chat, WAMessageCursor, WAMessage, LegacySocketConfig, WAMessageKey, ParticipantAction, WAMessageStatus, WAMessageStubType, GroupMetadata, AnyMessageContent, MiscMessageGenerationOptions, WAFlag, WAMetric, WAUrlInfo, MediaConnInfo, MessageUpdateType, MessageInfo, MessageInfoUpdate, WAMessageUpdate } from "../Types";
import { toNumber, generateWAMessage, decryptMediaMessageBuffer, extractMessageContent, getWAUploadToServer } from "../Utils";
import makeChatsSocket from "./chats";
import { DEFAULT_ORIGIN, MEDIA_PATH_MAP, WA_DEFAULT_EPHEMERAL } from "../Defaults";
import got from "got";
import { WA_DEFAULT_EPHEMERAL } from "../Defaults";
import { proto } from "../../WAProto";
const STATUS_MAP = {
@@ -288,8 +287,9 @@ const makeMessagesSocket = (config: LegacySocketConfig) => {
.then(() => emitUpdate(finalState))
.catch(() => emitUpdate(WAMessageStatus.ERROR))
}
onMessage(message, 'append')
if(config.emitOwnEvents) {
onMessage(message, 'append')
}
}
// messages received
@@ -362,7 +362,7 @@ const makeMessagesSocket = (config: LegacySocketConfig) => {
const updates = ids.map<MessageInfoUpdate>(id => ({
key: { ...keyPartial, id },
update: {
[updateKey]: { [jidNormalizedUser(attributes.participant)]: new Date(+attributes.t) }
[updateKey]: { [jidNormalizedUser(attributes.participant || attributes.to)]: new Date(+attributes.t) }
}
}))
ev.emit('message-info.update', updates)
@@ -489,7 +489,7 @@ const makeMessagesSocket = (config: LegacySocketConfig) => {
sendWAMessage: async(
jid: string,
content: AnyMessageContent,
options: MiscMessageGenerationOptions & { waitForAck?: boolean }
options: MiscMessageGenerationOptions & { waitForAck?: boolean } = { waitForAck: true }
) => {
const userJid = getState().legacy.user?.id
if(
@@ -521,7 +521,8 @@ const makeMessagesSocket = (config: LegacySocketConfig) => {
logger,
userJid: userJid,
getUrlInfo: generateUrlInfo,
upload: waUploadToServer
upload: waUploadToServer,
mediaCache: config.mediaCache
}
)

View File

@@ -2,7 +2,7 @@ import { Boom } from '@hapi/boom'
import { STATUS_CODES } from "http"
import { promisify } from "util"
import WebSocket from "ws"
import { BinaryNode, encodeBinaryNode } from "../WABinary"
import { BinaryNode, encodeBinaryNodeLegacy } from "../WABinary"
import { DisconnectReason, LegacySocketConfig, SocketQueryOptions, SocketSendMessageOptions, WAFlag, WAMetric, WATag } from "../Types"
import { aesEncrypt, hmacSign, promiseTimeout, unixTimestampSeconds, decodeWAMessage } from "../Utils"
import { DEFAULT_ORIGIN, DEF_CALLBACK_PREFIX, DEF_TAG_PREFIX, PHONE_CONNECTION_CB } from "../Defaults"
@@ -78,7 +78,7 @@ export const makeSocket = ({
if(!authInfo) {
throw new Boom('No encryption/mac keys to encrypt node with', { statusCode: 400 })
}
const binary = encodeBinaryNode(json) // encode the JSON to the WhatsApp binary format
const binary = encodeBinaryNodeLegacy(json) // encode the JSON to the WhatsApp binary format
const buff = aesEncrypt(binary, authInfo.encKey) // encrypt it using AES and our encKey
const sign = hmacSign(buff, authInfo.macKey) // sign the message using HMAC and our macKey
@@ -115,9 +115,9 @@ export const makeSocket = ({
ws.removeAllListeners('ws-close')
}
const onMessageRecieved = (message: string | Buffer) => {
if(message[0] === '!') {
if(message[0] === '!' || message[0] === '!'.charCodeAt(0)) {
// when the first character in the message is an '!', the server is sending a pong frame
const timestamp = message.slice(1, message.length).toString ('utf-8')
const timestamp = message.slice(1, message.length).toString()
lastDateRecv = new Date(parseInt(timestamp))
ws.emit('received-pong')
} else {
@@ -142,9 +142,9 @@ export const makeSocket = ({
/* Check if this is a response to a message we sent */
anyTriggered = ws.emit(`${DEF_TAG_PREFIX}${messageTag}`, json)
/* Check if this is a response to a message we are expecting */
const l0 = json.header || json[0] || ''
const l1 = json?.attributes || json?.[1] || { }
const l2 = json?.data?.[0]?.header || json[2]?.[0] || ''
const l0 = json.tag || json[0] || ''
const l1 = json?.attrs || json?.[1] || { }
const l2 = json?.content?.[0]?.tag || json[2]?.[0] || ''
Object.keys(l1).forEach(key => {
anyTriggered = ws.emit(`${DEF_CALLBACK_PREFIX}${l0},${key}:${l1[key]},${l2}`, json) || anyTriggered