mirror of
https://github.com/ckaczor/FeedCenter.git
synced 2026-01-13 17:22:48 -05:00
162 lines
4.5 KiB
C#
162 lines
4.5 KiB
C#
using Common.Debug;
|
|
using System;
|
|
using System.Linq;
|
|
using System.Xml;
|
|
|
|
namespace FeedCenter.FeedParsers
|
|
{
|
|
[Serializable]
|
|
internal class InvalidFeedFormatException : ApplicationException
|
|
{
|
|
internal InvalidFeedFormatException(Exception exception)
|
|
: base(string.Empty, exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
internal abstract class FeedParserBase
|
|
{
|
|
#region Member variables
|
|
|
|
protected readonly Feed Feed;
|
|
|
|
#endregion
|
|
|
|
#region Constructor
|
|
|
|
protected FeedParserBase(Feed feed)
|
|
{
|
|
Feed = feed;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
public abstract FeedReadResult ParseFeed(string feedText);
|
|
|
|
protected abstract FeedItem ParseFeedItem(XmlNode node);
|
|
|
|
protected void HandleFeedItem(XmlNode node, ref int sequence)
|
|
{
|
|
// Build a feed item from the node
|
|
FeedItem newFeedItem = ParseFeedItem(node);
|
|
|
|
if (newFeedItem == null)
|
|
return;
|
|
|
|
// Check for feed items with no guid or link
|
|
if (string.IsNullOrWhiteSpace(newFeedItem.Guid) && string.IsNullOrWhiteSpace(newFeedItem.Link))
|
|
return;
|
|
|
|
// Look for an item that has the same guid
|
|
FeedItem existingFeedItem = Feed.Items.FirstOrDefault(item => item.Guid == newFeedItem.Guid && item.ID != newFeedItem.ID);
|
|
|
|
// Check to see if we already have this feed item
|
|
if (existingFeedItem == null)
|
|
{
|
|
Tracer.WriteLine("New link: " + newFeedItem.Link);
|
|
|
|
// Associate the new item with the right feed
|
|
newFeedItem.Feed = Feed;
|
|
|
|
// Set the item as new
|
|
newFeedItem.New = true;
|
|
|
|
// Add the item to the list
|
|
Feed.Items.Add(newFeedItem);
|
|
|
|
// Feed was updated
|
|
Feed.LastUpdated = DateTime.Now;
|
|
}
|
|
else
|
|
{
|
|
Tracer.WriteLine("Existing link: " + newFeedItem.Link);
|
|
|
|
// Update the fields in the existing item
|
|
existingFeedItem.Link = newFeedItem.Link;
|
|
existingFeedItem.Title = newFeedItem.Title;
|
|
existingFeedItem.Guid = newFeedItem.Guid;
|
|
existingFeedItem.Description = newFeedItem.Description;
|
|
|
|
// Item is no longer new
|
|
existingFeedItem.New = false;
|
|
|
|
// Switch over to the existing item for the rest
|
|
newFeedItem = existingFeedItem;
|
|
}
|
|
|
|
// Item was last seen now
|
|
newFeedItem.LastFound = Feed.LastChecked;
|
|
|
|
// Set the sequence
|
|
newFeedItem.Sequence = sequence;
|
|
|
|
// Increment the sequence
|
|
sequence++;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Parser creation and detection
|
|
|
|
public static FeedParserBase CreateFeedParser(Feed feed, string feedText)
|
|
{
|
|
FeedType feedType = DetectFeedType(feedText);
|
|
|
|
switch (feedType)
|
|
{
|
|
case FeedType.Rss:
|
|
return new RssParser(feed);
|
|
|
|
case FeedType.Rdf:
|
|
return new RdfParser(feed);
|
|
|
|
case FeedType.Atom:
|
|
return new AtomParser(feed);
|
|
}
|
|
|
|
throw new ArgumentException($"Feed type {feedType} is not supported");
|
|
}
|
|
|
|
public static FeedType DetectFeedType(string feedText)
|
|
{
|
|
try
|
|
{
|
|
// Create the XML document
|
|
var document = new XmlDocument { XmlResolver = null };
|
|
|
|
// Load the XML document from the text
|
|
document.LoadXml(feedText);
|
|
|
|
// Loop over all child nodes
|
|
foreach (XmlNode node in document.ChildNodes)
|
|
{
|
|
switch (node.Name)
|
|
{
|
|
case "rss":
|
|
return FeedType.Rss;
|
|
|
|
case "rdf:RDF":
|
|
return FeedType.Rdf;
|
|
|
|
case "feed":
|
|
return FeedType.Atom;
|
|
}
|
|
}
|
|
|
|
// No clue!
|
|
return FeedType.Unknown;
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Tracer.WriteException(exception);
|
|
|
|
return FeedType.Unknown;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|