diff --git a/SharpRss/Models/FeedItemModel.cs b/SharpRss/Models/FeedItemModel.cs index 01e832c..6e51999 100644 --- a/SharpRss/Models/FeedItemModel.cs +++ b/SharpRss/Models/FeedItemModel.cs @@ -4,17 +4,18 @@ namespace SharpRss.Models { public class FeedItemModel { - public string Id { get; set; } = string.Empty; - public string FeedId { get; set; } = string.Empty; + public string? Id { get; set; } = string.Empty; + public string? FeedId { get; set; } = string.Empty; public bool Read { get; set; } - public string Type { get; set; } = string.Empty; - public string Title { get; set; } = string.Empty; - public string Description { get; set; } = string.Empty; - public string Link { get; set; } = string.Empty; - public DateTimeOffset LastUpdated { get; set; } + public string? Type { get; set; } = string.Empty; + public string? Title { get; set; } = string.Empty; + public string? Description { get; set; } = string.Empty; + public string? Link { get; set; } = string.Empty; + public DateTimeOffset? LastUpdated { get; set; } public DateTimeOffset? PublishingDate { get; set; } - public string Author { get; set; } = string.Empty; + public string? Author { get; set; } = string.Empty; public string[]? Categories { get; set; } - public string Content { get; set; } = string.Empty; + public string? Content { get; set; } = string.Empty; + public string? HexColor { get; set; } = string.Empty; } } diff --git a/SharpRss/Models/FeedModel.cs b/SharpRss/Models/FeedModel.cs index d63e51b..2dad140 100644 --- a/SharpRss/Models/FeedModel.cs +++ b/SharpRss/Models/FeedModel.cs @@ -9,17 +9,17 @@ namespace SharpRss.Models Url = rssUrl; Id = Guid.NewGuid().ToString(); } - public string Id { get; set; } - public string Url { get; set; } - public string Title { get; set; } = string.Empty; - public string GroupId { get; set; } = string.Empty; - 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 DateTimeOffset DateAdded { get; set; } - public DateTimeOffset LastUpdated { get; set; } - public string ImageUrl { get; set; } = string.Empty; - public string OriginalDocument { get; set; } = string.Empty; + public string? Id { get; set; } + public string? Url { get; set; } + public string? Title { get; set; } = string.Empty; + public string? GroupId { get; set; } = string.Empty; + 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 DateTimeOffset? DateAdded { get; set; } + public DateTimeOffset? LastUpdated { get; set; } + public string? ImageUrl { get; set; } = string.Empty; + public string? OriginalDocument { get; set; } = string.Empty; } } diff --git a/SharpRss/Services/DatabaseService.cs b/SharpRss/Services/DatabaseService.cs index 2e09713..c30f7f6 100644 --- a/SharpRss/Services/DatabaseService.cs +++ b/SharpRss/Services/DatabaseService.cs @@ -27,7 +27,7 @@ namespace SharpRss.Services public async Task> GetGroupsAsync(string? groupId = null) { _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {_groupTable} WHERE id=@gId;" : $"SELECT * FROM {_groupTable}", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {_groupTable} WHERE id=@gId;" : $"SELECT * FROM {_groupTable}", _sqlConn) { Parameters = { @@ -36,7 +36,7 @@ namespace SharpRss.Services }; await using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); HashSet groups = new HashSet(); - using SqliteCommand cmdFeedCount = new SqliteCommand($"SELECT COUNT(*) FROM {_feedTable} WHERE group_id=@groupId", _sqlConn); + await using SqliteCommand cmdFeedCount = new SqliteCommand($"SELECT COUNT(*) FROM {_feedTable} WHERE group_id=@groupId", _sqlConn); while (reader.Read()) { cmdFeedCount.Parameters.Clear(); @@ -66,7 +66,7 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_groupTable} (id, hex_color, icon, name) VALUES (IFNULL((SELECT id FROM {_groupTable} WHERE name=@name), @id), @hexColor, @icon, @name)", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_groupTable} (id, hex_color, icon, name) VALUES (IFNULL((SELECT id FROM {_groupTable} WHERE name=@name), @id), @hexColor, @icon, @name)", _sqlConn) { Parameters = { @@ -88,7 +88,7 @@ namespace SharpRss.Services bool result = false; _sqlConn.Open(); // Remove the group and remove the feeds that were part of the group. - using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_groupTable} WHERE id=@id; UPDATE {_feedTable} SET group_id=NULL WHERE group_id=@id", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_groupTable} WHERE id=@id; UPDATE {_feedTable} SET group_id=NULL WHERE group_id=@id", _sqlConn) { Parameters = { @@ -106,7 +106,7 @@ namespace SharpRss.Services { HashSet feeds = new HashSet(); _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {_feedTable} WHERE group_id=@groupId" : $"SELECT * FROM {_feedTable}", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {_feedTable} WHERE group_id=@groupId" : $"SELECT * FROM {_feedTable}", _sqlConn) { Parameters = { @@ -139,7 +139,7 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedItemTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc)", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedItemTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc)", _sqlConn) { Parameters = { @@ -151,8 +151,8 @@ namespace SharpRss.Services new SqliteParameter("description", feedModel.Description ?? string.Empty), new SqliteParameter("language", feedModel.Language ?? string.Empty), new SqliteParameter("copyright", feedModel.Copyright ?? string.Empty), - new SqliteParameter("dateAdded", feedModel.DateAdded.ToUnixTimeMilliseconds()), - new SqliteParameter("lastUpdated", feedModel.LastUpdated.ToUnixTimeMilliseconds()), + new SqliteParameter("dateAdded", feedModel.DateAdded?.ToUnixTimeMilliseconds()), + new SqliteParameter("lastUpdated", feedModel.LastUpdated?.ToUnixTimeMilliseconds()), new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty), new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty) } @@ -167,7 +167,7 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); // After removing the feed unset the feed id from the feed items - using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedTable} WHERE id=@id; UPDATE {_feedItemTable} SET feed_id=NULL WHERE feed_id=@id", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedTable} WHERE id=@id; UPDATE {_feedItemTable} SET feed_id=NULL WHERE feed_id=@id", _sqlConn) { Parameters = { @@ -181,20 +181,25 @@ namespace SharpRss.Services return result; } // Feed items - public async Task> GetFeedItemsAsync() + public async Task> GetFeedItemsAsync(string[]? feedIds = null) { - HashSet feeditems = new HashSet (); + HashSet feedItems = new HashSet(); _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {_feedItemTable}", _sqlConn); + await using SqliteCommand cmd = new SqliteCommand( + feedIds != null + ? $"SELECT * FROM {_feedItemTable} WHERE feed_id IN (@feedIds)" + : $"SELECT * FROM {_feedItemTable}", _sqlConn); + if (feedIds != null) + cmd.Parameters.Add(new SqliteParameter("feedIds", string.Join(',', feedIds))); + await using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); while (reader.Read()) { - feeditems.Add(new FeedItemModel() + feedItems.Add(new FeedItemModel() { Id = reader["id"].ToString(), FeedId = reader["feed_id"].ToString(), - Read = int.TryParse(reader["read"].ToString(), out int parsedValue)? parsedValue == 0 ? false : true : false, - Type = reader["type"].ToString(), + Read = int.TryParse(reader["read"].ToString(), out int parsedValue) && parsedValue != 0, Title = reader["title"].ToString(), Description = reader["description"].ToString(), Link = reader["link"].ToString(), @@ -206,14 +211,14 @@ namespace SharpRss.Services }); } _sqlConn.Close(); - return feeditems; + return feedItems; } public async Task SetFeedItemsAsync(HashSet items) { int result = 0; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedItemTable} (id, feed_id, read, title, description, link, last_updated, publishing_date, author, categories, content)" + - $"VALUES (IFNULL((SELECT id FROM {_feedItemTable} WHERE link=@link), @id), @feedId, @read, @title, @description, @link, @lastUpdated, @publishingDate, @author, @categories, @content)", _sqlConn); + await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedItemTable} (id, feed_id, read, title, description, link, last_updated, publishing_date, author, categories, content)" + + $"VALUES (IFNULL((SELECT id FROM {_feedItemTable} WHERE link=@link), @id), @feedId, @read, @title, @description, @link, @lastUpdated, @publishingDate, @author, @categories, @content)", _sqlConn); foreach (FeedItemModel item in items) { cmd.Parameters.Clear(); @@ -224,7 +229,7 @@ namespace SharpRss.Services cmd.Parameters.Add(new SqliteParameter("title", item.Title ?? string.Empty)); cmd.Parameters.Add(new SqliteParameter("description", item.Description ?? string.Empty)); cmd.Parameters.Add(new SqliteParameter("link", item.Link ?? string.Empty)); - cmd.Parameters.Add(new SqliteParameter("lastUpdated", item.LastUpdated.ToUnixTimeMilliseconds())); + cmd.Parameters.Add(new SqliteParameter("lastUpdated", item.LastUpdated?.ToUnixTimeMilliseconds())); cmd.Parameters.Add(new SqliteParameter("publishingDate", item.PublishingDate?.ToUnixTimeMilliseconds() ?? 0)); cmd.Parameters.Add(new SqliteParameter("author", item.Author ?? string.Empty)); cmd.Parameters.Add(new SqliteParameter("categories", item.Categories != null ? string.Join(',', item.Categories) : string.Empty)); @@ -242,7 +247,7 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedItemTable} WHERE id=@id", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedItemTable} WHERE id=@id", _sqlConn) { Parameters = { @@ -255,18 +260,18 @@ namespace SharpRss.Services _sqlConn.Close(); return result; } - public async Task GetGroupFromFeeditemAsync(FeedItemModel feedItem) + public async Task GetGroupFromFeedItemAsync(FeedItemModel feedItem) { GroupModel? result = null; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {_groupTable} WHERE id=(SELECT group_id FROM {_feedTable} WHERE id=@fId)", _sqlConn) + await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {_groupTable} WHERE id=(SELECT group_id FROM {_feedTable} WHERE id=@fId)", _sqlConn) { Parameters = { new SqliteParameter ("fId", feedItem.Id) } }; - using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); + await using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); HashSet? groups = null; if (reader.Read()) groups = await GetGroupsAsync(reader["group_id"].ToString()); diff --git a/SharpRss/Services/RssService.cs b/SharpRss/Services/RssService.cs index 94a0bc5..ba41fff 100644 --- a/SharpRss/Services/RssService.cs +++ b/SharpRss/Services/RssService.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using CodeHollow.FeedReader; using Serilog; using SharpRss.Models; +using ToolQit.Extensions; namespace SharpRss.Services { @@ -19,7 +20,7 @@ namespace SharpRss.Services } private readonly DatabaseService _dbService = new DatabaseService(); - public async Task> GetItemsAsync() + public async Task> GetGroupsFeedsAsync() { HashSet items = new HashSet(); items.UnionWith(await GetGroupsAsync()); @@ -58,7 +59,26 @@ namespace SharpRss.Services } public async Task> GetFeedsAsync(GroupModel? group = null) => await _dbService.GetFeedsAsync(group?.Id); public async Task> GetUngroupedFeedsAsync() => await _dbService.GetFeedsAsync(""); - private async Task AddFeedItems(IList items, FeedModel feedModel) + + public async Task> GetFeedItems(FeedModel feedModel) + { + var items = await _dbService.GetFeedItemsAsync(new []{ feedModel.Id ?? string.Empty }); + GroupModel? group = null; + if (feedModel.GroupId != null) + { + var model = await _dbService.GetGroupsAsync(feedModel.GroupId); + if (model != null && model.Any()) group = model.FirstOrDefault(); + } + // Update the items with the group data + if (group != null) + { + foreach (FeedItemModel feedItem in items) + feedItem.HexColor = group.HexColor; + } + return items; + } + + private async Task AddFeedItems(IList items, FeedModel feedModel) { int result = 0; if (!items.Any()) diff --git a/WebSharpRSS/Models/FeedItemData.cs b/WebSharpRSS/Models/FeedItemData.cs index 318c110..282b13e 100644 --- a/WebSharpRSS/Models/FeedItemData.cs +++ b/WebSharpRSS/Models/FeedItemData.cs @@ -1,4 +1,5 @@ -using SharpRss.Models; +using System; +using SharpRss.Models; using ToolQit; namespace WebSharpRSS.Models @@ -7,10 +8,10 @@ namespace WebSharpRSS.Models { public FeedItemData() { - FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), Link.Remove(Link.IndexOf("http", StringComparison.Ordinal), Link.IndexOf("://", StringComparison.Ordinal) + 3)); + if (Link == null) return; + //FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), Link.Remove(Link.IndexOf("http", StringComparison.Ordinal), Link.IndexOf("://", StringComparison.Ordinal) + 3)); } public static FeedItemData? FromModel(FeedItemModel model) => Utilities.ConvertFrom(model); - public string HexColor { get; set; } - public string FaviconUrl { get; set; } + public string FaviconUrl { get; set; } = string.Empty; } } diff --git a/WebSharpRSS/Models/TreeItemData.cs b/WebSharpRSS/Models/TreeItemData.cs index f2e0a70..d3280eb 100644 --- a/WebSharpRSS/Models/TreeItemData.cs +++ b/WebSharpRSS/Models/TreeItemData.cs @@ -1,7 +1,7 @@ -using CodeHollow.FeedReader; +using System; +using System.Collections.Generic; using MudBlazor; using SharpRss.Models; -using SharpRss.Services; using ToolQit; namespace WebSharpRSS.Models diff --git a/WebSharpRSS/Pages/Read.razor b/WebSharpRSS/Pages/Read.razor index f621fdb..ec3bb45 100644 --- a/WebSharpRSS/Pages/Read.razor +++ b/WebSharpRSS/Pages/Read.razor @@ -1,5 +1,11 @@ @page "/read/{Id}" @using WebSharpRSS.Models; +@using ToolQit.Extensions +@using Serilog +@using SharpRss.Models +@using SharpRss.Services + +@inject RssService _rssService; @if (isLoading) @@ -47,8 +53,16 @@ bool isLoading = true; bool failed = false; - protected override void OnInitialized() + protected override async void OnInitialized() { - + if (Id.IsNullEmptyWhiteSpace()) + { + Log.Warning("Invalid id!"); + failed = true; + } + var fItems = await _rssService.GetFeedItems(new FeedModel("") { Id = Id }); + items = fItems.Select(x => FeedItemData.FromModel(x)).ToHashSet(); + isLoading = false; + StateHasChanged(); } } \ No newline at end of file diff --git a/WebSharpRSS/Shared/SideGuide.razor b/WebSharpRSS/Shared/SideGuide.razor index 5ea9471..bd393c7 100644 --- a/WebSharpRSS/Shared/SideGuide.razor +++ b/WebSharpRSS/Shared/SideGuide.razor @@ -66,7 +66,7 @@ protected override async void OnInitialized() { Log.Verbose("Loading guide data..."); - HashSet items = await _rssService.GetItemsAsync(); + HashSet items = await _rssService.GetGroupsFeedsAsync(); _guideItems.UnionWith(ModelToTreeItem(items)); StateHasChanged();