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