SharpRSS/SharpRss/Services/DatabaseService.cs
2023-05-20 00:35:43 +02:00

123 lines
5.2 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using Microsoft.Data.Sqlite;
using Serilog;
using SharpRss.Models;
namespace SharpRss.Services
{
internal class DatabaseService : IDisposable
{
internal DatabaseService()
{
_sqlConn = new SqliteConnection(_connectionString);
InitializeDb();
}
private readonly SqliteConnection _sqlConn;
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";
public async Task RemoveGroupFromFeedsAsync(string groupId)
{
await _sqlConn.QueryAsync("UPDATE feed_data SET group_id=NULL WHERE group_id=@GroupId", new { GroupId = groupId });
}
public async Task<bool> AddCategoriesAsync(HashSet<GroupModel> categories)
{
bool result = true;
_sqlConn.Open();
foreach (var categoryModel in categories)
{
await _sqlConn.QueryAsync("INSERT INTO category_data (name, hex_color, path_icon, category_id) VALUES(@catName, @hexColor, @pathIcon, @categoryId) ON CONFLICT(name) DO UPDATE SET hex_color=@hexColor, path_icon=@pathIcon",
new { catName = categoryModel.Name, hexColor = categoryModel.HexColor, pathIcon = categoryModel.Icon, categoryId = categoryModel.Id });
}
_sqlConn.Close();
return result;
}
public async Task<bool> AddFeedsAsync(HashSet<FeedModel> feeds)
{
bool result = true;
_sqlConn.Open();
foreach (var feedModel in feeds)
{
await _sqlConn.QueryAsync("INSERT OR REPLACE INTO feed_data(url, feed_id, category_id) VALUES(@url, @feedId, @categoryId) ON CONFLICT(url) DO UPDATE SET category_id=@categoryId", new { url = feedModel.FeedUrl, feedId = feedModel.FeedId, categoryId = feedModel.GroupId });
}
_sqlConn.Close();
return result;
}
public async Task<HashSet<GroupModel>> GetCategoriesAsync()
{
HashSet<GroupModel> categories = new HashSet<GroupModel>();
_sqlConn.Open();
SqliteCommand cmd = _sqlConn.CreateCommand();
cmd.CommandText = "SELECT * FROM category_data";
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
while (reader.Read())
{
//categories.Add(GroupModel.Create(reader["name"].ToString(), reader["hex_color"].ToString(), reader["category_id"].ToString()));
}
_sqlConn.Close();
return categories;
}
public async Task<HashSet<FeedModel>> GetFeedsAsync(string? categoryId = null)
{
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
_sqlConn.Open();
SqliteCommand cmd = _sqlConn.CreateCommand();
cmd.CommandText = categoryId == null ? "SELECT * FROM feed_data" : "SELECT * FROM feed_data WHERE category_id=@categoryId";
if (categoryId != null)
cmd.Parameters.Add(new SqliteParameter("categoryId", categoryId));
await using SqliteDataReader reader = await cmd.ExecuteReaderAsync();
while (reader.Read())
{
//feeds.Add(FeedModel.Create(reader["url"].ToString(), reader["feed_id"].ToString(), reader["category_id"].ToString()));
}
_sqlConn.Close();
return feeds;
}
private async void InitializeDb()
{
Log.Verbose("Checking database...");
HashSet<string> failed = new HashSet<string>();
_sqlConn.Open();
Log.Verbose("Checking table: {Table}", _groupTable);
var queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_groupTable} (name STRING NOT NULL, hex_color STRING NOT NULL, icon STRING, id STRING PRIMARY KEY, CONSTRAINT name UNIQUE (name))");
if (queryResponse.Any()) failed.Add("category_data");
Log.Verbose("Checking table: {Table}", _feedTable);
queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedTable} (url STRING NOT NULL, id STRING PRIMARY KEY, group_id STRING DEFAULT NULL, CONSTRAINT url, UNIQUE (url))");
if (queryResponse.Any()) failed.Add("feed_data");
Log.Verbose("Checking table: {Table}", _feedItemTable);
queryResponse = await _sqlConn.QueryAsync($"CREATE TABLE IF NOT EXISTS {_feedItemTable} (id STRING PRIMARY KEY, feed_id STRING NOT NULL)");
if (queryResponse.Any()) failed.Add("feed_item_data");
_sqlConn.Close();
if (failed.Any())
{
var joined = string.Join(',', failed);
Log.Error("Failed to initialize table(s): {TableNames}", joined);
}
else
Log.Verbose("Checking database done!");
}
public void Dispose()
{
_sqlConn.Dispose();
}
}
}