diff --git a/Application/FeedCenter.csproj b/Application/FeedCenter.csproj
index 789e79a..e31cf55 100644
--- a/Application/FeedCenter.csproj
+++ b/Application/FeedCenter.csproj
@@ -157,6 +157,10 @@
..\packages\EntityFramework.SqlServerCompact.6.1.1\lib\net45\EntityFramework.SqlServerCompact.dll
+
+ ..\packages\HtmlAgilityPack.1.4.9\lib\Net45\HtmlAgilityPack.dll
+ True
+
diff --git a/Application/FeedParsers/FeedParserBase.cs b/Application/FeedParsers/FeedParserBase.cs
index b95e7f4..86b7583 100644
--- a/Application/FeedParsers/FeedParserBase.cs
+++ b/Application/FeedParsers/FeedParserBase.cs
@@ -119,7 +119,7 @@ namespace FeedCenter.FeedParsers
throw new ArgumentException($"Feed type {feedType} is not supported");
}
- private static FeedType DetectFeedType(string feedText)
+ public static FeedType DetectFeedType(string feedText)
{
try
{
@@ -150,7 +150,9 @@ namespace FeedCenter.FeedParsers
}
catch (Exception exception)
{
- throw new InvalidFeedFormatException(exception);
+ Tracer.WriteException(exception);
+
+ return FeedType.Unknown;
}
}
diff --git a/Application/Feeds/Feed.cs b/Application/Feeds/Feed.cs
index 9b709d4..fff032c 100644
--- a/Application/Feeds/Feed.cs
+++ b/Application/Feeds/Feed.cs
@@ -99,6 +99,18 @@ namespace FeedCenter
return await Task.Run(() => Read(database, forceRead));
}
+ public Tuple DetectFeedType()
+ {
+ var retrieveResult = RetrieveFeed();
+
+ if (retrieveResult.Item1 != FeedReadResult.Success)
+ {
+ return new Tuple(FeedType.Unknown, string.Empty);
+ }
+
+ return new Tuple(FeedParserBase.DetectFeedType(retrieveResult.Item2), retrieveResult.Item2);
+ }
+
private Tuple RetrieveFeed()
{
try
diff --git a/Application/MainWindow.xaml.cs b/Application/MainWindow.xaml.cs
index 511628c..ab54f9d 100644
--- a/Application/MainWindow.xaml.cs
+++ b/Application/MainWindow.xaml.cs
@@ -10,6 +10,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
+using System.Net;
using System.Threading;
using System.Web.UI;
using System.Windows;
@@ -17,11 +18,14 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
+using Common.Internet;
namespace FeedCenter
{
public partial class MainWindow
{
+ private readonly string[] _chromeExtensions = { "chrome-extension://ehojfdcmnajoklleckniaifaijfnkpbi/subscribe.html?", "chrome-extension://nlbjncdgjeocebhnmkbbbdekmmmcbfjd/subscribe.html?" };
+
#region Member variables
private int _feedIndex;
@@ -354,7 +358,7 @@ namespace FeedCenter
OpenAllToolbarButton.IsEnabled = (feedCount > 0);
MarkReadToolbarButton.IsEnabled = (feedCount > 0);
FeedLabel.Visibility = (feedCount == 0 ? Visibility.Hidden : Visibility.Visible);
- FeedButton.Visibility = (feedCount > 1 ? Visibility.Hidden : Visibility.Visible);
+ FeedButton.Visibility = (feedCount > 1 ? Visibility.Hidden : Visibility.Visible);
}
private void InitializeFeed()
@@ -788,6 +792,37 @@ namespace FeedCenter
feed.Source = feedUrl;
feed.Category = _database.DefaultCategory;
+ // Try to detect the feed type
+ var feedTypeResult = feed.DetectFeedType();
+
+ // If we can't figure it out it could be an HTML page
+ if (feedTypeResult.Item1 == FeedType.Unknown)
+ {
+ // Only check if the feed was able to be read - otherwise fall through and show the dialog
+ if (feedTypeResult.Item2.Length > 0)
+ {
+ // Create and load an HTML document with the text
+ var htmlDocument = new HtmlAgilityPack.HtmlDocument();
+ htmlDocument.LoadHtml(feedTypeResult.Item2);
+
+ // Look for all RSS or atom links in the document
+ var rssLinks = htmlDocument.DocumentNode.Descendants("link")
+ .Where(n => n.Attributes["type"] != null && (n.Attributes["type"].Value == "application/rss+xml" || n.Attributes["type"].Value == "application/atom+xml"))
+ .Select(n => UrlHelper.GetAbsoluteUrlString(feed.Source, n.Attributes["href"].Value))
+ .ToArray();
+
+ // If there was only one link found then switch to feed to it
+ if (rssLinks.Length == 1)
+ {
+ feed.Source = rssLinks[0];
+ }
+ else
+ {
+ // TODO - show dialog to choose feed
+ }
+ }
+ }
+
// Read the feed for the first time
var feedReadResult = feed.Read(_database);
@@ -899,6 +934,16 @@ namespace FeedCenter
// Get the data as a string
var data = (string) e.Data.GetData(DataFormats.Text);
+ // Check to see if the data starts with any known Chrome extension
+ var chromeExtension = _chromeExtensions.FirstOrDefault(c => data.StartsWith(c));
+
+ // Remove the Chrome extension URL and decode the URL
+ if (chromeExtension != null)
+ {
+ data = data.Substring(chromeExtension.Length);
+ data = WebUtility.UrlDecode(data);
+ }
+
// Handle the new feed but allow the drag/drop to complete
Dispatcher.BeginInvoke(new NewFeedDelegate(HandleNewFeed), data);
}
@@ -981,13 +1026,13 @@ namespace FeedCenter
// Create a menu item
var menuItem = new MenuItem
- {
- Header = display,
- Tag = feed,
+ {
+ Header = display,
+ Tag = feed,
- // Set the current item to bold
- FontWeight = feed == _currentFeed ? FontWeights.Bold : FontWeights.Normal
- };
+ // Set the current item to bold
+ FontWeight = feed == _currentFeed ? FontWeights.Bold : FontWeights.Normal
+ };
// Handle the click
@@ -1046,12 +1091,12 @@ namespace FeedCenter
var screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle);
var rectangle = new System.Drawing.Rectangle
- {
- X = (int) Left,
- Y = (int) Top,
- Width = (int) Width,
- Height = (int) Height
- };
+ {
+ X = (int) Left,
+ Y = (int) Top,
+ Width = (int) Width,
+ Height = (int) Height
+ };
var borderThickness = new Thickness();
diff --git a/Application/packages.config b/Application/packages.config
index 019450a..503c402 100644
--- a/Application/packages.config
+++ b/Application/packages.config
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/Setup/Product.wxs b/Setup/Product.wxs
index 6032891..194ee96 100644
--- a/Setup/Product.wxs
+++ b/Setup/Product.wxs
@@ -175,6 +175,8 @@
+
+