From e2dff90ddacfa15144b4ffd8916d3bb94309bf03 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:13:28 -0300 Subject: [PATCH 01/27] Added constructor, non static fields, and instruction to clean temporary folder to PdfHandle class --- Helpers/PdfHandler.cs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Helpers/PdfHandler.cs diff --git a/Helpers/PdfHandler.cs b/Helpers/PdfHandler.cs new file mode 100644 index 0000000..1952813 --- /dev/null +++ b/Helpers/PdfHandler.cs @@ -0,0 +1,30 @@ +using Microsoft.Extensions.Logging; +using telbot.Interfaces; +using telbot.Services; +using telbot.models; +using telbot.handle; +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 List 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 From 14b357e598cd815f172b800b0cbc94f363f9397a Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:14:09 -0300 Subject: [PATCH 02/27] Changed 'Check' method to private --- Helpers/PdfChecker.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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}$"); From 8563ffdd6e79f5ca555ac3c357254a3f40e70ad3 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:15:18 -0300 Subject: [PATCH 03/27] Changed static method to instanced method to use instanced fields --- Helpers/PdfWatcher.cs | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Helpers/PdfWatcher.cs b/Helpers/PdfWatcher.cs index ed833f4..be2a131 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,7 +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); + var registry = faturas.Find(f => f.filename == filename); if(registry == null) { var instalation = PdfHandle.Check(file); @@ -40,7 +36,10 @@ public static async void Watch() }; var fatura_txt = System.Text.Json.JsonSerializer.Serialize(fatura); logger.LogDebug(fatura_txt); - database.InserirFatura(fatura); + lock(_lock) + { + faturas.Add(fatura); + } } } } @@ -50,9 +49,8 @@ public static async void Watch() } } } - public static void Remove(List faturas) + public void Remove(List faturas) { - var logger = Logger.GetInstance(); try { foreach (var fatura in faturas) @@ -62,13 +60,16 @@ public static void Remove(List faturas) fatura.filename ); System.IO.File.Delete(filepath); - Database.GetInstance().RemoverFatura(fatura.rowid); + lock(_lock) + { + faturas.Remove(fatura); + } 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 From f5c7d375d0c9da916823dace06ad8dd83c3817ab Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:21:23 -0300 Subject: [PATCH 04/27] Added 'Sender' method that will send generated invoice to send them --- Helpers/PdfSender.cs | 88 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Helpers/PdfSender.cs diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs new file mode 100644 index 0000000..98bb003 --- /dev/null +++ b/Helpers/PdfSender.cs @@ -0,0 +1,88 @@ +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; + } + // Verifica em cada solicitação, se já foi gerada a fatura + foreach (var solicitacao in solicitacoes) + { + // Verifica se a solicitação já não expirou + if(!cfg.IS_DEVELOPMENT && + solicitacao.response_at.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) + { + solicitacao.status = 503; + var erro = new Exception("Não foi gerada nenhuma fatura pelo sistema SAP!"); + await bot.ErrorReport(erro, solicitacao); + continue; + } + List? faturas_info = null; + // Recupera a lista de faturas geradas + lock(_lock) + { + faturas_info = new List( + faturas.Where(f => + f.timestamp >= solicitacao.received_at && + f.instalation == solicitacao.information + ).ToList()); + } + // Verifica se já tem faturas para a solicitação + if (faturas_info is null) + { + continue; + } + // Verifica se a quantidade de faturas encontradas é a mesma quantidade esperada + if (faturas_info.Count != solicitacao.instance) + { + continue; + } + //! Se tudo der certo, aqui tem que começar a entregar as faturas + var fluxo_atual = 0; + var tasks = new List(); + var fluxos = new Stream[solicitacao.instance]; + foreach (var fatura in faturas_info) + { + 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; + logger.LogInformation("Enviada fatura ({fluxo_atual}/{quantidade_experada}): {filename}", + ++fluxo_atual, solicitacao.instance, fatura.filename); + } + await Task.WhenAll(tasks); + foreach(var fluxo in fluxos) fluxo.Close(); + Remove(faturas); + bot.SucessReport(solicitacao); + logger.LogInformation("Enviadas faturas para a instalação {instalation}", solicitacao.information); + } + } + catch (System.Exception erro) + { + logger.LogError(erro, "Ocorreu um erro ao tentar enviar a fatura!"); + } + } + } + } +} \ No newline at end of file From 4a0fa7f480caccb3a171051ec667e0ed3f736735 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:23:35 -0300 Subject: [PATCH 05/27] Changed instructions that send invoice directly to redirect requests to 'PdfSender' do this --- Handles/HandleAsynchronous.cs | 81 ++++++----------------------------- 1 file changed, 12 insertions(+), 69 deletions(-) diff --git a/Handles/HandleAsynchronous.cs b/Handles/HandleAsynchronous.cs index 30f1e1d..0950ce2 100644 --- a/Handles/HandleAsynchronous.cs +++ b/Handles/HandleAsynchronous.cs @@ -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: From 1137900253ce25271a910b8bd0b0c49bd74da639 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:30:14 -0300 Subject: [PATCH 06/27] Added annulment to filter argument to get all requests --- Handles/HandleAsynchronous.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Handles/HandleAsynchronous.cs b/Handles/HandleAsynchronous.cs index 0950ce2..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; From 6b58a68eb0b4e599e9c00aa5196a093ff71d1b64 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:33:14 -0300 Subject: [PATCH 07/27] Removed instructions to separate 'normal' calls from 'invoices' care --- Startup.cs | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Startup.cs b/Startup.cs index 650ebbd..bd1bc48 100644 --- a/Startup.cs +++ b/Startup.cs @@ -54,22 +54,10 @@ 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 + maxInstance: config.SAP_INSTANCIA ); # pragma warning restore CS4014 PdfHandle.Watch(); From 317d9ece0a1b4c364e8f41263f5b046b7329a527 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Tue, 11 Feb 2025 10:33:54 -0300 Subject: [PATCH 08/27] Changed static call to instanciated PdfHandler call --- Startup.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Startup.cs b/Startup.cs index bd1bc48..7d76d2a 100644 --- a/Startup.cs +++ b/Startup.cs @@ -60,7 +60,9 @@ static async Task Main(String[] args) maxInstance: config.SAP_INSTANCIA ); # pragma warning restore CS4014 - PdfHandle.Watch(); + var pdf_handler = new PdfHandle(); + pdf_handler.Watch(); + pdf_handler.Sender(); Console.ReadLine(); cts.Cancel(); } From 997fdcc46a2ff39314cba60ff8ec1a1b811fbe9d Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Wed, 19 Feb 2025 17:12:59 -0300 Subject: [PATCH 09/27] Filtered pending requests to avoid reprocessing finished requests. --- Startup.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Startup.cs b/Startup.cs index 7d76d2a..81f9d7e 100644 --- a/Startup.cs +++ b/Startup.cs @@ -57,7 +57,8 @@ static async Task Main(String[] args) HandleAsynchronous.Chief ( minInstance: 0, - maxInstance: config.SAP_INSTANCIA + maxInstance: config.SAP_INSTANCIA, + s => s.status == 0 ); # pragma warning restore CS4014 var pdf_handler = new PdfHandle(); @@ -99,13 +100,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; @@ -123,7 +125,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 ); @@ -133,7 +135,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 ); @@ -143,7 +145,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 ); @@ -153,7 +155,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 ); @@ -167,7 +169,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 From d1674806df7db8e122a4f0d8ca8c3f7c096fc662 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Wed, 19 Feb 2025 17:16:32 -0300 Subject: [PATCH 10/27] Changed getting singleton instance to class property, that hold instance. --- Helpers/PdfWatcher.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Helpers/PdfWatcher.cs b/Helpers/PdfWatcher.cs index be2a131..245f25d 100644 --- a/Helpers/PdfWatcher.cs +++ b/Helpers/PdfWatcher.cs @@ -56,9 +56,7 @@ public void Remove(List faturas) foreach (var fatura in faturas) { var filepath = System.IO.Path.Combine( - Configuration.GetInstance().TEMP_FOLDER, - fatura.filename - ); + cfg.TEMP_FOLDER, fatura.filename); System.IO.File.Delete(filepath); lock(_lock) { From 35558c1854d5ad52ebf467d2ca20ef16cb242caa Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Wed, 19 Feb 2025 17:21:18 -0300 Subject: [PATCH 11/27] Removed status limitation when retrieve requests --- Services/PostgresSQL.cs | 2 +- Services/SQLite.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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..a8f9d1d 100644 --- a/Services/SQLite.cs +++ b/Services/SQLite.cs @@ -166,7 +166,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; From 7abf6a7cb84a4bb7712a8110771d702427fe6089 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Wed, 19 Feb 2025 17:26:34 -0300 Subject: [PATCH 12/27] Added more one lock to avoid concurrent errors --- Helpers/PdfSender.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 98bb003..9f557fd 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -73,7 +73,10 @@ public async void Sender() } await Task.WhenAll(tasks); foreach(var fluxo in fluxos) fluxo.Close(); - Remove(faturas); + lock(_lock) + { + Remove(faturas_info); + } bot.SucessReport(solicitacao); logger.LogInformation("Enviadas faturas para a instalação {instalation}", solicitacao.information); } From 3610fe318b2dc822039d17c6681bff6c47df0f43 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 12:06:59 -0300 Subject: [PATCH 13/27] rewrite Logger class to avoid missconfiguration when instanced multiple times --- Services/Logging.cs | 91 +++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 66 deletions(-) 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 +} From 2c8839b23e80fe02fcdfb1f19e16910726554108 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 12:08:04 -0300 Subject: [PATCH 14/27] Added more filters to avoid response twice --- Startup.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Startup.cs b/Startup.cs index 81f9d7e..55d1ba9 100644 --- a/Startup.cs +++ b/Startup.cs @@ -58,7 +58,10 @@ static async Task Main(String[] args) ( minInstance: 0, maxInstance: config.SAP_INSTANCIA, - s => s.status == 0 + s => + s.typeRequest != TypeRequest.gestao && + s.typeRequest != TypeRequest.comando && + s.status == 0 ); # pragma warning restore CS4014 var pdf_handler = new PdfHandle(); From bd258ff49e780c0a46a67efd198abdba6a2c0894 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 12:08:32 -0300 Subject: [PATCH 15/27] Avoid check updates when in development --- Startup.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Startup.cs b/Startup.cs index 55d1ba9..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); From 74a9c5156d8c443c5a53abcb98028e37c2dbb7b8 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 12:09:59 -0300 Subject: [PATCH 16/27] Fixed some errors whiile handling with commands --- Handles/HandleCommand.cs | 43 +++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 25 deletions(-) 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 From 24e04be9ebb3d23191eb4932cee6e334b630951c Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 12:10:25 -0300 Subject: [PATCH 17/27] Updated lauch.json --- .vscode/launch.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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", From d044870037e1541b7d5468b49f3f9860da312947 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Thu, 20 Feb 2025 13:00:02 -0300 Subject: [PATCH 18/27] Added template string to apend timezone information on database --- Services/SQLite.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Services/SQLite.cs b/Services/SQLite.cs index a8f9d1d..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(); } @@ -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(); } From 25ccb4c98dc817cf825fe3a285820a35c5420d65 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 08:25:21 -0300 Subject: [PATCH 19/27] Changed List to ConcurrentBag type to avoid issue with concurrency --- Helpers/PdfHandler.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Helpers/PdfHandler.cs b/Helpers/PdfHandler.cs index 1952813..e1ed426 100644 --- a/Helpers/PdfHandler.cs +++ b/Helpers/PdfHandler.cs @@ -3,6 +3,7 @@ using telbot.Services; using telbot.models; using telbot.handle; +using System.Collections.Concurrent; namespace telbot.Helpers; public partial class PdfHandle { @@ -10,7 +11,7 @@ public partial class PdfHandle private readonly Configuration cfg; private readonly HandleMessage bot; private readonly ILogger logger; - private readonly List faturas = new(); + private readonly ConcurrentBag faturas = new(); private readonly Object _lock = new(); // Dedicated lock object public PdfHandle() { From a012388488d040fcc31a76387ff5ca7b1eb0e03c Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 08:28:58 -0300 Subject: [PATCH 20/27] Removed unnecessary locks and changed 'Find' method to 'FirstOrDefault' --- Helpers/PdfSender.cs | 13 +++++-------- Helpers/PdfWatcher.cs | 12 +++--------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 9f557fd..18c66d8 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -35,14 +35,11 @@ public async void Sender() } List? faturas_info = null; // Recupera a lista de faturas geradas - lock(_lock) - { - faturas_info = new List( - faturas.Where(f => - f.timestamp >= solicitacao.received_at && - f.instalation == solicitacao.information - ).ToList()); - } + faturas_info = new List( + faturas.Where(f => + f.timestamp >= solicitacao.received_at && + f.instalation == solicitacao.information + ).ToList()); // Verifica se já tem faturas para a solicitação if (faturas_info is null) { diff --git a/Helpers/PdfWatcher.cs b/Helpers/PdfWatcher.cs index 245f25d..2f0929d 100644 --- a/Helpers/PdfWatcher.cs +++ b/Helpers/PdfWatcher.cs @@ -18,7 +18,7 @@ public async void Watch() { if(System.IO.Path.GetExtension(file) != ".pdf") continue; var filename = System.IO.Path.GetFileName(file); - var registry = faturas.Find(f => f.filename == filename); + var registry = faturas.FirstOrDefault(f => f.filename == filename); if(registry == null) { var instalation = PdfHandle.Check(file); @@ -36,10 +36,7 @@ public async void Watch() }; var fatura_txt = System.Text.Json.JsonSerializer.Serialize(fatura); logger.LogDebug(fatura_txt); - lock(_lock) - { - faturas.Add(fatura); - } + faturas.Add(fatura); } } } @@ -58,10 +55,7 @@ public void Remove(List faturas) var filepath = System.IO.Path.Combine( cfg.TEMP_FOLDER, fatura.filename); System.IO.File.Delete(filepath); - lock(_lock) - { - faturas.Remove(fatura); - } + faturas.Remove(fatura); logger.LogDebug("Excluída fatura {fatura}", fatura.filename); } } From 0ac53b8a0719ad8b812d821d6203ebd99c1d7be4 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 08:36:51 -0300 Subject: [PATCH 21/27] Moved send file task to separated method --- Helpers/PdfSender.cs | 60 +++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 18c66d8..9570b97 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -21,6 +21,7 @@ public async void Sender() { continue; } + var tasks = new List(); // Verifica em cada solicitação, se já foi gerada a fatura foreach (var solicitacao in solicitacoes) { @@ -51,32 +52,10 @@ public async void Sender() continue; } //! Se tudo der certo, aqui tem que começar a entregar as faturas - var fluxo_atual = 0; - var tasks = new List(); - var fluxos = new Stream[solicitacao.instance]; - foreach (var fatura in faturas_info) - { - 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; - logger.LogInformation("Enviada fatura ({fluxo_atual}/{quantidade_experada}): {filename}", - ++fluxo_atual, solicitacao.instance, fatura.filename); - } - await Task.WhenAll(tasks); - foreach(var fluxo in fluxos) fluxo.Close(); - lock(_lock) - { - Remove(faturas_info); - } - bot.SucessReport(solicitacao); - logger.LogInformation("Enviadas faturas para a instalação {instalation}", solicitacao.information); + tasks.Add(Sender(faturas_info, solicitacao)); + } } + await Task.WhenAll(tasks); } catch (System.Exception erro) { @@ -84,5 +63,34 @@ public async void Sender() } } } + // 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(faturasInfo); + bot.SucessReport(solicitacao); + logger.LogInformation("Enviadas faturas para a instalação {instalation}", solicitacao.information); + } } -} \ No newline at end of file +} From aa92fe61e48fd95fb681f73102b429e93f0576fc Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 08:41:44 -0300 Subject: [PATCH 22/27] Merged two checks into one. --- Helpers/PdfSender.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 9570b97..214f649 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -41,19 +41,12 @@ public async void Sender() f.timestamp >= solicitacao.received_at && f.instalation == solicitacao.information ).ToList()); - // Verifica se já tem faturas para a solicitação - if (faturas_info is null) + // Verifica se já tem faturas para a solicitação e se é a quantidade esperada + if (faturas_info is not null && faturas_info.Count != solicitacao.instance) { - continue; - } - // Verifica se a quantidade de faturas encontradas é a mesma quantidade esperada - if (faturas_info.Count != solicitacao.instance) - { - continue; + //! Se tudo der certo, aqui tem que começar a entregar as faturas + tasks.Add(Sender(faturas_info, solicitacao)); } - //! Se tudo der certo, aqui tem que começar a entregar as faturas - tasks.Add(Sender(faturas_info, solicitacao)); - } } await Task.WhenAll(tasks); } From 211484cea568a7de76464b1b5c8e2fef8c966cb0 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 08:43:45 -0300 Subject: [PATCH 23/27] Moved the expiration check to the end of iteration. --- Helpers/PdfSender.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 214f649..52d0a53 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -25,15 +25,6 @@ public async void Sender() // Verifica em cada solicitação, se já foi gerada a fatura foreach (var solicitacao in solicitacoes) { - // Verifica se a solicitação já não expirou - if(!cfg.IS_DEVELOPMENT && - solicitacao.response_at.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) - { - solicitacao.status = 503; - var erro = new Exception("Não foi gerada nenhuma fatura pelo sistema SAP!"); - await bot.ErrorReport(erro, solicitacao); - continue; - } List? faturas_info = null; // Recupera a lista de faturas geradas faturas_info = new List( @@ -47,6 +38,15 @@ public async void Sender() //! Se tudo der certo, aqui tem que começar a entregar as faturas tasks.Add(Sender(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); } From da9cc05b06e1bd66a1dce636332a86c24f771d0d Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 14:32:59 -0300 Subject: [PATCH 24/27] Changed ConcurrentBag to ConcurrentDictionary because ConcurrentBag does not have a Remove method. --- Helpers/PdfHandler.cs | 2 +- Helpers/PdfSender.cs | 16 ++++++++-------- Helpers/PdfWatcher.cs | 11 +++++------ 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/Helpers/PdfHandler.cs b/Helpers/PdfHandler.cs index e1ed426..df53fe1 100644 --- a/Helpers/PdfHandler.cs +++ b/Helpers/PdfHandler.cs @@ -11,7 +11,7 @@ public partial class PdfHandle private readonly Configuration cfg; private readonly HandleMessage bot; private readonly ILogger logger; - private readonly ConcurrentBag faturas = new(); + private readonly ConcurrentDictionary faturas = new(); private readonly Object _lock = new(); // Dedicated lock object public PdfHandle() { diff --git a/Helpers/PdfSender.cs b/Helpers/PdfSender.cs index 52d0a53..1f76052 100644 --- a/Helpers/PdfSender.cs +++ b/Helpers/PdfSender.cs @@ -25,18 +25,18 @@ public async void Sender() // Verifica em cada solicitação, se já foi gerada a fatura foreach (var solicitacao in solicitacoes) { - List? faturas_info = null; // Recupera a lista de faturas geradas - faturas_info = new List( + + var faturas_info = new List( faturas.Where(f => - f.timestamp >= solicitacao.received_at && - f.instalation == solicitacao.information - ).ToList()); + 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 is not null && faturas_info.Count != solicitacao.instance) + if (faturas_info.Count == solicitacao.instance) { //! Se tudo der certo, aqui tem que começar a entregar as faturas - tasks.Add(Sender(faturas_info, solicitacao)); + 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) @@ -81,7 +81,7 @@ private async Task Sender(List faturasInfo, logsModel solicitacao) { fluxo.Close(); } - Remove(faturasInfo); + 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 2f0929d..87b9258 100644 --- a/Helpers/PdfWatcher.cs +++ b/Helpers/PdfWatcher.cs @@ -18,8 +18,7 @@ public async void Watch() { if(System.IO.Path.GetExtension(file) != ".pdf") continue; var filename = System.IO.Path.GetFileName(file); - var registry = faturas.FirstOrDefault(f => f.filename == filename); - if(registry == null) + if(!faturas.TryGetValue(filename, out _)) { var instalation = PdfHandle.Check(file); if(instalation == 0) @@ -36,7 +35,7 @@ public async void Watch() }; var fatura_txt = System.Text.Json.JsonSerializer.Serialize(fatura); logger.LogDebug(fatura_txt); - faturas.Add(fatura); + faturas.TryAdd(filename, fatura); } } } @@ -46,16 +45,16 @@ public async void Watch() } } } - public void Remove(List faturas) + public void Remove(List faturas_info) { try { - foreach (var fatura in faturas) + foreach (var fatura in faturas_info) { var filepath = System.IO.Path.Combine( cfg.TEMP_FOLDER, fatura.filename); System.IO.File.Delete(filepath); - faturas.Remove(fatura); + faturas.TryRemove(fatura.filename, out _); logger.LogDebug("Excluída fatura {fatura}", fatura.filename); } } From 49c6d7f891bef9980649f8761ef4a249c28f2101 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 15:21:35 -0300 Subject: [PATCH 25/27] Added instructions to remove expired invoice files --- Helpers/PdfWatcher.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Helpers/PdfWatcher.cs b/Helpers/PdfWatcher.cs index 87b9258..126f9e3 100644 --- a/Helpers/PdfWatcher.cs +++ b/Helpers/PdfWatcher.cs @@ -18,7 +18,7 @@ public async void Watch() { if(System.IO.Path.GetExtension(file) != ".pdf") continue; var filename = System.IO.Path.GetFileName(file); - if(!faturas.TryGetValue(filename, out _)) + if(!faturas.TryGetValue(filename, out pdfsModel? registro)) { var instalation = PdfHandle.Check(file); if(instalation == 0) @@ -37,6 +37,14 @@ public async void Watch() logger.LogDebug(fatura_txt); faturas.TryAdd(filename, fatura); } + if (registro is null) + { + continue; + } + if(registro.timestamp.AddMilliseconds(cfg.SAP_ESPERA) < DateTime.Now) + { + Remove(new List(){registro}); + } } } catch (System.Exception erro) From 3ebf53d50816431ea65051cc0817e43b5a365263 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 15:22:20 -0300 Subject: [PATCH 26/27] Updated comunicado.txt --- comunicado.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 From ee199166bb7c18e59633bd9e68b41a2c0e6c9f15 Mon Sep 17 00:00:00 2001 From: Ruan Faustino Camello Da Silva Date: Fri, 21 Feb 2025 15:22:42 -0300 Subject: [PATCH 27/27] Updated version --- version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version b/version index c71c3f7..9485a20 100644 --- a/version +++ b/version @@ -1 +1 @@ -20241129 +20250221 \ No newline at end of file