using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Argotic.Common;
using Argotic.Syndication;
using Serilog;
using SharpRss.Models;
namespace SharpRss.Services
{
///
/// Managing syndication feeds and categories.
///
public class SyndicationService
{
public SyndicationService()
{
Log.Information("Constructing SyndicationService...");
Task.Run(async () => await SetupTestCategoriesAndFeedsAsync());
}
public async Task> GetCategoriesAndSyndicationsAsync()
{
HashSet items = new HashSet();
items.UnionWith(await GetCategoriesAsync());
items.UnionWith(await GetUngroupedSyndicationsAsync());
return items;
}
public async Task CreateCategoryAsync(CategoryModel category) =>
await DbAccess.SetCategoryAsync(category);
public async Task> GetCategoriesAsync()
{
HashSet categories = await DbAccess.GetCategoriesAsync();
foreach (CategoryModel catModel in categories)
{
catModel.Syndications = await DbAccess.GetSyndicationsAsync(new[] { catModel.Id });
}
return categories;
}
private async void ForEachCategories(CategoryModel x) => x.Syndications = await DbAccess.GetSyndicationsAsync(new[] { x.Id });
public async Task AddSubscriptionAsync(string url, CategoryModel? category = null)
{
var syndication = SyndicationManager.CreateSyndication(url);
if (!syndication.Fetched)
{
Log.Warning("Failed to fetch syndication feed!");
return false;
}
if (category != null)
syndication.Category = category;
try
{
await DbAccess.SetSyndicationAsync(syndication);
}
catch (Exception e)
{
Log.Error(e,"Error adding syndication: {FeedUrl} to database!", url);
}
return true;
}
public async Task UpdateFeeds()
{
Log.Information("Fetching...");
var feeds = await GetSyndicationsAsync();
}
public async Task> GetSyndicationsAsync(string? categoryId = null) => await DbAccess.GetSyndicationsAsync(categoryId == null ? null : new[]{ categoryId });
public async Task> GetUngroupedSyndicationsAsync() => await DbAccess.GetSyndicationsAsync(new []{""});
public async Task> GetSyndicationItemsAsync(string feedId, string? groupId = null) => await GetSyndicationItemsFromSyndicationsAsync(new[] { feedId }, groupId);
public async Task> GetSyndicationItemsFromSyndicationsAsync(string[] feedIds, string? categoryId = null)
{
var items = await DbAccess.GetSyndicationItemsAsync(feedIds);
return items;
}
private static SyndicationModel FromResource(ISyndicationResource resource)
{
SyndicationModel model = new SyndicationModel();
switch (resource.Format)
{
case SyndicationContentFormat.Rss:
RssFeed rssFeed = (RssFeed)resource;
model.SyndicationType = rssFeed.Format.ToString();
model.Title = rssFeed.Channel.Title;
model.Description = rssFeed.Channel.Description;
model.Copyright = rssFeed.Channel.Copyright;
model.EncodedUrl = rssFeed.Channel.SelfLink.ToString();
model.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty;
model.Language = rssFeed.Channel.Language?.ToString();
break;
case SyndicationContentFormat.Atom:
AtomFeed atomFeed = (AtomFeed)resource;
break;
default:
Log.Information("Syndication implementation missing!");
break;
}
return model;
}
private GenericSyndicationFeed? CreateSyndication(string url)
{
Uri feedUri = new Uri(url);
Log.Verbose("Checking syndication: {FeedUrl}", feedUri.ToString());
if (!SyndicationDiscoveryUtility.UriExists(feedUri))
{
Log.Warning("Syndication: {FeedUri} does not exists!", feedUri.ToString());
return null;
}
Log.Verbose("Fetching syndication: {FeedUrl}", feedUri.ToString());
return GenericSyndicationFeed.Create(new Uri(url));
}
private async Task SetupTestCategoriesAndFeedsAsync()
{
Log.Information("Setting up test data...");
try
{
CategoryModel? newsCategory = await CreateCategoryAsync(new CategoryModel() { Name = "News", Icon = " "});
if (newsCategory != null)
{
await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen", newsCategory);
await AddSubscriptionAsync("https://www.ad.nl/home/rss.xml", newsCategory);
await AddSubscriptionAsync("https://www.nasa.gov/rss/dyn/breaking_news.rss", newsCategory);
await AddSubscriptionAsync("http://news.google.com/?output=atom", newsCategory);
}
CategoryModel? techCategory = await CreateCategoryAsync(new CategoryModel() { Name = "Tech", Icon = " "});
if (techCategory != null)
{
await AddSubscriptionAsync("https://itsfoss.com/feed", techCategory);
await AddSubscriptionAsync("http://fedoramagazine.org/feed/", techCategory);
await AddSubscriptionAsync("https://arstechnica.com/feed/", techCategory);
await AddSubscriptionAsync("https://feeds.arstechnica.com/arstechnica/gadgets", techCategory);
}
CategoryModel? youtubeCategory = await CreateCategoryAsync(new CategoryModel() { Name = "YouTube", Icon = " "});
if (youtubeCategory != null)
{
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCXuqSBlHAE6Xw-yeJA0Tunw", youtubeCategory);
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UC1Et9K-hHf-P_LzQkE_Q3Jw", youtubeCategory);
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCsXVk37bltHxD1rDPwtNM8Q", youtubeCategory);
}
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/feed/");
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/agenda/feed/");
await AddSubscriptionAsync("https://feeds.rijksoverheid.nl/nieuws.rss");
await AddSubscriptionAsync("https://nl.wikipedia.org/w/index.php?title=Speciaal:RecenteWijzigingen&feed=atom");
await AddSubscriptionAsync("https://feeds.aivd.nl/nieuws.rss");
await AddSubscriptionAsync("https://blogs.microsoft.com/feed");
await AddSubscriptionAsync("https://www.europarl.europa.eu/rss/doc/top-stories/nl.xml");
}
catch (Exception e)
{
Log.Error(e, "Exception!");
}
}
}
}