package chat import ( "bytes" "context" "fmt" "regexp" "strconv" "strings" "sync" "unicode" "git.maximotejeda.com/maximo/cedulados-bot/config" "git.maximotejeda.com/maximo/cedulados-bot/internal/adapter/grpc/cedulados" "git.maximotejeda.com/maximo/cedulados-bot/internal/adapter/helper" "git.maximotejeda.com/maximo/cedulados-bot/internal/application/domain" "git.maximotejeda.com/maximo/cedulados-bot/internal/ports" tgb "github.com/go-telegram-bot-api/telegram-bot-api/v5" "golang.org/x/text/runes" "golang.org/x/text/transform" "golang.org/x/text/unicode/norm" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) var ChatPool *sync.Pool type ChatObj struct { ctx context.Context update *tgb.Update bot *tgb.BotAPI u ports.UserService c ports.CeduladosService } func NewChatObj(bot *tgb.BotAPI, updt *tgb.Update) (chat *ChatObj) { if ChatPool == nil { ChatPool = &sync.Pool{ New: func() any { return &ChatObj{} }, } for i := 0; i < 20; i++ { ChatPool.Put(ChatPool.New()) } } else { fmt.Println("alredy populated") } chat = ChatPool.Get().(*ChatObj) chat.update = updt chat.bot = bot return chat } func (ch *ChatObj)Empty() { ch.update = nil ch.c = nil ch.u = nil ChatPool.Put(ch) } func (ch *ChatObj)Send(){ } func (ch *ChatObj)Handler( cSVC ports.CeduladosService, uSVC ports.UserService) { text := NormalizeText(ch.update.Message.Text) textList := strings.Split(text, " ") msg := tgb.NewMessage(ch.update.Message.Chat.ID, "") if len(textList) >= 1 && MessageChecker(text) == "digit" { // in case of message match a cedula ced, err := helper.NewCedula(ch.ctx, text) if err != nil { msg.Text = "cedula no reconocida " + err.Error() } else { msg, photoMsg := ProcessByCedula(ch.ctx, cSVC, uSVC, ced) msg.ChatID = ch.update.Message.Chat.ID if photoMsg != nil { photoMsg.ChatID = ch.update.Message.Chat.ID ch.bot.Send(photoMsg) } ch.bot.Send(msg) return } } else if len(textList) >= 2 && MessageChecker(text) == "word" { msg := ProcessByName(ch.ctx, cSVC, uSVC, textList) msg.ChatID = ch.update.Message.Chat.ID ch.bot.Send(msg) } msg.ReplyToMessageID = ch.update.Message.MessageID ch.bot.Send(msg) } // ProcessByCedula // // When a text arrives the chat if it match a cedula try to query db func ProcessByCedula(ctx context.Context, cSVC ports.CeduladosService, uSVC ports.UserService, ced *domain.Cedula) (message *tgb.MessageConfig, fotoMsg *tgb.PhotoConfig) { msg := tgb.NewMessage(0, "") message = &msg info , err := cSVC.CeduladoByCedula(context.Background(), ced) if err != nil { fmt.Println("error on query ", err) } fmt.Println("!!!!success on query", info) if info != nil { msg.Text = fmt.Sprintf(` Nombres: %s Apellidos: %s %s Cedula: %s Direccion: %s Telefono: %s `, strings.ToLower(info.Nombres), strings.ToLower(info.Apellido1), strings.ToLower(info.Apellido2), info.MunCed+info.SeqCed+info.VerCed, RemoveSpaces(info.Direccion), info.Telefono) } var opts []grpc.DialOption opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials())) cedConn, err := grpc.NewClient(config.GetCeduladosServiceURL(), opts...) if err != nil { panic(err) } c, err := cedulados.NewAdapter(cedConn) if err != nil { panic(err) } defer cedConn.Close() foto, err := c.QueryFotoByID(ctx, 1) if err != nil { fmt.Println("Photo not found", err.Error()) return } if foto != nil { rq := tgb.FileReader{Name: fmt.Sprintf("%s-%s-%s", ced.MunCed, ced.SeqCed, ced.VerCed), Reader: bytes.NewReader(foto.Imagen)} fotost := tgb.NewPhoto(msg.ChatID, rq) fotoMsg = &fotost } return } func ProcessByName(ctx context.Context, cSVC ports.CeduladosService, uSVC ports.UserService, nameList []string) (message *tgb.MessageConfig) { var err error page := int64(0) // look for if the last part of the list is a number lastItem := nameList[len(nameList)-1] if MessageChecker(lastItem) == "digit" && !strings.HasPrefix(lastItem, "0") { pageInt, err := strconv.ParseInt(lastItem, 10, 64) if err != nil { fmt.Println(err) } nameList = nameList[:len(nameList)-1] if pageInt < 20 { page = pageInt } } rows := &domain.MultipleResults{} message = &tgb.MessageConfig{} text := strings.Join(nameList, " ") res, err := cSVC.CeduladoByFTS(ctx, "maximo tejeda", 0) if err != nil { fmt.Println("error oon fts", err) } fmt.Println("sucess", res) rows, err = cSVC.CeduladoByFTS(ctx, text, page) if err != nil { message.Text = "no hubo resultados para la busqueda" return } textToSend := fmt.Sprintf(` Busqueda: Texto: %s Pagina: %d resultados desde: %d A %d De un total de: %d `, text, (rows.Page), (rows.Page*10)-9, (rows.Page)*10, rows.Total) for _, v := range rows.Data { textToSend = textToSend + fmt.Sprintf("\n %s %s %s \n %s-%s-%s\n", strings.ToLower(v.Nombres), strings.ToLower(v.Apellido1), strings.ToLower(v.Apellido2), v.MunCed, v.SeqCed, v.VerCed) } message.Text = textToSend return } func MessageChecker(text string) string { // Check is text start with number checkSpace := regexp.MustCompile(`^[\s]+.*`) checkNumber := regexp.MustCompile(`^[\d]+.*`) checkWord := regexp.MustCompile(`^[a-zA-Z% ]+.*`) if checkNumber.MatchString(text) { return "digit" } else if checkWord.MatchString(text) { return "word" } else if checkSpace.MatchString(text) { t := strings.TrimSpace(text) return MessageChecker(t) } return "" } // NormalizeText // remove foreign accent func NormalizeText(text string) string { t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) result, _, _ := transform.String(t, text) return result } func RemoveSpaces(text string) (res string) { re := regexp.MustCompile(`[\s]+`) res = re.ReplaceAllString(text, " ") return }