package main import ( "context" "database/sql" "errors" "fmt" "log/slog" "os" "os/signal" "strings" "syscall" "time" tb "github.com/go-telegram-bot-api/telegram-bot-api/v5" "github.com/maximotejeda/us_dop_bot/broadcast" commands "github.com/maximotejeda/us_dop_bot/command" "github.com/maximotejeda/us_dop_bot/db" edb "github.com/maximotejeda/us_dop_bot/edb" "github.com/maximotejeda/us_dop_bot/query" "github.com/nats-io/nats.go" ) func main() { dbUserUri := os.Getenv("DBURIUSER") dbInstUri := os.Getenv("DBURINST") token := os.Getenv("TOKEN") natsURI := os.Getenv("NATSURI") log := slog.New(slog.NewJSONHandler(os.Stderr, nil)) nc, _ := nats.Connect(natsURI) ctx := context.Background() userDB := db.Dial(ctx, db.DEFAULT_DRIVER, dbUserUri) instDB := edb.Dial(dbInstUri, log) bot, err := tb.NewBotAPI(token) if err != nil { panic(err) } bot.Debug = false log.Info("Bot Authorized", "username", bot.Self.UserName) u := tb.NewUpdate(0) u.Timeout = 60 // bot user update channel updtChan := bot.GetUpdatesChan(u) // subs chann ch := make(chan *nats.Msg, 64) defer close(ch) sub, err := nc.ChanSubscribe("dolar-crawler", ch) if err != nil { log.Error("subscribing", "error", err.Error()) } defer sub.Drain() defer nc.Close() // exit channel sign := make(chan os.Signal, 1) signal.Notify(sign, syscall.SIGINT, syscall.SIGTERM) defer close(sign) for { select { case update := <-updtChan: usr := db.NewUser(userDB, log) _, err := usr.Get(update.SentFrom().ID) if err != nil { if errors.Is(err, sql.ErrNoRows) { usr.Add(update.SentFrom().ID) } } if update.Message != nil { msg := tb.NewMessage(update.Message.Chat.ID, "") if update.Message.Text != "" && !update.Message.IsCommand() { log.Info("update", "username", update.Message.From.UserName, "message", update.Message.Text) msg.Text = update.Message.Text msg.ReplyToMessageID = update.Message.MessageID bot.Send(msg) } else if update.Message.IsCommand() { go func(update tb.Update) { msg = commands.CommandHandler(ctx, userDB, instDB, log, update) if resp, err := bot.Request(tb.NewDeleteMessage(update.Message.From.ID, update.Message.MessageID)); err != nil || !resp.Ok { log.Error(err.Error()) } bot.Send(msg) }(update) } } else if update.CallbackQuery != nil { ctx, cancel := context.WithTimeout(ctx, 3*time.Second) go func(update tb.Update) { msg := query.QueryHandler(ctx, userDB, instDB, log, update.CallbackQuery) //del := tb.NewDeleteMessage(update.CallbackQuery.From.ID, update.CallbackQuery.Message.MessageID) if resp, err := bot.Request(tb.NewDeleteMessage(update.CallbackQuery.From.ID, update.CallbackQuery.Message.MessageID)); err != nil || !resp.Ok { log.Error(err.Error()) } if msg != nil { if _, err := bot.Send(msg); err != nil { log.Error(err.Error()) } } else { data := update.CallbackQuery.Data dataList := strings.Split(data, "&") dataMap := map[string]string{} for _, val := range dataList { subData := strings.Split(val, "=") dataMap[subData[0]] = subData[1] } queryinf := tb.CallbackConfig{} name := dataMap["name"] if _, ok := dataMap["subs"]; ok { queryinf.Text = fmt.Sprintf("Te haz suscrito a %s:\nRecibiras un mensaje cuando cambie el precio del dolar.", name) } else if _, ok := dataMap["unsubs"]; ok { queryinf.Text = fmt.Sprintf("Haz eliminado a %s de tus suscripciones\nNo recibiras notificaciones de %s", name, name) } else if _, ok := dataMap["reset"]; ok { queryinf.Text = "Haz eliminado todas tus suscripciones" } if queryinf.Text != "" { queryinf.ShowAlert = true queryinf.CallbackQueryID = update.CallbackQuery.ID if resp, err := bot.Request(queryinf); err != nil || !resp.Ok { log.Error(err.Error()) } } } cancel() }(update) } case message := <-ch: // we are outside update so we will be querying db to // get users interested in specific updates ex bpd, brd, apa // userID inst=> comma separated string msgList := broadcast.SendList(ctx, userDB, log, message.Data) //log.Info(string(message.Data)) for _, msg := range msgList { go bot.Send(msg) } case <-sign: log.Error("killing app due to syscall ") os.Exit(1) } } }