Compare commits

..

No commits in common. "52e86c01cea407f9c28bd7e74512b94572e86308" and "0797fb85029f2fd42e31a8e846d23365fe10222a" have entirely different histories.

20 changed files with 103 additions and 120 deletions

View File

@ -1,4 +1,3 @@
appsettings.json appsettings.json
**/bin/** **/bin/
**/obj/** **/obj/
**/efbundle

View File

@ -17,7 +17,7 @@ RUN dotnet publish -o build
RUN ls build RUN ls build
FROM build as ef FROM build as ef
RUN dotnet tool install dotnet-ef --tool-path /usr/bin --version 7.0.8 RUN dotnet tool install dotnet-ef --tool-path /usr/bin
RUN dotnet ef migrations bundle --project "Newsbot.Collector.Database" RUN dotnet ef migrations bundle --project "Newsbot.Collector.Database"
FROM mcr.microsoft.com/dotnet/aspnet:7.0.3 as app FROM mcr.microsoft.com/dotnet/aspnet:7.0.3 as app

View File

@ -2,7 +2,6 @@ using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newsbot.Collector.Database.Repositories; using Newsbot.Collector.Database.Repositories;
using Newsbot.Collector.Domain.Dto; using Newsbot.Collector.Domain.Dto;
using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;
using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models;
@ -69,7 +68,7 @@ public class SubscriptionsController : ControllerBase
public IEnumerable<SubscriptionDto> GetBySourceId(Guid id) public IEnumerable<SubscriptionDto> GetBySourceId(Guid id)
{ {
var res = new List<SubscriptionDto>(); var res = new List<SubscriptionDto>();
var items = _subscription.ListBySourceId(id); var items = _subscription.ListBySourceID(id);
foreach (var item in items) res.Add(SubscriptionDto.Convert(item)); foreach (var item in items) res.Add(SubscriptionDto.Convert(item));
return res; return res;
} }
@ -89,7 +88,7 @@ public class SubscriptionsController : ControllerBase
var source = _sources.GetById(sourceId); var source = _sources.GetById(sourceId);
if (source.Id == Guid.Empty) return new BadRequestResult(); if (source.Id == Guid.Empty) return new BadRequestResult();
var item = _subscription.New(new SubscriptionEntity var item = _subscription.New(new SubscriptionModel
{ {
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
SourceId = sourceId, SourceId = sourceId,
@ -117,7 +116,7 @@ public class SubscriptionsController : ControllerBase
var source = _sources.GetById(sourceId); var source = _sources.GetById(sourceId);
if (source.Id == Guid.Empty) return new BadRequestResult(); if (source.Id == Guid.Empty) return new BadRequestResult();
var sub = _subscription.New(new SubscriptionEntity var sub = _subscription.New(new SubscriptionModel
{ {
DiscordWebHookId = discordId, DiscordWebHookId = discordId,
SourceId = sourceId, SourceId = sourceId,

View File

@ -14,11 +14,6 @@
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.33" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.7.33" />
<PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" /> <PackageReference Include="Hangfire.MemoryStorage" Version="1.7.0" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.8" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.4.0" /> <PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.4.0" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.4.0" /> <PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.4.0" />

View File

@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Newsbot.Collector.Api; using Newsbot.Collector.Api;
using Newsbot.Collector.Api.Authentication; using Newsbot.Collector.Api.Authentication;
using Newsbot.Collector.Database;
using Newsbot.Collector.Domain.Consts; using Newsbot.Collector.Domain.Consts;
using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models;
using Newsbot.Collector.Domain.Models.Config; using Newsbot.Collector.Domain.Models.Config;
@ -72,8 +71,6 @@ builder.Services.AddSwaggerGen(cfg =>
cfg.AddSecurityRequirement(requirement); cfg.AddSecurityRequirement(requirement);
}); });
builder.Services.AddDbContext<DatabaseContext>();
var app = builder.Build(); var app = builder.Build();
// Configure the HTTP request pipeline. // Configure the HTTP request pipeline.

View File

@ -16,7 +16,7 @@ public class DatabaseContext : DbContext
private string ConnectionString { get; set; } private string ConnectionString { get; set; }
public DatabaseContext(IConfiguration appsettings, string connectionString) public DatabaseContext(IConfiguration appsettings)
{ {
var connString = appsettings.GetConnectionString(ConfigConnectionStringConst.Database); var connString = appsettings.GetConnectionString(ConfigConnectionStringConst.Database);
ConnectionString = connString ?? ""; ConnectionString = connString ?? "";
@ -27,24 +27,13 @@ public class DatabaseContext : DbContext
ConnectionString = connectionString; ConnectionString = connectionString;
} }
public DatabaseContext(DbContextOptions<DatabaseContext> connectionString)
{
ConnectionString = "";
}
public DatabaseContext()
{
ConnectionString = "";
}
protected override void OnConfiguring(DbContextOptionsBuilder options) protected override void OnConfiguring(DbContextOptionsBuilder options)
{ {
options.UseNpgsql(ConnectionString); options.UseNpgsql(ConnectionString);
} }
public DatabaseContext(DbContextOptions<DatabaseContext> options, string connectionString) public DatabaseContext(DbContextOptions<DatabaseContext> options)
: base(options) : base(options)
{ {
ConnectionString = connectionString;
} }
} }

View File

@ -1,6 +1,5 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design; using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
namespace Newsbot.Collector.Database; namespace Newsbot.Collector.Database;

View File

@ -6,8 +6,8 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="dapper" Version="2.0.123" /> <PackageReference Include="dapper" Version="2.0.123" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.8"> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.7">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
</PackageReference> </PackageReference>

View File

@ -35,7 +35,7 @@ public class SourcesTable : ISourcesRepository
} }
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"Failed to save source to db. {model.ToString()} {ex.Message} "); Console.WriteLine($"Failed to save ");
} }
return model; return model;

View File

@ -1,7 +1,6 @@
using System.Data; using System.Data;
using Dapper; using Dapper;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;
using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models;
using Npgsql; using Npgsql;
@ -24,64 +23,104 @@ public class SubscriptionsTable : ISubscriptionRepository
_connectionString = connstr; _connectionString = connstr;
} }
public SubscriptionEntity New(SubscriptionEntity model) public SubscriptionModel New(SubscriptionModel model)
{ {
model.Id = new Guid(); model.Id = Guid.NewGuid();
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
context.Subscriptions.Add(model); var query =
context.SaveChanges(); "Insert Into subscriptions (ID, DiscordWebHookId, SourceId, codeAllowCommits, codeAllowReleases) Values (@id, @webhookId, @sourceId, @codeAllowCommits, @codeAllowReleases);";
return model; try
{
conn.Execute(query, new
{
id = model.Id,
webhookId = model.DiscordWebHookId,
sourceId = model.SourceId,
codeAllowCommits = model.CodeAllowCommits,
codeAllowReleases = model.CodeAllowReleases
});
return model;
}
catch
{
return new SubscriptionModel();
}
} }
public List<SubscriptionEntity> List(int page = 0, int count = 25) public List<SubscriptionModel> List(int page = 0, int count = 25)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
return context.Subscriptions.Skip(page * count).Take(count).ToList(); var query = @"Select * From subscriptions
Offset @page Fetch Next @count Rows Only;";
return conn.Query<SubscriptionModel>(query, new
{
page = page * count, count
}).ToList();
} }
public List<SubscriptionEntity> ListBySourceId(Guid id, int page = 0, int count = 25) public List<SubscriptionModel> ListBySourceID(Guid id, int page = 0, int count = 25)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
return context.Subscriptions.Where(f => f.SourceId.Equals(id)) var query = @"Select * From subscriptions
.Skip(page * count) Where sourceid = @sourceid
.ToList(); Offset @page Fetch Next @count Rows Only";
return conn.Query<SubscriptionModel>(query, new
{
page = page * count,
count,
sourceid = id
}).ToList();
} }
public List<SubscriptionEntity> ListByWebhook(Guid id, int page = 0, int count = 25) public List<SubscriptionModel> ListByWebhook(Guid id, int page = 0, int count = 25)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
return context.Subscriptions.Where(f => f.DiscordWebHookId.Equals(id)).Skip(page * count).ToList(); var query = @"Select * From subscriptions
Where discordwebhookid = @webhookid
Offset @page Fetch Next @count Rows Only";
return conn.Query<SubscriptionModel>(query, new
{
page = page * count,
count,
webhookid = id
}).ToList();
} }
public SubscriptionEntity GetById(Guid id) public SubscriptionModel GetById(Guid id)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
var res = context.Subscriptions var query = @"Select * From subscriptions Where id = @id;";
.FirstOrDefault(f => f.Id.Equals(id)); var res = conn.Query<SubscriptionModel>(query, new
return res ??= new SubscriptionEntity(); {
id
});
if (res.Count() == 0) return new SubscriptionModel();
return res.First();
} }
public SubscriptionEntity GetByWebhookAndSource(Guid webhookId, Guid sourceId) public SubscriptionModel GetByWebhookAndSource(Guid webhookId, Guid sourceId)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
var res = context.Subscriptions var query = @"Select * From subscriptions
.Where(f => f.DiscordWebHookId.Equals(webhookId)) Where discordwebhookid = @webhookid
.FirstOrDefault(f => f.SourceId.Equals(sourceId)); and sourceid = @sourceid;";
return res ??= new SubscriptionEntity(); var res = conn.Query<SubscriptionModel>(query, new
{
webhookid = webhookId,
sourceid = sourceId
});
if (res.Count() == 0) return new SubscriptionModel();
return res.First();
} }
public void Delete(Guid id) public void Delete(Guid id)
{ {
using var context = new DatabaseContext(_connectionString); using var conn = OpenConnection(_connectionString);
var res = context.Subscriptions.FirstOrDefault(f => f.Id.Equals(id)); var query = "Delete From subscriptions Where id = @id;";
if (res is null) conn.Execute(query, new
{ {
return; id
} });
context.Subscriptions.Remove(res);
context.SaveChanges();
} }
private IDbConnection OpenConnection(string connectionString) private IDbConnection OpenConnection(string connectionString)

View File

@ -11,7 +11,7 @@ public class SubscriptionDetailsDto
public SourceDto? Source { get; set; } public SourceDto? Source { get; set; }
public DiscordWebHookDto? DiscordWebHook { get; set; } public DiscordWebHookDto? DiscordWebHook { get; set; }
public static SubscriptionDetailsDto Convert(SubscriptionEntity subscription, SourceEntity source, public static SubscriptionDetailsDto Convert(SubscriptionModel subscription, SourceEntity source,
DiscordWebhookEntity discord) DiscordWebhookEntity discord)
{ {
return new SubscriptionDetailsDto return new SubscriptionDetailsDto

View File

@ -1,4 +1,3 @@
using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models;
namespace Newsbot.Collector.Domain.Dto; namespace Newsbot.Collector.Domain.Dto;
@ -11,7 +10,7 @@ public class SubscriptionDto
public bool CodeAllowReleases { get; set; } public bool CodeAllowReleases { get; set; }
public bool CodeAllowCommits { get; set; } public bool CodeAllowCommits { get; set; }
public static SubscriptionDto Convert(SubscriptionEntity model) public static SubscriptionDto Convert(SubscriptionModel model)
{ {
return new SubscriptionDto return new SubscriptionDto
{ {

View File

@ -1,18 +1,17 @@
using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Models; using Newsbot.Collector.Domain.Models;
namespace Newsbot.Collector.Domain.Interfaces; namespace Newsbot.Collector.Domain.Interfaces;
public interface ISubscriptionRepository public interface ISubscriptionRepository
{ {
SubscriptionEntity New(SubscriptionEntity model); SubscriptionModel New(SubscriptionModel model);
List<SubscriptionEntity> List(int page = 0, int count = 25); List<SubscriptionModel> List(int page = 0, int count = 25);
List<SubscriptionEntity> ListBySourceId(Guid id, int page = 0, int count = 25); List<SubscriptionModel> ListBySourceID(Guid id, int page = 0, int count = 25);
List<SubscriptionEntity> ListByWebhook(Guid id, int page = 0, int count = 25); List<SubscriptionModel> ListByWebhook(Guid id, int page = 0, int count = 25);
SubscriptionEntity GetById(Guid id); SubscriptionModel GetById(Guid id);
SubscriptionEntity GetByWebhookAndSource(Guid webhookId, Guid sourceId); SubscriptionModel GetByWebhookAndSource(Guid webhookId, Guid sourceId);
void Delete(Guid id); void Delete(Guid id);
} }

View File

@ -112,7 +112,7 @@ public class DiscordNotificationJob
} }
// Find all the subscriptions for that source // Find all the subscriptions for that source
var allSubscriptions = _subs.ListBySourceId(sourceDetails.Id); var allSubscriptions = _subs.ListBySourceID(sourceDetails.Id);
foreach (var sub in allSubscriptions) foreach (var sub in allSubscriptions)
SendSubscriptionNotification(request.Id, articleDetails, sourceDetails, sourceIcon, sub); SendSubscriptionNotification(request.Id, articleDetails, sourceDetails, sourceIcon, sub);
@ -121,7 +121,7 @@ public class DiscordNotificationJob
_queue.Delete(request.Id); _queue.Delete(request.Id);
} }
public void SendSubscriptionNotification(Guid requestId, ArticlesEntity articleDetails, SourceEntity sourceDetails, IconEntity sourceIcon, SubscriptionEntity sub) public void SendSubscriptionNotification(Guid requestId, ArticlesEntity articleDetails, SourceEntity sourceDetails, IconEntity sourceIcon, SubscriptionModel sub)
{ {
// Check if the subscription code flags // Check if the subscription code flags
// If the article is a code commit and the subscription does not want them, skip. // If the article is a code commit and the subscription does not want them, skip.

View File

@ -7,10 +7,6 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.46" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.46" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Selenium.WebDriver" Version="4.8.1" /> <PackageReference Include="Selenium.WebDriver" Version="4.8.1" />
<PackageReference Include="Selenium.WebDriver.GeckoDriver" Version="0.32.2" /> <PackageReference Include="Selenium.WebDriver.GeckoDriver" Version="0.32.2" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />

View File

@ -1,4 +1,5 @@
using Newsbot.Collector.Domain.Entities; using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Models;
using Newsbot.Collector.Services.Jobs; using Newsbot.Collector.Services.Jobs;
using Newsbot.Collector.Services.Notifications.Discord; using Newsbot.Collector.Services.Notifications.Discord;
@ -78,7 +79,7 @@ public class DiscordNotificationJobTest
Id = Guid.NewGuid(), Id = Guid.NewGuid(),
FileName = "https://www.redditstatic.com/desktop2x/img/favicon/android-icon-192x192.png" FileName = "https://www.redditstatic.com/desktop2x/img/favicon/android-icon-192x192.png"
}, },
new SubscriptionEntity new SubscriptionModel
{ {
CodeAllowCommits = false, CodeAllowCommits = false,
CodeAllowReleases = true CodeAllowReleases = true
@ -87,7 +88,6 @@ public class DiscordNotificationJobTest
} }
catch (MessageTypeNotRequestedException) catch (MessageTypeNotRequestedException)
{ {
Console.Write($"Message did not send as expected"); Console.Write($"Message did not send as expected");
} }

View File

@ -61,7 +61,7 @@ public class RssWatcherJobTest
[Fact] [Fact]
public void CanReadHtmlDrivenFeedPage() public void CanReadHtmlDrivenFeedPage()
{ {
//var url = "https://www.howtogeek.com/feed/"; var url = "https://www.howtogeek.com/feed/";
var client = new RssWatcherJob(); var client = new RssWatcherJob();
client.InitAndExecute(new RssWatcherJobOptions client.InitAndExecute(new RssWatcherJobOptions
{ {

View File

@ -9,10 +9,6 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.8">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" /> <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="7.0.4" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />

View File

@ -1,26 +1,2 @@
# Newsbot.Collector # Newsbot.Collector
C# API Server to collect news from around the world
C# API Server to collect news from around the world.
## Features
- YouTube
- Github
- Should support other source control services but untested
- RSS
## Notifications
- Discord Webhooks
## Legacy Features No longer support
- Twitter
- API Changes
- Reddit
- API Changes
- Could come back as long as the json dump is still available
- Instagram
- No plans to attempt to get this working again.

View File

@ -22,7 +22,7 @@ docker-migrate: ## Runs the migrations stored in the Docker image
docker run -it --env-file .env ghcr.io/jtom38/newsbot.collector:master /app/goose --dir "/app/migrations" up docker run -it --env-file .env ghcr.io/jtom38/newsbot.collector:master /app/goose --dir "/app/migrations" up
ef-build: ## Builds migration artifact ef-build: ## Builds migration artifact
dotnet ef migrations bundle --project "Newsbot.Collector.Database" --force dotnet ef migrations bundle --project "Newsbot.Collector.Database"
ef-migrate: ## Runs migrations based on the newest artifact ef-migrate: ## Runs migrations based on the newest artifact
dotnet ef migrations bundle --project "Newsbot.Collector.Database" --force dotnet ef migrations bundle --project "Newsbot.Collector.Database" --force