Fixed crash on initializing models, extended GetCategoriesAsync funtion

This commit is contained in:
Max 2023-06-10 19:06:30 +02:00
parent a17b2a7ebf
commit 4ff0f7c0c3
5 changed files with 99 additions and 102 deletions

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Security.Policy;
using System.Threading.Tasks;
using Dapper;
using Microsoft.Data.Sqlite;
@ -14,17 +13,17 @@ namespace SharpRss
{
internal static class DbAccess
{
static DbAccess()
{
Initialize();
}
private static readonly string ConnectionString = $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.sqlite")};";
private static bool _isInitialized;
public static async Task SetSyndicationAsync(SyndicationContainer synContainer)
{
if (synContainer.Category != null)
await SetCategoryAsync(synContainer.Category);
{
CategoryModel? catModel = await SetCategoryAsync(synContainer.Category);
if (catModel != null)
synContainer.FeedModel.CategoryId = catModel.Id;
}
if (synContainer.FeedModel != null)
await SetFeedAsync(synContainer.FeedModel);
if (synContainer.FeedItems != null && synContainer.FeedItems.Any())
@ -51,14 +50,18 @@ namespace SharpRss
}
return categories;
}
public static async Task<bool> SetCategoryAsync(CategoryModel category)
public static async Task<CategoryModel?> SetCategoryAsync(CategoryModel category)
{
if (category == null) return false;
CategoryModel? modelReturn = null;
if (category == null) return modelReturn;
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
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)",
new { category.Id, category.HexColor, category.Icon, category.Name });
return affected > 0;
if (affected <= 0) return modelReturn;
var catModel = await GetCategoriesAsync();
modelReturn = catModel.Where(x => x.Name == category.Name).ToHashSet().FirstOrDefault() ?? null;
return modelReturn;
}
public static async Task<bool> DeleteCategory(CategoryModel category)
{
@ -73,7 +76,7 @@ namespace SharpRss
{
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand(@"INSERT OR REPLACE INTO feed
/*await using SqliteCommand cmd = new SqliteCommand(@"INSERT OR REPLACE INTO feed
(url,
title,
category_id,
@ -116,8 +119,33 @@ namespace SharpRss
new SqliteParameter("ImageUrl", feed.ImageUrl ?? string.Empty)
}
};
int exec = await cmd.ExecuteNonQueryAsync();
/*int affected = await dbc.ExecuteAsync("INSERT OR REPLACE INTO feed (url, title, category_id, feed_type, feed_version, description, language, copyright, publication_date, last_updated, categories, image_url) VALUES (@Url, @Title, @CategoryId, @FeedType, @FeedVersion, @Description, @language, @Copyright, @PublicationDate, @LastUpdated, @Categories, @ImageUrl)",
int exec = await cmd.ExecuteNonQueryAsync();*/
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO feed
(url,
title,
category_id,
feed_type,
feed_version,
description,
language,
copyright,
publication_date,
last_updated,
categories,
image_url)
VALUES (
@Url,
@Title,
@CategoryId,
@FeedType,
@FeedVersion,
@Description,
@Language,
@Copyright,
@PublicationDate,
@LastUpdated,
@Categories,
@ImageUrl)",
new
{
Url = feed.OriginalUrl ?? string.Empty,
@ -130,18 +158,18 @@ namespace SharpRss
Copyright = feed.Copyright ?? string.Empty,
PublicationDate = feed.PublicationDate?.ToUnixTimeMilliseconds() ?? 0,
LastUpdated = feed.LastUpdated?.ToUnixTimeMilliseconds() ?? 0,
Categories = feed.Categories.Any() ? string.Join(',', feed.Categories) : string.Empty,
Categories = feed.Categories != null && feed.Categories.Any() ? string.Join(',', feed.Categories) : string.Empty,
ImageUrl = feed.ImageUrl ?? string.Empty
});
if (affected == 0)
Log.Warning("Failed to add feed: {FeedUrl}", feed.OriginalUrl);*/
Log.Warning("Failed to add feed: {FeedUrl}", feed.OriginalUrl);
}
public static async Task<HashSet<FeedModel>> GetFeedsAsync(string[]? categoryIds = null)
{
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
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 feed WHERE category_id == ''" : "SELECT * FROM feed WHERE category_id IN(@CatIds)", new { CatIds = categoryIds });
while (await reader.ReadAsync())
{
FeedModel feedModel = new FeedModel()
@ -172,7 +200,7 @@ namespace SharpRss
await using SqliteTransaction dbTransaction = dbc.BeginTransaction();
foreach (FeedItemModel item in items)
{
await using SqliteCommand cmd = new SqliteCommand(@"INSERT OR REPLACE INTO feed_item (id, feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)
/*await using SqliteCommand cmd = new SqliteCommand(@"INSERT OR REPLACE INTO feed_item (id, feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)
VALUES (@Id, @FeedUrl, @Read, @Title, @Description, @Link, @LastUpdated, @PublishingDate, @Authors, @Categories, @Content)", dbc, dbTransaction)
{
Parameters =
@ -190,8 +218,8 @@ namespace SharpRss
new SqliteParameter("Content", item.Content ?? string.Empty)
}
};
int exec = await cmd.ExecuteNonQueryAsync();
/*int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO feed_item (id, feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)
int exec = await cmd.ExecuteNonQueryAsync();*/
int affected = await dbc.ExecuteAsync(@"INSERT OR REPLACE INTO feed_item (id, feed_url, read, title, description, link, last_updated, publishing_date, authors, categories, content)
VALUES (@Id, @FeedUrl, @Read, @Title, @Description, @Link, @LastUpdated, @PublishingDate, @Authors, @Categories, @Content)",
transaction: dbTransaction,
param: new
@ -204,11 +232,11 @@ namespace SharpRss
Link = item.Link ?? string.Empty,
LastUpdated = item.LastUpdated?.ToUnixTimeMilliseconds() ?? 0,
PublishingDate = item.PublishingDate?.ToUnixTimeMilliseconds() ?? 0,
Authors = item.Authors.Any() ? string.Join(',', item.Authors) : string.Empty,
Categories = item.Categories.Any() ? string.Join(',', item.Categories) : string.Empty,
Authors = item.Authors != null && item.Authors.Any() ? string.Join(',', item.Authors) : string.Empty,
Categories = item.Categories != null && item.Categories.Any() ? string.Join(',', item.Categories) : string.Empty,
Content = item.Content ?? string.Empty
});
totalAffected += affected;*/
totalAffected += affected;
}
dbTransaction.Commit();
}
@ -239,7 +267,7 @@ namespace SharpRss
return items;
}
private static async void Initialize()
public static async void Initialize()
{
if (_isInitialized) return;
Log.Verbose("Checking database...");

View File

@ -79,42 +79,7 @@ namespace SharpRss.Services
var items = await DbAccess.GetFeedItemsAsync(feedIds);
return items;
}
/*private async Task<int> AddFeedItems(IList<FeedItem> items, FeedModel feedModel)
{
int result = 0;
if (!items.Any())
return result;
HashSet<FeedItemModel> itemModels = new HashSet<FeedItemModel>();
// TODO: implement!!!
result = await DbAccess.SetFeedItemsAsync(itemModels);
return result;
}*/
/*private IList<FeedItemModel> ConstructFeedItems(IList<FeedItem> items, FeedModel feed)
{
IList<FeedItemModel> itemModels = new List<FeedItemModel>();
if (!items.Any())
return itemModels;
foreach (FeedItem item in items)
{
itemModels.Add(new FeedItemModel()
{
Id = item.Id,
FeedId = feed.Id,
Title = item.Title,
Description = item.Description,
Link = item.Link,
LastUpdated = DateTimeOffset.Now,
PublishingDate = item.PublishingDate != null ? new DateTimeOffset((DateTime)item.PublishingDate) : null,
Author = item.Author,
Categories = item.Categories.ToArray(),
Content = item.Content
});
}
return itemModels;
}*/
private GenericSyndicationFeed? CreateFeed(string url)
{
Uri feedUri = new Uri(url);
@ -129,9 +94,7 @@ namespace SharpRss.Services
}
private async void SetupTestGroupsAndFeedsAsync()
{
/*CategoryModel newModel = new CategoryModel() { Name = "Test" };
bool added = await DbAccess.SetCategoryAsync(newModel);*/
await AddSubscriptionAsync("https://en.wikipedia.org/w/api.php?hidebots=1&hidecategorization=1&hideWikibase=1&urlversion=1&days=7&limit=50&action=feedrecentchanges&feedformat=atom");
/*await AddSubscriptionAsync("https://www.nu.nl/rss/Algemeen");*/
//TODO: Make multiple adding of feed to a transaction, now throws an exception.
/*var groupRes = await CreateGroupAsync(new GroupModel() { Name = "Test" });
groupRes = await CreateGroupAsync(new GroupModel() { Name = "News" });

View File

@ -61,62 +61,63 @@ namespace SharpRss
{
case SyndicationContentFormat.Rss:
RssFeed rssFeed = (RssFeed)container.SyndicationFeed.Resource;
container.FeedModel.OriginalUrl = rssFeed.Channel.SelfLink.ToString();
container.FeedModel.Title = rssFeed.Channel.Title;
container.FeedModel.FeedType = rssFeed.Format.ToString();
container.FeedModel.FeedVersion = rssFeed.Version.ToString();
container.FeedModel.Description = rssFeed.Channel.Description;
container.FeedModel.Language = rssFeed.Channel.Language?.ToString();
container.FeedModel.Copyright = rssFeed.Channel.Copyright;
container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(rssFeed.Channel.LastBuildDate);
container.FeedModel.Categories = rssFeed.Channel.Categories.Select(x => x.Value).ToArray();
if (rssFeed.Channel == null) break;
container.FeedModel.OriginalUrl = rssFeed.Channel.SelfLink?.ToString() ?? string.Empty;
container.FeedModel.Title = rssFeed.Channel.Title ?? string.Empty;
container.FeedModel.FeedType = rssFeed.Format.ToString() ?? string.Empty;
container.FeedModel.FeedVersion = rssFeed.Version?.ToString() ?? string.Empty;
container.FeedModel.Description = rssFeed.Channel.Description ?? string.Empty;
container.FeedModel.Language = rssFeed.Channel.Language?.ToString() ?? string.Empty;
container.FeedModel.Copyright = rssFeed.Channel.Copyright ?? string.Empty;
container.FeedModel.PublicationDate = rssFeed.Channel.LastBuildDate is not { Ticks: > 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssFeed.Channel.LastBuildDate);
container.FeedModel.Categories = rssFeed.Channel.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>();
container.FeedModel.ImageUrl = rssFeed.Channel.Image?.Url.ToString() ?? string.Empty;
foreach (var rssItem in rssFeed.Channel.Items)
{
FeedItemModel itemModel = new FeedItemModel()
{
Id = rssItem.Link.ToString(),
FeedUrl = container.FeedModel.OriginalUrl,
Type = container.FeedModel.FeedType,
Title = rssItem.Title,
Description = rssItem.Description,
Link = rssItem.Link.ToString(),
PublishingDate = rssItem.PublicationDate.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(rssItem.PublicationDate),
Authors = new []{ rssItem.Author },
Categories = rssItem.Categories.Select(x => x.Value).ToArray(),
Content = rssItem.Extensions.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).First(),
CommentsUrl = rssItem.Extensions.Where(x => x is WellFormedWebCommentsSyndicationExtension).Select(x => (x as WellFormedWebCommentsSyndicationExtension)?.Context.CommentsFeed.ToString()).First()
Id = rssItem.Link?.ToString() ?? string.Empty,
FeedUrl = container.FeedModel.OriginalUrl ?? string.Empty,
Type = container.FeedModel.FeedType ?? string.Empty,
Title = rssItem.Title ?? string.Empty,
Description = rssItem.Description ?? string.Empty,
Link = rssItem.Link?.ToString() ?? string.Empty,
PublishingDate = rssItem.PublicationDate is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(rssItem.PublicationDate),
Authors = rssItem.Author != null ? new []{ rssItem.Author } : Array.Empty<string>(),
Categories = rssItem.Categories?.Select(x => x.Value).ToArray() ?? Array.Empty<string>(),
Content = rssItem.Extensions?.Where(x => x is SiteSummaryContentSyndicationExtension).Select(x => (x as SiteSummaryContentSyndicationExtension)?.Context.Encoded).FirstOrDefault() ?? string.Empty,
CommentsUrl = rssItem.Extensions?.Where(x => x is WellFormedWebCommentsSyndicationExtension).Select(x => (x as WellFormedWebCommentsSyndicationExtension)?.Context.CommentsFeed.ToString()).FirstOrDefault() ?? string.Empty
};
container.FeedItems.Add(itemModel);
}
break;
case SyndicationContentFormat.Atom:
AtomFeed atomFeed = (AtomFeed)container.SyndicationFeed.Resource;
container.FeedModel.OriginalUrl = atomFeed.Id.Uri.ToString();
container.FeedModel.Title = atomFeed.Title.Content;
container.FeedModel.FeedType = atomFeed.Format.ToString();
container.FeedModel.FeedVersion = atomFeed.Version?.ToString();
container.FeedModel.Description = atomFeed.Subtitle?.Content;
container.FeedModel.Language = atomFeed.Language?.ToString();
container.FeedModel.Copyright = atomFeed.Rights?.Content;
container.FeedModel.PublicationDate = new DateTimeOffset(atomFeed.UpdatedOn);
container.FeedModel.Categories = atomFeed.Categories?.Select(x => x.Label).ToArray();
container.FeedModel.OriginalUrl = atomFeed.Id?.Uri.ToString() ?? string.Empty;
container.FeedModel.Title = atomFeed.Title?.Content ?? string.Empty;
container.FeedModel.FeedType = atomFeed.Format.ToString() ?? string.Empty;
container.FeedModel.FeedVersion = atomFeed.Version?.ToString() ?? string.Empty;
container.FeedModel.Description = atomFeed.Subtitle?.Content ?? string.Empty;
container.FeedModel.Language = atomFeed.Language?.ToString() ?? string.Empty;
container.FeedModel.Copyright = atomFeed.Rights?.Content ?? string.Empty;
container.FeedModel.PublicationDate = atomFeed.UpdatedOn != null ? new DateTimeOffset(atomFeed.UpdatedOn) : DateTimeOffset.MinValue;
container.FeedModel.Categories = atomFeed.Categories?.Select(x => x.Label).ToArray() ?? Array.Empty<string>();
container.FeedModel.ImageUrl = atomFeed.Icon?.Uri.ToString() ?? string.Empty;
foreach (var entry in atomFeed.Entries)
{
FeedItemModel itemModel = new FeedItemModel()
{
Id = entry.Id.Uri.ToString(),
FeedUrl = container.FeedModel.OriginalUrl,
Type = container.FeedModel.FeedType,
Title = entry.Title.Content,
Description = entry.Summary.Content,
Link = entry.Id.Uri.ToString(),
LastUpdated = entry.UpdatedOn.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(entry.UpdatedOn),
PublishingDate = entry.PublishedOn.Ticks <= 0 ? DateTimeOffset.MinValue : new DateTimeOffset(entry.PublishedOn),
Authors = entry.Authors.Select(auth => auth.Name).ToArray(),
Categories = entry.Categories.Select(cat => cat.Label).ToArray(),
Content = entry.Content?.Content
Id = entry.Id?.Uri.ToString() ?? string.Empty,
FeedUrl = container.FeedModel?.OriginalUrl ?? string.Empty,
Type = container.FeedModel?.FeedType ?? string.Empty,
Title = entry.Title?.Content ?? string.Empty,
Description = entry.Summary?.Content ?? string.Empty,
Link = entry.Id?.Uri.ToString() ?? string.Empty,
LastUpdated = entry.UpdatedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.UpdatedOn),
PublishingDate = entry.PublishedOn is not { Ticks: <= 0 } ? DateTimeOffset.MinValue : new DateTimeOffset(entry.PublishedOn),
Authors = entry.Authors?.Select(auth => auth.Name).ToArray() ?? Array.Empty<string>(),
Categories = entry.Categories?.Select(cat => cat.Label).ToArray() ?? Array.Empty<string>(),
Content = entry.Content?.Content ?? string.Empty
};
container.FeedItems.Add(itemModel);
}
@ -128,5 +129,10 @@ namespace SharpRss
container.Fetched = true;
return container;
}
public static void Init()
{
DbAccess.Initialize();
}
}
}

View File

@ -19,7 +19,7 @@ namespace WebSharpRSS
Caretaker.Settings.SetAppDefaultSettings();
SetupLogging();
Log.Information("Starting SharpRSS...");
//DbAccess_Old.Initialize();
SyndicationManager.Init();
_bootstrapped = true;
}

Binary file not shown.