systemprompt_generator/rss/
xml.rs1use chrono::{DateTime, Utc};
7
8#[derive(Debug, Clone)]
9pub struct RssItem {
10 pub title: String,
11 pub link: String,
12 pub description: String,
13 pub pub_date: DateTime<Utc>,
14 pub guid: String,
15 pub author: Option<String>,
16}
17
18#[derive(Debug, Clone)]
19pub struct RssChannel {
20 pub title: String,
21 pub link: String,
22 pub description: String,
23 pub items: Vec<RssItem>,
24}
25
26fn escape_xml(s: &str) -> String {
27 s.replace('&', "&")
28 .replace('<', "<")
29 .replace('>', ">")
30 .replace('"', """)
31 .replace('\'', "'")
32}
33
34fn format_rfc2822(dt: &DateTime<Utc>) -> String {
35 dt.format("%a, %d %b %Y %H:%M:%S +0000").to_string()
36}
37
38pub fn build_rss_xml(channel: &RssChannel) -> String {
39 let mut xml = String::with_capacity(8192);
40
41 xml.push_str(r#"<?xml version="1.0" encoding="UTF-8"?>"#);
42 xml.push('\n');
43 xml.push_str(r#"<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">"#);
44 xml.push('\n');
45 xml.push_str("<channel>\n");
46
47 xml.push_str(&format!(
48 " <title>{}</title>\n",
49 escape_xml(&channel.title)
50 ));
51 xml.push_str(&format!(" <link>{}</link>\n", escape_xml(&channel.link)));
52 xml.push_str(&format!(
53 " <description>{}</description>\n",
54 escape_xml(&channel.description)
55 ));
56 xml.push_str(&format!(
57 r#" <atom:link href="{}/feed.xml" rel="self" type="application/rss+xml"/>"#,
58 escape_xml(&channel.link)
59 ));
60 xml.push('\n');
61
62 for item in &channel.items {
63 xml.push_str(" <item>\n");
64 xml.push_str(&format!(" <title>{}</title>\n", escape_xml(&item.title)));
65 xml.push_str(&format!(" <link>{}</link>\n", escape_xml(&item.link)));
66 xml.push_str(&format!(
67 " <description>{}</description>\n",
68 escape_xml(&item.description)
69 ));
70 xml.push_str(&format!(
71 " <pubDate>{}</pubDate>\n",
72 format_rfc2822(&item.pub_date)
73 ));
74 xml.push_str(&format!(
75 " <guid isPermaLink=\"true\">{}</guid>\n",
76 escape_xml(&item.guid)
77 ));
78 if let Some(ref author) = item.author {
79 xml.push_str(&format!(" <author>{}</author>\n", escape_xml(author)));
80 }
81 xml.push_str(" </item>\n");
82 }
83
84 xml.push_str("</channel>\n");
85 xml.push_str("</rss>\n");
86
87 xml
88}