mirror of
https://github.com/hmaxnl/SharpRSS.git
synced 2025-01-18 21:04:21 +01:00
Working on database implementation.
This commit is contained in:
parent
c33d8e3a4e
commit
66acd6a1c2
|
@ -1,4 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
using System;
|
||||
using ToolQit.Extensions;
|
||||
|
||||
namespace SharpRss.Models
|
||||
{
|
||||
|
@ -7,18 +8,26 @@ namespace SharpRss.Models
|
|||
/// </summary>
|
||||
public class CategoryModel
|
||||
{
|
||||
public CategoryModel(CategoryModel model)
|
||||
public CategoryModel()
|
||||
{
|
||||
Name = model.Name;
|
||||
Feeds = model.Feeds;
|
||||
HexColor = $"#{_random.Next(0x1000000):X6}";
|
||||
CategoryId = Guid.NewGuid().ToString();
|
||||
}
|
||||
public CategoryModel(string name, HashSet<FeedModel> feeds)
|
||||
private readonly Random _random = new Random();
|
||||
|
||||
public static CategoryModel Create(string categoryName, string hexColor, string id)
|
||||
{
|
||||
Name = name;
|
||||
Feeds = feeds;
|
||||
CategoryModel catModel = new CategoryModel()
|
||||
{
|
||||
Name = categoryName,
|
||||
HexColor = hexColor,
|
||||
CategoryId = id
|
||||
};
|
||||
return catModel;
|
||||
}
|
||||
|
||||
public string Name { get; set; }
|
||||
public HashSet<FeedModel> Feeds { get; set; }
|
||||
public string HexColor { get; set; }
|
||||
public string CategoryId { get; private set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,38 @@
|
|||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using CodeHollow.FeedReader;
|
||||
|
||||
namespace SharpRss.Models
|
||||
{
|
||||
public class FeedModel
|
||||
{
|
||||
public FeedModel(string rssUrl)
|
||||
private FeedModel()
|
||||
{
|
||||
_rssUrl = rssUrl;
|
||||
_fetchTask = FetchAsync();
|
||||
|
||||
}
|
||||
private readonly Task _fetchTask;
|
||||
public FeedModel(Feed feed)
|
||||
{
|
||||
FeedId = Guid.NewGuid().ToString();
|
||||
Url = feed.Link;
|
||||
}
|
||||
|
||||
public string Url { get; set; }
|
||||
public string FeedId { get; private set; }
|
||||
public string CategoryId { get; set; } = "";
|
||||
|
||||
public async Task FetchAsync() => _feed = await FeedCache.GetFeed(_rssUrl);
|
||||
public static FeedModel Create(string url, string feedId, string categoryId)
|
||||
{
|
||||
FeedModel feedModel = new FeedModel()
|
||||
{
|
||||
Url = url,
|
||||
FeedId = feedId,
|
||||
CategoryId = categoryId
|
||||
};
|
||||
return feedModel;
|
||||
}
|
||||
|
||||
private Feed? _feed;
|
||||
//private readonly Task _fetchTask;
|
||||
//public async Task FetchAsync() => _feed = await FeedCache.GetFeed(Url);
|
||||
/*private Feed? _feed;
|
||||
public Feed Base {
|
||||
get
|
||||
{
|
||||
|
@ -28,7 +46,6 @@ namespace SharpRss.Models
|
|||
}
|
||||
return _feed ?? new Feed();
|
||||
}
|
||||
}
|
||||
private readonly string _rssUrl;
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CodeHollow.FeedReader;
|
||||
using SharpRss.Models;
|
||||
|
||||
namespace SharpRss
|
||||
{
|
||||
/// <summary>
|
||||
/// Managing RSS feeds and categories.
|
||||
/// </summary>
|
||||
public class RssService
|
||||
{
|
||||
public RssService()
|
||||
{
|
||||
/// Storage options:
|
||||
/// - Database
|
||||
/// - File
|
||||
/// - Memory
|
||||
combined.UnionWith(feedSet);
|
||||
combined.UnionWith(feedSet2);
|
||||
}
|
||||
|
||||
private static HashSet<FeedModel> feedSet = new HashSet<FeedModel>()
|
||||
{
|
||||
new FeedModel("http://fedoramagazine.org/feed/"),
|
||||
new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"),
|
||||
};
|
||||
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
||||
{
|
||||
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
||||
new FeedModel("https://itsfoss.com/feed")
|
||||
};
|
||||
private static HashSet<FeedModel> combined = new HashSet<FeedModel>();
|
||||
|
||||
HashSet<CategoryModel> set = new HashSet<CategoryModel>()
|
||||
{
|
||||
new CategoryModel("RSS", feedSet),
|
||||
new CategoryModel("Tech", feedSet2)
|
||||
};
|
||||
|
||||
public async Task<HashSet<CategoryModel>> GetCategories()
|
||||
{
|
||||
return set;
|
||||
}
|
||||
|
||||
public async Task<HashSet<FeedModel>> GetAllFeeds()
|
||||
{
|
||||
return combined;
|
||||
}
|
||||
|
||||
|
||||
/// Old
|
||||
|
||||
public async Task<Feed> GetFeed(string feedUrl)
|
||||
{
|
||||
var urls = await FeedReader.GetFeedUrlsFromUrlAsync(feedUrl);
|
||||
string url;
|
||||
if (urls.Count() < 1)
|
||||
url = _feeds[0];
|
||||
else
|
||||
url = urls.First().Url;
|
||||
|
||||
return await FeedReader.ReadAsync(url);
|
||||
}
|
||||
public async Task<HashSet<Feed>> GetFeedsFromCatAsync(CategoryModel category)
|
||||
{
|
||||
return new HashSet<Feed>();
|
||||
}
|
||||
|
||||
private readonly string[] _feeds = { "https://www.reddit.com/r/freshrss/.rss", "http://fedoramagazine.org/" };
|
||||
}
|
||||
}
|
116
SharpRss/Services/DatabaseService.cs
Normal file
116
SharpRss/Services/DatabaseService.cs
Normal file
|
@ -0,0 +1,116 @@
|
|||
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
|
||||
{
|
||||
public class DatabaseService : IDisposable
|
||||
{
|
||||
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();
|
||||
/*var queryResult = await _sqlConn.QueryAsync("SELECT * FROM category_data WHERE name=@catName", new { catName = category.Name });
|
||||
var enumerable = queryResult.ToList();
|
||||
if (queryResult != null && enumerable.Any()) // Category already exists!
|
||||
result = false;*/
|
||||
foreach (var categoryModel in categories)
|
||||
{
|
||||
await _sqlConn.QueryAsync("INSERT OR IGNORE INTO category_data (name, hex_color, category_id) VALUES(@catName, @hexColor, @categoryId)",
|
||||
new { catName = categoryModel.Name, hexColor = categoryModel.HexColor, categoryId = categoryModel.CategoryId });
|
||||
}
|
||||
/*if (result)
|
||||
{
|
||||
|
||||
|
||||
if (createResult.Any()) // Did not create the category
|
||||
result = false;
|
||||
}*/
|
||||
_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 IGNORE INTO feed_data(url, feed_id, category_id) VALUES(@url, @feedId, @categoryId)", new { url = feedModel.Url, feedId = feedModel.FeedId, categoryId = feedModel.CategoryId });
|
||||
}
|
||||
_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();
|
||||
var queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS category_data (name STRING NOT NULL, hex_color STRING NOT NULL, category_id STRING PRIMARY KEY)");
|
||||
if (queryResponse.Any())
|
||||
{
|
||||
_sqlConn.Close();
|
||||
_sqlConn.Dispose();
|
||||
throw new SqliteException("Error initializing database!", 0);
|
||||
}
|
||||
queryResponse = await _sqlConn.QueryAsync("CREATE TABLE IF NOT EXISTS feed_data (url STRING NOT NULL, feed_id STRING PRIMARY KEY, category_id STRING DEFAULT '')");
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
74
SharpRss/Services/RssService.cs
Normal file
74
SharpRss/Services/RssService.cs
Normal file
|
@ -0,0 +1,74 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using SharpRss.Models;
|
||||
|
||||
namespace SharpRss.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Managing RSS feeds and categories.
|
||||
/// </summary>
|
||||
public class RssService
|
||||
{
|
||||
public RssService()
|
||||
{
|
||||
_dbService = new DatabaseService();
|
||||
Initialize();
|
||||
}
|
||||
private readonly DatabaseService _dbService;
|
||||
|
||||
private async void Initialize()
|
||||
{
|
||||
//HashSet<CategoryModel> categoryModels = await _dbService.GetCategoriesAsync();
|
||||
}
|
||||
|
||||
public async Task<HashSet<object>> GetAllAsync()
|
||||
{
|
||||
HashSet<object> items = new HashSet<object>();
|
||||
return items;
|
||||
}
|
||||
|
||||
public async Task<HashSet<CategoryModel>> GetCategoriesAsync()
|
||||
{
|
||||
return new HashSet<CategoryModel>();
|
||||
}
|
||||
|
||||
public async Task<HashSet<FeedModel>> GetFeedsAsync(CategoryModel? categoryModel = null)
|
||||
{
|
||||
HashSet<FeedModel> feeds = new HashSet<FeedModel>();
|
||||
if (categoryModel != null)
|
||||
{
|
||||
// Get feeds from the category.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get all the feeds.
|
||||
}
|
||||
return feeds;
|
||||
}
|
||||
|
||||
public async void AddCategoryAsync(string name)
|
||||
{
|
||||
}
|
||||
|
||||
public async void AddFeedAsync(string rssUrl)
|
||||
{
|
||||
}
|
||||
|
||||
/*private static HashSet<FeedModel> feedSet = new HashSet<FeedModel>()
|
||||
{
|
||||
new FeedModel("http://fedoramagazine.org/feed/"),
|
||||
new FeedModel("https://www.nasa.gov/rss/dyn/breaking_news.rss"),
|
||||
};
|
||||
private static HashSet<FeedModel> feedSet2 = new HashSet<FeedModel>()
|
||||
{
|
||||
new FeedModel("https://journals.plos.org/plosone/feed/atom"),
|
||||
new FeedModel("https://itsfoss.com/feed")
|
||||
};*/
|
||||
|
||||
/*HashSet<CategoryModel> set = new HashSet<CategoryModel>()
|
||||
{
|
||||
new CategoryModel("RSS", feedSet),
|
||||
new CategoryModel("Tech", feedSet2)
|
||||
};*/
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CodeHollow.FeedReader" Version="1.2.6" />
|
||||
<PackageReference Include="Dapper" Version="2.0.123" />
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.5" />
|
||||
<PackageReference Include="Serilog" Version="2.12.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using SharpRss.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using SharpRss.Models;
|
||||
|
||||
namespace WebSharpRSS.Models
|
||||
{
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace WebSharpRSS.Models
|
|||
public TreeItemData(CategoryModel catModel)
|
||||
{
|
||||
CategoryModel = catModel;
|
||||
Feeds = CategoryModel.Feeds.Where(x => x.Base != null).Select(x => new TreeItemData(x)).ToHashSet();
|
||||
//Feeds = CategoryModel.Feeds.Where(x => x.Base != null).Select(x => new TreeItemData(x)).ToHashSet();
|
||||
Title = CategoryModel.Name;
|
||||
Icon = Icons.Material.Filled.RssFeed;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace WebSharpRSS.Models
|
|||
public TreeItemData(FeedModel feedModel)
|
||||
{
|
||||
FeedModel = feedModel;
|
||||
Feed = FeedModel.Base;
|
||||
//Feed = FeedModel.Base;
|
||||
Title = Feed.Title;
|
||||
string faviconAddress = Feed.Link.Remove(Feed.Link.IndexOf("http", StringComparison.Ordinal), Feed.Link.IndexOf("://", StringComparison.Ordinal) + 3);
|
||||
FaviconUrl = string.Format(Caretaker.Settings["Paths"].GetString("FaviconResolveUrl"), faviconAddress);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@using CodeHollow.FeedReader;
|
||||
@using SharpRss.Models;
|
||||
@using WebSharpRSS.Models;
|
||||
@using SharpRss.Services
|
||||
|
||||
@inject RssService _rssService;
|
||||
@inject FeedStateContainer _stateContainer;
|
||||
|
@ -11,12 +12,12 @@
|
|||
{
|
||||
foreach (var feedItem in _items)
|
||||
{
|
||||
<MudItem>
|
||||
<MudItem xs="6">
|
||||
<MudCard>
|
||||
<MudCardContent>
|
||||
<MudText>@feedItem.Title</MudText>
|
||||
<MudText Typo="Typo.body2">@feedItem.Description</MudText>
|
||||
<MudText Typo="Typo.overline">@feedItem.PublishingDateString</MudText>
|
||||
<MudText Typo="Typo.overline">@feedItem.PublishingDate.ToString()</MudText>
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
|
@ -46,7 +47,7 @@
|
|||
if (Feeds == null) return;
|
||||
foreach (var feedmodel in Feeds)
|
||||
{
|
||||
_items = feedmodel.Base.Items.OrderBy(x => x.PublishingDate).ToHashSet();
|
||||
//_items = feedmodel.Base.Items.OrderBy(x => x.PublishingDate).Reverse().ToHashSet();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ using MudBlazor.Services;
|
|||
using Serilog;
|
||||
using SharpRss;
|
||||
using SharpRss.Models;
|
||||
using SharpRss.Services;
|
||||
using ToolQit;
|
||||
using WebSharpRSS;
|
||||
using WebSharpRSS.Models;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@using MudBlazor.Utilities
|
||||
@using CodeHollow.FeedReader
|
||||
@using Serilog
|
||||
@using SharpRss.Services
|
||||
@using WebSharpRSS.Models;
|
||||
@using ToolQit.Extensions;
|
||||
|
||||
|
@ -10,7 +11,7 @@
|
|||
@inject RssService _rssService
|
||||
|
||||
<MudStack Spacing="2">
|
||||
<MudTreeView Items="Categories" @bind-SelectedValue="SelectedItem" Hover="true">
|
||||
<MudTreeView Items="GuideItems" @bind-SelectedValue="SelectedItem" Hover="true">
|
||||
<ItemTemplate>
|
||||
<MudTreeViewItem @bind-Expanded="@context.IsExpanded" Items="@context.Feeds" Value="@context">
|
||||
<Content>
|
||||
|
@ -38,7 +39,7 @@
|
|||
</MudStack>
|
||||
|
||||
@code {
|
||||
public HashSet<TreeItemData> Categories = new HashSet<TreeItemData>();
|
||||
public HashSet<TreeItemData> GuideItems = new HashSet<TreeItemData>();
|
||||
private TreeItemData? _selecteditem;
|
||||
private TreeItemData? SelectedItem
|
||||
{
|
||||
|
@ -58,14 +59,13 @@
|
|||
{
|
||||
|
||||
}
|
||||
//_navManager.NavigateTo("/");
|
||||
}
|
||||
protected override async void OnInitialized()
|
||||
{
|
||||
Log.Verbose("Loading guide data...");
|
||||
|
||||
HashSet<CategoryModel> cats = await _rssService.GetCategories();
|
||||
await Task.Run(() => Categories.UnionWith(cats.Select(x => new TreeItemData(x)).ToHashSet()));
|
||||
/*HashSet<CategoryModel> cats = await _rssService.GetAllAsync();
|
||||
await Task.Run(() => Categories.UnionWith(cats.Select(x => new TreeItemData(x)).ToHashSet()));*/
|
||||
|
||||
StateHasChanged();
|
||||
Log.Verbose(" Guide initialized!");
|
||||
|
|
BIN
WebSharpRSS/sharp_rss.db
Normal file
BIN
WebSharpRSS/sharp_rss.db
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user