diff --git a/.vscode/launch.json b/.vscode/launch.json index d70f6b2..6ef3a5a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,8 +10,8 @@ "request": "launch", "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. - "program": "../tmp/net7.0/win-x64/bot.dll", - "args": ["--em-desenvolvimento", "--sap-instancia=4"], + "program": "${workspaceFolder}/bin/Debug/net7.0/win-x64/bot.dll", + "args": ["--sap-instancia=4" ,"--use-sqlite"], "cwd": "${workspaceFolder}", // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console "console": "internalConsole", diff --git a/Handles/HandleAsynchronous.cs b/Handles/HandleAsynchronous.cs index 30f1e1d..4f6dbf5 100644 --- a/Handles/HandleAsynchronous.cs +++ b/Handles/HandleAsynchronous.cs @@ -79,7 +79,7 @@ public static async Task Chief ( Int32 minInstance, Int32 maxInstance, - Expression> filtro + Expression>? filtro = null ) { var instances = maxInstance - minInstance; @@ -284,28 +284,20 @@ await bot.SendDocumentAsyncWraper( await bot.ErrorReport(erro, solicitacao); break; } - var fluxo_atual = 0; - var resposta_txt = ExecutarSap( - "instalacao", - solicitacao.information, - solicitacao.instance - ); - if(!Int64.TryParse(resposta_txt, out Int64 instalation)) + // Testar se foi enviada o número de instalação + if (solicitacao.information > 999999999 || solicitacao.information < 99999999) { - solicitacao.status = 500; + solicitacao.status = 400; var erro = new Exception( - "Não foi recebido o número da instalação!"); + "Só será aceita solicitação de fatura pela instalação!"); await bot.ErrorReport(erro, solicitacao); break; } - var agora = DateTime.Now; - logger.LogDebug("Solicitando as faturas..."); - resposta_txt = ExecutarSap( + var resposta_txt = ExecutarSap( solicitacao.application, - instalation, + solicitacao.information, solicitacao.instance ); - logger.LogDebug("Quantidade experada: {quantidade}", resposta_txt); if(!Int32.TryParse(resposta_txt, out Int32 quantidade_experada)) { solicitacao.status = 500; @@ -314,62 +306,13 @@ await bot.SendDocumentAsyncWraper( await bot.ErrorReport(erro, solicitacao); break; } - var faturas = new List(); - var tasks = new List(); - while (true) - { - await Task.Delay(cfg.TASK_DELAY_LONG); - logger.LogDebug("Realizando a checagem"); - faturas = database.RecuperarFatura( - f => f.instalation == instalation && - f.timestamp >= agora - ); - foreach (var fatura in faturas) - logger.LogDebug(fatura.filename); - if(faturas.Count == quantidade_experada) break; - if(agora.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) break; - } - logger.LogDebug("Quantidade de faturas: ", faturas.Count); - if(!faturas.Any()) - { - solicitacao.status = 503; - var erro = new Exception( - "Não foi gerada nenhuma fatura pelo sistema SAP!"); - await bot.ErrorReport(erro, solicitacao); - logger.LogError("Não foi gerada nenhuma fatura pelo sistema SAP!"); - break; - } - if(faturas.Count != quantidade_experada) - { - solicitacao.status = 503; - var erro = new Exception( - "A quantidade de faturas não condiz com a quantidade esperada!"); - await bot.ErrorReport(erro, solicitacao); - logger.LogError("A quantidade de faturas não condiz com a quantidade esperada!"); - break; - } - var fluxos = new Stream[quantidade_experada]; - foreach (var fatura in faturas) - { - if(fatura.status == pdfsModel.Status.sent) continue; - var caminho = System.IO.Path.Combine(cfg.TEMP_FOLDER, fatura.filename); - fluxos[fluxo_atual] = System.IO.File.OpenRead(caminho); - tasks.Add(bot.SendDocumentAsyncWraper( - solicitacao.identifier, - fluxos[fluxo_atual], - fatura.filename - )); - fatura.status = pdfsModel.Status.sent; - database.AlterarFatura(fatura); - logger.LogInformation("Enviada fatura ({fluxo_atual}/{quantidade_experada}): {filename}", - ++fluxo_atual, quantidade_experada, fatura.filename + solicitacao.instance = quantidade_experada; + solicitacao.response_at = DateTime.Now; + solicitacao.status = 300; + database.AlterarSolicitacao(solicitacao); + await bot.sendTextMesssageWraper(solicitacao.identifier, + "Sua fatura foi solicitada, favor aguardar a geração!" ); - } - await Task.WhenAll(tasks); - foreach(var fluxo in fluxos) fluxo.Close(); - PdfHandle.Remove(faturas); - bot.SucessReport(solicitacao); - logger.LogInformation("Enviadas faturas para a instalação {instalation}", instalation); break; } case TypeRequest.ofsInfo: diff --git a/Handles/HandleCommand.cs b/Handles/HandleCommand.cs index 52f2db1..d90e967 100644 --- a/Handles/HandleCommand.cs +++ b/Handles/HandleCommand.cs @@ -45,14 +45,8 @@ public async static Task HandleCommand(logsModel request, UsersModel user) await bot.sendTextMesssageWraper(user.identifier, "*CONTROLADOR* para alterar para um usuário que pode receber avisos sobre outros usuário"); await bot.sendTextMesssageWraper(user.identifier, "*COMUNICADOR* para alterar para um usuário capaz de enviar transmissões pelo sistema"); break; - default: - { - var erro = new Exception("Comando solicitado não foi programado! Verifique e tente um válido!"); - request.status = 400; - await bot.ErrorReport(erro, request); - return; - } case "/info": + { var info = new System.Text.StringBuilder(); info.Append($"*Identificador:* {user.identifier}\n"); info.Append($"*Telefone:* {user.phone_number}\n"); @@ -63,13 +57,13 @@ public async static Task HandleCommand(logsModel request, UsersModel user) } info.Append($"*Versão:* {Updater.CurrentVersion().ToString("yyyyMMdd")}"); await bot.sendTextMesssageWraper(user.identifier, info.ToString()); + } break; case "/update": if(user.privilege != UsersModel.userLevel.proprietario) { - var erro = new Exception("Somente o proprietario podem usar esse comando!"); - await bot.ErrorReport(erro, request); - return; + request.status = 403; + throw new InvalidOperationException("Somente o proprietario podem usar esse comando!"); } try { @@ -91,17 +85,15 @@ public async static Task HandleCommand(logsModel request, UsersModel user) } catch { - var erro = new Exception("Não foi possível atualizar o sistema remotamente!"); - await bot.ErrorReport(erro, request); - return; + request.status = 500; + throw new InvalidOperationException("Não foi possível atualizar o sistema remotamente!"); } break; case "/hotfix": if(user.privilege != UsersModel.userLevel.proprietario) { - var erro = new Exception("Somente o proprietario podem usar esse comando!"); - await bot.ErrorReport(erro, request); - return; + request.status = 403; + throw new InvalidOperationException("Somente o proprietario podem usar esse comando!"); } if(!Updater.IsChangedVersionFile()) { @@ -114,9 +106,8 @@ public async static Task HandleCommand(logsModel request, UsersModel user) case "/restart": if(!user.pode_promover()) { - var erro = new Exception("Somente o proprietario ou administrador podem usar esse comando!"); - await bot.ErrorReport(erro, request); - return; + request.status = 403; + throw new InvalidOperationException("Somente o proprietario ou administrador podem usar esse comando!"); } if(Updater.IsChangedVersionFile()) { @@ -131,9 +122,8 @@ public async static Task HandleCommand(logsModel request, UsersModel user) case "/database": if(user.privilege != UsersModel.userLevel.proprietario) { - var erro = new Exception("Somente o proprietario podem usar esse comando!"); - await bot.ErrorReport(erro, request); - return; + request.status = 403; + throw new InvalidOperationException("Somente o proprietario podem usar esse comando!"); } var solicitacoes = Database.GetInstance().RecuperarSolicitacao(); var tabela_texto = TableMaker.Serialize(solicitacoes, ';'); @@ -161,14 +151,17 @@ public async static Task HandleCommand(logsModel request, UsersModel user) await bot.sendTextMesssageWraper(user.identifier, stringbuilder.ToString(), markdown: false); } break; + default: + { + request.status = 400; + throw new InvalidOperationException("Comando solicitado não foi programado!"); + } } bot.SucessReport(request); } - catch (System.Exception) + catch (System.Exception error) { - var error = new Exception("Houve um erro ao processar o seu comando!"); await bot.ErrorReport(error, request); } - return; } } \ No newline at end of file diff --git a/Helpers/PdfChecker.cs b/Helpers/PdfChecker.cs index ef40b26..7acc0ab 100644 --- a/Helpers/PdfChecker.cs +++ b/Helpers/PdfChecker.cs @@ -1,7 +1,7 @@ namespace telbot.Helpers; public partial class PdfHandle { - public static Int64 Check(String filepath) + private static Int64 Check(String filepath) { using var reader = new iTextSharp.text.pdf.PdfReader(filepath); var re = new System.Text.RegularExpressions.Regex("^[0-9]{10}$"); diff --git a/Helpers/PdfHandler.cs b/Helpers/PdfHandler.cs new file mode 100644 index 0000000..df53fe1 --- /dev/null +++ b/Helpers/PdfHandler.cs @@ -0,0 +1,31 @@ +using Microsoft.Extensions.Logging; +using telbot.Interfaces; +using telbot.Services; +using telbot.models; +using telbot.handle; +using System.Collections.Concurrent; +namespace telbot.Helpers; +public partial class PdfHandle +{ + private readonly IDatabase database; + private readonly Configuration cfg; + private readonly HandleMessage bot; + private readonly ILogger logger; + private readonly ConcurrentDictionary faturas = new(); + private readonly Object _lock = new(); // Dedicated lock object + public PdfHandle() + { + this.bot = HandleMessage.GetInstance(); + this.cfg = Configuration.GetInstance(); + this.database = Database.GetInstance(); + this.logger = Logger.GetInstance(); + // Delete all files in the temporary folder + var files = Directory.GetFiles(cfg.TEMP_FOLDER); + foreach (var file in files) + { + File.Delete(file); + } + var folders = Directory.GetDirectories(cfg.TEMP_FOLDER); + + } +} \ No newline at end of file diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs new file mode 100644 index 0000000..1f76052 --- /dev/null +++ b/Helpers/PdfSender.cs @@ -0,0 +1,89 @@ +using Microsoft.Extensions.Logging; +using telbot.models; +namespace telbot.Helpers +{ + public partial class PdfHandle + { + public async void Sender() + { + logger.LogDebug("Realizando a procura de faturas para entregar..."); + while (true) + { + try + { + await Task.Delay(cfg.TASK_DELAY); + // Recupera as solicitações redirecionadas + var solicitacoes = database.RecuperarSolicitacao( + r => r.status == 300 && + r.typeRequest == models.TypeRequest.pdfInfo); + // Verifica se há solicitações a serem enviadas + if (solicitacoes is null) + { + continue; + } + var tasks = new List(); + // Verifica em cada solicitação, se já foi gerada a fatura + foreach (var solicitacao in solicitacoes) + { + // Recupera a lista de faturas geradas + + var faturas_info = new List( + faturas.Where(f => + f.Value.timestamp >= solicitacao.received_at && + f.Value.instalation == solicitacao.information + ).Select(f => f.Value).ToList()); + // Verifica se já tem faturas para a solicitação e se é a quantidade esperada + if (faturas_info.Count == solicitacao.instance) + { + //! Se tudo der certo, aqui tem que começar a entregar as faturas + tasks.Add(Sender(new List(faturas_info), solicitacao)); + } + // Verifica se a solicitação já não expirou + if(solicitacao.response_at.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) + { + solicitacao.status = 503; + tasks.Add(bot.ErrorReport( + request: solicitacao, + error: new Exception("Não foi gerada nenhuma fatura pelo sistema SAP!") + )); + } + } + await Task.WhenAll(tasks); + } + catch (System.Exception erro) + { + logger.LogError(erro, "Ocorreu um erro ao tentar enviar a fatura!"); + } + } + } + // Método separado para enviar as faturas + private async Task Sender(List faturasInfo, logsModel solicitacao) + { + var fluxoAtual = 0; + var tasks = new List(); + var fluxos = new Stream[solicitacao.instance]; + foreach (var fatura in faturasInfo) + { + if (fatura.status == pdfsModel.Status.sent) continue; + var caminho = System.IO.Path.Combine(cfg.TEMP_FOLDER, fatura.filename); + fluxos[fluxoAtual] = System.IO.File.OpenRead(caminho); + tasks.Add(bot.SendDocumentAsyncWraper( + solicitacao.identifier, + fluxos[fluxoAtual], + fatura.filename + )); + fatura.status = pdfsModel.Status.sent; + logger.LogInformation("Enviada fatura ({fluxoAtual}/{quantidadeEsperada}): {filename}", + ++fluxoAtual, solicitacao.instance, fatura.filename); + } + await Task.WhenAll(tasks); + foreach (var fluxo in fluxos) + { + fluxo.Close(); + } + Remove(new List(faturasInfo)); + bot.SucessReport(solicitacao); + logger.LogInformation("Enviadas faturas para a instalação {instalation}", solicitacao.information); + } + } +} diff --git a/Helpers/PdfWatcher.cs b/Helpers/PdfWatcher.cs index ed833f4..126f9e3 100644 --- a/Helpers/PdfWatcher.cs +++ b/Helpers/PdfWatcher.cs @@ -4,13 +4,9 @@ namespace telbot.Helpers; public partial class PdfHandle { - public static async void Watch() + public async void Watch() { - var cfg = Configuration.GetInstance(); - var database = Database.GetInstance(); - var logger = Logger.GetInstance(); logger.LogDebug("Monitor de faturas iniciado!"); - logger.LogDebug(cfg.TEMP_FOLDER); while (true) { try @@ -22,8 +18,7 @@ public static async void Watch() { if(System.IO.Path.GetExtension(file) != ".pdf") continue; var filename = System.IO.Path.GetFileName(file); - var registry = database.RecuperarFatura(filename); - if(registry == null) + if(!faturas.TryGetValue(filename, out pdfsModel? registro)) { var instalation = PdfHandle.Check(file); if(instalation == 0) @@ -40,7 +35,15 @@ public static async void Watch() }; var fatura_txt = System.Text.Json.JsonSerializer.Serialize(fatura); logger.LogDebug(fatura_txt); - database.InserirFatura(fatura); + faturas.TryAdd(filename, fatura); + } + if (registro is null) + { + continue; + } + if(registro.timestamp.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) + { + Remove(new List(){registro}); } } } @@ -50,25 +53,22 @@ public static async void Watch() } } } - public static void Remove(List faturas) + public void Remove(List faturas_info) { - var logger = Logger.GetInstance(); try { - foreach (var fatura in faturas) + foreach (var fatura in faturas_info) { var filepath = System.IO.Path.Combine( - Configuration.GetInstance().TEMP_FOLDER, - fatura.filename - ); + cfg.TEMP_FOLDER, fatura.filename); System.IO.File.Delete(filepath); - Database.GetInstance().RemoverFatura(fatura.rowid); + faturas.TryRemove(fatura.filename, out _); logger.LogDebug("Excluída fatura {fatura}", fatura.filename); } } catch (System.Exception erro) { - logger.LogError(erro, "Ocorreu uma falha ao tentar remover as faturas: "); + logger.LogError(erro, "Ocorreu uma falha ao tentar remover as faturas!"); } } } \ No newline at end of file diff --git a/Services/Logging.cs b/Services/Logging.cs index 3b42e3f..2d573ba 100644 --- a/Services/Logging.cs +++ b/Services/Logging.cs @@ -1,75 +1,34 @@ using Serilog; +using Serilog.Extensions.Logging; using Microsoft.Extensions.Logging; namespace telbot.Services; -public class Logger : IDisposable +public static class Logger { - private static ILoggerFactory _loggerFactory; - private static Microsoft.Extensions.Logging.ILogger _instance; - private static readonly Object _lock = new(); - private bool _disposed = false; // To detect redundant calls - private Logger() {} + private static readonly Lazy _loggerFactory = new(() => { + var logsfilepath = System.IO.Path.Combine(AppContext.BaseDirectory, "log", "telbot_.log"); + var console_template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} | {Level:u} | {SourceContext} | {Message}{NewLine}"; + var logfile_template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} | {Level:u} | {SourceContext} | {Message} {Exception}{NewLine}"; + Log.Logger = new LoggerConfiguration() // Configure Serilog directly + .MinimumLevel.Verbose() + .WriteTo.Console( + outputTemplate: console_template, + restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information + ) + .WriteTo.File( + path: logsfilepath, + outputTemplate: logfile_template, + rollingInterval: RollingInterval.Day, + restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Verbose + ) + .CreateLogger(); + return new SerilogLoggerFactory(Log.Logger); // Crucial step! // Return the SerilogLoggerFactory directly + }); public static Microsoft.Extensions.Logging.ILogger GetInstance() { - var logsfilepath = System.IO.Path.Combine( - System.AppContext.BaseDirectory, - "log", "telbot_.log" - ); - lock (_lock) - { - if (_instance == null) - { - // Initialize Serilog and attach to Microsoft.Extensions.Logging - var logfile_template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} | {Level:u} | {SourceContext} | {Message}{NewLine}{Exception}"; - var console_template = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} | {Level:u} | {SourceContext} | {Message}"; - // Ensure the logger is flushed - Serilog.Log.CloseAndFlush(); - var logger = new Serilog.LoggerConfiguration() - .WriteTo.Console( - outputTemplate: logfile_template, - restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Information - ) - .WriteTo.File( - path: logsfilepath, - outputTemplate: console_template, - rollingInterval: RollingInterval.Day, - restrictedToMinimumLevel: Serilog.Events.LogEventLevel.Verbose - ) - .CreateLogger(); - // Use Serilog as the logging provider - _loggerFactory = LoggerFactory.Create(builder => - { - builder.AddSerilog(logger); - }); - } - // Create a logger for the calling type T - _instance = _loggerFactory.CreateLogger(); - return _instance; - } + return _loggerFactory.Value.CreateLogger(); } - public void Dispose() + public static void CloseAndFlush() { - Dispose(true); - GC.SuppressFinalize(this); + Log.CloseAndFlush(); } - protected virtual void Dispose(bool disposing) - { - if (!_disposed) - { - if (disposing) - { - // Dispose managed resources here. - Log.CloseAndFlush(); - _loggerFactory?.Dispose(); - } - // Dispose unmanaged resources here. - _disposed = true; - _instance = null; // Clear the singleton instance - _loggerFactory = null; - } - } - ~Logger() - { - // Finalizer (optional) - Dispose(false); - } -} \ No newline at end of file +} diff --git a/Services/PostgresSQL.cs b/Services/PostgresSQL.cs index 756b955..4ad8994 100644 --- a/Services/PostgresSQL.cs +++ b/Services/PostgresSQL.cs @@ -122,7 +122,7 @@ public List RecuperarSolicitacao(Expression>? e var solicitacoes = new List(); using(var command = connection.CreateCommand()) { - command.CommandText = "SELECT rowid, identifier, application, information, received_at, response_at, instance, status, request_type FROM solicitacoes WHERE status = 0"; + command.CommandText = "SELECT rowid, identifier, application, information, received_at, response_at, instance, status, request_type FROM solicitacoes"; using(var dataReader = command.ExecuteReader()) { if(!dataReader.HasRows) return solicitacoes; diff --git a/Services/SQLite.cs b/Services/SQLite.cs index cc06564..e02ec06 100644 --- a/Services/SQLite.cs +++ b/Services/SQLite.cs @@ -5,6 +5,7 @@ namespace telbot.Services; public class SQLite : IDatabase { + private const String dt_format = "o"; private bool _disposed = false; // To detect redundant calls private readonly String connectionString = "Data Source=database.db"; public SQLite(Configuration cfg) @@ -73,8 +74,8 @@ public void InserirUsuario(UsersModel user_model) "(identifier, create_at, update_at, privilege, inserted_by, phone_number, username)" + "VALUES (@valor1, @valor2, @valor3, @valor4, @valor5, @valor6, @valor7)"; command.Parameters.Add(new SQLiteParameter("@valor1", user_model.identifier)); - command.Parameters.Add(new SQLiteParameter("@valor2", user_model.create_at.ToString("u"))); - command.Parameters.Add(new SQLiteParameter("@valor3", user_model.update_at.ToString("u"))); + command.Parameters.Add(new SQLiteParameter("@valor2", user_model.create_at.ToString(dt_format))); + command.Parameters.Add(new SQLiteParameter("@valor3", user_model.update_at.ToString(dt_format))); command.Parameters.Add(new SQLiteParameter("@valor4", (int)user_model.privilege)); command.Parameters.Add(new SQLiteParameter("@valor5", user_model.inserted_by)); command.Parameters.Add(new SQLiteParameter("@valor6", user_model.phone_number)); @@ -129,7 +130,7 @@ public void AlterarUsuario(UsersModel user_model) "inserted_by = @valor4, username = @valor6 WHERE rowid = @valor5"; command.Parameters.Add(new SQLiteParameter("@valor1", user_model.phone_number)); command.Parameters.Add(new SQLiteParameter("@valor2", (int)user_model.privilege)); - command.Parameters.Add(new SQLiteParameter("@valor3", user_model.update_at.ToString("u"))); + command.Parameters.Add(new SQLiteParameter("@valor3", user_model.update_at.ToString(dt_format))); command.Parameters.Add(new SQLiteParameter("@valor4", user_model.inserted_by)); command.Parameters.Add(new SQLiteParameter("@valor5", user_model.rowid)); command.Parameters.Add(new SQLiteParameter("@valor6", user_model.username)); @@ -151,8 +152,8 @@ public void InserirSolicitacao(logsModel request) command.Parameters.Add(new SQLiteParameter("@valor1", request.identifier)); command.Parameters.Add(new SQLiteParameter("@valor2", request.application)); command.Parameters.Add(new SQLiteParameter("@valor3", request.information)); - command.Parameters.Add(new SQLiteParameter("@valor4", request.received_at.ToString("u"))); - command.Parameters.Add(new SQLiteParameter("@valor5", DateTime.MinValue.ToString("u"))); + command.Parameters.Add(new SQLiteParameter("@valor4", request.received_at.ToString(dt_format))); + command.Parameters.Add(new SQLiteParameter("@valor5", DateTime.MinValue.ToString(dt_format))); command.Parameters.Add(new SQLiteParameter("@valor6", request.typeRequest)); command.ExecuteNonQuery(); } @@ -166,7 +167,7 @@ public List RecuperarSolicitacao(Expression>? e connection.Open(); using(var command = connection.CreateCommand()) { - command.CommandText = "SELECT rowid, identifier, application, information, received_at, response_at, instance, status, request_type FROM solicitacoes WHERE status = 0"; + command.CommandText = "SELECT rowid, identifier, application, information, received_at, response_at, instance, status, request_type FROM solicitacoes"; using(var dataReader = command.ExecuteReader()) { if(!dataReader.HasRows) return solicitacoes; @@ -203,7 +204,7 @@ public void AlterarSolicitacao(logsModel request) command.CommandText = "UPDATE solicitacoes SET " + "response_at = @valor1, instance = @valor2, status = @valor3 " + "WHERE rowid = @valor4"; - command.Parameters.Add(new SQLiteParameter("@valor1", request.response_at.ToString("u"))); + command.Parameters.Add(new SQLiteParameter("@valor1", request.response_at.ToString(dt_format))); command.Parameters.Add(new SQLiteParameter("@valor2", request.instance)); command.Parameters.Add(new SQLiteParameter("@valor3", request.status)); command.Parameters.Add(new SQLiteParameter("@valor4", request.rowid)); @@ -224,7 +225,7 @@ public void InserirFatura(pdfsModel fatura) "VALUES (@valor1, @valor2, @valor3, @valor4)"; command.Parameters.Add(new SQLiteParameter("@valor1", fatura.filename)); command.Parameters.Add(new SQLiteParameter("@valor2", fatura.instalation)); - command.Parameters.Add(new SQLiteParameter("@valor3", fatura.timestamp)); + command.Parameters.Add(new SQLiteParameter("@valor3", fatura.timestamp.ToString(dt_format))); command.Parameters.Add(new SQLiteParameter("@valor4", fatura.status)); command.ExecuteNonQuery(); } diff --git a/Startup.cs b/Startup.cs index 650ebbd..8c2ac53 100644 --- a/Startup.cs +++ b/Startup.cs @@ -29,7 +29,10 @@ static async Task Main(String[] args) System.AppContext.BaseDirectory, "bot.exe.old"); if(System.IO.File.Exists(oldExecutableFile)) System.IO.File.Delete(oldExecutableFile); - telbot.Helpers.Updater.Update(); + if (!config.IS_DEVELOPMENT) + { + telbot.Helpers.Updater.Update(); + } Database.GetInstance(config); var bot = new TelegramBotClient(config.BOT_TOKEN); var msg = HandleMessage.GetInstance(bot); @@ -54,25 +57,19 @@ static async Task Main(String[] args) var sap_instance_check_args = new String[] { "instancia", "5", "0"}; HandleAnnouncement.Executador("sap.exe", sap_instance_check_args, null); # pragma warning disable CS4014 - // Set chief method to answer normal requests - var normal_max_instance = (int)Math.Ceiling(config.SAP_INSTANCIA / 2.0); HandleAsynchronous.Chief ( minInstance: 0, - maxInstance: normal_max_instance, - s => s.typeRequest != TypeRequest.pdfInfo && - s.typeRequest != TypeRequest.gestao && - s.typeRequest != TypeRequest.comando - ); - // Set chief method to answer invoice requests - HandleAsynchronous.Chief - ( - minInstance: normal_max_instance, maxInstance: config.SAP_INSTANCIA, - s => s.typeRequest == TypeRequest.pdfInfo + s => + s.typeRequest != TypeRequest.gestao && + s.typeRequest != TypeRequest.comando && + s.status == 0 ); # pragma warning restore CS4014 - PdfHandle.Watch(); + var pdf_handler = new PdfHandle(); + pdf_handler.Watch(); + pdf_handler.Sender(); Console.ReadLine(); cts.Cancel(); } @@ -109,13 +106,14 @@ private static async Task HandleUpdate(ITelegramBotClient _, Update update, Canc //##################################################// // direciona para um método correspondente ao tipo // //##################################################// + var datahora = update.Message.Date > DateTime.Now ? update.Message.Date.ToLocalTime() : update.Message.Date; switch (update.Message.Type) { case MessageType.Text: { await HandleTypeMessage.ManuscriptsType( usuario: usuario, - recebido_em: update.Message.Date.ToUniversalTime(), + recebido_em: datahora, mensagem: update.Message.Text! ); break; @@ -133,7 +131,7 @@ await HandleTypeMessage.PhoneNumberType( { await HandleTypeMessage.PhotographType( usuario: usuario, - recebido_em: update.Message.Date.ToUniversalTime(), + recebido_em: datahora, photograph: update.Message.Photo!.First().FileId, caption: update.Message.Caption ); @@ -143,7 +141,7 @@ await HandleTypeMessage.PhotographType( { await HandleTypeMessage.DocumentType( usuario: usuario, - recebido_em: update.Message.Date.ToUniversalTime(), + recebido_em: datahora, document: update.Message.Document!.FileId, caption: update.Message.Caption ); @@ -153,7 +151,7 @@ await HandleTypeMessage.DocumentType( { await HandleTypeMessage.VideoclipType( usuario: usuario, - recebido_em: update.Message.Date.ToUniversalTime(), + recebido_em: datahora, videoclip: update.Message.Video!.FileId, caption: update.Message.Caption ); @@ -163,7 +161,7 @@ await HandleTypeMessage.VideoclipType( { await HandleTypeMessage.CoordinatesType( usuario: usuario, - recebido_em: update.Message.Date.ToUniversalTime(), + recebido_em: datahora, lat: update.Message.Location!.Latitude, lon: update.Message.Location!.Longitude ); @@ -177,7 +175,7 @@ await chatbot.ErrorReport( request: new logsModel() { identifier = update.Message.From.Id, application = "nullmessage", - received_at = update.Message.Date.ToUniversalTime(), + received_at = datahora, response_at = DateTime.Now, typeRequest = TypeRequest.nullInfo, status = 400 diff --git a/comunicado.txt b/comunicado.txt index 06c6bcc..5a9607c 100644 --- a/comunicado.txt +++ b/comunicado.txt @@ -1,6 +1,13 @@ *COMUNICADO DE ATUALIZAÇÃO DO CHATBOT* -1. Realizado balanceamento das instâncias que atendem solicitações normais para as instâncias que atendem solicitações de fatura; -2. Melhorado as definições de armazenamento de logs, criando logs diários, facilitando a detecção de problemas e erros. +Adicionado sistema de envio de *fatura de forma assíncrona*. + +Agora, o chatbot irá realizar os processos de obtenção de faturas e envio separadamente: + +1. Primeiramente, ele atenderá à equipe e realizará a solicitação da fatura; +2. Outro agente aguardará pela fatura e enviará quando ela estiver pronta; +3. Isso liberará a fila para outras solicitações, reduzindo o tempo de espera. + +Ainda estaremos dependentes do sistema SAP, mas isso reduzirá muito o tempo de espera por faturas! _Versão atual: ${VERSION}_ \ No newline at end of file diff --git a/version b/version index c71c3f7..9485a20 100644 --- a/version +++ b/version @@ -1 +1 @@ -20241129 +20250221 \ No newline at end of file