@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.
- package/LICENSE +17 -0
- package/README.md +334 -0
- package/dist/index.cjs +1283 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1208 -0
- package/dist/index.d.ts +1208 -0
- package/dist/index.global.js +1288 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +1241 -0
- package/dist/index.js.map +1 -0
- package/package.json +68 -0
- package/src/access-key-manager.ts +69 -0
- package/src/api/access-key-api.ts +35 -0
- package/src/api/base.ts +143 -0
- package/src/api/channel-api.ts +37 -0
- package/src/api/clawbot-api.ts +42 -0
- package/src/api/friend-api.ts +47 -0
- package/src/api/message-api.ts +109 -0
- package/src/api/message-token-api.ts +52 -0
- package/src/api/open-base.ts +54 -0
- package/src/api/open-message-api.ts +50 -0
- package/src/api/pre-api.ts +42 -0
- package/src/api/setting-api.ts +99 -0
- package/src/api/topic-api.ts +80 -0
- package/src/api/topic-user-api.ts +30 -0
- package/src/api/user-api.ts +34 -0
- package/src/api/webhook-api.ts +34 -0
- package/src/callback.ts +46 -0
- package/src/client.ts +143 -0
- package/src/config.ts +92 -0
- package/src/enums.ts +170 -0
- package/src/exception.ts +48 -0
- package/src/http.ts +117 -0
- package/src/index.ts +116 -0
- package/src/models.ts +580 -0
- package/src/rate-limit.ts +92 -0
|
@@ -0,0 +1,1288 @@
|
|
|
1
|
+
var PerkPushPlus = (function (exports) {
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
// src/enums.ts
|
|
5
|
+
var Channel = /* @__PURE__ */ ((Channel2) => {
|
|
6
|
+
Channel2["WECHAT"] = "wechat";
|
|
7
|
+
Channel2["WEBHOOK"] = "webhook";
|
|
8
|
+
Channel2["CP"] = "cp";
|
|
9
|
+
Channel2["MAIL"] = "mail";
|
|
10
|
+
Channel2["SMS"] = "sms";
|
|
11
|
+
Channel2["VOICE"] = "voice";
|
|
12
|
+
Channel2["EXTENSION"] = "extension";
|
|
13
|
+
Channel2["APP"] = "app";
|
|
14
|
+
Channel2["CLAWBOT"] = "clawbot";
|
|
15
|
+
return Channel2;
|
|
16
|
+
})(Channel || {});
|
|
17
|
+
var Template = /* @__PURE__ */ ((Template2) => {
|
|
18
|
+
Template2["HTML"] = "html";
|
|
19
|
+
Template2["TXT"] = "txt";
|
|
20
|
+
Template2["JSON"] = "json";
|
|
21
|
+
Template2["MARKDOWN"] = "markdown";
|
|
22
|
+
Template2["CLOUD_MONITOR"] = "cloudMonitor";
|
|
23
|
+
Template2["JENKINS"] = "jenkins";
|
|
24
|
+
Template2["ROUTE"] = "route";
|
|
25
|
+
Template2["PAY"] = "pay";
|
|
26
|
+
return Template2;
|
|
27
|
+
})(Template || {});
|
|
28
|
+
var SendStatus = /* @__PURE__ */ ((SendStatus2) => {
|
|
29
|
+
SendStatus2[SendStatus2["NOT_SENT"] = 0] = "NOT_SENT";
|
|
30
|
+
SendStatus2[SendStatus2["SENDING"] = 1] = "SENDING";
|
|
31
|
+
SendStatus2[SendStatus2["SUCCESS"] = 2] = "SUCCESS";
|
|
32
|
+
SendStatus2[SendStatus2["FAILED"] = 3] = "FAILED";
|
|
33
|
+
return SendStatus2;
|
|
34
|
+
})(SendStatus || {});
|
|
35
|
+
var SendStatusDescription = {
|
|
36
|
+
[0 /* NOT_SENT */]: "\u672A\u53D1\u9001",
|
|
37
|
+
[1 /* SENDING */]: "\u53D1\u9001\u4E2D",
|
|
38
|
+
[2 /* SUCCESS */]: "\u53D1\u9001\u6210\u529F",
|
|
39
|
+
[3 /* FAILED */]: "\u53D1\u9001\u5931\u8D25"
|
|
40
|
+
};
|
|
41
|
+
var CallbackEvent = /* @__PURE__ */ ((CallbackEvent2) => {
|
|
42
|
+
CallbackEvent2["MESSAGE_COMPLETE"] = "message_complate";
|
|
43
|
+
CallbackEvent2["ADD_TOPIC_USER"] = "add_topic_user";
|
|
44
|
+
CallbackEvent2["ADD_FRIEND"] = "add_friend";
|
|
45
|
+
return CallbackEvent2;
|
|
46
|
+
})(CallbackEvent || {});
|
|
47
|
+
var WebhookType = /* @__PURE__ */ ((WebhookType2) => {
|
|
48
|
+
WebhookType2[WebhookType2["WORK_WECHAT_BOT"] = 1] = "WORK_WECHAT_BOT";
|
|
49
|
+
WebhookType2[WebhookType2["DING_TALK_BOT"] = 2] = "DING_TALK_BOT";
|
|
50
|
+
WebhookType2[WebhookType2["FEISHU_BOT"] = 3] = "FEISHU_BOT";
|
|
51
|
+
WebhookType2[WebhookType2["SERVER_CHAN"] = 4] = "SERVER_CHAN";
|
|
52
|
+
WebhookType2[WebhookType2["BARK"] = 50] = "BARK";
|
|
53
|
+
WebhookType2[WebhookType2["WORK_WECHAT_APP"] = 6] = "WORK_WECHAT_APP";
|
|
54
|
+
WebhookType2[WebhookType2["TENCENT_LIGHT_LINK"] = 7] = "TENCENT_LIGHT_LINK";
|
|
55
|
+
WebhookType2[WebhookType2["IFTTT"] = 8] = "IFTTT";
|
|
56
|
+
WebhookType2[WebhookType2["JI_JIAN_YUN"] = 9] = "JI_JIAN_YUN";
|
|
57
|
+
WebhookType2[WebhookType2["GOTIFY"] = 10] = "GOTIFY";
|
|
58
|
+
WebhookType2[WebhookType2["WX_PUSHER"] = 11] = "WX_PUSHER";
|
|
59
|
+
WebhookType2[WebhookType2["CUSTOM"] = 12] = "CUSTOM";
|
|
60
|
+
return WebhookType2;
|
|
61
|
+
})(WebhookType || {});
|
|
62
|
+
var WebhookTypeDescription = {
|
|
63
|
+
[1 /* WORK_WECHAT_BOT */]: "\u4F01\u4E1A\u5FAE\u4FE1\u673A\u5668\u4EBA",
|
|
64
|
+
[2 /* DING_TALK_BOT */]: "\u9489\u9489\u673A\u5668\u4EBA",
|
|
65
|
+
[3 /* FEISHU_BOT */]: "\u98DE\u4E66\u673A\u5668\u4EBA",
|
|
66
|
+
[4 /* SERVER_CHAN */]: "Server\u9171",
|
|
67
|
+
[50 /* BARK */]: "bark",
|
|
68
|
+
[6 /* WORK_WECHAT_APP */]: "\u4F01\u4E1A\u5FAE\u4FE1\u5E94\u7528",
|
|
69
|
+
[7 /* TENCENT_LIGHT_LINK */]: "\u817E\u8BAF\u8F7B\u8054",
|
|
70
|
+
[8 /* IFTTT */]: "IFTTT",
|
|
71
|
+
[9 /* JI_JIAN_YUN */]: "\u96C6\u7B80\u4E91",
|
|
72
|
+
[10 /* GOTIFY */]: "Gotify",
|
|
73
|
+
[11 /* WX_PUSHER */]: "WxPusher",
|
|
74
|
+
[12 /* CUSTOM */]: "\u81EA\u5B9A\u4E49"
|
|
75
|
+
};
|
|
76
|
+
var ErrorCode = /* @__PURE__ */ ((ErrorCode3) => {
|
|
77
|
+
ErrorCode3[ErrorCode3["OK"] = 200] = "OK";
|
|
78
|
+
ErrorCode3[ErrorCode3["NOT_LOGIN"] = 302] = "NOT_LOGIN";
|
|
79
|
+
ErrorCode3[ErrorCode3["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
|
|
80
|
+
ErrorCode3[ErrorCode3["IP_FORBIDDEN"] = 403] = "IP_FORBIDDEN";
|
|
81
|
+
ErrorCode3[ErrorCode3["SERVER_ERROR"] = 500] = "SERVER_ERROR";
|
|
82
|
+
ErrorCode3[ErrorCode3["DATA_ERROR"] = 600] = "DATA_ERROR";
|
|
83
|
+
ErrorCode3[ErrorCode3["FORBIDDEN_VIEW"] = 805] = "FORBIDDEN_VIEW";
|
|
84
|
+
ErrorCode3[ErrorCode3["INSUFFICIENT_POINTS"] = 888] = "INSUFFICIENT_POINTS";
|
|
85
|
+
ErrorCode3[ErrorCode3["RATE_LIMITED"] = 900] = "RATE_LIMITED";
|
|
86
|
+
ErrorCode3[ErrorCode3["NOT_VERIFIED"] = 905] = "NOT_VERIFIED";
|
|
87
|
+
ErrorCode3[ErrorCode3["INVALID_TOKEN"] = 903] = "INVALID_TOKEN";
|
|
88
|
+
ErrorCode3[ErrorCode3["VALIDATION_ERROR"] = 999] = "VALIDATION_ERROR";
|
|
89
|
+
ErrorCode3[ErrorCode3["UNKNOWN"] = -1] = "UNKNOWN";
|
|
90
|
+
return ErrorCode3;
|
|
91
|
+
})(ErrorCode || {});
|
|
92
|
+
function errorCodeFromValue(code) {
|
|
93
|
+
if (code == null) return -1 /* UNKNOWN */;
|
|
94
|
+
const known = [
|
|
95
|
+
200 /* OK */,
|
|
96
|
+
302 /* NOT_LOGIN */,
|
|
97
|
+
401 /* UNAUTHORIZED */,
|
|
98
|
+
403 /* IP_FORBIDDEN */,
|
|
99
|
+
500 /* SERVER_ERROR */,
|
|
100
|
+
600 /* DATA_ERROR */,
|
|
101
|
+
805 /* FORBIDDEN_VIEW */,
|
|
102
|
+
888 /* INSUFFICIENT_POINTS */,
|
|
103
|
+
900 /* RATE_LIMITED */,
|
|
104
|
+
905 /* NOT_VERIFIED */,
|
|
105
|
+
903 /* INVALID_TOKEN */,
|
|
106
|
+
999 /* VALIDATION_ERROR */
|
|
107
|
+
];
|
|
108
|
+
return known.includes(code) ? code : -1 /* UNKNOWN */;
|
|
109
|
+
}
|
|
110
|
+
function isRateLimitedCode(code) {
|
|
111
|
+
return code != null && code === 900 /* RATE_LIMITED */;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/exception.ts
|
|
115
|
+
var PushPlusError = class _PushPlusError extends Error {
|
|
116
|
+
/** 同 message。便于和其它语言 SDK 风格一致。 */
|
|
117
|
+
get businessMessage() {
|
|
118
|
+
return this.message;
|
|
119
|
+
}
|
|
120
|
+
constructor(message, code = -1, options) {
|
|
121
|
+
super(message);
|
|
122
|
+
this.name = "PushPlusError";
|
|
123
|
+
this.code = code;
|
|
124
|
+
if ((options == null ? void 0 : options.cause) !== void 0) {
|
|
125
|
+
this.cause = options.cause;
|
|
126
|
+
}
|
|
127
|
+
Object.setPrototypeOf(this, _PushPlusError.prototype);
|
|
128
|
+
}
|
|
129
|
+
/** 把数值 code 映射为 ErrorCode 枚举(未知为 UNKNOWN)。 */
|
|
130
|
+
get errorCode() {
|
|
131
|
+
return errorCodeFromValue(this.code);
|
|
132
|
+
}
|
|
133
|
+
/** 是否为 PushPlus 限流(code=900)。命中后建议当天停止继续调用发送消息接口。 */
|
|
134
|
+
isRateLimited() {
|
|
135
|
+
return isRateLimitedCode(this.code);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
var PushPlusException = PushPlusError;
|
|
139
|
+
|
|
140
|
+
// src/access-key-manager.ts
|
|
141
|
+
var AccessKeyManager = class {
|
|
142
|
+
constructor(config, api) {
|
|
143
|
+
this.cachedKey = null;
|
|
144
|
+
/** 最早过期时间戳(毫秒,含提前量);到达此刻必须刷新。 */
|
|
145
|
+
this.expireAtMs = 0;
|
|
146
|
+
/** 并发刷新去重。 */
|
|
147
|
+
this.inflight = null;
|
|
148
|
+
this.config = config;
|
|
149
|
+
this.api = api;
|
|
150
|
+
}
|
|
151
|
+
/** 获取有效的 AccessKey。如已缓存且未过期则直接返回;否则触发刷新。 */
|
|
152
|
+
async getAccessKey() {
|
|
153
|
+
if (this.isValid()) return this.cachedKey;
|
|
154
|
+
return this.refresh();
|
|
155
|
+
}
|
|
156
|
+
/** 强制刷新。多次并发调用时仅会真正发起一次刷新请求。 */
|
|
157
|
+
refresh() {
|
|
158
|
+
if (this.isValid()) return Promise.resolve(this.cachedKey);
|
|
159
|
+
if (this.inflight) return this.inflight;
|
|
160
|
+
this.inflight = this.doRefresh().finally(() => {
|
|
161
|
+
this.inflight = null;
|
|
162
|
+
});
|
|
163
|
+
return this.inflight;
|
|
164
|
+
}
|
|
165
|
+
/** 失效缓存。下次调用 getAccessKey() 时会重新拉取。 */
|
|
166
|
+
invalidate() {
|
|
167
|
+
this.cachedKey = null;
|
|
168
|
+
this.expireAtMs = 0;
|
|
169
|
+
}
|
|
170
|
+
async doRefresh() {
|
|
171
|
+
var _a;
|
|
172
|
+
const result = await this.api.getAccessKey();
|
|
173
|
+
if (!result || !result.accessKey) {
|
|
174
|
+
throw new PushPlusError("\u83B7\u53D6 AccessKey \u5931\u8D25\uFF1A\u8FD4\u56DE\u4E3A\u7A7A");
|
|
175
|
+
}
|
|
176
|
+
this.cachedKey = result.accessKey;
|
|
177
|
+
const ttlSec = (_a = result.expiresIn) != null ? _a : 7200;
|
|
178
|
+
const aheadSec = Math.max(0, this.config.accessKeyRefreshAheadSeconds);
|
|
179
|
+
const effectiveTtlSec = Math.max(1, ttlSec - aheadSec);
|
|
180
|
+
this.expireAtMs = Date.now() + effectiveTtlSec * 1e3;
|
|
181
|
+
return this.cachedKey;
|
|
182
|
+
}
|
|
183
|
+
isValid() {
|
|
184
|
+
return this.cachedKey != null && Date.now() < this.expireAtMs;
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// src/http.ts
|
|
189
|
+
var FetchHttpRequester = class {
|
|
190
|
+
constructor(config, fetchImpl) {
|
|
191
|
+
this.readTimeoutMs = config.readTimeoutMs;
|
|
192
|
+
this.logRequest = config.logRequest;
|
|
193
|
+
this.userAgent = config.userAgent;
|
|
194
|
+
const resolved = fetchImpl != null ? fetchImpl : typeof fetch !== "undefined" ? fetch.bind(globalThis) : void 0;
|
|
195
|
+
if (!resolved) {
|
|
196
|
+
throw new PushPlusError(
|
|
197
|
+
"\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u6CA1\u6709\u53EF\u7528\u7684 fetch \u5B9E\u73B0\u3002\u8BF7\u5728 Node.js 18+ \u4E2D\u8FD0\u884C\uFF0C\u6216\u81EA\u884C\u6CE8\u5165 HttpRequester \u5B9E\u4F8B\u3002"
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
this.fetchImpl = resolved;
|
|
201
|
+
}
|
|
202
|
+
async execute(options) {
|
|
203
|
+
var _a, _b;
|
|
204
|
+
const { method, url, headers, body } = options;
|
|
205
|
+
const finalHeaders = {};
|
|
206
|
+
let hasContentType = false;
|
|
207
|
+
if (headers) {
|
|
208
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
209
|
+
if (k == null || v == null) continue;
|
|
210
|
+
finalHeaders[k] = v;
|
|
211
|
+
if (k.toLowerCase() === "content-type") hasContentType = true;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
if (body != null && !hasContentType) {
|
|
215
|
+
finalHeaders["Content-Type"] = "application/json;charset=UTF-8";
|
|
216
|
+
}
|
|
217
|
+
if (typeof window === "undefined" && !finalHeaders["User-Agent"] && !finalHeaders["user-agent"]) {
|
|
218
|
+
finalHeaders["User-Agent"] = this.userAgent;
|
|
219
|
+
}
|
|
220
|
+
if (this.logRequest) {
|
|
221
|
+
console.debug("[pushplus] >>>", method, url, "body=", body);
|
|
222
|
+
}
|
|
223
|
+
const controller = new AbortController();
|
|
224
|
+
const timer = this.readTimeoutMs > 0 ? setTimeout(() => controller.abort(), this.readTimeoutMs) : null;
|
|
225
|
+
try {
|
|
226
|
+
const init = {
|
|
227
|
+
method: method.toUpperCase(),
|
|
228
|
+
headers: finalHeaders,
|
|
229
|
+
signal: controller.signal
|
|
230
|
+
};
|
|
231
|
+
if (body != null) {
|
|
232
|
+
init.body = body;
|
|
233
|
+
}
|
|
234
|
+
const resp = await this.fetchImpl(url, init);
|
|
235
|
+
const respBody = await resp.text();
|
|
236
|
+
if (this.logRequest) {
|
|
237
|
+
console.debug("[pushplus] <<< status=", resp.status, "body=", respBody);
|
|
238
|
+
}
|
|
239
|
+
return { statusCode: resp.status, body: respBody };
|
|
240
|
+
} catch (e) {
|
|
241
|
+
const err = e;
|
|
242
|
+
if (err && err.name === "AbortError") {
|
|
243
|
+
throw new PushPlusError(`\u8C03\u7528 PushPlus \u63A5\u53E3\u8D85\u65F6(${this.readTimeoutMs}ms): ${(_a = err.message) != null ? _a : ""}`, -1, {
|
|
244
|
+
cause: e
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
throw new PushPlusError(`\u8C03\u7528 PushPlus \u63A5\u53E3\u5931\u8D25: ${(_b = err == null ? void 0 : err.message) != null ? _b : String(e)}`, -1, { cause: e });
|
|
248
|
+
} finally {
|
|
249
|
+
if (timer) clearTimeout(timer);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
function isSuccessfulHttpStatus(status) {
|
|
254
|
+
return status >= 200 && status < 300;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/api/base.ts
|
|
258
|
+
var AbstractApi = class {
|
|
259
|
+
constructor(config, http) {
|
|
260
|
+
this.config = config;
|
|
261
|
+
this.http = http;
|
|
262
|
+
}
|
|
263
|
+
/** 拼接绝对 URL。 */
|
|
264
|
+
resolveUrl(path) {
|
|
265
|
+
if (path.startsWith("http://") || path.startsWith("https://")) {
|
|
266
|
+
return path;
|
|
267
|
+
}
|
|
268
|
+
return this.config.baseUrl + (path.startsWith("/") ? path : "/" + path);
|
|
269
|
+
}
|
|
270
|
+
/** 把对象拼成 query string。 */
|
|
271
|
+
buildQuery(params) {
|
|
272
|
+
if (!params) return "";
|
|
273
|
+
const parts = [];
|
|
274
|
+
for (const [k, v] of Object.entries(params)) {
|
|
275
|
+
if (v == null) continue;
|
|
276
|
+
parts.push(`${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`);
|
|
277
|
+
}
|
|
278
|
+
return parts.join("&");
|
|
279
|
+
}
|
|
280
|
+
/** 在 path 上追加 query string。 */
|
|
281
|
+
appendQuery(path, params) {
|
|
282
|
+
const q = this.buildQuery(params);
|
|
283
|
+
if (!q) return path;
|
|
284
|
+
return path + (path.includes("?") ? "&" : "?") + q;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* 执行请求并返回原始 ApiResponse(不进行 code 校验)。
|
|
288
|
+
*/
|
|
289
|
+
async execute(method, path, headers, body) {
|
|
290
|
+
const url = this.resolveUrl(path);
|
|
291
|
+
const json = body == null ? null : safeStringify(body);
|
|
292
|
+
const resp = await this.http.execute({ method, url, headers: headers != null ? headers : void 0, body: json });
|
|
293
|
+
if (!isSuccessfulHttpStatus(resp.statusCode)) {
|
|
294
|
+
throw new PushPlusError(
|
|
295
|
+
`PushPlus \u63A5\u53E3 HTTP \u8C03\u7528\u5931\u8D25: status=${resp.statusCode}, body=${resp.body}`,
|
|
296
|
+
resp.statusCode
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
return parseApiResponse(resp);
|
|
300
|
+
}
|
|
301
|
+
/** 执行请求并直接返回 data;非 200 抛出异常。 */
|
|
302
|
+
async executeForData(method, path, headers, body) {
|
|
303
|
+
var _a;
|
|
304
|
+
const resp = await this.execute(method, path, headers, body);
|
|
305
|
+
if (!isApiSuccess(resp)) {
|
|
306
|
+
throw new PushPlusError(
|
|
307
|
+
buildBusinessErrorMessage("PushPlus \u63A5\u53E3\u4E1A\u52A1\u5931\u8D25", resp),
|
|
308
|
+
(_a = resp.code) != null ? _a : -1
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
return resp.data;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
function isApiSuccess(resp) {
|
|
315
|
+
return resp.code === 200;
|
|
316
|
+
}
|
|
317
|
+
function safeStringify(value) {
|
|
318
|
+
try {
|
|
319
|
+
return JSON.stringify(value);
|
|
320
|
+
} catch (e) {
|
|
321
|
+
throw new PushPlusError(`\u5E8F\u5217\u5316\u8BF7\u6C42\u4F53\u5931\u8D25: ${e.message}`, -1, { cause: e });
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function parseApiResponse(resp) {
|
|
325
|
+
if (!resp.body || resp.body.length === 0) {
|
|
326
|
+
throw new PushPlusError("PushPlus \u63A5\u53E3\u8FD4\u56DE\u4E3A\u7A7A");
|
|
327
|
+
}
|
|
328
|
+
let raw;
|
|
329
|
+
try {
|
|
330
|
+
raw = JSON.parse(resp.body);
|
|
331
|
+
} catch (e) {
|
|
332
|
+
throw new PushPlusError(
|
|
333
|
+
`\u89E3\u6790 PushPlus \u54CD\u5E94\u5931\u8D25: ${e.message}, payload=${resp.body}`,
|
|
334
|
+
-1,
|
|
335
|
+
{ cause: e }
|
|
336
|
+
);
|
|
337
|
+
}
|
|
338
|
+
if (raw == null || typeof raw !== "object") {
|
|
339
|
+
throw new PushPlusError(`PushPlus \u63A5\u53E3\u8FD4\u56DE\u7ED3\u6784\u5F02\u5E38: ${resp.body}`);
|
|
340
|
+
}
|
|
341
|
+
const result = {
|
|
342
|
+
code: raw.code,
|
|
343
|
+
msg: raw.msg,
|
|
344
|
+
data: raw.data
|
|
345
|
+
};
|
|
346
|
+
if (!isApiSuccess(result)) {
|
|
347
|
+
const dataText = extractDataText(raw.data);
|
|
348
|
+
if (dataText && (!result.msg || result.msg.length === 0)) {
|
|
349
|
+
result.msg = dataText;
|
|
350
|
+
} else if (dataText && result.msg && !result.msg.includes(dataText)) {
|
|
351
|
+
result.msg = result.msg + ": " + dataText;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
return result;
|
|
355
|
+
}
|
|
356
|
+
function extractDataText(data) {
|
|
357
|
+
if (data == null) return null;
|
|
358
|
+
const t = typeof data;
|
|
359
|
+
if (t === "string") return data;
|
|
360
|
+
if (t === "number" || t === "boolean") return String(data);
|
|
361
|
+
try {
|
|
362
|
+
return JSON.stringify(data);
|
|
363
|
+
} catch (e) {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function buildBusinessErrorMessage(prefix, resp) {
|
|
368
|
+
return `${prefix}: code=${resp.code}, msg=${resp.msg}`;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// src/api/access-key-api.ts
|
|
372
|
+
var AccessKeyApi = class extends AbstractApi {
|
|
373
|
+
constructor(config, http) {
|
|
374
|
+
super(config, http);
|
|
375
|
+
}
|
|
376
|
+
async getAccessKey(token, secretKey) {
|
|
377
|
+
const t = token != null ? token : this.config.token;
|
|
378
|
+
const sk = secretKey != null ? secretKey : this.config.secretKey;
|
|
379
|
+
if (!t || t.trim().length === 0) {
|
|
380
|
+
throw new PushPlusError("\u83B7\u53D6 AccessKey \u9700\u8981 token");
|
|
381
|
+
}
|
|
382
|
+
if (!sk || sk.trim().length === 0) {
|
|
383
|
+
throw new PushPlusError("\u83B7\u53D6 AccessKey \u9700\u8981 secretKey");
|
|
384
|
+
}
|
|
385
|
+
return this.executeForData(
|
|
386
|
+
"POST",
|
|
387
|
+
"/api/common/openApi/getAccessKey",
|
|
388
|
+
null,
|
|
389
|
+
{ token: t, secretKey: sk }
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/api/open-base.ts
|
|
395
|
+
var _OpenAbstractApi = class _OpenAbstractApi extends AbstractApi {
|
|
396
|
+
constructor(config, http, accessKeyManager) {
|
|
397
|
+
super(config, http);
|
|
398
|
+
this.accessKeyManager = accessKeyManager;
|
|
399
|
+
}
|
|
400
|
+
async headersWithAccessKey() {
|
|
401
|
+
const key = await this.accessKeyManager.getAccessKey();
|
|
402
|
+
return { [_OpenAbstractApi.HEADER_ACCESS_KEY]: key };
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* 执行带 access-key 的请求;当返回 code=401 时自动刷新 key 并重试一次。
|
|
406
|
+
*/
|
|
407
|
+
async executeOpen(method, path, body) {
|
|
408
|
+
var _a, _b;
|
|
409
|
+
const headers = await this.headersWithAccessKey();
|
|
410
|
+
const resp = await this.execute(method, path, headers, body);
|
|
411
|
+
if (isApiSuccess(resp)) {
|
|
412
|
+
return resp.data;
|
|
413
|
+
}
|
|
414
|
+
if (resp.code === _OpenAbstractApi.CODE_ACCESS_KEY_INVALID) {
|
|
415
|
+
this.accessKeyManager.invalidate();
|
|
416
|
+
const retryHeaders = await this.headersWithAccessKey();
|
|
417
|
+
const retry = await this.execute(method, path, retryHeaders, body);
|
|
418
|
+
if (isApiSuccess(retry)) {
|
|
419
|
+
return retry.data;
|
|
420
|
+
}
|
|
421
|
+
throw new PushPlusError(
|
|
422
|
+
`PushPlus \u5F00\u653E\u63A5\u53E3\u4E1A\u52A1\u5931\u8D25(\u91CD\u8BD5\u540E): code=${retry.code}, msg=${retry.msg}`,
|
|
423
|
+
(_a = retry.code) != null ? _a : -1
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
throw new PushPlusError(
|
|
427
|
+
`PushPlus \u5F00\u653E\u63A5\u53E3\u4E1A\u52A1\u5931\u8D25: code=${resp.code}, msg=${resp.msg}`,
|
|
428
|
+
(_b = resp.code) != null ? _b : -1
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
_OpenAbstractApi.HEADER_ACCESS_KEY = "access-key";
|
|
433
|
+
/** PushPlus AccessKey 失效相关的业务码(用于触发自动重试)。 */
|
|
434
|
+
_OpenAbstractApi.CODE_ACCESS_KEY_INVALID = 401;
|
|
435
|
+
var OpenAbstractApi = _OpenAbstractApi;
|
|
436
|
+
|
|
437
|
+
// src/api/channel-api.ts
|
|
438
|
+
var ChannelApi = class extends OpenAbstractApi {
|
|
439
|
+
constructor(config, http, mgr) {
|
|
440
|
+
super(config, http, mgr);
|
|
441
|
+
}
|
|
442
|
+
/** 5. 微信公众号渠道列表。 */
|
|
443
|
+
mpList(q) {
|
|
444
|
+
return this.executeOpen("POST", "/api/open/mp/list", q != null ? q : {});
|
|
445
|
+
}
|
|
446
|
+
/** 6. 企业微信应用渠道列表。 */
|
|
447
|
+
cpList(q) {
|
|
448
|
+
return this.executeOpen("POST", "/api/open/cp/list", q != null ? q : {});
|
|
449
|
+
}
|
|
450
|
+
/** 7. 邮箱渠道列表。 */
|
|
451
|
+
mailList(q) {
|
|
452
|
+
return this.executeOpen("POST", "/api/open/mail/list", q != null ? q : {});
|
|
453
|
+
}
|
|
454
|
+
/** 8. 邮箱渠道详情。 */
|
|
455
|
+
mailDetail(mailId) {
|
|
456
|
+
return this.executeOpen(
|
|
457
|
+
"GET",
|
|
458
|
+
this.appendQuery("/api/open/mail/detail", { mailId })
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
// src/api/clawbot-api.ts
|
|
464
|
+
var ClawBotApi = class extends OpenAbstractApi {
|
|
465
|
+
constructor(config, http, mgr) {
|
|
466
|
+
super(config, http, mgr);
|
|
467
|
+
}
|
|
468
|
+
/** 1. 获取二维码。 */
|
|
469
|
+
getBotQrcode() {
|
|
470
|
+
return this.executeOpen("GET", "/api/open/clawBot/getBotQrcode");
|
|
471
|
+
}
|
|
472
|
+
/** 2. 扫码结果查询。 */
|
|
473
|
+
async getQrcodeStatus(qrcode) {
|
|
474
|
+
await this.executeOpen(
|
|
475
|
+
"GET",
|
|
476
|
+
this.appendQuery("/api/open/clawBot/getQrcodeStatus", { getQrcodeStatus: qrcode })
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
/** 3. 绑定详情。 */
|
|
480
|
+
botInfo() {
|
|
481
|
+
return this.executeOpen("GET", "/api/open/clawBot/botInfo");
|
|
482
|
+
}
|
|
483
|
+
/** 4. 解绑。 */
|
|
484
|
+
async unbind() {
|
|
485
|
+
await this.executeOpen("GET", "/api/open/clawBot/unbind");
|
|
486
|
+
}
|
|
487
|
+
/** 5. 获取发送消息。 */
|
|
488
|
+
getMsg() {
|
|
489
|
+
return this.executeOpen("GET", "/api/open/clawBot/getMsg");
|
|
490
|
+
}
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
// src/api/friend-api.ts
|
|
494
|
+
var FriendApi = class extends OpenAbstractApi {
|
|
495
|
+
constructor(config, http, mgr) {
|
|
496
|
+
super(config, http, mgr);
|
|
497
|
+
}
|
|
498
|
+
/** 1. 获取个人二维码。 */
|
|
499
|
+
getQrCode(options) {
|
|
500
|
+
const p = {};
|
|
501
|
+
if (options.appId != null) p.appId = options.appId;
|
|
502
|
+
if (options.content != null) p.content = options.content;
|
|
503
|
+
if (options.second != null) p.second = options.second;
|
|
504
|
+
if (options.scanCount != null) p.scanCount = options.scanCount;
|
|
505
|
+
return this.executeOpen("GET", this.appendQuery("/api/open/friend/getQrCode", p));
|
|
506
|
+
}
|
|
507
|
+
/** 2. 获取好友列表。 */
|
|
508
|
+
list(query) {
|
|
509
|
+
return this.executeOpen("POST", "/api/open/friend/list", query != null ? query : {});
|
|
510
|
+
}
|
|
511
|
+
/** 3. 删除好友。 */
|
|
512
|
+
async delete(friendId) {
|
|
513
|
+
await this.executeOpen(
|
|
514
|
+
"GET",
|
|
515
|
+
this.appendQuery("/api/open/friend/deleteFriend", { friendId })
|
|
516
|
+
);
|
|
517
|
+
}
|
|
518
|
+
/** 4. 修改好友备注。 */
|
|
519
|
+
async editRemark(id, remark) {
|
|
520
|
+
await this.executeOpen("POST", "/api/open/friend/editRemark", { id, remark });
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
|
|
524
|
+
// src/api/message-api.ts
|
|
525
|
+
var MessageApi = class extends AbstractApi {
|
|
526
|
+
constructor(config, http, rateLimitGuard) {
|
|
527
|
+
super(config, http);
|
|
528
|
+
this.rateLimitGuard = rateLimitGuard;
|
|
529
|
+
}
|
|
530
|
+
/** 暴露限流守卫,便于运维场景手动 clear 或观察解禁时间。 */
|
|
531
|
+
getRateLimitGuard() {
|
|
532
|
+
return this.rateLimitGuard;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* 发送单条消息。
|
|
536
|
+
*
|
|
537
|
+
* @returns 消息流水号
|
|
538
|
+
*/
|
|
539
|
+
async send(request) {
|
|
540
|
+
const req = this.withDefaultToken(request);
|
|
541
|
+
validateSend(req);
|
|
542
|
+
this.rateLimitGuard.check(req.token);
|
|
543
|
+
return this.executeWithGuard(
|
|
544
|
+
req.token,
|
|
545
|
+
() => this.executeForData("POST", "/send", null, req)
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* 多渠道发送消息。
|
|
550
|
+
*/
|
|
551
|
+
async batchSend(request) {
|
|
552
|
+
const req = this.withDefaultBatchToken(request);
|
|
553
|
+
validateBatch(req);
|
|
554
|
+
this.rateLimitGuard.check(req.token);
|
|
555
|
+
return this.executeWithGuard(
|
|
556
|
+
req.token,
|
|
557
|
+
() => this.executeForData("POST", "/batchSend", null, req)
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
/** 便捷方法:以默认渠道、默认模板发送一条简单消息。 */
|
|
561
|
+
sendSimple(title, content) {
|
|
562
|
+
return this.send({ title, content });
|
|
563
|
+
}
|
|
564
|
+
/* ============================== 内部辅助 ============================== */
|
|
565
|
+
async executeWithGuard(token, call) {
|
|
566
|
+
try {
|
|
567
|
+
return await call();
|
|
568
|
+
} catch (e) {
|
|
569
|
+
if (e instanceof PushPlusError && e.isRateLimited()) {
|
|
570
|
+
this.rateLimitGuard.markBlocked(token);
|
|
571
|
+
}
|
|
572
|
+
throw e;
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
withDefaultToken(req) {
|
|
576
|
+
if (req == null) throw new PushPlusError("SendRequest \u4E0D\u80FD\u4E3A\u7A7A");
|
|
577
|
+
if (!req.token || req.token.trim().length === 0) {
|
|
578
|
+
return { ...req, token: this.requireToken() };
|
|
579
|
+
}
|
|
580
|
+
return req;
|
|
581
|
+
}
|
|
582
|
+
withDefaultBatchToken(req) {
|
|
583
|
+
if (req == null) throw new PushPlusError("BatchSendRequest \u4E0D\u80FD\u4E3A\u7A7A");
|
|
584
|
+
if (!req.token || req.token.trim().length === 0) {
|
|
585
|
+
return { ...req, token: this.requireToken() };
|
|
586
|
+
}
|
|
587
|
+
return req;
|
|
588
|
+
}
|
|
589
|
+
requireToken() {
|
|
590
|
+
const t = this.config.token;
|
|
591
|
+
if (!t || t.trim().length === 0) {
|
|
592
|
+
throw new PushPlusError("\u53D1\u9001\u6D88\u606F\u9700\u8981 token\uFF0C\u4F46 PushPlusConfig.token \u4E3A\u7A7A");
|
|
593
|
+
}
|
|
594
|
+
return t;
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
function validateSend(req) {
|
|
598
|
+
if (!req.content || req.content.trim().length === 0) {
|
|
599
|
+
throw new PushPlusError("\u53D1\u9001\u6D88\u606F content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
function validateBatch(req) {
|
|
603
|
+
if (!req.content || req.content.trim().length === 0) {
|
|
604
|
+
throw new PushPlusError("\u6279\u91CF\u53D1\u9001\u6D88\u606F content \u4E0D\u80FD\u4E3A\u7A7A");
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
// src/api/message-token-api.ts
|
|
609
|
+
var MessageTokenApi = class extends OpenAbstractApi {
|
|
610
|
+
constructor(config, http, mgr) {
|
|
611
|
+
super(config, http, mgr);
|
|
612
|
+
}
|
|
613
|
+
/** 获取消息 token 列表。 */
|
|
614
|
+
list(query) {
|
|
615
|
+
return this.executeOpen("POST", "/api/open/token/list", query != null ? query : {});
|
|
616
|
+
}
|
|
617
|
+
/** 新增消息 token,返回新建的 token 字符串。 */
|
|
618
|
+
add(req) {
|
|
619
|
+
return this.executeOpen("POST", "/api/open/token/add", req);
|
|
620
|
+
}
|
|
621
|
+
/** 修改消息 token。 */
|
|
622
|
+
edit(req) {
|
|
623
|
+
return this.executeOpen("POST", "/api/open/token/edit", req);
|
|
624
|
+
}
|
|
625
|
+
/** 删除消息 token。 */
|
|
626
|
+
delete(id) {
|
|
627
|
+
const path = this.appendQuery("/api/open/token/deleteToken", { id });
|
|
628
|
+
return this.executeOpen("DELETE", path);
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* 消息 token 下拉选择列表。
|
|
632
|
+
*
|
|
633
|
+
* @param type 0-返回所有;1-返回未配置默认推送渠道的消息 token
|
|
634
|
+
*/
|
|
635
|
+
selectList(type) {
|
|
636
|
+
const path = this.appendQuery("/api/open/token/selectTokenList", { type: type != null ? type : 0 });
|
|
637
|
+
return this.executeOpen("GET", path);
|
|
638
|
+
}
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
// src/api/open-message-api.ts
|
|
642
|
+
var OpenMessageApi = class extends OpenAbstractApi {
|
|
643
|
+
constructor(config, http, mgr) {
|
|
644
|
+
super(config, http, mgr);
|
|
645
|
+
}
|
|
646
|
+
/** 1. 消息列表。 */
|
|
647
|
+
list(query) {
|
|
648
|
+
return this.executeOpen("POST", "/api/open/message/list", query != null ? query : {});
|
|
649
|
+
}
|
|
650
|
+
/** 2. 查询消息发送结果。 */
|
|
651
|
+
queryResult(shortCode) {
|
|
652
|
+
if (!shortCode || shortCode.trim().length === 0) {
|
|
653
|
+
throw new PushPlusError("shortCode \u4E0D\u80FD\u4E3A\u7A7A");
|
|
654
|
+
}
|
|
655
|
+
const path = this.appendQuery("/api/open/message/sendMessageResult", { shortCode });
|
|
656
|
+
return this.executeOpen("GET", path);
|
|
657
|
+
}
|
|
658
|
+
/** 3. 删除消息。 */
|
|
659
|
+
delete(shortCode) {
|
|
660
|
+
if (!shortCode || shortCode.trim().length === 0) {
|
|
661
|
+
throw new PushPlusError("shortCode \u4E0D\u80FD\u4E3A\u7A7A");
|
|
662
|
+
}
|
|
663
|
+
const path = this.appendQuery("/api/open/message/deleteMessage", { shortCode });
|
|
664
|
+
return this.executeOpen("DELETE", path);
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* 4. 消息详情(HTML 页面 URL)。
|
|
668
|
+
*
|
|
669
|
+
* 该接口直接返回 HTML 内容,SDK 仅返回访问 URL,调用方自行决定是否拉取页面内容。
|
|
670
|
+
*/
|
|
671
|
+
detailUrl(shortCode) {
|
|
672
|
+
if (!shortCode || shortCode.trim().length === 0) {
|
|
673
|
+
throw new PushPlusError("shortCode \u4E0D\u80FD\u4E3A\u7A7A");
|
|
674
|
+
}
|
|
675
|
+
return this.resolveUrl("/shortMessage/" + shortCode);
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
|
|
679
|
+
// src/api/pre-api.ts
|
|
680
|
+
var PreApi = class extends OpenAbstractApi {
|
|
681
|
+
constructor(config, http, mgr) {
|
|
682
|
+
super(config, http, mgr);
|
|
683
|
+
}
|
|
684
|
+
list(q) {
|
|
685
|
+
return this.executeOpen("POST", "/api/open/pre/list", q != null ? q : {});
|
|
686
|
+
}
|
|
687
|
+
detail(preId) {
|
|
688
|
+
return this.executeOpen("GET", this.appendQuery("/api/open/pre/detail", { preId }));
|
|
689
|
+
}
|
|
690
|
+
add(req) {
|
|
691
|
+
return this.executeOpen("POST", "/api/open/pre/add", req);
|
|
692
|
+
}
|
|
693
|
+
edit(req) {
|
|
694
|
+
return this.executeOpen("POST", "/api/open/pre/edit", req);
|
|
695
|
+
}
|
|
696
|
+
delete(preId) {
|
|
697
|
+
return this.executeOpen(
|
|
698
|
+
"DELETE",
|
|
699
|
+
this.appendQuery("/api/open/pre/delete", { preId })
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
/** 测试预处理代码,返回处理后的消息。 */
|
|
703
|
+
test(req) {
|
|
704
|
+
return this.executeOpen("POST", "/api/open/pre/test", req);
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// src/api/setting-api.ts
|
|
709
|
+
var SettingApi = class extends OpenAbstractApi {
|
|
710
|
+
constructor(config, http, mgr) {
|
|
711
|
+
super(config, http, mgr);
|
|
712
|
+
}
|
|
713
|
+
/** 1. 获取默认配置列表。 */
|
|
714
|
+
listUserDefault(q) {
|
|
715
|
+
return this.executeOpen("POST", "/api/open/setting/listUserDefault", q != null ? q : {});
|
|
716
|
+
}
|
|
717
|
+
/** 2. 默认配置详情。 */
|
|
718
|
+
detailUserDefault(id) {
|
|
719
|
+
return this.executeOpen(
|
|
720
|
+
"GET",
|
|
721
|
+
this.appendQuery("/api/open/setting/detailUserDefault", { id })
|
|
722
|
+
);
|
|
723
|
+
}
|
|
724
|
+
/** 3. 新增默认配置。 */
|
|
725
|
+
async addUserDefault(req) {
|
|
726
|
+
await this.executeOpen("POST", "/api/open/setting/addUserDefault", req);
|
|
727
|
+
}
|
|
728
|
+
/** 4. 修改默认配置。 */
|
|
729
|
+
async editUserDefault(req) {
|
|
730
|
+
await this.executeOpen("POST", "/api/open/setting/editUserDefault", req);
|
|
731
|
+
}
|
|
732
|
+
/** 5. 删除默认配置。 */
|
|
733
|
+
async deleteUserDefault(id) {
|
|
734
|
+
await this.executeOpen(
|
|
735
|
+
"DELETE",
|
|
736
|
+
this.appendQuery("/api/open/setting/deleteUserDefault", { id })
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
/**
|
|
740
|
+
* 6. 修改接收消息限制。
|
|
741
|
+
*
|
|
742
|
+
* @param recevieLimit 0-接收全部,1-不接收消息
|
|
743
|
+
*/
|
|
744
|
+
async changeReceiveLimit(recevieLimit) {
|
|
745
|
+
await this.executeOpen(
|
|
746
|
+
"GET",
|
|
747
|
+
this.appendQuery("/api/open/setting/changeRecevieLimit", { recevieLimit })
|
|
748
|
+
);
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* 7. 开启/关闭发送消息功能。
|
|
752
|
+
*
|
|
753
|
+
* @param isSend 0-禁用,1-启用
|
|
754
|
+
*/
|
|
755
|
+
async changeIsSend(isSend) {
|
|
756
|
+
await this.executeOpen(
|
|
757
|
+
"GET",
|
|
758
|
+
this.appendQuery("/api/open/setting/changeIsSend", { isSend })
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* 8. 修改打开消息方式。
|
|
763
|
+
*
|
|
764
|
+
* @param openMessageType 0:H5,1:小程序
|
|
765
|
+
*/
|
|
766
|
+
async changeOpenMessageType(openMessageType) {
|
|
767
|
+
await this.executeOpen(
|
|
768
|
+
"GET",
|
|
769
|
+
this.appendQuery("/api/open/setting/changeOpenMessageType", { openMessageType })
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* 9. 修改插件渠道转发。
|
|
774
|
+
*
|
|
775
|
+
* @param forward 0:否,1:是
|
|
776
|
+
*/
|
|
777
|
+
async changeExtensionForward(forward) {
|
|
778
|
+
await this.executeOpen(
|
|
779
|
+
"GET",
|
|
780
|
+
this.appendQuery("/api/open/setting/extension", { forward })
|
|
781
|
+
);
|
|
782
|
+
}
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
// src/api/topic-api.ts
|
|
786
|
+
var TopicApi = class extends OpenAbstractApi {
|
|
787
|
+
constructor(config, http, mgr) {
|
|
788
|
+
super(config, http, mgr);
|
|
789
|
+
}
|
|
790
|
+
/** 1. 群组列表。 */
|
|
791
|
+
list(query) {
|
|
792
|
+
return this.executeOpen("POST", "/api/open/topic/list", query != null ? query : {});
|
|
793
|
+
}
|
|
794
|
+
/** 2. 获取我创建的群组详情。 */
|
|
795
|
+
detail(topicId) {
|
|
796
|
+
return this.executeOpen("GET", this.appendQuery("/api/open/topic/detail", { topicId }));
|
|
797
|
+
}
|
|
798
|
+
/** 3. 获取我加入的群详情。 */
|
|
799
|
+
joinDetail(topicId) {
|
|
800
|
+
return this.executeOpen(
|
|
801
|
+
"GET",
|
|
802
|
+
this.appendQuery("/api/open/topic/joinTopicDetail", { topicId })
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
/** 4. 新增群组,返回新建群组编号。 */
|
|
806
|
+
add(req) {
|
|
807
|
+
return this.executeOpen("POST", "/api/open/topic/add", req);
|
|
808
|
+
}
|
|
809
|
+
/** 5. 修改群组。 */
|
|
810
|
+
edit(req) {
|
|
811
|
+
return this.executeOpen("POST", "/api/open/topic/editTopic", req);
|
|
812
|
+
}
|
|
813
|
+
/** 6. 获取群组二维码。 */
|
|
814
|
+
qrCode(topicId, second, scanCount) {
|
|
815
|
+
const params = { topicId };
|
|
816
|
+
if (second != null) params.second = second;
|
|
817
|
+
if (scanCount != null) params.scanCount = scanCount;
|
|
818
|
+
return this.executeOpen("GET", this.appendQuery("/api/open/topic/qrCode", params));
|
|
819
|
+
}
|
|
820
|
+
/** 7. 退出群组。 */
|
|
821
|
+
exit(topicId) {
|
|
822
|
+
return this.executeOpen(
|
|
823
|
+
"GET",
|
|
824
|
+
this.appendQuery("/api/open/topic/exitTopic", { topicId })
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
/** 8. 删除群组。 */
|
|
828
|
+
delete(topicId) {
|
|
829
|
+
return this.executeOpen("GET", this.appendQuery("/api/open/topic/delete", { topicId }));
|
|
830
|
+
}
|
|
831
|
+
/**
|
|
832
|
+
* 9. 上下架积分群组。
|
|
833
|
+
*
|
|
834
|
+
* @param isOpen 1-上架,0-下架
|
|
835
|
+
*/
|
|
836
|
+
setOpen(topicId, isOpen) {
|
|
837
|
+
return this.executeOpen("POST", "/api/open/topic/isOpen", { topic: topicId, isOpen });
|
|
838
|
+
}
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
// src/api/topic-user-api.ts
|
|
842
|
+
var TopicUserApi = class extends OpenAbstractApi {
|
|
843
|
+
constructor(config, http, mgr) {
|
|
844
|
+
super(config, http, mgr);
|
|
845
|
+
}
|
|
846
|
+
/** 1. 获取群组内用户。 */
|
|
847
|
+
subscriberList(query) {
|
|
848
|
+
return this.executeOpen("POST", "/api/open/topicUser/subscriberList", query);
|
|
849
|
+
}
|
|
850
|
+
/** 2. 删除群组内用户。 */
|
|
851
|
+
deleteUser(topicRelationId) {
|
|
852
|
+
const path = this.appendQuery("/api/open/topicUser/deleteTopicUser", { topicRelationId });
|
|
853
|
+
return this.executeOpen("POST", path);
|
|
854
|
+
}
|
|
855
|
+
/** 3. 修改订阅人备注。 */
|
|
856
|
+
async editRemark(id, remark) {
|
|
857
|
+
await this.executeOpen("POST", "/api/open/topicUser/editRemark", { id, remark });
|
|
858
|
+
}
|
|
859
|
+
};
|
|
860
|
+
|
|
861
|
+
// src/api/user-api.ts
|
|
862
|
+
var UserApi = class extends OpenAbstractApi {
|
|
863
|
+
constructor(config, http, mgr) {
|
|
864
|
+
super(config, http, mgr);
|
|
865
|
+
}
|
|
866
|
+
/** 获取用户 token。 */
|
|
867
|
+
getToken() {
|
|
868
|
+
return this.executeOpen("GET", "/api/open/user/token");
|
|
869
|
+
}
|
|
870
|
+
/** 个人资料详情。 */
|
|
871
|
+
myInfo() {
|
|
872
|
+
return this.executeOpen("GET", "/api/open/user/myInfo");
|
|
873
|
+
}
|
|
874
|
+
/** 获取解封剩余时间。 */
|
|
875
|
+
getLimitTime() {
|
|
876
|
+
return this.executeOpen("GET", "/api/open/user/userLimitTime");
|
|
877
|
+
}
|
|
878
|
+
/** 查询当日消息接口请求次数。 */
|
|
879
|
+
getSendCount() {
|
|
880
|
+
return this.executeOpen("GET", "/api/open/user/sendCount");
|
|
881
|
+
}
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
// src/api/webhook-api.ts
|
|
885
|
+
var WebhookApi = class extends OpenAbstractApi {
|
|
886
|
+
constructor(config, http, mgr) {
|
|
887
|
+
super(config, http, mgr);
|
|
888
|
+
}
|
|
889
|
+
list(q) {
|
|
890
|
+
return this.executeOpen("POST", "/api/open/webhook/list", q != null ? q : {});
|
|
891
|
+
}
|
|
892
|
+
detail(webhookId) {
|
|
893
|
+
return this.executeOpen(
|
|
894
|
+
"GET",
|
|
895
|
+
this.appendQuery("/api/open/webhook/detail", { webhookId })
|
|
896
|
+
);
|
|
897
|
+
}
|
|
898
|
+
/** 新增 webhook,返回新 id。 */
|
|
899
|
+
add(req) {
|
|
900
|
+
return this.executeOpen("POST", "/api/open/webhook/add", req);
|
|
901
|
+
}
|
|
902
|
+
edit(req) {
|
|
903
|
+
return this.executeOpen("POST", "/api/open/webhook/edit", req);
|
|
904
|
+
}
|
|
905
|
+
};
|
|
906
|
+
|
|
907
|
+
// src/config.ts
|
|
908
|
+
var DEFAULT_BASE_URL = "https://www.pushplus.plus";
|
|
909
|
+
function resolveConfig(input) {
|
|
910
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
|
|
911
|
+
const cfg = input != null ? input : {};
|
|
912
|
+
const baseUrl = ((_a = cfg.baseUrl) != null ? _a : DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
913
|
+
return {
|
|
914
|
+
token: (_b = cfg.token) != null ? _b : "",
|
|
915
|
+
secretKey: (_c = cfg.secretKey) != null ? _c : "",
|
|
916
|
+
baseUrl: baseUrl || DEFAULT_BASE_URL,
|
|
917
|
+
connectTimeoutMs: (_d = cfg.connectTimeoutMs) != null ? _d : 1e4,
|
|
918
|
+
readTimeoutMs: (_e = cfg.readTimeoutMs) != null ? _e : 3e4,
|
|
919
|
+
accessKeyRefreshAheadSeconds: (_f = cfg.accessKeyRefreshAheadSeconds) != null ? _f : 300,
|
|
920
|
+
logRequest: (_g = cfg.logRequest) != null ? _g : false,
|
|
921
|
+
rateLimitGuardEnabled: (_h = cfg.rateLimitGuardEnabled) != null ? _h : true,
|
|
922
|
+
rateLimitCooldownMs: (_i = cfg.rateLimitCooldownMs) != null ? _i : 0,
|
|
923
|
+
userAgent: (_j = cfg.userAgent) != null ? _j : `@perk-net/perk-pushplus-sdk/1.0.0`
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
// src/rate-limit.ts
|
|
928
|
+
var RateLimitGuard = class {
|
|
929
|
+
constructor(config) {
|
|
930
|
+
this.blockedUntil = /* @__PURE__ */ new Map();
|
|
931
|
+
this.enabled = config.rateLimitGuardEnabled;
|
|
932
|
+
this.cooldownMs = config.rateLimitCooldownMs;
|
|
933
|
+
}
|
|
934
|
+
/**
|
|
935
|
+
* 在发起发送类请求前调用:若当前 token 处于限流期,直接抛 PushPlusError
|
|
936
|
+
* (code = ErrorCode.RATE_LIMITED),不会发起 HTTP。
|
|
937
|
+
*/
|
|
938
|
+
check(token) {
|
|
939
|
+
if (!this.enabled) return;
|
|
940
|
+
const key = this.normalize(token);
|
|
941
|
+
if (!key) return;
|
|
942
|
+
const until = this.blockedUntil.get(key);
|
|
943
|
+
if (until == null) return;
|
|
944
|
+
const now = Date.now();
|
|
945
|
+
if (now < until) {
|
|
946
|
+
throw new PushPlusError(
|
|
947
|
+
`PushPlus \u672C\u5730\u9650\u6D41\u5B88\u536B\uFF1A\u5F53\u524D token \u5DF2\u547D\u4E2D code=900\uFF0C\u5728 ${new Date(until).toISOString()} \u4E4B\u524D\u4E0D\u518D\u53D1\u8D77\u8BF7\u6C42\uFF08\u8BF7\u53C2\u8003\u5B98\u65B9\u6587\u6863\u51CF\u5C11\u65E0\u7528\u8BF7\u6C42\uFF09`,
|
|
948
|
+
900 /* RATE_LIMITED */
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
this.blockedUntil.delete(key);
|
|
952
|
+
}
|
|
953
|
+
/**
|
|
954
|
+
* 在收到服务端 code=900 后调用:登记限流状态,直到 cooldownUntil 到期。
|
|
955
|
+
*/
|
|
956
|
+
markBlocked(token) {
|
|
957
|
+
if (!this.enabled) return;
|
|
958
|
+
const key = this.normalize(token);
|
|
959
|
+
if (!key) return;
|
|
960
|
+
const until = this.cooldownUntil(Date.now());
|
|
961
|
+
this.blockedUntil.set(key, until);
|
|
962
|
+
}
|
|
963
|
+
/** 仅供测试或运维手动清除(例如已确认服务端解禁)。 */
|
|
964
|
+
clear(token) {
|
|
965
|
+
const key = this.normalize(token);
|
|
966
|
+
if (key) this.blockedUntil.delete(key);
|
|
967
|
+
}
|
|
968
|
+
/** 返回该 token 的解禁时间(毫秒时间戳);未被限流则为 null。 */
|
|
969
|
+
blockedUntilAt(token) {
|
|
970
|
+
const key = this.normalize(token);
|
|
971
|
+
if (!key) return null;
|
|
972
|
+
const until = this.blockedUntil.get(key);
|
|
973
|
+
return until != null ? until : null;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* 计算解禁时间:
|
|
977
|
+
* - cooldownMs > 0 时使用 now + cooldownMs;
|
|
978
|
+
* - 否则使用「系统默认时区的次日 0 点」。
|
|
979
|
+
*/
|
|
980
|
+
cooldownUntil(now) {
|
|
981
|
+
if (this.cooldownMs && this.cooldownMs > 0) {
|
|
982
|
+
return now + this.cooldownMs;
|
|
983
|
+
}
|
|
984
|
+
const d = new Date(now);
|
|
985
|
+
d.setHours(0, 0, 0, 0);
|
|
986
|
+
d.setDate(d.getDate() + 1);
|
|
987
|
+
return d.getTime();
|
|
988
|
+
}
|
|
989
|
+
normalize(token) {
|
|
990
|
+
if (token == null) return null;
|
|
991
|
+
const t = String(token).trim();
|
|
992
|
+
return t.length === 0 ? null : t;
|
|
993
|
+
}
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
// src/client.ts
|
|
997
|
+
var PushPlusClient = class _PushPlusClient {
|
|
998
|
+
constructor(options = {}) {
|
|
999
|
+
var _a;
|
|
1000
|
+
this.config = resolveConfig(options);
|
|
1001
|
+
this.httpRequester = (_a = options.httpRequester) != null ? _a : new FetchHttpRequester(this.config);
|
|
1002
|
+
this.rateLimitGuard = new RateLimitGuard(this.config);
|
|
1003
|
+
this.message = new MessageApi(this.config, this.httpRequester, this.rateLimitGuard);
|
|
1004
|
+
this.accessKey = new AccessKeyApi(this.config, this.httpRequester);
|
|
1005
|
+
this.accessKeyManager = new AccessKeyManager(this.config, this.accessKey);
|
|
1006
|
+
this.openMessage = new OpenMessageApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1007
|
+
this.user = new UserApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1008
|
+
this.messageToken = new MessageTokenApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1009
|
+
this.topic = new TopicApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1010
|
+
this.topicUser = new TopicUserApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1011
|
+
this.friend = new FriendApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1012
|
+
this.webhook = new WebhookApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1013
|
+
this.channel = new ChannelApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1014
|
+
this.clawBot = new ClawBotApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1015
|
+
this.setting = new SettingApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1016
|
+
this.pre = new PreApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1017
|
+
}
|
|
1018
|
+
/** 与 Java SDK 风格一致的 Builder 入口。 */
|
|
1019
|
+
static builder() {
|
|
1020
|
+
return new PushPlusClientBuilder();
|
|
1021
|
+
}
|
|
1022
|
+
/** 工厂方法。 */
|
|
1023
|
+
static of(options) {
|
|
1024
|
+
return new _PushPlusClient(options);
|
|
1025
|
+
}
|
|
1026
|
+
/* ============================== 便捷转发方法 ============================== */
|
|
1027
|
+
/** 发送一条简单消息(默认 wechat / html)。 */
|
|
1028
|
+
sendSimple(title, content) {
|
|
1029
|
+
return this.message.sendSimple(title, content);
|
|
1030
|
+
}
|
|
1031
|
+
/** 发送消息。 */
|
|
1032
|
+
send(req) {
|
|
1033
|
+
return this.message.send(req);
|
|
1034
|
+
}
|
|
1035
|
+
/** 多渠道发送消息。 */
|
|
1036
|
+
batchSend(req) {
|
|
1037
|
+
return this.message.batchSend(req);
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
var PushPlusClientBuilder = class {
|
|
1041
|
+
constructor() {
|
|
1042
|
+
this.opt = {};
|
|
1043
|
+
}
|
|
1044
|
+
token(v) {
|
|
1045
|
+
this.opt.token = v;
|
|
1046
|
+
return this;
|
|
1047
|
+
}
|
|
1048
|
+
secretKey(v) {
|
|
1049
|
+
this.opt.secretKey = v;
|
|
1050
|
+
return this;
|
|
1051
|
+
}
|
|
1052
|
+
baseUrl(v) {
|
|
1053
|
+
this.opt.baseUrl = v;
|
|
1054
|
+
return this;
|
|
1055
|
+
}
|
|
1056
|
+
connectTimeoutMs(v) {
|
|
1057
|
+
this.opt.connectTimeoutMs = v;
|
|
1058
|
+
return this;
|
|
1059
|
+
}
|
|
1060
|
+
readTimeoutMs(v) {
|
|
1061
|
+
this.opt.readTimeoutMs = v;
|
|
1062
|
+
return this;
|
|
1063
|
+
}
|
|
1064
|
+
accessKeyRefreshAheadSeconds(v) {
|
|
1065
|
+
this.opt.accessKeyRefreshAheadSeconds = v;
|
|
1066
|
+
return this;
|
|
1067
|
+
}
|
|
1068
|
+
logRequest(v) {
|
|
1069
|
+
this.opt.logRequest = v;
|
|
1070
|
+
return this;
|
|
1071
|
+
}
|
|
1072
|
+
rateLimitGuardEnabled(v) {
|
|
1073
|
+
this.opt.rateLimitGuardEnabled = v;
|
|
1074
|
+
return this;
|
|
1075
|
+
}
|
|
1076
|
+
rateLimitCooldownMs(v) {
|
|
1077
|
+
this.opt.rateLimitCooldownMs = v;
|
|
1078
|
+
return this;
|
|
1079
|
+
}
|
|
1080
|
+
userAgent(v) {
|
|
1081
|
+
this.opt.userAgent = v;
|
|
1082
|
+
return this;
|
|
1083
|
+
}
|
|
1084
|
+
httpRequester(req) {
|
|
1085
|
+
this.opt.httpRequester = req;
|
|
1086
|
+
return this;
|
|
1087
|
+
}
|
|
1088
|
+
build() {
|
|
1089
|
+
if (this.opt.token != null && this.opt.token.trim().length === 0) {
|
|
1090
|
+
throw new PushPlusError("token \u4E0D\u80FD\u4E3A\u7A7A\u5B57\u7B26\u4E32");
|
|
1091
|
+
}
|
|
1092
|
+
return new PushPlusClient(this.opt);
|
|
1093
|
+
}
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
// src/callback.ts
|
|
1097
|
+
function parseCallback(json) {
|
|
1098
|
+
if (json == null) {
|
|
1099
|
+
throw new PushPlusError("\u56DE\u8C03\u8BF7\u6C42\u4F53\u4E0D\u80FD\u4E3A\u7A7A");
|
|
1100
|
+
}
|
|
1101
|
+
if (typeof json === "string") {
|
|
1102
|
+
try {
|
|
1103
|
+
return JSON.parse(json);
|
|
1104
|
+
} catch (e) {
|
|
1105
|
+
throw new PushPlusError(`\u89E3\u6790 PushPlus \u56DE\u8C03\u5931\u8D25: ${e.message}`, -1, { cause: e });
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
return json;
|
|
1109
|
+
}
|
|
1110
|
+
var CallbackParser = {
|
|
1111
|
+
parse: parseCallback
|
|
1112
|
+
};
|
|
1113
|
+
|
|
1114
|
+
// src/models.ts
|
|
1115
|
+
var SendRequestBuilder = class {
|
|
1116
|
+
constructor() {
|
|
1117
|
+
this.req = {};
|
|
1118
|
+
}
|
|
1119
|
+
token(v) {
|
|
1120
|
+
this.req.token = v;
|
|
1121
|
+
return this;
|
|
1122
|
+
}
|
|
1123
|
+
title(v) {
|
|
1124
|
+
this.req.title = v;
|
|
1125
|
+
return this;
|
|
1126
|
+
}
|
|
1127
|
+
content(v) {
|
|
1128
|
+
this.req.content = v;
|
|
1129
|
+
return this;
|
|
1130
|
+
}
|
|
1131
|
+
topic(v) {
|
|
1132
|
+
this.req.topic = v;
|
|
1133
|
+
return this;
|
|
1134
|
+
}
|
|
1135
|
+
template(v) {
|
|
1136
|
+
this.req.template = v;
|
|
1137
|
+
return this;
|
|
1138
|
+
}
|
|
1139
|
+
channel(v) {
|
|
1140
|
+
this.req.channel = v;
|
|
1141
|
+
return this;
|
|
1142
|
+
}
|
|
1143
|
+
option(v) {
|
|
1144
|
+
this.req.option = v;
|
|
1145
|
+
return this;
|
|
1146
|
+
}
|
|
1147
|
+
callbackUrl(v) {
|
|
1148
|
+
this.req.callbackUrl = v;
|
|
1149
|
+
return this;
|
|
1150
|
+
}
|
|
1151
|
+
timestamp(v) {
|
|
1152
|
+
this.req.timestamp = v;
|
|
1153
|
+
return this;
|
|
1154
|
+
}
|
|
1155
|
+
to(v) {
|
|
1156
|
+
this.req.to = v;
|
|
1157
|
+
return this;
|
|
1158
|
+
}
|
|
1159
|
+
pre(v) {
|
|
1160
|
+
this.req.pre = v;
|
|
1161
|
+
return this;
|
|
1162
|
+
}
|
|
1163
|
+
build() {
|
|
1164
|
+
return { ...this.req };
|
|
1165
|
+
}
|
|
1166
|
+
};
|
|
1167
|
+
function sendRequest() {
|
|
1168
|
+
return new SendRequestBuilder();
|
|
1169
|
+
}
|
|
1170
|
+
var BatchSendRequestBuilder = class {
|
|
1171
|
+
constructor() {
|
|
1172
|
+
this.req = {};
|
|
1173
|
+
this.channelList = [];
|
|
1174
|
+
this.optionList = [];
|
|
1175
|
+
}
|
|
1176
|
+
token(v) {
|
|
1177
|
+
this.req.token = v;
|
|
1178
|
+
return this;
|
|
1179
|
+
}
|
|
1180
|
+
title(v) {
|
|
1181
|
+
this.req.title = v;
|
|
1182
|
+
return this;
|
|
1183
|
+
}
|
|
1184
|
+
content(v) {
|
|
1185
|
+
this.req.content = v;
|
|
1186
|
+
return this;
|
|
1187
|
+
}
|
|
1188
|
+
topic(v) {
|
|
1189
|
+
this.req.topic = v;
|
|
1190
|
+
return this;
|
|
1191
|
+
}
|
|
1192
|
+
template(v) {
|
|
1193
|
+
this.req.template = v;
|
|
1194
|
+
return this;
|
|
1195
|
+
}
|
|
1196
|
+
callbackUrl(v) {
|
|
1197
|
+
this.req.callbackUrl = v;
|
|
1198
|
+
return this;
|
|
1199
|
+
}
|
|
1200
|
+
timestamp(v) {
|
|
1201
|
+
this.req.timestamp = v;
|
|
1202
|
+
return this;
|
|
1203
|
+
}
|
|
1204
|
+
to(v) {
|
|
1205
|
+
this.req.to = v;
|
|
1206
|
+
return this;
|
|
1207
|
+
}
|
|
1208
|
+
pre(v) {
|
|
1209
|
+
this.req.pre = v;
|
|
1210
|
+
return this;
|
|
1211
|
+
}
|
|
1212
|
+
/** 追加一个 channel。 */
|
|
1213
|
+
channel(ch) {
|
|
1214
|
+
this.channelList.push(typeof ch === "string" ? ch : ch);
|
|
1215
|
+
return this;
|
|
1216
|
+
}
|
|
1217
|
+
/** 追加一个 option,与最近一次 channel() 配对;可传空串。 */
|
|
1218
|
+
option(opt) {
|
|
1219
|
+
this.optionList.push(opt != null ? opt : "");
|
|
1220
|
+
return this;
|
|
1221
|
+
}
|
|
1222
|
+
/** 直接以 CSV 形式指定多渠道字符串(与累积式 channel(Channel) 互斥)。 */
|
|
1223
|
+
channelString(csv) {
|
|
1224
|
+
this.req.channel = csv;
|
|
1225
|
+
return this;
|
|
1226
|
+
}
|
|
1227
|
+
/** 直接以 CSV 形式指定 option 字符串。 */
|
|
1228
|
+
optionString(csv) {
|
|
1229
|
+
this.req.option = csv;
|
|
1230
|
+
return this;
|
|
1231
|
+
}
|
|
1232
|
+
build() {
|
|
1233
|
+
const finalChannel = this.channelList.length > 0 ? this.channelList.join(",") : this.req.channel;
|
|
1234
|
+
const finalOption = this.optionList.length > 0 ? this.optionList.join(",") : this.req.option;
|
|
1235
|
+
return { ...this.req, channel: finalChannel, option: finalOption };
|
|
1236
|
+
}
|
|
1237
|
+
};
|
|
1238
|
+
function batchSendRequest() {
|
|
1239
|
+
return new BatchSendRequestBuilder();
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
exports.AbstractApi = AbstractApi;
|
|
1243
|
+
exports.AccessKeyApi = AccessKeyApi;
|
|
1244
|
+
exports.AccessKeyManager = AccessKeyManager;
|
|
1245
|
+
exports.BatchSendRequestBuilder = BatchSendRequestBuilder;
|
|
1246
|
+
exports.CallbackEvent = CallbackEvent;
|
|
1247
|
+
exports.CallbackParser = CallbackParser;
|
|
1248
|
+
exports.Channel = Channel;
|
|
1249
|
+
exports.ChannelApi = ChannelApi;
|
|
1250
|
+
exports.ClawBotApi = ClawBotApi;
|
|
1251
|
+
exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
1252
|
+
exports.ErrorCode = ErrorCode;
|
|
1253
|
+
exports.FetchHttpRequester = FetchHttpRequester;
|
|
1254
|
+
exports.FriendApi = FriendApi;
|
|
1255
|
+
exports.MessageApi = MessageApi;
|
|
1256
|
+
exports.MessageTokenApi = MessageTokenApi;
|
|
1257
|
+
exports.OpenAbstractApi = OpenAbstractApi;
|
|
1258
|
+
exports.OpenMessageApi = OpenMessageApi;
|
|
1259
|
+
exports.PreApi = PreApi;
|
|
1260
|
+
exports.PushPlusClient = PushPlusClient;
|
|
1261
|
+
exports.PushPlusClientBuilder = PushPlusClientBuilder;
|
|
1262
|
+
exports.PushPlusError = PushPlusError;
|
|
1263
|
+
exports.PushPlusException = PushPlusException;
|
|
1264
|
+
exports.RateLimitGuard = RateLimitGuard;
|
|
1265
|
+
exports.SendRequestBuilder = SendRequestBuilder;
|
|
1266
|
+
exports.SendStatus = SendStatus;
|
|
1267
|
+
exports.SendStatusDescription = SendStatusDescription;
|
|
1268
|
+
exports.SettingApi = SettingApi;
|
|
1269
|
+
exports.Template = Template;
|
|
1270
|
+
exports.TopicApi = TopicApi;
|
|
1271
|
+
exports.TopicUserApi = TopicUserApi;
|
|
1272
|
+
exports.UserApi = UserApi;
|
|
1273
|
+
exports.WebhookApi = WebhookApi;
|
|
1274
|
+
exports.WebhookType = WebhookType;
|
|
1275
|
+
exports.WebhookTypeDescription = WebhookTypeDescription;
|
|
1276
|
+
exports.batchSendRequest = batchSendRequest;
|
|
1277
|
+
exports.errorCodeFromValue = errorCodeFromValue;
|
|
1278
|
+
exports.isRateLimitedCode = isRateLimitedCode;
|
|
1279
|
+
exports.isSuccessfulHttpStatus = isSuccessfulHttpStatus;
|
|
1280
|
+
exports.parseCallback = parseCallback;
|
|
1281
|
+
exports.resolveConfig = resolveConfig;
|
|
1282
|
+
exports.sendRequest = sendRequest;
|
|
1283
|
+
|
|
1284
|
+
return exports;
|
|
1285
|
+
|
|
1286
|
+
})({});
|
|
1287
|
+
//# sourceMappingURL=index.global.js.map
|
|
1288
|
+
//# sourceMappingURL=index.global.js.map
|