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){