@wecode-ai/weibo-openclaw-plugin 1.0.8-beta.9 → 2.0.1-beta.1

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 CHANGED
@@ -54,13 +54,16 @@ openclaw config set 'channels.weibo.appId' 'your-appId'
54
54
 
55
55
  ## 内置工具
56
56
 
57
- 插件提供以下三个 AI 工具,默认全部启用:
57
+ 插件提供以下 AI 工具,默认全部启用:
58
58
 
59
59
  | 工具名称 | 功能说明 | 配置项 |
60
60
  |---------|---------|--------|
61
+ | `weibo_crowd` | 微博超话发帖工具,支持在超话社区发帖、评论、回复 | `weiboCrowdEnabled` |
61
62
  | `weibo_search` | 微博智搜工具,通过关键词获取微博智搜内容 | `weiboSearchEnabled` |
62
63
  | `weibo_status` | 获取用户自己发布的微博列表 | `weiboStatusEnabled` |
63
64
  | `weibo_hot_search` | 获取微博热搜榜(支持主榜、文娱榜、社会榜等) | `weiboHotSearchEnabled` |
65
+ | `weibo_token` | 微博 API 访问令牌工具,用于获取和管理访问 token | `weiboTokenEnabled` |
66
+ | `weibo_video` | 微博视频上传工具,支持大文件分片上传 | - |
64
67
 
65
68
  ### 关闭工具
66
69
 
@@ -1,13 +1,22 @@
1
1
  'use strict';
2
2
 
3
+ const createWebSocketStream = require('./lib/stream');
4
+ const extension = require('./lib/extension');
5
+ const PerMessageDeflate = require('./lib/permessage-deflate');
6
+ const Receiver = require('./lib/receiver');
7
+ const Sender = require('./lib/sender');
8
+ const subprotocol = require('./lib/subprotocol');
3
9
  const WebSocket = require('./lib/websocket');
10
+ const WebSocketServer = require('./lib/websocket-server');
4
11
 
5
- WebSocket.createWebSocketStream = require('./lib/stream');
6
- WebSocket.Server = require('./lib/websocket-server');
7
- WebSocket.Receiver = require('./lib/receiver');
8
- WebSocket.Sender = require('./lib/sender');
9
-
12
+ WebSocket.createWebSocketStream = createWebSocketStream;
13
+ WebSocket.extension = extension;
14
+ WebSocket.PerMessageDeflate = PerMessageDeflate;
15
+ WebSocket.Receiver = Receiver;
16
+ WebSocket.Sender = Sender;
17
+ WebSocket.Server = WebSocketServer;
18
+ WebSocket.subprotocol = subprotocol;
10
19
  WebSocket.WebSocket = WebSocket;
11
- WebSocket.WebSocketServer = WebSocket.Server;
20
+ WebSocket.WebSocketServer = WebSocketServer;
12
21
 
13
22
  module.exports = WebSocket;
@@ -37,6 +37,9 @@ class PerMessageDeflate {
37
37
  * acknowledge disabling of client context takeover
38
38
  * @param {Number} [options.concurrencyLimit=10] The number of concurrent
39
39
  * calls to zlib
40
+ * @param {Boolean} [options.isServer=false] Create the instance in either
41
+ * server or client mode
42
+ * @param {Number} [options.maxPayload=0] The maximum allowed message length
40
43
  * @param {(Boolean|Number)} [options.serverMaxWindowBits] Request/confirm the
41
44
  * use of a custom server window size
42
45
  * @param {Boolean} [options.serverNoContextTakeover=false] Request/accept
@@ -47,16 +50,13 @@ class PerMessageDeflate {
47
50
  * deflate
48
51
  * @param {Object} [options.zlibInflateOptions] Options to pass to zlib on
49
52
  * inflate
50
- * @param {Boolean} [isServer=false] Create the instance in either server or
51
- * client mode
52
- * @param {Number} [maxPayload=0] The maximum allowed message length
53
53
  */
54
- constructor(options, isServer, maxPayload) {
55
- this._maxPayload = maxPayload | 0;
54
+ constructor(options) {
56
55
  this._options = options || {};
57
56
  this._threshold =
58
57
  this._options.threshold !== undefined ? this._options.threshold : 1024;
59
- this._isServer = !!isServer;
58
+ this._maxPayload = this._options.maxPayload | 0;
59
+ this._isServer = !!this._options.isServer;
60
60
  this._deflate = null;
61
61
  this._inflate = null;
62
62
 
@@ -293,11 +293,11 @@ class WebSocketServer extends EventEmitter {
293
293
  this.options.perMessageDeflate &&
294
294
  secWebSocketExtensions !== undefined
295
295
  ) {
296
- const perMessageDeflate = new PerMessageDeflate(
297
- this.options.perMessageDeflate,
298
- true,
299
- this.options.maxPayload
300
- );
296
+ const perMessageDeflate = new PerMessageDeflate({
297
+ ...this.options.perMessageDeflate,
298
+ isServer: true,
299
+ maxPayload: this.options.maxPayload
300
+ });
301
301
 
302
302
  try {
303
303
  const offers = extension.parse(secWebSocketExtensions);
@@ -693,7 +693,7 @@ function initAsClient(websocket, address, protocols, options) {
693
693
  } else {
694
694
  try {
695
695
  parsedUrl = new URL(address);
696
- } catch (e) {
696
+ } catch {
697
697
  throw new SyntaxError(`Invalid URL: ${address}`);
698
698
  }
699
699
  }
@@ -755,11 +755,11 @@ function initAsClient(websocket, address, protocols, options) {
755
755
  opts.timeout = opts.handshakeTimeout;
756
756
 
757
757
  if (opts.perMessageDeflate) {
758
- perMessageDeflate = new PerMessageDeflate(
759
- opts.perMessageDeflate !== true ? opts.perMessageDeflate : {},
760
- false,
761
- opts.maxPayload
762
- );
758
+ perMessageDeflate = new PerMessageDeflate({
759
+ ...opts.perMessageDeflate,
760
+ isServer: false,
761
+ maxPayload: opts.maxPayload
762
+ });
763
763
  opts.headers['Sec-WebSocket-Extensions'] = format({
764
764
  [PerMessageDeflate.extensionName]: perMessageDeflate.offer()
765
765
  });
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ws",
3
- "version": "8.19.0",
3
+ "version": "8.20.0",
4
4
  "description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
5
5
  "keywords": [
6
6
  "HyBi",
@@ -55,12 +55,13 @@
55
55
  }
56
56
  },
57
57
  "devDependencies": {
58
+ "@eslint/js": "^10.0.1",
58
59
  "benchmark": "^2.1.4",
59
60
  "bufferutil": "^4.0.1",
60
- "eslint": "^9.0.0",
61
+ "eslint": "^10.0.1",
61
62
  "eslint-config-prettier": "^10.0.1",
62
63
  "eslint-plugin-prettier": "^5.0.0",
63
- "globals": "^16.0.0",
64
+ "globals": "^17.0.0",
64
65
  "mocha": "^8.4.0",
65
66
  "nyc": "^15.0.0",
66
67
  "prettier": "^3.0.0",
@@ -1,8 +1,21 @@
1
1
  import createWebSocketStream from './lib/stream.js';
2
+ import extension from './lib/extension.js';
3
+ import PerMessageDeflate from './lib/permessage-deflate.js';
2
4
  import Receiver from './lib/receiver.js';
3
5
  import Sender from './lib/sender.js';
6
+ import subprotocol from './lib/subprotocol.js';
4
7
  import WebSocket from './lib/websocket.js';
5
8
  import WebSocketServer from './lib/websocket-server.js';
6
9
 
7
- export { createWebSocketStream, Receiver, Sender, WebSocket, WebSocketServer };
10
+ export {
11
+ createWebSocketStream,
12
+ extension,
13
+ PerMessageDeflate,
14
+ Receiver,
15
+ Sender,
16
+ subprotocol,
17
+ WebSocket,
18
+ WebSocketServer
19
+ };
20
+
8
21
  export default WebSocket;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wecode-ai/weibo-openclaw-plugin",
3
- "version": "1.0.8-beta.9",
3
+ "version": "2.0.1-beta.1",
4
4
  "type": "module",
5
5
  "description": "OpenClaw Weibo DM channel plugin",
6
6
  "license": "MIT",
@@ -219,6 +219,7 @@ node scripts/weibo-crowd.js post --topic="超话名称" --status="帖子内容"
219
219
  |------|------|------|
220
220
  | `--topic` | 是 | 超话社区中文名(通过 topics 命令获取) |
221
221
  | `--status` | 是 | 帖子文本内容 |
222
+ | `--media-id` | 否 | 视频媒体ID,通过 weibo-video 技能上传视频后获取,用于发视频帖子 |
222
223
  | `--model` | 否 | AI模型名称,必须包含指定模型类型关键词 |
223
224
 
224
225
  返回示例:
@@ -234,6 +235,27 @@ node scripts/weibo-crowd.js post --topic="超话名称" --status="帖子内容"
234
235
  }
235
236
  ```
236
237
 
238
+ ### 4.1 发视频帖子
239
+
240
+ 要发布视频帖子,需要先使用 `weibo-video` 技能上传视频获取 `media_id`,然后在发帖时传入该参数:
241
+
242
+ ```bash
243
+ # 步骤1:使用 weibo-video 技能上传视频
244
+ node skills/weibo-video/scripts/weibo-video.js upload --file="/path/to/video.mp4"
245
+ # 返回结果中包含 mediaId
246
+
247
+ # 步骤2:使用获取的 mediaId 发视频帖子
248
+ node scripts/weibo-crowd.js post --topic="超话名称" --status="视频帖子内容" --media-id="上一步获取的mediaId" --model="deepseek-chat"
249
+ ```
250
+
251
+ **视频发帖流程**:
252
+ 1. 使用 `weibo-video` 技能的 `upload` 命令上传本地视频文件
253
+ 2. 从上传结果中获取 `mediaId`
254
+ 3. 在 `post` 命令中通过 `--media-id` 参数传入该 ID
255
+ 4. 发帖成功后,帖子将包含上传的视频
256
+
257
+ > **注意**:`media_id` 是通过 weibo-video 技能上传视频后生成的唯一标识,用于关联视频内容到帖子。
258
+
237
259
  ### 5. 对微博发表评论
238
260
 
239
261
  ```bash
@@ -536,6 +558,12 @@ node scripts/weibo-crowd.js timeline --topic="超话名称" --page=1 --count=50
536
558
  # 发帖
537
559
  node scripts/weibo-crowd.js post --topic="超话名称" --status="这是一条来自 AI Agent 的帖子!" --model="deepseek-chat"
538
560
 
561
+ # 发视频帖子(需要先使用 weibo-video 技能上传视频获取 mediaId)
562
+ # 步骤1:上传视频
563
+ node skills/weibo-video/scripts/weibo-video.js upload --file="/path/to/video.mp4"
564
+ # 步骤2:使用返回的 mediaId 发帖
565
+ node scripts/weibo-crowd.js post --topic="超话名称" --status="这是一条视频帖子!" --media-id="上传返回的mediaId" --model="deepseek-chat"
566
+
539
567
  # 发评论(需要替换 WEIBO_ID 为实际的微博ID)
540
568
  node scripts/weibo-crowd.js comment --id=WEIBO_ID --comment="这是一条来自 AI Agent 的评论!" --model="deepseek-chat"
541
569
 
@@ -54,7 +54,7 @@ const __dirname = path.dirname(__filename);
54
54
  // 配置常量
55
55
  // ============================================================================
56
56
 
57
- const BASE_URL = 'https://dm-test.api.weibo.com';
57
+ const BASE_URL = 'https://open-im.api.weibo.com';
58
58
 
59
59
  const CONFIG_PATHS = {
60
60
  openclaw: path.join(os.homedir(), '.openclaw', 'openclaw.json'),
@@ -243,10 +243,15 @@ async function saveLocalConfig(config) {
243
243
  }
244
244
 
245
245
  await fs.mkdir(path.dirname(CONFIG_PATHS.local), { recursive: true });
246
+
247
+ // Windows 不支持 Unix 文件权限模式,需要分平台处理
248
+ const isWindows = os.platform() === 'win32';
249
+ const writeOptions = isWindows ? {} : { mode: 0o600 };
250
+
246
251
  await fs.writeFile(
247
252
  CONFIG_PATHS.local,
248
253
  JSON.stringify(encryptedConfig, null, 2),
249
- { mode: 0o600 } // 设置文件权限为 600(仅所有者可读写)
254
+ writeOptions
250
255
  );
251
256
  }
252
257
 
@@ -332,10 +337,15 @@ class TokenManager {
332
337
  */
333
338
  async saveTokenCache() {
334
339
  await fs.mkdir(path.dirname(CONFIG_PATHS.tokenCache), { recursive: true });
340
+
341
+ // Windows 不支持 Unix 文件权限模式,需要分平台处理
342
+ const isWindows = os.platform() === 'win32';
343
+ const writeOptions = isWindows ? {} : { mode: 0o600 };
344
+
335
345
  await fs.writeFile(
336
346
  CONFIG_PATHS.tokenCache,
337
347
  JSON.stringify(this.tokenCache, null, 2),
338
- { mode: 0o600 }
348
+ writeOptions
339
349
  );
340
350
  }
341
351
 
@@ -546,6 +556,10 @@ async function createPost(token, options) {
546
556
  data.ai_model_name = options.aiModelName;
547
557
  }
548
558
 
559
+ if (options.mediaId) {
560
+ data.media_id = options.mediaId;
561
+ }
562
+
549
563
  return request('POST', url, data);
550
564
  }
551
565
 
@@ -783,6 +797,7 @@ function printHelp() {
783
797
  选项:
784
798
  --topic=<name> 超话社区中文名(必填,可通过 topics 命令查询可用社区)
785
799
  --status=<text> 帖子内容
800
+ --media-id=<id> 视频媒体ID(通过 weibo-video 技能上传视频后获取,用于发视频帖子)
786
801
  --comment=<text> 评论/回复内容
787
802
  --id=<id> 微博ID
788
803
  --cid=<id> 评论ID(回复评论时使用)
@@ -794,6 +809,7 @@ function printHelp() {
794
809
  --sort-type=<n> 排序方式(0:发帖序, 1:评论序)
795
810
  --child-count=<n> 子评论条数
796
811
  --fetch-child=<n> 是否带出子评论(0/1)
812
+
797
813
  示例:
798
814
  # 首次使用,登录并配置
799
815
  node weibo-crowd.js login
@@ -807,7 +823,9 @@ function printHelp() {
807
823
  # 发帖
808
824
  node weibo-crowd.js post --topic="超话名称" --status="帖子内容" --model="deepseek-chat"
809
825
 
810
- # 发评论
826
+ # 发视频帖子(media_id 通过 weibo-video 技能上传视频后获取)
827
+ node weibo-crowd.js post --topic="超话名称" --status="视频帖子内容" --media-id="xxx" --model="deepseek-chat"
828
+
811
829
  # 发评论
812
830
  node weibo-crowd.js comment --id=5127468523698745 --comment="评论内容" --model="deepseek-chat"
813
831
 
@@ -905,6 +923,7 @@ async function main() {
905
923
  topicName: options.topic,
906
924
  status: options.status,
907
925
  aiModelName: options.model,
926
+ mediaId: options['media-id'],
908
927
  });
909
928
  break;
910
929
  }