package bot import ( "context" "fmt" "strings" "time" "git.dev.m-and-m.ovh/mderasse/tesla/alert" "git.dev.m-and-m.ovh/mderasse/tesla/api" log "github.com/sirupsen/logrus" tele "gopkg.in/telebot.v3" ) var apiClient *api.Client // Init will initialize telegram bot. func Init(alertChan chan api.Availability) { log.Info("Starting bot initialization") log.Debug("Loading bot configuration") config, err := initBotConfig() if err != nil { log.Fatalf("Fail to initialize bot configuration. Error: %s", err.Error()) } apiClient, err = api.NewClient() if err != nil { log.Fatalf("Fail to instantiate the HTTP Client. Error: %s", err.Error()) } pref := tele.Settings{ Token: config.Token, Poller: &tele.LongPoller{Timeout: 10 * time.Second}, ParseMode: tele.ModeMarkdownV2, } bot, err := tele.NewBot(pref) if err != nil { log.Fatal(err) return } log.Debug("Initializing bot middlewares") initMiddlewares(bot, config) log.Debug("Initializing bot commands") initCommands(bot, config) log.Debug("Launching alert handler") go handleAlert(bot, config, alertChan) bot.Start() } func handleAlert(bot *tele.Bot, config *botConfig, alertChan chan api.Availability) { for availability := range alertChan { log.Warn("ALLERLRTEFDF") for _, chatId := range config.AlertChatIds { log.Infof("Sending alert to chat %d", chatId) _, err := bot.Send( tele.ChatID(chatId), fmt.Sprintf( "ALERT\\!\\! Found a Tesla Long Range in *%s* color is: *%d* €", strings.Join(availability.Paint, " and "), availability.Price, ), ) if err != nil { log.Warnf("Fail to send alert message. Error: %s", err.Error()) } } } } func initMiddlewares(bot *tele.Bot, config *botConfig) { log.Infof("Trusting the following chats: %v", config.WhiteListChatIds) bot.Use( middlewareAllowChat(config.WhiteListChatIds...), ) } func middlewareAllowChat(chatIds ...int64) tele.MiddlewareFunc { return func(next tele.HandlerFunc) tele.HandlerFunc { return func(c tele.Context) error { for _, chat := range chatIds { if chat == c.Chat().ID { return next(c) } } return nil } } } func initCommands(bot *tele.Bot, config *botConfig) { bot.Handle(tele.OnText, func(c tele.Context) error { msg := c.Text() if c.Chat().ID < 0 { if !strings.HasPrefix(msg, fmt.Sprintf("@%s", config.BotName)) { return nil } msg = strings.TrimPrefix(msg, fmt.Sprintf("@%s ", config.BotName)) } log.Debugf("receive telegram message: %s", msg) switch strings.ToLower(msg) { case "help": return help(c) case "price": return price(c) case "list": return list(c) default: return home(c) } }) bot.Handle(&tele.Btn{Unique: "list"}, list) bot.Handle(&tele.Btn{Unique: "price"}, price) bot.Handle(&tele.Btn{Unique: "help"}, help) bot.Handle(&tele.Btn{Unique: "home"}, home) } func home(c tele.Context) error { return c.EditOrReply( "Welcome to Tesla Alerter\\. What can i do for you ?", &homeMenu, ) } func help(c tele.Context) error { return c.EditOrReply( fmt.Sprintf(`I'm a bot that have for main objective to inform you about tesla price\. I will also send you alert when tesla car are at a price under %d€`, alert.PriceAlert), &helpMenu, ) } func price(c tele.Context) error { availabilities, err := apiClient.GetAvailabilities(context.Background(), &api.AvailabilityParams{ Query: carFilter, Count: 1, }) if err != nil { log.Warnf("Fail to retrieve availability from tesla website. Error: %s", err.Error()) return c.Send("Fail to retrieve availability from tesla website :(") } return c.Reply( fmt.Sprintf("The lowest price currently found for a *Tesla Long Range* in *%s* color is: *%d* €", strings.Join(availabilities.Results[0].Paint, " and "), availabilities.Results[0].Price, ), ) } func list(c tele.Context) error { availabilities, err := apiClient.GetAvailabilities(context.Background(), &api.AvailabilityParams{ Query: carFilter, Count: 30, }) if err != nil { log.Warnf("Fail to retrieve availability from tesla website. Error: %s", err.Error()) return c.Send("Fail to retrieve availability from tesla website :(") } availabilitiesStr := fmt.Sprintf("Found *%s* cars\n", availabilities.TotalMatchesFound) for _, availability := range availabilities.Results { availabilitiesStr = fmt.Sprintf( "%sTesla Long Range, color *%s* available in *%s* for *%d*€\n", availabilitiesStr, strings.Join(availability.Paint, " and "), strings.ReplaceAll(availability.City, "-", "\\-"), availability.Price, ) } return c.Reply(availabilitiesStr) }