diff --git a/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemory.cs b/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemory.cs index 73e1f9c0..88460268 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemory.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemory.cs @@ -11,8 +11,8 @@ public class TranslationMemory [JsonPropertyName("hash_text")] public string HashText { get; set; } - [JsonPropertyName("memories")] - public List Memories { get; set; } = new List(); + [JsonPropertyName("translations")] + public List Translations { get; set; } = new List(); } public class TranslationMemoryItem diff --git a/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemoryQuery.cs b/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemoryQuery.cs index 66f1df8e..be5191f8 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemoryQuery.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Translation/Models/TranslationMemoryQuery.cs @@ -10,6 +10,11 @@ public class TranslationMemoryQuery { } + + public override string ToString() + { + return $"[Origin: {OriginalText}] translates to [{Language}]"; + } } public class TranslationMemoryInput : TranslationMemoryQuery @@ -23,7 +28,7 @@ public class TranslationMemoryInput : TranslationMemoryQuery public override string ToString() { - return $"Origin: {OriginalText} -> Translation: {TranslatedText} (Language: {Language})"; + return $"[Origin: {OriginalText}] -> [Translation: {TranslatedText}] (Language: {Language})"; } } @@ -38,6 +43,6 @@ public class TranslationMemoryOutput: TranslationMemoryQuery public override string ToString() { - return $"Origin: {OriginalText} -> Translation: {TranslatedText} (Language: {Language})"; + return $"[Origin: {OriginalText}] -> [Translation: {TranslatedText}] (Language: {Language})"; } } \ No newline at end of file diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Translation.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Translation.cs index 8d8a14e7..e52e09c2 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Translation.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Translation.cs @@ -37,7 +37,7 @@ public partial class FileRepository var foundMemory = memories.FirstOrDefault(x => x.HashText.Equals(query.HashText)); if (foundMemory == null) continue; - var foundItem = foundMemory.Memories?.FirstOrDefault(x => x.Language.Equals(query.Language)); + var foundItem = foundMemory.Translations?.FirstOrDefault(x => x.Language.Equals(query.Language)); if (foundItem == null) continue; list.Add(new TranslationMemoryOutput @@ -97,7 +97,7 @@ public partial class FileRepository Id = Guid.NewGuid().ToString(), OriginalText = input.OriginalText, HashText = input.HashText, - Memories = new List { newItem } + Translations = new List { newItem } }; if (memories == null) @@ -111,16 +111,16 @@ public partial class FileRepository } else { - var foundItem = foundMemory.Memories?.FirstOrDefault(x => x.Language.Equals(input.Language)); + var foundItem = foundMemory.Translations?.FirstOrDefault(x => x.Language.Equals(input.Language)); if (foundItem != null) continue; - if (foundMemory.Memories == null) + if (foundMemory.Translations == null) { - foundMemory.Memories = new List { newItem }; + foundMemory.Translations = new List { newItem }; } else { - foundMemory.Memories.Add(newItem); + foundMemory.Translations.Add(newItem); } } } diff --git a/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs b/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs index d72bef2a..399f9c0d 100644 --- a/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs +++ b/src/Infrastructure/BotSharp.Core/Translation/TranslationService.cs @@ -122,7 +122,7 @@ public class TranslationService : ITranslationService Language = language }); } -; + _db.SaveTranslationMemories(memoryInputs); } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/TranslationMemoryDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/TranslationMemoryDocument.cs new file mode 100644 index 00000000..54c11b3e --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/TranslationMemoryDocument.cs @@ -0,0 +1,8 @@ +namespace BotSharp.Plugin.MongoStorage.Collections; + +public class TranslationMemoryDocument : MongoBase +{ + public string OriginalText { get; set; } + public string HashText { get; set; } + public List Translations { get; set; } = new List(); +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Models/TranslationMemoryMongoElement.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/TranslationMemoryMongoElement.cs new file mode 100644 index 00000000..0d090b78 --- /dev/null +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Models/TranslationMemoryMongoElement.cs @@ -0,0 +1,25 @@ +namespace BotSharp.Plugin.MongoStorage.Models; + +public class TranslationMemoryMongoElement +{ + public string TranslatedText { get; set; } + public string Language { get; set; } + + public static TranslationMemoryMongoElement ToMongoElement(TranslationMemoryItem item) + { + return new TranslationMemoryMongoElement + { + TranslatedText = item.TranslatedText, + Language = item.Language + }; + } + + public static TranslationMemoryItem ToDomainElement(TranslationMemoryMongoElement element) + { + return new TranslationMemoryItem + { + TranslatedText = element.TranslatedText, + Language = element.Language + }; + } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs index ca691e05..dfbbfbaa 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/MongoDbContext.cs @@ -1,5 +1,3 @@ -using BotSharp.Plugin.MongoStorage.Collections; - namespace BotSharp.Plugin.MongoStorage; public class MongoDbContext @@ -117,4 +115,7 @@ public class MongoDbContext public IMongoCollection Plugins => Database.GetCollection($"{_collectionPrefix}_Plugins"); + + public IMongoCollection TranslationMemories + => Database.GetCollection($"{_collectionPrefix}_TranslationMemories"); } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs index 97ceee9f..167f4b79 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Agent.cs @@ -2,8 +2,6 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Functions.Models; using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Routing.Models; -using BotSharp.Plugin.MongoStorage.Collections; -using BotSharp.Plugin.MongoStorage.Models; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs index a3df61da..a00858c4 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.AgentTask.cs @@ -1,6 +1,5 @@ using BotSharp.Abstraction.Repositories.Filters; using BotSharp.Abstraction.Tasks.Models; -using BotSharp.Plugin.MongoStorage.Collections; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index aefd0db5..bed3a255 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -1,9 +1,5 @@ using BotSharp.Abstraction.Conversations.Models; -using BotSharp.Abstraction.Files; using BotSharp.Abstraction.Repositories.Filters; -using BotSharp.Abstraction.Repositories.Models; -using BotSharp.Plugin.MongoStorage.Collections; -using BotSharp.Plugin.MongoStorage.Models; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Log.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Log.cs index 94adacc3..31631230 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Log.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Log.cs @@ -1,6 +1,4 @@ using BotSharp.Abstraction.Loggers.Models; -using BotSharp.Plugin.MongoStorage.Collections; -using BotSharp.Plugin.MongoStorage.Models; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Plugin.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Plugin.cs index c6bc60b3..b26da408 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Plugin.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Plugin.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Plugins.Models; -using BotSharp.Plugin.MongoStorage.Collections; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs index 470b1fb1..44320bd9 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Transaction.cs @@ -1,8 +1,5 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Users.Models; -using BotSharp.Plugin.MongoStorage.Collections; -using BotSharp.Plugin.MongoStorage.Models; - namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Translation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Translation.cs index 9f2f98a1..5f0e987e 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Translation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Translation.cs @@ -1,14 +1,125 @@ +using Microsoft.Extensions.Logging; +using System.Threading; + namespace BotSharp.Plugin.MongoStorage.Repository; public partial class MongoRepository { public IEnumerable GetTranslationMemories(IEnumerable queries) { - throw new NotImplementedException(); + var list = new List(); + if (queries.IsNullOrEmpty()) + { + return list; + } + + var hashTexts = queries.Where(x => !string.IsNullOrEmpty(x.HashText)).Select(x => x.HashText).ToList(); + var filter = Builders.Filter.In(x => x.HashText, hashTexts); + var memories = _dc.TranslationMemories.Find(filter).ToList(); + if (memories.IsNullOrEmpty()) return list; + + foreach (var query in queries) + { + if (string.IsNullOrWhiteSpace(query.HashText) || string.IsNullOrWhiteSpace(query.Language)) + { + continue; + } + + var foundMemory = memories.FirstOrDefault(x => x.HashText.Equals(query.HashText)); + if (foundMemory == null) continue; + + var foundItem = foundMemory.Translations?.FirstOrDefault(x => x.Language.Equals(query.Language)); + if (foundItem == null) continue; + + list.Add(new TranslationMemoryOutput + { + OriginalText = query.OriginalText, + TranslatedText = foundItem.TranslatedText, + HashText = foundMemory.HashText, + Language = foundItem.Language, + }); + } + + return list; } public bool SaveTranslationMemories(IEnumerable inputs) { - throw new NotImplementedException(); + if (inputs.IsNullOrEmpty()) return false; + + var hashTexts = inputs.Where(x => !string.IsNullOrEmpty(x.HashText)).Select(x => x.HashText).ToList(); + var filter = Builders.Filter.In(x => x.HashText, hashTexts); + var memories = _dc.TranslationMemories.Find(filter)?.ToList() ?? new List(); + + var newMemories = new List(); + var updateMemories = new List(); + + try + { + foreach (var input in inputs) + { + if (string.IsNullOrWhiteSpace(input.OriginalText) || + string.IsNullOrWhiteSpace(input.TranslatedText) || + string.IsNullOrWhiteSpace(input.HashText) || + string.IsNullOrWhiteSpace(input.Language)) + { + continue; + } + + var newItem = new TranslationMemoryMongoElement + { + TranslatedText = input.TranslatedText, + Language = input.Language + }; + + var foundMemory = memories?.FirstOrDefault(x => x.HashText.Equals(input.HashText)); + if (foundMemory == null) + { + newMemories.Add(new TranslationMemoryDocument + { + Id = Guid.NewGuid().ToString(), + OriginalText = input.OriginalText, + HashText = input.HashText, + Translations = new List { newItem } + }); + } + else + { + var foundItem = foundMemory.Translations?.FirstOrDefault(x => x.Language.Equals(input.Language)); + if (foundItem != null) continue; + + if (foundMemory.Translations == null) + { + foundMemory.Translations = new List { newItem }; + } + else + { + foundMemory.Translations.Add(newItem); + } + updateMemories.Add(foundMemory); + } + } + + if (!newMemories.IsNullOrEmpty()) + { + _dc.TranslationMemories.InsertMany(newMemories); + } + + if (!updateMemories.IsNullOrEmpty()) + { + foreach (var mem in updateMemories) + { + var updateFilter = Builders.Filter.Eq(x => x.Id, mem.Id); + _dc.TranslationMemories.ReplaceOne(updateFilter, mem); + Thread.Sleep(50); + } + } + return true; + } + catch (Exception ex) + { + _logger.LogWarning($"Error when saving translation memories: {ex.Message}"); + return false; + } } } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs index 9a3ce3f4..11f48287 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.User.cs @@ -1,5 +1,4 @@ using BotSharp.Abstraction.Users.Models; -using BotSharp.Plugin.MongoStorage.Collections; namespace BotSharp.Plugin.MongoStorage.Repository; diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs index 02d21c43..133edba1 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.cs @@ -1,6 +1,7 @@ using BotSharp.Abstraction.Agents.Models; using BotSharp.Abstraction.Conversations.Models; using BotSharp.Abstraction.Users.Models; +using Microsoft.Extensions.Logging; namespace BotSharp.Plugin.MongoStorage.Repository; @@ -8,12 +9,17 @@ public partial class MongoRepository : IBotSharpRepository { private readonly MongoDbContext _dc; private readonly IServiceProvider _services; + private readonly ILogger _logger; private UpdateOptions _options; - public MongoRepository(MongoDbContext dc, IServiceProvider services) + public MongoRepository( + MongoDbContext dc, + IServiceProvider services, + ILogger logger) { _dc = dc; _services = services; + _logger = logger; _options = new UpdateOptions { IsUpsert = true, diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Using.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Using.cs index f40df94a..7c74b648 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Using.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Using.cs @@ -12,4 +12,6 @@ global using Microsoft.Extensions.Configuration; global using Microsoft.Extensions.DependencyInjection; global using MongoDB.Bson; global using MongoDB.Driver; -global using MongoDB.Bson.Serialization.Attributes; \ No newline at end of file +global using MongoDB.Bson.Serialization.Attributes; +global using BotSharp.Plugin.MongoStorage.Collections; +global using BotSharp.Plugin.MongoStorage.Models; \ No newline at end of file