@netcat-ai/openclaw-weixin 2.4.7

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.
Files changed (116) hide show
  1. package/CHANGELOG.md +156 -0
  2. package/CHANGELOG.zh_CN.md +156 -0
  3. package/LICENSE +27 -0
  4. package/README.md +355 -0
  5. package/README.zh_CN.md +351 -0
  6. package/dist/index.js +16 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/src/api/api.js +484 -0
  9. package/dist/src/api/api.js.map +1 -0
  10. package/dist/src/api/config-cache.js +64 -0
  11. package/dist/src/api/config-cache.js.map +1 -0
  12. package/dist/src/api/session-guard.js +49 -0
  13. package/dist/src/api/session-guard.js.map +1 -0
  14. package/dist/src/api/types.js +37 -0
  15. package/dist/src/api/types.js.map +1 -0
  16. package/dist/src/auth/accounts.js +328 -0
  17. package/dist/src/auth/accounts.js.map +1 -0
  18. package/dist/src/auth/login-qr.js +331 -0
  19. package/dist/src/auth/login-qr.js.map +1 -0
  20. package/dist/src/auth/pairing.js +104 -0
  21. package/dist/src/auth/pairing.js.map +1 -0
  22. package/dist/src/cdn/aes-ecb.js +19 -0
  23. package/dist/src/cdn/aes-ecb.js.map +1 -0
  24. package/dist/src/cdn/cdn-upload.js +74 -0
  25. package/dist/src/cdn/cdn-upload.js.map +1 -0
  26. package/dist/src/cdn/cdn-url.js +14 -0
  27. package/dist/src/cdn/cdn-url.js.map +1 -0
  28. package/dist/src/cdn/pic-decrypt.js +89 -0
  29. package/dist/src/cdn/pic-decrypt.js.map +1 -0
  30. package/dist/src/cdn/upload.js +115 -0
  31. package/dist/src/cdn/upload.js.map +1 -0
  32. package/dist/src/channel.js +478 -0
  33. package/dist/src/channel.js.map +1 -0
  34. package/dist/src/compat.js +67 -0
  35. package/dist/src/compat.js.map +1 -0
  36. package/dist/src/config/config-schema.js +20 -0
  37. package/dist/src/config/config-schema.js.map +1 -0
  38. package/dist/src/config/reply-progress.js +5 -0
  39. package/dist/src/config/reply-progress.js.map +1 -0
  40. package/dist/src/media/media-download.js +95 -0
  41. package/dist/src/media/media-download.js.map +1 -0
  42. package/dist/src/media/mime.js +73 -0
  43. package/dist/src/media/mime.js.map +1 -0
  44. package/dist/src/media/silk-transcode.js +64 -0
  45. package/dist/src/media/silk-transcode.js.map +1 -0
  46. package/dist/src/messaging/debug-mode.js +63 -0
  47. package/dist/src/messaging/debug-mode.js.map +1 -0
  48. package/dist/src/messaging/error-notice.js +25 -0
  49. package/dist/src/messaging/error-notice.js.map +1 -0
  50. package/dist/src/messaging/inbound.js +201 -0
  51. package/dist/src/messaging/inbound.js.map +1 -0
  52. package/dist/src/messaging/markdown-filter.js +368 -0
  53. package/dist/src/messaging/markdown-filter.js.map +1 -0
  54. package/dist/src/messaging/outbound-hooks.js +58 -0
  55. package/dist/src/messaging/outbound-hooks.js.map +1 -0
  56. package/dist/src/messaging/process-message.js +406 -0
  57. package/dist/src/messaging/process-message.js.map +1 -0
  58. package/dist/src/messaging/reply-progress-sender.js +93 -0
  59. package/dist/src/messaging/reply-progress-sender.js.map +1 -0
  60. package/dist/src/messaging/send-media.js +54 -0
  61. package/dist/src/messaging/send-media.js.map +1 -0
  62. package/dist/src/messaging/send.js +220 -0
  63. package/dist/src/messaging/send.js.map +1 -0
  64. package/dist/src/messaging/slash-commands.js +70 -0
  65. package/dist/src/messaging/slash-commands.js.map +1 -0
  66. package/dist/src/monitor/monitor.js +146 -0
  67. package/dist/src/monitor/monitor.js.map +1 -0
  68. package/dist/src/storage/state-dir.js +9 -0
  69. package/dist/src/storage/state-dir.js.map +1 -0
  70. package/dist/src/storage/sync-buf.js +64 -0
  71. package/dist/src/storage/sync-buf.js.map +1 -0
  72. package/dist/src/util/logger.js +120 -0
  73. package/dist/src/util/logger.js.map +1 -0
  74. package/dist/src/util/random.js +16 -0
  75. package/dist/src/util/random.js.map +1 -0
  76. package/dist/src/util/redact.js +54 -0
  77. package/dist/src/util/redact.js.map +1 -0
  78. package/index.ts +19 -0
  79. package/openclaw.plugin.json +22 -0
  80. package/package.json +75 -0
  81. package/src/api/api.ts +586 -0
  82. package/src/api/config-cache.ts +79 -0
  83. package/src/api/session-guard.ts +58 -0
  84. package/src/api/types.ts +278 -0
  85. package/src/auth/accounts.ts +394 -0
  86. package/src/auth/login-qr.ts +458 -0
  87. package/src/auth/pairing.ts +120 -0
  88. package/src/cdn/aes-ecb.ts +21 -0
  89. package/src/cdn/cdn-upload.ts +93 -0
  90. package/src/cdn/cdn-url.ts +20 -0
  91. package/src/cdn/pic-decrypt.ts +101 -0
  92. package/src/cdn/upload.ts +168 -0
  93. package/src/channel.ts +548 -0
  94. package/src/compat.ts +77 -0
  95. package/src/config/config-schema.ts +23 -0
  96. package/src/config/reply-progress.ts +10 -0
  97. package/src/media/media-download.ts +149 -0
  98. package/src/media/mime.ts +76 -0
  99. package/src/media/silk-transcode.ts +74 -0
  100. package/src/messaging/debug-mode.ts +69 -0
  101. package/src/messaging/error-notice.ts +32 -0
  102. package/src/messaging/inbound.ts +262 -0
  103. package/src/messaging/markdown-filter.ts +361 -0
  104. package/src/messaging/outbound-hooks.ts +88 -0
  105. package/src/messaging/process-message.ts +525 -0
  106. package/src/messaging/reply-progress-sender.ts +122 -0
  107. package/src/messaging/send-media.ts +72 -0
  108. package/src/messaging/send.ts +294 -0
  109. package/src/messaging/slash-commands.ts +110 -0
  110. package/src/monitor/monitor.ts +224 -0
  111. package/src/storage/state-dir.ts +11 -0
  112. package/src/storage/sync-buf.ts +81 -0
  113. package/src/util/logger.ts +145 -0
  114. package/src/util/random.ts +17 -0
  115. package/src/util/redact.ts +54 -0
  116. package/src/vendor.d.ts +25 -0
@@ -0,0 +1,120 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { resolvePreferredOpenClawTmpDir } from "openclaw/plugin-sdk/infra-runtime";
5
+ /**
6
+ * Plugin logger — writes JSON lines to the main openclaw log file:
7
+ * <tmpDir>/openclaw-YYYY-MM-DD.log
8
+ * Same file and format used by all other channels.
9
+ */
10
+ const MAIN_LOG_DIR = resolvePreferredOpenClawTmpDir();
11
+ const SUBSYSTEM = "gateway/channels/openclaw-weixin";
12
+ const RUNTIME = "node";
13
+ const RUNTIME_VERSION = process.versions.node;
14
+ const HOSTNAME = os.hostname() || "unknown";
15
+ const PARENT_NAMES = ["openclaw"];
16
+ /** tslog-compatible level IDs (higher = more severe). */
17
+ const LEVEL_IDS = {
18
+ TRACE: 1,
19
+ DEBUG: 2,
20
+ INFO: 3,
21
+ WARN: 4,
22
+ ERROR: 5,
23
+ FATAL: 6,
24
+ };
25
+ const DEFAULT_LOG_LEVEL = "INFO";
26
+ function resolveMinLevel() {
27
+ const env = process.env.OPENCLAW_LOG_LEVEL?.toUpperCase();
28
+ if (env && env in LEVEL_IDS)
29
+ return LEVEL_IDS[env];
30
+ return LEVEL_IDS[DEFAULT_LOG_LEVEL];
31
+ }
32
+ let minLevelId = resolveMinLevel();
33
+ /** Dynamically change the minimum log level at runtime. */
34
+ export function setLogLevel(level) {
35
+ const upper = level.toUpperCase();
36
+ if (!(upper in LEVEL_IDS)) {
37
+ throw new Error(`Invalid log level: ${level}. Valid levels: ${Object.keys(LEVEL_IDS).join(", ")}`);
38
+ }
39
+ minLevelId = LEVEL_IDS[upper];
40
+ }
41
+ /** Shift a Date into local time so toISOString() renders local clock digits. */
42
+ function toLocalISO(now) {
43
+ const offsetMs = -now.getTimezoneOffset() * 60_000;
44
+ const sign = offsetMs >= 0 ? "+" : "-";
45
+ const abs = Math.abs(now.getTimezoneOffset());
46
+ const offStr = `${sign}${String(Math.floor(abs / 60)).padStart(2, "0")}:${String(abs % 60).padStart(2, "0")}`;
47
+ return new Date(now.getTime() + offsetMs).toISOString().replace("Z", offStr);
48
+ }
49
+ function localDateKey(now) {
50
+ return toLocalISO(now).slice(0, 10);
51
+ }
52
+ function resolveMainLogPath() {
53
+ const dateKey = localDateKey(new Date());
54
+ return path.join(MAIN_LOG_DIR, `openclaw-${dateKey}.log`);
55
+ }
56
+ let logDirEnsured = false;
57
+ function buildLoggerName(accountId) {
58
+ return accountId ? `${SUBSYSTEM}/${accountId}` : SUBSYSTEM;
59
+ }
60
+ function writeLog(level, message, accountId) {
61
+ const levelId = LEVEL_IDS[level] ?? LEVEL_IDS.INFO;
62
+ if (levelId < minLevelId)
63
+ return;
64
+ const now = new Date();
65
+ const loggerName = buildLoggerName(accountId);
66
+ const prefixedMessage = accountId ? `[${accountId}] ${message}` : message;
67
+ const entry = JSON.stringify({
68
+ "0": loggerName,
69
+ "1": prefixedMessage,
70
+ _meta: {
71
+ runtime: RUNTIME,
72
+ runtimeVersion: RUNTIME_VERSION,
73
+ hostname: HOSTNAME,
74
+ name: loggerName,
75
+ parentNames: PARENT_NAMES,
76
+ date: now.toISOString(),
77
+ logLevelId: LEVEL_IDS[level] ?? LEVEL_IDS.INFO,
78
+ logLevelName: level,
79
+ },
80
+ time: toLocalISO(now),
81
+ });
82
+ try {
83
+ if (!logDirEnsured) {
84
+ fs.mkdirSync(MAIN_LOG_DIR, { recursive: true });
85
+ logDirEnsured = true;
86
+ }
87
+ fs.appendFileSync(resolveMainLogPath(), `${entry}\n`, "utf-8");
88
+ }
89
+ catch {
90
+ // Best-effort; never block on logging failures.
91
+ }
92
+ }
93
+ /** Creates a logger instance, optionally bound to a specific account. */
94
+ function createLogger(accountId) {
95
+ return {
96
+ info(message) {
97
+ writeLog("INFO", message, accountId);
98
+ },
99
+ debug(message) {
100
+ writeLog("DEBUG", message, accountId);
101
+ },
102
+ warn(message) {
103
+ writeLog("WARN", message, accountId);
104
+ },
105
+ error(message) {
106
+ writeLog("ERROR", message, accountId);
107
+ },
108
+ withAccount(id) {
109
+ return createLogger(id);
110
+ },
111
+ getLogFilePath() {
112
+ return resolveMainLogPath();
113
+ },
114
+ close() {
115
+ // No-op: appendFileSync has no persistent handle to close.
116
+ },
117
+ };
118
+ }
119
+ export const logger = createLogger();
120
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../../src/util/logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AAEnF;;;;GAIG;AAEH,MAAM,YAAY,GAAG,8BAA8B,EAAE,CAAC;AACtD,MAAM,SAAS,GAAG,kCAAkC,CAAC;AACrD,MAAM,OAAO,GAAG,MAAM,CAAC;AACvB,MAAM,eAAe,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC9C,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,SAAS,CAAC;AAC5C,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,CAAC;AAElC,yDAAyD;AACzD,MAAM,SAAS,GAA2B;IACxC,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;IACR,KAAK,EAAE,CAAC;CACT,CAAC;AAEF,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAEjC,SAAS,eAAe;IACtB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,WAAW,EAAE,CAAC;IAC1D,IAAI,GAAG,IAAI,GAAG,IAAI,SAAS;QAAE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IACnD,OAAO,SAAS,CAAC,iBAAiB,CAAC,CAAC;AACtC,CAAC;AAED,IAAI,UAAU,GAAG,eAAe,EAAE,CAAC;AAEnC,2DAA2D;AAC3D,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAClC,IAAI,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,mBAAmB,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,UAAU,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,gFAAgF;AAChF,SAAS,UAAU,CAAC,GAAS;IAC3B,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,GAAG,MAAM,CAAC;IACnD,MAAM,IAAI,GAAG,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;IACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,GAAG,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC;IAC9G,OAAO,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AAC/E,CAAC;AAED,SAAS,YAAY,CAAC,GAAS;IAC7B,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,kBAAkB;IACzB,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACzC,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,OAAO,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,IAAI,aAAa,GAAG,KAAK,CAAC;AAc1B,SAAS,eAAe,CAAC,SAAkB;IACzC,OAAO,SAAS,CAAC,CAAC,CAAC,GAAG,SAAS,IAAI,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC7D,CAAC;AAED,SAAS,QAAQ,CAAC,KAAa,EAAE,OAAe,EAAE,SAAkB;IAClE,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI,CAAC;IACnD,IAAI,OAAO,GAAG,UAAU;QAAE,OAAO;IAEjC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,SAAS,KAAK,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;QAC3B,GAAG,EAAE,UAAU;QACf,GAAG,EAAE,eAAe;QACpB,KAAK,EAAE;YACL,OAAO,EAAE,OAAO;YAChB,cAAc,EAAE,eAAe;YAC/B,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,YAAY;YACzB,IAAI,EAAE,GAAG,CAAC,WAAW,EAAE;YACvB,UAAU,EAAE,SAAS,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,IAAI;YAC9C,YAAY,EAAE,KAAK;SACpB;QACD,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC;KACtB,CAAC,CAAC;IACH,IAAI,CAAC;QACH,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAChD,aAAa,GAAG,IAAI,CAAC;QACvB,CAAC;QACD,EAAE,CAAC,cAAc,CAAC,kBAAkB,EAAE,EAAE,GAAG,KAAK,IAAI,EAAE,OAAO,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,gDAAgD;IAClD,CAAC;AACH,CAAC;AAED,yEAAyE;AACzE,SAAS,YAAY,CAAC,SAAkB;IACtC,OAAO;QACL,IAAI,CAAC,OAAe;YAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,OAAe;YACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QACD,IAAI,CAAC,OAAe;YAClB,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,OAAe;YACnB,QAAQ,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;QACxC,CAAC;QACD,WAAW,CAAC,EAAU;YACpB,OAAO,YAAY,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC;QACD,cAAc;YACZ,OAAO,kBAAkB,EAAE,CAAC;QAC9B,CAAC;QACD,KAAK;YACH,2DAA2D;QAC7D,CAAC;KACF,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAW,YAAY,EAAE,CAAC"}
@@ -0,0 +1,16 @@
1
+ import crypto from "node:crypto";
2
+ /**
3
+ * Generate a prefixed unique ID using timestamp + crypto random bytes.
4
+ * Format: `{prefix}:{timestamp}-{8-char hex}`
5
+ */
6
+ export function generateId(prefix) {
7
+ return `${prefix}:${Date.now()}-${crypto.randomBytes(4).toString("hex")}`;
8
+ }
9
+ /**
10
+ * Generate a temporary file name with random suffix.
11
+ * Format: `{prefix}-{timestamp}-{8-char hex}{ext}`
12
+ */
13
+ export function tempFileName(prefix, ext) {
14
+ return `${prefix}-${Date.now()}-${crypto.randomBytes(4).toString("hex")}${ext}`;
15
+ }
16
+ //# sourceMappingURL=random.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"random.js","sourceRoot":"","sources":["../../../src/util/random.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAEjC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAAc;IACvC,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AAC5E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,MAAc,EAAE,GAAW;IACtD,OAAO,GAAG,MAAM,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,EAAE,CAAC;AAClF,CAAC"}
@@ -0,0 +1,54 @@
1
+ const DEFAULT_BODY_MAX_LEN = 200;
2
+ const DEFAULT_TOKEN_PREFIX_LEN = 6;
3
+ /**
4
+ * Truncate a string, appending a length indicator when trimmed.
5
+ * Returns `""` for empty/undefined input.
6
+ */
7
+ export function truncate(s, max) {
8
+ if (!s)
9
+ return "";
10
+ if (s.length <= max)
11
+ return s;
12
+ return `${s.slice(0, max)}…(len=${s.length})`;
13
+ }
14
+ /**
15
+ * Redact a token/secret: show only the first few chars + total length.
16
+ * Returns `"(none)"` when absent.
17
+ */
18
+ export function redactToken(token, prefixLen = DEFAULT_TOKEN_PREFIX_LEN) {
19
+ if (!token)
20
+ return "(none)";
21
+ if (token.length <= prefixLen)
22
+ return `****(len=${token.length})`;
23
+ return `${token.slice(0, prefixLen)}…(len=${token.length})`;
24
+ }
25
+ /** Field names whose values should be masked in logged JSON bodies. */
26
+ const SENSITIVE_FIELDS = /\b(context_token|bot_token|token|authorization|Authorization)\b/;
27
+ /**
28
+ * Truncate a JSON body string to `maxLen` chars for safe logging.
29
+ * Redacts known sensitive fields before truncating.
30
+ */
31
+ export function redactBody(body, maxLen = DEFAULT_BODY_MAX_LEN) {
32
+ if (!body)
33
+ return "(empty)";
34
+ // Mask values of known sensitive JSON keys: "key":"value" → "key":"<redacted>"
35
+ const redacted = body.replace(/"(context_token|bot_token|token|authorization|Authorization)"\s*:\s*"[^"]*"/g, '"$1":"<redacted>"');
36
+ if (redacted.length <= maxLen)
37
+ return redacted;
38
+ return `${redacted.slice(0, maxLen)}…(truncated, totalLen=${redacted.length})`;
39
+ }
40
+ /**
41
+ * Strip query string (which often contains signatures/tokens) from a URL,
42
+ * keeping only origin + pathname.
43
+ */
44
+ export function redactUrl(rawUrl) {
45
+ try {
46
+ const u = new URL(rawUrl);
47
+ const base = `${u.origin}${u.pathname}`;
48
+ return u.search ? `${base}?<redacted>` : base;
49
+ }
50
+ catch {
51
+ return truncate(rawUrl, 80);
52
+ }
53
+ }
54
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../../src/util/redact.ts"],"names":[],"mappings":"AAAA,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,wBAAwB,GAAG,CAAC,CAAC;AAEnC;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,CAAqB,EAAE,GAAW;IACzD,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAClB,IAAI,CAAC,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC;AAChD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,KAAyB,EAAE,SAAS,GAAG,wBAAwB;IACzF,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,IAAI,KAAK,CAAC,MAAM,IAAI,SAAS;QAAE,OAAO,YAAY,KAAK,CAAC,MAAM,GAAG,CAAC;IAClE,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,KAAK,CAAC,MAAM,GAAG,CAAC;AAC9D,CAAC;AAED,uEAAuE;AACvE,MAAM,gBAAgB,GAAG,iEAAiE,CAAC;AAE3F;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,IAAwB,EAAE,MAAM,GAAG,oBAAoB;IAChF,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5B,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAC3B,8EAA8E,EAC9E,mBAAmB,CACpB,CAAC;IACF,IAAI,QAAQ,CAAC,MAAM,IAAI,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC/C,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC,yBAAyB,QAAQ,CAAC,MAAM,GAAG,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"}
package/index.ts ADDED
@@ -0,0 +1,19 @@
1
+ import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
2
+ import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
3
+
4
+ import { weixinPlugin } from "./src/channel.js";
5
+ import { assertHostCompatibility } from "./src/compat.js";
6
+ import { WeixinConfigSchema } from "./src/config/config-schema.js";
7
+
8
+ export default {
9
+ id: "openclaw-weixin",
10
+ name: "Weixin",
11
+ description: "Weixin channel (getUpdates long-poll + sendMessage)",
12
+ configSchema: buildChannelConfigSchema(WeixinConfigSchema),
13
+ register(api: OpenClawPluginApi) {
14
+ // Fail-fast: reject incompatible host versions before any side-effects.
15
+ assertHostCompatibility(api.runtime?.version);
16
+
17
+ api.registerChannel({ plugin: weixinPlugin });
18
+ },
19
+ };
@@ -0,0 +1,22 @@
1
+ {
2
+ "id": "openclaw-weixin",
3
+ "version": "2.4.7",
4
+ "channels": [
5
+ "openclaw-weixin"
6
+ ],
7
+ "channelConfigs": {
8
+ "openclaw-weixin": {
9
+ "schema": {
10
+ "type": "object",
11
+ "additionalProperties": true
12
+ },
13
+ "label": "openclaw-weixin",
14
+ "description": "Weixin channel configuration."
15
+ }
16
+ },
17
+ "configSchema": {
18
+ "type": "object",
19
+ "additionalProperties": false,
20
+ "properties": {}
21
+ }
22
+ }
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@netcat-ai/openclaw-weixin",
3
+ "version": "2.4.7",
4
+ "description": "OpenClaw Weixin channel",
5
+ "license": "MIT",
6
+ "author": "Tencent",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/netcat-ai/openclaw-weixin.git"
10
+ },
11
+ "type": "module",
12
+ "files": [
13
+ "src/",
14
+ "!src/**/*.test.ts",
15
+ "!src/**/node_modules/",
16
+ "index.ts",
17
+ "openclaw.plugin.json",
18
+ "dist/",
19
+ "README.md",
20
+ "README.zh_CN.md",
21
+ "CHANGELOG.md",
22
+ "CHANGELOG.zh_CN.md"
23
+ ],
24
+ "scripts": {
25
+ "test": "vitest run --coverage",
26
+ "typecheck": "tsc --noEmit",
27
+ "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
28
+ "build": "npm run clean && tsc",
29
+ "prepublishOnly": "npm run typecheck && npm run build"
30
+ },
31
+ "engines": {
32
+ "node": ">=22"
33
+ },
34
+ "dependencies": {
35
+ "qrcode-terminal": "0.12.0",
36
+ "zod": "^4.3.6"
37
+ },
38
+ "peerDependencies": {
39
+ "openclaw": ">=2026.5.12"
40
+ },
41
+ "devDependencies": {
42
+ "@vitest/coverage-v8": "^3.1.0",
43
+ "openclaw": "2026.5.12",
44
+ "silk-wasm": "^3.7.1",
45
+ "typescript": "^5.8.0",
46
+ "vitest": "^3.1.0"
47
+ },
48
+ "openclaw": {
49
+ "extensions": [
50
+ "./index.ts"
51
+ ],
52
+ "runtimeExtensions": [
53
+ "./dist/index.js"
54
+ ],
55
+ "channel": {
56
+ "id": "openclaw-weixin",
57
+ "label": "openclaw-weixin",
58
+ "selectionLabel": "openclaw-weixin",
59
+ "docsPath": "/channels/openclaw-weixin",
60
+ "docsLabel": "openclaw-weixin",
61
+ "blurb": "Weixin channel",
62
+ "order": 75
63
+ },
64
+ "install": {
65
+ "npmSpec": "@netcat-ai/openclaw-weixin",
66
+ "defaultChoice": "npm",
67
+ "minHostVersion": ">=2026.5.12"
68
+ }
69
+ },
70
+ "ilink_appid": "bot",
71
+ "publishConfig": {
72
+ "access": "public",
73
+ "registry": "https://registry.npmjs.org"
74
+ }
75
+ }