Skip to main content
Glama

MCP RSS

by ronnycoding
OpmlService.ts3.58 kB
import { XMLParser } from 'fast-xml-parser'; import fs from 'fs'; import path from 'path'; import { Feed } from '../entities/Feed'; import { AppDataSource } from '../config/database'; interface OpmlOutline { text: string; title: string; type?: string; xmlUrl?: string; htmlUrl?: string; outline?: OpmlOutline[]; } export class OpmlService { /** * 解析OPML文件并保存订阅源到数据库 * @param opmlFilePath OPML文件路径 */ async parseAndSaveFeeds(opmlFilePath: string): Promise<void> { try { // 获取绝对路径 const absolutePath = path.isAbsolute(opmlFilePath) ? opmlFilePath : path.join(process.cwd(), opmlFilePath); // console.log(`解析OPML文件: ${absolutePath}`); // 读取OPML文件 const opmlContent = fs.readFileSync(absolutePath, 'utf-8'); // 解析XML const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '', isArray: (name: string, jpath: string) => { if (name === 'outline') return true; return false; }, parseAttributeValue: true }); const result = parser.parse(opmlContent); // 打印解析结果以便调试 // console.log('解析结果:', JSON.stringify(result, null, 2)); // 处理订阅源 if (result.opml && result.opml.body && result.opml.body.outline) { // console.log('找到outline元素:', result.opml.body.outline); await this.processOutlines(result.opml.body.outline); } else { // console.error('OPML文件格式不正确'); } } catch (error) { // console.error('解析OPML文件失败:', error); } } /** * 处理OPML中的outline元素 * @param outlines outline元素数组 * @param parentCategory 父分类 */ private async processOutlines(outlines: OpmlOutline[], parentCategory: string = '', level: number = 0): Promise<void> { const feedRepository = AppDataSource.getRepository(Feed); const indent = ' '.repeat(level); // console.log(`处理${outlines.length}个outline元素`); for (const outline of outlines) { // 打印当前outline的基本信息和属性 // console.log(`${indent}└─ ${outline.title || outline.text || '未命名'}`); // console.log(`${indent} 类型: ${outline.type || '未指定'}`); // console.log(`${indent} RSS URL: ${outline.xmlUrl || '无'}`); // 如果是RSS订阅源 if (outline.type === 'rss' && outline.xmlUrl) { // 检查是否已存在 const existingFeed = await feedRepository.findOne({ where: { url: outline.xmlUrl } }); if (!existingFeed) { // 创建新的订阅源 const feed = new Feed(); feed.title = outline.title || outline.text || '未命名'; feed.url = outline.xmlUrl; feed.htmlUrl = outline.htmlUrl || ''; feed.category = parentCategory; await feedRepository.save(feed); // console.log(`${indent} ├─ RSS URL: ${feed.url}`); // console.log(`${indent} ├─ 网站URL: ${feed.htmlUrl || '未提供'}`); // console.log(`${indent} └─ 分类: ${feed.category || '未分类'}`); } } // 如果是分类 else if (outline.outline) { const categoryName = outline.title || outline.text || ''; await this.processOutlines(outline.outline, categoryName, level + 1); } } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ronnycoding/my_mcp_rss'

If you have feedback or need assistance with the MCP directory API, please join our Discord server