mirror of
https://github.com/FranP-code/Baileys.git
synced 2025-10-13 00:32:22 +00:00
147 lines
4.8 KiB
TypeScript
147 lines
4.8 KiB
TypeScript
import { WA } from './Constants'
|
|
import { proto } from './WAMessage'
|
|
|
|
export default class Encoder {
|
|
data: Array<number> = []
|
|
|
|
pushByte(value: number) {
|
|
this.data.push(value & 0xff)
|
|
}
|
|
pushInt(value: number, n: number, littleEndian = false) {
|
|
for (let i = 0; i < n; i++) {
|
|
const curShift = littleEndian ? i : n - 1 - i
|
|
this.data.push((value >> (curShift * 8)) & 0xff)
|
|
}
|
|
}
|
|
pushInt20(value: number) {
|
|
this.pushBytes([(value >> 16) & 0x0f, (value >> 8) & 0xff, value & 0xff])
|
|
}
|
|
pushBytes(bytes: Uint8Array | Array<number>) {
|
|
this.data.push.apply(this.data, bytes)
|
|
}
|
|
pushString(str: string) {
|
|
const bytes = new TextEncoder().encode(str)
|
|
this.pushBytes(bytes)
|
|
}
|
|
writeByteLength(length: number) {
|
|
if (length >= 4294967296) {
|
|
throw 'string too large to encode: ' + length
|
|
}
|
|
if (length >= 1 << 20) {
|
|
this.pushByte(WA.Tags.BINARY_32)
|
|
this.pushInt(length, 4) // 32 bit integer
|
|
} else if (length >= 256) {
|
|
this.pushByte(WA.Tags.BINARY_20)
|
|
this.pushInt20(length)
|
|
} else {
|
|
this.pushByte(WA.Tags.BINARY_8)
|
|
this.pushByte(length)
|
|
}
|
|
}
|
|
writeStringRaw(string: string) {
|
|
this.writeByteLength(string.length)
|
|
this.pushString(string)
|
|
}
|
|
writeJid(left: string, right: string) {
|
|
this.pushByte(WA.Tags.JID_PAIR)
|
|
left && left.length > 0 ? this.writeString(left) : this.writeToken(WA.Tags.LIST_EMPTY)
|
|
this.writeString(right)
|
|
}
|
|
writeToken(token: number) {
|
|
if (token < 245) {
|
|
this.pushByte(token)
|
|
} else if (token <= 500) {
|
|
throw 'invalid token'
|
|
}
|
|
}
|
|
writeString(token: string, i: boolean = null) {
|
|
if (token === 'c.us') {
|
|
token = 's.whatsapp.net'
|
|
}
|
|
|
|
const tokenIndex = WA.SingleByteTokens.indexOf(token)
|
|
if (!i && token === 's.whatsapp.net') {
|
|
this.writeToken(tokenIndex)
|
|
} else if (tokenIndex >= 0) {
|
|
if (tokenIndex < WA.Tags.SINGLE_BYTE_MAX) {
|
|
this.writeToken(tokenIndex)
|
|
} else {
|
|
const overflow = tokenIndex - WA.Tags.SINGLE_BYTE_MAX
|
|
const dictionaryIndex = overflow >> 8
|
|
if (dictionaryIndex < 0 || dictionaryIndex > 3) {
|
|
throw 'double byte dict token out of range: ' + token + ', ' + tokenIndex
|
|
}
|
|
this.writeToken(WA.Tags.DICTIONARY_0 + dictionaryIndex)
|
|
this.writeToken(overflow % 256)
|
|
}
|
|
} else if (token) {
|
|
const jidSepIndex = token.indexOf('@')
|
|
if (jidSepIndex <= 0) {
|
|
this.writeStringRaw(token)
|
|
} else {
|
|
this.writeJid(token.slice(0, jidSepIndex), token.slice(jidSepIndex + 1, token.length))
|
|
}
|
|
}
|
|
}
|
|
writeAttributes(attrs: Record<string, string> | string, keys: string[]) {
|
|
if (!attrs) {
|
|
return
|
|
}
|
|
keys.forEach((key) => {
|
|
this.writeString(key)
|
|
this.writeString(attrs[key])
|
|
})
|
|
}
|
|
writeListStart(listSize: number) {
|
|
if (listSize === 0) {
|
|
this.pushByte(WA.Tags.LIST_EMPTY)
|
|
} else if (listSize < 256) {
|
|
this.pushBytes([WA.Tags.LIST_8, listSize])
|
|
} else {
|
|
this.pushBytes([WA.Tags.LIST_16, listSize])
|
|
}
|
|
}
|
|
writeChildren(children: string | Array<WA.Node> | Object) {
|
|
if (!children) {
|
|
return
|
|
}
|
|
|
|
if (typeof children === 'string') {
|
|
this.writeString(children, true)
|
|
} else if (Array.isArray(children)) {
|
|
this.writeListStart(children.length)
|
|
children.forEach((c) => {
|
|
if (c) this.writeNode(c)
|
|
})
|
|
} else if (typeof children === 'object') {
|
|
const buffer = WA.Message.encode(children as proto.WebMessageInfo).finish()
|
|
this.writeByteLength(buffer.length)
|
|
this.pushBytes(buffer)
|
|
} else {
|
|
throw 'invalid children: ' + children + ' (' + typeof children + ')'
|
|
}
|
|
}
|
|
getValidKeys(obj: Object) {
|
|
return obj ? Object.keys(obj).filter((key) => obj[key] !== null && obj[key] !== undefined) : []
|
|
}
|
|
writeNode(node: WA.Node) {
|
|
if (!node) {
|
|
return
|
|
} else if (node.length !== 3) {
|
|
throw 'invalid node given: ' + node
|
|
}
|
|
const validAttributes = this.getValidKeys(node[1])
|
|
|
|
this.writeListStart(2 * validAttributes.length + 1 + (node[2] ? 1 : 0))
|
|
this.writeString(node[0])
|
|
this.writeAttributes(node[1], validAttributes)
|
|
this.writeChildren(node[2])
|
|
}
|
|
write(data) {
|
|
this.data = []
|
|
this.writeNode(data)
|
|
|
|
return Buffer.from(this.data)
|
|
}
|
|
}
|