mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2024-11-09 23:44:20 +01:00
Reworking db & Syndication implementation
This commit is contained in:
parent
924e174240
commit
1f0e8840c1
|
@ -21,9 +21,8 @@ namespace SharpRss
|
||||||
private const string FeedItemTable = "feed_item_data";
|
private const string FeedItemTable = "feed_item_data";
|
||||||
|
|
||||||
// Groups
|
// Groups
|
||||||
public static async Task<HashSet<GroupModel>> GetGroupsAsync(string? groupId = null)
|
public static async Task<HashSet<CategoryModel>> GetGroupsAsync(string? groupId = null)
|
||||||
{
|
{
|
||||||
CheckInitialized();
|
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {GroupTable} WHERE id=@gId;" : $"SELECT * FROM {GroupTable}", dbc)
|
await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {GroupTable} WHERE id=@gId;" : $"SELECT * FROM {GroupTable}", dbc)
|
||||||
|
@ -34,7 +33,7 @@ namespace SharpRss
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||||
HashSet<GroupModel> groups = new HashSet<GroupModel>();
|
HashSet<CategoryModel> groups = new HashSet<CategoryModel>();
|
||||||
await using SqliteCommand cmdFeedCount = new SqliteCommand($"SELECT COUNT(*) FROM {FeedTable} WHERE group_id=@groupId", dbc);
|
await using SqliteCommand cmdFeedCount = new SqliteCommand($"SELECT COUNT(*) FROM {FeedTable} WHERE group_id=@groupId", dbc);
|
||||||
while (reader.Read())
|
while (reader.Read())
|
||||||
{
|
{
|
||||||
|
@ -43,7 +42,7 @@ namespace SharpRss
|
||||||
using SqliteDataReader countReader = await cmdFeedCount.ExecuteReaderAsync();
|
using SqliteDataReader countReader = await cmdFeedCount.ExecuteReaderAsync();
|
||||||
int count = countReader.Read() ? countReader.GetInt32(0) : 0;
|
int count = countReader.Read() ? countReader.GetInt32(0) : 0;
|
||||||
|
|
||||||
groups.Add(new GroupModel()
|
groups.Add(new CategoryModel()
|
||||||
{
|
{
|
||||||
Name = reader["name"].ToString(),
|
Name = reader["name"].ToString(),
|
||||||
FeedCount = count,
|
FeedCount = count,
|
||||||
|
@ -54,7 +53,7 @@ namespace SharpRss
|
||||||
}
|
}
|
||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
public static async Task<bool> SetGroupAsync(GroupModel groupModel)
|
public static async Task<bool> SetGroupAsync(CategoryModel groupModel)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
|
@ -74,7 +73,7 @@ namespace SharpRss
|
||||||
result = true;
|
result = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public static async Task<bool> RemoveGroupAsync(GroupModel groupModel)
|
public static async Task<bool> RemoveGroupAsync(CategoryModel groupModel)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
|
@ -93,6 +92,7 @@ namespace SharpRss
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
// Feeds
|
// Feeds
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
///
|
///
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -115,14 +115,15 @@ namespace SharpRss
|
||||||
feeds.Add(await ReaderToFeedModel(reader));
|
feeds.Add(await ReaderToFeedModel(reader));
|
||||||
return feeds;
|
return feeds;
|
||||||
}
|
}
|
||||||
public static async Task<FeedModel?> GetFeedAsync(string feedId)
|
public static async Task<FeedModel?> GetFeedAsync(string url)
|
||||||
{
|
{
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
FeedModel? feed = null;
|
FeedModel? feed = null;
|
||||||
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {FeedTable} WHERE id=@id", dbc)
|
//TODO: Use dapper to simplify this query.
|
||||||
|
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {FeedTable} WHERE url=@Url", dbc)
|
||||||
{
|
{
|
||||||
Parameters = { new SqliteParameter("id", feedId) }
|
Parameters = { new SqliteParameter("Url", url) }
|
||||||
};
|
};
|
||||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
|
@ -241,7 +242,7 @@ namespace SharpRss
|
||||||
};
|
};
|
||||||
if (feedItemModel is { FeedId: { } })
|
if (feedItemModel is { FeedId: { } })
|
||||||
{
|
{
|
||||||
FeedModel? feedModel = await GetFeedAsync(feedItemModel.FeedId);
|
FeedModel? feedModel = await GetFeedAsync(feedItemModel.FeedUrl);
|
||||||
feedItemModel.Feed = feedModel;
|
feedItemModel.Feed = feedModel;
|
||||||
}
|
}
|
||||||
feedItems.Add(feedItemModel);
|
feedItems.Add(feedItemModel);
|
||||||
|
@ -303,9 +304,9 @@ namespace SharpRss
|
||||||
result = true;
|
result = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
public static async Task<GroupModel?> GetGroupFromFeedItemAsync(FeedItemModel feedItem)
|
public static async Task<CategoryModel?> GetGroupFromFeedItemAsync(FeedItemModel feedItem)
|
||||||
{
|
{
|
||||||
GroupModel? result = null;
|
CategoryModel? result = null;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {GroupTable} WHERE id=(SELECT group_id FROM {FeedTable} WHERE id=@fId)", dbc)
|
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {GroupTable} WHERE id=(SELECT group_id FROM {FeedTable} WHERE id=@fId)", dbc)
|
||||||
|
@ -316,7 +317,7 @@ namespace SharpRss
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
|
||||||
HashSet<GroupModel>? groups = null;
|
HashSet<CategoryModel>? groups = null;
|
||||||
if (reader.Read())
|
if (reader.Read())
|
||||||
groups = await GetGroupsAsync(reader["group_id"].ToString());
|
groups = await GetGroupsAsync(reader["group_id"].ToString());
|
||||||
if (groups != null && groups.Any())
|
if (groups != null && groups.Any())
|
||||||
|
@ -348,10 +349,6 @@ namespace SharpRss
|
||||||
}
|
}
|
||||||
|
|
||||||
//===
|
//===
|
||||||
private static void CheckInitialized()
|
|
||||||
{
|
|
||||||
if (!_isInitialized) throw new TypeInitializationException(nameof(DbAccess), null);
|
|
||||||
}
|
|
||||||
public static async void Initialize()
|
public static async void Initialize()
|
||||||
{
|
{
|
||||||
if (_isInitialized) return;
|
if (_isInitialized) return;
|
||||||
|
@ -359,17 +356,17 @@ namespace SharpRss
|
||||||
HashSet<string> failed = new HashSet<string>();
|
HashSet<string> failed = new HashSet<string>();
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
Log.Verbose("Checking table: {Table}", GroupTable);
|
Log.Verbose("Checking table: {Table}", "category");
|
||||||
var queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS {GroupTable} (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY)");
|
var queryResponse = await dbc.QueryAsync("CREATE TABLE IF NOT EXISTS category (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY)");
|
||||||
if (queryResponse.Any()) failed.Add("category_data");
|
if (queryResponse.Any()) failed.Add("category");
|
||||||
|
|
||||||
Log.Verbose("Checking table: {Table}", FeedTable);
|
Log.Verbose("Checking table: {Table}", "feed");
|
||||||
queryResponse = await dbc.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)");
|
queryResponse = await dbc.QueryAsync($"CREATE TABLE IF NOT EXISTS feed (url STRING PRIMARY KEY, 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");
|
if (queryResponse.Any()) failed.Add("feed");
|
||||||
|
|
||||||
Log.Verbose("Checking table: {Table}", FeedItemTable);
|
Log.Verbose("Checking table: {Table}", "feed_item");
|
||||||
queryResponse = await dbc.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)");
|
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)");
|
||||||
if (queryResponse.Any()) failed.Add("feed_item_data");
|
if (queryResponse.Any()) failed.Add("feed_item");
|
||||||
|
|
||||||
if (failed.Any())
|
if (failed.Any())
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,9 +3,9 @@ using ToolQit;
|
||||||
|
|
||||||
namespace SharpRss.Models
|
namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
public class GroupModel
|
public class CategoryModel
|
||||||
{
|
{
|
||||||
public GroupModel()
|
public CategoryModel()
|
||||||
{
|
{
|
||||||
HexColor = Utilities.GenerateRandomHexColor();
|
HexColor = Utilities.GenerateRandomHexColor();
|
||||||
Id = Guid.NewGuid().ToString();
|
Id = Guid.NewGuid().ToString();
|
|
@ -6,7 +6,9 @@ namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
public FeedModel? Feed { get; set; }
|
public FeedModel? Feed { get; set; }
|
||||||
public string? Id { get; set; } = string.Empty;
|
public string? Id { get; set; } = string.Empty;
|
||||||
|
// FeedId will be removed
|
||||||
public string? FeedId { get; set; } = string.Empty;
|
public string? FeedId { get; set; } = string.Empty;
|
||||||
|
public string FeedUrl { get; set; } = string.Empty;
|
||||||
public bool Read { get; set; }
|
public bool Read { get; set; }
|
||||||
public string? Type { get; set; } = string.Empty;
|
public string? Type { get; set; } = string.Empty;
|
||||||
public string? Title { get; set; } = string.Empty;
|
public string? Title { get; set; } = string.Empty;
|
||||||
|
|
|
@ -7,9 +7,8 @@ namespace SharpRss.Models
|
||||||
public FeedModel(string rssUrl)
|
public FeedModel(string rssUrl)
|
||||||
{
|
{
|
||||||
Url = rssUrl;
|
Url = rssUrl;
|
||||||
Id = Guid.NewGuid().ToString();
|
|
||||||
}
|
}
|
||||||
public GroupModel? Group { get; set; }
|
public CategoryModel? Group { get; set; }
|
||||||
public string? Id { get; set; }
|
public string? Id { get; set; }
|
||||||
public string? Url { get; set; }
|
public string? Url { get; set; }
|
||||||
public string? Title { get; set; } = string.Empty;
|
public string? Title { get; set; } = string.Empty;
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Argotic.Common;
|
using Argotic.Common;
|
||||||
using Argotic.Syndication;
|
using Argotic.Syndication;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SharpRss.Models;
|
using SharpRss.Models;
|
||||||
|
|
||||||
|
@ -26,14 +27,50 @@ namespace SharpRss.Services
|
||||||
items.UnionWith(await GetUngroupedFeedsAsync());
|
items.UnionWith(await GetUngroupedFeedsAsync());
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
public async Task<bool> CreateGroupAsync(GroupModel group) => await DbAccess.SetGroupAsync(group);
|
public async Task<bool> CreateGroupAsync(CategoryModel group) => await DbAccess.SetGroupAsync(group);
|
||||||
public async Task<HashSet<GroupModel>> GetGroupsAsync() => await DbAccess.GetGroupsAsync();
|
public async Task<HashSet<CategoryModel>> GetGroupsAsync() => await DbAccess.GetGroupsAsync();
|
||||||
|
|
||||||
//TODO: Need to rework this implementation!!!
|
//TODO: Rework this!
|
||||||
public async Task<bool> AddFeedsAsync(string[]? rssUrls, GroupModel? group = null)
|
// Subscribe to a feed.
|
||||||
|
public async Task<bool> AddSubscriptionAsync(string url, CategoryModel? group = null)
|
||||||
{
|
{
|
||||||
|
// Check for valid feed url
|
||||||
|
bool validate = SyndicationDiscoveryUtility.UriExists(new Uri(url));
|
||||||
|
if (!validate) return false;
|
||||||
|
// Check if feed exists in db
|
||||||
|
FeedModel? dbFeed = await DbAccess.GetFeedAsync(url);
|
||||||
|
if (dbFeed == null)
|
||||||
|
{
|
||||||
|
GenericSyndicationFeed genFeed = new GenericSyndicationFeed();
|
||||||
|
switch (genFeed.Format)
|
||||||
|
{
|
||||||
|
case SyndicationContentFormat.Rss:
|
||||||
|
RssFeed rssFeed = (RssFeed)genFeed.Resource;
|
||||||
|
break;
|
||||||
|
case SyndicationContentFormat.Atom:
|
||||||
|
AtomFeed atomFeed = (AtomFeed)genFeed.Resource;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Log.Information("Feed implementation missing!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Update feed if newer
|
||||||
|
// Update/fetch items
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
private static FeedModel FromResource(ISyndicationResource resource)
|
||||||
|
{
|
||||||
|
FeedModel model = new FeedModel("");
|
||||||
|
switch (resource)
|
||||||
|
{
|
||||||
|
case RssFeed rssFeed:
|
||||||
|
//TODO: From feed to model
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task UpdateFeeds()
|
public async Task UpdateFeeds()
|
||||||
{
|
{
|
||||||
|
@ -122,14 +159,14 @@ namespace SharpRss.Services
|
||||||
throw;
|
throw;
|
||||||
}*/
|
}*/
|
||||||
var groups = await GetGroupsAsync();
|
var groups = await GetGroupsAsync();
|
||||||
GroupModel testGroup = groups.Single(x => x.Name == "News");
|
CategoryModel testGroup = groups.Single(x => x.Name == "News");
|
||||||
await AddFeedsAsync(new[]
|
/*await AddFeedsAsync(new[]
|
||||||
{
|
{
|
||||||
"https://www.nu.nl/rss/Algemeen",
|
"https://www.nu.nl/rss/Algemeen",
|
||||||
"https://www.nu.nl/rss/Economie",
|
"https://www.nu.nl/rss/Economie",
|
||||||
"https://www.nu.nl/rss/Sport",
|
"https://www.nu.nl/rss/Sport",
|
||||||
"http://news.google.com/?output=atom"
|
"http://news.google.com/?output=atom"
|
||||||
}, testGroup);
|
}, testGroup);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|
|
@ -18,12 +18,6 @@ namespace WebSharpRSS
|
||||||
//paths.Set("FaviconResolveUrl", "https://icons.duckduckgo.com/ip3/{0}.ico", false);
|
//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("FaviconResolveUrl", "http://www.google.com/s2/favicons?domain={0}", false);
|
||||||
paths.Set("LogPath", Path.Combine(Environment.CurrentDirectory, "logs", "log_.json"), false);
|
paths.Set("LogPath", Path.Combine(Environment.CurrentDirectory, "logs", "log_.json"), false);
|
||||||
|
|
||||||
var dbSql = dataCon["SQL"];
|
|
||||||
dbSql.Set("Host", "localhost", false);
|
|
||||||
dbSql.Set("Port", "6969", false);
|
|
||||||
dbSql.Set("Username", "sharpUser", false);
|
|
||||||
dbSql.Set("Password", "sh@rP@s$", false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static LoggerConfiguration? _configuration;
|
private static LoggerConfiguration? _configuration;
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace WebSharpRSS.Models
|
||||||
{
|
{
|
||||||
public class TreeItemData
|
public class TreeItemData
|
||||||
{
|
{
|
||||||
public TreeItemData(GroupModel groupModel)
|
public TreeItemData(CategoryModel groupModel)
|
||||||
{
|
{
|
||||||
GroupModel = groupModel;
|
GroupModel = groupModel;
|
||||||
Title = groupModel.Name;
|
Title = groupModel.Name;
|
||||||
|
@ -23,7 +23,7 @@ namespace WebSharpRSS.Models
|
||||||
if (FeedModel.Url == null) return;
|
if (FeedModel.Url == null) return;
|
||||||
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.Url).Host);
|
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), new Uri(FeedModel.Url).Host);
|
||||||
}
|
}
|
||||||
public readonly GroupModel? GroupModel;
|
public readonly CategoryModel? GroupModel;
|
||||||
public readonly FeedModel? FeedModel;
|
public readonly FeedModel? FeedModel;
|
||||||
|
|
||||||
public HashSet<TreeItemData>? Children { get; set; }
|
public HashSet<TreeItemData>? Children { get; set; }
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
{
|
|
||||||
"Paths": {
|
|
||||||
"FaviconResolveUrl": "http://www.google.com/s2/favicons?domain={0}",
|
|
||||||
"LogPath": "/home/max/GitHub/SharpRSS/WebSharpRSS/logs/log_.json"
|
|
||||||
},
|
|
||||||
"SQL": {
|
|
||||||
"Host": "localhost",
|
|
||||||
"Port": "6969",
|
|
||||||
"Username": "sharpUser",
|
|
||||||
"Password": "sh@rP@s$"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -76,5 +76,5 @@
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
Log.Verbose("Guide initialized!");
|
Log.Verbose("Guide initialized!");
|
||||||
}
|
}
|
||||||
private HashSet<TreeItemData> ModelToTreeItem<T>(HashSet<T> model) => model.Select(x => x is GroupModel model ? new TreeItemData(model) : x is FeedModel feedModel ? new TreeItemData(feedModel) : throw new ArgumentException("Item arg is invalid!")).ToHashSet();
|
private HashSet<TreeItemData> ModelToTreeItem<T>(HashSet<T> model) => model.Select(x => x is CategoryModel model ? new TreeItemData(model) : x is FeedModel feedModel ? new TreeItemData(feedModel) : throw new ArgumentException("Item arg is invalid!")).ToHashSet();
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user