1 module vibelog.rss; 2 3 import vibe.core.stream; 4 import vibe.inet.message : toRFC822DateTimeString; 5 6 import std.datetime; 7 8 9 final class RssFeed { 10 RssChannel[] channels; 11 12 void render(OutputStream)(OutputStream dst) 13 if (isOutputStream!OutputStream) 14 { 15 dst.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"); 16 dst.write("<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n"); 17 foreach( ch; channels ) 18 ch.render(dst); 19 dst.write("</rss>\n"); 20 dst.flush(); 21 } 22 } 23 24 final class RssChannel { 25 string title; 26 string link; 27 string webLink; 28 string description; 29 string language = "en-us"; 30 string copyright; 31 SysTime pubDate; 32 33 string imageTitle; 34 string imageUrl; 35 string imageLink; 36 37 RssEntry[] entries; 38 39 void render(OutputStream)(OutputStream dst) 40 if (isOutputStream!OutputStream) 41 { 42 dst.write("\t<channel>\n"); 43 dst.write("\t\t<title>"); dst.write(title); dst.write("</title>\n"); 44 dst.write("\t\t<link>"); dst.write(link); dst.write("</link>\n"); 45 dst.write("\t\t<atom:link href=\""); dst.write(link); dst.write("feed/rss\" rel=\"self\" type=\"application/rss+xml\" />\n"); 46 dst.write("\t\t<description>"); dst.write(description); dst.write("</description>\n"); 47 dst.write("\t\t<language>"); dst.write(language); dst.write("</language>\n"); 48 dst.write("\t\t<copyright>"); dst.write(copyright); dst.write("</copyright>\n"); 49 dst.write("\t\t<pubDate>"); dst.write(toRFC822DateTimeString(pubDate)); dst.write("</pubDate>\n"); 50 if( imageUrl.length ){ 51 dst.write("\t\t<image>\n"); 52 dst.write("\t\t\t<url>"); dst.write(imageUrl); dst.write("</url>\n"); 53 dst.write("\t\t\t<title>"); dst.write(imageTitle); dst.write("</title>\n"); 54 dst.write("\t\t\t<link>"); dst.write(imageLink); dst.write("</link>\n"); 55 dst.write("\t\t</image>\n"); 56 } 57 foreach( e; entries ) 58 e.render(dst); 59 dst.write("\t</channel>\n"); 60 } 61 } 62 63 final class RssEntry { 64 string title; 65 string description; 66 string link; 67 string language = "en-us"; 68 string author; 69 string guid; 70 SysTime pubDate; 71 72 void render(OutputStream)(OutputStream dst) 73 if (isOutputStream!OutputStream) 74 { 75 import vibe.textfilter.html : htmlEscape; 76 77 dst.write("\t\t<item>\n"); 78 dst.write("\t\t\t<title>"); dst.write(title); dst.write("</title>\n"); 79 dst.write("\t\t\t<description>"); dst.write(description); dst.write("</description>\n"); 80 dst.write("\t\t\t<link>"); dst.write(link); dst.write("</link>\n"); 81 dst.write("\t\t\t<author>"); dst.write(htmlEscape(author)); dst.write("</author>\n"); 82 dst.write("\t\t\t<guid isPermaLink=\"false\">"); dst.write(guid); dst.write("</guid>\n"); 83 dst.write("\t\t\t<pubDate>"); dst.write(toRFC822DateTimeString(pubDate)); dst.write("</pubDate>\n"); 84 dst.write("\t\t</item>\n"); 85 } 86 }