2023-07-09 21:29:33 -07:00
using Newsbot.Collector.Database ;
2023-03-05 20:12:59 -08:00
using Newsbot.Collector.Database.Repositories ;
2023-06-23 20:09:57 -07:00
using Newsbot.Collector.Domain.Entities ;
2023-03-05 20:12:59 -08:00
using Newsbot.Collector.Domain.Interfaces ;
using Newsbot.Collector.Domain.Models ;
using Newsbot.Collector.Services.Notifications.Discord ;
2023-03-05 22:33:41 -08:00
using Serilog ;
2023-03-05 20:12:59 -08:00
namespace Newsbot.Collector.Services.Jobs ;
2023-04-14 21:39:02 -07:00
public class MessageTypeNotRequestedException : Exception
{
public MessageTypeNotRequestedException ( )
{
}
public MessageTypeNotRequestedException ( string message ) : base ( message )
{
}
public MessageTypeNotRequestedException ( string message , Exception inner ) : base ( message , inner )
{
}
}
2023-03-05 20:12:59 -08:00
public class DiscordNotificationJobOptions
{
2023-04-01 08:53:34 -07:00
public string? ConnectionString { get ; init ; }
public string? OpenTelemetry { get ; init ; }
public bool IsEnabled { get ; init ; }
2023-03-05 20:12:59 -08:00
}
2023-03-05 22:33:41 -08:00
public class DiscordNotificationJob
2023-03-05 20:12:59 -08:00
{
2023-04-01 08:53:34 -07:00
private const string JobName = "DiscordNotifications" ;
2023-07-09 21:29:33 -07:00
private ILogger _logger ;
//private DatabaseContext _databaseContext;
2023-03-05 20:12:59 -08:00
private IArticlesRepository _article ;
2023-03-31 22:49:39 -07:00
private IIconsRepository _icons ;
2023-04-13 22:13:06 -07:00
private IDiscordQueueRepository _queue ;
private ISourcesRepository _sources ;
2023-07-09 21:29:33 -07:00
private IDiscordNotificationRepository _subs ;
2023-04-13 22:13:06 -07:00
private IDiscordWebHooksRepository _webhook ;
2023-03-05 22:33:41 -08:00
public DiscordNotificationJob ( )
2023-03-05 20:12:59 -08:00
{
_queue = new DiscordQueueTable ( "" ) ;
_article = new ArticlesTable ( "" ) ;
_webhook = new DiscordWebhooksTable ( "" ) ;
_sources = new SourcesTable ( "" ) ;
2023-07-09 21:29:33 -07:00
_subs = new DiscordNotificationTable ( "" ) ;
2023-03-31 22:49:39 -07:00
_icons = new IconsTable ( "" ) ;
2023-04-01 08:53:34 -07:00
_logger = JobLogger . GetLogger ( "" , JobName ) ;
2023-03-05 20:12:59 -08:00
}
2023-03-05 22:33:41 -08:00
public void InitAndExecute ( DiscordNotificationJobOptions options )
2023-03-05 20:12:59 -08:00
{
2023-07-09 21:29:33 -07:00
//_databaseContext = new DatabaseContext(options.ConnectionString ?? "");
2023-04-01 08:53:34 -07:00
_queue = new DiscordQueueTable ( options . ConnectionString ? ? "" ) ;
_article = new ArticlesTable ( options . ConnectionString ? ? "" ) ;
_webhook = new DiscordWebhooksTable ( options . ConnectionString ? ? "" ) ;
_sources = new SourcesTable ( options . ConnectionString ? ? "" ) ;
2023-07-09 21:29:33 -07:00
_subs = new DiscordNotificationTable ( options . ConnectionString ? ? "" ) ;
2023-04-01 08:53:34 -07:00
_icons = new IconsTable ( options . ConnectionString ? ? "" ) ;
2023-03-31 22:49:39 -07:00
2023-04-01 08:53:34 -07:00
_logger = JobLogger . GetLogger ( options . OpenTelemetry ? ? "" , JobName ) ;
if ( ! options . IsEnabled )
{
_logger . Warning ( $"{JobName} - Going to exit because feature flag is off." ) ;
return ;
}
2023-04-13 22:13:06 -07:00
2023-04-01 08:53:34 -07:00
_logger . Information ( $"{JobName} - Starting up the job." ) ;
2023-03-05 22:33:41 -08:00
Execute ( ) ;
2023-03-05 20:12:59 -08:00
}
private void Execute ( )
{
//collect all the new requests
2023-07-09 21:29:33 -07:00
2023-04-13 22:13:06 -07:00
var requests = _queue . List ( 100 ) ;
2023-04-03 06:46:35 -07:00
_logger . Debug ( $"{JobName} - Collected {requests.Count} items to send" ) ;
2023-03-05 20:12:59 -08:00
2023-04-14 21:39:02 -07:00
foreach ( var request in requests ) ProcessQueueItem ( request ) ;
_logger . Information ( $"{JobName} - Loop has been completed." ) ;
}
2023-06-23 20:19:09 -07:00
public void ProcessQueueItem ( DiscordQueueEntity request )
2023-04-14 21:39:02 -07:00
{
2023-06-23 20:19:09 -07:00
_logger . Debug ( $"{JobName} - Processing {request.Id}" ) ;
2023-04-14 21:39:02 -07:00
// Get all details on the article in the queue
2023-06-23 20:19:09 -07:00
var articleDetails = _article . GetById ( request . ArticleId ) ;
2023-04-14 21:39:02 -07:00
// Get the details of the source
2023-06-23 23:01:40 -07:00
var sourceDetails = _sources . GetById ( articleDetails . SourceId ) ;
if ( sourceDetails . Id = = Guid . Empty )
2023-03-05 20:12:59 -08:00
{
2023-04-14 21:39:02 -07:00
_logger . Error (
2023-06-23 20:09:57 -07:00
$"{JobName} - Article ({articleDetails.Id}) was linked to a empty Source ID. Removing from the queue." ) ;
2023-06-23 20:19:09 -07:00
_queue . Delete ( request . Id ) ;
2023-04-14 21:39:02 -07:00
return ;
2023-03-05 20:12:59 -08:00
}
2023-04-13 22:13:06 -07:00
2023-06-23 23:01:40 -07:00
var sourceIcon = new IconEntity ( ) ;
2023-04-14 21:39:02 -07:00
try
{
2023-06-23 23:01:40 -07:00
sourceIcon = _icons . GetBySourceId ( sourceDetails . Id ) ;
2023-04-14 21:39:02 -07:00
}
catch
{
_logger . Warning ( "{JobName} - Source ID \'{SourceDetailsId}\' is missing an icon" , JobName ,
2023-06-23 23:01:40 -07:00
sourceDetails . Id ) ;
2023-04-14 21:39:02 -07:00
}
// Find all the subscriptions for that source
2023-06-25 21:02:26 -07:00
var allSubscriptions = _subs . ListBySourceId ( sourceDetails . Id ) ;
2023-04-14 21:39:02 -07:00
foreach ( var sub in allSubscriptions )
2023-06-23 20:19:09 -07:00
SendSubscriptionNotification ( request . Id , articleDetails , sourceDetails , sourceIcon , sub ) ;
2023-04-14 21:39:02 -07:00
2023-06-23 20:19:09 -07:00
_logger . Debug ( "{JobName} - Removing {RequestId} from the queue" , JobName , request . Id ) ;
_queue . Delete ( request . Id ) ;
2023-04-14 21:39:02 -07:00
}
2023-07-09 21:29:33 -07:00
public void SendSubscriptionNotification ( Guid requestId , ArticlesEntity articleDetails , SourceEntity sourceDetails , IconEntity sourceIcon , DiscordNotificationEntity sub )
2023-04-14 21:39:02 -07:00
{
// Check if the subscription code flags
// If the article is a code commit and the subscription does not want them, skip.
if ( articleDetails . CodeIsCommit & & ! sub . CodeAllowCommits ) throw new MessageTypeNotRequestedException ( "Message was a code commit and was not requested by the subscription." ) ;
// same for releases
if ( articleDetails . CodeIsRelease & & ! sub . CodeAllowReleases ) throw new MessageTypeNotRequestedException ( "Message was a code release and was not requested by the subscription" ) ;
// find the discord webhooks we need to post to
2023-06-23 21:55:56 -07:00
var discordDetails = _webhook . GetById ( sub . DiscordWebHookId ) ;
2023-04-14 21:39:02 -07:00
if ( discordDetails . Enabled = = false ) return ;
2023-07-09 21:29:33 -07:00
var client = new DiscordClient ( discordDetails . Url ) ;
2023-04-14 21:39:02 -07:00
try
{
client . SendMessage ( GenerateDiscordMessage ( sourceDetails , articleDetails , sourceIcon ) ) ;
}
catch ( Exception e )
{
_logger . Error ( "Failed to post message to Discord. {ErrorMessage}" , e . Message ) ;
_logger . Debug ( "Queue Record: {RequestId}" , requestId ) ;
2023-06-23 20:09:57 -07:00
_logger . Debug ( "Article: {ArticleDetailsId}" , articleDetails . Id ) ;
2023-06-23 23:01:40 -07:00
_logger . Debug ( "Source: {SourceDetailsId}" , sourceDetails . Id ) ;
2023-04-14 21:39:02 -07:00
_logger . Debug ( "Subscription: {SubId}" , sub . Id ) ;
}
Thread . Sleep ( 3000 ) ;
2023-03-05 20:12:59 -08:00
}
2023-06-23 23:01:40 -07:00
public DiscordMessage GenerateDiscordMessage ( SourceEntity source , ArticlesEntity article , IconEntity icon )
2023-03-05 20:12:59 -08:00
{
var embed = new DiscordMessageEmbed
{
Title = article . Title ,
Color = DiscordMessageEmbedColors . Red ,
2023-05-25 21:42:32 -07:00
Description = MessageValidation . ConvertHtmlCodes ( article . Description ) ,
2023-03-05 20:12:59 -08:00
Author = new DiscordMessageEmbedAuthor
{
Name = article . AuthorName ,
2023-03-31 22:49:39 -07:00
IconUrl = icon . FileName
2023-03-05 20:12:59 -08:00
} ,
Footer = new DiscordMessageEmbedFooter
{
2023-04-13 22:13:06 -07:00
Text = "Brought to you by Newsbot"
2023-03-05 22:33:41 -08:00
} ,
Fields = new DiscordMessageEmbedField [ ]
{
2023-04-13 22:13:06 -07:00
new ( )
2023-03-05 22:33:41 -08:00
{
Name = "Link" ,
2023-06-23 20:09:57 -07:00
Value = article . Url ,
2023-04-13 22:13:06 -07:00
Inline = false
2023-03-05 22:33:41 -08:00
}
2023-03-05 20:12:59 -08:00
}
} ;
2023-06-23 20:09:57 -07:00
if ( article . Url is not null & & article . Url ! = "" ) embed . Url = article . Url ;
2023-03-05 20:12:59 -08:00
2023-04-01 08:53:34 -07:00
if ( article . Thumbnail ! = "" )
2023-03-05 20:12:59 -08:00
embed . Image = new DiscordMessageEmbedImage
{
Url = article . Thumbnail
} ;
2023-04-13 22:13:06 -07:00
if ( article . AuthorImage is not null & & article . AuthorImage ! = "" ) embed . Author . IconUrl = article . AuthorImage ;
2023-03-05 20:12:59 -08:00
return new DiscordMessage
{
2023-04-13 22:13:06 -07:00
Embeds = new [ ]
2023-03-05 20:12:59 -08:00
{
embed
}
} ;
}
}