max-account-api 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +328 -0
- package/dist/auth.d.ts +85 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +204 -0
- package/dist/auth.js.map +1 -0
- package/dist/client.d.ts +724 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1601 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/media.d.ts +67 -0
- package/dist/media.d.ts.map +1 -0
- package/dist/media.js +233 -0
- package/dist/media.js.map +1 -0
- package/dist/opcodes.d.ts +435 -0
- package/dist/opcodes.d.ts.map +1 -0
- package/dist/opcodes.js +456 -0
- package/dist/opcodes.js.map +1 -0
- package/dist/qr-bind.d.ts +60 -0
- package/dist/qr-bind.d.ts.map +1 -0
- package/dist/qr-bind.js +102 -0
- package/dist/qr-bind.js.map +1 -0
- package/dist/raw-transport.d.ts +125 -0
- package/dist/raw-transport.d.ts.map +1 -0
- package/dist/raw-transport.js +510 -0
- package/dist/raw-transport.js.map +1 -0
- package/dist/storage.d.ts +56 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +70 -0
- package/dist/storage.js.map +1 -0
- package/dist/transport.d.ts +52 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +193 -0
- package/dist/transport.js.map +1 -0
- package/dist/types.d.ts +1141 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +10 -0
- package/dist/types.js.map +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { UserAgent, HelloResponse } from './types.js';
|
|
3
|
+
export interface RawTransportOptions {
|
|
4
|
+
host?: string;
|
|
5
|
+
port?: number;
|
|
6
|
+
servername?: string;
|
|
7
|
+
/** Reject self-signed / mismatched certs (default true). */
|
|
8
|
+
rejectUnauthorized?: boolean;
|
|
9
|
+
connectTimeoutMs?: number;
|
|
10
|
+
requestTimeoutMs?: number;
|
|
11
|
+
/** When true, hex-dump every TX/RX frame to stderr for diagnostics. */
|
|
12
|
+
debug?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface SendOptions {
|
|
15
|
+
/**
|
|
16
|
+
* If set, prepend `(<prefixInt>, <hint>, body)` to the payload — observed on
|
|
17
|
+
* op 17 phone-auth frames (prefixInt=-16). For op 17 hints:
|
|
18
|
+
* - 21 for START_AUTH
|
|
19
|
+
* - 17 for RESEND
|
|
20
|
+
*/
|
|
21
|
+
prependOpHint?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Custom prefix byte when `prependOpHint` is set. Defaults to 0xf0
|
|
24
|
+
* (observed on op 17 / 18 / 115). Sent as a raw byte.
|
|
25
|
+
*/
|
|
26
|
+
prefixInt?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Prepend a single msgpack int before the payload (no hint). Used by op 18
|
|
29
|
+
* verify (observed prefix = -31).
|
|
30
|
+
*/
|
|
31
|
+
prependScalar?: number;
|
|
32
|
+
/** Override the flags byte (header offset 6). Op 17 uses 1, op 18 uses 2. */
|
|
33
|
+
flags?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Raw bytes prepended verbatim before the msgpack body. Used by HELLO
|
|
36
|
+
* (`[0xf3, 0x5a]`) — a fixed "session-greeting" tag that gates mobile-only
|
|
37
|
+
* features server-side. Mutually exclusive with `prependOpHint` /
|
|
38
|
+
* `prependScalar`.
|
|
39
|
+
*/
|
|
40
|
+
rawPrefix?: Buffer;
|
|
41
|
+
}
|
|
42
|
+
export declare class RawTransport extends EventEmitter {
|
|
43
|
+
private sock;
|
|
44
|
+
private seq;
|
|
45
|
+
private readonly pending;
|
|
46
|
+
private rxBuf;
|
|
47
|
+
private readonly opts;
|
|
48
|
+
constructor(opts?: RawTransportOptions);
|
|
49
|
+
private hexDump;
|
|
50
|
+
connect(): Promise<void>;
|
|
51
|
+
close(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Op 290 — confirm a web-side QR login from this authenticated mobile
|
|
54
|
+
* session. This is the headless equivalent of scanning the QR with the
|
|
55
|
+
* MAX mobile app's camera.
|
|
56
|
+
*
|
|
57
|
+
* Pass the `qrLink` string returned by the web client's op 288 response.
|
|
58
|
+
* The server uses this to flip the corresponding `trackId` to
|
|
59
|
+
* `loginAvailable:true`, which the web client picks up via op 289 polling.
|
|
60
|
+
*
|
|
61
|
+
* Returns when the server ACKs (empty body). The actual web-side LOGIN
|
|
62
|
+
* issuance happens on the web WS — see {@link import('./qr-bind.js').qrBindWebSession}
|
|
63
|
+
* for the full flow.
|
|
64
|
+
*
|
|
65
|
+
* Wire prefix: `f0 34` (op-hint 0x34), `flags=1`.
|
|
66
|
+
*/
|
|
67
|
+
confirmQrAuth(qrLink: string): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Send op 19 (LOGIN) over the mobile binary transport.
|
|
70
|
+
*
|
|
71
|
+
* Reversed from MAX Android v26.15.1: the request map carries:
|
|
72
|
+
* { chatCacheFingerprint: <96-byte binary>, // local cache hash; zeros OK for fresh session
|
|
73
|
+
* exp: { chatsCountGroups: <2-byte binary> }, // server-side experiment caps
|
|
74
|
+
* token: <LOGIN token from op 115>,
|
|
75
|
+
* presenceSync: 0,
|
|
76
|
+
* interactive: true }
|
|
77
|
+
* with a 5-byte raw prefix `f0 ff ff ff 3c` and `flags=1` in the header.
|
|
78
|
+
*
|
|
79
|
+
* Returns the full LoginResponse (profile, chats, contacts, refreshed token).
|
|
80
|
+
* Use after HELLO + phone-auth (op 17/18 [+ 115 for 2FA]) on the same socket.
|
|
81
|
+
*/
|
|
82
|
+
mobileLogin(token: string): Promise<unknown>;
|
|
83
|
+
/**
|
|
84
|
+
* Send op 6 (HELLO) using the captured Android byte template.
|
|
85
|
+
*
|
|
86
|
+
* MAX's server rejects any re-encoded HELLO whose msgpack token stream
|
|
87
|
+
* deviates from the captured Android-client form — even semantically
|
|
88
|
+
* identical maps trigger a silent TCP close. We work around this by
|
|
89
|
+
* shipping the exact bytes the v26.15.1 Android client sent and patching
|
|
90
|
+
* only the per-install identifiers (`mt_instanceid` UUID + 16-hex
|
|
91
|
+
* `deviceId`). `userAgent` content is therefore fixed at the template's
|
|
92
|
+
* values; the `userAgent` argument is ignored (kept for API parity but
|
|
93
|
+
* marked optional). Always emits the first frame (seq=1) on a fresh
|
|
94
|
+
* connection — call right after `connect()`.
|
|
95
|
+
*/
|
|
96
|
+
hello(mobileDeviceId: string, mtInstanceId: string, _userAgent?: UserAgent): Promise<HelloResponse>;
|
|
97
|
+
request<TRes = unknown>(opcode: number, payload?: unknown, opts?: SendOptions): Promise<TRes>;
|
|
98
|
+
private key;
|
|
99
|
+
private encodeBody;
|
|
100
|
+
private encodeFrame;
|
|
101
|
+
private onData;
|
|
102
|
+
private handleFrame;
|
|
103
|
+
/**
|
|
104
|
+
* Decompress an LZ4-block-encoded body. The mobile binary protocol uses
|
|
105
|
+
* `lz4-java` `fastCompressor()` server-side (see `d2d.java`); we use the
|
|
106
|
+
* pure-JS `lz4js` block codec on the client. The `cof` byte from the header
|
|
107
|
+
* encodes the ratio `(uncompressed/compressed)+1`, which we use to size the
|
|
108
|
+
* output buffer with headroom.
|
|
109
|
+
*/
|
|
110
|
+
private lz4Decompress;
|
|
111
|
+
/**
|
|
112
|
+
* Decode the body. Mobile-protocol responses prepend 2+ raw bytes before
|
|
113
|
+
* the actual msgpack map (e.g. op 6 reply: `f0 d2 … 87 <map>`; op 17 reply:
|
|
114
|
+
* `f3 a7 … 85 <map>`; op 18: similar). The map's trailing bytes can also
|
|
115
|
+
* contain "junk" the server still sends — `msgpackDecode` errors on extra
|
|
116
|
+
* bytes after the value. We scan offsets for a container header (fixmap /
|
|
117
|
+
* fixarray / map16) and use `decodeMulti` to take the FIRST value, which
|
|
118
|
+
* tolerates trailing data. Falls back to last stream value otherwise.
|
|
119
|
+
*/
|
|
120
|
+
private decodeBody;
|
|
121
|
+
/** Scan `buf` for the longest msgpack str8/str16/str32 ASCII payload. */
|
|
122
|
+
private extractLongestString;
|
|
123
|
+
private onClose;
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=raw-transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-transport.d.ts","sourceRoot":"","sources":["../src/raw-transport.ts"],"names":[],"mappings":"AAgCA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAE7E,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAiCD,qBAAa,YAAa,SAAQ,YAAY;IAC5C,OAAO,CAAC,IAAI,CAA8B;IAC1C,OAAO,CAAC,GAAG,CAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgC;gBAEzC,IAAI,GAAE,mBAAwB;IAc1C,OAAO,CAAC,OAAO;IAcf,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IA6BxB,KAAK,IAAI,IAAI;IAUb;;;;;;;;;;;;;;OAcG;IACG,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlD;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAelD;;;;;;;;;;;;OAYG;IACG,KAAK,CACT,cAAc,EAAE,MAAM,EACtB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,SAAS,GACrB,OAAO,CAAC,aAAa,CAAC;IAmCzB,OAAO,CAAC,IAAI,GAAG,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BjG,OAAO,CAAC,GAAG;IAIX,OAAO,CAAC,UAAU;IAoBlB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,MAAM;IAuBd,OAAO,CAAC,WAAW;IA+CnB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IAcrB;;;;;;;;OAQG;IACH,OAAO,CAAC,UAAU;IA4DlB,yEAAyE;IACzE,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,OAAO;CAQhB"}
|
|
@@ -0,0 +1,510 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Raw TLS transport for the MAX mobile protocol (api.oneme.ru:443).
|
|
3
|
+
*
|
|
4
|
+
* The web client uses WebSocket with JSON frames; the Android/iOS client
|
|
5
|
+
* uses a custom binary frame format over plain TLS — and crucially, the
|
|
6
|
+
* server gates phone-auth (ops 17/18) and other mobile-only flows behind
|
|
7
|
+
* `userAgent.deviceType === 'ANDROID'` / `'IOS'`, which the WS endpoint
|
|
8
|
+
* refuses (close code 1008, "deviceType forbidden").
|
|
9
|
+
*
|
|
10
|
+
* Wire format (observed via Frida hooks on Conscrypt SSLOutputStream):
|
|
11
|
+
*
|
|
12
|
+
* offset 0 : 0x0a magic
|
|
13
|
+
* offset 1 : direction (0 = client→server, 1 = server→client, 3 = error)
|
|
14
|
+
* offset 2-3 : seq (2B big-endian — wraps at 65536)
|
|
15
|
+
* offset 4-5 : opcode (2B big-endian — high byte is 0 for op < 256;
|
|
16
|
+
* non-zero for op > 255, e.g. op 290 = 0x0122)
|
|
17
|
+
* offset 6 : flags (observed 0 for PING/HELLO, 1 for op-17 phone-auth)
|
|
18
|
+
* offset 7-9 : payload length (3B big-endian)
|
|
19
|
+
* offset 10+ : msgpack payload
|
|
20
|
+
*
|
|
21
|
+
* Most payloads are a plain msgpack map (e.g. PING `{interactive:true}`).
|
|
22
|
+
* Some ops (notably op 17 phone-auth) prepend two msgpack ints to the map
|
|
23
|
+
* (observed `(-16, 21, {...})` for START_AUTH, `(-16, 17, {...})` for
|
|
24
|
+
* RESEND). We replicate the mobile behaviour by wrapping such payloads in
|
|
25
|
+
* a `[hint, op, body]` triplet when `prependOpHint` is set.
|
|
26
|
+
*
|
|
27
|
+
* This module ships only what the phone-auth flow needs:
|
|
28
|
+
* - `RawTransport.hello()` → op 6 with ANDROID userAgent
|
|
29
|
+
* - `RawTransport.request(op, body)` → generic request/response
|
|
30
|
+
* - automatic seq numbering + (op, seq) correlation
|
|
31
|
+
*/
|
|
32
|
+
import * as tls from 'node:tls';
|
|
33
|
+
import { EventEmitter } from 'node:events';
|
|
34
|
+
import { encode as msgpackEncode, decodeMulti as msgpackDecodeMulti, decode as msgpackDecode } from '@msgpack/msgpack';
|
|
35
|
+
// @ts-expect-error — no types ship with lz4js (pure-JS LZ4 block codec).
|
|
36
|
+
import lz4js from 'lz4js';
|
|
37
|
+
import { Opcode } from './opcodes.js';
|
|
38
|
+
const FRAME_MAGIC = 0x0a;
|
|
39
|
+
const HEADER_SIZE = 10;
|
|
40
|
+
const DIR_CLIENT = 0;
|
|
41
|
+
const FLAGS_DEFAULT = 0;
|
|
42
|
+
const FLAGS_PHONE_AUTH = 1;
|
|
43
|
+
/**
|
|
44
|
+
* Captured byte-template of a real Android client's op 6 HELLO frame.
|
|
45
|
+
* Re-encoding the same map content via standard msgpack is silently dropped
|
|
46
|
+
* by the server (no error reply, just TCP close) — the server's parser
|
|
47
|
+
* appears to depend on this *exact* token stream, including bytes that look
|
|
48
|
+
* like JNI buffer artifacts but are part of the protocol. The only fields
|
|
49
|
+
* we patch are `mt_instanceid` (UUID, offset 29, 36 bytes) and `deviceId`
|
|
50
|
+
* (16-hex, offset 298, 16 bytes). Header seq stays 1 — HELLO is always the
|
|
51
|
+
* first frame on a fresh connection.
|
|
52
|
+
*
|
|
53
|
+
* Captured from MAX Android v26.15.1 (build 6690) against api.oneme.ru:443.
|
|
54
|
+
*/
|
|
55
|
+
const HELLO_TEMPLATE_HEX = '0a000001000602000130f35a84ad6d745f696e7374616e63656964d92430393437366632372d663230362d343139362d383662612d656537663434643566363233a9757365724167656e748baa64657669636554797065a7414e44524f4944aa61707056657273696f6ea732362e31352e31a96f731200f322aa416e64726f6964203134a874696d657a6f6e65ad4575726f70652f4d6f73636f77a673637265656eb7343430647069200700f500313038307832313338ae70757368447500f31aa347434da461726368a67838365f3634a66c6f63616c65a27275ab6275696c644e756d626572cd1a22a900f20a4e616d65ba476f6f676c652073646b5f6770686f6e6536345f3f0012accf00144c4500a0af636c69656e74536573cf004249640ba82100f0044964b066646630393164333564346535343162';
|
|
56
|
+
const HELLO_TEMPLATE = Buffer.from(HELLO_TEMPLATE_HEX, 'hex');
|
|
57
|
+
const HELLO_MT_OFFSET = 29; // 36 chars
|
|
58
|
+
const HELLO_DEVICE_OFFSET = 298; // 16 chars
|
|
59
|
+
export class RawTransport extends EventEmitter {
|
|
60
|
+
sock = null;
|
|
61
|
+
seq = 0;
|
|
62
|
+
pending = new Map();
|
|
63
|
+
rxBuf = Buffer.alloc(0);
|
|
64
|
+
opts;
|
|
65
|
+
constructor(opts = {}) {
|
|
66
|
+
super();
|
|
67
|
+
this.opts = {
|
|
68
|
+
host: 'api.oneme.ru',
|
|
69
|
+
port: 443,
|
|
70
|
+
servername: opts.servername ?? opts.host ?? 'api.oneme.ru',
|
|
71
|
+
rejectUnauthorized: true,
|
|
72
|
+
connectTimeoutMs: 15_000,
|
|
73
|
+
requestTimeoutMs: 30_000,
|
|
74
|
+
debug: false,
|
|
75
|
+
...opts,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
hexDump(tag, buf) {
|
|
79
|
+
if (!this.opts.debug)
|
|
80
|
+
return;
|
|
81
|
+
const lines = [`[${tag}] ${buf.length} bytes`];
|
|
82
|
+
for (let off = 0; off < buf.length; off += 16) {
|
|
83
|
+
const chunk = buf.subarray(off, off + 16);
|
|
84
|
+
const hex = Array.from(chunk).map((b) => b.toString(16).padStart(2, '0')).join(' ');
|
|
85
|
+
const ascii = Array.from(chunk)
|
|
86
|
+
.map((b) => (b >= 32 && b < 127 ? String.fromCharCode(b) : '.'))
|
|
87
|
+
.join('');
|
|
88
|
+
lines.push(` ${off.toString(16).padStart(4, '0')}: ${hex.padEnd(48)} ${ascii}`);
|
|
89
|
+
}
|
|
90
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
91
|
+
}
|
|
92
|
+
connect() {
|
|
93
|
+
return new Promise((resolve, reject) => {
|
|
94
|
+
const sock = tls.connect({
|
|
95
|
+
host: this.opts.host,
|
|
96
|
+
port: this.opts.port,
|
|
97
|
+
servername: this.opts.servername,
|
|
98
|
+
rejectUnauthorized: this.opts.rejectUnauthorized,
|
|
99
|
+
// Mobile clients negotiate plain TLS (no ALPN preference observed).
|
|
100
|
+
});
|
|
101
|
+
this.sock = sock;
|
|
102
|
+
const to = setTimeout(() => {
|
|
103
|
+
sock.destroy(new Error('TLS connect timeout'));
|
|
104
|
+
}, this.opts.connectTimeoutMs);
|
|
105
|
+
sock.once('secureConnect', () => {
|
|
106
|
+
clearTimeout(to);
|
|
107
|
+
this.emit('open');
|
|
108
|
+
resolve();
|
|
109
|
+
});
|
|
110
|
+
sock.on('data', (chunk) => this.onData(typeof chunk === 'string' ? Buffer.from(chunk) : chunk));
|
|
111
|
+
sock.on('error', (e) => {
|
|
112
|
+
clearTimeout(to);
|
|
113
|
+
this.emit('error', e);
|
|
114
|
+
reject(e);
|
|
115
|
+
});
|
|
116
|
+
sock.on('close', () => this.onClose());
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
close() {
|
|
120
|
+
this.sock?.end();
|
|
121
|
+
this.sock = null;
|
|
122
|
+
for (const [k, p] of this.pending) {
|
|
123
|
+
clearTimeout(p.timer);
|
|
124
|
+
p.reject(new Error('Transport closed'));
|
|
125
|
+
this.pending.delete(k);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Op 290 — confirm a web-side QR login from this authenticated mobile
|
|
130
|
+
* session. This is the headless equivalent of scanning the QR with the
|
|
131
|
+
* MAX mobile app's camera.
|
|
132
|
+
*
|
|
133
|
+
* Pass the `qrLink` string returned by the web client's op 288 response.
|
|
134
|
+
* The server uses this to flip the corresponding `trackId` to
|
|
135
|
+
* `loginAvailable:true`, which the web client picks up via op 289 polling.
|
|
136
|
+
*
|
|
137
|
+
* Returns when the server ACKs (empty body). The actual web-side LOGIN
|
|
138
|
+
* issuance happens on the web WS — see {@link import('./qr-bind.js').qrBindWebSession}
|
|
139
|
+
* for the full flow.
|
|
140
|
+
*
|
|
141
|
+
* Wire prefix: `f0 34` (op-hint 0x34), `flags=1`.
|
|
142
|
+
*/
|
|
143
|
+
async confirmQrAuth(qrLink) {
|
|
144
|
+
const req = { qrLink };
|
|
145
|
+
await this.request(Opcode.QR_CONFIRM, req, { prependOpHint: 0x34, flags: 1 });
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Send op 19 (LOGIN) over the mobile binary transport.
|
|
149
|
+
*
|
|
150
|
+
* Reversed from MAX Android v26.15.1: the request map carries:
|
|
151
|
+
* { chatCacheFingerprint: <96-byte binary>, // local cache hash; zeros OK for fresh session
|
|
152
|
+
* exp: { chatsCountGroups: <2-byte binary> }, // server-side experiment caps
|
|
153
|
+
* token: <LOGIN token from op 115>,
|
|
154
|
+
* presenceSync: 0,
|
|
155
|
+
* interactive: true }
|
|
156
|
+
* with a 5-byte raw prefix `f0 ff ff ff 3c` and `flags=1` in the header.
|
|
157
|
+
*
|
|
158
|
+
* Returns the full LoginResponse (profile, chats, contacts, refreshed token).
|
|
159
|
+
* Use after HELLO + phone-auth (op 17/18 [+ 115 for 2FA]) on the same socket.
|
|
160
|
+
*/
|
|
161
|
+
async mobileLogin(token) {
|
|
162
|
+
if (!this.sock || this.sock.destroyed)
|
|
163
|
+
throw new Error('RawTransport not connected');
|
|
164
|
+
const payload = {
|
|
165
|
+
chatCacheFingerprint: Buffer.alloc(96), // 96-byte zero binary for fresh session
|
|
166
|
+
exp: { chatsCountGroups: Buffer.from([0x09, 0x32]) },
|
|
167
|
+
token,
|
|
168
|
+
presenceSync: 0,
|
|
169
|
+
interactive: true,
|
|
170
|
+
};
|
|
171
|
+
return this.request(19, payload, {
|
|
172
|
+
flags: 1,
|
|
173
|
+
rawPrefix: Buffer.from([0xf0, 0xff, 0xff, 0xff, 0x3c]),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Send op 6 (HELLO) using the captured Android byte template.
|
|
178
|
+
*
|
|
179
|
+
* MAX's server rejects any re-encoded HELLO whose msgpack token stream
|
|
180
|
+
* deviates from the captured Android-client form — even semantically
|
|
181
|
+
* identical maps trigger a silent TCP close. We work around this by
|
|
182
|
+
* shipping the exact bytes the v26.15.1 Android client sent and patching
|
|
183
|
+
* only the per-install identifiers (`mt_instanceid` UUID + 16-hex
|
|
184
|
+
* `deviceId`). `userAgent` content is therefore fixed at the template's
|
|
185
|
+
* values; the `userAgent` argument is ignored (kept for API parity but
|
|
186
|
+
* marked optional). Always emits the first frame (seq=1) on a fresh
|
|
187
|
+
* connection — call right after `connect()`.
|
|
188
|
+
*/
|
|
189
|
+
async hello(mobileDeviceId, mtInstanceId, _userAgent) {
|
|
190
|
+
if (!this.sock || this.sock.destroyed)
|
|
191
|
+
throw new Error('RawTransport not connected');
|
|
192
|
+
if (!/^[0-9a-f]{16}$/.test(mobileDeviceId)) {
|
|
193
|
+
throw new Error('hello(): mobileDeviceId must be 16 lowercase hex chars');
|
|
194
|
+
}
|
|
195
|
+
if (mtInstanceId.length !== 36) {
|
|
196
|
+
throw new Error('hello(): mtInstanceId must be a 36-char UUID string');
|
|
197
|
+
}
|
|
198
|
+
const frame = Buffer.from(HELLO_TEMPLATE);
|
|
199
|
+
Buffer.from(mtInstanceId, 'utf-8').copy(frame, HELLO_MT_OFFSET);
|
|
200
|
+
Buffer.from(mobileDeviceId, 'utf-8').copy(frame, HELLO_DEVICE_OFFSET);
|
|
201
|
+
// Sync our seq counter with the template (1) so subsequent ops get 2, 3, …
|
|
202
|
+
this.seq = 1;
|
|
203
|
+
const seq = 1;
|
|
204
|
+
this.hexDump('TX op=6 (HELLO template)', frame);
|
|
205
|
+
return new Promise((resolve, reject) => {
|
|
206
|
+
const timer = setTimeout(() => {
|
|
207
|
+
this.pending.delete(this.key(6, seq));
|
|
208
|
+
reject(new Error('HELLO timeout'));
|
|
209
|
+
}, this.opts.requestTimeoutMs);
|
|
210
|
+
this.pending.set(this.key(6, seq), {
|
|
211
|
+
resolve: (v) => resolve(v),
|
|
212
|
+
reject,
|
|
213
|
+
timer,
|
|
214
|
+
});
|
|
215
|
+
this.sock.write(frame, (err) => {
|
|
216
|
+
if (err) {
|
|
217
|
+
clearTimeout(timer);
|
|
218
|
+
this.pending.delete(this.key(6, seq));
|
|
219
|
+
reject(err);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
request(opcode, payload, opts = {}) {
|
|
225
|
+
if (!this.sock || this.sock.destroyed) {
|
|
226
|
+
return Promise.reject(new Error('RawTransport not connected'));
|
|
227
|
+
}
|
|
228
|
+
const seq = (++this.seq) & 0xffff;
|
|
229
|
+
const body = this.encodeBody(opcode, payload, opts);
|
|
230
|
+
let flags = FLAGS_DEFAULT;
|
|
231
|
+
if (opts.flags !== undefined)
|
|
232
|
+
flags = opts.flags;
|
|
233
|
+
else if (opts.prependOpHint !== undefined)
|
|
234
|
+
flags = FLAGS_PHONE_AUTH;
|
|
235
|
+
const frame = this.encodeFrame(seq, opcode, flags, body);
|
|
236
|
+
this.hexDump(`TX op=${opcode} seq=${seq} flags=${flags}`, frame);
|
|
237
|
+
return new Promise((resolve, reject) => {
|
|
238
|
+
const timer = setTimeout(() => {
|
|
239
|
+
this.pending.delete(this.key(opcode, seq));
|
|
240
|
+
reject(new Error(`Request timeout: op=${opcode} seq=${seq}`));
|
|
241
|
+
}, this.opts.requestTimeoutMs);
|
|
242
|
+
this.pending.set(this.key(opcode, seq), {
|
|
243
|
+
resolve: (v) => resolve(v),
|
|
244
|
+
reject,
|
|
245
|
+
timer,
|
|
246
|
+
});
|
|
247
|
+
this.sock.write(frame, (err) => {
|
|
248
|
+
if (err) {
|
|
249
|
+
clearTimeout(timer);
|
|
250
|
+
this.pending.delete(this.key(opcode, seq));
|
|
251
|
+
reject(err);
|
|
252
|
+
}
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
key(op, seq) {
|
|
257
|
+
return `${op}:${seq}`;
|
|
258
|
+
}
|
|
259
|
+
encodeBody(_op, payload, opts) {
|
|
260
|
+
if (payload === undefined)
|
|
261
|
+
return Buffer.alloc(0);
|
|
262
|
+
const body = Buffer.from(msgpackEncode(payload));
|
|
263
|
+
if (opts.rawPrefix !== undefined) {
|
|
264
|
+
return Buffer.concat([opts.rawPrefix, body]);
|
|
265
|
+
}
|
|
266
|
+
if (opts.prependOpHint !== undefined) {
|
|
267
|
+
// Observed wire prefix: 2 raw bytes [0xf0, <hint>]. The first byte
|
|
268
|
+
// is fixed (0xf0); the second is an op-specific subtype byte and is
|
|
269
|
+
// NOT msgpack-encoded — values >0x7f appear verbatim (e.g. 0xad on op 18).
|
|
270
|
+
const prefixByte = (opts.prefixInt ?? 0xf0) & 0xff;
|
|
271
|
+
const hintByte = opts.prependOpHint & 0xff;
|
|
272
|
+
return Buffer.concat([Buffer.from([prefixByte, hintByte]), body]);
|
|
273
|
+
}
|
|
274
|
+
if (opts.prependScalar !== undefined) {
|
|
275
|
+
return Buffer.concat([Buffer.from(msgpackEncode(opts.prependScalar)), body]);
|
|
276
|
+
}
|
|
277
|
+
return body;
|
|
278
|
+
}
|
|
279
|
+
encodeFrame(seq, op, flags, body) {
|
|
280
|
+
const buf = Buffer.alloc(HEADER_SIZE + body.length);
|
|
281
|
+
buf[0] = FRAME_MAGIC;
|
|
282
|
+
buf[1] = DIR_CLIENT;
|
|
283
|
+
buf[2] = (seq >> 8) & 0xff;
|
|
284
|
+
buf[3] = seq & 0xff;
|
|
285
|
+
buf[4] = (op >> 8) & 0xff;
|
|
286
|
+
buf[5] = op & 0xff;
|
|
287
|
+
buf[6] = flags & 0xff;
|
|
288
|
+
buf[7] = (body.length >> 16) & 0xff;
|
|
289
|
+
buf[8] = (body.length >> 8) & 0xff;
|
|
290
|
+
buf[9] = body.length & 0xff;
|
|
291
|
+
body.copy(buf, HEADER_SIZE);
|
|
292
|
+
return buf;
|
|
293
|
+
}
|
|
294
|
+
onData(chunk) {
|
|
295
|
+
this.rxBuf = this.rxBuf.length === 0 ? chunk : Buffer.concat([this.rxBuf, chunk]);
|
|
296
|
+
while (this.rxBuf.length >= HEADER_SIZE) {
|
|
297
|
+
const magic = this.rxBuf[0];
|
|
298
|
+
if (magic !== FRAME_MAGIC) {
|
|
299
|
+
this.emit('error', new Error(`Bad frame magic: 0x${magic.toString(16)}`));
|
|
300
|
+
this.rxBuf = Buffer.alloc(0);
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
const dir = this.rxBuf[1];
|
|
304
|
+
const seq = (this.rxBuf[2] << 8) | this.rxBuf[3];
|
|
305
|
+
const op = (this.rxBuf[4] << 8) | this.rxBuf[5];
|
|
306
|
+
const flags = this.rxBuf[6];
|
|
307
|
+
const len = (this.rxBuf[7] << 16) | (this.rxBuf[8] << 8) | this.rxBuf[9];
|
|
308
|
+
if (this.rxBuf.length < HEADER_SIZE + len)
|
|
309
|
+
return; // wait for more
|
|
310
|
+
const fullFrame = this.rxBuf.subarray(0, HEADER_SIZE + len);
|
|
311
|
+
const body = this.rxBuf.subarray(HEADER_SIZE, HEADER_SIZE + len);
|
|
312
|
+
this.hexDump(`RX op=${op} seq=${seq} flags=${flags}`, fullFrame);
|
|
313
|
+
this.rxBuf = this.rxBuf.subarray(HEADER_SIZE + len);
|
|
314
|
+
this.handleFrame(dir, seq, op, flags, body);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
handleFrame(dir, seq, op, flags, body) {
|
|
318
|
+
let payload = undefined;
|
|
319
|
+
if (body.length > 0) {
|
|
320
|
+
// `flags` is the `cof` byte (compress-or-flag): when non-zero the
|
|
321
|
+
// mobile binary protocol stores LZ4-compressed bytes after the header.
|
|
322
|
+
// The Android client encodes the ratio as `(uncompressed/compressed)+1`
|
|
323
|
+
// so we use it to size the decompression target generously, then trim.
|
|
324
|
+
let workingBody = body;
|
|
325
|
+
if (flags !== 0) {
|
|
326
|
+
try {
|
|
327
|
+
workingBody = this.lz4Decompress(body, flags);
|
|
328
|
+
}
|
|
329
|
+
catch (e) {
|
|
330
|
+
this.emit('error', new Error(`LZ4 decompress fail op=${op}: ${e.message}`));
|
|
331
|
+
// Fall back to raw bytes — extractLongestString may still find a token.
|
|
332
|
+
workingBody = body;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
try {
|
|
336
|
+
payload = this.decodeBody(workingBody);
|
|
337
|
+
}
|
|
338
|
+
catch (e) {
|
|
339
|
+
this.emit('error', new Error(`msgpack decode fail op=${op}: ${e.message}`));
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
this.emit('frame', { dir, seq, op, flags, payload });
|
|
344
|
+
if (dir === DIR_CLIENT) {
|
|
345
|
+
// echoed our own frame? unlikely on TLS but skip just in case
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
// dir = server → either response to our request or server-pushed event.
|
|
349
|
+
const p = this.pending.get(this.key(op, seq));
|
|
350
|
+
if (p) {
|
|
351
|
+
clearTimeout(p.timer);
|
|
352
|
+
this.pending.delete(this.key(op, seq));
|
|
353
|
+
if (payload && typeof payload === 'object' && payload.error) {
|
|
354
|
+
p.reject(new Error(`Server error: ${payload.error}`));
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
p.resolve(payload);
|
|
358
|
+
}
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
this.emit('push', { seq, op, payload });
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Decompress an LZ4-block-encoded body. The mobile binary protocol uses
|
|
365
|
+
* `lz4-java` `fastCompressor()` server-side (see `d2d.java`); we use the
|
|
366
|
+
* pure-JS `lz4js` block codec on the client. The `cof` byte from the header
|
|
367
|
+
* encodes the ratio `(uncompressed/compressed)+1`, which we use to size the
|
|
368
|
+
* output buffer with headroom.
|
|
369
|
+
*/
|
|
370
|
+
lz4Decompress(body, cof) {
|
|
371
|
+
// Headroom factor: cof=1 means ratio<2 (low compression), cof=N means up
|
|
372
|
+
// to (N-1)x. Use (cof+2)x + 1KB padding for safety; lz4js writes only the
|
|
373
|
+
// actual decompressed bytes and returns the length.
|
|
374
|
+
const headroom = Math.max(cof, 2) + 2;
|
|
375
|
+
const estSize = body.length * headroom + 1024;
|
|
376
|
+
const out = Buffer.alloc(estSize);
|
|
377
|
+
const inU8 = body instanceof Uint8Array ? body : new Uint8Array(body);
|
|
378
|
+
const written = lz4js.decompressBlock(inU8, out, 0, body.length, 0);
|
|
379
|
+
return out.subarray(0, written);
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Decode the body. Mobile-protocol responses prepend 2+ raw bytes before
|
|
383
|
+
* the actual msgpack map (e.g. op 6 reply: `f0 d2 … 87 <map>`; op 17 reply:
|
|
384
|
+
* `f3 a7 … 85 <map>`; op 18: similar). The map's trailing bytes can also
|
|
385
|
+
* contain "junk" the server still sends — `msgpackDecode` errors on extra
|
|
386
|
+
* bytes after the value. We scan offsets for a container header (fixmap /
|
|
387
|
+
* fixarray / map16) and use `decodeMulti` to take the FIRST value, which
|
|
388
|
+
* tolerates trailing data. Falls back to last stream value otherwise.
|
|
389
|
+
*/
|
|
390
|
+
decodeBody(body) {
|
|
391
|
+
// Scan offsets 0..8 for a container header. Prefer MAP candidates over
|
|
392
|
+
// ARRAY candidates — op 18 reply starts with `f2 91 82 …` where `91` is
|
|
393
|
+
// a fixarray-1 wrapping the real fixmap-2 payload at offset 2; without
|
|
394
|
+
// this preference we'd return `[{…}]` instead of `{…}`.
|
|
395
|
+
let arrayFallback = undefined;
|
|
396
|
+
const tryAt = (off) => {
|
|
397
|
+
try {
|
|
398
|
+
for (const v of msgpackDecodeMulti(body.subarray(off))) {
|
|
399
|
+
return v; // first value only
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
// ignore
|
|
404
|
+
}
|
|
405
|
+
return undefined;
|
|
406
|
+
};
|
|
407
|
+
for (let pass = 0; pass < 2; pass++) {
|
|
408
|
+
const wantMap = pass === 0;
|
|
409
|
+
for (let off = 0; off < Math.min(body.length, 9); off++) {
|
|
410
|
+
const h = body[off];
|
|
411
|
+
const isFixmap = h >= 0x80 && h <= 0x8f;
|
|
412
|
+
const isFixarr = h >= 0x90 && h <= 0x9f;
|
|
413
|
+
const isMap16 = h === 0xde || h === 0xdf;
|
|
414
|
+
const isArr16 = h === 0xdc || h === 0xdd;
|
|
415
|
+
const matches = wantMap ? (isFixmap || isMap16) : (isFixarr || isArr16);
|
|
416
|
+
if (!matches)
|
|
417
|
+
continue;
|
|
418
|
+
const v = tryAt(off);
|
|
419
|
+
if (v && typeof v === 'object') {
|
|
420
|
+
if (wantMap)
|
|
421
|
+
return v;
|
|
422
|
+
// Unwrap a 1-element array containing a map (server wraps some
|
|
423
|
+
// responses like op 18 in a fixarray).
|
|
424
|
+
if (Array.isArray(v) && v.length === 1 && v[0] && typeof v[0] === 'object') {
|
|
425
|
+
return v[0];
|
|
426
|
+
}
|
|
427
|
+
arrayFallback ??= v;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
if (arrayFallback !== undefined)
|
|
432
|
+
return arrayFallback;
|
|
433
|
+
// Fallback A: stream-decode, return the last value.
|
|
434
|
+
try {
|
|
435
|
+
const values = [];
|
|
436
|
+
for (const v of msgpackDecodeMulti(body))
|
|
437
|
+
values.push(v);
|
|
438
|
+
if (values.length > 0)
|
|
439
|
+
return values[values.length - 1];
|
|
440
|
+
}
|
|
441
|
+
catch {
|
|
442
|
+
try {
|
|
443
|
+
return msgpackDecode(body);
|
|
444
|
+
}
|
|
445
|
+
catch { }
|
|
446
|
+
}
|
|
447
|
+
// Fallback B: if the body clearly contains a LOGIN token response (op 115
|
|
448
|
+
// / op 18 happy path), the server uses an opaque non-msgpack form for the
|
|
449
|
+
// inner `LOGIN.<key>` field — scan for ASCII markers and pull out the
|
|
450
|
+
// longest str8/str16 value as the token.
|
|
451
|
+
const hasTokenAttrs = body.indexOf(Buffer.from('tokenAttrs')) >= 0;
|
|
452
|
+
const hasLogin = body.indexOf(Buffer.from('LOGIN')) >= 0;
|
|
453
|
+
if (hasTokenAttrs && hasLogin) {
|
|
454
|
+
const tok = this.extractLongestString(body);
|
|
455
|
+
if (tok)
|
|
456
|
+
return { tokenAttrs: { LOGIN: { token: tok } } };
|
|
457
|
+
}
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
/** Scan `buf` for the longest msgpack str8/str16/str32 ASCII payload. */
|
|
461
|
+
extractLongestString(buf) {
|
|
462
|
+
let best = null;
|
|
463
|
+
for (let i = 0; i < buf.length - 2; i++) {
|
|
464
|
+
let len = 0;
|
|
465
|
+
let start = -1;
|
|
466
|
+
const h = buf[i];
|
|
467
|
+
if (h === 0xd9) {
|
|
468
|
+
len = buf[i + 1];
|
|
469
|
+
start = i + 2;
|
|
470
|
+
}
|
|
471
|
+
else if (h === 0xda) {
|
|
472
|
+
len = (buf[i + 1] << 8) | buf[i + 2];
|
|
473
|
+
start = i + 3;
|
|
474
|
+
}
|
|
475
|
+
else if (h === 0xdb) {
|
|
476
|
+
len = ((buf[i + 1] << 24) >>> 0) | (buf[i + 2] << 16) | (buf[i + 3] << 8) | buf[i + 4];
|
|
477
|
+
start = i + 5;
|
|
478
|
+
}
|
|
479
|
+
else
|
|
480
|
+
continue;
|
|
481
|
+
if (len < 50 || start + len > buf.length)
|
|
482
|
+
continue;
|
|
483
|
+
const slice = buf.subarray(start, start + len);
|
|
484
|
+
// Token-like = printable ASCII (base64url charset).
|
|
485
|
+
let printable = true;
|
|
486
|
+
for (let k = 0; k < slice.length; k++) {
|
|
487
|
+
const c = slice[k];
|
|
488
|
+
if (c < 0x20 || c > 0x7e) {
|
|
489
|
+
printable = false;
|
|
490
|
+
break;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
if (!printable)
|
|
494
|
+
continue;
|
|
495
|
+
const s = slice.toString('utf-8');
|
|
496
|
+
if (!best || s.length > best.length)
|
|
497
|
+
best = s;
|
|
498
|
+
}
|
|
499
|
+
return best;
|
|
500
|
+
}
|
|
501
|
+
onClose() {
|
|
502
|
+
this.emit('close');
|
|
503
|
+
for (const [k, p] of this.pending) {
|
|
504
|
+
clearTimeout(p.timer);
|
|
505
|
+
p.reject(new Error('Transport closed by peer'));
|
|
506
|
+
this.pending.delete(k);
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
//# sourceMappingURL=raw-transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"raw-transport.js","sourceRoot":"","sources":["../src/raw-transport.ts"],"names":[],"mappings":"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"}
|