diff --git a/SharpRss/Models/FeedItemModel.cs b/SharpRss/Models/FeedItemModel.cs index b153340..99260bc 100644 --- a/SharpRss/Models/FeedItemModel.cs +++ b/SharpRss/Models/FeedItemModel.cs @@ -4,17 +4,22 @@ namespace SharpRss.Models { public class FeedItemModel { - public string Id { get; set; } - public string FeedId { get; set; } + public FeedItemModel() + { + Id = Guid.NewGuid().ToString(); + LastUpdated = DateTime.Now; + } + public string Id { get; set; } + public string? FeedId { get; set; } public bool Read { get; set; } - public string Type { get; set; } - public string Title { get; set; } - public string Description { get; set; } - public string Link { 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; } - public string[] Categories { get; set; } - public string Content { get; set; } + public string Author { get; set; } = string.Empty; + public string[]? Categories { get; set; } + public string Content { get; set; } = string.Empty; } } diff --git a/SharpRss/Services/DatabaseService.cs b/SharpRss/Services/DatabaseService.cs index 3e76aa7..a72d712 100644 --- a/SharpRss/Services/DatabaseService.cs +++ b/SharpRss/Services/DatabaseService.cs @@ -27,7 +27,7 @@ namespace SharpRss.Services public async Task> GetGroupsAsync(string? groupName = null) { _sqlConn.Open(); - SqliteCommand cmd = new SqliteCommand(groupName != null ? $"SELECT * FROM {_groupTable} WHERE name=@name;" : $"SELECT * FROM {_groupTable}", _sqlConn) + using SqliteCommand cmd = new SqliteCommand(groupName != null ? $"SELECT * FROM {_groupTable} WHERE name=@name;" : $"SELECT * FROM {_groupTable}", _sqlConn) { Parameters = { @@ -59,7 +59,7 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); - 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) + 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 = { @@ -80,8 +80,8 @@ namespace SharpRss.Services { bool result = false; _sqlConn.Open(); - // Remove the group and remove the feeds that were part of the group. - SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_groupTable} WHERE id=@id; UPDATE {_feedTable} SET group_id=NULL WHERE group_id=@id", _sqlConn) + // 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) { Parameters = { @@ -99,7 +99,7 @@ namespace SharpRss.Services { HashSet feeds = new HashSet(); _sqlConn.Open(); - SqliteCommand cmd = new SqliteCommand(feedName != null ? $"SELECT * FROM {_feedTable} WHERE name=@name" : $"SELECT * FROM {_feedTable}", _sqlConn) + using SqliteCommand cmd = new SqliteCommand(feedName != null ? $"SELECT * FROM {_feedTable} WHERE name=@name" : $"SELECT * FROM {_feedTable}", _sqlConn) { Parameters = { @@ -112,11 +112,11 @@ namespace SharpRss.Services return feeds; } - public async Task AddFeedAsync(FeedModel feedModel) + public async Task SetFeedAsync(FeedModel feedModel) { bool result = false; _sqlConn.Open(); - SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url)" + + 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 = @@ -139,7 +139,98 @@ namespace SharpRss.Services _sqlConn.Close(); return result; } + public async Task RemoveFeedAsync(FeedModel feedModel) + { + 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) + { + Parameters = + { + new SqliteParameter("id", feedModel.Id) + } + }; + int affected = await cmd.ExecuteNonQueryAsync(); + if (affected != 0) + result = true; + _sqlConn.Close(); + return result; + } // Feed item + public async Task> GetFeedItemsAsync() + { + HashSet feeditems = new HashSet (); + _sqlConn.Open(); + using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {_feedItemTable}", _sqlConn); + await using SqliteDataReader reader = await cmd.ExecuteReaderAsync(); + while (reader.Read()) + { + 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(), + Title = reader["title"].ToString(), + Description = reader["description"].ToString(), + Link = reader["link"].ToString(), + LastUpdated = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())), + PublishingDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publishing_date"].ToString())), + Author = reader["author"].ToString(), + Categories = reader["categories"].ToString().Split(','), + Content = reader["content"].ToString() + }); + } + _sqlConn.Close(); + 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, 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); + 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("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("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)); + int affected = await cmd.ExecuteNonQueryAsync(); + if (affected == 0) + Log.Verbose($"Could not set feed item: {item.Link}"); + else + result += affected; + } + _sqlConn.Close(); + return result; // Return the amount affected rows. + } + public async Task RemoveFeedItemAsync(FeedItemModel itemModel) + { + bool result = false; + _sqlConn.Open(); + using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedItemTable} WHERE id=@id", _sqlConn) + { + Parameters = + { + new SqliteParameter("id", itemModel.Id) + } + }; + int affected = await cmd.ExecuteNonQueryAsync(); + if (affected != 0) + result = true; + _sqlConn.Close(); + return result; + } private async void InitializeDb() { diff --git a/ToolQit b/ToolQit index 0f3a3fb..af3abae 160000 --- a/ToolQit +++ b/ToolQit @@ -1 +1 @@ -Subproject commit 0f3a3fb0f9145aad31a44eb25159d0f2a5a1c7fd +Subproject commit af3abae0445b30c3ef58579a18e6e179eaea5986