diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs index ffb4986a..6a04e796 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/IConversationService.cs @@ -12,6 +12,7 @@ public interface IConversationService Task GetConversation(string id); Task> GetConversations(ConversationFilter filter); Task UpdateConversationTitle(string id, string title); + Task UpdateConversationTitleAlias(string id, string titleAlias); Task UpdateConversationTags(string conversationId, List tags); Task UpdateConversationMessage(string conversationId, UpdateMessageRequest request); Task> GetLastConversations(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs index 5ded2c7c..a485a9c4 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Conversations/Models/Conversation.cs @@ -13,6 +13,7 @@ public class Conversation /// public string? TaskId { get; set; } public string Title { get; set; } = string.Empty; + public string TitleAlias { get; set; } = string.Empty; [JsonIgnore] public List Dialogs { get; set; } = new(); diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs index ab1a0a9f..23543049 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/Filters/ConversationFilter.cs @@ -8,6 +8,7 @@ public class ConversationFilter /// public string? Id { get; set; } public string? Title { get; set; } + public string? TitleAlias { get; set; } public string? AgentId { get; set; } public string? Status { get; set; } public string? Channel { get; set; } diff --git a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs index 61982cc4..fa6f074c 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Repositories/IBotSharpRepository.cs @@ -86,6 +86,7 @@ public interface IBotSharpRepository : IHaveServiceProvider Conversation GetConversation(string conversationId); PagedItems GetConversations(ConversationFilter filter); void UpdateConversationTitle(string conversationId, string title); + void UpdateConversationTitleAlias(string conversationId, string titleAlias); bool UpdateConversationTags(string conversationId, List tags); bool UpdateConversationMessage(string conversationId, UpdateMessageRequest request); void UpdateConversationBreakpoint(string conversationId, ConversationBreakpoint breakpoint); diff --git a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs index 55d80c18..67b0b1b0 100644 --- a/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs +++ b/src/Infrastructure/BotSharp.Core/Conversations/Services/ConversationService.cs @@ -51,6 +51,14 @@ public partial class ConversationService : IConversationService return conversation; } + public async Task UpdateConversationTitleAlias(string id, string titleAlias) + { + var db = _services.GetRequiredService(); + db.UpdateConversationTitleAlias(id, titleAlias); + var conversation = db.GetConversation(id); + return conversation; + } + public async Task UpdateConversationTags(string conversationId, List tags) { var db = _services.GetRequiredService(); diff --git a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs index d2c519eb..165dc34b 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/BotSharpDbContext.cs @@ -105,6 +105,8 @@ public class BotSharpDbContext : Database, IBotSharpRepository public void UpdateConversationTitle(string conversationId, string title) => throw new NotImplementedException(); + public void UpdateConversationTitleAlias(string conversationId, string titleAlias) + => throw new NotImplementedException(); public bool UpdateConversationTags(string conversationId, List tags) => throw new NotImplementedException(); diff --git a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs index fd13936c..34345271 100644 --- a/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs +++ b/src/Infrastructure/BotSharp.Core/Repository/FileRepository/FileRepository.Conversation.cs @@ -134,6 +134,22 @@ namespace BotSharp.Core.Repository } } } + public void UpdateConversationTitleAlias(string conversationId, string titleAlias) + { + var convDir = FindConversationDirectory(conversationId); + if (!string.IsNullOrEmpty(convDir)) + { + var convFile = Path.Combine(convDir, CONVERSATION_FILE); + var content = File.ReadAllText(convFile); + var record = JsonSerializer.Deserialize(content, _options); + if (record != null) + { + record.TitleAlias = titleAlias; + record.UpdatedTime = DateTime.UtcNow; + File.WriteAllText(convFile, JsonSerializer.Serialize(record, _options)); + } + } + } public bool UpdateConversationTags(string conversationId, List tags) { @@ -356,6 +372,10 @@ namespace BotSharp.Core.Repository { matched = matched && record.Title.Contains(filter.Title); } + if (filter?.TitleAlias != null) + { + matched = matched && record.TitleAlias.Contains(filter.TitleAlias); + } if (filter?.AgentId != null) { matched = matched && record.AgentId == filter.AgentId; diff --git a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs index 389bf96f..266c5ac5 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/Controllers/ConversationController.cs @@ -223,6 +223,30 @@ public class ConversationController : ControllerBase return response != null; } + [HttpPut("/conversation/{conversationId}/update-title-alias")] + public async Task UpdateConversationTitleAlias([FromRoute] string conversationId, [FromBody] UpdateConversationTitleAliasModel newTile) + { + var userService = _services.GetRequiredService(); + var conversationService = _services.GetRequiredService(); + + var user = await userService.GetUser(_user.Id); + var filter = new ConversationFilter + { + Id = conversationId, + UserId = user.Role != UserRole.Admin ? user.Id : null + }; + var conversations = await conversationService.GetConversations(filter); + + if (conversations.Items.IsNullOrEmpty()) + { + return false; + } + + var response = await conversationService.UpdateConversationTitleAlias(conversationId, newTile.NewTitleAlias); + return response != null; + } + + [HttpPut("/conversation/{conversationId}/update-tags")] public async Task UpdateConversationTags([FromRoute] string conversationId, [FromBody] UpdateConversationRequest request) { diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs index 90b4ff67..a660a525 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/ConversationViewModel.cs @@ -15,6 +15,9 @@ public class ConversationViewModel [JsonPropertyName("title")] public string Title { get; set; } = string.Empty; + [JsonPropertyName("title_alias")] + public string TitleAlias { get; set; } = string.Empty; + public UserViewModel User { get; set; } = new UserViewModel(); public string Event { get; set; } @@ -48,6 +51,7 @@ public class ConversationViewModel }, AgentId = sess.AgentId, Title = sess.Title, + TitleAlias = sess.TitleAlias, Channel = sess.Channel, Status = sess.Status, TaskId = sess.TaskId, diff --git a/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/UpdateConversationTitleAliasModel.cs b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/UpdateConversationTitleAliasModel.cs new file mode 100644 index 00000000..5d9ac2fd --- /dev/null +++ b/src/Infrastructure/BotSharp.OpenAPI/ViewModels/Conversations/UpdateConversationTitleAliasModel.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace BotSharp.OpenAPI.ViewModels.Conversations; + +public class UpdateConversationTitleAliasModel +{ + [Required] + public string NewTitleAlias { get; set; } +} diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDocument.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDocument.cs index 28b0391a..52c26b52 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDocument.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Collections/ConversationDocument.cs @@ -6,6 +6,7 @@ public class ConversationDocument : MongoBase public string UserId { get; set; } public string? TaskId { get; set; } public string Title { get; set; } + public string TitleAlias { get; set; } public string Channel { get; set; } public string ChannelId { get; set; } public string Status { get; set; } diff --git a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs index cdd78ae2..468f467a 100644 --- a/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs +++ b/src/Plugins/BotSharp.Plugin.MongoStorage/Repository/MongoRepository.Conversation.cs @@ -114,6 +114,17 @@ public partial class MongoRepository _dc.Conversations.UpdateOne(filterConv, updateConv); } + public void UpdateConversationTitleAlias(string conversationId, string titleAlias) + { + if (string.IsNullOrEmpty(conversationId)) return; + + var filterConv = Builders.Filter.Eq(x => x.Id, conversationId); + var updateConv = Builders.Update + .Set(x => x.UpdatedTime, DateTime.UtcNow) + .Set(x => x.TitleAlias, titleAlias); + + _dc.Conversations.UpdateOne(filterConv, updateConv); + } public bool UpdateConversationTags(string conversationId, List tags) { @@ -301,6 +312,10 @@ public partial class MongoRepository { convFilters.Add(convBuilder.Regex(x => x.Title, new BsonRegularExpression(filter.Title, "i"))); } + if (!string.IsNullOrEmpty(filter?.TitleAlias)) + { + convFilters.Add(convBuilder.Regex(x => x.Title, new BsonRegularExpression(filter.TitleAlias, "i"))); + } if (!string.IsNullOrEmpty(filter?.AgentId)) { convFilters.Add(convBuilder.Eq(x => x.AgentId, filter.AgentId));