Последняя активность 5 hours ago

Astro-theme-fuwari的Ech0说说获取参数

Allen2030 ревизий этого фрагмента 5 hours ago. К ревизии

1 file changed, 150 insertions

ech0-api.ts(файл создан)

@@ -0,0 +1,150 @@
1 + // Ech0 API 工具函数
2 +
3 + interface EssayData {
4 + id: number;
5 + content: string;
6 + time: string;
7 + tags: string[];
8 + images?: string[];
9 + }
10 +
11 + /**
12 + * 从Ech0 RSS获取动态数据
13 + * @param apiUrl Ech0 API地址
14 + * @returns 转换后的动态数据数组
15 + */
16 + export async function fetchEch0Posts(apiUrl: string): Promise<EssayData[]> {
17 + try {
18 + const response = await fetch(`${apiUrl}/rss`);
19 +
20 + if (!response.ok) {
21 + throw new Error(`Failed to fetch Ech0 posts: ${response.status}`);
22 + }
23 +
24 + const xmlText = await response.text();
25 + return parseRssData(xmlText);
26 + } catch (error) {
27 + console.error('Error fetching Ech0 posts:', error);
28 + // 出错时返回空数组,避免页面崩溃
29 + return [];
30 + }
31 + }
32 +
33 + /**
34 + * 解析RSS XML数据
35 + * @param xmlText RSS XML文本
36 + * @returns 转换后的动态数据数组
37 + */
38 + function parseRssData(xmlText: string): EssayData[] {
39 + // 使用正则表达式解析RSS数据,避免使用DOMParser(浏览器特有API)
40 + const entryRegex = /<entry>([\s\S]*?)<\/entry>/g;
41 + const entries: EssayData[] = [];
42 + let match;
43 +
44 + let index = 0;
45 + while ((match = entryRegex.exec(xmlText)) !== null) {
46 + const entryText = match[1];
47 + index++;
48 +
49 + // 提取更新时间
50 + const updatedRegex = /<updated>([\s\S]*?)<\/updated>/;
51 + const updatedMatch = entryText.match(updatedRegex);
52 + const updated = updatedMatch ? updatedMatch[1] : '';
53 +
54 + // 提取摘要(使用更宽松的正则表达式,支持换行符)
55 + const summaryRegex = /<summary[^>]*>([\s\S]*?)<\/summary>/i;
56 + const summaryMatch = entryText.match(summaryRegex);
57 + const summary = summaryMatch ? summaryMatch[1] : '';
58 +
59 + // 提取纯文本内容
60 + const content = extractPlainText(summary);
61 +
62 + // 提取图片
63 + const images = extractImages(summary);
64 +
65 + entries.push({
66 + id: index,
67 + content,
68 + time: formatDate(updated),
69 + tags: ['生活'], // 默认标签
70 + images: images.length > 0 ? images : undefined
71 + });
72 + }
73 +
74 + // 按ID倒序排列
75 + return entries.sort((a, b) => b.id - a.id);
76 + }
77 +
78 + /**
79 + * 从HTML中提取纯文本
80 + * @param html HTML文本
81 + * @returns 纯文本
82 + */
83 + function extractPlainText(html: string): string {
84 + // 解码HTML实体
85 + let decodedHtml = html
86 + .replace(/&lt;/g, '<')
87 + .replace(/&gt;/g, '>')
88 + .replace(/&amp;/g, '&')
89 + .replace(/&quot;/g, '"')
90 + .replace(/&#34;/g, '"')
91 + .replace(/&#39;/g, "'")
92 + .replace(/&#xA;/g, '\n');
93 +
94 + // 使用正则表达式移除HTML标签
95 + let plainText = decodedHtml.replace(/<[^>]*>/g, '').trim();
96 +
97 + // 如果纯文本为空,说明可能是纯图片的说说,返回一个占位符
98 + return plainText || '[图片]';
99 + }
100 +
101 + /**
102 + * 从HTML中提取图片URL
103 + * @param html HTML文本
104 + * @returns 图片URL数组
105 + */
106 + function extractImages(html: string): string[] {
107 + console.log('原始HTML:', html);
108 +
109 + // 解码HTML实体
110 + let decodedHtml = html
111 + .replace(/&lt;/g, '<')
112 + .replace(/&gt;/g, '>')
113 + .replace(/&amp;/g, '&')
114 + .replace(/&quot;/g, '"')
115 + .replace(/&#34;/g, '"')
116 + .replace(/&#39;/g, "'");
117 +
118 + console.log('解码后HTML:', decodedHtml);
119 +
120 + // 使用更宽松的正则表达式提取图片URL
121 + const imgRegex = /<img[^>]*src=["']([^"']+)["']/gi;
122 + const images: string[] = [];
123 + let match;
124 +
125 + while ((match = imgRegex.exec(decodedHtml)) !== null) {
126 + let url = match[1];
127 + console.log('找到图片URL:', url);
128 +
129 + // 将HTTP URL转换为HTTPS
130 + if (url.startsWith('http://')) {
131 + url = url.replace('http://', 'https://');
132 + console.log('转换为HTTPS:', url);
133 + }
134 +
135 + images.push(url);
136 + }
137 +
138 + console.log('最终图片数组:', images);
139 + return images;
140 + }
141 +
142 + /**
143 + * 格式化日期
144 + * @param dateString ISO日期字符串
145 + * @returns YYYY-MM-DD格式的日期字符串
146 + */
147 + function formatDate(dateString: string): string {
148 + const date = new Date(dateString);
149 + return date.toISOString().split('T')[0];
150 + }
Новее Позже