dsh-shlr-bilitoolkit 0.1.20 → 0.1.21

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.
@@ -5,9 +5,11 @@ delete)都是公开行为,受风控和人机验证限制,使用前请自
5
5
  */
6
6
  import { readFile } from "node:fs/promises";
7
7
  import { basename } from "node:path";
8
+ import FormData from "form-data";
8
9
  import * as endpoints from "../endpoints.js";
9
10
  import { BiliApiError } from "../errors.js";
10
11
  import { Dynamic } from "../models.js";
12
+ import { guessImageType } from "../util.js";
11
13
  const FEATURES = "itemOpusStyle";
12
14
  const REFERER = "https://t.bilibili.com/";
13
15
  export class DynamicAPI {
@@ -119,23 +121,29 @@ export class DynamicAPI {
119
121
  bytes = await readFile(String(img));
120
122
  name = basename(String(img));
121
123
  }
122
- // 动态图床上传是 multipart,直接用底层 axios(client.post 会做表单编码,不适合二进制)
124
+ // 动态图床上传是 multipart,用 form-data 包(Node 下 axios 靠它正确序列化二进制)
123
125
  const form = new FormData();
124
126
  form.append("biz", "draw");
125
127
  form.append("csrf", this.client.csrf);
126
- form.append("file_up", new Blob([bytes]), name);
127
- const resp = await this.client.http.post(endpoints.DYNAMIC_IMAGE_UPLOAD, form, { headers: { Referer: REFERER } });
128
+ form.append("file_up", bytes, { filename: name, contentType: guessImageType(name) });
129
+ const resp = await this.client.http.post(endpoints.DYNAMIC_IMAGE_UPLOAD, form, {
130
+ headers: { ...form.getHeaders(), Referer: REFERER },
131
+ maxContentLength: Infinity,
132
+ maxBodyLength: Infinity,
133
+ });
128
134
  const data = resp?.data ?? {};
129
- const d = data.data ?? {};
130
- if (data.code !== 0 || !d.url) {
131
- throw new BiliApiError(`图片上传失败: ${data.message ?? "接口未返回 url"}`, data.code, d);
135
+ const raw = data.data;
136
+ const url = typeof raw === "string" ? raw : raw?.url;
137
+ if (data.code !== 0 || !url) {
138
+ throw new BiliApiError(`图片上传失败: ${data.message ?? "接口未返回 url"}`, data.code, raw);
132
139
  }
140
+ const meta = raw && typeof raw === "object" ? raw : {};
133
141
  return {
134
- img_src: String(d.url),
135
- img_width: Number(d.image_width ?? d.width ?? 0),
136
- img_height: Number(d.image_height ?? d.height ?? 0),
142
+ img_src: String(url),
143
+ img_width: Number(meta.image_width ?? meta.width ?? 0),
144
+ img_height: Number(meta.image_height ?? meta.height ?? 0),
137
145
  // 接口有时不返回体积,用字节数兜底(KB)
138
- img_size: Number(d.img_size ?? Math.round(bytes.length / 1024)),
146
+ img_size: Number(meta.img_size ?? Math.round(bytes.length / 1024)),
139
147
  };
140
148
  }
141
149
  /** 发布图文动态(文字 + 最多若干张图片)。图片可以是本地路径或 Buffer。 */
@@ -6,8 +6,10 @@
6
6
  */
7
7
  import { readFile } from "node:fs/promises";
8
8
  import { basename } from "node:path";
9
+ import FormData from "form-data";
9
10
  import * as endpoints from "../endpoints.js";
10
11
  import { BiliApiError } from "../errors.js";
12
+ import { guessImageType } from "../util.js";
11
13
  const SEX_VALUES = ["男", "女", "保密"];
12
14
  const MAX_SIGN_LENGTH = 70;
13
15
  export class ProfileAPI {
@@ -73,13 +75,19 @@ export class ProfileAPI {
73
75
  const form = new FormData();
74
76
  form.append("biz", "draw");
75
77
  form.append("csrf", this.client.csrf);
76
- form.append("file_up", new Blob([bytes]), name);
77
- const resp = await this.client.http.post(endpoints.DYNAMIC_IMAGE_UPLOAD, form, { headers: { Referer: "https://space.bilibili.com/" } });
78
+ form.append("file_up", bytes, { filename: name, contentType: guessImageType(name) });
79
+ const resp = await this.client.http.post(endpoints.DYNAMIC_IMAGE_UPLOAD, form, {
80
+ headers: { ...form.getHeaders(), Referer: "https://space.bilibili.com/" },
81
+ maxContentLength: Infinity,
82
+ maxBodyLength: Infinity,
83
+ });
78
84
  const data = resp?.data ?? {};
79
- if (data.code !== 0 || !data.data?.url) {
80
- throw new BiliApiError(`头像图片上传失败: ${data.message ?? "接口未返回 url"}`, data.code, data.data);
85
+ const raw = data.data;
86
+ const url = typeof raw === "string" ? raw : raw?.url;
87
+ if (data.code !== 0 || !url) {
88
+ throw new BiliApiError(`头像图片上传失败: ${data.message ?? "接口未返回 url"}`, data.code, raw);
81
89
  }
82
- return String(data.data.url);
90
+ return String(url);
83
91
  }
84
92
  /** 更换头像:先上传图片拿 URL,再调 face/update。img 为本地路径或 Buffer。 */
85
93
  async changeAvatar(img) {
package/dist/util.d.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  /** 小工具函数。 */
2
2
  export declare function sleep(ms: number): Promise<void>;
3
+ /** 根据文件名猜图片 MIME,用于 multipart 上传(缺省按 jpeg)。 */
4
+ export declare function guessImageType(name: string): string;
package/dist/util.js CHANGED
@@ -2,3 +2,16 @@
2
2
  export function sleep(ms) {
3
3
  return new Promise((resolve) => setTimeout(resolve, ms));
4
4
  }
5
+ const IMAGE_TYPES = {
6
+ png: "image/png",
7
+ jpg: "image/jpeg",
8
+ jpeg: "image/jpeg",
9
+ gif: "image/gif",
10
+ webp: "image/webp",
11
+ bmp: "image/bmp",
12
+ };
13
+ /** 根据文件名猜图片 MIME,用于 multipart 上传(缺省按 jpeg)。 */
14
+ export function guessImageType(name) {
15
+ const ext = (name.toLowerCase().split(".").pop() ?? "").trim();
16
+ return IMAGE_TYPES[ext] ?? "image/jpeg";
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-shlr-bilitoolkit",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "深海猎人专用B站接口工具箱 dsh 插件。",
5
5
  "type": "module",
6
6
  "main": "dist/dsh.js",
@@ -23,10 +23,11 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "axios": "^1.7.0",
26
+ "form-data": "^4.0.6",
26
27
  "qrcode": "^1.5.4"
27
28
  },
28
29
  "devDependencies": {
29
- "@deepseek-ai/cordis": "0.0.1-rc.1",
30
+ "@deepseek-ai/cordis": "^4.0.5",
30
31
  "@deepseek-ai/dsh-tools": "0.0.1-rc.1",
31
32
  "@types/node": "^22.0.0",
32
33
  "@types/qrcode": "^1.5.5",