2023-05-18 01:27:11 +02:00
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
{
2023-05-18 20:15:31 +02:00
internal class DatabaseService : IDisposable
2023-05-18 01:27:11 +02:00
{
private string _connectionString = > $"Data Source={Path.Combine(Environment.CurrentDirectory, " sharp_rss . db ")};" ;
internal DatabaseService ( )
{
_sqlConn = new SqliteConnection ( _connectionString ) ;
InitializeDb ( ) ;
}
private readonly SqliteConnection _sqlConn ;
public async Task < bool > AddCategoriesAsync ( HashSet < CategoryModel > categories )
{
bool result = true ;
_sqlConn . Open ( ) ;
foreach ( var categoryModel in categories )
{
2023-05-18 20:15:31 +02:00
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 . PathIcon , categoryId = categoryModel . CategoryId } ) ;
2023-05-18 01:27:11 +02:00
}
_sqlConn . Close ( ) ;
return result ;
}
public async Task < bool > AddFeedsAsync ( HashSet < FeedModel > feeds )
{
bool result = true ;
_sqlConn . Open ( ) ;
foreach ( var feedModel in feeds )
{
2023-05-18 20:15:31 +02:00
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 . CategoryId } ) ;
2023-05-18 01:27:11 +02:00
}
_sqlConn . Close ( ) ;
return result ;
}
public async Task < HashSet < CategoryModel > > GetCategoriesAsync ( )
{
HashSet < CategoryModel > categories = new HashSet < CategoryModel > ( ) ;
_sqlConn . Open ( ) ;
SqliteCommand cmd = _sqlConn . CreateCommand ( ) ;
cmd . CommandText = "SELECT * FROM category_data" ;
await using SqliteDataReader reader = await cmd . ExecuteReaderAsync ( ) ;
while ( reader . Read ( ) )
categories . Add ( CategoryModel . 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..." ) ;
_sqlConn . Open ( ) ;
2023-05-18 20:15:31 +02:00
var queryResponse = await _sqlConn . QueryAsync ( "CREATE TABLE IF NOT EXISTS category_data (name STRING NOT NULL, hex_color STRING NOT NULL, path_icon STRING, category_id STRING PRIMARY KEY, CONSTRAINT name UNIQUE (name))" ) ;
2023-05-18 01:27:11 +02:00
if ( queryResponse . Any ( ) )
{
_sqlConn . Close ( ) ;
_sqlConn . Dispose ( ) ;
throw new SqliteException ( "Error initializing database!" , 0 ) ;
}
2023-05-18 20:15:31 +02:00
queryResponse = await _sqlConn . QueryAsync ( "CREATE TABLE IF NOT EXISTS feed_data (url STRING NOT NULL, feed_id STRING PRIMARY KEY, category_id STRING NOT NULL DEFAULT '', CONSTRAINT url, UNIQUE (url))" ) ;
2023-05-18 01:27:11 +02:00
if ( queryResponse . Any ( ) )
{
_sqlConn . Close ( ) ;
_sqlConn . Dispose ( ) ;
throw new SqliteException ( "Error initializing database!" , 0 ) ;
}
_sqlConn . Close ( ) ;
Log . Verbose ( "Checking database done!" ) ;
}
public void Dispose ( )
{
_sqlConn . Dispose ( ) ;
}
}
}