From 86337f92a24214706f0ee5d2167c1d68b266c67e Mon Sep 17 00:00:00 2001 From: Max <51083570+DRdrProfessor@users.noreply.github.com> Date: Sun, 4 Jun 2023 02:16:47 +0200 Subject: [PATCH] Working on syndication manager, handling feed fetching --- SharpRss/{DbAccess.cs => DbAccess_Old.cs} | 38 +++---- SharpRss/Models/FeedItemModel.cs | 6 +- SharpRss/Models/FeedModel.cs | 32 ++++-- SharpRss/Services/RssService.cs | 36 +++---- SharpRss/SyndicationManager.cs | 125 +++++++++++++++++++++- WebSharpRSS/Bootstrapper.cs | 25 +++-- WebSharpRSS/Models/TreeItemData.cs | 4 +- WebSharpRSS/Pages/List.razor | 2 +- WebSharpRSS/Program.cs | 8 +- WebSharpRSS/Shared/SideGuide.razor | 4 +- 10 files changed, 206 insertions(+), 74 deletions(-) rename SharpRss/{DbAccess.cs => DbAccess_Old.cs} (92%) diff --git a/SharpRss/DbAccess.cs b/SharpRss/DbAccess_Old.cs similarity index 92% rename from SharpRss/DbAccess.cs rename to SharpRss/DbAccess_Old.cs index b6d78a0..e614774 100644 --- a/SharpRss/DbAccess.cs +++ b/SharpRss/DbAccess_Old.cs @@ -4,8 +4,6 @@ using System.Data; using System.IO; using System.Linq; using System.Threading.Tasks; -using System.Transactions; -using Argotic.Syndication; using Dapper; using Microsoft.Data.Sqlite; using Serilog; @@ -13,7 +11,7 @@ using SharpRss.Models; namespace SharpRss { - public static class DbAccess + public static class DbAccess_Old { //TODO: Rename group => category. //TODO: Reworking feed => model/db implementation. @@ -149,17 +147,16 @@ namespace SharpRss { Parameters = { - new SqliteParameter("url", feedModel.Url ?? string.Empty), + new SqliteParameter("url", feedModel.OriginalUrl ?? string.Empty), new SqliteParameter("title", feedModel.Title ?? string.Empty), new SqliteParameter("groupId", feedModel.GroupId ?? string.Empty), new SqliteParameter("feedType", feedModel.FeedType ?? string.Empty), 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() ?? 0), + new SqliteParameter("dateAdded", feedModel.PublicationDate?.ToUnixTimeMilliseconds() ?? 0), new SqliteParameter("lastUpdated", feedModel.LastUpdated?.ToUnixTimeMilliseconds() ?? 0), - new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty), - new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty) + new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty) } }; try @@ -230,8 +227,8 @@ namespace SharpRss HashSet feedItems = new HashSet(); foreach (var dbFeed in dbFeeds) { - GenericSyndicationFeed syndication = new GenericSyndicationFeed(); - syndication.Load(dbFeed.OriginalDocument); + /*GenericSyndicationFeed syndication = new GenericSyndicationFeed(); + syndication.Load(dbFeed.OriginalDocument);*/ //TODO: Get items and add to db } } @@ -245,7 +242,7 @@ namespace SharpRss { Parameters = { - new SqliteParameter("Url", feedModel.Url) + new SqliteParameter("Url", feedModel.OriginalUrl) } }; int affected = await cmd.ExecuteNonQueryAsync(); @@ -280,14 +277,14 @@ namespace SharpRss DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())), PublishingDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publishing_date"].ToString())), - Author = reader["author"].ToString(), + Authors = reader["authors"].ToString().ToString().Split(','), Categories = reader["categories"].ToString().Split(','), Content = reader["content"].ToString() }; if (feedItemModel is { FeedId: { } }) { FeedModel? feedModel = await GetFeedAsync(feedItemModel.FeedUrl); - feedItemModel.Feed = feedModel; + //feedItemModel.Feed = feedModel; } feedItems.Add(feedItemModel); } @@ -300,8 +297,8 @@ namespace SharpRss await using SqliteConnection dbc = new SqliteConnection(ConnectionString); dbc.Open(); await using SqliteTransaction transaction = dbc.BeginTransaction(); - 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)", dbc) + await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedItemTable} (id, feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)" + + $"VALUES (IFNULL((SELECT id FROM {FeedItemTable} WHERE link=@link), @id), @feedUrl, @read, @title, @description, @link, @lastUpdated, @publishingDate, @authors, @categories, @content)", dbc) { Transaction = transaction }; @@ -309,7 +306,7 @@ namespace SharpRss { cmd.Parameters.Clear(); cmd.Parameters.Add(new SqliteParameter("id", item.Id ?? string.Empty)); - cmd.Parameters.Add(new SqliteParameter("feedId", item.FeedId ?? string.Empty)); + cmd.Parameters.Add(new SqliteParameter("feedUrl", item.FeedUrl ?? string.Empty)); cmd.Parameters.Add(new SqliteParameter("read", item.Read ? 1 : 0)); cmd.Parameters.Add(new SqliteParameter("type", item.Type ?? string.Empty)); cmd.Parameters.Add(new SqliteParameter("title", item.Title ?? string.Empty)); @@ -317,7 +314,7 @@ namespace SharpRss cmd.Parameters.Add(new SqliteParameter("link", item.Link ?? string.Empty)); 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("authors", item.Authors != null ? string.Join(',', item.Authors) : string.Empty)); cmd.Parameters.Add(new SqliteParameter("categories", item.Categories != null ? string.Join(',', item.Categories) : string.Empty)); cmd.Parameters.Add(new SqliteParameter("content", item.Content ?? string.Empty)); if (dbc.State != ConnectionState.Open) @@ -372,17 +369,16 @@ namespace SharpRss { FeedModel fetchedFeed = new FeedModel() { - Url = reader["url"].ToString(), + OriginalUrl = reader["url"].ToString(), Title = reader["title"].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), + PublicationDate = 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(), - OriginalDocument = reader["original_document"].ToString() + ImageUrl = reader["image_url"].ToString() }; //TODO: Set group on insert /*var groupFetch = await GetGroupsAsync(fetchedFeed.GroupId); @@ -410,7 +406,7 @@ namespace SharpRss if (queryResponse.Any()) failed.Add("feed"); Log.Verbose("Checking table: {Table}", "feed_item"); - queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS feed_item (id STRING PRIMARY KEY, feed_id STRING, read INT, title STRING, description STRING, link STRING, last_updated INT, publishing_date INT, author STRING, categories STRING, content STRING)"); + queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS feed_item (id STRING PRIMARY KEY, feed_url STRING, read INT, title STRING, description STRING, link STRING, last_updated INT, publishing_date INT, authors STRING, categories STRING, content STRING)"); if (queryResponse.Any()) failed.Add("feed_item"); if (failed.Any()) diff --git a/SharpRss/Models/FeedItemModel.cs b/SharpRss/Models/FeedItemModel.cs index 506e196..bc7456f 100644 --- a/SharpRss/Models/FeedItemModel.cs +++ b/SharpRss/Models/FeedItemModel.cs @@ -4,7 +4,6 @@ namespace SharpRss.Models { public class FeedItemModel { - public FeedModel? Feed { get; set; } public string? Id { get; set; } = string.Empty; // FeedId will be removed public string? FeedId { get; set; } = string.Empty; @@ -16,9 +15,10 @@ namespace SharpRss.Models 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[]? Authors { get; set; } public string[]? Categories { get; set; } public string? Content { get; set; } = string.Empty; - public string? HexColor => Feed?.Group?.HexColor; + public string? CommentsUrl { get; set; } = string.Empty; + public string? HexColor { get; set; } = string.Empty; } } diff --git a/SharpRss/Models/FeedModel.cs b/SharpRss/Models/FeedModel.cs index 5f2b50a..0e761e1 100644 --- a/SharpRss/Models/FeedModel.cs +++ b/SharpRss/Models/FeedModel.cs @@ -1,23 +1,37 @@ using System; +using ToolQit; +using ToolQit.Extensions; namespace SharpRss.Models { public class FeedModel { - public FeedModel() - { - } - public CategoryModel? Group { get; set; } - public string Url { get; set; } + public CategoryModel? Category { get; set; } + public string OriginalUrl { get; set; } = string.Empty; public string? Title { get; set; } = string.Empty; public string? GroupId { get; set; } = string.Empty; public string? FeedType { get; set; } = string.Empty; + public string? FeedVersion { 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 DateTimeOffset? PublicationDate { get; set; } + public DateTimeOffset? LastUpdated { get; set; } = DateTimeOffset.Now; + public string[]? Categories { get; set; } + private string _imageUrl = string.Empty; + public string ImageUrl + { + get + { + if (_imageUrl.IsNullEmptyWhiteSpace()) + _imageUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(OriginalUrl).Host); + return _imageUrl; + } + set + { + if (!value.IsNullEmptyWhiteSpace()) + _imageUrl = value; + } + } } } diff --git a/SharpRss/Services/RssService.cs b/SharpRss/Services/RssService.cs index b11c520..0e544b2 100644 --- a/SharpRss/Services/RssService.cs +++ b/SharpRss/Services/RssService.cs @@ -1,11 +1,8 @@ using System; using System.Collections.Generic; -using System.ComponentModel.Design; -using System.Linq; using System.Threading.Tasks; using Argotic.Common; using Argotic.Syndication; -using Microsoft.Data.Sqlite; using Serilog; using SharpRss.Models; @@ -21,33 +18,33 @@ namespace SharpRss.Services SetupTestGroupsAndFeedsAsync(); } - public async Task> GetGroupsFeedsAsync() + public async Task> GetCategoriesFeedsAsync() { HashSet items = new HashSet(); items.UnionWith(await GetCategoriesAsync()); items.UnionWith(await GetUngroupedFeedsAsync()); return items; } - public async Task CreateGroupAsync(CategoryModel group) => await DbAccess.SetCategoryAsync(group); - public async Task> GetCategoriesAsync() => await DbAccess.GetCategoriesAsync(); + public async Task CreateGroupAsync(CategoryModel group) => await DbAccess_Old.SetCategoryAsync(group); + public async Task> GetCategoriesAsync() => await DbAccess_Old.GetCategoriesAsync(); //TODO: Rework this! // Subscribe to a feed. public async Task AddSubscriptionAsync(string url, CategoryModel? group = null) { - // Check for valid feed url - bool validate = SyndicationDiscoveryUtility.UriExists(new Uri(url)); - if (!validate) return false; + /*if (!SyndicationManager.GetFeed(url, out GenericSyndicationFeed? genFeed)) return false;*/ + var feed = SyndicationManager.CreateSyndication(url); // Check if feed exists in db - FeedModel? fModel = await DbAccess.GetFeedAsync(url); + FeedModel? fModel = await DbAccess_Old.GetFeedAsync(url); // If not exists fetch feed & add. if (fModel == null) { - GenericSyndicationFeed genFeed = GenericSyndicationFeed.Create(new Uri(url)); + /*if (!SyndicationManager.TryGetGenericFeed(url, out GenericSyndicationFeed? genFeed)) return false;*/ + /*if (genFeed == null) return false; fModel = FromResource(genFeed.Resource); - fModel.GroupId = group?.Id; + fModel.GroupId = group?.Id;*/ // Add feed - FeedModel? dbFeed = await DbAccess.SetFeedAsync(fModel); + //FeedModel? dbFeed = await DbAccess.SetFeedAsync(fModel); // Update/fetch items //await DbAccess.FetchFeedItemsAsync(new string[] { fModel.Url }); } @@ -64,7 +61,7 @@ namespace SharpRss.Services model.Title = rssFeed.Channel.Title; model.Description = rssFeed.Channel.Description; model.Copyright = rssFeed.Channel.Copyright; - model.Url = rssFeed.Channel.SelfLink.ToString(); + model.OriginalUrl = rssFeed.Channel.SelfLink.ToString(); model.ImageUrl = rssFeed.Channel.Image?.Url.ToString(); model.Language = rssFeed.Channel.Language?.ToString(); break; @@ -84,13 +81,13 @@ namespace SharpRss.Services var feeds = await GetFeedsAsync(); } - public async Task> GetFeedsAsync(string? groupId = null) => await DbAccess.GetFeedsAsync(groupId); - public async Task> GetUngroupedFeedsAsync() => await DbAccess.GetFeedsAsync(""); + public async Task> GetFeedsAsync(string? groupId = null) => await DbAccess_Old.GetFeedsAsync(groupId); + public async Task> GetUngroupedFeedsAsync() => await DbAccess_Old.GetFeedsAsync(""); public async Task> GetFeedItemsAsync(string feedId, string? groupId = null) => await GetFeedItemsFromFeedsAsync(new[] { feedId }, groupId); public async Task> GetFeedItemsFromFeedsAsync(string[] feedIds, string? groupId = null) { - var items = await DbAccess.GetFeedItemsAsync(feedIds); + var items = await DbAccess_Old.GetFeedItemsAsync(feedIds); return items; } @@ -143,6 +140,7 @@ namespace SharpRss.Services } private async void SetupTestGroupsAndFeedsAsync() { + await AddSubscriptionAsync("https://en.wikipedia.org/w/api.php?hidebots=1&hidecategorization=1&hideWikibase=1&urlversion=1&days=7&limit=50&action=feedrecentchanges&feedformat=atom"); //TODO: Make multiple adding of feed to a transaction, now throws an exception. /*var groupRes = await CreateGroupAsync(new GroupModel() { Name = "Test" }); groupRes = await CreateGroupAsync(new GroupModel() { Name = "News" }); @@ -165,8 +163,8 @@ namespace SharpRss.Services throw; }*/ /*var groups = await GetGroupsAsync(); - CategoryModel testGroup = groups.Single(x => x.Name == "News"); - await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen", testGroup);*/ + CategoryModel testGroup = groups.Single(x => x.Name == "News");*/ + /*await AddFeedsAsync(new[] { "https://www.nu.nl/rss/Algemeen", diff --git a/SharpRss/SyndicationManager.cs b/SharpRss/SyndicationManager.cs index 9847ee0..d125459 100644 --- a/SharpRss/SyndicationManager.cs +++ b/SharpRss/SyndicationManager.cs @@ -1,16 +1,133 @@ using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Argotic.Common; +using Argotic.Extensions.Core; using Argotic.Syndication; +using Serilog; +using SharpRss.Models; namespace SharpRss { + /// + /// Struct that contains the necessary objects for adding/fetching feeds and items + /// + public struct SyndicationContainer + { + public GenericSyndicationFeed SyndicationFeed { get; set; } + public CategoryModel Category { get; set; } + public FeedModel FeedModel { get; set; } + public HashSet FeedItems { get; set; } + } public static class SyndicationManager { - public static bool TryGetFeed(string feedUrl, out GenericSyndicationFeed? feed) + public static SyndicationContainer CreateSyndication(string feedUrl) { - feed = null; + GenericSyndicationFeed? syndicationFeed = null; Uri feedUri = new Uri(feedUrl); - feed = GenericSyndicationFeed.Create(feedUri); - return false; + try + { + Log.Debug("Fetching feed: {FeedUri}", feedUri.ToString()); + syndicationFeed = GenericSyndicationFeed.Create(feedUri); + } + catch (Exception e) + { + Log.Error(e,"Could not get feed: {FeedUrl}", feedUrl); + } + return ConstructSyndicationContainer(syndicationFeed); + } + + public static Stream FeedToStream(GenericSyndicationFeed syndicationFeed) + { + MemoryStream memStream = new MemoryStream(); + syndicationFeed.Resource.Save(memStream); + if (memStream.Length <= 0) + Log.Warning("Failed to serialize {FeedType} feed: {FeedUri}", syndicationFeed.Format.ToString(), syndicationFeed.Title); + memStream.Position = 0; + return memStream; + } + + private static SyndicationContainer ConstructSyndicationContainer(GenericSyndicationFeed? syndicationFeed) + { + SyndicationContainer container = new SyndicationContainer(); + if (syndicationFeed == null) + { + Log.Error("Could not construct syndication container!"); + return container; + } + container.SyndicationFeed = syndicationFeed; + container.FeedModel = new FeedModel(); + container.FeedItems = new HashSet(); + switch (syndicationFeed.Resource.Format) + { + case SyndicationContentFormat.Rss: + RssFeed rssFeed = (RssFeed)container.SyndicationFeed.Resource; + container.FeedModel.OriginalUrl = rssFeed.Channel.SelfLink.ToString(); + container.FeedModel.Title = rssFeed.Channel.Title; + container.FeedModel.FeedType = rssFeed.Format.ToString(); + container.FeedModel.FeedVersion = rssFeed.Version.ToString(); + container.FeedModel.Description = rssFeed.Channel.Description; + container.FeedModel.Language = rssFeed.Channel.Language?.ToString(); + container.FeedModel.Copyright = rssFeed.Channel.Copyright; + container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(rssFeed.Channel.LastBuildDate); + container.FeedModel.Categories = rssFeed.Channel.Categories.Select(x => x.Value).ToArray(); + container.FeedModel.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty; + foreach (var rssItem in rssFeed.Channel.Items) + { + FeedItemModel itemModel = new FeedItemModel() + { + Id = rssItem.Link.ToString(), + FeedUrl = container.FeedModel.OriginalUrl, + Type = container.FeedModel.FeedType, + Title = rssItem.Title, + Description = rssItem.Description, + Link = rssItem.Link.ToString(), + PublishingDate = rssItem.PublicationDate.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(rssItem.PublicationDate), + Authors = new []{ rssItem.Author }, + Categories = rssItem.Categories.Select(x => x.Value).ToArray(), + Content = rssItem.Extensions.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).First(), + CommentsUrl = rssItem.Extensions.Where(x => x is WellFormedWebCommentsSyndicationExtension).Select(x => (x as WellFormedWebCommentsSyndicationExtension)?.Context.CommentsFeed.ToString()).First() + }; + container.FeedItems.Add(itemModel); + } + break; + case SyndicationContentFormat.Atom: + AtomFeed atomFeed = (AtomFeed)container.SyndicationFeed.Resource; + container.FeedModel.OriginalUrl = atomFeed.Id.Uri.ToString(); + container.FeedModel.Title = atomFeed.Title.Content; + container.FeedModel.FeedType = atomFeed.Format.ToString(); + container.FeedModel.FeedVersion = atomFeed.Version?.ToString(); + container.FeedModel.Description = atomFeed.Subtitle?.Content; + container.FeedModel.Language = atomFeed.Language?.ToString(); + container.FeedModel.Copyright = atomFeed.Rights?.Content; + container.FeedModel.PublicationDate = new DateTimeOffset(atomFeed.UpdatedOn); + container.FeedModel.Categories = atomFeed.Categories?.Select(x => x.Label).ToArray(); + container.FeedModel.ImageUrl = atomFeed.Icon?.Uri.ToString() ?? string.Empty; + foreach (var entry in atomFeed.Entries) + { + FeedItemModel itemModel = new FeedItemModel() + { + Id = entry.Id.Uri.ToString(), + FeedUrl = container.FeedModel.OriginalUrl, + Type = container.FeedModel.FeedType, + Title = entry.Title.Content, + Description = entry.Summary.Content, + Link = entry.Id.Uri.ToString(), + LastUpdated = entry.UpdatedOn.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(entry.UpdatedOn), + PublishingDate = entry.PublishedOn.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(entry.PublishedOn), + Authors = entry.Authors.Select(auth => auth.Name).ToArray(), + Categories = entry.Categories.Select(cat => cat.Label).ToArray(), + Content = entry.Content?.Content + }; + container.FeedItems.Add(itemModel); + } + break; + default: + Log.Warning("Feed implementation missing!"); + break; + } + return container; } } } \ No newline at end of file diff --git a/WebSharpRSS/Bootstrapper.cs b/WebSharpRSS/Bootstrapper.cs index 55cac56..5a1fc93 100644 --- a/WebSharpRSS/Bootstrapper.cs +++ b/WebSharpRSS/Bootstrapper.cs @@ -2,32 +2,45 @@ using System; using System.IO; using Serilog; using Serilog.Formatting.Json; -using Serilog.Sinks.SystemConsole.Themes; -using SharpRss.Models; +using SharpRss; using ToolQit; using ToolQit.Containers; -using WebSharpRSS.Models; namespace WebSharpRSS { public static class Bootstrapper { - public static void SetAppDefaultSettings(this DataContainer dataCon) + private static bool _defaultsSet; + private static bool _bootstrapped; + + public static void Bootstrap() + { + if (_bootstrapped) return; + Caretaker.Settings.SetAppDefaultSettings(); + SetupLogging(); + Log.Information("Starting SharpRSS..."); + DbAccess_Old.Initialize(); + _bootstrapped = true; + } + + private static void SetAppDefaultSettings(this DataContainer dataCon) { var paths = dataCon["Paths"]; //paths.Set("FaviconResolveUrl", "https://icons.duckduckgo.com/ip3/{0}.ico", false); paths.Set("FaviconResolveUrl", "http://www.google.com/s2/favicons?domain={0}", false); paths.Set("LogPath", Path.Combine(Environment.CurrentDirectory, "logs", "log_.json"), false); + _defaultsSet = true; } private static LoggerConfiguration? _configuration; - public static void SetupLogging() + private static void SetupLogging() { + if (!_defaultsSet) throw new Exception("Bootstrapper defaults are not initialized!"); if (_configuration != null) return; _configuration = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File(new JsonFormatter(), Caretaker.Settings["Paths"].GetString("LogPath"), rollingInterval: RollingInterval.Day) - .MinimumLevel.Verbose(); + .MinimumLevel.Verbose(); // ONLY FOR DEBUGGING!!! Log.Logger = _configuration.CreateLogger(); } diff --git a/WebSharpRSS/Models/TreeItemData.cs b/WebSharpRSS/Models/TreeItemData.cs index 76b80f9..08f765e 100644 --- a/WebSharpRSS/Models/TreeItemData.cs +++ b/WebSharpRSS/Models/TreeItemData.cs @@ -20,8 +20,8 @@ namespace WebSharpRSS.Models { FeedModel = feedModel; Title = feedModel.Title ?? string.Empty; - if (FeedModel.Url == null) return; - FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.Url).Host); + if (FeedModel.OriginalUrl == null) return; + FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.OriginalUrl).Host); } public readonly CategoryModel? GroupModel; public readonly FeedModel? FeedModel; diff --git a/WebSharpRSS/Pages/List.razor b/WebSharpRSS/Pages/List.razor index 1037a23..dbc1268 100644 --- a/WebSharpRSS/Pages/List.razor +++ b/WebSharpRSS/Pages/List.razor @@ -57,7 +57,7 @@ else if (Gid != null) { var feeds = await _rssService.GetFeedsAsync(Gid); - var feedIds = feeds.Select(x => x.Url); + var feedIds = feeds.Select(x => x.OriginalUrl); var feedItems = await _rssService.GetFeedItemsFromFeedsAsync(feedIds.ToArray()); items = feedItems.Select(x => FeedItemData.FromModel(x)).OrderBy(x => x.PublishingDate).Reverse().ToHashSet(); } diff --git a/WebSharpRSS/Program.cs b/WebSharpRSS/Program.cs index 1f8389e..2854e78 100644 --- a/WebSharpRSS/Program.cs +++ b/WebSharpRSS/Program.cs @@ -3,17 +3,11 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using MudBlazor; using MudBlazor.Services; -using Serilog; -using SharpRss; using SharpRss.Services; -using ToolQit; using WebSharpRSS; using WebSharpRSS.Models; -Caretaker.Settings.SetAppDefaultSettings(); -Bootstrapper.SetupLogging(); -Log.Information("Starting..."); -DbAccess.Initialize(); +Bootstrapper.Bootstrap(); var builder = WebApplication.CreateBuilder(args); builder.Services.AddRazorPages(); diff --git a/WebSharpRSS/Shared/SideGuide.razor b/WebSharpRSS/Shared/SideGuide.razor index fa1dc59..7704dac 100644 --- a/WebSharpRSS/Shared/SideGuide.razor +++ b/WebSharpRSS/Shared/SideGuide.razor @@ -51,7 +51,7 @@ if (_selectedItem == null) return; if (_selectedItem.FeedModel != null) { - _navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.Url}"); + _navigation.NavigateTo($"/list?fid={_selectedItem.FeedModel.OriginalUrl}"); } else if (_selectedItem.GroupModel != null) { @@ -70,7 +70,7 @@ protected override async void OnInitialized() { Log.Verbose("Loading guide data..."); - HashSet items = await _rssService.GetGroupsFeedsAsync(); + HashSet items = await _rssService.GetCategoriesFeedsAsync(); _guideItems.UnionWith(ModelToTreeItem(items)); StateHasChanged();