Tesla/bot/bot.go

187 lines
4.5 KiB
Go
Raw Normal View History

2023-06-05 13:41:48 +00:00
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...),
2023-06-05 13:41:48 +00:00
)
}
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
}
}
}
2023-06-05 13:41:48 +00:00
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)
}