package cmd import ( "context" "errors" "fmt" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" "strings" "time" "udico.de/uditaren/goboter" "udico.de/uditaren/loadmaster2k/api" . "udico.de/uditaren/loadmaster2k/config" "udico.de/uditaren/terminator" ) var cBot = &cobra.Command{ Use: "bot", Short: "Run the bot", } func init() { cBot.RunE = executeBot cRoot.AddCommand(cBot) } type Load struct { Area *Area Load int Status string Err error } func (l Load) String() string { if l.Err != nil { return fmt.Sprintf("%v: error='%v'", l.Area, l.Err.Error()) } return fmt.Sprintf("%v: load=%v%%, status='%v'", l.Area, l.Load, l.Status) } func executeBot(cmd *cobra.Command, args []string) error { log.Info("Starting bot") defer log.Info("Bot done") if C.Bot.Token == "" { return errors.New("missing bot api token") } if len(C.Bot.Channels) == 0 { log.Warn("There is no channel associated to the bot.") log.Warn("Please add the bot to a channel. It will respond with a single message, which you may pin.") log.Warn("Channel and message id will be dumped to the logs") } tBot := goboter.NewTelegramBot(C.Bot.Token, "loadmaster2k") tContext, tCancelFunc := context.WithCancel(context.Background()) go tBot.LongPoll(tContext, 30) go func() { updates: for { select { case tUpdate := <- tBot.Updates: log.Infof("BOT: %v", tUpdate) case <-terminator.Terminate: tCancelFunc() break updates } } }() log.Debugf("Checking state every %v seconds", C.Bot.Interval) tTickC := time.NewTicker(time.Second * time.Duration(C.Bot.Interval)).C waiter: for { // handle here to simulate an "initial tick" log.Debug("Tick...") loads := make([]*Load, 0, 5) for i, area := range C.Areas { log.Debugf("Fetching load data for %v", area) tLoad := &Load{ Area: &C.Areas[i], } tData, err := api.FetchArea(area.Id) if err != nil { tLoad.Err = err continue } else { tLoad.Load, tLoad.Status = api.ParseAreaStatus(tData) } loads = append(loads, tLoad) log.Info(tLoad) } tMessage := &strings.Builder{} for _, tL := range loads { tMessage.WriteString(fmt.Sprintf("%v: __*%v%%*__ \\(%v\\)\n", tL.Area.Name, tL.Load, tL.Status)) } tMessage.WriteString("\\(Stand " + time.Now().Format("2006\\-01\\-02 15:04") + "\\)" ) for _, tChan := range C.Bot.Channels { if tChan.Id != 0 { if tChan.Message != 0 { // edit _, err := tBot.EditMessageText(tChan.Id, tChan.Message, tMessage.String()) if err != nil { log.WithError(err).Error("cannot update message") } } else { tMsg, err := tBot.SendMessage(tChan.Id, tMessage.String(), 0) log.WithError(err).Info(tMsg) } } } select { case <-tTickC: continue case <-terminator.Terminate: log.Info("Terminating bot") break waiter } } return nil }