mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
Implenting rssservice
This commit is contained in:
parent
f83b4451a7
commit
29f9abd5de
|
@ -4,12 +4,7 @@ namespace SharpRss.Models
|
|||
{
|
||||
public class FeedItemModel
|
||||
{
|
||||
public FeedItemModel()
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
LastUpdated = DateTime.Now;
|
||||
}
|
||||
public string Id { get; set; }
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string? FeedId { get; set; }
|
||||
public bool Read { get; set; }
|
||||
public string Type { get; set; } = string.Empty;
|
||||
|
|
|
@ -4,20 +4,23 @@ namespace SharpRss.Models
|
|||
{
|
||||
public class FeedModel
|
||||
{
|
||||
public FeedModel() { }
|
||||
public FeedModel(string rssUrl)
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
Url = rssUrl;
|
||||
Id = Guid.NewGuid().ToString();
|
||||
Copyright = "EMPTY";
|
||||
ImageUrl = "EMPTY";
|
||||
}
|
||||
public string Id { get; set; }
|
||||
public string Url { get; set; }
|
||||
public string Id { get; set; } = string.Empty;
|
||||
public string Url { get; set; } = string.Empty;
|
||||
public string? GroupId { get; set; }
|
||||
public string FeedType { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
public string Language { get; set; } = string.Empty;
|
||||
public string Copyright { get; set; } = string.Empty;
|
||||
public string Copyright { get; set; } = "EMPTY";
|
||||
public DateTimeOffset DateAdded { get; set; }
|
||||
public DateTimeOffset LastUpdated { get; set; }
|
||||
public string ImageUrl { get; set; } = string.Empty;
|
||||
public string ImageUrl { get; set; } = "EMPTY";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace SharpRss.Services
|
|||
private readonly string _feedTable = "feed_data";
|
||||
private readonly string _feedItemTable = "feed_item_data";
|
||||
|
||||
// Group
|
||||
public async Task<HashSet<GroupModel?>> GetGroupsAsync(string? groupName = null)
|
||||
// Groups
|
||||
public async Task<HashSet<GroupModel>> GetGroupsAsync(string? groupName = null)
|
||||
{
|
||||
_sqlConn.Open();
|
||||
using SqliteCommand cmd = new SqliteCommand(groupName != null ? $"SELECT * FROM {_groupTable} WHERE name=@name;" : $"SELECT * FROM {_groupTable}", _sqlConn)
|
||||
|
@ -35,7 +35,7 @@ namespace SharpRss.Services
|
|||
}
|
||||
};
|
||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||
HashSet<GroupModel?> groups = new HashSet<GroupModel?>();
|
||||
HashSet<GroupModel> groups = new HashSet<GroupModel>();
|
||||
while (reader.Read())
|
||||
{
|
||||
groups.Add(new GroupModel()
|
||||
|
@ -51,7 +51,7 @@ namespace SharpRss.Services
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a group if not exists else will update the group.
|
||||
/// Creates a group if not exists then update the group.
|
||||
/// </summary>
|
||||
/// <param name="groupModel"></param>
|
||||
/// <returns></returns>
|
||||
|
@ -94,20 +94,35 @@ namespace SharpRss.Services
|
|||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
// Feed
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? feedName = null)
|
||||
// Feeds
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(GroupModel? group = null)
|
||||
{
|
||||
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
|
||||
_sqlConn.Open();
|
||||
using SqliteCommand cmd = new SqliteCommand(feedName != null ? $"SELECT * FROM {_feedTable} WHERE name=@name" : $"SELECT * FROM {_feedTable}", _sqlConn)
|
||||
using SqliteCommand cmd = new SqliteCommand(group != null ? $"SELECT * FROM {_feedTable} WHERE group_id=@groupid" : $"SELECT * FROM {_feedTable}", _sqlConn)
|
||||
{
|
||||
Parameters =
|
||||
{
|
||||
new SqliteParameter("name", feedName)
|
||||
new SqliteParameter("groupId", group?.Id == string.Empty ? null : group?.Id)
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
Log.Verbose("{FeedAmount} feeds found!", affected);
|
||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||
while (reader.Read())
|
||||
{
|
||||
feeds.Add(new FeedModel()
|
||||
{
|
||||
Id = reader["id"].ToString(),
|
||||
Url = reader["url"].ToString(),
|
||||
GroupId = reader["group_id"].ToString(),
|
||||
FeedType = reader["feed_type"].ToString(),
|
||||
Description = reader["description"].ToString(),
|
||||
Language = reader["language"].ToString(),
|
||||
Copyright = reader["copyright"].ToString(),
|
||||
DateAdded = DateTimeOffset.FromUnixTimeMilliseconds(long.TryParse(reader["date_added"].ToString(), out long parsedVal) ? parsedVal : 0),
|
||||
LastUpdated = DateTimeOffset.FromUnixTimeMilliseconds(long.TryParse(reader["last_updated"].ToString(), out long lastUpdated) ? lastUpdated : 0),
|
||||
ImageUrl = reader["image_url"].ToString()
|
||||
});
|
||||
}
|
||||
_sqlConn.Close();
|
||||
return feeds;
|
||||
}
|
||||
|
@ -116,8 +131,7 @@ namespace SharpRss.Services
|
|||
{
|
||||
bool result = false;
|
||||
_sqlConn.Open();
|
||||
using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url)" +
|
||||
$"VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @groupId, @feedType, @description, @language, @copyright, @dateAdded, @lastUpdated, @imageUrl)", _sqlConn)
|
||||
using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @groupId, @feedType, @description, @language, @copyright, @dateAdded, @lastUpdated, @imageUrl)", _sqlConn)
|
||||
{
|
||||
Parameters =
|
||||
{
|
||||
|
@ -127,10 +141,10 @@ namespace SharpRss.Services
|
|||
new SqliteParameter("feedType", feedModel.FeedType),
|
||||
new SqliteParameter("description", feedModel.Description),
|
||||
new SqliteParameter("language", feedModel.Language),
|
||||
new SqliteParameter("copyright", feedModel.Copyright),
|
||||
new SqliteParameter("copyright", "EMPTY"),
|
||||
new SqliteParameter("dateAdded", feedModel.DateAdded.ToUnixTimeMilliseconds()),
|
||||
new SqliteParameter("lastUpdated", feedModel.LastUpdated.ToUnixTimeMilliseconds()),
|
||||
new SqliteParameter("imageUrl", feedModel.ImageUrl)
|
||||
new SqliteParameter("imageUrl", "EMPTY")
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
|
@ -156,7 +170,7 @@ namespace SharpRss.Services
|
|||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
// Feed item
|
||||
// Feed items
|
||||
public async Task<HashSet<FeedItemModel>> GetFeedItemsAsync()
|
||||
{
|
||||
HashSet<FeedItemModel> feeditems = new HashSet<FeedItemModel> ();
|
||||
|
|
|
@ -3,13 +3,14 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CodeHollow.FeedReader;
|
||||
using Serilog;
|
||||
using SharpRss.Models;
|
||||
using ToolQit.Extensions;
|
||||
|
||||
namespace SharpRss.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Managing RSS feeds and categories.
|
||||
/// Managing RSS feeds and groups.
|
||||
/// </summary>
|
||||
public class RssService : IDisposable
|
||||
{
|
||||
|
@ -19,8 +20,78 @@ namespace SharpRss.Services
|
|||
}
|
||||
private readonly DatabaseService _dbService = new DatabaseService();
|
||||
|
||||
|
||||
public async Task<bool> CreateGroupAsync(GroupModel group) => await _dbService.SetGroupAsync(group);
|
||||
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);
|
||||
if (fetched == null)
|
||||
return result;
|
||||
FeedModel feedModel = new FeedModel(rssUrl)
|
||||
{
|
||||
GroupId = group?.Id,
|
||||
FeedType = fetched.Type.ToString(),
|
||||
Description = fetched.Description,
|
||||
Language = fetched.Language,
|
||||
Copyright = fetched.Copyright,
|
||||
DateAdded = DateTimeOffset.Now,
|
||||
LastUpdated = DateTimeOffset.Now,
|
||||
ImageUrl = fetched.ImageUrl,
|
||||
};
|
||||
result = await _dbService.SetFeedAsync(feedModel);
|
||||
if (!result)
|
||||
return result;
|
||||
if (await AddFeedItems(fetched.Items, feedModel) == 0)
|
||||
Log.Warning($"No feed items added to feed: {feedModel.Url}");
|
||||
return result;
|
||||
}
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(GroupModel? group = null) => await _dbService.GetFeedsAsync(group);
|
||||
public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await _dbService.GetFeedsAsync(new GroupModel() { Id = "" });
|
||||
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);
|
||||
}
|
||||
private async void SetupTestCategoriesAndFeedsAsync()
|
||||
{
|
||||
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);
|
||||
|
||||
/*bool result = await _dbService.SetGroupAsync(new GroupModel() { Name = "News" });
|
||||
result = await _dbService.SetGroupAsync(new GroupModel() { Name = "Tech" });
|
||||
result = await _dbService.SetGroupAsync(new GroupModel() { Name = "Science" });
|
||||
|
|
2
ToolQit
2
ToolQit
|
@ -1 +1 @@
|
|||
Subproject commit af3abae0445b30c3ef58579a18e6e179eaea5986
|
||||
Subproject commit 0f3a3fb0f9145aad31a44eb25159d0f2a5a1c7fd
|
|
@ -9,21 +9,17 @@ namespace WebSharpRSS.Models
|
|||
{
|
||||
_service = rssService;
|
||||
CategoryModel = catModel;
|
||||
Initialize();
|
||||
}
|
||||
|
||||
public TreeItemData(FeedModel feedModel, RssService rssService)
|
||||
{
|
||||
_service = rssService;
|
||||
FeedModel = feedModel;
|
||||
|
||||
Initialize();
|
||||
}
|
||||
|
||||
private readonly RssService _service;
|
||||
public readonly GroupModel? CategoryModel;
|
||||
public readonly FeedModel? FeedModel;
|
||||
//private HashSet<FeedModel> _feedModels;
|
||||
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public bool IsSelected { get; set; }
|
||||
|
@ -33,57 +29,5 @@ namespace WebSharpRSS.Models
|
|||
// Category
|
||||
public bool HasChild { get; set; }
|
||||
public bool IsExpanded { get; set; }
|
||||
//public HashSet<TreeItemData>? Feeds { get; set; }
|
||||
// Feed
|
||||
//public Feed? Feed { get; private set; }
|
||||
/*public int FeeditemCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (CategoryModel != null && Feeds != null)
|
||||
{
|
||||
int feedsCount = 0;
|
||||
foreach (var item in Feeds)
|
||||
{
|
||||
if (item.Feed != null)
|
||||
feedsCount += item.FeeditemCount;
|
||||
}
|
||||
return feedsCount;
|
||||
}
|
||||
else if (Feed != null)
|
||||
return Feed.Items.Count;
|
||||
return 0;
|
||||
}
|
||||
}*/
|
||||
|
||||
private async void Initialize()
|
||||
{
|
||||
/*if (CategoryModel != null)
|
||||
{
|
||||
Title = CategoryModel.Name;
|
||||
Icon = Icons.Material.Filled.Category;
|
||||
/*_feedModels = await _service.GetFeedsAsync(CategoryModel);
|
||||
if (_feedModels.Any())
|
||||
Feeds = _feedModels.Select(x => new TreeItemData(x, _service)).OrderBy(x => x.Title).ToHashSet();#1#
|
||||
}
|
||||
|
||||
if (FeedModel != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//Feed = await _service.GetFeedAsync(FeedModel.FeedUrl);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Error fetching feed: {FeedUrl}", FeedModel.FeedUrl);
|
||||
Feed = null;
|
||||
return;
|
||||
}
|
||||
Icon = Icons.Material.Filled.RssFeed;
|
||||
Title = Feed.Title;
|
||||
string faviconAddress = Feed.Link.Remove(Feed.Link.IndexOf("http", StringComparison.Ordinal), Feed.Link.IndexOf("://", StringComparison.Ordinal) + 3);
|
||||
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAddress);
|
||||
}*/
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,9 +9,9 @@
|
|||
@inject FeedStateContainer _stateContainer;
|
||||
@inject RssService _rssService
|
||||
|
||||
<MudStack Spacing="2">
|
||||
@*<MudTreeView Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
|
||||
$1$<ItemTemplate>
|
||||
@*<MudStack Spacing="2">
|
||||
<MudTreeView Items="_guideItems" @bind-SelectedValue="SelectedItem" Hover="true">
|
||||
<ItemTemplate>
|
||||
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Items="@context.Feeds" Value="@context" CanExpand="@context.HasChild" @onclick="ItemClicked">
|
||||
<Content>
|
||||
<div style="display: grid; grid-template-columns: 1fr auto; align-items: center; width: 100%">
|
||||
|
@ -33,13 +33,13 @@
|
|||
</div>
|
||||
</Content>
|
||||
</MudTreeViewItem>
|
||||
</ItemTemplate>#1#
|
||||
</MudTreeView>*@
|
||||
</MudStack>
|
||||
</ItemTemplate>
|
||||
</MudTreeView>
|
||||
</MudStack>*@
|
||||
|
||||
@code {
|
||||
private MudTheme Theme = new MudTheme();
|
||||
//private readonly HashSet<TreeItemData> _guideItems = new HashSet<TreeItemData>();
|
||||
private readonly HashSet<TreeItemData> _guideItems = new HashSet<TreeItemData>();
|
||||
/*private TreeItemData? _selectedItem;
|
||||
private TreeItemData? SelectedItem
|
||||
{
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user