proto: update manually to 2.3000.1020608496

This commit is contained in:
Rajeh Taher
2025-03-06 04:22:17 +02:00
parent 9a175a6a08
commit 99142aac96
17 changed files with 89037 additions and 20777 deletions

View File

@@ -1,4 +0,0 @@
yarn pbjs -t static-module -w commonjs -o ./WAProto/index.js ./WAProto/WAProto.proto;
yarn pbts -o ./WAProto/index.d.ts ./WAProto/index.js;
#protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_opt=env=node,useOptionals=true,forceLong=long --ts_proto_out=. ./src/Binary/WAMessage.proto;

File diff suppressed because it is too large Load Diff

17821
WAProto/index.d.ts vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
node_modules
.DS_Store

View File

@@ -1,8 +0,0 @@
# Proto Extract
Derived initially from `whatseow`'s proto extract, this version generates a predictable diff friendly protobuf. It also does not rely on a hardcoded set of modules to look for but finds all proto modules on its own and extracts the proto from there.
## Usage
1. Install dependencies with `yarn` (or `npm install`)
2. `yarn start`
3. The script will update `../WAProto/WAProto.proto` (except if something is broken)

View File

@@ -1,382 +0,0 @@
const request = require('request-promise-native')
const acorn = require('acorn')
const walk = require('acorn-walk')
const fs = require('fs/promises')
const addPrefix = (lines, prefix) => lines.map(line => prefix + line)
const extractAllExpressions = (node) => {
const expressions = [node]
const exp = node.expression
if(exp) {
expressions.push(exp)
}
if(node.expression?.expressions?.length) {
for(const exp of node.expression?.expressions) {
expressions.push(...extractAllExpressions(exp))
}
}
return expressions
}
async function findAppModules() {
const ua = {
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:100.0) Gecko/20100101 Firefox/100.0',
'Sec-Fetch-Dest': 'script',
'Sec-Fetch-Mode': 'no-cors',
'Sec-Fetch-Site': 'same-origin',
'Referer': 'https://web.whatsapp.com/',
'Accept': '*/*',
'Accept-Language': 'Accept-Language: en-US,en;q=0.5',
}
}
const baseURL = 'https://web.whatsapp.com'
const serviceworker = await request.get(`${baseURL}/serviceworker.js`, ua)
const versions = [...serviceworker.matchAll(/assets-manifest-([\d\.]+).json/g)].map(r => r[1])
const version = versions[0]
let bootstrapQRURL = ''
if(version) {
const asset = await request.get(`${baseURL}/assets-manifest-${version}.json`, ua)
const hashFiles = JSON.parse(asset)
const files = Object.keys(hashFiles)
const app = files.find(f => /^app\./.test(f))
bootstrapQRURL = `${baseURL}/${app}`
} else {
const index = await request.get(baseURL, ua)
const bootstrapQRID = index.match(/src="\/app.([0-9a-z]{10,}).js"/)[1]
bootstrapQRURL = baseURL + '/app.' + bootstrapQRID + '.js'
}
console.error('Found source JS URL:', bootstrapQRURL)
const qrData = await request.get(bootstrapQRURL, ua)
const waVersion = qrData.match(/(?:appVersion:|VERSION_STR=)"(\d\.\d+\.\d+)"/)[1]
console.log('Current version:', waVersion)
// This one list of types is so long that it's split into two JavaScript declarations.
// The module finder below can't handle it, so just patch it manually here.
const patchedQrData = qrData.replace('t.ActionLinkSpec=void 0,t.TemplateButtonSpec', 't.ActionLinkSpec=t.TemplateButtonSpec')
//const patchedQrData = qrData.replace("Spec=void 0,t.", "Spec=t.")
const qrModules = acorn.parse(patchedQrData).body[0].expression.arguments[0].elements[1].properties
const result = qrModules.filter(m => {
const hasProto = !!m.value.body.body.find(b => {
const expressions = extractAllExpressions(b)
return expressions?.find(e => e?.left?.property?.name === 'internalSpec')
})
if(hasProto) {
return true
}
})
return result
}
(async() => {
const unspecName = name => name.endsWith('Spec') ? name.slice(0, -4) : name
const unnestName = name => name.split('$').slice(-1)[0]
const getNesting = name => name.split('$').slice(0, -1).join('$')
const makeRenameFunc = () => (
name => {
name = unspecName(name)
return name// .replaceAll('$', '__')
// return renames[name] ?? unnestName(name)
}
)
// The constructor IDs that can be used for enum types
// const enumConstructorIDs = [76672, 54302]
const modules = await findAppModules()
// Sort modules so that whatsapp module id changes don't change the order in the output protobuf schema
// const modules = []
// for (const mod of wantedModules) {
// modules.push(unsortedModules.find(node => node.key.value === mod))
// }
// find aliases of cross references between the wanted modules
const modulesInfo = {}
const moduleIndentationMap = {}
modules.forEach(({ key, value }) => {
const requiringParam = value.params[2].name
modulesInfo[key.value] = { crossRefs: [] }
walk.simple(value, {
VariableDeclarator(node) {
if(node.init && node.init.type === 'CallExpression' && node.init.callee.name === requiringParam && node.init.arguments.length === 1) {
modulesInfo[key.value].crossRefs.push({ alias: node.id.name, module: node.init.arguments[0].value })
}
}
})
})
// find all identifiers and, for enums, their array of values
for(const mod of modules) {
const modInfo = modulesInfo[mod.key.value]
const rename = makeRenameFunc(mod.key.value)
// all identifiers will be initialized to "void 0" (i.e. "undefined") at the start, so capture them here
walk.ancestor(mod, {
UnaryExpression(node, anc) {
if(!modInfo.identifiers && node.operator === 'void') {
const assignments = []
let i = 1
anc.reverse()
while(anc[i].type === 'AssignmentExpression') {
assignments.push(anc[i++].left)
}
const makeBlankIdent = a => {
const key = rename(a.property.name)
const indentation = getNesting(key)
const value = { name: key }
moduleIndentationMap[key] = moduleIndentationMap[key] || { }
moduleIndentationMap[key].indentation = indentation
if(indentation.length) {
moduleIndentationMap[indentation] = moduleIndentationMap[indentation] || { }
moduleIndentationMap[indentation].members = moduleIndentationMap[indentation].members || new Set()
moduleIndentationMap[indentation].members.add(key)
}
return [key, value]
}
modInfo.identifiers = Object.fromEntries(assignments.map(makeBlankIdent).reverse())
}
}
})
const enumAliases = {}
// enums are defined directly, and both enums and messages get a one-letter alias
walk.simple(mod, {
VariableDeclarator(node) {
if(
node.init?.type === 'CallExpression'
// && enumConstructorIDs.includes(node.init.callee?.arguments?.[0]?.value)
&& !!node.init.arguments.length
&& node.init.arguments[0].type === 'ObjectExpression'
&& node.init.arguments[0].properties.length
) {
const values = node.init.arguments[0].properties.map(p => ({
name: p.key.name,
id: p.value.value
}))
enumAliases[node.id.name] = values
}
},
AssignmentExpression(node) {
if(node.left.type === 'MemberExpression' && modInfo.identifiers[rename(node.left.property.name)]) {
const ident = modInfo.identifiers[rename(node.left.property.name)]
ident.alias = node.right.name
// enumAliases[ident.alias] = enumAliases[ident.alias] || []
ident.enumValues = enumAliases[ident.alias]
}
},
})
}
// find the contents for all protobuf messages
for(const mod of modules) {
const modInfo = modulesInfo[mod.key.value]
const rename = makeRenameFunc(mod.key.value)
// message specifications are stored in a "internalSpec" attribute of the respective identifier alias
walk.simple(mod, {
AssignmentExpression(node) {
if(node.left.type === 'MemberExpression' && node.left.property.name === 'internalSpec' && node.right.type === 'ObjectExpression') {
const targetIdent = Object.values(modInfo.identifiers).find(v => v.alias === node.left.object.name)
if(!targetIdent) {
console.warn(`found message specification for unknown identifier alias: ${node.left.object.name}`)
return
}
// partition spec properties by normal members and constraints (like "__oneofs__") which will be processed afterwards
const constraints = []
let members = []
for(const p of node.right.properties) {
p.key.name = p.key.type === 'Identifier' ? p.key.name : p.key.value
const arr = p.key.name.substr(0, 2) === '__' ? constraints : members
arr.push(p)
}
members = members.map(({ key: { name }, value: { elements } }) => {
let type
const flags = []
const unwrapBinaryOr = n => (n.type === 'BinaryExpression' && n.operator === '|') ? [].concat(unwrapBinaryOr(n.left), unwrapBinaryOr(n.right)) : [n]
// find type and flags
unwrapBinaryOr(elements[1]).forEach(m => {
if(m.type === 'MemberExpression' && m.object.type === 'MemberExpression') {
if(m.object.property.name === 'TYPES') {
type = m.property.name.toLowerCase()
} else if(m.object.property.name === 'FLAGS') {
flags.push(m.property.name.toLowerCase())
}
}
})
// determine cross reference name from alias if this member has type "message" or "enum"
if(type === 'message' || type === 'enum') {
const currLoc = ` from member '${name}' of message '${targetIdent.name}'`
if(elements[2].type === 'Identifier') {
type = Object.values(modInfo.identifiers).find(v => v.alias === elements[2].name)?.name
if(!type) {
console.warn(`unable to find reference of alias '${elements[2].name}'` + currLoc)
}
} else if(elements[2].type === 'MemberExpression') {
const crossRef = modInfo.crossRefs.find(r => r.alias === elements[2].object.name)
if(crossRef && modulesInfo[crossRef.module].identifiers[rename(elements[2].property.name)]) {
type = rename(elements[2].property.name)
} else {
console.warn(`unable to find reference of alias to other module '${elements[2].object.name}' or to message ${elements[2].property.name} of this module` + currLoc)
}
}
}
return { name, id: elements[0].value, type, flags }
})
// resolve constraints for members
constraints.forEach(c => {
if(c.key.name === '__oneofs__' && c.value.type === 'ObjectExpression') {
const newOneOfs = c.value.properties.map(p => ({
name: p.key.name,
type: '__oneof__',
members: p.value.elements.map(e => {
const idx = members.findIndex(m => m.name === e.value)
const member = members[idx]
members.splice(idx, 1)
return member
})
}))
members.push(...newOneOfs)
}
})
targetIdent.members = members
}
}
})
}
const decodedProtoMap = { }
const spaceIndent = ' '.repeat(4)
for(const mod of modules) {
const modInfo = modulesInfo[mod.key.value]
const identifiers = Object.values(modInfo.identifiers)
// enum stringifying function
const stringifyEnum = (ident, overrideName = null) => [].concat(
[`enum ${overrideName || ident.displayName || ident.name} {`],
addPrefix(ident.enumValues.map(v => `${v.name} = ${v.id};`), spaceIndent),
['}']
)
// message specification member stringifying function
const stringifyMessageSpecMember = (info, completeFlags, parentName = undefined) => {
if(info.type === '__oneof__') {
return [].concat(
[`oneof ${info.name} {`],
addPrefix([].concat(...info.members.map(m => stringifyMessageSpecMember(m, false))), spaceIndent),
['}']
)
} else {
if(info.flags.includes('packed')) {
info.flags.splice(info.flags.indexOf('packed'))
info.packed = ' [packed=true]'
}
if(completeFlags && info.flags.length === 0) {
info.flags.push('optional')
}
const ret = []
const indentation = moduleIndentationMap[info.type]?.indentation
let typeName = unnestName(info.type)
if(indentation !== parentName && indentation) {
typeName = `${indentation.replaceAll('$', '.')}.${typeName}`
}
// if(info.enumValues) {
// // typeName = unnestName(info.type)
// ret = stringifyEnum(info, typeName)
// }
ret.push(`${info.flags.join(' ') + (info.flags.length === 0 ? '' : ' ')}${typeName} ${info.name} = ${info.id}${info.packed || ''};`)
return ret
}
}
// message specification stringifying function
const stringifyMessageSpec = (ident) => {
const members = moduleIndentationMap[ident.name]?.members
const result = []
result.push(
`message ${ident.displayName || ident.name} {`,
...addPrefix([].concat(...ident.members.map(m => stringifyMessageSpecMember(m, true, ident.name))), spaceIndent),
)
if(members?.size) {
const sortedMembers = Array.from(members).sort()
for(const memberName of sortedMembers) {
let entity = modInfo.identifiers[memberName]
if(entity) {
const displayName = entity.name.slice(ident.name.length + 1)
entity = { ...entity, displayName }
result.push(...addPrefix(getEntity(entity), spaceIndent))
} else {
console.log('missing nested entity ', memberName)
}
}
}
result.push('}')
result.push('')
return result
}
const getEntity = (v) => {
let result
if(v.members) {
result = stringifyMessageSpec(v)
} else if(v.enumValues?.length) {
result = stringifyEnum(v)
} else {
result = ['// Unknown entity ' + v.name]
}
return result
}
const stringifyEntity = v => {
return {
content: getEntity(v).join('\n'),
name: v.name
}
}
for(const value of identifiers) {
const { name, content } = stringifyEntity(value)
if(!moduleIndentationMap[name]?.indentation?.length) {
decodedProtoMap[name] = content
}
// decodedProtoMap[name] = content
}
}
// console.log(moduleIndentationMap)
const decodedProto = Object.keys(decodedProtoMap).sort()
const sortedStr = decodedProto.map(d => decodedProtoMap[d]).join('\n')
const decodedProtoStr = `syntax = "proto2";\npackage proto;\n\n${sortedStr}`
const destinationPath = '../WAProto/WAProto.proto'
await fs.writeFile(destinationPath, decodedProtoStr)
console.log(`Extracted protobuf schema to "${destinationPath}"`)
})()

View File

@@ -1,15 +0,0 @@
{
"name": "whatsapp-web-protobuf-extractor",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node index.js"
},
"dependencies": {
"acorn": "^6.4.1",
"acorn-walk": "^6.1.1",
"request": "^2.88.0",
"request-promise-core": "^1.1.2",
"request-promise-native": "^1.0.7"
}
}

View File

@@ -1,357 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
acorn-walk@^6.1.1:
version "6.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c"
integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA==
acorn@^6.4.1:
version "6.4.2"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6"
integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==
ajv@^6.12.3:
version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
dependencies:
fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.8.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-json-stable-stringify@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.3:
version "5.1.5"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd"
integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==
dependencies:
ajv "^6.12.3"
har-schema "^2.0.0"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.2.3"
verror "1.10.0"
lodash@^4.17.19:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
mime-db@1.50.0:
version "1.50.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f"
integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==
mime-types@^2.1.12, mime-types@~2.1.19:
version "2.1.33"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb"
integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==
dependencies:
mime-db "1.50.0"
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
psl@^1.1.28:
version "1.8.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
punycode@^2.1.0, punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
request-promise-core@1.1.4, request-promise-core@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f"
integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==
dependencies:
lodash "^4.17.19"
request-promise-native@^1.0.7:
version "1.0.9"
resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28"
integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==
dependencies:
request-promise-core "1.1.4"
stealthy-require "^1.1.1"
tough-cookie "^2.3.3"
request@^2.88.0:
version "2.88.2"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.3"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.5.0"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
stealthy-require@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
tough-cookie@^2.3.3, tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
dependencies:
psl "^1.1.28"
punycode "^2.1.1"
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
uri-js@^4.2.2:
version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
dependencies:
punycode "^2.1.0"
uuid@^3.3.2:
version "3.4.0"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
verror@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"

View File

@@ -1,3 +1,3 @@
{
"version": [2, 3000, 1019707846]
"version": [2, 3000, 1020608496]
}

View File

@@ -2,6 +2,7 @@
import NodeCache from '@cacheable/node-cache'
import { Boom } from '@hapi/boom'
import { randomBytes } from 'crypto'
import Long = require('long');
import { proto } from '../../WAProto'
import { DEFAULT_CACHE_TTLS, KEY_BUNDLE_TYPE, MIN_PREKEY_COUNT } from '../Defaults'
import { MessageReceiptType, MessageRelayOptions, MessageUserReceipt, SocketConfig, WACallEvent, WAMessageKey, WAMessageStatus, WAMessageStubType, WAPatchName } from '../Types'
@@ -846,7 +847,7 @@ export const makeMessagesRecvSocket = (config: SocketConfig) => {
throw new Boom('Not authenticated')
}
const pdoMessage = {
const pdoMessage: proto.Message.IPeerDataOperationRequestMessage = {
historySyncOnDemandRequest: {
chatJid: oldestMsgKey.remoteJid,
oldestMsgFromMe: oldestMsgKey.fromMe,

View File

@@ -669,15 +669,15 @@ export const makeMessagesSocket = (config: SocketConfig) => {
try {
const media = await decryptMediaRetryData(result.media!, mediaKey, result.key.id!)
if(media.result !== proto.MediaRetryNotification.ResultType.SUCCESS) {
const resultStr = proto.MediaRetryNotification.ResultType[media.result]
const resultStr = proto.MediaRetryNotification.ResultType[media.result!]
throw new Boom(
`Media re-upload failed by device (${resultStr})`,
{ data: media, statusCode: getStatusCodeForMediaRetry(media.result) || 404 }
{ data: media, statusCode: getStatusCodeForMediaRetry(media.result!) || 404 }
)
}
content.directPath = media.directPath
content.url = getUrlFromDirectPath(content.directPath)
content.url = getUrlFromDirectPath(content.directPath!)
logger.debug({ directPath: media.directPath, key: result.key }, 'media update successful')
} catch(err) {

View File

@@ -1,6 +1,5 @@
import NodeCache from '@cacheable/node-cache'
import { randomBytes } from 'crypto'
import type { Logger } from 'pino'
import { DEFAULT_CACHE_TTLS } from '../Defaults'
import type { AuthenticationCreds, CacheStore, SignalDataSet, SignalDataTypeMap, SignalKeyStore, SignalKeyStoreWithTransaction, TransactionCapabilityOptions } from '../Types'
import { Curve, signedKeyPair } from './crypto'

View File

@@ -217,13 +217,13 @@ export const decodeSyncdMutations = async(
const syncAction = proto.SyncActionData.decode(result)
if(validateMacs) {
const hmac = hmacSign(syncAction.index, key.indexKey)
const hmac = hmacSign(syncAction.index!, key.indexKey)
if(Buffer.compare(hmac, record.index!.blob!) !== 0) {
throw new Boom('HMAC index verification failed')
}
}
const indexStr = Buffer.from(syncAction.index).toString()
const indexStr = Buffer.from(syncAction.index!).toString()
onMutation({ syncAction, index: JSON.parse(indexStr) })
ltGenerator.mix({

View File

@@ -149,7 +149,7 @@ export const decryptMessageNode = (
for(const { tag, attrs, content } of stanza.content) {
if(tag === 'verified_name' && content instanceof Uint8Array) {
const cert = proto.VerifiedNameCertificate.decode(content)
const details = proto.VerifiedNameCertificate.Details.decode(cert.details)
const details = proto.VerifiedNameCertificate.Details.decode(cert.details!)
fullMessage.verifiedBizName = details.verifiedName
}

View File

@@ -332,7 +332,6 @@ export const generateWAMessageContent = async(
}
if(urlInfo) {
extContent.canonicalUrl = urlInfo['canonical-url']
extContent.matchedText = urlInfo['matched-text']
extContent.jpegThumbnail = urlInfo.jpegThumbnail
extContent.description = urlInfo.description

View File

@@ -131,27 +131,27 @@ export const configureSuccessfulPairing = (
const { details, hmac } = proto.ADVSignedDeviceIdentityHMAC.decode(deviceIdentityNode.content as Buffer)
// check HMAC matches
const advSign = hmacSign(details, Buffer.from(advSecretKey, 'base64'))
if(Buffer.compare(hmac, advSign) !== 0) {
const advSign = hmacSign(details!, Buffer.from(advSecretKey, 'base64'))
if(Buffer.compare(hmac!, advSign) !== 0) {
throw new Boom('Invalid account signature')
}
const account = proto.ADVSignedDeviceIdentity.decode(details)
const account = proto.ADVSignedDeviceIdentity.decode(details!)
const { accountSignatureKey, accountSignature, details: deviceDetails } = account
// verify the device signature matches
const accountMsg = Buffer.concat([ Buffer.from([6, 0]), deviceDetails, signedIdentityKey.public ])
if(!Curve.verify(accountSignatureKey, accountMsg, accountSignature)) {
const accountMsg = Buffer.concat([ Buffer.from([6, 0]), deviceDetails!, signedIdentityKey.public ])
if(!Curve.verify(accountSignatureKey!, accountMsg, accountSignature!)) {
throw new Boom('Failed to verify account signature')
}
// sign the details with our identity key
const deviceMsg = Buffer.concat([ Buffer.from([6, 1]), deviceDetails, signedIdentityKey.public, accountSignatureKey ])
const deviceMsg = Buffer.concat([ Buffer.from([6, 1]), deviceDetails!, signedIdentityKey.public, accountSignatureKey! ])
account.deviceSignature = Curve.sign(signedIdentityKey.private, deviceMsg)
const identity = createSignalIdentity(jid, accountSignatureKey)
const identity = createSignalIdentity(jid, accountSignatureKey!)
const accountEnc = encodeSignedDeviceIdentity(account, false)
const deviceIdentity = proto.ADVDeviceIdentity.decode(account.details)
const deviceIdentity = proto.ADVDeviceIdentity.decode(account.details!)
const reply: BinaryNode = {
tag: 'iq',
@@ -167,7 +167,7 @@ export const configureSuccessfulPairing = (
content: [
{
tag: 'device-identity',
attrs: { 'key-index': deviceIdentity.keyIndex.toString() },
attrs: { 'key-index': deviceIdentity.keyIndex!.toString() },
content: accountEnc
}
]