mytglib 2.0.1 → 2.0.3
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/README.md +106 -43
- package/dist/index.js +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -55,6 +55,20 @@ npm run example:login
|
|
|
55
55
|
|
|
56
56
|
示例按服务端响应处理邮箱设置、邮箱验证码、手机验证码和新账号注册。reCAPTCHA 出现时会显示 `action` 与 `siteKey`,并等待输入外部移动端求解器返回的 token。
|
|
57
57
|
|
|
58
|
+
### RegHelp 发码验收
|
|
59
|
+
|
|
60
|
+
`examples/reghelp-send-code.js` 默认读取 `examples/.env`,使用 `ios.API_CREDENTIALS`
|
|
61
|
+
第一项(当前 API ID `8`)和手机号 `+19156326494` 发起一次真实的 `auth.sendCode`。
|
|
62
|
+
可通过 `TELEGRAM_PHONE` 覆盖手机号,或同时通过 `TG_API_ID` 与 `TG_API_HASH` 选择数组中的其他凭据:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm run example:reghelp-send-code
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
该示例会完整输出 device token API、RegHelp 建任务与每次轮询、`invokeWithReCaptcha` 和最终
|
|
69
|
+
`auth.sentCode` 响应,并输出中间件从 Telegram challenge 暴露的全部字段。其中包含 device token、
|
|
70
|
+
rcmToken 和 `phoneCodeHash`。只应在可信的本地终端运行,且每次执行都会真实请求发送登录验证码。
|
|
71
|
+
|
|
58
72
|
## 基本 API
|
|
59
73
|
|
|
60
74
|
下面是常见的短信验证码登录路径;邮箱设置、新账号注册等完整分支见 `examples/login.js`。
|
|
@@ -102,6 +116,29 @@ try {
|
|
|
102
116
|
}
|
|
103
117
|
```
|
|
104
118
|
|
|
119
|
+
Android 和 iOS 分别通过公开且深冻结的 `android.API_CREDENTIALS` 与
|
|
120
|
+
`ios.API_CREDENTIALS` 列出可用的官方 API 凭据。Android 支持 ID 4、6,iOS 支持 ID 8、1;
|
|
121
|
+
数组第一项是省略自定义参数时的默认值,仍分别为 Android API ID 4 和 iOS API ID 8。需要使用
|
|
122
|
+
同平台的其他官方凭据时,保持 `clientType` 为 `"android"` 或 `"ios"`,并同时传入数组中同一项的
|
|
123
|
+
`apiId` 与 `apiHash`:
|
|
124
|
+
|
|
125
|
+
```js
|
|
126
|
+
const iosCore = new CoreClient({
|
|
127
|
+
clientType: "ios",
|
|
128
|
+
apiId: 1,
|
|
129
|
+
apiHash: "b6b154c3707471f5339bd661645ed3d6",
|
|
130
|
+
phone: "+12025550123",
|
|
131
|
+
proxy: { type: "http", host: "127.0.0.1", port: 8080 },
|
|
132
|
+
sessionDirPath: resolve("telegram-sessions"),
|
|
133
|
+
deviceTokenResolver: async () => ({ token: "AQIDBA==" }),
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`apiId` 与 `apiHash` 必须同时省略或同时提供;显式提供时必须精确匹配所选平台公开数组中的同一对,
|
|
138
|
+
不能交叉组合,也不会新增 `clientType`。选中的凭据会用于连接初始化和登录请求;首次授权新建 session
|
|
139
|
+
Metadata 时也会保存该凭据,之后 `syncSessionJson()` 从这份注册快照导出。重新打开已有 session 时,
|
|
140
|
+
按既有契约保留首次写入的 API 凭据及其他初始化配置,不会用本次构造参数改写注册快照。
|
|
141
|
+
|
|
105
142
|
iOS 默认使用 `ios.CURRENT_VERSION` 的最后一项。覆盖版本时仍需同时传入 `appVersion` 与
|
|
106
143
|
`overrideLayer`,以兼容现有调用方;`appVersion` 会原样用于 Telegram `initConnection.appVersion`,
|
|
107
144
|
`overrideLayer` 不会传给底层客户端。Node.js 的协议 layer 始终由 `@mtcute/node` 当前 codec 的
|
|
@@ -185,8 +222,9 @@ const jsonFilePath = await core.syncSessionJson();
|
|
|
185
222
|
测试或删除账号,不需要手工启用、停用或扩缩容。
|
|
186
223
|
|
|
187
224
|
Pool 使用消费者模式:外部请求只消费已经连接的 `READY` 槽位,不会在请求路径中临时连接
|
|
188
|
-
Telegram。创建 Pool
|
|
189
|
-
|
|
225
|
+
Telegram。创建 Pool 和后续补槽均为异步操作;检测可以在内部 deadline 内等待正在连接、正在被其他
|
|
226
|
+
请求使用或正在异步补入的槽位,但不会同步建立临时账号连接。生产环境应在接入流量前完成基础暖槽,
|
|
227
|
+
并为重试配置独立的 `RETRY` 暖槽。
|
|
190
228
|
|
|
191
229
|
### 初始化与导入
|
|
192
230
|
|
|
@@ -197,6 +235,7 @@ import { createPhoneStatusPool } from "mytglib";
|
|
|
197
235
|
const pool = await createPhoneStatusPool({
|
|
198
236
|
databasePath: resolve(".data/phone-status-pool/pool.sqlite"),
|
|
199
237
|
minWarmSlots: 10,
|
|
238
|
+
retryWarmSlots: 200,
|
|
200
239
|
});
|
|
201
240
|
|
|
202
241
|
const account = await pool.importAccount({
|
|
@@ -213,9 +252,9 @@ console.log(account.accountId, account.runtimeStatus);
|
|
|
213
252
|
自动识别。两套 schema 同时存在时:两侧都有效且授权状态完全一致才接受;两侧都有效但内容冲突
|
|
214
253
|
则拒绝;只有一侧有效时使用有效侧;两侧都无有效授权时拒绝。会话文件与 JSON 必须属于同一个
|
|
215
254
|
有效账号,导入时会严格核对 auth key、DC、账号身份和手机号。Pool 只接受 Telegram 官方移动端
|
|
216
|
-
凭据:Android
|
|
217
|
-
`
|
|
218
|
-
|
|
255
|
+
凭据:Android 必须精确匹配 `android.API_CREDENTIALS` 中的 ID 4 或 6 凭据对,iOS 必须精确匹配
|
|
256
|
+
`ios.API_CREDENTIALS` 中的 ID 8 或 1 凭据对;TDesktop、自定义 API ID、交叉组合或平台与
|
|
257
|
+
API 凭据不匹配的 JSON 会在建立 Telegram 连接前直接拒绝。当前不支持代理。
|
|
219
258
|
|
|
220
259
|
为兼容常见会话导出格式,JSON 的 `session_file` 只能写真实文件名
|
|
221
260
|
`account.session` 或同名 stem `account`,不得携带目录组件;导入后会统一规整为真实文件名。
|
|
@@ -239,12 +278,21 @@ SQLite 与 StringSession 中的 endpoint 只用于交叉校验;实际创建 Po
|
|
|
239
278
|
例如导入 500 个账号且设置 `minWarmSlots: 100` 时,Pool 只会先预热目标槽位,
|
|
240
279
|
剩余账号作为持久化库存待命,不会把 500 个账号同时上线。
|
|
241
280
|
|
|
242
|
-
|
|
281
|
+
`retryWarmSlots` 是专门服务账号级失败重试的独立暖槽数,默认值为 `0`,生产环境可按流量单独配置
|
|
282
|
+
(首轮建议 `200`,不把比例写死在代码中)。首次检测只使用 `PRIMARY` 槽;账号错误、
|
|
283
|
+
`FLOOD_WAIT` 或 RPC 超时等需要换账号时,只使用 `RETRY` 槽,普通 `PRIMARY` 槽不会被重试借用。
|
|
284
|
+
`maxAccountsPerPhone` 限制一次手机号检测最多使用的不同账号数,默认值为 `8`,可配置上限为 `16`,
|
|
285
|
+
用于避免单个手机号占满重试区。
|
|
286
|
+
|
|
287
|
+
Pool 的 PRIMARY 策略硬上限固定为 `minWarmSlots * 5`,加上 `retryWarmSlots` 后形成总策略上限,实际连接上限还会受进程 CPU、内存、文件描述符和
|
|
243
288
|
事件循环压力评估限制。忙碌槽位超过当前连接数一半时,Pool 会在资源允许的情况下异步提高目标槽位;
|
|
244
289
|
高峰过后,弹性槽位连续空闲 10 分钟才进入回收,并且每 30 秒最多回收一个,避免连接数瞬间震荡。
|
|
290
|
+
进入 `PRESSURED` 时,Pool 会先回收 PRIMARY 弹性槽,并保留当前资源上限能够承载的基础 PRIMARY
|
|
291
|
+
和独立 RETRY 槽;若上限不足,则优先保证 PRIMARY,按剩余容量降低 RETRY 数。只有进入
|
|
292
|
+
`CRITICAL` 时才暂停建连并回收全部 RETRY 和 PRIMARY 弹性槽。
|
|
245
293
|
当总连接上限高于 `minWarmSlots` 时,Pool 会在这个上限内部为导入和待机账号自检保留 1 个临时
|
|
246
|
-
管理连接位;该预留不会突破 `
|
|
247
|
-
|
|
294
|
+
管理连接位;该预留不会突破 PRIMARY 策略上限与 `retryWarmSlots` 之和。若资源上限已经低到不高于
|
|
295
|
+
最小暖槽数,管理建连会返回 `POOL_BUSY`,优先保护正在提供服务的暖槽。
|
|
248
296
|
|
|
249
297
|
### 检测与返回值
|
|
250
298
|
|
|
@@ -277,12 +325,17 @@ console.log(response.status, response.waitTime, response.error);
|
|
|
277
325
|
未映射到上述业务状态的检测异常会被捕获并以 `OTHER_ERROR` 正常返回,`error` 仅保留可用的 `message`、`name`、
|
|
278
326
|
`code`、`text` 和 `seconds`。
|
|
279
327
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
328
|
+
外部 HTTP 接口的端到端目标是 15 秒;Pool 内部为输入、排队、重试和清理预留固定的 14 秒共享
|
|
329
|
+
检测 deadline。每次 Telegram 检测 RPC 单独使用最多约 3 秒的局部 timeout,且关闭 mtcute 自带的该请求
|
|
330
|
+
重试。第一次使用 `PRIMARY` 槽;账号级错误、`FLOOD_WAIT` 或 RPC 超时后,后续尝试只从已经
|
|
331
|
+
`READY` 或正在异步补入的 `RETRY` 槽获取。后续尝试次数由剩余 `RETRY` 资源、单手机号账号上限和
|
|
332
|
+
14 秒 deadline 共同限制;资源允许时,仍可继续使用剩余重试暖槽兜底。
|
|
333
|
+
|
|
334
|
+
请求会在 deadline 内等待正在使用、正在连接或正在补槽的对应角色槽位,但不会在请求路径同步重启账号。
|
|
335
|
+
没有任何未使用的合格账号、重试暖槽耗尽或 deadline 到期时,返回最后一次已经实际发生的暖槽错误;
|
|
336
|
+
如果还没有发生暖槽错误,则返回 `OTHER_ERROR`,并通过 `error.code` 区分 `POOL_RETRY_TIMEOUT`、
|
|
337
|
+
`POOL_QUEUE_FULL` 或 `POOL_RESOURCE_CRITICAL` 等 Pool 原因。触发 `FLOOD_WAIT` 的账号会按 Telegram
|
|
338
|
+
返回的等待秒数退出暖槽并进入冷却,Pool 随即从库存异步补入其他账号。
|
|
286
339
|
若暖槽返回冻结账号错误,Pool 会将该账号永久隔离并换用其他 `READY` 槽位;当前检测返回的错误仍保留
|
|
287
340
|
Telegram 原始 `code = 420` 和错误文本。
|
|
288
341
|
`PHONE_NUMBER_FLOOD` 是目标手机号级错误,不换槽重试,只保护目标手机号 5 分钟且不处罚账号。
|
|
@@ -319,6 +372,9 @@ const removed = await pool.removeAccount(account.accountId);
|
|
|
319
372
|
`BUSY`;触发 flood 的账号进入 `COOLDOWN`,认证失效等致命错误会进入 `QUARANTINED`。
|
|
320
373
|
`testAccount()` 是由管理员主动触发的账号健康自检,不会拿这个账号去检测某个外部手机号,也不会由
|
|
321
374
|
协调器定时自动执行。`QUARANTINED` 是终态;自检不会把已隔离账号恢复为 `ACTIVE` 或重新加入调度。
|
|
375
|
+
单账号自检失败时会直接拒绝 Promise:Telegram RPC 错误保留具体的 `message`、数值 `code`、`text` 和
|
|
376
|
+
`seconds` 字段;Pool 自身错误仍使用 `PhoneStatusPoolError` 的字符串 `code`。`testAccounts()` 继续将
|
|
377
|
+
单账号错误收敛到批量报告的 `{ code, message }`,不改变批量接口契约。
|
|
322
378
|
管理接口返回完整 `phone` 和 ISO 格式或 `null` 的 `cooldownUntil`,但不会包含 auth key、原始
|
|
323
379
|
Metadata、session、Telegram 冻结时间或申诉地址等内部探测字段。
|
|
324
380
|
|
|
@@ -346,9 +402,10 @@ Metadata、session、Telegram 冻结时间或申诉地址等内部探测字段
|
|
|
346
402
|
`PoolAccount` 或 `null`,`error` 为 `null` 或 `{ code: string | null, message: string }`。
|
|
347
403
|
取消信号会停止批次并直接拒绝当前调用,不会把取消记成账号失败或改变账号健康状态。
|
|
348
404
|
|
|
349
|
-
`getStatus()`
|
|
350
|
-
|
|
351
|
-
|
|
405
|
+
`getStatus()` 可用于健康检查和后台展示,包含生命周期、账号库存、各运行态槽位数、PRIMARY/RETRY
|
|
406
|
+
角色槽位、对应等待队列、当前目标、策略上限、资源上限、资源压力和建连并发等信息。若业务需要等待
|
|
407
|
+
初始暖槽,可以在 API 对外接流量前轮询 `status.runtime.ready`;检测方法只在共享 deadline 内等待已安排的
|
|
408
|
+
槽位,不会同步创建连接。
|
|
352
409
|
|
|
353
410
|
### 部署与关闭
|
|
354
411
|
|
|
@@ -404,14 +461,21 @@ Telegram 客户端、定时器、缓存、SQLite 连接和 owner lock。关闭
|
|
|
404
461
|
### Rust API
|
|
405
462
|
|
|
406
463
|
Rust 实现从 `grammers_core` 根模块导出 `create_phone_status_pool()`、`PhoneStatusPool` 及相关
|
|
407
|
-
输入、响应和状态类型。调度、持久化格式和暖槽策略与 Node.js
|
|
408
|
-
`
|
|
409
|
-
`
|
|
410
|
-
|
|
411
|
-
`
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
464
|
+
输入、响应和状态类型。调度、持久化格式和暖槽策略与 Node.js 实现一致。手机号检测统一返回
|
|
465
|
+
扁平的 `PhoneStatusCheckResponse`,字段为 `wait_time`、`phone`、`started_at`、`ended_at`、
|
|
466
|
+
`duration_ms`、`status` 和 `error`;serde 序列化后与 Node.js 的 camelCase 对齐。没有可用资源、
|
|
467
|
+
排队超时或资源压力不会返回旧的 `BUSY` 变体,而是返回
|
|
468
|
+
`status = PhoneStatusPoolResult::OtherError`,序列化值为 `OTHER_ERROR`,并在 `error.code` 中区分
|
|
469
|
+
`POOL_RETRY_TIMEOUT`、`POOL_QUEUE_FULL` 或 `POOL_RESOURCE_CRITICAL`。创建和管理操作的
|
|
470
|
+
无效输入、调用取消、Pool 生命周期错误或内部协调错误仍通过 `PhoneStatusPoolError` 返回。
|
|
471
|
+
`test_account()` 的单账号失败会把 Telegram RPC 的具体文本写入 `PhoneStatusPoolError` 的 `message()`;
|
|
472
|
+
需要与 Node.js 对齐的结构化字段时调用 `phone_status_error()`,可取得 `message`、RPC 数值 `code`、
|
|
473
|
+
`text` 和 `seconds`。`PhoneStatusPoolError::code()` 仍保留 Pool 层分类,批量 `test_accounts()` 的错误
|
|
474
|
+
报告契约不变。
|
|
475
|
+
Rust Pool 使用 14 秒共享检测 deadline,每次 Telegram 检测 RPC 最多约 3 秒;首次只用 `PRIMARY`
|
|
476
|
+
暖槽,账号级失败后的重试只用隔离的 `RETRY` 暖槽。后续尝试由剩余 `RETRY` 资源、
|
|
477
|
+
`max_accounts_per_phone` 和 deadline 共同限制;`PHONE_NUMBER_FLOOD` 按手机号保护,
|
|
478
|
+
不换账号。
|
|
415
479
|
Rust 与 Node.js 采用相同的冻结账号规则:导入时探测到 `FROZEN` 或 `UNKNOWN` 不落库,运行中发现冻结
|
|
416
480
|
则进入终态 `QUARANTINED`。AppConfig 主动识别冻结返回 `ACCOUNT_INVALID`;Telegram RPC 真实返回的
|
|
417
481
|
`FROZEN_*` 错误仍在错误 source 链中保留 `code = 420`,不会改写成 401。公共账号结构不暴露冻结
|
|
@@ -421,13 +485,15 @@ Rust 字段名使用 snake_case,通过 serde 序列化时使用 camelCase。
|
|
|
421
485
|
|
|
422
486
|
```rust,no_run
|
|
423
487
|
use grammers_core::{
|
|
424
|
-
CheckPhoneStatusInput, CloseOptions, ImportAccountInput,
|
|
425
|
-
|
|
488
|
+
CheckPhoneStatusInput, CloseOptions, ImportAccountInput, PhoneStatusPoolError,
|
|
489
|
+
PhoneStatusPoolOptions, TestAccountsInput, create_phone_status_pool,
|
|
426
490
|
};
|
|
427
491
|
|
|
428
492
|
# async fn example() -> Result<(), PhoneStatusPoolError> {
|
|
429
493
|
let mut options = PhoneStatusPoolOptions::new("/secure/phone-status-pool/pool.sqlite");
|
|
430
494
|
options.min_warm_slots = 10;
|
|
495
|
+
options.retry_warm_slots = 200;
|
|
496
|
+
options.max_accounts_per_phone = 8;
|
|
431
497
|
let pool = create_phone_status_pool(options).await?;
|
|
432
498
|
|
|
433
499
|
// 即使任一管理或检测步骤失败,下面仍会执行安全关闭。
|
|
@@ -439,20 +505,13 @@ use grammers_core::{
|
|
|
439
505
|
))
|
|
440
506
|
.await?;
|
|
441
507
|
|
|
442
|
-
|
|
508
|
+
let response = pool
|
|
443
509
|
.check_phone_status(CheckPhoneStatusInput::new("+12025550123"))
|
|
444
|
-
.await
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
cached,
|
|
450
|
-
..
|
|
451
|
-
} => println!("{result:?} {checked_at} cached={cached}"),
|
|
452
|
-
PhoneStatusCheckResponse::Busy {
|
|
453
|
-
retry_after_seconds,
|
|
454
|
-
} => println!("BUSY retryAfterSeconds={retry_after_seconds}"),
|
|
455
|
-
}
|
|
510
|
+
.await?;
|
|
511
|
+
println!(
|
|
512
|
+
"status={:?} waitTime={} durationMs={} error={:?}",
|
|
513
|
+
response.status, response.wait_time, response.duration_ms, response.error,
|
|
514
|
+
);
|
|
456
515
|
|
|
457
516
|
let accounts = pool.list_accounts().await?;
|
|
458
517
|
let detail = pool.get_account(&account.account_id).await?;
|
|
@@ -481,7 +540,8 @@ use grammers_core::{
|
|
|
481
540
|
# }
|
|
482
541
|
```
|
|
483
542
|
|
|
484
|
-
`PhoneStatusPoolOptions::new()` 要求绝对数据库路径,`min_warm_slots` 省略时为 `10
|
|
543
|
+
`PhoneStatusPoolOptions::new()` 要求绝对数据库路径,`min_warm_slots` 省略时为 `10`,
|
|
544
|
+
`retry_warm_slots` 默认为 `0`,`max_accounts_per_phone` 默认为 `8` 且最大为 `16`。创建方法只
|
|
485
545
|
打开本地状态并启动异步预热,不等待 Telegram 暖槽连接完成;可在接入业务流量前轮询
|
|
486
546
|
`pool.get_status().await?.runtime.ready`。同一个数据库仍只能由一个 Pool 实例持有,进程退出前应
|
|
487
547
|
始终调用 `pool.close(CloseOptions::default()).await`。如果强制关闭宽限期结束时仍有后台清理,
|
|
@@ -667,8 +727,11 @@ console.log(result);
|
|
|
667
727
|
|
|
668
728
|
`vendor/grammers` 是为后续 Tauri/Rust 桌面端准备的内置 fork,其中项目自有的
|
|
669
729
|
`grammers-core` 承载 `src` 对应的 Rust 实现。它目前尚未接入本 npm 包的 JavaScript 运行路径,
|
|
670
|
-
也不会进入 npm 发布包。
|
|
671
|
-
|
|
730
|
+
也不会进入 npm 发布包。crate 根模块公开 `ApiCredentials`、`android::API_CREDENTIALS` 和
|
|
731
|
+
`ios::API_CREDENTIALS`;`CoreClientConfig.api_id` 与 `api_hash` 同时省略时使用对应数组第一项,同时
|
|
732
|
+
提供时必须精确匹配同平台凭据对。Rust `CoreClient` 在 backend 连接初始化尚未完成、没有业务
|
|
733
|
+
transport frame 写出时,若初始化明确超时会自动重新创建一次 backend;该限定重试独立于 RPC 的
|
|
734
|
+
`max_retry_count`。
|
|
672
735
|
上游基线、本地覆盖层、
|
|
673
736
|
可重复的同步流程和验证范围见
|
|
674
737
|
[grammers fork 维护文档](docs/grammers-fork.md)。
|