maximo tejeda ceb402a65d
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 5s
INITIAL COMMIT
2024-07-21 11:40:07 -04:00

216 lines
5.7 KiB
Go

package message
import (
"fmt"
"log/slog"
"regexp"
"strconv"
"strings"
"sync"
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
"github.com/maximotejeda/us_dop_bot/internal/application/domain"
"github.com/maximotejeda/us_dop_bot/internal/application/static"
"github.com/maximotejeda/us_dop_bot/internal/ports"
)
var ChatPool *sync.Pool
type Message struct {
bot *tgbotapi.BotAPI
update *tgbotapi.Update
msg *tgbotapi.MessageConfig
log *slog.Logger
dolar ports.DolarService
user ports.UserService
}
// NewMessage
// Factory for message handler
func NewMessage(bot *tgbotapi.BotAPI, update *tgbotapi.Update, dolar ports.DolarService, user ports.UserService) *Message {
if ChatPool == nil {
ChatPool = &sync.Pool{
New: func() any { return &Message{} },
}
for i := 0; i < 20; i++ {
ChatPool.Put(ChatPool.New())
}
}
log := slog.Default()
log = log.With("function", "message", "chat", update.Message.Chat.ID, "userid", update.Message.From.ID, "username", update.Message.From.UserName)
message := ChatPool.Get().(*Message)
message.update = update
message.bot = bot
message.log = log
message.dolar = dolar
message.user = user
return message
}
// Empty
// Returns pointer to pool
func (m *Message) Empty() {
m.update = nil
m.msg = nil
m.log = nil
m.dolar = nil
m.user = nil
ChatPool.Put(m)
}
// Send
// Process message sending to bot
func (m *Message) Send() {
defer m.Empty()
m.bot.Send(m.msg)
}
// Handler
// Manage features for messages
func (m *Message) Handler() {
msg := tgbotapi.NewMessage(m.update.Message.Chat.ID, "")
m.msg = &msg
msgtext := static.RemoveAccent(m.update.Message.Text)
re := regexp.MustCompile(`(?P<operacion>([cC]omprar?\s?(me)?|[vV]en(de)?(r)?(ta)?\s?(me)?))\s(?P<cantidad>[0-9.]{1,8})\s(?P<moneda>(dolar(e)?(s)?|peso(s)?|dollars?))\s?(?P<institucion>(.*))?`)
match := re.FindStringSubmatch(msgtext)
if len(match) != 0 {
operacion := match[1]
operacion = strings.ToLower(operacion)
cantidadStr := match[8]
cantidad, err := strconv.ParseFloat(cantidadStr, 64)
if err != nil {
m.log.Error("converting to float cantidad", "error", err)
m.msg.Text = "cantidad no reconocidad " + cantidadStr
m.Send()
return
}
moneda := match[9]
moneda = strings.ToLower(moneda)
institucion := match[14]
institucion = strings.ToLower(institucion)
switch {
case strings.Contains(operacion, "compra"):
txt := m.Compra(cantidad, moneda, institucion)
m.msg.Text = txt
case strings.Contains(operacion, "vend"):
txt := m.Venta(cantidad, moneda, institucion)
m.msg.Text = txt
default:
m.msg.Text = "operacion no reconocida"
}
m.Send()
}
}
func (m *Message) Compra(cantidad float64, moneda, institucion string) string {
txt := ""
inst := static.NewInstList()
list := []*domain.History{}
if institucion == "" {
brd, bp, bhd, bcd := m.getPrincipalBank()
list = []*domain.History{brd, bp, bhd, bcd}
} else {
txtList := inst.GetName(institucion)
if len(txtList) <= 0 {
txt = "no institution with name " + institucion
return txt
} else {
for _, v := range txtList {
i, err := m.dolar.GetLatest(v.Name)
if err != nil {
m.log.Error("getting latest", "inst", v, "error", err)
continue
}
list = append(list, i)
}
}
}
if strings.Contains(moneda, "peso") {
txt = fmt.Sprintf("Comprando dolares \nRD.$ %.2f pesos:\n", cantidad)
for _, it := range list {
compra := cantidad / it.Venta
txt = txt + fmt.Sprintf(" %s \t->\t USD$. %.2f\n", inst.GetAbbrev(it.Institution.Name), compra)
}
} else if strings.Contains(moneda, "dol") {
txt = fmt.Sprintf("Comprando %.2f dolares:\n", cantidad)
for _, it := range list {
compra := cantidad * it.Venta
txt = txt + fmt.Sprintf(" %s \t->\t RD$. %.2f\n", inst.GetAbbrev(it.Institution.Name), compra)
}
}
return txt
}
func (m *Message) Venta(cantidad float64, moneda, institucion string) string {
txt := ""
list := []*domain.History{}
inst := static.NewInstList()
if institucion == "" {
brd, bp, bhd, bcd := m.getPrincipalBank()
list = []*domain.History{brd, bp, bhd, bcd}
} else {
txtList := inst.GetName(institucion)
if len(txtList) <= 0 {
txt = "no institution with name " + institucion
return txt
} else {
for _, v := range txtList {
i, err := m.dolar.GetLatest(v.Name)
if err != nil {
m.log.Error("getting latest", "inst", v, "error", err)
continue
}
list = append(list, i)
}
}
}
if len(list) <= 0 {
return "no institutions found with name " + institucion
}
if strings.Contains(moneda, "peso") {
txt = fmt.Sprintf("Vendiendo equivalente a RD.$ %.2f pesos:\n", cantidad)
for _, it := range list {
venta := cantidad / it.Compra
txt = txt + fmt.Sprintf(" %s \t->\t USD$. %.2f\n", inst.GetAbbrev(it.Institution.Name), venta)
}
} else if strings.Contains(moneda, "dol") {
txt = fmt.Sprintf("Vendiendo USD.$ %.2f dolares\n", cantidad)
for _, it := range list {
venta := cantidad * it.Compra
txt = txt + fmt.Sprintf(" %s \t->\t RD$. %.2f\n", inst.GetAbbrev(it.Institution.Name), venta)
}
}
return txt
}
func (m *Message) getPrincipalBank() (brd, bp, bhd, bcd *domain.History) {
// principales bancos
// bhd reservas popular central
brd, err := m.dolar.GetLatest("banreservas")
if err != nil {
m.log.Error("query latest for banreservas", "error", err)
}
bp, err = m.dolar.GetLatest("banco popular")
if err != nil {
m.log.Error("query latest for banco popular")
}
bhd, err = m.dolar.GetLatest("banco hipotecario dominicano")
if err != nil {
m.log.Error("query latest for banreservas")
}
bcd, err = m.dolar.GetLatest("banco central dominicano")
if err != nil {
m.log.Error("query latest for banreservas")
}
return brd, bp, bhd, bcd
}