Moved db acces to static class.

This commit is contained in:
Max 2023-05-29 16:14:26 +02:00
parent 2355da58b2
commit 323486f36d
5 changed files with 159 additions and 143 deletions

View File

@ -9,25 +9,23 @@ using Microsoft.Data.Sqlite;
using Serilog;
using SharpRss.Models;
namespace SharpRss.Services
namespace SharpRss
{
internal class DatabaseService : IDisposable
public static class DbAccess
{
internal DatabaseService()
{
InitializeDb();
}
private readonly string _connectionString = $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.sqlite")};";
private readonly string _groupTable = "group_data";
private readonly string _feedTable = "feed_data";
private readonly string _feedItemTable = "feed_item_data";
private static bool _isInitialized;
private static readonly string ConnectionString = $"Data Source={Path.Combine(Environment.CurrentDirectory, "sharp_rss.sqlite")};";
private const string GroupTable = "group_data";
private const string FeedTable = "feed_data";
private const string FeedItemTable = "feed_item_data";
// Groups
public async Task<HashSet<GroupModel>> GetGroupsAsync(string? groupId = null)
public static async Task<HashSet<GroupModel>> GetGroupsAsync(string? groupId = null)
{
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
CheckInitialized();
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
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)
{
Parameters =
{
@ -36,7 +34,7 @@ namespace SharpRss.Services
};
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
HashSet<GroupModel> groups = new HashSet<GroupModel>();
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())
{
cmdFeedCount.Parameters.Clear();
@ -55,12 +53,12 @@ namespace SharpRss.Services
}
return groups;
}
public async Task<bool> SetGroupAsync(GroupModel groupModel)
public static async Task<bool> SetGroupAsync(GroupModel groupModel)
{
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await 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)", dbc)
await 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)", dbc)
{
Parameters =
{
@ -75,13 +73,13 @@ namespace SharpRss.Services
result = true;
return result;
}
public async Task<bool> RemoveGroupAsync(GroupModel groupModel)
public static async Task<bool> RemoveGroupAsync(GroupModel groupModel)
{
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
// Remove the group and remove the feeds that were part of the group.
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_groupTable} WHERE id=@id; UPDATE {_feedTable} SET group_id=NULL WHERE group_id=@id", dbc)
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {GroupTable} WHERE id=@id; UPDATE {FeedTable} SET group_id=NULL WHERE group_id=@id", dbc)
{
Parameters =
{
@ -99,12 +97,12 @@ namespace SharpRss.Services
/// </summary>
/// <param name="groupId">Empty = ungrouped feeds | null = all feeds | id = grouped feeds</param>
/// <returns></returns>
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? groupId = null)
public static async Task<HashSet<FeedModel>> GetFeedsAsync(string? groupId = null)
{
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {_feedTable} WHERE group_id=@groupId" : $"SELECT * FROM {_feedTable}", dbc)
await using SqliteCommand cmd = new SqliteCommand(groupId != null ? $"SELECT * FROM {FeedTable} WHERE group_id=@groupId" : $"SELECT * FROM {FeedTable}", dbc)
{
Parameters =
{
@ -116,12 +114,12 @@ namespace SharpRss.Services
feeds.Add(await ReaderToFeedModel(reader));
return feeds;
}
public async Task<FeedModel?> GetFeedAsync(string feedId)
public static async Task<FeedModel?> GetFeedAsync(string feedId)
{
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
FeedModel? feed = null;
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {_feedTable} WHERE id=@id", dbc)
await using SqliteCommand cmd = new SqliteCommand($"SELECT * FROM {FeedTable} WHERE id=@id", dbc)
{
Parameters = { new SqliteParameter("id", feedId) }
};
@ -130,12 +128,16 @@ namespace SharpRss.Services
feed = await ReaderToFeedModel(reader);
return feed;
}
public async Task<FeedModel?> SetFeedAsync(FeedModel feedModel)
public static async Task<FeedModel?> SetFeedsAsync(IEnumerable<FeedModel> feedModels)
{
FeedModel? resultModel = null;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc); SELECT * FROM {_feedTable} WHERE url=@url", dbc)
await using SqliteTransaction transaction = dbc.BeginTransaction();
foreach (var feedModel in feedModels)
{
//await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {_feedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {_feedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc); SELECT * FROM {_feedTable} WHERE url=@url", dbc)
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedTable} (id, url, title, group_id, feed_type, description, language, copyright, date_added, last_updated, image_url, original_document) VALUES (IFNULL((SELECT id FROM {FeedTable} WHERE url=@url), @id), @url, @title, @groupId, @feedType, @description, @language, @copyright, IFNULL((SELECT date_added FROM {FeedTable} WHERE id=@id), @dateAdded), @lastUpdated, @imageUrl, @originalDoc)", dbc)
{
Parameters =
{
@ -153,17 +155,21 @@ namespace SharpRss.Services
new SqliteParameter("originalDoc", feedModel.OriginalDocument ?? string.Empty)
}
};
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
if (reader.Read())
resultModel = await ReaderToFeedModel(reader);
/*await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();*/
await cmd.ExecuteNonQueryAsync();
}
/*if (reader.Read())
resultModel = await ReaderToFeedModel(reader);*/
await transaction.CommitAsync();
return resultModel;
}
public async Task<bool> RemoveFeedAsync(FeedModel feedModel)
public static async Task<bool> RemoveFeedAsync(FeedModel feedModel)
{
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedTable} WHERE id=@id; UPDATE {_feedItemTable} SET feed_id=NULL WHERE feed_id=@id", dbc)
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {FeedTable} WHERE id=@id; UPDATE {FeedItemTable} SET feed_id=NULL WHERE feed_id=@id", dbc)
{
Parameters =
{
@ -176,16 +182,16 @@ namespace SharpRss.Services
return result;
}
// Feed items
public async Task<HashSet<FeedItemModel>> GetFeedItemsAsync(string[]? feedIds = null)
public static async Task<HashSet<FeedItemModel>> GetFeedItemsAsync(string[]? feedIds = null)
{
List<string>? formattedIds = feedIds?.Select(s => $"'{s}'").ToList();
HashSet<FeedItemModel> feedItems = new HashSet<FeedItemModel>();
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand(
formattedIds != null
? $"SELECT * FROM {_feedItemTable} WHERE feed_id IN ({string.Join(", ", formattedIds)})"
: $"SELECT * FROM {_feedItemTable}", dbc);
? $"SELECT * FROM {FeedItemTable} WHERE feed_id IN ({string.Join(", ", formattedIds)})"
: $"SELECT * FROM {FeedItemTable}", dbc);
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
while (reader.Read())
@ -215,14 +221,14 @@ namespace SharpRss.Services
}
return feedItems;
}
public async Task<int> SetFeedItemsAsync(HashSet<FeedItemModel> items)
public static async Task<int> SetFeedItemsAsync(HashSet<FeedItemModel> items)
{
int result = 0;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteTransaction transaction = dbc.BeginTransaction();
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {_feedItemTable} (id, feed_id, read, title, description, link, last_updated, publishing_date, author, categories, content)" +
$"VALUES (IFNULL((SELECT id FROM {_feedItemTable} WHERE link=@link), @id), @feedId, @read, @title, @description, @link, @lastUpdated, @publishingDate, @author, @categories, @content)", dbc);
await using SqliteCommand cmd = new SqliteCommand($"INSERT OR REPLACE INTO {FeedItemTable} (id, feed_id, read, title, description, link, last_updated, publishing_date, author, categories, content)" +
$"VALUES (IFNULL((SELECT id FROM {FeedItemTable} WHERE link=@link), @id), @feedId, @read, @title, @description, @link, @lastUpdated, @publishingDate, @author, @categories, @content)", dbc);
foreach (FeedItemModel item in items)
{
cmd.Parameters.Clear();
@ -247,14 +253,14 @@ namespace SharpRss.Services
result += affected;
}
transaction.Commit();
return result; // Return the amount affected rows.
return result;
}
public async Task<bool> RemoveFeedItemAsync(FeedItemModel itemModel)
public static async Task<bool> RemoveFeedItemAsync(FeedItemModel itemModel)
{
bool result = false;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {_feedItemTable} WHERE id=@id", dbc)
await using SqliteCommand cmd = new SqliteCommand($"DELETE FROM {FeedItemTable} WHERE id=@id", dbc)
{
Parameters =
{
@ -266,12 +272,12 @@ namespace SharpRss.Services
result = true;
return result;
}
public async Task<GroupModel?> GetGroupFromFeedItemAsync(FeedItemModel feedItem)
public static async Task<GroupModel?> GetGroupFromFeedItemAsync(FeedItemModel feedItem)
{
GroupModel? result = null;
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
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)
{
Parameters =
{
@ -286,7 +292,7 @@ namespace SharpRss.Services
result = groups.FirstOrDefault();
return result;
}
private async Task<FeedModel> ReaderToFeedModel(SqliteDataReader reader)
private static async Task<FeedModel> ReaderToFeedModel(SqliteDataReader reader)
{
FeedModel fetchedFeed = new FeedModel(reader["url"].ToString())
{
@ -309,22 +315,29 @@ namespace SharpRss.Services
Log.Warning("Could not get group from feed: {FeedId}", fetchedFeed.Id);
return fetchedFeed;
}
private async void InitializeDb()
//===
private static void CheckInitialized()
{
if (!_isInitialized) throw new TypeInitializationException(nameof(DbAccess), null);
}
public static async void Initialize()
{
if (_isInitialized) return;
Log.Verbose("Checking database...");
HashSet<string> failed = new HashSet<string>();
await using SqliteConnection dbc = new SqliteConnection(_connectionString);
await using SqliteConnection dbc = new SqliteConnection(ConnectionString);
dbc.Open();
Log.Verbose("Checking table: {Table}", _groupTable);
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)");
Log.Verbose("Checking table: {Table}", GroupTable);
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)");
if (queryResponse.Any()) failed.Add("category_data");
Log.Verbose("Checking table: {Table}", _feedTable);
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)");
Log.Verbose("Checking table: {Table}", FeedTable);
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)");
if (queryResponse.Any()) failed.Add("feed_data");
Log.Verbose("Checking table: {Table}", _feedItemTable);
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)");
Log.Verbose("Checking table: {Table}", FeedItemTable);
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)");
if (queryResponse.Any()) failed.Add("feed_item_data");
if (failed.Any())
@ -334,9 +347,7 @@ namespace SharpRss.Services
}
else
Log.Verbose("Checking database done!");
}
public void Dispose()
{
_isInitialized = true;
}
}
}

View File

@ -1,43 +0,0 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CodeHollow.FeedReader;
using Serilog;
using ToolQit.Extensions;
namespace SharpRss
{
/// <summary>
/// Global memory feed cache.
/// </summary>
public static class FeedCache
{
private static readonly Dictionary<string, Feed> CachedFeeds = new Dictionary<string, Feed>();
public static async Task<Feed> GetFeed(string urlKey)
{
Log.Verbose("Fetching feed: {UrlKey}", urlKey);
if (urlKey.IsNullEmptyWhiteSpace())
{
Log.Error("RSS Url is empty!");
return new Feed();
}
if (CachedFeeds.TryGetValue(urlKey, out Feed? fModel))
return fModel;
string feedUrl;
var urls = await FeedReader.GetFeedUrlsFromUrlAsync(urlKey);
if (!urls.Any())
feedUrl = urlKey;
else
feedUrl = urls.First().Url;
Feed feed = await FeedReader.ReadAsync(feedUrl);
if (feed != null)
{
Log.Warning("Could not get feed: {FeedUrl}", feedUrl);
CachedFeeds[feedUrl] = feed;
}
return feed;
}
}
}

View File

@ -17,7 +17,6 @@ namespace SharpRss.Services
{
SetupTestGroupsAndFeedsAsync();
}
private readonly DatabaseService _dbService = new DatabaseService();
public async Task<HashSet<object>> GetGroupsFeedsAsync()
{
@ -26,20 +25,39 @@ namespace SharpRss.Services
items.UnionWith(await GetUngroupedFeedsAsync());
return items;
}
public async Task<bool> CreateGroupAsync(GroupModel group) => await _dbService.SetGroupAsync(group);
public async Task<HashSet<GroupModel>> GetGroupsAsync() => await _dbService.GetGroupsAsync();
public async Task<bool> CreateGroupAsync(GroupModel group) => await DbAccess.SetGroupAsync(group);
public async Task<HashSet<GroupModel>> GetGroupsAsync() => await DbAccess.GetGroupsAsync();
//TODO: Need to rework this implementation!!!
/*public async Task<bool> FetchFeeds(string[]? rssUrls, GroupModel? group = null)
public async Task<bool> AddFeedsAsync(string[]? rssUrls, GroupModel? group = null)
{
bool result = false;
if (rssUrls == null) return result;
HashSet<Feed> fetchedFeeds = new HashSet<Feed>();
foreach (var rssUrl in rssUrls)
{
fetchedFeeds.Add(await FetchFeed(rssUrl));
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
HashSet<FeedItemModel> itemModels = new HashSet<FeedItemModel>();
foreach (var feed in fetchedFeeds)
{
FeedModel feedModel = new FeedModel(feed.Link)
{
Title = feed.Title,
GroupId = group?.Id ?? string.Empty,
FeedType = feed.Type.ToString(),
Description = feed.Description,
Language = feed.Language,
Copyright = feed.Copyright,
DateAdded = DateTimeOffset.Now,
LastUpdated = DateTimeOffset.Now,
ImageUrl = feed.ImageUrl,
OriginalDocument = feed.OriginalDocument
};
feeds.Add(feedModel);
}
Feed fetched = await FetchFeed(rssUrl);
/*Feed fetched = await FetchFeed(rssUrl);
if (fetched == null)
return result;
@ -59,18 +77,19 @@ namespace SharpRss.Services
FeedModel? dbFeed = await _dbService.SetFeedAsync(feedModel);
result = dbFeed != null;
if (dbFeed == null)
return result;*/
//itemModels.Add(ConstructFeedItems());
/*if (await AddFeedItems(fetched.Items, dbFeed) == 0)
Log.Warning("No feed items added to feed: {FeedUrl}", dbFeed.Url);*/
return result;
if (await AddFeedItems(fetched.Items, dbFeed) == 0)
Log.Warning("No feed items added to feed: {FeedUrl}", dbFeed.Url);
return result;
}*/
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? groupId = null) => await _dbService.GetFeedsAsync(groupId);
public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await _dbService.GetFeedsAsync("");
}
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? groupId = null) => await DbAccess.GetFeedsAsync(groupId);
public async Task<HashSet<FeedModel>> GetUngroupedFeedsAsync() => await DbAccess.GetFeedsAsync("");
public async Task<HashSet<FeedItemModel>> GetFeedItemsAsync(string feedId, string? groupId = null) => await GetFeedItemsFromFeedsAsync(new[] { feedId }, groupId);
public async Task<HashSet<FeedItemModel>> GetFeedItemsFromFeedsAsync(string[] feedIds, string? groupId = null)
{
var items = await _dbService.GetFeedItemsAsync(feedIds);
var items = await DbAccess.GetFeedItemsAsync(feedIds);
return items;
}
@ -80,12 +99,22 @@ namespace SharpRss.Services
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 = feedModel.Id,
FeedId = feed.Id,
Title = item.Title,
Description = item.Description,
Link = item.Link,
@ -96,9 +125,9 @@ namespace SharpRss.Services
Content = item.Content
});
}
result = await _dbService.SetFeedItemsAsync(itemModels);
return result;
return itemModels;
}
private async Task<Feed> FetchFeed(string url)
{
Log.Verbose("Fetching feed: {FeedUrl}", url);
@ -135,7 +164,6 @@ namespace SharpRss.Services
public void Dispose()
{
_dbService.Dispose();
}
}
}

View File

@ -4,6 +4,7 @@ using Microsoft.Extensions.Hosting;
using MudBlazor;
using MudBlazor.Services;
using Serilog;
using SharpRss;
using SharpRss.Services;
using ToolQit;
using WebSharpRSS;
@ -12,6 +13,7 @@ using WebSharpRSS.Models;
Caretaker.Settings.SetAppDefaultSettings();
Bootstrapper.SetupLogging();
Log.Information("Starting...");
DbAccess.Initialize();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();

View File

@ -23,4 +23,22 @@
<ProjectReference Include="..\SharpRss\SharpRss.csproj" />
</ItemGroup>
<ItemGroup>
<_ContentIncludedByDefault Remove="logs\log_20230507.json" />
<_ContentIncludedByDefault Remove="logs\log_20230509.json" />
<_ContentIncludedByDefault Remove="logs\log_20230512.json" />
<_ContentIncludedByDefault Remove="logs\log_20230513.json" />
<_ContentIncludedByDefault Remove="logs\log_20230515.json" />
<_ContentIncludedByDefault Remove="logs\log_20230517.json" />
<_ContentIncludedByDefault Remove="logs\log_20230518.json" />
<_ContentIncludedByDefault Remove="logs\log_20230519.json" />
<_ContentIncludedByDefault Remove="logs\log_20230521.json" />
<_ContentIncludedByDefault Remove="logs\log_20230522.json" />
<_ContentIncludedByDefault Remove="logs\log_20230523.json" />
<_ContentIncludedByDefault Remove="logs\log_20230524.json" />
<_ContentIncludedByDefault Remove="logs\log_20230525.json" />
<_ContentIncludedByDefault Remove="logs\log_20230526.json" />
<_ContentIncludedByDefault Remove="logs\log_20230527.json" />
</ItemGroup>
</Project>