package chat import ( "bytes" "context" "fmt" "regexp" "strconv" "strings" "sync" "unicode" 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" ) var ChatPool *sync.Pool type ChatObj struct { update *tgb.Update bot *tgb.BotAPI } 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 EmptyChat(chat *ChatObj) { chat.update = nil ChatPool.Put(chat) } func HandleChat(bot *tgb.BotAPI, updt *tgb.Update) { chat := NewChatObj(bot, updt) defer EmptyChat(chat) text := NormalizeText(updt.Message.Text) textList := strings.Split(text, " ") msg := tgb.NewMessage(updt.Message.Chat.ID, "") if len(textList) >= 1 && MessageChecker(text) == "digit" { // in case of message match a cedula ced, err := info.NewCedula(text) if err != nil { msg.Text = "cedula no reconocida " + err.Error() } else { msg, photoMsg := ProcessByCedula(*ced) msg.ChatID = updt.Message.Chat.ID if photoMsg != nil { photoMsg.ChatID = updt.Message.Chat.ID bot.Send(photoMsg) } bot.Send(msg) return } } else if len(textList) >= 2 && MessageChecker(text) == "word" { msg := ProcessByName(textList) msg.ChatID = updt.Message.Chat.ID bot.Send(msg) } msg.ReplyToMessageID = updt.Message.MessageID bot.Send(msg) } // ProcessByCedula // // When a text arrives the chat if it match a cedula try to query db func ProcessByCedula(dbS *db.DB, ced info.Cedula) (message *tgb.MessageConfig, fotoMsg *tgb.PhotoConfig) { msg := tgb.NewMessage(0, "") message = &msg ctx := context.Background() info, err := info.GetByCedula(ctx, dbS, ced) if err != nil { msg.Text = "error buscando cedula " + err.Error() } 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) } foto, err := fotos.GetImageByCedulas(ctx, dbS, ced) 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)} fotost := tgb.NewPhoto(msg.ChatID, rq) fotoMsg = &fotost } return } func ProcessByName(dbS *db.DB, nameList []string) (message *tgb.MessageConfig) { ctx := context.Background() var err error page := 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.Atoi(lastItem) if err != nil { fmt.Println(err) } nameList = nameList[:len(nameList)-1] if pageInt < 20 { page = pageInt } } rows := &info.MultipleResults{} message = &tgb.MessageConfig{} text := strings.Join(nameList, " ") rows, err = info.GetByFTS(ctx, dbS, text, uint(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 }