@perk-net/perk-pushplus-sdk 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -0
- package/dist/index.cjs +233 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +158 -2
- package/dist/index.d.ts +158 -2
- package/dist/index.global.js +233 -5
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +232 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/api/image-api.ts +241 -0
- package/src/client.ts +3 -0
- package/src/config.ts +1 -1
- package/src/enums.ts +2 -0
- package/src/http.ts +101 -6
- package/src/index.ts +11 -0
- package/src/models.ts +68 -0
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
- **同时支持 Node.js 与浏览器**:Node.js 18+ 使用内置 `fetch`,浏览器使用原生 `fetch`,无运行时依赖。
|
|
6
6
|
- **三种产物**:CommonJS (`.cjs`) + ESModule (`.js`) + 浏览器 IIFE (`.global.js`),可通过 npm / `<script>` 直接加载。
|
|
7
7
|
- **完整 TypeScript 类型**:所有请求 / 响应 / 枚举 / 回调全部带类型声明。
|
|
8
|
+
- **全部开放接口**:用户、消息、消息 token、群组、群组用户、好友、webhook、渠道、ClawBot、功能设置、预处理、图片服务(含一键上传到 PushPlus 图床)。
|
|
8
9
|
- **AccessKey 自动管理**:缓存 + 过期前自动刷新;`code=401` 自动刷新并重试一次。
|
|
9
10
|
- **本地限流守卫**:命中 `code=900` 后按 token 短路同 token 后续发送,避免被服务端长期封禁。
|
|
10
11
|
- **Builder 链式 API**:与 Java/Python SDK 风格保持一致。
|
|
@@ -85,6 +86,16 @@ await client.send({
|
|
|
85
86
|
content: 'v1.0.0',
|
|
86
87
|
template: Template.MARKDOWN,
|
|
87
88
|
});
|
|
89
|
+
|
|
90
|
+
// push 表单:template=form 时需传 pushId(表单编码)
|
|
91
|
+
await client.send(
|
|
92
|
+
sendRequest()
|
|
93
|
+
.title('表单通知')
|
|
94
|
+
.content('您有新的表单待填写')
|
|
95
|
+
.template(Template.FORM)
|
|
96
|
+
.pushId('表单编码')
|
|
97
|
+
.build(),
|
|
98
|
+
);
|
|
88
99
|
```
|
|
89
100
|
|
|
90
101
|
### 3. 多渠道发送
|
|
@@ -163,8 +174,49 @@ await client.setting.changeOpenMessageType(0);
|
|
|
163
174
|
|
|
164
175
|
// 预处理(仅会员)
|
|
165
176
|
const out = await client.pre.test({ content: '...', message: 'hi' });
|
|
177
|
+
|
|
178
|
+
// 图片服务(一行上传到 PushPlus 图床,30 天有效)
|
|
179
|
+
import { readFile } from 'node:fs/promises';
|
|
180
|
+
const bytes = await readFile('/tmp/logo.png');
|
|
181
|
+
const uploaded = await client.image.uploadBytes(bytes, { fileName: 'logo.png' });
|
|
182
|
+
console.log(uploaded.url); // 直接拿到可访问的图片 URL
|
|
183
|
+
const imgs = await client.image.list({ current: 1, pageSize: 10 });
|
|
184
|
+
await client.image.delete(imgs.list[0].id);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### 图片服务
|
|
188
|
+
|
|
189
|
+
PushPlus 基于七牛云提供图片图床(30 天有效,可主动删除)。SDK 把「获取上传凭证 → multipart 表单上传 → 解析 URL」封装成一步:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
// Node.js:从文件读取
|
|
193
|
+
import { readFile } from 'node:fs/promises';
|
|
194
|
+
const bytes = await readFile('/tmp/a.png');
|
|
195
|
+
const r = await client.image.uploadBytes(bytes, { fileName: 'a.png' });
|
|
196
|
+
console.log(r.url);
|
|
197
|
+
|
|
198
|
+
// 浏览器:input[type=file]
|
|
199
|
+
const file = (document.querySelector('input[type=file]') as HTMLInputElement).files![0];
|
|
200
|
+
await client.image.uploadBytes(file, { fileName: file.name, contentType: file.type });
|
|
201
|
+
|
|
202
|
+
// 已上传图片列表
|
|
203
|
+
const page = await client.image.list({ current: 1, pageSize: 10 });
|
|
204
|
+
|
|
205
|
+
// 主动删除(未删除的图片默认 30 天后由系统自动清理)
|
|
206
|
+
await client.image.delete(page.list![0].id!);
|
|
166
207
|
```
|
|
167
208
|
|
|
209
|
+
需要自己控制凭证的获取与上传过程时(如缓存 token、分布式上传),可拆开调用:
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
const token = await client.image.getUploadToken();
|
|
213
|
+
const r = await client.image.upload(token, bytes, { fileName: 'a.png', contentType: 'image/png' });
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
> 上传图片的真正请求会按七牛云规范以 `multipart/form-data` 提交到 `uploadUrl`,**不会**携带 PushPlus 的 `access-key`;其余三个接口(获取凭证 / 列表 / 删除)走 PushPlus 开放接口,自动带上 `access-key`。
|
|
217
|
+
>
|
|
218
|
+
> 接受的二进制形态:`Uint8Array`(Node 中 `Buffer` 是其子类,可直接传)、`ArrayBuffer`、`Blob`/`File`(浏览器 + Node 18+)。
|
|
219
|
+
|
|
168
220
|
### 5. 回调解析
|
|
169
221
|
|
|
170
222
|
PushPlus 在消息发送完成、群组新增用户、新增好友时会回调你预置的 URL。SDK 提供类型安全的解析:
|
package/dist/index.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var Template = /* @__PURE__ */ ((Template2) => {
|
|
|
22
22
|
Template2["JENKINS"] = "jenkins";
|
|
23
23
|
Template2["ROUTE"] = "route";
|
|
24
24
|
Template2["PAY"] = "pay";
|
|
25
|
+
Template2["FORM"] = "form";
|
|
25
26
|
return Template2;
|
|
26
27
|
})(Template || {});
|
|
27
28
|
var SendStatus = /* @__PURE__ */ ((SendStatus2) => {
|
|
@@ -185,6 +186,25 @@ var AccessKeyManager = class {
|
|
|
185
186
|
};
|
|
186
187
|
|
|
187
188
|
// src/http.ts
|
|
189
|
+
async function callExecuteRaw(requester, options) {
|
|
190
|
+
if (typeof requester.executeRaw === "function") {
|
|
191
|
+
return requester.executeRaw(options);
|
|
192
|
+
}
|
|
193
|
+
const { method, url, headers, body } = options;
|
|
194
|
+
let text = null;
|
|
195
|
+
if (body != null) {
|
|
196
|
+
if (typeof Blob !== "undefined" && body instanceof Blob) {
|
|
197
|
+
text = await body.text();
|
|
198
|
+
} else if (body instanceof Uint8Array) {
|
|
199
|
+
text = new TextDecoder("utf-8").decode(body);
|
|
200
|
+
} else if (body instanceof ArrayBuffer) {
|
|
201
|
+
text = new TextDecoder("utf-8").decode(new Uint8Array(body));
|
|
202
|
+
} else {
|
|
203
|
+
text = String(body);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return requester.execute({ method, url, headers, body: text });
|
|
207
|
+
}
|
|
188
208
|
var FetchHttpRequester = class {
|
|
189
209
|
constructor(config, fetchImpl) {
|
|
190
210
|
this.readTimeoutMs = config.readTimeoutMs;
|
|
@@ -200,7 +220,29 @@ var FetchHttpRequester = class {
|
|
|
200
220
|
}
|
|
201
221
|
async execute(options) {
|
|
202
222
|
var _a, _b;
|
|
203
|
-
|
|
223
|
+
return this.doExecute({
|
|
224
|
+
method: options.method,
|
|
225
|
+
url: options.url,
|
|
226
|
+
headers: options.headers,
|
|
227
|
+
body: (_a = options.body) != null ? _a : null,
|
|
228
|
+
bodyForLog: (_b = options.body) != null ? _b : null,
|
|
229
|
+
defaultContentType: "application/json;charset=UTF-8"
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
async executeRaw(options) {
|
|
233
|
+
var _a;
|
|
234
|
+
return this.doExecute({
|
|
235
|
+
method: options.method,
|
|
236
|
+
url: options.url,
|
|
237
|
+
headers: options.headers,
|
|
238
|
+
body: (_a = options.body) != null ? _a : null,
|
|
239
|
+
bodyForLog: null,
|
|
240
|
+
defaultContentType: "application/octet-stream"
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
async doExecute(args) {
|
|
244
|
+
var _a, _b;
|
|
245
|
+
const { method, url, headers, body, bodyForLog, defaultContentType } = args;
|
|
204
246
|
const finalHeaders = {};
|
|
205
247
|
let hasContentType = false;
|
|
206
248
|
if (headers) {
|
|
@@ -210,14 +252,19 @@ var FetchHttpRequester = class {
|
|
|
210
252
|
if (k.toLowerCase() === "content-type") hasContentType = true;
|
|
211
253
|
}
|
|
212
254
|
}
|
|
213
|
-
if (body != null && !hasContentType) {
|
|
214
|
-
finalHeaders["Content-Type"] =
|
|
255
|
+
if (body != null && !hasContentType && defaultContentType) {
|
|
256
|
+
finalHeaders["Content-Type"] = defaultContentType;
|
|
215
257
|
}
|
|
216
258
|
if (typeof window === "undefined" && !finalHeaders["User-Agent"] && !finalHeaders["user-agent"]) {
|
|
217
259
|
finalHeaders["User-Agent"] = this.userAgent;
|
|
218
260
|
}
|
|
219
261
|
if (this.logRequest) {
|
|
220
|
-
|
|
262
|
+
if (bodyForLog != null) {
|
|
263
|
+
console.debug("[pushplus] >>>", method, url, "body=", bodyForLog);
|
|
264
|
+
} else {
|
|
265
|
+
const len = bodyLength(body);
|
|
266
|
+
console.debug("[pushplus] >>>", method, url, "bodyBytes=", len);
|
|
267
|
+
}
|
|
221
268
|
}
|
|
222
269
|
const controller = new AbortController();
|
|
223
270
|
const timer = this.readTimeoutMs > 0 ? setTimeout(() => controller.abort(), this.readTimeoutMs) : null;
|
|
@@ -249,6 +296,14 @@ var FetchHttpRequester = class {
|
|
|
249
296
|
}
|
|
250
297
|
}
|
|
251
298
|
};
|
|
299
|
+
function bodyLength(body) {
|
|
300
|
+
if (body == null) return 0;
|
|
301
|
+
if (typeof body === "string") return body.length;
|
|
302
|
+
if (body instanceof Uint8Array) return body.byteLength;
|
|
303
|
+
if (body instanceof ArrayBuffer) return body.byteLength;
|
|
304
|
+
if (typeof Blob !== "undefined" && body instanceof Blob) return body.size;
|
|
305
|
+
return -1;
|
|
306
|
+
}
|
|
252
307
|
function isSuccessfulHttpStatus(status) {
|
|
253
308
|
return status >= 200 && status < 300;
|
|
254
309
|
}
|
|
@@ -520,6 +575,168 @@ var FriendApi = class extends OpenAbstractApi {
|
|
|
520
575
|
}
|
|
521
576
|
};
|
|
522
577
|
|
|
578
|
+
// src/api/image-api.ts
|
|
579
|
+
var ImageApi = class extends OpenAbstractApi {
|
|
580
|
+
constructor(config, http, mgr) {
|
|
581
|
+
super(config, http, mgr);
|
|
582
|
+
}
|
|
583
|
+
/** 1. 获取上传凭证。 */
|
|
584
|
+
getUploadToken() {
|
|
585
|
+
return this.executeOpen("GET", "/api/open/userImage/uploadToken");
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* 2. 上传图片到七牛云。
|
|
589
|
+
*
|
|
590
|
+
* 使用「获取上传凭证」返回的 `uploadUrl` 与 `uploadToken`,
|
|
591
|
+
* 按七牛云表单上传规范以 `multipart/form-data` 提交。该请求
|
|
592
|
+
* **不会** 携带 PushPlus 的 `access-key` 头。
|
|
593
|
+
*/
|
|
594
|
+
async upload(token, file, options) {
|
|
595
|
+
if (token == null) {
|
|
596
|
+
throw new PushPlusError("\u4E0A\u4F20\u51ED\u8BC1 token \u4E0D\u80FD\u4E3A null");
|
|
597
|
+
}
|
|
598
|
+
if (!token.uploadToken) {
|
|
599
|
+
throw new PushPlusError("\u4E0A\u4F20\u51ED\u8BC1 uploadToken \u4E0D\u80FD\u4E3A\u7A7A");
|
|
600
|
+
}
|
|
601
|
+
const uploadUrl = token.uploadUrl || token.uploadHost;
|
|
602
|
+
if (!uploadUrl) {
|
|
603
|
+
throw new PushPlusError("\u4E0A\u4F20\u51ED\u8BC1\u672A\u8FD4\u56DE uploadUrl/uploadHost");
|
|
604
|
+
}
|
|
605
|
+
return this.uploadToQiniu(uploadUrl, token.uploadToken, file, options);
|
|
606
|
+
}
|
|
607
|
+
/**
|
|
608
|
+
* 2. 上传图片到七牛云(低层方法)。直接指定上传地址与 token。
|
|
609
|
+
*/
|
|
610
|
+
async uploadToQiniu(uploadUrl, uploadToken, file, options) {
|
|
611
|
+
var _a, _b;
|
|
612
|
+
if (!uploadUrl) {
|
|
613
|
+
throw new PushPlusError("uploadUrl \u4E0D\u80FD\u4E3A\u7A7A");
|
|
614
|
+
}
|
|
615
|
+
if (!uploadToken) {
|
|
616
|
+
throw new PushPlusError("uploadToken \u4E0D\u80FD\u4E3A\u7A7A");
|
|
617
|
+
}
|
|
618
|
+
const bytes = await toUint8Array(file);
|
|
619
|
+
if (bytes.byteLength === 0) {
|
|
620
|
+
throw new PushPlusError("\u4E0A\u4F20\u6587\u4EF6\u5185\u5BB9\u4E0D\u80FD\u4E3A\u7A7A");
|
|
621
|
+
}
|
|
622
|
+
const fileName = options.fileName || "file";
|
|
623
|
+
const contentType = options.contentType || guessContentTypeByName(fileName) || "application/octet-stream";
|
|
624
|
+
const boundary = "----PushPlusBoundary" + randomBoundarySuffix();
|
|
625
|
+
const body = buildMultipartBody(boundary, uploadToken, fileName, contentType, bytes);
|
|
626
|
+
const resp = await callExecuteRaw(this.http, {
|
|
627
|
+
method: "POST",
|
|
628
|
+
url: uploadUrl,
|
|
629
|
+
headers: { "Content-Type": `multipart/form-data; boundary=${boundary}` },
|
|
630
|
+
body
|
|
631
|
+
});
|
|
632
|
+
if (!isSuccessfulHttpStatus(resp.statusCode)) {
|
|
633
|
+
throw new PushPlusError(
|
|
634
|
+
`\u4E0A\u4F20\u56FE\u7247\u5230\u4E03\u725B\u4E91\u5931\u8D25: status=${resp.statusCode}, body=${resp.body}`,
|
|
635
|
+
resp.statusCode
|
|
636
|
+
);
|
|
637
|
+
}
|
|
638
|
+
let result;
|
|
639
|
+
try {
|
|
640
|
+
result = JSON.parse(resp.body);
|
|
641
|
+
} catch (e) {
|
|
642
|
+
throw new PushPlusError(
|
|
643
|
+
`\u89E3\u6790\u4E03\u725B\u4E91\u54CD\u5E94\u5931\u8D25: ${e.message}, payload=${resp.body}`,
|
|
644
|
+
-1,
|
|
645
|
+
{ cause: e }
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
if (result == null || typeof result !== "object") {
|
|
649
|
+
throw new PushPlusError(`\u4E03\u725B\u4E91\u8FD4\u56DE\u975E JSON \u5BF9\u8C61: ${resp.body}`);
|
|
650
|
+
}
|
|
651
|
+
if (result.errno !== 0) {
|
|
652
|
+
throw new PushPlusError(
|
|
653
|
+
`\u4E03\u725B\u4E91\u4E0A\u4F20\u5931\u8D25: errno=${result.errno}, msg=${(_a = result.msg) != null ? _a : ""}`,
|
|
654
|
+
(_b = result.errno) != null ? _b : -1
|
|
655
|
+
);
|
|
656
|
+
}
|
|
657
|
+
return result;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* 便捷方法:自动获取上传凭证后上传字节数组 / Blob / ArrayBuffer。
|
|
661
|
+
*
|
|
662
|
+
* @example
|
|
663
|
+
* ```ts
|
|
664
|
+
* await client.image.uploadBytes(buffer, { fileName: 'a.png' });
|
|
665
|
+
* await client.image.uploadBytes(blob, { fileName: 'b.jpg', contentType: 'image/jpeg' });
|
|
666
|
+
* ```
|
|
667
|
+
*/
|
|
668
|
+
async uploadBytes(file, options) {
|
|
669
|
+
const token = await this.getUploadToken();
|
|
670
|
+
return this.upload(token, file, options);
|
|
671
|
+
}
|
|
672
|
+
/** 3. 图片列表。 */
|
|
673
|
+
list(query) {
|
|
674
|
+
return this.executeOpen(
|
|
675
|
+
"POST",
|
|
676
|
+
"/api/open/userImage/list",
|
|
677
|
+
query != null ? query : {}
|
|
678
|
+
);
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* 4. 主动删除图片;未删除的图片默认 30 天后由系统自动清理。
|
|
682
|
+
*/
|
|
683
|
+
async delete(id) {
|
|
684
|
+
await this.executeOpen(
|
|
685
|
+
"DELETE",
|
|
686
|
+
this.appendQuery("/api/open/userImage/delete", { id })
|
|
687
|
+
);
|
|
688
|
+
}
|
|
689
|
+
};
|
|
690
|
+
async function toUint8Array(file) {
|
|
691
|
+
if (file == null) {
|
|
692
|
+
throw new PushPlusError("\u4E0A\u4F20\u6587\u4EF6\u4E0D\u80FD\u4E3A null");
|
|
693
|
+
}
|
|
694
|
+
if (file instanceof Uint8Array) {
|
|
695
|
+
return file;
|
|
696
|
+
}
|
|
697
|
+
if (file instanceof ArrayBuffer) {
|
|
698
|
+
return new Uint8Array(file);
|
|
699
|
+
}
|
|
700
|
+
if (typeof Blob !== "undefined" && file instanceof Blob) {
|
|
701
|
+
const ab = await file.arrayBuffer();
|
|
702
|
+
return new Uint8Array(ab);
|
|
703
|
+
}
|
|
704
|
+
throw new PushPlusError(`\u4E0D\u652F\u6301\u7684\u4E0A\u4F20\u6587\u4EF6\u7C7B\u578B: ${Object.prototype.toString.call(file)}`);
|
|
705
|
+
}
|
|
706
|
+
function buildMultipartBody(boundary, uploadToken, fileName, contentType, fileBytes) {
|
|
707
|
+
const crlf = "\r\n";
|
|
708
|
+
const enc = new TextEncoder();
|
|
709
|
+
const head = enc.encode(
|
|
710
|
+
`--${boundary}${crlf}Content-Disposition: form-data; name="token"${crlf}${crlf}${uploadToken}${crlf}--${boundary}${crlf}Content-Disposition: form-data; name="file"; filename="${escapeFileName(fileName)}"${crlf}Content-Type: ${contentType}${crlf}${crlf}`
|
|
711
|
+
);
|
|
712
|
+
const tail = enc.encode(`${crlf}--${boundary}--${crlf}`);
|
|
713
|
+
const out = new Uint8Array(head.byteLength + fileBytes.byteLength + tail.byteLength);
|
|
714
|
+
out.set(head, 0);
|
|
715
|
+
out.set(fileBytes, head.byteLength);
|
|
716
|
+
out.set(tail, head.byteLength + fileBytes.byteLength);
|
|
717
|
+
return out;
|
|
718
|
+
}
|
|
719
|
+
function escapeFileName(name) {
|
|
720
|
+
return name.replace(/"/g, "_").replace(/\r/g, " ").replace(/\n/g, " ");
|
|
721
|
+
}
|
|
722
|
+
function guessContentTypeByName(name) {
|
|
723
|
+
const lower = name.toLowerCase();
|
|
724
|
+
if (lower.endsWith(".png")) return "image/png";
|
|
725
|
+
if (lower.endsWith(".jpg") || lower.endsWith(".jpeg")) return "image/jpeg";
|
|
726
|
+
if (lower.endsWith(".gif")) return "image/gif";
|
|
727
|
+
if (lower.endsWith(".webp")) return "image/webp";
|
|
728
|
+
if (lower.endsWith(".bmp")) return "image/bmp";
|
|
729
|
+
if (lower.endsWith(".svg")) return "image/svg+xml";
|
|
730
|
+
return null;
|
|
731
|
+
}
|
|
732
|
+
function randomBoundarySuffix() {
|
|
733
|
+
let s = "";
|
|
734
|
+
for (let i = 0; i < 32; i++) {
|
|
735
|
+
s += Math.floor(Math.random() * 16).toString(16);
|
|
736
|
+
}
|
|
737
|
+
return s;
|
|
738
|
+
}
|
|
739
|
+
|
|
523
740
|
// src/api/message-api.ts
|
|
524
741
|
var MessageApi = class extends AbstractApi {
|
|
525
742
|
constructor(config, http, rateLimitGuard) {
|
|
@@ -919,7 +1136,7 @@ function resolveConfig(input) {
|
|
|
919
1136
|
logRequest: (_g = cfg.logRequest) != null ? _g : false,
|
|
920
1137
|
rateLimitGuardEnabled: (_h = cfg.rateLimitGuardEnabled) != null ? _h : true,
|
|
921
1138
|
rateLimitCooldownMs: (_i = cfg.rateLimitCooldownMs) != null ? _i : 0,
|
|
922
|
-
userAgent: (_j = cfg.userAgent) != null ? _j : `@perk-net/perk-pushplus-sdk/1.
|
|
1139
|
+
userAgent: (_j = cfg.userAgent) != null ? _j : `@perk-net/perk-pushplus-sdk/1.1.0`
|
|
923
1140
|
};
|
|
924
1141
|
}
|
|
925
1142
|
|
|
@@ -1013,6 +1230,7 @@ var PushPlusClient = class _PushPlusClient {
|
|
|
1013
1230
|
this.clawBot = new ClawBotApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1014
1231
|
this.setting = new SettingApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1015
1232
|
this.pre = new PreApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1233
|
+
this.image = new ImageApi(this.config, this.httpRequester, this.accessKeyManager);
|
|
1016
1234
|
}
|
|
1017
1235
|
/** 与 Java SDK 风格一致的 Builder 入口。 */
|
|
1018
1236
|
static builder() {
|
|
@@ -1159,6 +1377,10 @@ var SendRequestBuilder = class {
|
|
|
1159
1377
|
this.req.pre = v;
|
|
1160
1378
|
return this;
|
|
1161
1379
|
}
|
|
1380
|
+
pushId(v) {
|
|
1381
|
+
this.req.pushId = v;
|
|
1382
|
+
return this;
|
|
1383
|
+
}
|
|
1162
1384
|
build() {
|
|
1163
1385
|
return { ...this.req };
|
|
1164
1386
|
}
|
|
@@ -1208,6 +1430,10 @@ var BatchSendRequestBuilder = class {
|
|
|
1208
1430
|
this.req.pre = v;
|
|
1209
1431
|
return this;
|
|
1210
1432
|
}
|
|
1433
|
+
pushId(v) {
|
|
1434
|
+
this.req.pushId = v;
|
|
1435
|
+
return this;
|
|
1436
|
+
}
|
|
1211
1437
|
/** 追加一个 channel。 */
|
|
1212
1438
|
channel(ch) {
|
|
1213
1439
|
this.channelList.push(typeof ch === "string" ? ch : ch);
|
|
@@ -1251,6 +1477,7 @@ exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
|
1251
1477
|
exports.ErrorCode = ErrorCode;
|
|
1252
1478
|
exports.FetchHttpRequester = FetchHttpRequester;
|
|
1253
1479
|
exports.FriendApi = FriendApi;
|
|
1480
|
+
exports.ImageApi = ImageApi;
|
|
1254
1481
|
exports.MessageApi = MessageApi;
|
|
1255
1482
|
exports.MessageTokenApi = MessageTokenApi;
|
|
1256
1483
|
exports.OpenAbstractApi = OpenAbstractApi;
|
|
@@ -1273,6 +1500,7 @@ exports.WebhookApi = WebhookApi;
|
|
|
1273
1500
|
exports.WebhookType = WebhookType;
|
|
1274
1501
|
exports.WebhookTypeDescription = WebhookTypeDescription;
|
|
1275
1502
|
exports.batchSendRequest = batchSendRequest;
|
|
1503
|
+
exports.callExecuteRaw = callExecuteRaw;
|
|
1276
1504
|
exports.errorCodeFromValue = errorCodeFromValue;
|
|
1277
1505
|
exports.isRateLimitedCode = isRateLimitedCode;
|
|
1278
1506
|
exports.isSuccessfulHttpStatus = isSuccessfulHttpStatus;
|