loadmaster2k/cmd/bot.go
2020-10-28 15:35:21 +01:00

122 lines
2.7 KiB
Go

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{}
tMessage.WriteString("Hallenauslastung (" + time.Now().Format("2006-01-02 15:04") + "):\n" )
for _, tL := range loads {
tMessage.WriteString(fmt.Sprintf("*%v*: %v%% (%v)\n", tL.Area.Name, tL.Load, tL.Status))
}
for _, tChan := range C.Bot.Channels {
if tChan.Id != 0 {
if tChan.Message != 0 {
// edit
tBot.EditMessageText(tChan.Id, tChan.Message, tMessage.String())
} 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
}