2023-05-20 00:04:45 +02:00
|
|
|
using System;
|
2023-05-18 01:27:11 +02:00
|
|
|
using System.Collections.Generic;
|
2023-05-18 20:15:31 +02:00
|
|
|
using System.Linq;
|
2023-05-18 01:27:11 +02:00
|
|
|
using System.Threading.Tasks;
|
2023-05-18 20:15:31 +02:00
|
|
|
using CodeHollow.FeedReader;
|
2023-05-22 15:55:21 +02:00
|
|
|
using Serilog;
|
2023-05-18 01:27:11 +02:00
|
|
|
using SharpRss.Models;
|
|
|
|
|
|
|
|
namespace SharpRss.Services
|
|
|
|
{
|
|
|
|
/// <summary>
|
2023-05-22 15:55:21 +02:00
|
|
|
/// Managing RSS feeds and groups.
|
2023-05-18 01:27:11 +02:00
|
|
|
/// </summary>
|
2023-05-19 14:40:57 +02:00
|
|
|
public class RssService : IDisposable
|
2023-05-18 01:27:11 +02:00
|
|
|
{
|
|
|
|
public RssService()
|
|
|
|
{
|
2023-05-23 15:04:02 +02:00
|
|
|
//SetupTestCategoriesAndFeedsAsync();
|
2023-05-18 01:27:11 +02:00
|
|
|
}
|
2023-05-18 20:15:31 +02:00
|
|
|
private readonly DatabaseService _dbService = new DatabaseService();
|
2023-05-23 15:04:02 +02:00
|
|
|
|
|
|
|
public async Task<HashSet<object>> GetItemsAsync()
|
|
|
|
{
|
|
|
|
HashSet<object> items = new HashSet<object>();
|
|
|
|
items.UnionWith(await GetGroupsAsync());
|
|
|
|
items.UnionWith(await GetUngroupedFeedsAsync());
|
|
|
|
return items;
|
|
|
|
}
|
2023-05-22 19:09:01 +02:00
|
|
|
public async Task<bool> CreateGroupAsync(GroupModel group) => await _dbService.SetGroupAsync(group);
|
2023-05-22 15:55:21 +02:00
|
|
|
public async Task<HashSet<GroupModel>> GetGroupsAsync() => await _dbService.GetGroupsAsync();
|
|
|
|
|
|
|
|
public async Task<bool> AddFeed(string rssUrl, GroupModel? group = null)
|
|
|
|
{
|
|
|
|
bool result = false;
|
|
|
|
Feed fetched = await FetchFeed(rssUrl);
|
2023-05-22 19:09:01 +02:00
|
|
|
|
2023-05-22 15:55:21 +02:00
|
|
|
if (fetched == null)
|
|
|
|
return result;
|
|
|
|
FeedModel feedModel = new FeedModel(rssUrl)
|
|
|
|
{
|
2023-05-22 19:09:01 +02:00
|
|
|
Title = fetched.Title,
|
|
|
|
GroupId = group?.Id ?? string.Empty,
|
2023-05-22 15:55:21 +02:00
|
|
|
FeedType = fetched.Type.ToString(),
|
|
|
|
Description = fetched.Description,
|
|
|
|
Language = fetched.Language,
|
|
|
|
Copyright = fetched.Copyright,
|
|
|
|
DateAdded = DateTimeOffset.Now,
|
|
|
|
LastUpdated = DateTimeOffset.Now,
|
|
|
|
ImageUrl = fetched.ImageUrl,
|
2023-05-22 19:09:01 +02:00
|
|
|
OriginalDocument = fetched.OriginalDocument
|
2023-05-22 15:55:21 +02:00
|
|
|
};
|
|
|
|
result = await _dbService.SetFeedAsync(feedModel);
|
|
|
|
if (!result)
|
|
|
|
return result;
|
|
|
|
if (await AddFeedItems(fetched.Items, feedModel) == 0)
|
2023-05-22 19:09:01 +02:00
|
|
|
Log.Warning("No feed items added to feed: {FeedUrl}", feedModel.Url);
|
2023-05-22 15:55:21 +02:00
|
|
|
return result;
|
|
|
|
}
|
2023-05-23 15:04:02 +02:00
|
|
|
public async Task<HashSet<FeedModel>> GetFeedsAsync(GroupModel? group = null) => await _dbService.GetFeedsAsync(group?.Id);
|
|
|
|
public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await _dbService.GetFeedsAsync("");
|
2023-05-22 15:55:21 +02:00
|
|
|
private async Task<int> AddFeedItems(IList<FeedItem> items, FeedModel feedModel)
|
|
|
|
{
|
|
|
|
int result = 0;
|
|
|
|
if (!items.Any())
|
|
|
|
return result;
|
|
|
|
HashSet<FeedItemModel> itemModels = new HashSet<FeedItemModel>();
|
|
|
|
foreach (FeedItem item in items)
|
|
|
|
{
|
|
|
|
itemModels.Add(new FeedItemModel()
|
|
|
|
{
|
|
|
|
Id = item.Id,
|
|
|
|
FeedId = feedModel.Id,
|
|
|
|
Title = item.Title,
|
|
|
|
Description = item.Description,
|
|
|
|
Link = item.Link,
|
|
|
|
LastUpdated = DateTimeOffset.Now,
|
|
|
|
PublishingDate = item.PublishingDate != null ? new DateTimeOffset((DateTime)item.PublishingDate) : null,
|
|
|
|
Author = item.Author,
|
|
|
|
Categories = item.Categories.ToArray(),
|
|
|
|
Content = item.Content
|
|
|
|
});
|
|
|
|
}
|
|
|
|
result = await _dbService.SetFeedItemsAsync(itemModels);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
private async Task<Feed> FetchFeed(string url)
|
|
|
|
{
|
|
|
|
var urls = await FeedReader.ParseFeedUrlsAsStringAsync(url);
|
|
|
|
string feedurl = url;
|
|
|
|
if (urls.Any())
|
|
|
|
feedurl = urls.First();
|
|
|
|
return await FeedReader.ReadAsync(feedurl);
|
|
|
|
}
|
2023-05-21 21:56:37 +02:00
|
|
|
private async void SetupTestCategoriesAndFeedsAsync()
|
2023-05-18 01:27:11 +02:00
|
|
|
{
|
2023-05-22 19:09:01 +02:00
|
|
|
var groupRes = await CreateGroupAsync(new GroupModel() { Name = "Test" });
|
|
|
|
groupRes = await CreateGroupAsync(new GroupModel() { Name = "News" });
|
|
|
|
groupRes = await CreateGroupAsync(new GroupModel() { Name = "Tech" });
|
|
|
|
groupRes = await CreateGroupAsync(new GroupModel() { Name = "Science" });
|
2023-05-22 15:55:21 +02:00
|
|
|
var groups = await GetGroupsAsync();
|
|
|
|
GroupModel testGroup = groups.Single(x => x.Name == "Test");
|
|
|
|
var res = await AddFeed("http://fedoramagazine.org/feed/", testGroup);
|
|
|
|
res = await AddFeed("https://www.nasa.gov/rss/dyn/breaking_news.rss", testGroup);
|
|
|
|
res = await AddFeed("https://journals.plos.org/plosone/feed/atom", testGroup);
|
|
|
|
res = await AddFeed("https://itsfoss.com/feed", testGroup);
|
2023-05-18 01:27:11 +02:00
|
|
|
}
|
2023-05-19 14:40:57 +02:00
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
{
|
|
|
|
_dbService.Dispose();
|
|
|
|
}
|
|
|
|
}
|
2023-05-18 01:27:11 +02:00
|
|
|
}
|