mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
Reworked backend & DbAccess
This commit is contained in:
parent
ea91abe629
commit
13d5c207f5
37
SharpRss/Core/Cache/TempCache.cs
Normal file
37
SharpRss/Core/Cache/TempCache.cs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using SharpRss.Models;
|
||||||
|
|
||||||
|
namespace SharpRss.Core.Cache
|
||||||
|
{
|
||||||
|
internal enum CacheFetch
|
||||||
|
{
|
||||||
|
Category,
|
||||||
|
Syndication
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static class TempCache
|
||||||
|
{
|
||||||
|
private static Dictionary<string, CategoryModel> _categoryCache = new Dictionary<string, CategoryModel>();
|
||||||
|
private static Dictionary<string, SyndicationModel> _syndicationCache = new Dictionary<string, SyndicationModel>();
|
||||||
|
|
||||||
|
public static async Task UpdateCache(CacheFetch cf)
|
||||||
|
{
|
||||||
|
switch (cf)
|
||||||
|
{
|
||||||
|
case CacheFetch.Category:
|
||||||
|
var cats = await DbAccess.GetCategoriesAsync();
|
||||||
|
_categoryCache = cats.ToDictionary(x => x.Id);
|
||||||
|
break;
|
||||||
|
case CacheFetch.Syndication:
|
||||||
|
var syndications = await DbAccess.GetSyndicationsAsync();
|
||||||
|
_syndicationCache = syndications.ToDictionary(x => x.EncodedUrl);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CategoryModel? GetCategory(string catId) => _categoryCache.TryGetValue(catId, out CategoryModel catModel) ? catModel : null;
|
||||||
|
public static SyndicationModel? GetSyndication(string encodedUrl) => _syndicationCache.TryGetValue(encodedUrl, out SyndicationModel synModel) ? synModel : null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,26 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using SharpRss.Models;
|
|
||||||
using SharpRss.Services;
|
|
||||||
|
|
||||||
namespace SharpRss.Core
|
|
||||||
{
|
|
||||||
public class FeedCache
|
|
||||||
{
|
|
||||||
public FeedCache()
|
|
||||||
{
|
|
||||||
FetchFeeds();
|
|
||||||
}
|
|
||||||
private readonly SyndicationService _syndicationService = new SyndicationService();
|
|
||||||
private Dictionary<string, SyndicationModel> _cachedFeeds = new Dictionary<string, SyndicationModel>();
|
|
||||||
|
|
||||||
private async void FetchFeeds()
|
|
||||||
{
|
|
||||||
HashSet<SyndicationModel> fetchedFeeds = await _syndicationService.GetFeedsAsync();
|
|
||||||
_cachedFeeds = fetchedFeeds.ToDictionary(x => x.EncodedUrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SyndicationModel? CacheFeed(string encodedUrl) => _cachedFeeds.TryGetValue(encodedUrl, out SyndicationModel model) ? model : null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||||
using Dapper;
|
using Dapper;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using SharpRss.Core;
|
using SharpRss.Core.Cache;
|
||||||
using SharpRss.Models;
|
using SharpRss.Models;
|
||||||
|
|
||||||
namespace SharpRss
|
namespace SharpRss
|
||||||
|
@ -44,9 +44,10 @@ namespace SharpRss
|
||||||
Id = reader["id"].ToString(),
|
Id = reader["id"].ToString(),
|
||||||
Name = reader["name"].ToString(),
|
Name = reader["name"].ToString(),
|
||||||
HexColor = reader["hex_color"].ToString(),
|
HexColor = reader["hex_color"].ToString(),
|
||||||
Icon = reader["icon"].ToString()
|
Icon = reader["icon"].ToString(),
|
||||||
|
LastUpdated = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString()))
|
||||||
};
|
};
|
||||||
categoryModel.SyndicationCount = await dbc.ExecuteScalarAsync<int>($"SELECT COUNT(*) FROM feed WHERE category_id=@CatId", new { CatId = categoryModel.Id });
|
categoryModel.SyndicationCount = await dbc.ExecuteScalarAsync<int>($"SELECT COUNT(*) FROM syndication WHERE category_id=@CatId", new { CatId = categoryModel.Id });
|
||||||
categories.Add(categoryModel);
|
categories.Add(categoryModel);
|
||||||
}
|
}
|
||||||
return categories;
|
return categories;
|
||||||
|
@ -57,8 +58,8 @@ namespace SharpRss
|
||||||
if (category == null) return modelReturn;
|
if (category == null) return modelReturn;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
int affected = await dbc.ExecuteAsync("INSERT OR REPLACE INTO category (id, hex_color, icon, name) VALUES (IFNULL((SELECT id FROM category WHERE name=@Name), @Id), @HexColor, @Icon, @Name)",
|
int affected = await dbc.ExecuteAsync("INSERT OR REPLACE INTO category (id, name, hex_color, last_updated) VALUES (IFNULL((SELECT id FROM category WHERE name=@Name), @Id), @Name, @HexColor, @LastUpdated)",
|
||||||
new { category.Id, category.HexColor, category.Icon, category.Name });
|
new { Id = category.Id, Name = category.Name, HexColor = category.HexColor, LastUpdated = category.LastUpdated.ToUnixTimeMilliseconds() });
|
||||||
if (affected <= 0) return modelReturn;
|
if (affected <= 0) return modelReturn;
|
||||||
var catModel = await GetCategoriesAsync();
|
var catModel = await GetCategoriesAsync();
|
||||||
modelReturn = catModel.Where(x => x.Name == category.Name).ToHashSet().FirstOrDefault() ?? null;
|
modelReturn = catModel.Where(x => x.Name == category.Name).ToHashSet().FirstOrDefault() ?? null;
|
||||||
|
@ -69,7 +70,7 @@ namespace SharpRss
|
||||||
if (category == null) return false;
|
if (category == null) return false;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
int affected = await dbc.ExecuteAsync("DELETE FROM category WHERE id=@Id; UPDATE feed SET category_id=NULL WHERE category_id=@Id",new { category.Id });
|
int affected = await dbc.ExecuteAsync("DELETE FROM category WHERE id=@Id; UPDATE syndication SET category_id=NULL WHERE category_id=@Id",new { category.Id });
|
||||||
return affected > 0;
|
return affected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,30 +78,32 @@ namespace SharpRss
|
||||||
{
|
{
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO feed
|
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO syndication
|
||||||
(encoded_url,
|
(encoded_url,
|
||||||
title,
|
title,
|
||||||
category_id,
|
category_id,
|
||||||
feed_type,
|
syndication_type,
|
||||||
feed_version,
|
version,
|
||||||
description,
|
description,
|
||||||
language,
|
language,
|
||||||
copyright,
|
copyright,
|
||||||
publication_date,
|
|
||||||
last_updated,
|
last_updated,
|
||||||
|
publication_date,
|
||||||
|
syn_updated_date,
|
||||||
categories,
|
categories,
|
||||||
image_url)
|
image_url)
|
||||||
VALUES (
|
VALUES (
|
||||||
@EncodedUrl,
|
@EncodedUrl,
|
||||||
@Title,
|
@Title,
|
||||||
@CategoryId,
|
@CategoryId,
|
||||||
@FeedType,
|
@SyndicationType,
|
||||||
@FeedVersion,
|
@Version,
|
||||||
@Description,
|
@Description,
|
||||||
@Language,
|
@Language,
|
||||||
@Copyright,
|
@Copyright,
|
||||||
@PublicationDate,
|
|
||||||
@LastUpdated,
|
@LastUpdated,
|
||||||
|
@PublicationDate,
|
||||||
|
@SynUpdatedDate,
|
||||||
@Categories,
|
@Categories,
|
||||||
@ImageUrl)",
|
@ImageUrl)",
|
||||||
new
|
new
|
||||||
|
@ -108,13 +111,14 @@ namespace SharpRss
|
||||||
EncodedUrl = syndication.EncodedUrl,
|
EncodedUrl = syndication.EncodedUrl,
|
||||||
Title = syndication.Title ?? string.Empty,
|
Title = syndication.Title ?? string.Empty,
|
||||||
CategoryId = syndication.CategoryId ?? string.Empty,
|
CategoryId = syndication.CategoryId ?? string.Empty,
|
||||||
FeedType = syndication.SyndicationType ?? string.Empty,
|
SyndicationType = syndication.SyndicationType ?? string.Empty,
|
||||||
FeedVersion = syndication.SyndicationVersion ?? string.Empty,
|
Version = syndication.Version ?? string.Empty,
|
||||||
Description = syndication.Description ?? string.Empty,
|
Description = syndication.Description ?? string.Empty,
|
||||||
Language = syndication.Language ?? string.Empty,
|
Language = syndication.Language ?? string.Empty,
|
||||||
Copyright = syndication.Copyright ?? string.Empty,
|
Copyright = syndication.Copyright ?? string.Empty,
|
||||||
|
LastUpdated = syndication.LastUpdated.ToUnixTimeMilliseconds(),
|
||||||
PublicationDate = syndication.PublicationDate?.ToUnixTimeMilliseconds() ?? 0,
|
PublicationDate = syndication.PublicationDate?.ToUnixTimeMilliseconds() ?? 0,
|
||||||
LastUpdated = syndication.SynUpdatedDate?.ToUnixTimeMilliseconds() ?? 0,
|
SynUpdatedDate = syndication.SynUpdatedDate?.ToUnixTimeMilliseconds() ?? 0,
|
||||||
Categories = syndication.Categories != null && syndication.Categories.Any() ? SyndicationManager.FormatStringArrayToString(syndication.Categories) : string.Empty,
|
Categories = syndication.Categories != null && syndication.Categories.Any() ? SyndicationManager.FormatStringArrayToString(syndication.Categories) : string.Empty,
|
||||||
ImageUrl = syndication.ImageUrl ?? string.Empty
|
ImageUrl = syndication.ImageUrl ?? string.Empty
|
||||||
});
|
});
|
||||||
|
@ -125,8 +129,9 @@ namespace SharpRss
|
||||||
{
|
{
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
|
await TempCache.UpdateCache(CacheFetch.Category);
|
||||||
HashSet<SyndicationModel> feeds = new HashSet<SyndicationModel>();
|
HashSet<SyndicationModel> feeds = new HashSet<SyndicationModel>();
|
||||||
await using DbDataReader reader = await dbc.ExecuteReaderAsync(categoryIds == null ? "SELECT * FROM feed" : "SELECT * FROM feed WHERE category_id IN(@CatIds)", new { CatIds = categoryIds });
|
await using DbDataReader reader = await dbc.ExecuteReaderAsync(categoryIds == null ? "SELECT * FROM syndication" : "SELECT * FROM syndication WHERE category_id IN(@CatIds)", new { CatIds = categoryIds });
|
||||||
while (await reader.ReadAsync())
|
while (await reader.ReadAsync())
|
||||||
{
|
{
|
||||||
SyndicationModel syndicationModel = new SyndicationModel()
|
SyndicationModel syndicationModel = new SyndicationModel()
|
||||||
|
@ -134,17 +139,19 @@ namespace SharpRss
|
||||||
EncodedUrl = reader["encoded_url"].ToString(),
|
EncodedUrl = reader["encoded_url"].ToString(),
|
||||||
Title = reader["title"].ToString(),
|
Title = reader["title"].ToString(),
|
||||||
CategoryId = reader["category_id"].ToString(),
|
CategoryId = reader["category_id"].ToString(),
|
||||||
SyndicationType = reader["feed_type"].ToString(),
|
SyndicationType = reader["syndication_type"].ToString(),
|
||||||
SyndicationVersion = reader["feed_version"].ToString(),
|
Version = reader["version"].ToString(),
|
||||||
Description = reader["description"].ToString(),
|
Description = reader["description"].ToString(),
|
||||||
Language = reader["language"].ToString(),
|
Language = reader["language"].ToString(),
|
||||||
Copyright = reader["copyright"].ToString(),
|
Copyright = reader["copyright"].ToString(),
|
||||||
|
LastUpdated = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())),
|
||||||
PublicationDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publication_date"].ToString())),
|
PublicationDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publication_date"].ToString())),
|
||||||
SynUpdatedDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())),
|
SynUpdatedDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["syn_updated_date"].ToString())),
|
||||||
Categories = SyndicationManager.StringToStringArray(reader["categories"].ToString()),
|
Categories = SyndicationManager.StringToStringArray(reader["categories"].ToString()),
|
||||||
ImageUrl = reader["image_url"].ToString()
|
ImageUrl = reader["image_url"].ToString()
|
||||||
};
|
};
|
||||||
syndicationModel.ItemCount = await dbc.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM feed_item WHERE encoded_feed_url=@EncodedFeedUrl", new { EncodedFeedUrl = syndicationModel.EncodedUrl });
|
syndicationModel.Category = TempCache.GetCategory(syndicationModel.CategoryId);
|
||||||
|
syndicationModel.ItemCount = await dbc.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM syndication_item WHERE encoded_syndication_url=@EncodedFeedUrl", new { EncodedFeedUrl = syndicationModel.EncodedUrl });
|
||||||
feeds.Add(syndicationModel);
|
feeds.Add(syndicationModel);
|
||||||
}
|
}
|
||||||
return feeds;
|
return feeds;
|
||||||
|
@ -153,9 +160,9 @@ namespace SharpRss
|
||||||
{
|
{
|
||||||
if (syndication == null) return false;
|
if (syndication == null) return false;
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
int affected = await dbc.ExecuteAsync("DELETE FROM feed WHERE encoded_url=@EncodedUrl", new { EncodedUrl = syndication.EncodedUrl });
|
int affected = await dbc.ExecuteAsync("DELETE FROM syndication WHERE encoded_url=@EncodedUrl", new { EncodedUrl = syndication.EncodedUrl });
|
||||||
if (affected > 0 && deleteItems)
|
if (affected > 0 && deleteItems)
|
||||||
await dbc.ExecuteAsync("DELETE FROM feed_item WHERE encoded_feed_url=@EncodedUrl", new { EncodedUrl = syndication.EncodedUrl });
|
await dbc.ExecuteAsync("DELETE FROM syndication_item WHERE encoded_syndication_url=@EncodedUrl", new { EncodedUrl = syndication.EncodedUrl });
|
||||||
return affected > 0;
|
return affected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,53 +174,57 @@ namespace SharpRss
|
||||||
await using SqliteTransaction dbTransaction = dbc.BeginTransaction();
|
await using SqliteTransaction dbTransaction = dbc.BeginTransaction();
|
||||||
foreach (SyndicationItemModel item in items)
|
foreach (SyndicationItemModel item in items)
|
||||||
{
|
{
|
||||||
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO feed_item (id, encoded_feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)
|
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO syndication_item (link, encoded_syndication_url, read, type, title, description, last_updated, item_updated_date, publishing_date, authors, categories, content, comments_url)
|
||||||
VALUES (@Id, @EncodedFeedUrl, @Read, @Title, @Description, @Link, @LastUpdated, @PublishingDate, @Authors, @Categories, @Content)",
|
VALUES (@Link, @EncodedSyndicationUrl, @Read, @Type, @Title, @Description, @LastUpdated, @ItemUpdatedDate, @PublishingDate, @Authors, @Categories, @Content, @CommentsUrl)",
|
||||||
transaction: dbTransaction,
|
transaction: dbTransaction,
|
||||||
param: new
|
param: new
|
||||||
{
|
{
|
||||||
Id = item.Id ?? string.Empty,
|
Link = item.Link ?? string.Empty,
|
||||||
EncodedFeedUrl = item.EncodedSyndicationUrl ?? string.Empty,
|
EncodedSyndicationUrl = item.EncodedSyndicationUrl ?? string.Empty,
|
||||||
Read = item.Read.ToString(),
|
Read = item.Read.ToString(),
|
||||||
|
Type = item.Type ?? string.Empty,
|
||||||
Title = item.Title ?? string.Empty,
|
Title = item.Title ?? string.Empty,
|
||||||
Description = item.Description ?? string.Empty,
|
Description = item.Description ?? string.Empty,
|
||||||
Link = item.Link ?? string.Empty,
|
LastUpdated = item.LastUpdated.ToUnixTimeMilliseconds(),
|
||||||
LastUpdated = item.ItemUpdatedDate?.ToUnixTimeMilliseconds() ?? 0,
|
ItemUpdatedDate = item.ItemUpdatedDate?.ToUnixTimeMilliseconds() ?? 0,
|
||||||
PublishingDate = item.PublishingDate?.ToUnixTimeMilliseconds() ?? 0,
|
PublishingDate = item.PublishingDate?.ToUnixTimeMilliseconds() ?? 0,
|
||||||
Authors = item.Authors != null && item.Authors.Any() ? SyndicationManager.FormatStringArrayToString(item.Authors) : string.Empty,
|
Authors = item.Authors != null && item.Authors.Any() ? SyndicationManager.FormatStringArrayToString(item.Authors) : string.Empty,
|
||||||
Categories = item.Categories != null && item.Categories.Any() ? SyndicationManager.FormatStringArrayToString(item.Categories) : string.Empty,
|
Categories = item.Categories != null && item.Categories.Any() ? SyndicationManager.FormatStringArrayToString(item.Categories) : string.Empty,
|
||||||
Content = item.Content ?? string.Empty
|
Content = item.Content ?? string.Empty,
|
||||||
|
CommentsUrl = item.CommentsUrl ?? string.Empty
|
||||||
});
|
});
|
||||||
totalAffected += affected;
|
totalAffected += affected;
|
||||||
}
|
}
|
||||||
dbTransaction.Commit();
|
dbTransaction.Commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<HashSet<SyndicationItemModel>> GetSyndicationItemsAsync(string[]? encodedFeedUrls)
|
public static async Task<HashSet<SyndicationItemModel>> GetSyndicationItemsAsync(string[]? encodedSyndicationUrls)
|
||||||
{
|
{
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
HashSet<SyndicationItemModel> items = new HashSet<SyndicationItemModel>();
|
HashSet<SyndicationItemModel> items = new HashSet<SyndicationItemModel>();
|
||||||
FeedCache fCache = new FeedCache();
|
await TempCache.UpdateCache(CacheFetch.Syndication);
|
||||||
await using DbDataReader reader = await dbc.ExecuteReaderAsync(encodedFeedUrls == null ? "SELECT * FROM feed_item" : $"SELECT * FROM feed_item WHERE encoded_feed_url IN({FormatParametersFromArray(encodedFeedUrls)})");
|
await using DbDataReader reader = await dbc.ExecuteReaderAsync(encodedSyndicationUrls == null ? "SELECT * FROM syndication_item" : $"SELECT * FROM syndication_item WHERE encoded_syndication_url IN({FormatParametersFromArray(encodedSyndicationUrls)})");
|
||||||
//NOTE(dbg): While debugging this part of the function the code below (Reader.ReadAsync) will return 0, because the debugger already reads the items from the reader.
|
//NOTE(dbg): While debugging this part of the function the code below (Reader.ReadAsync) will return 0, because the debugger already reads the items from the reader.
|
||||||
while (await reader.ReadAsync())
|
while (await reader.ReadAsync())
|
||||||
{
|
{
|
||||||
SyndicationItemModel syndicationItemModel = new SyndicationItemModel()
|
SyndicationItemModel syndicationItemModel = new SyndicationItemModel()
|
||||||
{
|
{
|
||||||
Id = reader["id"].ToString(),
|
Link = reader["link"].ToString(),
|
||||||
EncodedSyndicationUrl = reader["encoded_feed_url"].ToString(),
|
EncodedSyndicationUrl = reader["encoded_syndication_url"].ToString(),
|
||||||
Read = bool.Parse(reader["read"].ToString()),
|
Read = bool.Parse(reader["read"].ToString()),
|
||||||
|
Type = reader["type"].ToString(),
|
||||||
Title = reader["title"].ToString(),
|
Title = reader["title"].ToString(),
|
||||||
Description = reader["description"].ToString(),
|
Description = reader["description"].ToString(),
|
||||||
Link = reader["link"].ToString(),
|
LastUpdated = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())),
|
||||||
ItemUpdatedDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["last_updated"].ToString())),
|
ItemUpdatedDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["item_updated_date"].ToString())),
|
||||||
PublishingDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publishing_date"].ToString())),
|
PublishingDate = DateTimeOffset.FromUnixTimeMilliseconds(long.Parse(reader["publishing_date"].ToString())),
|
||||||
Authors = SyndicationManager.StringToStringArray(reader["authors"].ToString()),
|
Authors = SyndicationManager.StringToStringArray(reader["authors"].ToString()),
|
||||||
Categories = SyndicationManager.StringToStringArray(reader["categories"].ToString()),
|
Categories = SyndicationManager.StringToStringArray(reader["categories"].ToString()),
|
||||||
Content = reader["content"].ToString()
|
Content = reader["content"].ToString(),
|
||||||
|
CommentsUrl = reader["comments_url"].ToString()
|
||||||
};
|
};
|
||||||
syndicationItemModel.SyndicationParent = fCache.CacheFeed(syndicationItemModel.EncodedSyndicationUrl) ?? new SyndicationModel();
|
syndicationItemModel.SyndicationParent = TempCache.GetSyndication(syndicationItemModel.EncodedSyndicationUrl) ?? new SyndicationModel(); // The new syndication should never be initialized, if this hits then the date is not valid for some reason!!!
|
||||||
items.Add(syndicationItemModel);
|
items.Add(syndicationItemModel);
|
||||||
}
|
}
|
||||||
Log.Debug("Fetching feed items resulted: {ItemCount} item(s)", items.Count);
|
Log.Debug("Fetching feed items resulted: {ItemCount} item(s)", items.Count);
|
||||||
|
@ -226,13 +237,13 @@ namespace SharpRss
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
Log.Verbose("Checking table: {Table}", "category");
|
Log.Verbose("Checking table: {Table}", "category");
|
||||||
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS category (id STRING PRIMARY KEY, name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING)");
|
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS category (id STRING PRIMARY KEY, name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, last_updated INT)");
|
||||||
|
|
||||||
Log.Verbose("Checking table: {Table}", "feed");
|
Log.Verbose("Checking table: {Table}", "feed");
|
||||||
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS feed (encoded_url STRING PRIMARY KEY, title STRING, category_id STRING, feed_type STRING, feed_version STRING, description STRING, language STRING, copyright STRING, publication_date INT, last_updated INT, categories STRING, image_url STRING)");
|
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS syndication (encoded_url STRING PRIMARY KEY, title STRING, category_id STRING, syndication_type STRING, version STRING, description STRING, language STRING, copyright STRING, last_updated INT, publication_date INT, syn_updated_date INT, categories STRING, image_url STRING)");
|
||||||
|
|
||||||
Log.Verbose("Checking table: {Table}", "feed_item");
|
Log.Verbose("Checking table: {Table}", "feed_item");
|
||||||
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS feed_item (id STRING PRIMARY KEY, encoded_feed_url STRING, read STRING, title STRING, description STRING, link STRING, last_updated INT, publishing_date INT, authors STRING, categories STRING, content STRING)");
|
await dbc.ExecuteAsync("CREATE TABLE IF NOT EXISTS syndication_item (link STRING PRIMARY KEY, encoded_syndication_url STRING, read STRING, type STRING, title STRING, description STRING, last_updated INT, item_updated_date INT, publishing_date INT, authors STRING, categories STRING, content STRING, comments_url STRING)");
|
||||||
Log.Verbose("Checking database done!");
|
Log.Verbose("Checking database done!");
|
||||||
_isInitialized = true;
|
_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
@ -242,11 +253,11 @@ namespace SharpRss
|
||||||
string[] formatted = dbParams.Select(s => $"'{s}'").ToArray();
|
string[] formatted = dbParams.Select(s => $"'{s}'").ToArray();
|
||||||
return string.Join(", ", formatted);
|
return string.Join(", ", formatted);
|
||||||
}
|
}
|
||||||
public static async Task<int> GetSyndicationCountAsync(string[] encodedSyndicationUrls)
|
/*public static async Task<int> GetSyndicationCountAsync(string[] encodedSyndicationUrls)
|
||||||
{
|
{
|
||||||
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
|
||||||
dbc.Open();
|
dbc.Open();
|
||||||
return await dbc.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM feed WHERE encoded_url IN(@Urls)");
|
return await dbc.ExecuteScalarAsync<int>("SELECT COUNT(*) FROM syndication WHERE encoded_url IN(@Urls)");
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,13 +6,12 @@ namespace SharpRss.Models
|
||||||
{
|
{
|
||||||
public SyndicationModel SyndicationParent { get; set; } = new SyndicationModel();
|
public SyndicationModel SyndicationParent { get; set; } = new SyndicationModel();
|
||||||
// Db props
|
// Db props
|
||||||
public string? Id { get; set; } = string.Empty;
|
public string? Link { get; set; } = string.Empty;
|
||||||
public string EncodedSyndicationUrl { get; set; } = string.Empty;
|
public string EncodedSyndicationUrl { 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;
|
||||||
public string? Description { get; set; } = string.Empty;
|
public string? Description { get; set; } = string.Empty;
|
||||||
public string? Link { get; set; } = string.Empty;
|
|
||||||
public DateTimeOffset LastUpdated { get; set; } = DateTimeOffset.Now;
|
public DateTimeOffset LastUpdated { get; set; } = DateTimeOffset.Now;
|
||||||
public DateTimeOffset? ItemUpdatedDate { get; set; }
|
public DateTimeOffset? ItemUpdatedDate { get; set; }
|
||||||
public DateTimeOffset? PublishingDate { get; set; }
|
public DateTimeOffset? PublishingDate { get; set; }
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace SharpRss.Models
|
||||||
public string? Title { get; set; } = string.Empty;
|
public string? Title { get; set; } = string.Empty;
|
||||||
public string? CategoryId { get; set; } = string.Empty;
|
public string? CategoryId { get; set; } = string.Empty;
|
||||||
public string? SyndicationType { get; set; } = string.Empty;
|
public string? SyndicationType { get; set; } = string.Empty;
|
||||||
public string? SyndicationVersion { get; set; } = string.Empty;
|
public string? Version { get; set; } = string.Empty;
|
||||||
public string? Description { get; set; } = string.Empty;
|
public string? Description { get; set; } = string.Empty;
|
||||||
public string? Language { get; set; } = string.Empty;
|
public string? Language { get; set; } = string.Empty;
|
||||||
public string? Copyright { get; set; } = string.Empty;
|
public string? Copyright { get; set; } = string.Empty;
|
||||||
|
|
|
@ -103,39 +103,46 @@ namespace SharpRss.Services
|
||||||
}
|
}
|
||||||
private async void SetupTestCategoriesAndFeedsAsync()
|
private async void SetupTestCategoriesAndFeedsAsync()
|
||||||
{
|
{
|
||||||
/*CategoryModel? newsCategory = await CreateCategoryAsync(new CategoryModel() { Name = "News" });
|
/*try
|
||||||
if (newsCategory != null)
|
|
||||||
{
|
{
|
||||||
await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen", newsCategory);
|
CategoryModel? newsCategory = await CreateCategoryAsync(new CategoryModel() { Name = "News" });
|
||||||
await AddSubscriptionAsync("https://www.ad.nl/home/rss.xml", newsCategory);
|
if (newsCategory != null)
|
||||||
await AddSubscriptionAsync("https://www.nasa.gov/rss/dyn/breaking_news.rss", newsCategory);
|
{
|
||||||
await AddSubscriptionAsync("http://news.google.com/?output=atom", newsCategory);
|
await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen", newsCategory);
|
||||||
}*/
|
await AddSubscriptionAsync("https://www.ad.nl/home/rss.xml", newsCategory);
|
||||||
|
await AddSubscriptionAsync("https://www.nasa.gov/rss/dyn/breaking_news.rss", newsCategory);
|
||||||
|
await AddSubscriptionAsync("http://news.google.com/?output=atom", newsCategory);
|
||||||
|
}
|
||||||
|
|
||||||
/*CategoryModel? techCategory = await CreateCategoryAsync(new CategoryModel() { Name = "Tech" });
|
CategoryModel? techCategory = await CreateCategoryAsync(new CategoryModel() { Name = "Tech" });
|
||||||
if (techCategory != null)
|
if (techCategory != null)
|
||||||
{
|
{
|
||||||
await AddSubscriptionAsync("https://itsfoss.com/feed", techCategory);
|
await AddSubscriptionAsync("https://itsfoss.com/feed", techCategory);
|
||||||
await AddSubscriptionAsync("http://fedoramagazine.org/feed/", techCategory);
|
await AddSubscriptionAsync("http://fedoramagazine.org/feed/", techCategory);
|
||||||
await AddSubscriptionAsync("https://arstechnica.com/feed/", techCategory);
|
await AddSubscriptionAsync("https://arstechnica.com/feed/", techCategory);
|
||||||
await AddSubscriptionAsync("https://feeds.arstechnica.com/arstechnica/gadgets", techCategory);
|
await AddSubscriptionAsync("https://feeds.arstechnica.com/arstechnica/gadgets", techCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
CategoryModel? youtubeCategory = await CreateCategoryAsync(new CategoryModel() { Name = "YouTube" });
|
CategoryModel? youtubeCategory = await CreateCategoryAsync(new CategoryModel() { Name = "YouTube" });
|
||||||
if (youtubeCategory != null)
|
if (youtubeCategory != null)
|
||||||
{
|
{
|
||||||
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCXuqSBlHAE6Xw-yeJA0Tunw", youtubeCategory);
|
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCXuqSBlHAE6Xw-yeJA0Tunw", youtubeCategory);
|
||||||
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UC1Et9K-hHf-P_LzQkE_Q3Jw", youtubeCategory);
|
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UC1Et9K-hHf-P_LzQkE_Q3Jw", youtubeCategory);
|
||||||
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCsXVk37bltHxD1rDPwtNM8Q", youtubeCategory);
|
await AddSubscriptionAsync("https://www.youtube.com/feeds/videos.xml?channel_id=UCsXVk37bltHxD1rDPwtNM8Q", youtubeCategory);
|
||||||
}
|
}
|
||||||
|
|
||||||
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/feed/");
|
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/feed/");
|
||||||
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/agenda/feed/");
|
await AddSubscriptionAsync("http://www.digitaleoverheid.nl/agenda/feed/");
|
||||||
await AddSubscriptionAsync("https://feeds.rijksoverheid.nl/nieuws.rss");
|
await AddSubscriptionAsync("https://feeds.rijksoverheid.nl/nieuws.rss");
|
||||||
await AddSubscriptionAsync("https://nl.wikipedia.org/w/index.php?title=Speciaal:RecenteWijzigingen&feed=atom");
|
await AddSubscriptionAsync("https://nl.wikipedia.org/w/index.php?title=Speciaal:RecenteWijzigingen&feed=atom");
|
||||||
await AddSubscriptionAsync("https://feeds.aivd.nl/nieuws.rss");
|
await AddSubscriptionAsync("https://feeds.aivd.nl/nieuws.rss");
|
||||||
await AddSubscriptionAsync("https://blogs.microsoft.com/feed");
|
await AddSubscriptionAsync("https://blogs.microsoft.com/feed");
|
||||||
await AddSubscriptionAsync("https://www.europarl.europa.eu/rss/doc/top-stories/nl.xml");*/
|
await AddSubscriptionAsync("https://www.europarl.europa.eu/rss/doc/top-stories/nl.xml");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Error(e, "Exception!");
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -66,7 +66,7 @@ namespace SharpRss
|
||||||
container.SyndicationModel.EncodedUrl = EncodeUrlToBase64(syndicationUrl);
|
container.SyndicationModel.EncodedUrl = EncodeUrlToBase64(syndicationUrl);
|
||||||
container.SyndicationModel.Title = rssFeed.Channel.Title ?? string.Empty;
|
container.SyndicationModel.Title = rssFeed.Channel.Title ?? string.Empty;
|
||||||
container.SyndicationModel.SyndicationType = rssFeed.Format.ToString() ?? string.Empty;
|
container.SyndicationModel.SyndicationType = rssFeed.Format.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.SyndicationVersion = rssFeed.Version?.ToString() ?? string.Empty;
|
container.SyndicationModel.Version = rssFeed.Version?.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.Description = rssFeed.Channel.Description ?? string.Empty;
|
container.SyndicationModel.Description = rssFeed.Channel.Description ?? string.Empty;
|
||||||
container.SyndicationModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty;
|
container.SyndicationModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty;
|
container.SyndicationModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty;
|
||||||
|
@ -77,12 +77,11 @@ namespace SharpRss
|
||||||
{
|
{
|
||||||
SyndicationItemModel itemModel = new SyndicationItemModel()
|
SyndicationItemModel itemModel = new SyndicationItemModel()
|
||||||
{
|
{
|
||||||
Id = rssItem.Link?.ToString() ?? string.Empty,
|
Link = rssItem.Link?.ToString() ?? string.Empty,
|
||||||
EncodedSyndicationUrl = container.SyndicationModel.EncodedUrl ?? string.Empty,
|
EncodedSyndicationUrl = container.SyndicationModel.EncodedUrl ?? string.Empty,
|
||||||
Type = container.SyndicationModel.SyndicationType ?? string.Empty,
|
Type = container.SyndicationModel.SyndicationType ?? string.Empty,
|
||||||
Title = rssItem.Title ?? string.Empty,
|
Title = rssItem.Title ?? string.Empty,
|
||||||
Description = rssItem.Description ?? string.Empty,
|
Description = rssItem.Description ?? string.Empty,
|
||||||
Link = rssItem.Link?.ToString() ?? string.Empty,
|
|
||||||
PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? new DateTimeOffset(rssItem.PublicationDate) : DateTimeOffset.MinValue,
|
PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? new DateTimeOffset(rssItem.PublicationDate) : DateTimeOffset.MinValue,
|
||||||
Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(),
|
Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(),
|
||||||
Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(),
|
Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(),
|
||||||
|
@ -97,7 +96,7 @@ namespace SharpRss
|
||||||
container.SyndicationModel.EncodedUrl = EncodeUrlToBase64(syndicationUrl);
|
container.SyndicationModel.EncodedUrl = EncodeUrlToBase64(syndicationUrl);
|
||||||
container.SyndicationModel.Title = atomFeed.Title?.Content ?? string.Empty;
|
container.SyndicationModel.Title = atomFeed.Title?.Content ?? string.Empty;
|
||||||
container.SyndicationModel.SyndicationType = atomFeed.Format.ToString() ?? string.Empty;
|
container.SyndicationModel.SyndicationType = atomFeed.Format.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.SyndicationVersion = atomFeed.Version?.ToString() ?? string.Empty;
|
container.SyndicationModel.Version = atomFeed.Version?.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.Description = atomFeed.Subtitle?.Content ?? string.Empty;
|
container.SyndicationModel.Description = atomFeed.Subtitle?.Content ?? string.Empty;
|
||||||
container.SyndicationModel.Language = atomFeed.Language?.ToString() ?? string.Empty;
|
container.SyndicationModel.Language = atomFeed.Language?.ToString() ?? string.Empty;
|
||||||
container.SyndicationModel.Copyright = atomFeed.Rights?.Content ?? string.Empty;
|
container.SyndicationModel.Copyright = atomFeed.Rights?.Content ?? string.Empty;
|
||||||
|
@ -108,14 +107,13 @@ namespace SharpRss
|
||||||
{
|
{
|
||||||
SyndicationItemModel itemModel = new SyndicationItemModel()
|
SyndicationItemModel itemModel = new SyndicationItemModel()
|
||||||
{
|
{
|
||||||
Id = entry.Id?.Uri.ToString() ?? string.Empty,
|
Link = entry.Id?.Uri.ToString() ?? string.Empty,
|
||||||
EncodedSyndicationUrl = container.SyndicationModel?.EncodedUrl ?? string.Empty,
|
EncodedSyndicationUrl = container.SyndicationModel?.EncodedUrl ?? string.Empty,
|
||||||
Type = container.SyndicationModel?.SyndicationType ?? string.Empty,
|
Type = container.SyndicationModel?.SyndicationType ?? string.Empty,
|
||||||
Title = entry.Title?.Content ?? string.Empty,
|
Title = entry.Title?.Content ?? string.Empty,
|
||||||
Description = entry.Summary?.Content ?? string.Empty,
|
Description = entry.Summary?.Content ?? string.Empty,
|
||||||
Link = entry.Id?.Uri.ToString() ?? string.Empty,
|
|
||||||
ItemUpdatedDate = entry.UpdatedOn is { Ticks: > 0 } ? new DateTimeOffset(entry.UpdatedOn) : DateTimeOffset.Now,
|
ItemUpdatedDate = entry.UpdatedOn is { Ticks: > 0 } ? new DateTimeOffset(entry.UpdatedOn) : DateTimeOffset.Now,
|
||||||
PublishingDate = entry.PublishedOn is { Ticks: > 0 } ? new DateTimeOffset(entry.PublishedOn) : entry.UpdatedOn,
|
PublishingDate = entry.PublishedOn is { Ticks: > 0 } ? new DateTimeOffset(entry.PublishedOn) : DateTimeOffset.MinValue,
|
||||||
Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(),
|
Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(),
|
||||||
Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(),
|
Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(),
|
||||||
Content = entry.Content?.Content ?? string.Empty
|
Content = entry.Content?.Content ?? string.Empty
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
var parameters = new DialogParameters();
|
var parameters = new DialogParameters();
|
||||||
parameters.Add("Data", syndicationItem);
|
parameters.Add("Data", syndicationItem);
|
||||||
_dialogService.Show<ReadDialog>("", parameters, _dialogOptions);
|
_dialogService.Show<ReadDialog>("", parameters, _dialogOptions);
|
||||||
Log.Verbose("Item: {ItemId} clicked", syndicationItem.Id);
|
Log.Verbose("Item: {ItemId} clicked", syndicationItem.Link);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Binary file not shown.
Loading…
Reference in New Issue
Block a user