diff --git a/SharpRss/Models/FeedItemModel.cs b/SharpRss/Models/FeedItemModel.cs index 47c60e3..01e832c 100644 --- a/SharpRss/Models/FeedItemModel.cs +++ b/SharpRss/Models/FeedItemModel.cs @@ -5,7 +5,7 @@ namespace SharpRss.Models public class FeedItemModel { public string Id { get; set; } = string.Empty; - public string? FeedId { get; set; } + 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; diff --git a/SharpRss/Models/FeedModel.cs b/SharpRss/Models/FeedModel.cs index c580850..d63e51b 100644 --- a/SharpRss/Models/FeedModel.cs +++ b/SharpRss/Models/FeedModel.cs @@ -4,23 +4,22 @@ namespace SharpRss.Models { public class FeedModel { - public FeedModel() { } public FeedModel(string rssUrl) { Url = rssUrl; Id = Guid.NewGuid().ToString(); - Copyright = "EMPTY"; - ImageUrl = "EMPTY"; } - public string Id { get; set; } = string.Empty; - public string Url { get; set; } = string.Empty; - public string? GroupId { get; set; } + 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; } = "EMPTY"; + public string Copyright { get; set; } = string.Empty; public DateTimeOffset DateAdded { get; set; } public DateTimeOffset LastUpdated { get; set; } - public string ImageUrl { get; set; } = "EMPTY"; + 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 a5b34eb..10456fd 100644 --- a/SharpRss/Services/DatabaseService.cs +++ b/SharpRss/Services/DatabaseService.cs @@ -15,7 +15,7 @@ namespace SharpRss.Services internal DatabaseService() { _sqlConn = new SqliteConnection(_connectionString); - InitializeDb(); + //InitializeDb(); } private readonly SqliteConnection _sqlConn; private readonly string _connectionString = $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.sqlite")};"; @@ -109,10 +109,10 @@ namespace SharpRss.Services await using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); while (reader.Read()) { - feeds.Add(new FeedModel() + feeds.Add(new FeedModel(reader["url"].ToString()) { Id = reader["id"].ToString(), - Url = reader["url"].ToString(), + Title = reader["group_id"].ToString(), GroupId = reader["group_id"].ToString(), FeedType = reader["feed_type"].ToString(), Description = reader["description"].ToString(), @@ -120,7 +120,8 @@ namespace SharpRss.Services 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() + ImageUrl = reader["image_url"].ToString(), + OriginalDocument = reader["original_document"].ToString() }); } _sqlConn.Close(); @@ -131,20 +132,22 @@ 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, 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, @dateAdded, @lastUpdated, @imageUrl, @originalDoc)", _sqlConn) { Parameters = { - new SqliteParameter("id", feedModel.Id), - new SqliteParameter("url", feedModel.Url), - new SqliteParameter("groupId", feedModel.GroupId), - new SqliteParameter("feedType", feedModel.FeedType), - new SqliteParameter("description", feedModel.Description), - new SqliteParameter("language", feedModel.Language), - new SqliteParameter("copyright", "EMPTY"), + new SqliteParameter("id", feedModel.Id ?? string.Empty), + new SqliteParameter("url", feedModel.Url ?? 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()), new SqliteParameter("lastUpdated", feedModel.LastUpdated.ToUnixTimeMilliseconds()), - new SqliteParameter("imageUrl", "EMPTY") + new SqliteParameter("imageUrl", feedModel.ImageUrl ?? string.Empty), + new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty) } }; int affected = await cmd.ExecuteNonQueryAsync(); @@ -202,26 +205,26 @@ namespace SharpRss.Services { int result = 0; _sqlConn.Open(); - using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedItemTable} (id, feed_id, read, type, title, description, link, last_updated, publishing_date, author, categories, content)" + - $"VALUES (IFNULL((SELECT id FROM {_feedItemTable} WHERE url=@url), @id), @feedId, @read, @type, @title, @description, @link, @lastUpdated, @publishingDate, @author, @categories, @content)", _sqlConn); + 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(); - cmd.Parameters.Add(new SqliteParameter("id", item.Id)); - cmd.Parameters.Add(new SqliteParameter("feedid", item.FeedId)); + 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("read", item.Read ? 1 : 0)); - cmd.Parameters.Add(new SqliteParameter("type", item.Type)); - cmd.Parameters.Add(new SqliteParameter("title", item.Title)); - cmd.Parameters.Add(new SqliteParameter("description", item.Description)); - cmd.Parameters.Add(new SqliteParameter("link", item.Link)); + cmd.Parameters.Add(new SqliteParameter("type", item.Type ?? string.Empty)); + 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("publishingDate", item.PublishingDate?.ToUnixTimeMilliseconds() ?? 0)); - cmd.Parameters.Add(new SqliteParameter("author", item.Author)); - cmd.Parameters.Add(new SqliteParameter("categories", string.Join(',', item.Categories))); - cmd.Parameters.Add(new SqliteParameter("content", item.Content)); + 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)); + cmd.Parameters.Add(new SqliteParameter("content", item.Content ?? string.Empty)); int affected = await cmd.ExecuteNonQueryAsync(); if (affected == 0) - Log.Verbose($"Could not set feed item: {item.Link}"); + Log.Verbose("Could not set feed item: {FeedLink}", item.Link); else result += affected; } @@ -256,11 +259,11 @@ namespace SharpRss.Services if (queryResponse.Any()) failed.Add("category_data"); Log.Verbose("Checking table: {Table}", _feedTable); - queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedTable} (id STRING PRIMARY KEY, url STRING NOT NULL, group_id STRING DEFAULT NULL, feed_type STRING, description STRING, language STRING, copyright STRING, date_added INT, last_updated INT, image_url STRING)"); + queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedTable} (id STRING PRIMARY KEY, url STRING NOT NULL, title STRING, group_id STRING, feed_type STRING, description STRING, language STRING, copyright STRING, date_added INT, last_updated INT, image_url STRING, original_document STRING)"); if (queryResponse.Any()) failed.Add("feed_data"); Log.Verbose("Checking table: {Table}", _feedItemTable); - queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedItemTable} (id STRING PRIMARY KEY, feed_id STRING DEFAULT NULL, read INT, type STRING, title STRING, description STRING, link STRING, last_updated INT, publishing_date INT, author STRING, categories STRING, content STRING)"); + queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedItemTable} (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)"); if (queryResponse.Any()) failed.Add("feed_item_data"); _sqlConn.Close(); diff --git a/SharpRss/Services/RssService.cs b/SharpRss/Services/RssService.cs index 198867d..fbb11b9 100644 --- a/SharpRss/Services/RssService.cs +++ b/SharpRss/Services/RssService.cs @@ -5,7 +5,6 @@ using System.Threading.Tasks; using CodeHollow.FeedReader; using Serilog; using SharpRss.Models; -using ToolQit.Extensions; namespace SharpRss.Services { @@ -16,23 +15,24 @@ namespace SharpRss.Services { public RssService() { - SetupTestCategoriesAndFeedsAsync(); + SetupTestCategoriesAndFeedsAsync(); } private readonly DatabaseService _dbService = new DatabaseService(); - - - public async Task CreateGroupAsync(GroupModel group) => await _dbService.SetGroupAsync(group); + + public async Task CreateGroupAsync(GroupModel group) => await _dbService.SetGroupAsync(group); public async Task> GetGroupsAsync() => await _dbService.GetGroupsAsync(); public async Task 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, + Title = fetched.Title, + GroupId = group?.Id ?? string.Empty, FeedType = fetched.Type.ToString(), Description = fetched.Description, Language = fetched.Language, @@ -40,12 +40,13 @@ namespace SharpRss.Services DateAdded = DateTimeOffset.Now, LastUpdated = DateTimeOffset.Now, ImageUrl = fetched.ImageUrl, + OriginalDocument = fetched.OriginalDocument }; 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}"); + Log.Warning("No feed items added to feed: {FeedUrl}", feedModel.Url); return result; } public async Task> GetFeedsAsync(GroupModel? group = null) => await _dbService.GetFeedsAsync(group); @@ -85,37 +86,16 @@ namespace SharpRss.Services } private async void SetupTestCategoriesAndFeedsAsync() { + 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" }); 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" }); - result = await _dbService.SetGroupAsync(new GroupModel() { Name = "Test" });*/ - - /*GroupModel? editGroup = await _dbService.GetGroupsAsync("Test"); - if (editGroup != null) - { - bool result2 = await _dbService.RemoveGroupAsync(editGroup); - }*/ - /*await _dbService.AddCategoriesAsync(new HashSet() - { - new CategoryModel() { Name = "All" }, - new CategoryModel() { Name = "RSS" }, - new CategoryModel() { Name = "Tech" }, - new CategoryModel() { Name = "News" } - }); - await _dbService.AddFeedsAsync(new HashSet() - { - new FeedModel("http://fedoramagazine.org/feed/"), - new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"), - new FeedModel("https://journals.plos.org/plosone/feed/atom"), - new FeedModel("https://itsfoss.com/feed") - });*/ } public void Dispose() diff --git a/WebSharpRSS/sharp_rss.sqlite b/WebSharpRSS/sharp_rss.sqlite index c57d0c7..ad75249 100644 Binary files a/WebSharpRSS/sharp_rss.sqlite and b/WebSharpRSS/sharp_rss.sqlite differ