Second commit

This commit is contained in:
beyondx123
2026-07-05 13:22:25 +08:00
parent 991eec8cef
commit 09c79b677b
8 changed files with 6944 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
#!/usr/bin/env node
/**
* 飞书文档复制工具
*
* 功能:
* 1. 读取源飞书文档(wiki/docx)的完整内容
* 2. 在你的飞书账号下创建新文档
* 3. 复制所有文本、格式、图片到新文档
*
* 用法:node feishu-copy.mjs <source_wiki_url> [目标文件夹token]
*
* 示例:
* node feishu-copy.mjs https://xxx.feishu.cn/wiki/ABC123
* node feishu-copy.mjs https://xxx.feishu.cn/wiki/ABC123 fldcnXXXXXXX
*/
import { execSync } from 'child_process';
import { unlinkSync } from 'fs';
import { basename } from 'path';
const argv = process.argv.slice(2);
if (!argv[0] || argv[0] === '--help' || argv[0] === '-h') {
console.log(`
用法:node feishu-copy.mjs <source_url> [目标文件夹token]
参数:
source_url 源文档 URLwiki 或 docx
目标文件夹token 可选,新文档放在指定文件夹下
示例:
node feishu-copy.mjs https://yitanger.feishu.cn/wiki/R9NywV2i9izjuqkPd63cWuafn4g
node feishu-copy.mjs https://yitanger.feishu.cn/wiki/ABC123 fldcnXXXXXXX
`);
process.exit(0);
}
const sourceUrl = argv[0].trim();
const targetFolder = argv[1]?.trim();
console.log('╔════════════════════════════════════════════╗');
console.log('║ 飞书文档复制工具 ║');
console.log('╚════════════════════════════════════════════╝');
console.log(`📎 源文档: ${sourceUrl}\n`);
// ── 1. 解析源文档 token ───────────────────────────────────────────────────────
console.log('🔍 正在解析源文档...');
let obj_token, title;
if (sourceUrl.includes('/wiki/')) {
// wiki → 先解析成 docx token
const nodeInfo = larkJson(`lark-cli wiki +node-get --node-token "${sourceUrl}"`);
if (!nodeInfo.ok) die('获取 wiki 节点失败', nodeInfo);
obj_token = nodeInfo.data.obj_token;
title = nodeInfo.data.title;
} else if (sourceUrl.includes('/docx/') || sourceUrl.match(/[A-Za-z0-9]{20,}/)) {
// docx URL 或直接是 token
obj_token = sourceUrl.match(/[A-Za-z0-9]{20,}/)?.[0] || sourceUrl;
// 先 fetch 一次拿标题
const docInfo = larkJson(`lark-cli docs +fetch --doc ${obj_token} --api-version v2`);
if (!docInfo.ok) die('获取文档失败', docInfo);
title = docInfo.data.document.title || '未命名文档';
} else {
die('不支持的 URL 格式', { url: sourceUrl });
}
console.log(`✅ 标题:${title}`);
console.log(`✅ obj_token${obj_token}\n`);
// ── 2. 导出源文档为 Markdown ─────────────────────────────────────────────────
console.log('📄 正在导出源文档为 Markdown...');
const exportResult = larkJson(
`lark-cli drive +export --token ${obj_token} --doc-type docx --file-extension markdown --output-dir . --overwrite`
);
if (!exportResult.ok) die('导出失败', exportResult);
const mdPath = exportResult.data.saved_path;
const mdFile = basename(mdPath); // 相对文件名,lark-cli 只接受相对路径
console.log(`✅ 已导出(${mdFile}\n`);
// ── 3. 导入为新文档 ──────────────────────────────────────────────────────────
console.log('📝 正在导入为新文档...');
const importCmd = targetFolder
? `lark-cli drive +import --file "@${mdFile}" --type markdown --folder-token ${targetFolder}`
: `lark-cli drive +import --file "@${mdFile}" --type markdown`;
const cwd = process.cwd();
const importResult = larkJson(importCmd, { cwd });
if (!importResult.ok) die('导入失败', importResult);
const newDocToken = importResult.data?.token || importResult.data?.document_id;
if (!newDocToken) die('导入返回异常', importResult);
// 删除临时导出文件
try { unlinkSync(mdPath); } catch {}
console.log(`✅ 新文档已创建并写入内容`);
console.log(`✅ 新文档 token${newDocToken}\n`);
console.log('╔════════════════════════════════════════════╗');
console.log(`║ ✅ 复制完成!`);
console.log(`║ 📄 新文档: https://feishu.cn/docx/${newDocToken}`);
console.log(`║ 💡 图片为飞书链接,需登录后可见`);
console.log('╚════════════════════════════════════════════╝');
// ── helpers ──────────────────────────────────────────────────────────────────
function larkJson(cmd, opts = {}) {
try {
return JSON.parse(execSync(cmd, { encoding: 'utf-8', ...opts }));
} catch (e) {
try { return JSON.parse(e.stderr || e.stdout || '{}'); } catch { return {}; }
}
}
function die(msg, info) {
console.error(`${msg}:`, info?.error?.message || JSON.stringify(info));
process.exit(1);
}