mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
Implementing database backend.
This commit is contained in:
parent
6d2fce5290
commit
367949c200
|
@ -1,30 +1,19 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpRss.Models
|
||||
{
|
||||
public class FeedItemModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Last time the item is fetched.
|
||||
/// </summary>
|
||||
public DateTime LastUpdated { get; set; }
|
||||
/// <summary>
|
||||
/// The feed in which the item is part of.
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
public string FeedId { get; set; }
|
||||
/// <summary>
|
||||
/// If the item is read.
|
||||
/// </summary>
|
||||
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 DateTime? PublishingDate { get; set; }
|
||||
public DateTimeOffset LastUpdated { get; set; }
|
||||
public DateTimeOffset? PublishingDate { get; set; }
|
||||
public string Author { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string[] Categories { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
|
|
@ -4,16 +4,20 @@ namespace SharpRss.Models
|
|||
{
|
||||
public class FeedModel
|
||||
{
|
||||
public string FeedId { get; set; }
|
||||
public string GroupId { get; set; }
|
||||
public string FeedType { get; set; }
|
||||
public string FeedUrl { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Language { get; set; }
|
||||
public string Copyright { get; set; }
|
||||
public DateTime LastUpdated { get; set; }
|
||||
public string ImageUrl { get; set; }
|
||||
public int TotalItems { get; set; }
|
||||
public int TotalRead { get; set; }
|
||||
public FeedModel(string rssUrl)
|
||||
{
|
||||
Id = Guid.NewGuid().ToString();
|
||||
Url = rssUrl;
|
||||
}
|
||||
public string Id { get; set; }
|
||||
public string Url { get; set; }
|
||||
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 DateTimeOffset DateAdded { get; set; }
|
||||
public DateTimeOffset LastUpdated { get; set; }
|
||||
public string ImageUrl { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@ namespace SharpRss.Models
|
|||
{
|
||||
public class GroupModel
|
||||
{
|
||||
public GroupModel(string name)
|
||||
public GroupModel()
|
||||
{
|
||||
Name = name;
|
||||
HexColor = Utilities.GenerateRandomHexColor();
|
||||
Id = Guid.NewGuid().ToString();
|
||||
}
|
||||
public string Name { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string HexColor { get; set; }
|
||||
public string Icon { get; set; }
|
||||
public string Id { get; private set; }
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
public string Id { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,86 +23,139 @@ namespace SharpRss.Services
|
|||
private readonly string _feedTable = "feed_data";
|
||||
private readonly string _feedItemTable = "feed_item_data";
|
||||
|
||||
public async Task RemoveGroupFromFeedsAsync(string groupId)
|
||||
// Group
|
||||
public async Task<HashSet<GroupModel?>> GetGroupsAsync(string? groupName = null)
|
||||
{
|
||||
await _sqlConn.QueryAsync("UPDATE feed_data SET group_id=NULL WHERE group_id=@GroupId", new { GroupId = groupId });
|
||||
}
|
||||
|
||||
public async Task<bool> AddCategoriesAsync(HashSet<GroupModel> categories)
|
||||
{
|
||||
bool result = true;
|
||||
_sqlConn.Open();
|
||||
foreach (var categoryModel in categories)
|
||||
SqliteCommand cmd = new SqliteCommand(groupName != null ? $"SELECT * FROM {_groupTable} WHERE name=@name;" : $"SELECT * FROM {_groupTable}", _sqlConn)
|
||||
{
|
||||
await _sqlConn.QueryAsync("INSERT INTO category_data (name, hex_color, path_icon, category_id) VALUES(@catName, @hexColor, @pathIcon, @categoryId) ON CONFLICT(name) DO UPDATE SET hex_color=@hexColor, path_icon=@pathIcon",
|
||||
new { catName = categoryModel.Name, hexColor = categoryModel.HexColor, pathIcon = categoryModel.Icon, categoryId = categoryModel.Id });
|
||||
}
|
||||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> AddFeedsAsync(HashSet<FeedModel> feeds)
|
||||
Parameters =
|
||||
{
|
||||
bool result = true;
|
||||
_sqlConn.Open();
|
||||
foreach (var feedModel in feeds)
|
||||
{
|
||||
await _sqlConn.QueryAsync("INSERT OR REPLACE INTO feed_data(url, feed_id, category_id) VALUES(@url, @feedId, @categoryId) ON CONFLICT(url) DO UPDATE SET category_id=@categoryId", new { url = feedModel.FeedUrl, feedId = feedModel.FeedId, categoryId = feedModel.GroupId });
|
||||
new SqliteParameter("name", groupName)
|
||||
}
|
||||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<HashSet<GroupModel>> GetCategoriesAsync()
|
||||
{
|
||||
HashSet<GroupModel> categories = new HashSet<GroupModel>();
|
||||
_sqlConn.Open();
|
||||
SqliteCommand cmd = _sqlConn.CreateCommand();
|
||||
cmd.CommandText = "SELECT * FROM category_data";
|
||||
};
|
||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||
HashSet<GroupModel?> groups = new HashSet<GroupModel?>();
|
||||
while (reader.Read())
|
||||
{
|
||||
//categories.Add(GroupModel.Create(reader["name"].ToString(), reader["hex_color"].ToString(), reader["category_id"].ToString()));
|
||||
groups.Add(new GroupModel()
|
||||
{
|
||||
Name = reader["name"].ToString(),
|
||||
HexColor = reader["hex_color"].ToString(),
|
||||
Icon = reader["icon"].ToString(),
|
||||
Id = reader["id"].ToString()
|
||||
});
|
||||
}
|
||||
|
||||
_sqlConn.Close();
|
||||
return categories;
|
||||
return groups;
|
||||
}
|
||||
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? categoryId = null)
|
||||
/// <summary>
|
||||
/// Creates a group if not exists else will update the group.
|
||||
/// </summary>
|
||||
/// <param name="groupModel"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> SetGroupAsync(GroupModel groupModel)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Parameters =
|
||||
{
|
||||
new SqliteParameter("id", groupModel.Id),
|
||||
new SqliteParameter("hexColor", groupModel.HexColor),
|
||||
new SqliteParameter("icon", groupModel.Icon),
|
||||
new SqliteParameter("name", groupModel.Name)
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
if (affected != 0)
|
||||
result = true;
|
||||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> RemoveGroupAsync(GroupModel groupModel)
|
||||
{
|
||||
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)
|
||||
{
|
||||
Parameters =
|
||||
{
|
||||
new SqliteParameter("id", groupModel.Id)
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
if (affected != 0)
|
||||
result = true;
|
||||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
// Feed
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? feedName = null)
|
||||
{
|
||||
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
|
||||
_sqlConn.Open();
|
||||
|
||||
SqliteCommand cmd = _sqlConn.CreateCommand();
|
||||
cmd.CommandText = categoryId == null ? "SELECT * FROM feed_data" : "SELECT * FROM feed_data WHERE category_id=@categoryId";
|
||||
if (categoryId != null)
|
||||
cmd.Parameters.Add(new SqliteParameter("categoryId", categoryId));
|
||||
|
||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||
while (reader.Read())
|
||||
SqliteCommand cmd = new SqliteCommand(feedName != null ? $"SELECT * FROM {_feedTable} WHERE name=@name" : $"SELECT * FROM {_feedTable}", _sqlConn)
|
||||
{
|
||||
//feeds.Add(FeedModel.Create(reader["url"].ToString(), reader["feed_id"].ToString(), reader["category_id"].ToString()));
|
||||
Parameters =
|
||||
{
|
||||
new SqliteParameter("name", feedName)
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
Log.Verbose("{FeedAmount} feeds found!", affected);
|
||||
_sqlConn.Close();
|
||||
return feeds;
|
||||
}
|
||||
|
||||
public async Task<bool> AddFeedAsync(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)" +
|
||||
$"VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @groupId, @feedType, @description, @language, @copyright, @dateAdded, @lastUpdated, @imageUrl)", _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", feedModel.Copyright),
|
||||
new SqliteParameter("dateAdded", feedModel.DateAdded.ToUnixTimeMilliseconds()),
|
||||
new SqliteParameter("lastUpdated", feedModel.LastUpdated.ToUnixTimeMilliseconds()),
|
||||
new SqliteParameter("imageUrl", feedModel.ImageUrl)
|
||||
}
|
||||
};
|
||||
int affected = await cmd.ExecuteNonQueryAsync();
|
||||
if (affected != 0)
|
||||
result = true;
|
||||
_sqlConn.Close();
|
||||
return result;
|
||||
}
|
||||
// Feed item
|
||||
|
||||
private async void InitializeDb()
|
||||
{
|
||||
Log.Verbose("Checking database...");
|
||||
HashSet<string> failed = new HashSet<string>();
|
||||
_sqlConn.Open();
|
||||
Log.Verbose("Checking table: {Table}", _groupTable);
|
||||
var queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_groupTable} (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY, CONSTRAINT name UNIQUE (name))");
|
||||
var queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_groupTable} (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY)");
|
||||
if (queryResponse.Any()) failed.Add("category_data");
|
||||
|
||||
Log.Verbose("Checking table: {Table}", _feedTable);
|
||||
queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedTable} (url STRING NOT NULL, id STRING PRIMARY KEY, group_id STRING DEFAULT NULL, CONSTRAINT url, UNIQUE (url))");
|
||||
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)");
|
||||
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 NOT NULL)");
|
||||
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)");
|
||||
if (queryResponse.Any()) failed.Add("feed_item_data");
|
||||
|
||||
_sqlConn.Close();
|
||||
|
|
|
@ -15,13 +15,23 @@ namespace SharpRss.Services
|
|||
{
|
||||
public RssService()
|
||||
{
|
||||
//SetupTestCategoriesAndFeedsAsync();
|
||||
SetupTestCategoriesAndFeedsAsync();
|
||||
}
|
||||
private readonly DatabaseService _dbService = new DatabaseService();
|
||||
|
||||
/*private async void SetupTestCategoriesAndFeedsAsync()
|
||||
private async void SetupTestCategoriesAndFeedsAsync()
|
||||
{
|
||||
await _dbService.AddCategoriesAsync(new HashSet<CategoryModel>()
|
||||
/*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<CategoryModel>()
|
||||
{
|
||||
new CategoryModel() { Name = "All" },
|
||||
new CategoryModel() { Name = "RSS" },
|
||||
|
@ -34,59 +44,7 @@ namespace SharpRss.Services
|
|||
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 async Task<Feed> GetFeedAsync(string rssUrl)
|
||||
{
|
||||
/*return await FeedCache.GetFeed(rssUrl);*/
|
||||
return new Feed();
|
||||
}
|
||||
|
||||
public async Task<HashSet<object>> GetAllUnsortedAsync()
|
||||
{
|
||||
HashSet<object> items = new HashSet<object>();
|
||||
/*var categories = await _dbService.GetCategoriesAsync();
|
||||
var feeds = await _dbService.GetFeedsAsync(string.Empty);
|
||||
items.UnionWith(categories);
|
||||
items.UnionWith(feeds);*/
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<HashSet<GroupModel>> GetCategoriesAsync()
|
||||
{
|
||||
/*var result = await _dbService.GetCategoriesAsync();
|
||||
return result.OrderBy(x => x.Name).ToHashSet();*/
|
||||
return new HashSet<GroupModel>();
|
||||
}
|
||||
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(GroupModel? categoryModel = null)
|
||||
{
|
||||
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
|
||||
/*if (categoryModel != null)
|
||||
feeds = await _dbService.GetFeedsAsync(categoryModel.Id);
|
||||
else
|
||||
feeds = await _dbService.GetFeedsAsync();*/
|
||||
return feeds;
|
||||
}
|
||||
|
||||
public async void AddCategoryAsync(string name, string? icon, string hexColor)
|
||||
{
|
||||
/*GroupModel groupModel = new GroupModel()
|
||||
{
|
||||
Name = name
|
||||
};
|
||||
if (icon != null)
|
||||
groupModel.PathIcon = icon;
|
||||
if (!hexColor.IsNullEmptyWhiteSpace())
|
||||
groupModel.HexColor = hexColor;*/
|
||||
//await _dbService.AddCategoriesAsync(new HashSet<GroupModel>() { groupModel });
|
||||
}
|
||||
|
||||
public async void AddFeedAsync(string rssUrl, GroupModel? category = null)
|
||||
{
|
||||
//FeedModel feedModel = new FeedModel(rssUrl, category);
|
||||
//await _dbService.AddFeedsAsync(new HashSet<FeedModel>() { feedModel });
|
||||
});*/
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.5" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user