@perk-net/perk-pushplus-sdk 1.0.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.
@@ -0,0 +1,1208 @@
1
+ /**
2
+ * PushPlus SDK 全局配置。
3
+ *
4
+ * 通过 `PushPlusClient.builder()` 或直接 `new PushPlusClient(config)` 构建实例。
5
+ * 所有字段都有合理默认值,仅 `token` 是发送消息接口必填、`secretKey` 是开放接口必填。
6
+ */
7
+ interface PushPlusConfig {
8
+ /**
9
+ * 用户 token 或消息 token,发送消息接口默认使用。
10
+ * 注意:获取 AccessKey 必须使用用户 token。
11
+ */
12
+ token?: string;
13
+ /**
14
+ * 用户 secretKey,调用开放接口(获取 AccessKey)必填。
15
+ * 在 pushplus 个人中心 -> 开发设置 中配置。
16
+ */
17
+ secretKey?: string;
18
+ /**
19
+ * 服务器基础地址。默认:https://www.pushplus.plus
20
+ */
21
+ baseUrl?: string;
22
+ /** 连接超时(毫秒)。默认 10000。 */
23
+ connectTimeoutMs?: number;
24
+ /** 请求/读超时(毫秒)。默认 30000。 */
25
+ readTimeoutMs?: number;
26
+ /**
27
+ * 在 AccessKey 过期前提前多少秒刷新。默认提前 5 分钟(300 秒),
28
+ * 文档中提到老 AccessKey 在新 AccessKey 生成后 5 分钟内仍可用。
29
+ */
30
+ accessKeyRefreshAheadSeconds?: number;
31
+ /** 是否启用请求/响应详细日志。默认关闭。 */
32
+ logRequest?: boolean;
33
+ /**
34
+ * 是否启用本地限流守卫。默认开启。
35
+ *
36
+ * 开启后,当任意一次发送消息接口返回 code=900(请求次数过多)时,
37
+ * 后续对同一 token 的发送调用会被 SDK 直接短路,不再发起 HTTP,
38
+ * 直到 `rateLimitCooldownMs`(默认次日 0 点)到期。
39
+ */
40
+ rateLimitGuardEnabled?: boolean;
41
+ /**
42
+ * 命中 code=900 后的本地禁推时长(毫秒)。
43
+ * 不传或 <=0 表示使用默认策略:到「次日 0 点」。
44
+ *
45
+ * 注意:服务端实际禁推时长可能更长(文档示例为 2 天)。
46
+ */
47
+ rateLimitCooldownMs?: number;
48
+ /** 自定义 User-Agent。 */
49
+ userAgent?: string;
50
+ }
51
+ /** PushPlus 默认服务地址。 */
52
+ declare const DEFAULT_BASE_URL = "https://www.pushplus.plus";
53
+ interface ResolvedPushPlusConfig {
54
+ token: string;
55
+ secretKey: string;
56
+ baseUrl: string;
57
+ connectTimeoutMs: number;
58
+ readTimeoutMs: number;
59
+ accessKeyRefreshAheadSeconds: number;
60
+ logRequest: boolean;
61
+ rateLimitGuardEnabled: boolean;
62
+ rateLimitCooldownMs: number;
63
+ userAgent: string;
64
+ }
65
+ declare function resolveConfig(input: PushPlusConfig | undefined | null): ResolvedPushPlusConfig;
66
+
67
+ interface HttpRequestOptions {
68
+ method: string;
69
+ url: string;
70
+ headers?: Record<string, string>;
71
+ body?: string | null;
72
+ }
73
+ interface HttpResponse {
74
+ statusCode: number;
75
+ body: string;
76
+ }
77
+ /**
78
+ * HTTP 请求执行器抽象。
79
+ *
80
+ * SDK 默认提供基于 `fetch` 的实现(Node 18+ 内置 / 浏览器原生)。
81
+ * 调用方也可以自行实现并通过 `PushPlusClient` 注入以使用其它客户端(如 axios/undici/got)。
82
+ */
83
+ interface HttpRequester {
84
+ execute(options: HttpRequestOptions): Promise<HttpResponse>;
85
+ }
86
+ /**
87
+ * 基于 fetch 的请求执行器。
88
+ *
89
+ * - Node.js:18+ 自带全局 fetch;< 18 需要使用 polyfill 或自定义 HttpRequester。
90
+ * - 浏览器:所有现代浏览器原生支持。
91
+ *
92
+ * 实现是无状态的,可作为 SDK 单例长期复用。
93
+ */
94
+ declare class FetchHttpRequester implements HttpRequester {
95
+ private readonly readTimeoutMs;
96
+ private readonly logRequest;
97
+ private readonly userAgent;
98
+ private readonly fetchImpl;
99
+ constructor(config: ResolvedPushPlusConfig, fetchImpl?: typeof fetch);
100
+ execute(options: HttpRequestOptions): Promise<HttpResponse>;
101
+ }
102
+ /**
103
+ * 是否处于成功的 HTTP 状态码区间(2xx)。
104
+ */
105
+ declare function isSuccessfulHttpStatus(status: number): boolean;
106
+
107
+ /**
108
+ * PushPlus 发送渠道枚举。
109
+ *
110
+ * 对应官方文档「发送渠道(channel)枚举」。
111
+ */
112
+ declare enum Channel {
113
+ /** 微信公众号(默认)。 */
114
+ WECHAT = "wechat",
115
+ /** 第三方 webhook(企业微信/钉钉/飞书/bark/Gotify/Server酱/IFTTT/WxPusher 等)。 */
116
+ WEBHOOK = "webhook",
117
+ /** 企业微信应用。 */
118
+ CP = "cp",
119
+ /** 邮箱。 */
120
+ MAIL = "mail",
121
+ /** 短信(收费)。 */
122
+ SMS = "sms",
123
+ /** 语音(收费)。 */
124
+ VOICE = "voice",
125
+ /** 浏览器扩展插件 / 桌面应用程序。 */
126
+ EXTENSION = "extension",
127
+ /** App 渠道(安卓/鸿蒙/iOS)。 */
128
+ APP = "app",
129
+ /** 微信 ClawBot。 */
130
+ CLAWBOT = "clawbot"
131
+ }
132
+ /**
133
+ * PushPlus 消息模板枚举。
134
+ */
135
+ declare enum Template {
136
+ /** 默认模板,支持 HTML 文本。 */
137
+ HTML = "html",
138
+ /** 纯文本,不转义 HTML。 */
139
+ TXT = "txt",
140
+ /** 基于 JSON 格式展示。 */
141
+ JSON = "json",
142
+ /** Markdown 格式。 */
143
+ MARKDOWN = "markdown",
144
+ /** 阿里云监控报警定制模板。 */
145
+ CLOUD_MONITOR = "cloudMonitor",
146
+ /** Jenkins 插件定制模板。 */
147
+ JENKINS = "jenkins",
148
+ /** 路由器插件定制模板。 */
149
+ ROUTE = "route",
150
+ /** 支付成功通知模板。 */
151
+ PAY = "pay"
152
+ }
153
+ /**
154
+ * 消息投递状态。
155
+ *
156
+ * 0-未发送/未投递,1-发送中,2-发送成功,3-发送失败。
157
+ */
158
+ declare enum SendStatus {
159
+ NOT_SENT = 0,
160
+ SENDING = 1,
161
+ SUCCESS = 2,
162
+ FAILED = 3
163
+ }
164
+ declare const SendStatusDescription: Record<SendStatus, string>;
165
+ /**
166
+ * 回调事件类型。
167
+ */
168
+ declare enum CallbackEvent {
169
+ /** 消息发送完成。 */
170
+ MESSAGE_COMPLETE = "message_complate",
171
+ /** 群组新增用户。 */
172
+ ADD_TOPIC_USER = "add_topic_user",
173
+ /** 新增好友。 */
174
+ ADD_FRIEND = "add_friend"
175
+ }
176
+ /**
177
+ * Webhook 渠道类型。
178
+ *
179
+ * 对应开放接口文档「webhook 列表」中的 webhookType 枚举值。
180
+ */
181
+ declare enum WebhookType {
182
+ WORK_WECHAT_BOT = 1,
183
+ DING_TALK_BOT = 2,
184
+ FEISHU_BOT = 3,
185
+ SERVER_CHAN = 4,
186
+ BARK = 50,
187
+ WORK_WECHAT_APP = 6,
188
+ TENCENT_LIGHT_LINK = 7,
189
+ IFTTT = 8,
190
+ JI_JIAN_YUN = 9,
191
+ GOTIFY = 10,
192
+ WX_PUSHER = 11,
193
+ CUSTOM = 12
194
+ }
195
+ declare const WebhookTypeDescription: Record<number, string>;
196
+ /**
197
+ * PushPlus 接口业务返回码语义。
198
+ *
199
+ * 对应官方文档「接口返回码说明」:https://www.pushplus.plus/doc/guide/code.html
200
+ */
201
+ declare enum ErrorCode {
202
+ /** 200 执行成功。 */
203
+ OK = 200,
204
+ /** 302 未登录。 */
205
+ NOT_LOGIN = 302,
206
+ /** 401 请求未授权(开放接口未启用)。 */
207
+ UNAUTHORIZED = 401,
208
+ /** 403 请求 IP 未授权(白名单未配置)。 */
209
+ IP_FORBIDDEN = 403,
210
+ /** 500 系统异常,请稍后再试。 */
211
+ SERVER_ERROR = 500,
212
+ /** 600 数据异常,操作失败。 */
213
+ DATA_ERROR = 600,
214
+ /** 805 无权查看。 */
215
+ FORBIDDEN_VIEW = 805,
216
+ /** 888 积分不足,需要充值。 */
217
+ INSUFFICIENT_POINTS = 888,
218
+ /** 900 用户账号使用受限(请求次数过多)。 */
219
+ RATE_LIMITED = 900,
220
+ /** 905 账户未进行实名认证。 */
221
+ NOT_VERIFIED = 905,
222
+ /** 903 无效的用户令牌。 */
223
+ INVALID_TOKEN = 903,
224
+ /** 999 服务端验证错误。 */
225
+ VALIDATION_ERROR = 999,
226
+ /** 其它未在文档中列出的 code。 */
227
+ UNKNOWN = -1
228
+ }
229
+ declare function errorCodeFromValue(code: number | null | undefined): ErrorCode;
230
+ declare function isRateLimitedCode(code: number | null | undefined): boolean;
231
+
232
+ /**
233
+ * PushPlus 接口统一响应。所有接口都遵循 `{code, msg, data}` 结构。
234
+ */
235
+ interface ApiResponse<T = unknown> {
236
+ code?: number;
237
+ msg?: string;
238
+ data?: T;
239
+ }
240
+ /** 通用分页请求参数。 */
241
+ interface PageQuery {
242
+ /** 当前所在分页数,默认 1。 */
243
+ current?: number;
244
+ /** 每页大小,默认 20,最大 50。 */
245
+ pageSize?: number;
246
+ }
247
+ /** 分页响应结构。 */
248
+ interface PageResult<T> {
249
+ pageNum?: number;
250
+ pageSize?: number;
251
+ total?: number;
252
+ pages?: number;
253
+ list?: T[];
254
+ }
255
+ /**
256
+ * 发送消息请求。对应 `/send` 接口。
257
+ *
258
+ * 推荐使用 `SendRequestBuilder`(`SendRequest.builder()`)链式构建。
259
+ */
260
+ interface SendRequest {
261
+ /** 用户 token 或消息 token。可不填,由 SDK 从 PushPlusConfig 自动注入。 */
262
+ token?: string;
263
+ /** 消息标题。 */
264
+ title?: string;
265
+ /** 消息内容;必填。 */
266
+ content?: string;
267
+ /** 群组编码。不填仅发送给自己;channel 为 webhook 时无效。 */
268
+ topic?: string;
269
+ /** 发送模板,默认 html。 */
270
+ template?: Template | string;
271
+ /** 发送渠道,默认 wechat。 */
272
+ channel?: Channel | string;
273
+ /** 渠道配置参数(cp/webhook/mail 渠道使用渠道编码)。 */
274
+ option?: string;
275
+ /** 异步回调地址。 */
276
+ callbackUrl?: string;
277
+ /** 毫秒时间戳;服务器时间大于此时间戳消息不会发送。 */
278
+ timestamp?: number;
279
+ /** 好友令牌;多个用逗号分隔。 */
280
+ to?: string;
281
+ /** 预处理编码(仅会员)。 */
282
+ pre?: string;
283
+ }
284
+ declare class SendRequestBuilder {
285
+ private req;
286
+ token(v?: string): this;
287
+ title(v?: string): this;
288
+ content(v?: string): this;
289
+ topic(v?: string): this;
290
+ template(v?: Template | string): this;
291
+ channel(v?: Channel | string): this;
292
+ option(v?: string): this;
293
+ callbackUrl(v?: string): this;
294
+ timestamp(v?: number): this;
295
+ to(v?: string): this;
296
+ pre(v?: string): this;
297
+ build(): SendRequest;
298
+ }
299
+ /**
300
+ * 创建 SendRequest 链式构造器。
301
+ */
302
+ declare function sendRequest(): SendRequestBuilder;
303
+ /**
304
+ * 多渠道发送消息请求。对应 `/batchSend` 接口。
305
+ */
306
+ interface BatchSendRequest {
307
+ token?: string;
308
+ title?: string;
309
+ content?: string;
310
+ topic?: string;
311
+ template?: Template | string;
312
+ /** 多渠道,逗号分隔。 */
313
+ channel?: string;
314
+ /** 多渠道 option,逗号分隔;与 channel 一一对应。 */
315
+ option?: string;
316
+ callbackUrl?: string;
317
+ timestamp?: number;
318
+ to?: string;
319
+ pre?: string;
320
+ }
321
+ /**
322
+ * 链式 Builder:支持以 `channel(Channel)` / `option(string)` 形式累积调用,
323
+ * 内部自动用逗号拼接并按顺序一一对应。
324
+ *
325
+ * 也可以通过 `channelString`/`optionString` 直接指定 CSV 字符串。
326
+ * 累积式优先级高于 CSV 字符串。
327
+ */
328
+ declare class BatchSendRequestBuilder {
329
+ private req;
330
+ private readonly channelList;
331
+ private readonly optionList;
332
+ token(v?: string): this;
333
+ title(v?: string): this;
334
+ content(v?: string): this;
335
+ topic(v?: string): this;
336
+ template(v?: Template | string): this;
337
+ callbackUrl(v?: string): this;
338
+ timestamp(v?: number): this;
339
+ to(v?: string): this;
340
+ pre(v?: string): this;
341
+ /** 追加一个 channel。 */
342
+ channel(ch: Channel | string): this;
343
+ /** 追加一个 option,与最近一次 channel() 配对;可传空串。 */
344
+ option(opt?: string): this;
345
+ /** 直接以 CSV 形式指定多渠道字符串(与累积式 channel(Channel) 互斥)。 */
346
+ channelString(csv?: string): this;
347
+ /** 直接以 CSV 形式指定 option 字符串。 */
348
+ optionString(csv?: string): this;
349
+ build(): BatchSendRequest;
350
+ }
351
+ /**
352
+ * 创建 BatchSendRequest 链式构造器。
353
+ */
354
+ declare function batchSendRequest(): BatchSendRequestBuilder;
355
+ /** 批量发送的单条渠道结果。 */
356
+ interface BatchSendResult {
357
+ /** 消息流水号;可用于查询发送结果。 */
358
+ shortCode?: string;
359
+ /** 业务消息。 */
360
+ message?: string;
361
+ /** 业务 code。 */
362
+ code?: number;
363
+ /** 渠道。 */
364
+ channel?: Channel | string;
365
+ }
366
+ interface MessageCompleteInfo {
367
+ /** 推送错误内容(如有)。 */
368
+ message?: string;
369
+ /** 消息流水号。 */
370
+ shortCode?: string;
371
+ /** 发送状态:0-未发送,1-发送中,2-发送成功,3-发送失败。 */
372
+ sendStatus?: SendStatus | number;
373
+ }
374
+ interface TopicUserInfo {
375
+ id?: number;
376
+ openId?: string;
377
+ topicId?: number;
378
+ userSex?: number;
379
+ isFollow?: number;
380
+ nickName?: string;
381
+ havePhone?: number;
382
+ topicCode?: string;
383
+ topicName?: string;
384
+ headImgUrl?: string;
385
+ emailStatus?: number;
386
+ }
387
+ interface FriendInfo {
388
+ token?: string;
389
+ friendId?: number;
390
+ isFollow?: number;
391
+ nickName?: string;
392
+ havePhone?: number;
393
+ createTime?: string;
394
+ emailStatus?: number;
395
+ }
396
+ /**
397
+ * PushPlus 回调统一载体。
398
+ *
399
+ * 使用 `parseCallback(json)` 解析回调请求体后,
400
+ * 根据 `event` 判断事件类型并取对应的字段。
401
+ */
402
+ interface CallbackPayload {
403
+ event?: CallbackEvent | string;
404
+ messageInfo?: MessageCompleteInfo;
405
+ topicUserInfo?: TopicUserInfo;
406
+ friendInfo?: FriendInfo;
407
+ /** 自定义二维码参数(仅 add_friend 事件有值)。 */
408
+ qrCode?: string;
409
+ }
410
+ interface AccessKeyResult {
411
+ /** 访问令牌,后续请求需加到 header 中。 */
412
+ accessKey?: string;
413
+ /** 过期时间(单位秒)。 */
414
+ expiresIn?: number;
415
+ }
416
+ interface UserInfo {
417
+ openId?: string;
418
+ unionId?: string;
419
+ nickName?: string;
420
+ headImgUrl?: string;
421
+ userSex?: number;
422
+ token?: string;
423
+ phoneNumber?: string;
424
+ email?: string;
425
+ emailStatus?: number;
426
+ birthday?: string;
427
+ points?: number;
428
+ }
429
+ interface SendCount {
430
+ wechatSendCount?: number;
431
+ cpSendCount?: number;
432
+ webhookSendCount?: number;
433
+ mailSendCount?: number;
434
+ }
435
+ interface UserLimitTime {
436
+ /** 1-无限制,2-短期限制,3-永久限制。 */
437
+ sendLimit?: number;
438
+ userLimitTime?: string;
439
+ }
440
+ interface MessageItem {
441
+ topicName?: string;
442
+ /** 消息类型:1-一对一消息,2-一对多消息。 */
443
+ messageType?: number;
444
+ title?: string;
445
+ shortCode?: string;
446
+ channel?: Channel | string;
447
+ updateTime?: string;
448
+ }
449
+ interface SendMessageResult {
450
+ /** 0-未投递,1-发送中,2-已发送,3-发送失败。 */
451
+ status?: SendStatus | number;
452
+ errorMessage?: string;
453
+ updateTime?: string;
454
+ }
455
+ interface MessageTokenAddRequest {
456
+ /** 令牌名称;必填。 */
457
+ name: string;
458
+ /** 过期时间,格式 yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss;不填默认 2999-12-31。 */
459
+ expireTime?: string;
460
+ }
461
+ interface MessageTokenEditRequest {
462
+ id: number;
463
+ name?: string;
464
+ expireTime?: string;
465
+ }
466
+ interface MessageTokenItem {
467
+ id?: number;
468
+ name?: string;
469
+ expireTime?: string;
470
+ token?: string;
471
+ }
472
+ interface MessageTokenOption {
473
+ id?: number;
474
+ name?: string;
475
+ }
476
+ interface TopicListQuery {
477
+ current?: number;
478
+ pageSize?: number;
479
+ /** 例如 { topicType: 0 };0-我创建的,1-我加入的。 */
480
+ params?: Record<string, unknown>;
481
+ }
482
+ interface TopicQrCode {
483
+ qrCodeImgUrl?: string;
484
+ /** 0-临时二维码,1-永久二维码。 */
485
+ forever?: number;
486
+ }
487
+ interface TopicAddRequest {
488
+ topicCode?: string;
489
+ topicName?: string;
490
+ contact?: string;
491
+ introduction?: string;
492
+ receiptMessage?: string;
493
+ appId?: string;
494
+ icon?: string;
495
+ /** 0普通;1积分;2公开。默认 0。 */
496
+ topicType?: number;
497
+ price?: number | string;
498
+ topicDescribe?: string;
499
+ }
500
+ interface TopicEditRequest {
501
+ /** 群组编号,必填。 */
502
+ topic: number;
503
+ topicCode?: string;
504
+ topicName?: string;
505
+ contact?: string;
506
+ introduction?: string;
507
+ receiptMessage?: string;
508
+ icon?: string;
509
+ price?: number | string;
510
+ topicDescribe?: string;
511
+ }
512
+ interface TopicDetail {
513
+ topicId?: number;
514
+ topicName?: string;
515
+ topicCode?: string;
516
+ qrCodeImgUrl?: string;
517
+ contact?: string;
518
+ introduction?: string;
519
+ receiptMessage?: string;
520
+ nickName?: string;
521
+ createTime?: string;
522
+ topicUserCount?: number;
523
+ icon?: string;
524
+ appId?: string;
525
+ topicType?: number;
526
+ price?: number | string;
527
+ topicDescribe?: string;
528
+ userNickName?: string;
529
+ isApproved?: number;
530
+ firstIsApproved?: number;
531
+ approveReason?: string;
532
+ isOpen?: number;
533
+ }
534
+ interface TopicItem {
535
+ icon?: string;
536
+ topicId?: number;
537
+ topicCode?: string;
538
+ topicName?: string;
539
+ nickName?: string;
540
+ createTime?: string;
541
+ topicUserCount?: number;
542
+ /** 0普通群组;1积分群组;2公开群组。 */
543
+ topicType?: number;
544
+ isApproved?: number;
545
+ firstIsApproved?: number;
546
+ approveReason?: string;
547
+ /** 0否,1是。 */
548
+ isOpen?: number;
549
+ }
550
+ interface TopicUserItem {
551
+ id?: number;
552
+ nickName?: string;
553
+ openId?: string;
554
+ headImgUrl?: string;
555
+ userSex?: number;
556
+ havePhone?: number;
557
+ isFollow?: number;
558
+ emailStatus?: number;
559
+ followTime?: string;
560
+ remark?: string;
561
+ }
562
+ interface TopicUserListQuery {
563
+ current?: number;
564
+ pageSize?: number;
565
+ /** 例如 { topicId }。 */
566
+ params?: Record<string, unknown>;
567
+ }
568
+ interface WebhookItem {
569
+ id?: number;
570
+ webhookCode?: string;
571
+ webhookName?: string;
572
+ webhookType?: WebhookType | number;
573
+ webhookTypeName?: string;
574
+ webhookUrl?: string;
575
+ createTime?: string;
576
+ /** 自定义类型才返回。 */
577
+ httpMethod?: string;
578
+ headers?: string;
579
+ body?: string;
580
+ }
581
+ interface WebhookSaveRequest {
582
+ /** 仅修改时使用。 */
583
+ id?: number;
584
+ webhookCode?: string;
585
+ webhookName?: string;
586
+ webhookType?: WebhookType | number;
587
+ webhookUrl?: string;
588
+ /** 自定义类型时使用。 */
589
+ httpMethod?: string;
590
+ headers?: string;
591
+ body?: string;
592
+ }
593
+ interface FriendItem {
594
+ id?: number;
595
+ friendId?: number;
596
+ token?: string;
597
+ headImgUrl?: string;
598
+ nickName?: string;
599
+ emailStatus?: number;
600
+ havePhone?: number;
601
+ isFollow?: number;
602
+ remark?: string;
603
+ createTime?: string;
604
+ }
605
+ interface FriendQrCode {
606
+ qrCodeImgUrl?: string;
607
+ }
608
+ interface ClawBotInfo {
609
+ createTime?: string;
610
+ /** 是否有对话令牌(文档为字符串/数字混用,统一用 number 兼容)。 */
611
+ haveContextToken?: number;
612
+ }
613
+ interface ClawBotMessage {
614
+ /** 1-文字,3-语音。 */
615
+ type?: number;
616
+ text?: string;
617
+ }
618
+ interface ClawBotQrCode {
619
+ url?: string;
620
+ qrcode?: string;
621
+ }
622
+ interface MpItem {
623
+ id?: number;
624
+ nickName?: string;
625
+ headImg?: string;
626
+ principalName?: string;
627
+ authorizationAppid?: string;
628
+ funcInfo?: string;
629
+ serviceType?: number;
630
+ verifyType?: number;
631
+ alias?: string;
632
+ updateTime?: string;
633
+ }
634
+ interface CpItem {
635
+ id?: number;
636
+ cpName?: string;
637
+ cpCode?: string;
638
+ }
639
+ interface MailItem {
640
+ id?: number;
641
+ mailName?: string;
642
+ mailCode?: string;
643
+ }
644
+ interface MailDetail {
645
+ id?: number;
646
+ mailName?: string;
647
+ mailCode?: string;
648
+ account?: string;
649
+ password?: string;
650
+ smtpServer?: string;
651
+ smtpSsl?: number;
652
+ smtpPort?: number;
653
+ createTime?: string;
654
+ }
655
+ interface UserDefaultDetail {
656
+ id?: number;
657
+ channel?: Channel | string;
658
+ option?: string;
659
+ pre?: string;
660
+ updateTime?: string;
661
+ name?: string;
662
+ tokenId?: number;
663
+ }
664
+ interface UserDefaultItem {
665
+ id?: number;
666
+ channel?: Channel | string;
667
+ channelTxt?: string;
668
+ updateTime?: string;
669
+ name?: string;
670
+ }
671
+ interface UserDefaultSaveRequest {
672
+ /** 默认配置编号(修改时必填)。 */
673
+ id?: number;
674
+ channel?: Channel | string;
675
+ option?: string;
676
+ pre?: string;
677
+ /** 消息令牌 id;用户令牌为 0。 */
678
+ tokenId?: number;
679
+ }
680
+ interface PreItem {
681
+ id?: number;
682
+ preName?: string;
683
+ preCode?: string;
684
+ /** 1-JavaScript。 */
685
+ contentType?: number;
686
+ createTime?: string;
687
+ }
688
+ interface PreDetail {
689
+ id?: number;
690
+ preName?: string;
691
+ preCode?: string;
692
+ contentType?: number;
693
+ content?: string;
694
+ }
695
+ interface PreSaveRequest {
696
+ /** 修改时必填。 */
697
+ id?: number;
698
+ content?: string;
699
+ preName?: string;
700
+ preCode?: string;
701
+ /** 1-JavaScript。 */
702
+ contentType?: number;
703
+ }
704
+ interface PreTestRequest {
705
+ content?: string;
706
+ contentType?: number;
707
+ message?: string;
708
+ }
709
+
710
+ /**
711
+ * API 基类,提供请求执行与统一错误处理。
712
+ */
713
+ declare abstract class AbstractApi {
714
+ protected readonly config: ResolvedPushPlusConfig;
715
+ protected readonly http: HttpRequester;
716
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester);
717
+ /** 拼接绝对 URL。 */
718
+ protected resolveUrl(path: string): string;
719
+ /** 把对象拼成 query string。 */
720
+ protected buildQuery(params: Record<string, unknown> | undefined | null): string;
721
+ /** 在 path 上追加 query string。 */
722
+ protected appendQuery(path: string, params: Record<string, unknown> | undefined | null): string;
723
+ /**
724
+ * 执行请求并返回原始 ApiResponse(不进行 code 校验)。
725
+ */
726
+ protected execute<T>(method: string, path: string, headers: Record<string, string> | undefined | null, body: unknown): Promise<ApiResponse<T>>;
727
+ /** 执行请求并直接返回 data;非 200 抛出异常。 */
728
+ protected executeForData<T>(method: string, path: string, headers: Record<string, string> | undefined | null, body: unknown): Promise<T>;
729
+ }
730
+
731
+ /**
732
+ * AccessKey 接口。对应文档「一. 获取 AccessKey」。
733
+ */
734
+ declare class AccessKeyApi extends AbstractApi {
735
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester);
736
+ /** 使用配置中的 token + secretKey 获取 AccessKey。 */
737
+ getAccessKey(): Promise<AccessKeyResult>;
738
+ /** 使用指定 token + secretKey 获取 AccessKey。 */
739
+ getAccessKey(token: string, secretKey: string): Promise<AccessKeyResult>;
740
+ }
741
+
742
+ /**
743
+ * AccessKey 管理器。
744
+ *
745
+ * 提供线程/异步并发安全的 AccessKey 缓存 + 过期前自动刷新能力。
746
+ *
747
+ * 在调用任意需要 access-key 的开放接口前,OpenAbstractApi 会自动通过本类拿到一个有效的 AccessKey。
748
+ *
749
+ * 刷新策略:在 expiresIn 到期前 `accessKeyRefreshAheadSeconds` 秒视为过期。
750
+ * 文档说明老 key 在新 key 生成后 5 分钟内仍可用,因此默认 300 秒提前量足够安全。
751
+ */
752
+ declare class AccessKeyManager {
753
+ private readonly config;
754
+ private readonly api;
755
+ private cachedKey;
756
+ /** 最早过期时间戳(毫秒,含提前量);到达此刻必须刷新。 */
757
+ private expireAtMs;
758
+ /** 并发刷新去重。 */
759
+ private inflight;
760
+ constructor(config: ResolvedPushPlusConfig, api: AccessKeyApi);
761
+ /** 获取有效的 AccessKey。如已缓存且未过期则直接返回;否则触发刷新。 */
762
+ getAccessKey(): Promise<string>;
763
+ /** 强制刷新。多次并发调用时仅会真正发起一次刷新请求。 */
764
+ refresh(): Promise<string>;
765
+ /** 失效缓存。下次调用 getAccessKey() 时会重新拉取。 */
766
+ invalidate(): void;
767
+ private doRefresh;
768
+ private isValid;
769
+ }
770
+
771
+ /**
772
+ * 开放接口基类。会自动在 header 中带上 access-key,
773
+ * 并在收到 401 类业务错误时尝试重试一次(刷新 AccessKey 后重试)。
774
+ */
775
+ declare abstract class OpenAbstractApi extends AbstractApi {
776
+ static readonly HEADER_ACCESS_KEY = "access-key";
777
+ /** PushPlus AccessKey 失效相关的业务码(用于触发自动重试)。 */
778
+ private static readonly CODE_ACCESS_KEY_INVALID;
779
+ protected readonly accessKeyManager: AccessKeyManager;
780
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, accessKeyManager: AccessKeyManager);
781
+ private headersWithAccessKey;
782
+ /**
783
+ * 执行带 access-key 的请求;当返回 code=401 时自动刷新 key 并重试一次。
784
+ */
785
+ protected executeOpen<T>(method: string, path: string, body?: unknown): Promise<T>;
786
+ }
787
+
788
+ /**
789
+ * 开放接口 - 微信公众号/企业微信/邮箱渠道列表(文档「七. 渠道配置接口」 5-8)。
790
+ */
791
+ declare class ChannelApi extends OpenAbstractApi {
792
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
793
+ /** 5. 微信公众号渠道列表。 */
794
+ mpList(q?: PageQuery): Promise<PageResult<MpItem>>;
795
+ /** 6. 企业微信应用渠道列表。 */
796
+ cpList(q?: PageQuery): Promise<PageResult<CpItem>>;
797
+ /** 7. 邮箱渠道列表。 */
798
+ mailList(q?: PageQuery): Promise<PageResult<MailItem>>;
799
+ /** 8. 邮箱渠道详情。 */
800
+ mailDetail(mailId: number): Promise<MailDetail>;
801
+ }
802
+
803
+ /**
804
+ * 开放接口 - 微信 ClawBot(文档「八. 微信ClawBot接口」)。
805
+ */
806
+ declare class ClawBotApi extends OpenAbstractApi {
807
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
808
+ /** 1. 获取二维码。 */
809
+ getBotQrcode(): Promise<ClawBotQrCode>;
810
+ /** 2. 扫码结果查询。 */
811
+ getQrcodeStatus(qrcode: string): Promise<void>;
812
+ /** 3. 绑定详情。 */
813
+ botInfo(): Promise<ClawBotInfo>;
814
+ /** 4. 解绑。 */
815
+ unbind(): Promise<void>;
816
+ /** 5. 获取发送消息。 */
817
+ getMsg(): Promise<ClawBotMessage[]>;
818
+ }
819
+
820
+ /**
821
+ * 开放接口 - 好友功能(文档「十. 好友功能接口」)。
822
+ */
823
+ declare class FriendApi extends OpenAbstractApi {
824
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
825
+ /** 1. 获取个人二维码。 */
826
+ getQrCode(options: {
827
+ appId?: string;
828
+ content?: string;
829
+ second?: number;
830
+ scanCount?: number;
831
+ }): Promise<FriendQrCode>;
832
+ /** 2. 获取好友列表。 */
833
+ list(query?: PageQuery): Promise<PageResult<FriendItem>>;
834
+ /** 3. 删除好友。 */
835
+ delete(friendId: number): Promise<void>;
836
+ /** 4. 修改好友备注。 */
837
+ editRemark(id: number, remark: string): Promise<void>;
838
+ }
839
+
840
+ /**
841
+ * 本地限流守卫:当 PushPlus 服务端返回 ErrorCode.RATE_LIMITED(code=900)时,
842
+ * 在内存里按 token 维度记录"解禁时间",期间任何发送类调用都会直接抛 PushPlusError,
843
+ * 不再发起 HTTP,避免继续打到上游浪费请求并加重账号限制。
844
+ *
845
+ * 对应官方文档建议:https://www.pushplus.plus/doc/guide/code.html
846
+ *
847
+ * 默认禁推到「次日 0 点」自动解禁;也可以通过 rateLimitCooldownMs 配置一个固定时长。
848
+ *
849
+ * 仅本地视角:服务端实际禁推时长可能与本地估算不同(文档示例为 2 天)。
850
+ */
851
+ declare class RateLimitGuard {
852
+ private readonly enabled;
853
+ private readonly cooldownMs;
854
+ private readonly blockedUntil;
855
+ constructor(config: ResolvedPushPlusConfig);
856
+ /**
857
+ * 在发起发送类请求前调用:若当前 token 处于限流期,直接抛 PushPlusError
858
+ * (code = ErrorCode.RATE_LIMITED),不会发起 HTTP。
859
+ */
860
+ check(token: string | undefined | null): void;
861
+ /**
862
+ * 在收到服务端 code=900 后调用:登记限流状态,直到 cooldownUntil 到期。
863
+ */
864
+ markBlocked(token: string | undefined | null): void;
865
+ /** 仅供测试或运维手动清除(例如已确认服务端解禁)。 */
866
+ clear(token: string | undefined | null): void;
867
+ /** 返回该 token 的解禁时间(毫秒时间戳);未被限流则为 null。 */
868
+ blockedUntilAt(token: string | undefined | null): number | null;
869
+ /**
870
+ * 计算解禁时间:
871
+ * - cooldownMs > 0 时使用 now + cooldownMs;
872
+ * - 否则使用「系统默认时区的次日 0 点」。
873
+ */
874
+ private cooldownUntil;
875
+ private normalize;
876
+ }
877
+
878
+ /**
879
+ * 发送消息接口。
880
+ *
881
+ * 对应 PushPlus 文档「二. 发送消息接口」与「三. 多渠道发送消息接口」。
882
+ *
883
+ * 内置本地限流守卫:当上游返回 ErrorCode.RATE_LIMITED(code=900)时,
884
+ * 后续对同一 token 的发送调用会在 SDK 内被直接短路抛 PushPlusError,
885
+ * 不再发起 HTTP,直到守卫到期自动解除。
886
+ */
887
+ declare class MessageApi extends AbstractApi {
888
+ private readonly rateLimitGuard;
889
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, rateLimitGuard: RateLimitGuard);
890
+ /** 暴露限流守卫,便于运维场景手动 clear 或观察解禁时间。 */
891
+ getRateLimitGuard(): RateLimitGuard;
892
+ /**
893
+ * 发送单条消息。
894
+ *
895
+ * @returns 消息流水号
896
+ */
897
+ send(request: SendRequest): Promise<string>;
898
+ /**
899
+ * 多渠道发送消息。
900
+ */
901
+ batchSend(request: BatchSendRequest): Promise<BatchSendResult[]>;
902
+ /** 便捷方法:以默认渠道、默认模板发送一条简单消息。 */
903
+ sendSimple(title: string | undefined, content: string): Promise<string>;
904
+ private executeWithGuard;
905
+ private withDefaultToken;
906
+ private withDefaultBatchToken;
907
+ private requireToken;
908
+ }
909
+
910
+ /**
911
+ * 开放接口 - 消息 token(文档「四. 消息token接口」)。
912
+ */
913
+ declare class MessageTokenApi extends OpenAbstractApi {
914
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
915
+ /** 获取消息 token 列表。 */
916
+ list(query?: PageQuery): Promise<PageResult<MessageTokenItem>>;
917
+ /** 新增消息 token,返回新建的 token 字符串。 */
918
+ add(req: MessageTokenAddRequest): Promise<string>;
919
+ /** 修改消息 token。 */
920
+ edit(req: MessageTokenEditRequest): Promise<string>;
921
+ /** 删除消息 token。 */
922
+ delete(id: number): Promise<string>;
923
+ /**
924
+ * 消息 token 下拉选择列表。
925
+ *
926
+ * @param type 0-返回所有;1-返回未配置默认推送渠道的消息 token
927
+ */
928
+ selectList(type?: number): Promise<MessageTokenOption[]>;
929
+ }
930
+
931
+ /**
932
+ * 开放接口 - 消息接口(文档「二. 消息接口」)。
933
+ */
934
+ declare class OpenMessageApi extends OpenAbstractApi {
935
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
936
+ /** 1. 消息列表。 */
937
+ list(query?: PageQuery): Promise<PageResult<MessageItem>>;
938
+ /** 2. 查询消息发送结果。 */
939
+ queryResult(shortCode: string): Promise<SendMessageResult>;
940
+ /** 3. 删除消息。 */
941
+ delete(shortCode: string): Promise<string>;
942
+ /**
943
+ * 4. 消息详情(HTML 页面 URL)。
944
+ *
945
+ * 该接口直接返回 HTML 内容,SDK 仅返回访问 URL,调用方自行决定是否拉取页面内容。
946
+ */
947
+ detailUrl(shortCode: string): string;
948
+ }
949
+
950
+ /**
951
+ * 开放接口 - 预处理信息(文档「十一. 预处理信息接口」)。注:需开通会员。
952
+ */
953
+ declare class PreApi extends OpenAbstractApi {
954
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
955
+ list(q?: PageQuery): Promise<PageResult<PreItem>>;
956
+ detail(preId: number): Promise<PreDetail>;
957
+ add(req: PreSaveRequest): Promise<number>;
958
+ edit(req: PreSaveRequest): Promise<string>;
959
+ delete(preId: number): Promise<string>;
960
+ /** 测试预处理代码,返回处理后的消息。 */
961
+ test(req: PreTestRequest): Promise<string>;
962
+ }
963
+
964
+ /**
965
+ * 开放接口 - 功能设置(文档「九. 功能设置接口」)。
966
+ */
967
+ declare class SettingApi extends OpenAbstractApi {
968
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
969
+ /** 1. 获取默认配置列表。 */
970
+ listUserDefault(q?: PageQuery): Promise<PageResult<UserDefaultItem>>;
971
+ /** 2. 默认配置详情。 */
972
+ detailUserDefault(id: number): Promise<UserDefaultDetail>;
973
+ /** 3. 新增默认配置。 */
974
+ addUserDefault(req: UserDefaultSaveRequest): Promise<void>;
975
+ /** 4. 修改默认配置。 */
976
+ editUserDefault(req: UserDefaultSaveRequest): Promise<void>;
977
+ /** 5. 删除默认配置。 */
978
+ deleteUserDefault(id: number): Promise<void>;
979
+ /**
980
+ * 6. 修改接收消息限制。
981
+ *
982
+ * @param recevieLimit 0-接收全部,1-不接收消息
983
+ */
984
+ changeReceiveLimit(recevieLimit: number): Promise<void>;
985
+ /**
986
+ * 7. 开启/关闭发送消息功能。
987
+ *
988
+ * @param isSend 0-禁用,1-启用
989
+ */
990
+ changeIsSend(isSend: number): Promise<void>;
991
+ /**
992
+ * 8. 修改打开消息方式。
993
+ *
994
+ * @param openMessageType 0:H5,1:小程序
995
+ */
996
+ changeOpenMessageType(openMessageType: number): Promise<void>;
997
+ /**
998
+ * 9. 修改插件渠道转发。
999
+ *
1000
+ * @param forward 0:否,1:是
1001
+ */
1002
+ changeExtensionForward(forward: number): Promise<void>;
1003
+ }
1004
+
1005
+ /**
1006
+ * 开放接口 - 群组接口(文档「五. 群组接口」)。
1007
+ */
1008
+ declare class TopicApi extends OpenAbstractApi {
1009
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
1010
+ /** 1. 群组列表。 */
1011
+ list(query?: TopicListQuery): Promise<PageResult<TopicItem>>;
1012
+ /** 2. 获取我创建的群组详情。 */
1013
+ detail(topicId: number): Promise<TopicDetail>;
1014
+ /** 3. 获取我加入的群详情。 */
1015
+ joinDetail(topicId: number): Promise<TopicDetail>;
1016
+ /** 4. 新增群组,返回新建群组编号。 */
1017
+ add(req: TopicAddRequest): Promise<number>;
1018
+ /** 5. 修改群组。 */
1019
+ edit(req: TopicEditRequest): Promise<string>;
1020
+ /** 6. 获取群组二维码。 */
1021
+ qrCode(topicId: number, second?: number, scanCount?: number): Promise<TopicQrCode>;
1022
+ /** 7. 退出群组。 */
1023
+ exit(topicId: number): Promise<string>;
1024
+ /** 8. 删除群组。 */
1025
+ delete(topicId: number): Promise<string>;
1026
+ /**
1027
+ * 9. 上下架积分群组。
1028
+ *
1029
+ * @param isOpen 1-上架,0-下架
1030
+ */
1031
+ setOpen(topicId: number, isOpen: number): Promise<string>;
1032
+ }
1033
+
1034
+ /**
1035
+ * 开放接口 - 群组用户(文档「六. 群组用户接口」)。
1036
+ */
1037
+ declare class TopicUserApi extends OpenAbstractApi {
1038
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
1039
+ /** 1. 获取群组内用户。 */
1040
+ subscriberList(query: TopicUserListQuery): Promise<PageResult<TopicUserItem>>;
1041
+ /** 2. 删除群组内用户。 */
1042
+ deleteUser(topicRelationId: number): Promise<string>;
1043
+ /** 3. 修改订阅人备注。 */
1044
+ editRemark(id: number, remark: string): Promise<void>;
1045
+ }
1046
+
1047
+ /**
1048
+ * 开放接口 - 用户接口(文档「三. 用户接口」)。
1049
+ */
1050
+ declare class UserApi extends OpenAbstractApi {
1051
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
1052
+ /** 获取用户 token。 */
1053
+ getToken(): Promise<string>;
1054
+ /** 个人资料详情。 */
1055
+ myInfo(): Promise<UserInfo>;
1056
+ /** 获取解封剩余时间。 */
1057
+ getLimitTime(): Promise<UserLimitTime>;
1058
+ /** 查询当日消息接口请求次数。 */
1059
+ getSendCount(): Promise<SendCount>;
1060
+ }
1061
+
1062
+ /**
1063
+ * 开放接口 - webhook 渠道配置(文档「七. 渠道配置接口」 1-4)。
1064
+ */
1065
+ declare class WebhookApi extends OpenAbstractApi {
1066
+ constructor(config: ResolvedPushPlusConfig, http: HttpRequester, mgr: AccessKeyManager);
1067
+ list(q?: PageQuery): Promise<PageResult<WebhookItem>>;
1068
+ detail(webhookId: number): Promise<WebhookItem>;
1069
+ /** 新增 webhook,返回新 id。 */
1070
+ add(req: WebhookSaveRequest): Promise<number>;
1071
+ edit(req: WebhookSaveRequest): Promise<string>;
1072
+ }
1073
+
1074
+ interface PushPlusClientOptions extends PushPlusConfig {
1075
+ /** 自定义 HTTP 客户端实现。 */
1076
+ httpRequester?: HttpRequester;
1077
+ }
1078
+ /**
1079
+ * PushPlus SDK 统一入口。
1080
+ *
1081
+ * 兼容 Node.js(>=18 内置 fetch)与浏览器环境。
1082
+ *
1083
+ * @example 快速开始
1084
+ * ```ts
1085
+ * import { PushPlusClient } from '@perk-net/perk-pushplus-sdk';
1086
+ *
1087
+ * const client = new PushPlusClient({
1088
+ * token: 'your_user_token',
1089
+ * secretKey: 'your_secret_key', // 调用开放接口才需要
1090
+ * });
1091
+ *
1092
+ * // 发送消息
1093
+ * const shortCode = await client.sendSimple('标题', 'Hello PushPlus');
1094
+ *
1095
+ * // 调用开放接口(无需手动管理 AccessKey)
1096
+ * const info = await client.user.myInfo();
1097
+ * ```
1098
+ */
1099
+ declare class PushPlusClient {
1100
+ /** 已解析的不可变配置。 */
1101
+ readonly config: ResolvedPushPlusConfig;
1102
+ readonly httpRequester: HttpRequester;
1103
+ readonly accessKeyManager: AccessKeyManager;
1104
+ readonly rateLimitGuard: RateLimitGuard;
1105
+ readonly message: MessageApi;
1106
+ readonly accessKey: AccessKeyApi;
1107
+ readonly openMessage: OpenMessageApi;
1108
+ readonly user: UserApi;
1109
+ readonly messageToken: MessageTokenApi;
1110
+ readonly topic: TopicApi;
1111
+ readonly topicUser: TopicUserApi;
1112
+ readonly friend: FriendApi;
1113
+ readonly webhook: WebhookApi;
1114
+ readonly channel: ChannelApi;
1115
+ readonly clawBot: ClawBotApi;
1116
+ readonly setting: SettingApi;
1117
+ readonly pre: PreApi;
1118
+ constructor(options?: PushPlusClientOptions);
1119
+ /** 与 Java SDK 风格一致的 Builder 入口。 */
1120
+ static builder(): PushPlusClientBuilder;
1121
+ /** 工厂方法。 */
1122
+ static of(options: PushPlusClientOptions): PushPlusClient;
1123
+ /** 发送一条简单消息(默认 wechat / html)。 */
1124
+ sendSimple(title: string | undefined, content: string): Promise<string>;
1125
+ /** 发送消息。 */
1126
+ send(req: SendRequest): Promise<string>;
1127
+ /** 多渠道发送消息。 */
1128
+ batchSend(req: BatchSendRequest): Promise<BatchSendResult[]>;
1129
+ }
1130
+ /**
1131
+ * 链式 Builder,与 Java/Python SDK 风格保持一致。
1132
+ */
1133
+ declare class PushPlusClientBuilder {
1134
+ private readonly opt;
1135
+ token(v?: string): this;
1136
+ secretKey(v?: string): this;
1137
+ baseUrl(v?: string): this;
1138
+ connectTimeoutMs(v: number): this;
1139
+ readTimeoutMs(v: number): this;
1140
+ accessKeyRefreshAheadSeconds(v: number): this;
1141
+ logRequest(v: boolean): this;
1142
+ rateLimitGuardEnabled(v: boolean): this;
1143
+ rateLimitCooldownMs(v: number): this;
1144
+ userAgent(v: string): this;
1145
+ httpRequester(req: HttpRequester): this;
1146
+ build(): PushPlusClient;
1147
+ }
1148
+
1149
+ /**
1150
+ * PushPlus SDK 统一运行时异常。
1151
+ *
1152
+ * 该异常会在以下场景抛出:
1153
+ * - HTTP 请求失败(网络异常、非 2xx 状态码)
1154
+ * - PushPlus 业务接口返回 code != 200
1155
+ * - JSON 序列化/反序列化异常
1156
+ * - SDK 参数校验失败
1157
+ * - 本地限流守卫命中(code=900 后被短路),不会真正发起 HTTP 请求
1158
+ */
1159
+ declare class PushPlusError extends Error {
1160
+ /** PushPlus 接口返回的业务 code。HTTP 错误时为对应的 HTTP 状态码;其他为 -1。 */
1161
+ readonly code: number;
1162
+ /** 同 message。便于和其它语言 SDK 风格一致。 */
1163
+ get businessMessage(): string;
1164
+ constructor(message: string, code?: number, options?: {
1165
+ cause?: unknown;
1166
+ });
1167
+ /** 把数值 code 映射为 ErrorCode 枚举(未知为 UNKNOWN)。 */
1168
+ get errorCode(): ErrorCode;
1169
+ /** 是否为 PushPlus 限流(code=900)。命中后建议当天停止继续调用发送消息接口。 */
1170
+ isRateLimited(): boolean;
1171
+ }
1172
+ /**
1173
+ * 兼容 Java SDK 命名(PushPlusException)的别名导出。
1174
+ */
1175
+ declare const PushPlusException: typeof PushPlusError;
1176
+
1177
+ /**
1178
+ * PushPlus 回调请求体解析工具。
1179
+ *
1180
+ * 用法:在你的回调接口中拿到原始 JSON body,直接传入 `parseCallback(body)` 即可。
1181
+ *
1182
+ * @example
1183
+ * ```ts
1184
+ * import { parseCallback, CallbackEvent } from '@perk-net/perk-pushplus-sdk';
1185
+ *
1186
+ * function onPushPlusCallback(rawBody: string) {
1187
+ * const payload = parseCallback(rawBody);
1188
+ * switch (payload.event) {
1189
+ * case CallbackEvent.MESSAGE_COMPLETE:
1190
+ * // payload.messageInfo
1191
+ * break;
1192
+ * case CallbackEvent.ADD_TOPIC_USER:
1193
+ * // payload.topicUserInfo
1194
+ * break;
1195
+ * case CallbackEvent.ADD_FRIEND:
1196
+ * // payload.friendInfo, payload.qrCode
1197
+ * break;
1198
+ * }
1199
+ * return 'ok';
1200
+ * }
1201
+ * ```
1202
+ */
1203
+ declare function parseCallback(json: string | object): CallbackPayload;
1204
+ declare const CallbackParser: {
1205
+ parse: typeof parseCallback;
1206
+ };
1207
+
1208
+ export { AbstractApi, AccessKeyApi, AccessKeyManager, type AccessKeyResult, type ApiResponse, type BatchSendRequest, BatchSendRequestBuilder, type BatchSendResult, CallbackEvent, CallbackParser, type CallbackPayload, Channel, ChannelApi, ClawBotApi, type ClawBotInfo, type ClawBotMessage, type ClawBotQrCode, type CpItem, DEFAULT_BASE_URL, ErrorCode, FetchHttpRequester, FriendApi, type FriendInfo, type FriendItem, type FriendQrCode, type HttpRequestOptions, type HttpRequester, type HttpResponse, type MailDetail, type MailItem, MessageApi, type MessageCompleteInfo, type MessageItem, type MessageTokenAddRequest, MessageTokenApi, type MessageTokenEditRequest, type MessageTokenItem, type MessageTokenOption, type MpItem, OpenAbstractApi, OpenMessageApi, type PageQuery, type PageResult, PreApi, type PreDetail, type PreItem, type PreSaveRequest, type PreTestRequest, PushPlusClient, PushPlusClientBuilder, type PushPlusClientOptions, type PushPlusConfig, PushPlusError, PushPlusException, RateLimitGuard, type ResolvedPushPlusConfig, type SendCount, type SendMessageResult, type SendRequest, SendRequestBuilder, SendStatus, SendStatusDescription, SettingApi, Template, type TopicAddRequest, TopicApi, type TopicDetail, type TopicEditRequest, type TopicItem, type TopicListQuery, type TopicQrCode, TopicUserApi, type TopicUserInfo, type TopicUserItem, type TopicUserListQuery, UserApi, type UserDefaultDetail, type UserDefaultItem, type UserDefaultSaveRequest, type UserInfo, type UserLimitTime, WebhookApi, type WebhookItem, type WebhookSaveRequest, WebhookType, WebhookTypeDescription, batchSendRequest, errorCodeFromValue, isRateLimitedCode, isSuccessfulHttpStatus, parseCallback, resolveConfig, sendRequest };