Newsbot.Collector/Newsbot.Collector.Services/Jobs/DiscordNotificationJob.cs

200 lines
6.8 KiB
C#
Raw Normal View History

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;
using Serilog;
2023-03-05 20:12:59 -08:00
namespace Newsbot.Collector.Services.Jobs;
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
{
public string? ConnectionString { get; init; }
public string? OpenTelemetry { get; init; }
public bool IsEnabled { get; init; }
2023-03-05 20:12:59 -08:00
}
public class DiscordNotificationJob
2023-03-05 20:12:59 -08:00
{
private const string JobName = "DiscordNotifications";
2023-03-05 20:12:59 -08:00
private IArticlesRepository _article;
private IIconsRepository _icons;
private ILogger _logger;
2023-03-05 20:12:59 -08:00
private IDiscordQueueRepository _queue;
private ISourcesRepository _sources;
private ISubscriptionRepository _subs;
private IDiscordWebHooksRepository _webhook;
public DiscordNotificationJob()
2023-03-05 20:12:59 -08:00
{
_queue = new DiscordQueueTable("");
_article = new ArticlesTable("");
_webhook = new DiscordWebhooksTable("");
_sources = new SourcesTable("");
_subs = new SubscriptionsTable("");
_icons = new IconsTable("");
_logger = JobLogger.GetLogger("", JobName);
2023-03-05 20:12:59 -08:00
}
public void InitAndExecute(DiscordNotificationJobOptions options)
2023-03-05 20:12:59 -08:00
{
_queue = new DiscordQueueTable(options.ConnectionString ?? "");
_article = new ArticlesTable(options.ConnectionString ?? "");
_webhook = new DiscordWebhooksTable(options.ConnectionString ?? "");
_sources = new SourcesTable(options.ConnectionString ?? "");
_subs = new SubscriptionsTable(options.ConnectionString ?? "");
_icons = new IconsTable(options.ConnectionString ?? "");
_logger = JobLogger.GetLogger(options.OpenTelemetry ?? "", JobName);
if (!options.IsEnabled)
{
_logger.Warning($"{JobName} - Going to exit because feature flag is off.");
return;
}
_logger.Information($"{JobName} - Starting up the job.");
Execute();
2023-03-05 20:12:59 -08:00
}
private void Execute()
{
//collect all the new requests
var requests = _queue.List(100);
_logger.Debug($"{JobName} - Collected {requests.Count} items to send");
2023-03-05 20:12:59 -08: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-06-23 20:19:09 -07:00
_logger.Debug($"{JobName} - Processing {request.Id}");
// Get all details on the article in the queue
2023-06-23 20:19:09 -07:00
var articleDetails = _article.GetById(request.ArticleId);
// Get the details of the source
2023-06-23 20:09:57 -07:00
var sourceDetails = _sources.GetByID(articleDetails.SourceId);
if (sourceDetails.ID == Guid.Empty)
2023-03-05 20:12:59 -08: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);
return;
2023-03-05 20:12:59 -08:00
}
var sourceIcon = new IconModel();
try
{
sourceIcon = _icons.GetBySourceId(sourceDetails.ID);
}
catch
{
_logger.Warning("{JobName} - Source ID \'{SourceDetailsId}\' is missing an icon", JobName,
sourceDetails.ID);
}
// Find all the subscriptions for that source
var allSubscriptions = _subs.ListBySourceID(sourceDetails.ID);
foreach (var sub in allSubscriptions)
2023-06-23 20:19:09 -07:00
SendSubscriptionNotification(request.Id, articleDetails, sourceDetails, sourceIcon, sub);
2023-06-23 20:19:09 -07:00
_logger.Debug("{JobName} - Removing {RequestId} from the queue", JobName, request.Id);
_queue.Delete(request.Id);
}
2023-06-23 20:09:57 -07:00
public void SendSubscriptionNotification(Guid requestId, ArticlesEntity articleDetails, SourceModel sourceDetails,
IconModel sourceIcon, SubscriptionModel sub)
{
// 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
var discordDetails = _webhook.GetByID(sub.DiscordWebHookId);
if (discordDetails.Enabled == false) return;
var client = new DiscordWebhookClient(discordDetails.Url);
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);
_logger.Debug("Source: {SourceDetailsId}", sourceDetails.ID);
_logger.Debug("Subscription: {SubId}", sub.Id);
}
Thread.Sleep(3000);
2023-03-05 20:12:59 -08:00
}
2023-06-23 20:09:57 -07:00
public DiscordMessage GenerateDiscordMessage(SourceModel source, ArticlesEntity article, IconModel icon)
2023-03-05 20:12:59 -08:00
{
var embed = new DiscordMessageEmbed
{
Title = article.Title,
Color = DiscordMessageEmbedColors.Red,
Description = MessageValidation.ConvertHtmlCodes(article.Description),
2023-03-05 20:12:59 -08:00
Author = new DiscordMessageEmbedAuthor
{
Name = article.AuthorName,
IconUrl = icon.FileName
2023-03-05 20:12:59 -08:00
},
Footer = new DiscordMessageEmbedFooter
{
Text = "Brought to you by Newsbot"
},
Fields = new DiscordMessageEmbedField[]
{
new()
{
Name = "Link",
2023-06-23 20:09:57 -07:00
Value = article.Url,
Inline = false
}
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
if (article.Thumbnail != "")
2023-03-05 20:12:59 -08:00
embed.Image = new DiscordMessageEmbedImage
{
Url = article.Thumbnail
};
if (article.AuthorImage is not null && article.AuthorImage != "") embed.Author.IconUrl = article.AuthorImage;
2023-03-05 20:12:59 -08:00
return new DiscordMessage
{
Embeds = new[]
2023-03-05 20:12:59 -08:00
{
embed
}
};
}
}