UNPKG

feishu-mcp

Version:

Model Context Protocol server for Feishu integration

113 lines (112 loc) 3.83 kB
/** * 从URL或ID中提取飞书文档ID * 支持多种格式: * 1. 标准文档URL: https://xxx.feishu.cn/docs/xxx 或 https://xxx.feishu.cn/docx/xxx * 2. API URL: https://open.feishu.cn/open-apis/docx/v1/documents/xxx * 3. 直接ID: JcKbdlokYoPIe0xDzJ1cduRXnRf * * @param input 文档URL或ID * @returns 提取的文档ID或null */ export function extractDocumentId(input) { // 移除首尾空白 input = input.trim(); // 处理各种URL格式 const docxMatch = input.match(/\/docx\/([a-zA-Z0-9_-]+)/i); const docsMatch = input.match(/\/docs\/([a-zA-Z0-9_-]+)/i); const apiMatch = input.match(/\/documents\/([a-zA-Z0-9_-]+)/i); const directIdMatch = input.match(/^([a-zA-Z0-9_-]{10,})$/); // 假设ID至少10个字符 // 按优先级返回匹配结果 const match = docxMatch || docsMatch || apiMatch || directIdMatch; return match ? match[1] : null; } /** * 从URL或Token中提取Wiki节点ID * 支持多种格式: * 1. Wiki URL: https://xxx.feishu.cn/wiki/xxx * 2. 直接Token: xxx * * @param input Wiki URL或Token * @returns 提取的Wiki Token或null */ export function extractWikiToken(input) { // 移除首尾空白 input = input.trim(); // 处理Wiki URL格式 const wikiMatch = input.match(/\/wiki\/([a-zA-Z0-9_-]+)/i); const directMatch = input.match(/^([a-zA-Z0-9_-]{10,})$/); // 假设Token至少10个字符 // 提取Token,如果存在查询参数,去掉它们 let token = wikiMatch ? wikiMatch[1] : (directMatch ? directMatch[1] : null); if (token && token.includes('?')) { token = token.split('?')[0]; } return token; } /** * 规范化文档ID * 提取输入中的文档ID,如果提取失败则返回原输入 * * @param input 文档URL或ID * @returns 规范化的文档ID * @throws 如果无法提取有效ID则抛出错误 */ export function normalizeDocumentId(input) { const id = extractDocumentId(input); if (!id) { throw new Error(`无法从 "${input}" 提取有效的文档ID`); } return id; } /** * 规范化Wiki Token * 提取输入中的Wiki Token,如果提取失败则返回原输入 * * @param input Wiki URL或Token * @returns 规范化的Wiki Token * @throws 如果无法提取有效Token则抛出错误 */ export function normalizeWikiToken(input) { const token = extractWikiToken(input); if (!token) { throw new Error(`无法从 "${input}" 提取有效的Wiki Token`); } return token; } /** * 根据图片二进制数据检测MIME类型 * @param buffer 图片二进制数据 * @returns MIME类型字符串 */ export function detectMimeType(buffer) { // 简单的图片格式检测,根据文件头进行判断 if (buffer.length < 4) { return 'application/octet-stream'; } // JPEG格式 if (buffer[0] === 0xFF && buffer[1] === 0xD8 && buffer[2] === 0xFF) { return 'image/jpeg'; } // PNG格式 else if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47) { return 'image/png'; } // GIF格式 else if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) { return 'image/gif'; } // SVG格式 - 检查字符串前缀 else if (buffer.length > 5 && buffer.toString('ascii', 0, 5).toLowerCase() === '<?xml' || buffer.toString('ascii', 0, 4).toLowerCase() === '<svg') { return 'image/svg+xml'; } // WebP格式 else if (buffer.length > 12 && buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 && buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50) { return 'image/webp'; } // 默认二进制流 else { return 'application/octet-stream'; } }