fix: registration + add captcha support (#227)

* fix: registration + update mobile version

* feat: add captcha support for registration

* fix: jid protocol address missing device

* fix: linting errors
This commit is contained in:
Samuel Scheit
2023-08-10 11:15:12 +02:00
committed by GitHub
parent 30b96c528b
commit 49ab16f592
5 changed files with 43 additions and 17 deletions

View File

@@ -3,6 +3,8 @@ import NodeCache from 'node-cache'
import readline from 'readline'
import makeWASocket, { AnyMessageContent, delay, DisconnectReason, fetchLatestBaileysVersion, getAggregateVotesInPollMessage, makeCacheableSignalKeyStore, makeInMemoryStore, PHONENUMBER_MCC, proto, useMultiFileAuthState, WAMessageContent, WAMessageKey } from '../src'
import MAIN_LOGGER from '../src/Utils/logger'
import open from 'open'
import fs from 'fs'
const logger = MAIN_LOGGER.child({})
logger.level = 'trace'
@@ -105,21 +107,38 @@ const startSock = async() => {
}
}
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() {
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 (!registration.method) {
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()
}
if(code !== 'sms' && code !== 'voice') {
return await askForOTP()
registration.method = code
}
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()
}
}

View File

@@ -69,6 +69,7 @@
"jest": "^27.0.6",
"jimp": "^0.16.1",
"link-preview-js": "^3.0.0",
"open": "^8.4.2",
"qrcode-terminal": "^0.12.0",
"release-it": "^15.10.3",
"sharp": "^0.30.5",

View File

@@ -19,6 +19,7 @@ export const PHONE_CONNECTION_CB = 'CB:Pong'
export const WA_DEFAULT_EPHEMERAL = 7 * 24 * 60 * 60
export const MOBILE_TOKEN = Buffer.from('0a1mLfGUIBVrMKF1RdvLI5lkRBvof6vn0fD2QRSM3d3683e76445591c0591bc3c034c3bca')
export const MOBILE_REGISTRATION_ENDPOINT = 'https://v.whatsapp.net/v2'
export const MOBILE_USERAGENT = 'WhatsApp/2.23.13.82 iOS/15.3.1 Device/Apple-iPhone_7'

View File

@@ -3,6 +3,7 @@ import { GroupCipher, GroupSessionBuilder, SenderKeyDistributionMessage, SenderK
import { SignalAuthState } from '../Types'
import { SignalRepository } from '../Types/Signal'
import { generateSignalPubKey } from '../Utils'
import { jidDecode } from '../WABinary'
export function makeLibSignalRepository(auth: SignalAuthState): SignalRepository {
const storage = signalStorage(auth)
@@ -76,10 +77,9 @@ export function makeLibSignalRepository(auth: SignalAuthState): SignalRepository
}
}
const jidToSignalAddress = (jid: string) => jid.split('@')[0]
const jidToSignalProtocolAddress = (jid: string) => {
return new libsignal.ProtocolAddress(jidToSignalAddress(jid), 0)
const { user, device } = jidDecode(jid)!
return new libsignal.ProtocolAddress(user, device || 0)
}
const jidToSignalSenderKeyName = (group: string, user: string): string => {

View File

@@ -86,7 +86,11 @@ export interface RegistrationOptions {
/**
* How to send the one time code
*/
method?: 'sms' | 'voice'
method?: 'sms' | 'voice' | 'captcha'
/**
* The captcha code if it was requested
*/
captcha?: string
}
export type RegistrationParams = RegistrationData & RegistrationOptions
@@ -136,6 +140,7 @@ export function registrationParams(params: RegistrationParams) {
id: convertBufferToUrlHex(params.identityId),
backup_token: convertBufferToUrlHex(params.backupToken),
token: md5(Buffer.concat([MOBILE_TOKEN, Buffer.from(params.phoneNumberNationalNumber)])).toString('hex'),
fraud_checkpoint_code: params.captcha,
}
}
@@ -196,13 +201,11 @@ export async function mobileRegisterFetch(path: string, opts: AxiosRequestConfig
const parameter = [] as string[]
for(const param in opts.params) {
parameter.push(param + '=' + urlencode(opts.params[param]))
if(opts.params[param] !== null && opts.params[param] !== undefined) {
parameter.push(param + '=' + urlencode(opts.params[param]))
}
}
console.log('parameter', opts.params, parameter)
// const params = urlencode(mobileRegisterEncrypt(parameter.join('&')))
// url += `?ENC=${params}`
url += `?${parameter.join('&')}`
delete opts.params
}
@@ -230,16 +233,18 @@ export async function mobileRegisterFetch(path: string, opts: AxiosRequestConfig
export interface ExistsResponse {
status: 'fail'
status: 'fail' | 'sent'
voice_length?: number
voice_wait?: number
sms_length?: number
sms_wait?: number
reason?: 'incorrect' | 'missing_param'
reason?: 'incorrect' | 'missing_param' | 'code_checkpoint'
login?: string
flash_type?: number
ab_hash?: string
ab_key?: string
exp_cfg?: string
lid?: string
image_blob?: string
audio_blob?: string
}