diff --git a/Program.cs b/Program.cs index fcbf366..65cf47a 100755 --- a/Program.cs +++ b/Program.cs @@ -58,7 +58,7 @@ public class MastodonBot case { CallbackQuery: { } callbackQuery }: { if(callbackQuery.Data == "new_random"){ await HandleStartMessage.HandleStartMessageAsync(callbackQuery.Message, bot, db, logger,callbackQuery); break;} - else {await HandlePostAction.HandleCallbackQuery(callbackQuery, backupDb, bot, logger); break;} + else {await HandlePostAction.HandleCallbackQuery(callbackQuery, db, bot, logger); break;} } default: logger.LogInformation($"Received unhandled update {update.Type}"); break; @@ -74,7 +74,7 @@ public class MastodonBot } else if (message.Text == "/backup") { - await HandleDbBackup.HandleDbBackupAsync(bot, logger, config.DB_NAME, config.ADMIN_NUMID, backupDb); + await HandleDbBackup.HandleDbBackupAsync(bot, logger, config.DB_NAME, config.ADMIN_NUMID, backupDb, db); } // Send a message to prompt user to send /start and recieve their cat photo only if its from a telegram user and not a channel else if (message.Chat.Type == ChatType.Private) @@ -84,9 +84,9 @@ public class MastodonBot } // Set a timer to fetch and process posts every 15 minutes - _postFetchTimer = new Timer(async _ => await RunCheck.runAsync(backupDb, bot, config.TAG, logger, config.INSTANCE), null, TimeSpan.Zero, TimeSpan.FromMinutes(10)); + _postFetchTimer = new Timer(async _ => await RunCheck.runAsync(db, bot, config.TAG, logger, config.INSTANCE), null, TimeSpan.Zero, TimeSpan.FromMinutes(10)); // Another timer to automatically backup the DB every 1 hour - _backupTimer = new Timer(async _ => await HandleDbBackup.HandleDbBackupAsync(bot, logger, config.DB_NAME, config.ADMIN_NUMID, backupDb), null, TimeSpan.Zero, TimeSpan.FromHours(6)); + _backupTimer = new Timer(async _ => await HandleDbBackup.HandleDbBackupAsync(bot, logger, config.DB_NAME, config.ADMIN_NUMID, backupDb,db), null, TimeSpan.Zero, TimeSpan.FromHours(6)); // Keep the bot running await Task.Delay(-1); } diff --git a/Services/HandleDbBackup.cs b/Services/HandleDbBackup.cs index c3f1542..85cc7b7 100755 --- a/Services/HandleDbBackup.cs +++ b/Services/HandleDbBackup.cs @@ -1,5 +1,6 @@ using JsonFlatFileDataStore; using Microsoft.Extensions.Logging; +using MongoDB.Driver; using mstdnCats.Models; using Telegram.Bot; using Telegram.Bot.Types; @@ -9,10 +10,19 @@ namespace mstdnCats.Services; public class HandleDbBackup { - public static async Task HandleDbBackupAsync(TelegramBotClient _bot, ILogger? logger, string dbname, string adminId,IDocumentCollection _db) + public static async Task HandleDbBackupAsync(TelegramBotClient _bot, ILogger? logger, string dbname, string adminId,IDocumentCollection _bkDb,IMongoCollection _db) { logger?.LogInformation("Backup requested"); + // Retrieve all posts from DB + var posts = _db.AsQueryable().ToList(); + // Retrieve all existing posts in backup DB + var existingPosts = _bkDb.AsQueryable().ToList(); + // Insert new posts that are not in backup DB (First saves all the new ones in a list and then inserts them all at once) + var newPosts = posts.Where(x => !existingPosts.Any(y => y.mstdnPostId == x.mstdnPostId)).ToList(); + await _bkDb.InsertManyAsync(newPosts); + + await using Stream stream = System.IO.File.OpenRead("./data/" + dbname+"_BK.json"); var message = await _bot.SendDocument(adminId, document: InputFile.FromStream(stream, dbname+"_BK.json"), caption: "Backup of " + dbname + "\nCreated at " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss" + "\nCurrent post count: " + _db.AsQueryable().Count()), parseMode: ParseMode.Html); diff --git a/Services/HandlePostAction.cs b/Services/HandlePostAction.cs index b21eb63..da2963c 100755 --- a/Services/HandlePostAction.cs +++ b/Services/HandlePostAction.cs @@ -2,6 +2,7 @@ using CatsOfMastodonBot.Models; using JsonFlatFileDataStore; using Microsoft.AspNetCore.Mvc.Diagnostics; using Microsoft.Extensions.Logging; +using MongoDB.Driver; using mstdnCats.Models; using Telegram.Bot; using Telegram.Bot.Types; @@ -12,10 +13,10 @@ namespace mstdnCats.Services { public class HandlePostAction { - public static async Task HandleCallbackQuery(CallbackQuery callbackQuery, IDocumentCollection _db, TelegramBotClient _bot, ILogger? logger) + public static async Task HandleCallbackQuery(CallbackQuery callbackQuery, IMongoCollection _db, TelegramBotClient _bot, ILogger? logger) { var config = ConfigData.fetchData(); - + // Extract media ID from callback query data string[] parts = callbackQuery.Data.Split('-'); if (parts.Length != 2) @@ -27,16 +28,14 @@ namespace mstdnCats.Services string action = parts[0]; string mediaId = parts[1]; - var post = _db.AsQueryable().FirstOrDefault(p => p.MediaAttachments.Any(m => m.MediaId == mediaId)); - // Extract Only media attachments into a list of media attachments - + var filter = Builders.Filter.Eq("MediaAttachments.MediaId", mediaId); + var post = await _db.Find(filter).FirstOrDefaultAsync(); if (post == null) { logger?.LogInformation("No matching post found."); return; } - var allMediaAttachments = _db.AsQueryable().SelectMany(p => p.MediaAttachments).ToList(); // Approve the media attachment if (action == "approve") @@ -45,21 +44,22 @@ namespace mstdnCats.Services if (mediaAttachment != null) { // Check if the media attachment is already approved - if (mediaAttachment.Approved){ - await _bot.AnswerCallbackQuery(callbackQuery.Id, "Media attachment is already approved.",true); + if (mediaAttachment.Approved) + { + await _bot.AnswerCallbackQuery(callbackQuery.Id, "Media attachment is already approved.", true); return; } - - mediaAttachment.Approved = true; - bool updated = await _db.UpdateOneAsync(p => p.mstdnPostId == post.mstdnPostId, post); - + // Update the media attachment + var update = Builders.Update.Set("MediaAttachments.$.Approved", true); + var result = await _db.UpdateOneAsync(filter, update); - if (updated) + if (result.ModifiedCount > 0) { try { // Send the media attachment to the channel + var allMediaAttachments = post.MediaAttachments.ToList(); await _bot.SendPhoto(config.CHANNEL_NUMID, allMediaAttachments.First(m => m.MediaId == mediaId).Url, caption: $"Post from " + $"" + @@ -81,8 +81,6 @@ namespace mstdnCats.Services { logger?.LogError($"Failed to update the media attachment {mediaId}. Record might not exist or was not found."); } - - } else { @@ -103,19 +101,26 @@ namespace mstdnCats.Services } else { - post.MediaAttachments.RemoveAll(m => m.MediaId == mediaId); - await _db.UpdateOneAsync(p => p.mstdnPostId == post.mstdnPostId, post); - await _bot.AnswerCallbackQuery(callbackQuery.Id, "Media attachment rejected."); - await _bot.DeleteMessage(callbackQuery.Message.Chat.Id, callbackQuery.Message.Id); + var update = Builders.Update.PullFilter("MediaAttachments", Builders.Filter.Eq("MediaId", mediaId)); + var result = await _db.UpdateOneAsync(filter, update); - logger?.LogTrace($"Media attachment {mediaId} removed from post {post.mstdnPostId}."); + if (result.ModifiedCount > 0) + { + await _bot.AnswerCallbackQuery(callbackQuery.Id, "Media attachment rejected."); + await _bot.DeleteMessage(callbackQuery.Message.Chat.Id, callbackQuery.Message.Id); + + logger?.LogTrace($"Media attachment {mediaId} removed from post {post.mstdnPostId}."); + } + else + { + logger?.LogError($"Failed to remove media attachment {mediaId} from post {post.mstdnPostId}."); + } } } else { logger?.LogError("Invalid action specified."); } - } } } \ No newline at end of file diff --git a/Services/HandleStartMessage.cs b/Services/HandleStartMessage.cs index 5aa9643..6999889 100755 --- a/Services/HandleStartMessage.cs +++ b/Services/HandleStartMessage.cs @@ -1,6 +1,7 @@ using JsonFlatFileDataStore; using Microsoft.Extensions.Logging; using MongoDB.Driver; +using MongoDB.Driver.Linq; using mstdnCats.Models; using Telegram.Bot; using Telegram.Bot.Types; @@ -16,9 +17,9 @@ namespace CatsOfMastodonBot.Services logger?.LogInformation("Start message received, trigger source: " + (callbackQuery != null ? "Callback" : "Start command")); // choose all media attachments that are approved - var mediaAttachmentsToSelect = _db.AsQueryable() + var mediaAttachmentsToSelect =await _db.AsQueryable() .Where(post => post.MediaAttachments.Any(media => media.Approved)) - .ToList(); + .ToListAsync(); // select random approved media attachment var selectedMediaAttachment = mediaAttachmentsToSelect[new Random().Next(mediaAttachmentsToSelect.Count)]; // send media attachment diff --git a/Services/ProcessPosts.cs b/Services/ProcessPosts.cs index fad5290..0e2ce15 100755 --- a/Services/ProcessPosts.cs +++ b/Services/ProcessPosts.cs @@ -1,6 +1,7 @@ using CatsOfMastodonBot.Models; using JsonFlatFileDataStore; using Microsoft.Extensions.Logging; +using MongoDB.Driver; using mstdnCats.Models; using Telegram.Bot; using Telegram.Bot.Types.Enums; @@ -10,7 +11,7 @@ namespace mstdnCats.Services { public class ProcessPosts { - public static async Task> checkAndInsertPostsAsync(IDocumentCollection _db, TelegramBotClient _bot, List fetchedPosts, ILogger? logger) + public static async Task> checkAndInsertPostsAsync(IMongoCollection _db, TelegramBotClient _bot, List fetchedPosts, ILogger? logger) { var config = ConfigData.fetchData(); diff --git a/Services/RunCheck.cs b/Services/RunCheck.cs index 52132a1..7d34b86 100755 --- a/Services/RunCheck.cs +++ b/Services/RunCheck.cs @@ -1,5 +1,6 @@ using JsonFlatFileDataStore; using Microsoft.Extensions.Logging; +using MongoDB.Driver; using mstdnCats.Models; using Telegram.Bot; @@ -7,7 +8,7 @@ namespace mstdnCats.Services { public class RunCheck { - public static async Task runAsync(IDocumentCollection _db, TelegramBotClient _bot, string _tag, ILogger? logger, string _instance) + public static async Task runAsync(IMongoCollection _db, TelegramBotClient _bot, string _tag, ILogger? logger, string _instance) { // Run check try