DRSS

Ugly RSS interface for D.
git clone git://xatko.vsos.ethz.ch/DRSS.git
Log | Files | Refs | Submodules

commit 822f344cf44ac0990d76c35262c41dc90c8248ca
parent 5844326c2854de51f0fa5060c54b4f170772b893
Author: Dominik Schmidt <das1993@hotmail.com>
Date:   Wed,  9 Sep 2015 19:14:16 +0200

Documentation!

Diffstat:
drss/render.d | 18++++++++++++++++++
drss/rss.d | 117++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 134 insertions(+), 1 deletion(-)

diff --git a/drss/render.d b/drss/render.d @@ -1,3 +1,4 @@ +/// Generate an RSS-Feed out of an DRSS-Class module drss.render; import kxml.xml; import drss.rss; @@ -6,6 +7,14 @@ import std.range; public alias DRSS_Header=Tuple!(string, string); +/** + * Interprets the header and generates the template for the atom-feed + * + * Params: + * h=The header-tuple + * Returns: + * The XmlNode to the root-node of an valid atom-feed + */ XmlNode getRSSRoot(DRSS_Header h[]){ XmlNode rss = new XmlNode("feed"); rss.setAttribute("xmlns","http://www.w3.org/2005/Atom"); @@ -15,6 +24,15 @@ XmlNode getRSSRoot(DRSS_Header h[]){ return rss; } +/** + * Generates a full-blown Atom-XML-Tree corresponding to rss. + * + * Params: + * rss = The feed + * h = The extra headers to add to the feed + * Returns: + * An XmlNode pointing to a Atom-Document. + */ XmlNode generateRSS(T)(DRSS!(T) rss, DRSS_Header h[]){ XmlNode root = getRSSRoot(h); foreach(ref T p; rss.entries){ diff --git a/drss/rss.d b/drss/rss.d @@ -7,22 +7,37 @@ import std.algorithm; import std.string; import std.range; import kxml.xml; + +/** + * A basic Entry-type. + * + * If it is sufficient, you don't have to define your own... + */ struct Entry{ + ///Content-Type of the entry. enum Type{ HTML, Plain } static immutable string[] TypeTable=[Type.HTML:"html", Type.Plain:"text"]; + ///The Content-type of this entry. Type type; + ///The ID of the entry string id; + ///The raw content to be displayed either as HTML or Plain-text (Depending on type) string content; + ///The publishdate of the entry SysTime date; + ///Compares according to the publishdate int opCmp(inout ref Entry b) const{ return date.opCmp(b.date); } + ///ditto int opCmp(inout Entry b) const{ return date.opCmp(b.date); } + + ///Generates a atom-xmlnode for the entry XmlNode toXML(){ XmlNode e=new XmlNode("entry"); e.addChild(new XmlNode("id").addCData(id)); @@ -32,34 +47,96 @@ struct Entry{ } } +/** + * The main RSS-Class. + * + * Its template-parameter is to specify the entry-type, which is of + * Type drss.rss.Entry by default. + * + */ abstract class DRSS(T=Entry){ private string lastUpdated; SList!(T) entries; uint new_entries=0; + /** + * Determines wether the date set by parse is reliable or not. + * + * This has an impact in adding it to the entry-list entries. + * + */ enum DateReliable{ + ///Always iterate through the entries and check if the ID exists NO, + ///Only iterate through the entries and check if the ID exists, if the new entry is newer than the newest old one SEMI, //If entry is newer, check the id additionally. + ///Never iterate through the entries to check if the ID exists YES }; + /// DateReliable date_reliability=DateReliable.SEMI; + ///At what point shall the entries be discarded. uint max_entries=100; uint entry_count=0; HTTP http; ubyte buffer[]; + /** + * Parse a raw document. + * + * This function should extract the Posts from document and add + * them using addEntry + * --- + * override void parse(string document){ + * foreach(Entry e; splitDocumentIntoEntries(document)){ + * this.addEntry(e); + * } + * } + * --- + * + */ abstract void parse(string document); - + + /** + * Initialize the Feed by url + * Params: + * url = The url to fetch the raw-data from + */ this(string url){ auto h=HTTP(); h.url=url; this(h); } + /** + * Initialize the feed by a custom HTTP-request + * + * This allows for things like: + * --- + * this(){ + * auto h=HTTP(); + * h.url="http://herp.derp/rss.xml"; + * h.setUserAgent("MyCustomUserAgent 1.0"); + * super(h); + * } + * --- + * Params: + * http = The http-request to execute when updateing + */ this(HTTP http){ this.http=http; this.http.onReceive = &addContent; this.http.onReceiveHeader = &parseHeader; } + /** + * Check if the entry newent is new. + * Operation depends on the value of date_reliability. + * $(SEE_ALSO enum DateReliable) + * + * Params: + * newent = the entry to check + * Returns: + * false if the entry is already in entries, true otherwise + */ private bool checkIfNewEntry(in ref T newent){ if(entries.empty){ return true; @@ -82,6 +159,15 @@ abstract class DRSS(T=Entry){ return false; } + /** + * Add an entry to the list. + * + * Params: + * newent = The entry to add + * Returns: + * true if the entry was added, false otherwise. + * + */ bool addEntry(T newent){ if(checkIfNewEntry(newent)){ entries.insertFront(newent); @@ -94,6 +180,21 @@ abstract class DRSS(T=Entry){ } } + /** + * Updates the whole stream. + * + * $(OL + * $(LI Calls `fetch();`, if document is null) + * $(LI Passes the result to `update();`) + * $(LI Discards the old Entries with `removeOldEntries();` + * ) + * + * Params: + * document = The document to parse or null, to fetch it. + * Returns: + * true if the feed has new entries. + * + */ final bool update(ubyte document[]=null){ if(document is null){ if(!fetch()){ @@ -112,10 +213,14 @@ abstract class DRSS(T=Entry){ return (new_entries>0); } + ///Return the total count of entries @property size_t length(){ return entry_count; } + /** + * Removes every entry older than the max_entries newest. + */ private void removeOldEntries(){ auto r=entries[]; auto i=max_entries; @@ -127,22 +232,32 @@ abstract class DRSS(T=Entry){ } } + ///Returns a range with the new entries since the last call to update() @property auto news(){ return entries[].take(new_entries); } + ///Sets the new entries since the last call to update to 0. public void discardNews(){ new_entries=0; } + private void parseHeader(in char[] key, in char[] value){ if(key=="date"){ lastUpdated=value.dup; } } + private auto addContent(ubyte[]data){ buffer~=data; return data.length; } + /** + * Fetches the document and saves it internally. + * + * Returns: + * true if upstream reports to have new entries, false otherwise + */ public bool fetch(){ debug(RSS) writeln("Updateing"); if(lastUpdated.length!=0){