package main import ( "encoding/json" "fmt" "regexp" "strconv" "time" tb "gopkg.in/tucnak/telebot.v2" ) type Bot struct { bot *tb.Bot Config *TelegramConfig } func (b *Bot) Start() { var err error b.bot, err = tb.NewBot(tb.Settings{ Token: b.Config.Token, URL: b.Config.URL, Poller: &tb.LongPoller{Timeout: 10 * time.Second}, }) failError(err, "Bot.Start() : registering bot") b.BotHandlers() } func (b *Bot) SendUser(id int64, msg string) { u := tb.User{ ID: int(id), } _, err := b.bot.Send(&u, msg) logErrorDebug(err, "Bot.SendUser()") } func (b *Bot) SendChat(chatID int64, text string) { opt := tb.SendOptions{ ParseMode: tb.ModeDefault, } ch := tb.Chat{ ID: chatID, } _, err := b.bot.Send(&ch, text, &opt) logErrorDebug(err, "Bot.SendChat()") } func (b *Bot) BotHandlers() { b.bot.Handle("/pause", botPause) b.bot.Handle("/unpause", botUnpause) b.bot.Handle("/register", botRegister) b.bot.Handle("/delete", botDelete) b.bot.Handle("/companies", botCompanies) b.bot.Handle("/clients", botClients) b.bot.Handle("/players", botPlayers) b.bot.Handle(tb.OnPhoto, botPhoto) b.bot.Handle(tb.OnChannelPost, botChannelPost) b.bot.Handle(tb.OnQuery, botQuery) b.bot.Handle(tb.OnText, botText) b.bot.Handle(tb.OnDocument, botDocument) go func() { time.Sleep(time.Second) b.SendUser(b.Config.AdminID, fmt.Sprintf("Started (%s)", version)) }() b.bot.Start() } func botPause(m *tb.Message) { for userID, cc := range cfg.Clients { if userID == m.Sender.ID { if co, ok := srv.Status.Companies[cc.CompanyID]; ok { if clt, ok2 := srv.Status.Clients[co.ClientID]; ok2 { clt.Paused = true if !srv.Status.Paused { srv.Pause() } else { bot.SendChat(bot.Config.ChatID, "Game already paused.") } botPlayers(m) return } } } } botPlayers(m) bot.SendChat(bot.Config.ChatID, "You are not playing and cannot pause the game.") return } func botUnpause(m *tb.Message) { PrintText(m) for userID, cc := range cfg.Clients { if userID == m.Sender.ID { if co, ok := srv.Status.Companies[cc.CompanyID]; ok { if clt, ok2 := srv.Status.Clients[co.ClientID]; ok2 { clt.Paused = false if !srv.NeedPause() { srv.Unpause() } else { bot.SendChat(bot.Config.ChatID, fmt.Sprintf("Cannot unpause : %s", srv.NeedPauseReason())) } botPlayers(m) return } } } } botPlayers(m) bot.SendChat(bot.Config.ChatID, "You are not playing and cannot unpause the game.") return } func botDelete(m *tb.Message) { logInfoDebug("[%d] %s(%d) | %s(%d) : delete : %s\n", m.ID, m.Chat.Title, m.Chat.ID, m.Sender.Username, m.Sender.ID, m.Text) if m.Sender.ID == int(bot.Config.AdminID) { r := regexp.MustCompile("/delete (?P[0-9]+)") ID64, _ := strconv.ParseInt(r.ReplaceAllString(m.Text, "${CompanyID}"), 10, 64) srv.DeleteCompany(uint8(ID64)) bot.SendChat(m.Chat.ID, "Deleting") } else { bot.SendChat(m.Chat.ID, "Not authorized to delete") } return } func botCompanies(m *tb.Message) { str := "Companies :" for k, v := range srv.Status.Companies { str = str + "\r\n" + fmt.Sprintf(" - %s (%d)", v.Name, k) } bot.SendChat(m.Chat.ID, str) } func botClients(m *tb.Message) { str := "Clients :" for k, v := range srv.Status.Clients { str = str + "\r\n" + fmt.Sprintf(" - %s (%d) : company #%d", v.Name, k, v.CompanyID) } bot.SendChat(m.Chat.ID, str) } func botPlayers(m *tb.Message) { d1 := time.Now().Sub(cfg.Game.StartDate) days := int(time.Duration(d1.Hours()) / 24) d2 := time.Duration(days+1)*(time.Hour)*24 - d1 str := fmt.Sprintf("Update in %s\r\n", d2) online := "" for _, cc := range cfg.Clients { if cc.Online { online = online + fmt.Sprintf(" - @%s (%s) : %s", cc.Username, cc.TimeLeft, srv.Status.Companies[cc.CompanyID].Name) + "\r\n" } } offline := "" for _, cc := range cfg.Clients { if _, ok := srv.Status.Companies[cc.CompanyID]; ok && !cc.Online { offline = offline + fmt.Sprintf(" - @%s (%s) : %s", cc.Username, cc.TimeLeft, srv.Status.Companies[cc.CompanyID].Name) + "\r\n" } } if len(online) > 0 { str = str + "Players online :\r\n" + online } if len(offline) > 0 { str = str + "Players offline :\r\n" + offline } bot.SendChat(m.Chat.ID, str) } func botRegister(m *tb.Message) { cc, ok := cfg.Clients[m.Sender.ID] if !ok { cc = &ClientConfig{ UserID: m.Sender.ID, Username: m.Sender.Username, CompanyID: 255, } cfg.Clients[m.Sender.ID] = cc } coList := make(map[uint8]struct{}) for coID, _ := range srv.Status.Companies { coList[coID] = struct{}{} } for _, c := range cfg.Clients { if c.CompanyID != 255 { if _, ok := coList[c.CompanyID]; !ok { logInfoAlert("botRegister : %s : no such CompanyID : %d", c.Username, c.CompanyID) c.CompanyID = 255 } else { delete(coList, c.CompanyID) } } } if len(coList) == 0 { bot.SendChat(m.Chat.ID, "No company to register") return } if len(coList) == 1 { for id, _ := range coList { cc.CompanyID = id days := int(time.Now().Sub(cfg.Game.StartDate).Hours() / 24) cc.TimeLeft = cfg.Game.StartingAllotment + cfg.Game.DailyAllotment*time.Duration(days) bot.SendChat(m.Chat.ID, fmt.Sprintf("@%s registered %s (with %s playable)", cc.Username, srv.Status.Companies[cc.CompanyID].Name, cc.TimeLeft)) return } } bot.SendChat(m.Chat.ID, "More than one company unregistered. Wait for bot update (poke @tiennou)") return } func PrintText(m *tb.Message) { logInfoDebug("[%d] %s(%d) | %s(%d) : %s\n", m.ID, m.Chat.Title, m.Chat.ID, m.Sender.Username, m.Sender.ID, m.Text) return } func botPhoto(m *tb.Message) { logInfoDebug("botPhoto :", m.Text) // photos only } func botDocument(m *tb.Message) { logInfoDebug("botDocument : %s (%d bytes)\n", m.Document.FileName, m.Document.File.FileSize) // documents only } func botChannelPost(m *tb.Message) { PrintText(m) b, _ := json.Marshal(m) logInfoDebug("botChannelPost : %s\n", string(b)) // channel posts only } func botQuery(q *tb.Query) { logInfoDebug("botQuery") // incoming inline queries } func botText(m *tb.Message) { PrintText(m) }