Skip to content

Commit

Permalink
mobile: deprecation.
Browse files Browse the repository at this point in the history
  • Loading branch information
PurpShell committed Oct 14, 2024
1 parent 647f8d7 commit b86cd30
Show file tree
Hide file tree
Showing 17 changed files with 43 additions and 528 deletions.
88 changes: 3 additions & 85 deletions Example/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ logger.level = 'trace'
const useStore = !process.argv.includes('--no-store')
const doReplies = process.argv.includes('--do-reply')
const usePairingCode = process.argv.includes('--use-pairing-code')
const useMobile = process.argv.includes('--mobile')

// external map to store retry counts of messages when decryption/encryption fails
// keep this out of the socket itself, so as to prevent a message decryption/encryption loop across socket restarts
Expand Down Expand Up @@ -45,7 +44,6 @@ const startSock = async() => {
version,
logger,
printQRInTerminal: !usePairingCode,
mobile: useMobile,
auth: {
creds: state.creds,
/** caching makes the store faster to send/recv messages */
Expand All @@ -63,93 +61,13 @@ const startSock = async() => {
store?.bind(sock.ev)

// Pairing code for Web clients
if(usePairingCode && !sock.authState.creds.registered) {
if(useMobile) {
throw new Error('Cannot use pairing code with mobile api')
}

const phoneNumber = await question('Please enter your mobile phone number:\n')
if (usePairingCode && !sock.authState.creds.registered) {
// todo move to QR event
const phoneNumber = await question('Please enter your phone number:\n')
const code = await sock.requestPairingCode(phoneNumber)
console.log(`Pairing code: ${code}`)
}

// If mobile was chosen, ask for the code
if(useMobile && !sock.authState.creds.registered) {
const { registration } = sock.authState.creds || { registration: {} }

if(!registration.phoneNumber) {
registration.phoneNumber = await question('Please enter your mobile phone number:\n')
}

const libPhonenumber = await import("libphonenumber-js")
const phoneNumber = libPhonenumber.parsePhoneNumber(registration!.phoneNumber)
if(!phoneNumber?.isValid()) {
throw new Error('Invalid phone number: ' + registration!.phoneNumber)
}

registration.phoneNumber = phoneNumber.format('E.164')
registration.phoneNumberCountryCode = phoneNumber.countryCallingCode
registration.phoneNumberNationalNumber = phoneNumber.nationalNumber
const mcc = PHONENUMBER_MCC[phoneNumber.countryCallingCode]
if(!mcc) {
throw new Error('Could not find MCC for phone number: ' + registration!.phoneNumber + '\nPlease specify the MCC manually.')
}

registration.phoneNumberMobileCountryCode = mcc

async function enterCode() {
try {
const code = await question('Please enter the one time code:\n')
const response = await sock.register(code.replace(/["']/g, '').trim().toLowerCase())
console.log('Successfully registered your phone number.')
console.log(response)
rl.close()
} catch(error) {
console.error('Failed to register your phone number. Please try again.\n', error)
await askForOTP()
}
}

async function enterCaptcha() {
const response = await sock.requestRegistrationCode({ ...registration, method: 'captcha' })
const path = __dirname + '/captcha.png'
fs.writeFileSync(path, Buffer.from(response.image_blob!, 'base64'))

open(path)
const code = await question('Please enter the captcha code:\n')
fs.unlinkSync(path)
registration.captcha = code.replace(/["']/g, '').trim().toLowerCase()
}

async function askForOTP() {
if (!registration.method) {
await delay(2000)
let code = await question('How would you like to receive the one time code for registration? "sms" or "voice"\n')
code = code.replace(/["']/g, '').trim().toLowerCase()
if(code !== 'sms' && code !== 'voice') {
return await askForOTP()
}

registration.method = code
}

try {
await sock.requestRegistrationCode(registration)
await enterCode()
} catch(error) {
console.error('Failed to request registration code. Please try again.\n', error)

if(error?.reason === 'code_checkpoint') {
await enterCaptcha()
}

await askForOTP()
}
}

askForOTP()
}

const sendMessageWTyping = async(msg: AnyMessageContent, jid: string) => {
await sock.presenceSubscribe(jid)
await delay(500)
Expand Down
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,6 @@ connectToWhatsApp()

If the connection is successful, you will see a QR code printed on your terminal screen, scan it with WhatsApp on your phone and you'll be logged in!

**Note:** install `qrcode-terminal` using `yarn add qrcode-terminal` to auto-print the QR to the terminal.

**Note:** the code to support the legacy version of WA Web (pre multi-device) has been removed in v5. Only the standard multi-device connection is now supported. This is done as WA seems to have completely dropped support for the legacy version.

## Connecting native mobile api

Baileys also supports the native mobile API, which allows users to authenticate as a standalone WhatsApp client using their phone number.

Run the [example](Example/example.ts) file with ``--mobile`` cli flag to use the native mobile API.

## Configuring the Connection

You can configure the connection by passing a `SocketConfig` object.
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
"changelog:preview": "conventional-changelog -p angular -u",
"changelog:update": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
"example": "node --inspect -r ts-node/register Example/example.ts",
"example:mobile": "node --inspect -r ts-node/register Example/example.ts --mobile",
"gen:protobuf": "sh WAProto/GenerateStatics.sh",
"lint": "eslint src --ext .js,.ts,.jsx,.tsx",
"lint:fix": "eslint src --fix --ext .js,.ts,.jsx,.tsx",
Expand Down
16 changes: 0 additions & 16 deletions src/Defaults/index.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
import { createHash } from 'crypto'
import { proto } from '../../WAProto'
import { makeLibSignalRepository } from '../Signal/libsignal'
import type { AuthenticationState, MediaType, SocketConfig, WAVersion } from '../Types'
import { Browsers } from '../Utils'
import logger from '../Utils/logger'
import { version } from './baileys-version.json'
import phoneNumberMCC from './phonenumber-mcc.json'

export const UNAUTHORIZED_CODES = [401, 403, 419]

export const PHONENUMBER_MCC = phoneNumberMCC

export const DEFAULT_ORIGIN = 'https://web.whatsapp.com'
export const MOBILE_ENDPOINT = 'g.whatsapp.net'
export const MOBILE_PORT = 443
export const DEF_CALLBACK_PREFIX = 'CB:'
export const DEF_TAG_PREFIX = 'TAG:'
export const PHONE_CONNECTION_CB = 'CB:Pong'

export const WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60

const WA_VERSION = '2.24.6.77'

const WA_VERSION_HASH = createHash('md5').update(WA_VERSION).digest('hex')
export const MOBILE_TOKEN = Buffer.from('0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM' + WA_VERSION_HASH)
export const MOBILE_REGISTRATION_ENDPOINT = 'https://v.whatsapp.net/v2'
export const MOBILE_USERAGENT = `WhatsApp/${WA_VERSION} iOS/15.3.1 Device/Apple-iPhone_7`
export const REGISTRATION_PUBLIC_KEY = Buffer.from([
5, 142, 140, 15, 116, 195, 235, 197, 215, 166, 134, 92, 108, 60, 132, 56, 86, 176, 97, 33, 204, 232, 234, 119, 77,
34, 251, 111, 18, 37, 18, 48, 45,
])
export const NOISE_MODE = 'Noise_XX_25519_AESGCM_SHA256\0\0\0\0'
export const DICT_VERSION = 2
export const KEY_BUNDLE_TYPE = Buffer.from([5])
Expand Down
5 changes: 2 additions & 3 deletions src/Socket/Client/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './abstract-socket-client'
export * from './mobile-socket-client'
export * from './web-socket-client'
export * from './types'
export * from './websocket'
66 changes: 0 additions & 66 deletions src/Socket/Client/mobile-socket-client.ts

This file was deleted.

File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import WebSocket from 'ws'
import { DEFAULT_ORIGIN } from '../../Defaults'
import { AbstractSocketClient } from './abstract-socket-client'
import { AbstractSocketClient } from './types'

export class WebSocketClient extends AbstractSocketClient {

Expand Down
10 changes: 6 additions & 4 deletions src/Socket/chats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import NodeCache from 'node-cache'
import { proto } from '../../WAProto'
import { DEFAULT_CACHE_TTLS, PROCESSABLE_HISTORY_TYPES } from '../Defaults'
import { ALL_WA_PATCH_NAMES, ChatModification, ChatMutation, LTHashState, MessageUpsertType, PresenceData, SocketConfig, WABusinessHoursConfig, WABusinessProfile, WAMediaUpload, WAMessage, WAPatchCreate, WAPatchName, WAPresence, WAPrivacyCallValue, WAPrivacyGroupAddValue, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '../Types'
import { LabelActionBody } from '../Types/Label'
import { chatModificationToAppPatch, ChatMutationMap, decodePatches, decodeSyncdSnapshot, encodeSyncdPatch, extractSyncdPatches, generateProfilePicture, getHistoryMsg, newLTHashState, processSyncAction } from '../Utils'
import { makeMutex } from '../Utils/make-mutex'
import processMessage from '../Utils/process-message'
import { BinaryNode, getBinaryNodeChild, getBinaryNodeChildren, jidNormalizedUser, reduceBinaryNodeToDictionary, S_WHATSAPP_NET } from '../WABinary'
import { makeSocket } from './socket'
import { Label, LabelActionBody } from '../Types/Label'

const MAX_SYNC_ATTEMPTS = 2

Expand Down Expand Up @@ -221,7 +221,7 @@ export const makeChatsSocket = (config: SocketConfig) => {

/** update the profile picture for yourself or a group */
const updateProfilePicture = async(jid: string, content: WAMediaUpload) => {
let targetJid;
let targetJid
if(!jid) {
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
}
Expand Down Expand Up @@ -251,7 +251,7 @@ export const makeChatsSocket = (config: SocketConfig) => {

/** remove the profile picture for yourself or a group */
const removeProfilePicture = async(jid: string) => {
let targetJid;
let targetJid
if(!jid) {
throw new Boom('Illegal no-jid profile update. Please specify either your ID or the ID of the chat you wish to update')
}
Expand Down Expand Up @@ -777,6 +777,7 @@ export const makeChatsSocket = (config: SocketConfig) => {
authState.creds.lastPropHash = propsNode?.attrs?.hash
ev.emit('creds.update', authState.creds)
}

props = reduceBinaryNodeToDictionary(propsNode, 'prop')
}

Expand Down Expand Up @@ -1002,7 +1003,8 @@ export const makeChatsSocket = (config: SocketConfig) => {
// if we don't have the app state key
// we keep buffering events until we finally have
// the key and can sync the messages
if(!authState.creds?.myAppStateKeyId && !config.mobile) {
// todo scrutinize
if(!authState.creds?.myAppStateKeyId) {
ev.buffer()
needToFlushWithAppStateSync = true
}
Expand Down
12 changes: 5 additions & 7 deletions src/Socket/messages-send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -469,17 +469,15 @@ export const makeMessagesSocket = (config: SocketConfig) => {

await authState.keys.set({ 'sender-key-memory': { [jid]: senderKeyMap } })
} else {
const { user: meUser, device: meDevice } = jidDecode(meId)!
const { user: meUser } = jidDecode(meId)!

if(!participant) {
devices.push({ user })
// do not send message to self if the device is 0 (mobile)

if(!(additionalAttributes?.['category'] === 'peer' && user === meUser)) {
if(meDevice !== undefined && meDevice !== 0) {
devices.push({ user: meUser })
}
if(user !== meUser) {
devices.push({ user: meUser })
}

if(additionalAttributes?.['category'] !== 'peer') {
const additionalDevices = await getUSyncDevices([ meId, jid ], !!useUserDevicesCache, true)
devices.push(...additionalDevices)
}
Expand Down
Loading

0 comments on commit b86cd30

Please sign in to comment.