添加完整的微信插件测试框架,包含: - 微信插件源码(weixin-plugin/) - TypeScript 类型定义(types.ts) - 插件编译脚本(scripts/build-weixin-plugin.sh) - 简化测试脚本(scripts/test-weixin-simple.js) - 完整测试脚本(scripts/test-weixin-plugin.js) - 项目配置和依赖管理(package.json) - 使用说明文档(README.md) 主要功能: - 支持二维码登录认证 - HTTP 长轮询消息接收 - 文本、图片、视频、文件消息收发 - 自动回复测试 - 运行状态统计 Generated with [Claude Code](https://claude.com/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
import os from "node:os";
|
|
|
|
function resolvePreferredOpenClawTmpDir(): string {
|
|
const envOverride = process.env.OPENCLAW_TMP_DIR?.trim();
|
|
if (envOverride) return envOverride;
|
|
const stateDir = process.env.OPENCLAW_STATE_DIR?.trim() ||
|
|
process.env.CLAWDBOT_STATE_DIR?.trim() ||
|
|
path.join(os.homedir(), ".openclaw");
|
|
return path.join(stateDir, "tmp");
|
|
}
|
|
|
|
function mainLogDir(): string {
|
|
return resolvePreferredOpenClawTmpDir();
|
|
}
|
|
|
|
function currentDayLogFileName(): string {
|
|
const now = new Date();
|
|
const offsetMs = -now.getTimezoneOffset() * 60_000;
|
|
const dateKey = new Date(now.getTime() + offsetMs).toISOString().slice(0, 10);
|
|
return `originclawai-${dateKey}.log`;
|
|
}
|
|
|
|
function resolveLogFileName(file: string): string {
|
|
if (/^\d{8}$/.test(file)) {
|
|
const yyyy = file.slice(0, 4);
|
|
const mm = file.slice(4, 6);
|
|
const dd = file.slice(6, 8);
|
|
return `originclawai-${yyyy}-${mm}-${dd}.log`;
|
|
}
|
|
if (/^\d{10}$/.test(file)) {
|
|
const yyyy = file.slice(0, 4);
|
|
const mm = file.slice(4, 6);
|
|
const dd = file.slice(6, 8);
|
|
return `originclawai-${yyyy}-${mm}-${dd}.log`;
|
|
}
|
|
return file;
|
|
}
|
|
|
|
export async function uploadWeixinLog(params: {
|
|
uploadUrl: string;
|
|
file?: string;
|
|
}): Promise<void> {
|
|
const { uploadUrl, file } = params;
|
|
|
|
const logDir = mainLogDir();
|
|
const rawFile = file ?? currentDayLogFileName();
|
|
const fileName = resolveLogFileName(rawFile);
|
|
const filePath = path.isAbsolute(fileName) ? fileName : path.join(logDir, fileName);
|
|
|
|
let content: Buffer;
|
|
try {
|
|
content = await fs.readFile(filePath);
|
|
} catch (err) {
|
|
throw new Error(`Failed to read log file: ${filePath}: ${String(err)}`);
|
|
}
|
|
|
|
const formData = new FormData();
|
|
formData.append("file", new Blob([new Uint8Array(content)], { type: "text/plain" }), fileName);
|
|
|
|
const res = await fetch(uploadUrl, { method: "POST", body: formData });
|
|
if (!res.ok) {
|
|
const body = await res.text().catch(() => "");
|
|
throw new Error(`Upload failed: HTTP ${res.status} ${res.statusText}: ${body}`);
|
|
}
|
|
} |