using System.Linq.Dynamic.Core; using BotSharp.Abstraction.Files.Enums; using BotSharp.Abstraction.Files.Models; using BotSharp.Abstraction.Files.Utilities; using BotSharp.Plugin.ExcelHandler.Helpers.Sqlite; using BotSharp.Plugin.ExcelHandler.Models; using BotSharp.Plugin.ExcelHandler.Services; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; namespace BotSharp.Plugin.ExcelHandler.Functions; public class HandleExcelRequestFn : IFunctionCallback { public string Name => "handle_excel_request"; public string Indication => "Handling excel request"; private readonly IServiceProvider _serviceProvider; private readonly IFileStorageService _fileStorage; private readonly ILogger _logger; private readonly BotSharpOptions _options; private readonly IMySqlService _mySqlService; private HashSet _excelMimeTypes; private double _excelRowSize = 0; private double _excelColumnSize = 0; private string _tableName = "tempTable"; private string _currentFileName = string.Empty; private List _headerColumns = new List(); private List _columnTypes = new List(); public HandleExcelRequestFn( IServiceProvider serviceProvider, IFileStorageService fileStorage, ILogger logger, BotSharpOptions options, IMySqlService mySqlService ) { _serviceProvider = serviceProvider; _fileStorage = fileStorage; _logger = logger; _options = options; _mySqlService = mySqlService; } public async Task Execute(RoleDialogModel message) { var args = JsonSerializer.Deserialize(message.FunctionArgs, _options.JsonSerializerOptions); var conv = _serviceProvider.GetRequiredService(); if (_excelMimeTypes.IsNullOrEmpty()) { _excelMimeTypes = FileUtility.GetMimeFileTypes(new List { "excel", "spreadsheet" }).ToHashSet(); } var dialogs = conv.GetDialogHistory(); var isExcelExist = AssembleFiles(conv.ConversationId, dialogs); if (!isExcelExist) { message.Content = "No excel files found in the conversation"; return true; } if (!DeleteTable()) { message.Content = "Failed to clear existing tables. Please manually delete all existing tables"; } else { var resultList = GetResponeFromDialogs(dialogs); var states = _serviceProvider.GetRequiredService(); message.Content = GenerateSqlExecutionSummary(resultList); states.SetState("excel_import_result",message.Content); } return true; } #region Private Methods private bool AssembleFiles(string convId, List dialogs) { if (dialogs.IsNullOrEmpty()) return false; var messageId = dialogs.Select(x => x.MessageId).Distinct().ToList(); var contentType = FileUtility.GetContentFileTypes(mimeTypes: _excelMimeTypes); var excelMessageFiles = _fileStorage.GetMessageFiles(convId, messageId, FileSourceType.User, contentType); if (excelMessageFiles.IsNullOrEmpty()) return false; dialogs.ForEach(dialog => { var found = excelMessageFiles.Where(y => y.MessageId == dialog.MessageId).ToList(); if (found.IsNullOrEmpty()) return; dialog.Files = found.Select(x => new BotSharpFile { ContentType = x.ContentType, FileUrl = x.FileUrl, FileStorageUrl = x.FileStorageUrl }).ToList(); }); return true; } private List GetResponeFromDialogs(List dialogs) { var dialog = dialogs.Last(x => !x.Files.IsNullOrEmpty()); var sqlCommandList = new List(); foreach (var file in dialog.Files) { if (file == null || string.IsNullOrWhiteSpace(file.FileStorageUrl)) continue; string extension = Path.GetExtension(file.FileStorageUrl); if (!_excelMimeTypes.Contains(extension)) continue; _currentFileName = Path.GetFileName(file.FileStorageUrl); var bytes = _fileStorage.GetFileBytes(file.FileStorageUrl); var workbook = ConvertToWorkBook(bytes); //var dbService = CreateDbService(DbServiceType.MySql); var currentCommandList = _mySqlService.WriteExcelDataToDB(workbook); sqlCommandList.AddRange(currentCommandList); } return sqlCommandList; } private bool DeleteTable() { try { //_mySqlService.DeleteTableSqlQuery(); return true; } catch (Exception ex) { _logger.LogError(ex, "Failed to delete table"); return false; } } private string GenerateSqlExecutionSummary(List messageList) { var stringBuilder = new StringBuilder(); if (messageList.Any(x => x.isSuccessful)) { stringBuilder.Append("---Success---"); stringBuilder.Append("\r\n"); foreach (var message in messageList.Where(x => x.isSuccessful)) { stringBuilder.Append(message.Message); stringBuilder.Append("\r\n\r\n"); } } if (messageList.Any(x => !x.isSuccessful)) { stringBuilder.Append("---Failed---"); stringBuilder.Append("\r\n"); foreach (var message in messageList.Where(x => !x.isSuccessful)) { stringBuilder.Append(message.Message); stringBuilder.Append("\r\n"); } } return stringBuilder.ToString(); } private IWorkbook ConvertToWorkBook(byte[] bytes) { IWorkbook workbook; using (var fileStream = new MemoryStream(bytes)) { workbook = new XSSFWorkbook(fileStream); } return workbook; } #endregion }