From 706dc3e944acee4dea58ca0ead2d042894092302 Mon Sep 17 00:00:00 2001 From: Vladimir Hodakov Date: Sat, 23 Dec 2017 01:40:36 +0400 Subject: [PATCH] Reminders for league. Now just reminders, without attack button --- cmd/i2_bot/i2_bot.go | 4 + lib/appcontext/appcontext.go | 8 ++ lib/config/config.go | 4 +- lib/dbmapping/alarms.go | 16 +++ lib/migrations/30_create_alarms.go | 38 ++++++ lib/migrations/migrations.go | 1 + lib/pinner/exported.go | 2 - lib/pinner/pinner.go | 116 ++++-------------- lib/pinner/pinnerinterface/pinnerinterface.go | 4 +- lib/reminder/exported.go | 30 +++++ lib/reminder/reminder.go | 73 +++++++++++ .../reminderinterface/reminderinterface.go | 21 ++++ lib/reminder/responders.go | 25 ++++ lib/reminder/sender.go | 32 +++++ lib/reminder/updaters.go | 60 +++++++++ lib/router/callback_request.go | 29 +++++ lib/router/private_request.go | 3 + lib/router/routerinterface/routerinterface.go | 1 + lib/talkers/help.go | 31 ++--- 19 files changed, 381 insertions(+), 117 deletions(-) create mode 100644 lib/dbmapping/alarms.go create mode 100644 lib/migrations/30_create_alarms.go create mode 100644 lib/reminder/exported.go create mode 100644 lib/reminder/reminder.go create mode 100644 lib/reminder/reminderinterface/reminderinterface.go create mode 100644 lib/reminder/responders.go create mode 100644 lib/reminder/sender.go create mode 100644 lib/reminder/updaters.go create mode 100644 lib/router/callback_request.go diff --git a/cmd/i2_bot/i2_bot.go b/cmd/i2_bot/i2_bot.go index 829091e..6b4c7a3 100644 --- a/cmd/i2_bot/i2_bot.go +++ b/cmd/i2_bot/i2_bot.go @@ -13,6 +13,7 @@ import ( "lab.pztrn.name/fat0troll/i2_bot/lib/orders" "lab.pztrn.name/fat0troll/i2_bot/lib/pinner" "lab.pztrn.name/fat0troll/i2_bot/lib/pokedexer" + "lab.pztrn.name/fat0troll/i2_bot/lib/reminder" "lab.pztrn.name/fat0troll/i2_bot/lib/router" "lab.pztrn.name/fat0troll/i2_bot/lib/squader" "lab.pztrn.name/fat0troll/i2_bot/lib/statistics" @@ -44,6 +45,7 @@ func main() { users.New(c) statistics.New(c) orders.New(c) + reminder.New(c) c.Log.Info("=======================") c.Log.Info("= i2_bot initialized. =") @@ -66,6 +68,8 @@ func main() { } } else if update.InlineQuery != nil { c.Router.RouteInline(&update) + } else if update.CallbackQuery != nil { + c.Router.RouteCallback(&update) } else if update.ChosenInlineResult != nil { c.Log.Debug(update.ChosenInlineResult.ResultID) } else { diff --git a/lib/appcontext/appcontext.go b/lib/appcontext/appcontext.go index ae7fbfb..50e3ed9 100644 --- a/lib/appcontext/appcontext.go +++ b/lib/appcontext/appcontext.go @@ -16,6 +16,7 @@ import ( "lab.pztrn.name/fat0troll/i2_bot/lib/orders/ordersinterface" "lab.pztrn.name/fat0troll/i2_bot/lib/pinner/pinnerinterface" "lab.pztrn.name/fat0troll/i2_bot/lib/pokedexer/pokedexerinterface" + "lab.pztrn.name/fat0troll/i2_bot/lib/reminder/reminderinterface" "lab.pztrn.name/fat0troll/i2_bot/lib/router/routerinterface" "lab.pztrn.name/fat0troll/i2_bot/lib/squader/squaderinterface" "lab.pztrn.name/fat0troll/i2_bot/lib/statistics/statisticsinterface" @@ -43,6 +44,7 @@ type Context struct { Broadcaster broadcasterinterface.BroadcasterInterface Welcomer welcomerinterface.WelcomerInterface Pinner pinnerinterface.PinnerInterface + Reminder reminderinterface.ReminderInterface Chatter chatterinterface.ChatterInterface Squader squaderinterface.SquaderInterface Users usersinterface.UsersInterface @@ -137,6 +139,12 @@ func (c *Context) RegisterPinnerInterface(pi pinnerinterface.PinnerInterface) { c.Pinner.Init() } +// RegisterReminderInterface registering reminder interface in application +func (c *Context) RegisterReminderInterface(ri reminderinterface.ReminderInterface) { + c.Reminder = ri + c.Reminder.Init() +} + // RegisterForwarderInterface registers forwarder interface in application func (c *Context) RegisterForwarderInterface(fi forwarderinterface.ForwarderInterface) { c.Forwarder = fi diff --git a/lib/config/config.go b/lib/config/config.go index 4c44193..28eec17 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -10,8 +10,8 @@ import ( "path/filepath" ) -// VERSION is the urrent bot's version -const VERSION = "0.6" +// VERSION is the current bot's version +const VERSION = "0.6.5" // DatabaseConnection handles database connection settings in config.yaml type DatabaseConnection struct { diff --git a/lib/dbmapping/alarms.go b/lib/dbmapping/alarms.go new file mode 100644 index 0000000..8caa275 --- /dev/null +++ b/lib/dbmapping/alarms.go @@ -0,0 +1,16 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package dbmapping + +import ( + "time" +) + +// Alarm is a struct, which represents `alarms` table item in databse. +type Alarm struct { + ID int `db:"id"` + PlayerID int `db:"player_id"` + TurnirNumber int `db:"turnir_number"` // From 1 to 12 + CreatedAt time.Time `db:"created_at"` +} diff --git a/lib/migrations/30_create_alarms.go b/lib/migrations/30_create_alarms.go new file mode 100644 index 0000000..e533041 --- /dev/null +++ b/lib/migrations/30_create_alarms.go @@ -0,0 +1,38 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package migrations + +import ( + "database/sql" +) + +// CreateAlarmsUp creates `alarms` table +func CreateAlarmsUp(tx *sql.Tx) error { + request := "CREATE TABLE `alarms` (" + request += "`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID настройки оповещения'," + request += "`player_id` int(11) NOT NULL COMMENT 'Игрок, которому отправляется оповещение'," + request += "`turnir_number` int(11) NOT NULL COMMENT 'Номер турнира (от 1 до 12)'," + request += "`created_at` datetime NOT NULL COMMENT 'Добавлен в базу'," + request += "PRIMARY KEY (`id`)," + request += "UNIQUE KEY `id` (`id`)," + request += "KEY `alarms_player_id` (`player_id`)," + request += "KEY `alarms_turnir_number` (`turnir_number`)" + request += ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Оповещения на Турнир лиг'" + _, err := tx.Exec(request) + if err != nil { + return err + } + + return nil +} + +// CreateAlarmsDown drops `alarms` table +func CreateAlarmsDown(tx *sql.Tx) error { + _, err := tx.Exec("DROP TABLE `alarms`") + if err != nil { + return err + } + + return nil +} diff --git a/lib/migrations/migrations.go b/lib/migrations/migrations.go index 5f6058b..2d63db4 100644 --- a/lib/migrations/migrations.go +++ b/lib/migrations/migrations.go @@ -40,6 +40,7 @@ func (m *Migrations) Init() { goose.AddNamedMigration("27_add_new_weapon.go", AddNewWeaponUp, AddNewWeaponDown) goose.AddNamedMigration("28_fix_locations.go", FixLocationsUp, FixLocationsDown) goose.AddNamedMigration("29_fix_leagues_names.go", FixLeaguesNamesUp, FixLeaguesNamesDown) + goose.AddNamedMigration("30_create_alarms.go", CreateAlarmsUp, CreateAlarmsUp) } // Migrate migrates database to current version diff --git a/lib/pinner/exported.go b/lib/pinner/exported.go index 231d2ea..f6170c5 100644 --- a/lib/pinner/exported.go +++ b/lib/pinner/exported.go @@ -25,6 +25,4 @@ func New(ac *appcontext.Context) { // Init is an initialization function for pinner func (p *Pinner) Init() { c.Log.Info("Initializing Pinner...") - - c.Cron.AddFunc("0 55 4-23/2 * * *", p.PinBattleAlert) } diff --git a/lib/pinner/pinner.go b/lib/pinner/pinner.go index b2d511c..52d2214 100644 --- a/lib/pinner/pinner.go +++ b/lib/pinner/pinner.go @@ -5,28 +5,17 @@ package pinner import ( "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" "strconv" "strings" ) -// PinMessageToAllChats pins message to all groups where bot exist -func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string { +func (p *Pinner) execMassMessagePin(update *tgbotapi.Update, groupChats []dbmapping.Chat) string { messageToPin := update.Message.CommandArguments() - - if messageToPin == "" { - return "fail" - } - - groupChats, ok := c.Chatter.GetAllGroupChats() - if !ok { - return "fail" - } - for i := range groupChats { if groupChats[i].ChatType == "supergroup" { message := messageToPin + "\n\n" - message += "© " + update.Message.From.FirstName + " " + update.Message.From.LastName - message += " (@" + update.Message.From.UserName + ")" + message += "© " + c.Users.GetPrettyName(update.Message.From) msg := tgbotapi.NewMessage(groupChats[i].TelegramID, message) msg.ParseMode = "Markdown" @@ -60,7 +49,7 @@ func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string { } } - message := "*Ваше сообщение отправлено и запинено во все чаты, где сидит бот.*\n\n" + message := "*Ваше сообщение отправлено и запинено в чаты, где сидит бот.*\n\n" message += "Текст отправленного сообщения:\n\n" message += messageToPin @@ -72,6 +61,22 @@ func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string { return "ok" } +// PinMessageToAllChats pins message to all groups where bot exist +func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string { + messageToPin := update.Message.CommandArguments() + + if messageToPin == "" { + return "fail" + } + + groupChats, ok := c.Chatter.GetAllGroupChats() + if !ok { + return "fail" + } + + return p.execMassMessagePin(update, groupChats) +} + // PinMessageToSomeChats pins message to selected groups where bot exist func (p *Pinner) PinMessageToSomeChats(update *tgbotapi.Update) string { commandArgs := update.Message.CommandArguments() @@ -101,84 +106,5 @@ func (p *Pinner) PinMessageToSomeChats(update *tgbotapi.Update) string { } c.Log.Debug("Got " + strconv.Itoa(len(groupChats)) + " group chats...") - for i := range groupChats { - if groupChats[i].ChatType == "supergroup" { - message := messageToPin + "\n\n" - message += "© " + update.Message.From.FirstName + " " + update.Message.From.LastName - message += " (@" + update.Message.From.UserName + ")" - - msg := tgbotapi.NewMessage(groupChats[i].TelegramID, message) - msg.ParseMode = "Markdown" - - pinnableMessage, err := c.Bot.Send(msg) - if err != nil { - c.Log.Error(err.Error()) - - message := "*Ваше сообщение не отправлено.*\n\n" - message += "Обычно это связано с тем, что нарушена разметка Markdown. " - message += "К примеру, если вы хотели использовать нижнее\\_подчёркивание, то печатать его надо так — \\\\_. То же самое касается всех управляющих разметкой символов в Markdown в случае, если вы их хотите использовать как текст, а не как управляющий символ Markdown." - - msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - - return "fail" - } - - pinChatMessageConfig := tgbotapi.PinChatMessageConfig{ - ChatID: pinnableMessage.Chat.ID, - MessageID: pinnableMessage.MessageID, - DisableNotification: true, - } - - _, err = c.Bot.PinChatMessage(pinChatMessageConfig) - if err != nil { - c.Log.Error(err.Error()) - } - } - } - - message := "*Ваше сообщение отправлено и запинено во все чаты, где сидит бот.*\n\n" - message += "Текст отправленного сообщения:\n\n" - message += messageToPin - - msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - - return "ok" -} - -// PinBattleAlert pins to all squads 'battle alert' at :55 of every even hour -// Even hours are in Moscow timezone -func (p *Pinner) PinBattleAlert() { - c.Log.Debug("> Cron invoked PinBattleAlert()") - - message := "*Турнир Лиги покемемов состоится через 5 минут!*\nБоевая готовность, отряд!" - groupChats, _ := c.Squader.GetAllSquadChats() - - for i := range groupChats { - if groupChats[i].ChatType == "supergroup" { - msg := tgbotapi.NewMessage(groupChats[i].TelegramID, message) - msg.ParseMode = "Markdown" - - pinnableMessage, err := c.Bot.Send(msg) - if err != nil { - c.Log.Error(err.Error()) - } - - pinChatMessageConfig := tgbotapi.PinChatMessageConfig{ - ChatID: pinnableMessage.Chat.ID, - MessageID: pinnableMessage.MessageID, - DisableNotification: false, - } - - _, err = c.Bot.PinChatMessage(pinChatMessageConfig) - if err != nil { - c.Log.Error(err.Error()) - } - } - } + return p.execMassMessagePin(update, groupChats) } diff --git a/lib/pinner/pinnerinterface/pinnerinterface.go b/lib/pinner/pinnerinterface/pinnerinterface.go index efd8a02..b8bb394 100644 --- a/lib/pinner/pinnerinterface/pinnerinterface.go +++ b/lib/pinner/pinnerinterface/pinnerinterface.go @@ -7,12 +7,10 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) -// PinnerInterface implements Pinner for importing via appcontex +// PinnerInterface implements Pinner for importing via appcontext type PinnerInterface interface { Init() - PinBattleAlert() - PinMessageToSomeChats(update *tgbotapi.Update) string PinMessageToAllChats(update *tgbotapi.Update) string } diff --git a/lib/reminder/exported.go b/lib/reminder/exported.go new file mode 100644 index 0000000..2e5eb31 --- /dev/null +++ b/lib/reminder/exported.go @@ -0,0 +1,30 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminder + +import ( + "lab.pztrn.name/fat0troll/i2_bot/lib/appcontext" + "lab.pztrn.name/fat0troll/i2_bot/lib/reminder/reminderinterface" +) + +var ( + c *appcontext.Context +) + +// Reminder is a function-handling struct for Reminder +type Reminder struct{} + +// New is a appcontext initialization function +func New(ac *appcontext.Context) { + c = ac + r := &Reminder{} + c.RegisterReminderInterface(reminderinterface.ReminderInterface(r)) +} + +// Init is an initialization function for reminder +func (r *Reminder) Init() { + c.Log.Info("Initializing Reminder...") + + c.Cron.AddFunc("0 55 0-23/2 * * *", r.SendReminders) +} diff --git a/lib/reminder/reminder.go b/lib/reminder/reminder.go new file mode 100644 index 0000000..97ab4a6 --- /dev/null +++ b/lib/reminder/reminder.go @@ -0,0 +1,73 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminder + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" + "strconv" +) + +func (r *Reminder) getRemindersForUser(playerRaw *dbmapping.Player) ([]dbmapping.Alarm, bool) { + alarmsList := []dbmapping.Alarm{} + + err := c.Db.Select(&alarmsList, "SELECT * FROM alarms WHERE player_id=?", playerRaw.ID) + if err != nil { + c.Log.Error(err.Error()) + return alarmsList, false + } + + return alarmsList, true +} + +func (r *Reminder) formatRemindersButtons(playerRaw *dbmapping.Player) tgbotapi.InlineKeyboardMarkup { + currentAlarms, _ := r.getRemindersForUser(playerRaw) + + alarmExist := make(map[string]string) + for i := range currentAlarms { + alarmExist[strconv.Itoa(currentAlarms[i].TurnirNumber)] = "enabled" + } + + keyboard := tgbotapi.InlineKeyboardMarkup{} + rows := make(map[int][]tgbotapi.InlineKeyboardButton) + rows[0] = []tgbotapi.InlineKeyboardButton{} + rows[1] = []tgbotapi.InlineKeyboardButton{} + rows[2] = []tgbotapi.InlineKeyboardButton{} + for i := 1; i <= 12; i++ { + hours := 2 * (i - 1) + if alarmExist[strconv.Itoa(i)] != "" { + hoursStr := "✅ " + hoursStr += strconv.Itoa(hours) + ":55" + btn := tgbotapi.NewInlineKeyboardButtonData(hoursStr, "disable_reminder_"+strconv.Itoa(i)) + rows[(i-1)/4] = append(rows[(i-1)/4], btn) + } else { + hoursStr := "🚫 " + hoursStr += strconv.Itoa(hours) + ":55" + btn := tgbotapi.NewInlineKeyboardButtonData(hoursStr, "enable_reminder_"+strconv.Itoa(i)) + rows[(i-1)/4] = append(rows[(i-1)/4], btn) + } + } + + for i := range rows { + keyboard.InlineKeyboard = append(keyboard.InlineKeyboard, rows[i]) + } + + return keyboard +} + +func (r *Reminder) formatRemindersMessageText(playerRaw *dbmapping.Player) string { + message := "*Ваши напоминания о битвах:*\n" + message += "За пять минут до битвы бот может присылать вам в личные сообщения напоминание о том, " + message += "что битва скоро состоится, и стоит встать на атаку.\n" + message += "Кнопками ниже вы можете настроить, к каким из битв вас оповещать. Время московское.\n\n" + + currentAlarms, ok := r.getRemindersForUser(playerRaw) + if !ok { + message += "Не удалось получить настройки оповещений из базы. Ошибка." + } else { + message += "Установлено оповещений: " + strconv.Itoa(len(currentAlarms)) + } + + return message +} diff --git a/lib/reminder/reminderinterface/reminderinterface.go b/lib/reminder/reminderinterface/reminderinterface.go new file mode 100644 index 0000000..51de280 --- /dev/null +++ b/lib/reminder/reminderinterface/reminderinterface.go @@ -0,0 +1,21 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminderinterface + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" +) + +// ReminderInterface implements Reminder for importing via appcontext +type ReminderInterface interface { + Init() + + AlarmsList(update *tgbotapi.Update, playerRaw *dbmapping.Player) string + + CreateAlarmSetting(update *tgbotapi.Update, playerRaw *dbmapping.Player) string + DestroyAlarmSetting(update *tgbotapi.Update, playerRaw *dbmapping.Player) string + + SendReminders() +} diff --git a/lib/reminder/responders.go b/lib/reminder/responders.go new file mode 100644 index 0000000..fa568ba --- /dev/null +++ b/lib/reminder/responders.go @@ -0,0 +1,25 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminder + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" +) + +// AlarmsList lists all alarms for user with buttons to enable/disable each of available alarms +func (r *Reminder) AlarmsList(update *tgbotapi.Update, playerRaw *dbmapping.Player) string { + msg := tgbotapi.MessageConfig{} + msg.Text = r.formatRemindersMessageText(playerRaw) + msg.ParseMode = "Markdown" + msg.ChatID = update.Message.Chat.ID + + remindersMsg, _ := c.Bot.Send(msg) + + keyboard := r.formatRemindersButtons(playerRaw) + buttonsUpdate := tgbotapi.NewEditMessageReplyMarkup(update.Message.Chat.ID, remindersMsg.MessageID, keyboard) + c.Bot.Send(buttonsUpdate) + + return "ok" +} diff --git a/lib/reminder/sender.go b/lib/reminder/sender.go new file mode 100644 index 0000000..309c550 --- /dev/null +++ b/lib/reminder/sender.go @@ -0,0 +1,32 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminder + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" + "time" +) + +// SendReminders sends reminders for users about coming league tournament +func (r *Reminder) SendReminders() { + currentHour := time.Now().Hour() + nextTournamentID := (currentHour / 2) + 1 + + playersRaw := []dbmapping.Player{} + err := c.Db.Select(&playersRaw, "SELECT p.* FROM players p, alarms a WHERE a.turnir_number=? AND a.player_id = p.id GROUP BY p.id", nextTournamentID) + if err != nil { + c.Log.Error(err.Error()) + } + + for i := range playersRaw { + message := "*Турнир Лиг покемемов состоится через пять минут!*\n" + message += "Вперёд, за опытом и деньгами! Выстави атаку и жди результата!" + + msg := tgbotapi.NewMessage(int64(playersRaw[i].TelegramID), message) + msg.ParseMode = "Markdown" + + c.Bot.Send(msg) + } +} diff --git a/lib/reminder/updaters.go b/lib/reminder/updaters.go new file mode 100644 index 0000000..2b27a4d --- /dev/null +++ b/lib/reminder/updaters.go @@ -0,0 +1,60 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package reminder + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" + "strconv" + "strings" + "time" +) + +// CreateAlarmSetting creates alarm setting for user +func (r *Reminder) CreateAlarmSetting(update *tgbotapi.Update, playerRaw *dbmapping.Player) string { + turnirNumber := strings.TrimPrefix(update.CallbackQuery.Data, "enable_reminder_") + turnirNumberInt, err := strconv.Atoi(turnirNumber) + if err != nil { + c.Log.Error(err.Error()) + return "fail" + } + + alarm := dbmapping.Alarm{} + alarm.PlayerID = playerRaw.ID + alarm.TurnirNumber = turnirNumberInt + alarm.CreatedAt = time.Now().UTC() + + _, err = c.Db.NamedExec("INSERT INTO `alarms` VALUES(NULL, :player_id, :turnir_number, :created_at)", &alarm) + if err != nil { + c.Log.Error(err.Error()) + return "fail" + } + + keyboard := r.formatRemindersButtons(playerRaw) + buttonsUpdate := tgbotapi.NewEditMessageReplyMarkup(update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Message.MessageID, keyboard) + c.Bot.Send(buttonsUpdate) + + return "ok" +} + +// DestroyAlarmSetting creates alarm setting for user +func (r *Reminder) DestroyAlarmSetting(update *tgbotapi.Update, playerRaw *dbmapping.Player) string { + turnirNumber := strings.TrimPrefix(update.CallbackQuery.Data, "disable_reminder_") + turnirNumberInt, err := strconv.Atoi(turnirNumber) + if err != nil { + c.Log.Error(err.Error()) + return "fail" + } + + _, err = c.Db.Exec(c.Db.Rebind("DELETE FROM `alarms` WHERE player_id=? AND turnir_number=?"), playerRaw.ID, turnirNumberInt) + if err != nil { + c.Log.Error(err.Error()) + } + + keyboard := r.formatRemindersButtons(playerRaw) + buttonsUpdate := tgbotapi.NewEditMessageReplyMarkup(update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Message.MessageID, keyboard) + c.Bot.Send(buttonsUpdate) + + return "ok" +} diff --git a/lib/router/callback_request.go b/lib/router/callback_request.go new file mode 100644 index 0000000..2a71e36 --- /dev/null +++ b/lib/router/callback_request.go @@ -0,0 +1,29 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package router + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "regexp" +) + +// RouteCallback routes inline requests to bot +func (r *Router) RouteCallback(update *tgbotapi.Update) string { + playerRaw, ok := c.Users.GetOrCreatePlayer(update.CallbackQuery.From.ID) + if !ok { + return "fail" + } + + var enableAlarmCallback = regexp.MustCompile("enable_reminder_(\\d+)\\z") + var disableAlarmCallback = regexp.MustCompile("disable_reminder_(\\d+)\\z") + + switch { + case enableAlarmCallback.MatchString(update.CallbackQuery.Data): + return c.Reminder.CreateAlarmSetting(update, &playerRaw) + case disableAlarmCallback.MatchString(update.CallbackQuery.Data): + return c.Reminder.DestroyAlarmSetting(update, &playerRaw) + } + + return "ok" +} diff --git a/lib/router/private_request.go b/lib/router/private_request.go index 215b3fa..009cf9d 100644 --- a/lib/router/private_request.go +++ b/lib/router/private_request.go @@ -80,6 +80,9 @@ func (r *Router) routePrivateRequest(update *tgbotapi.Update, playerRaw *dbmappi case update.Message.Command() == "best": c.Pokedexer.BestPokememesList(update, playerRaw) return "ok" + case update.Message.Command() == "reminders": + return c.Reminder.AlarmsList(update, playerRaw) + case update.Message.Command() == "send_all": if c.Users.PlayerBetterThan(playerRaw, "admin") { c.Broadcaster.AdminBroadcastMessageCompose(update, playerRaw) diff --git a/lib/router/routerinterface/routerinterface.go b/lib/router/routerinterface/routerinterface.go index ac436b4..8d8da4b 100644 --- a/lib/router/routerinterface/routerinterface.go +++ b/lib/router/routerinterface/routerinterface.go @@ -11,6 +11,7 @@ import ( type RouterInterface interface { Init() + RouteCallback(update *tgbotapi.Update) string RouteInline(update *tgbotapi.Update) string RouteRequest(update *tgbotapi.Update) string } diff --git a/lib/talkers/help.go b/lib/talkers/help.go index 607b5d3..71d5e18 100644 --- a/lib/talkers/help.go +++ b/lib/talkers/help.go @@ -52,25 +52,26 @@ func (t *Talkers) HelpMessage(update *tgbotapi.Update, playerRaw *dbmapping.Play message := "*Бот Инстинкта Enchanched.*\n\n" message += "Текущая версия: *" + config.VERSION + "*\n\n" message += "Список команд\n\n" - message += "+ /me – посмотреть свой сохраненный профиль в боте\n" - message += "+ /best – посмотреть лучших покемонов для поимки\n" - message += "+ /pokedeks – получить список известных боту покемемов\n" - message += "+ /academy — Академия Инстинкта\n" - message += "+ /bastion — Бастион Инстинкта\n" + message += "\\* /me – посмотреть свой сохраненный профиль в боте\n" + message += "\\* /best – посмотреть лучших покемонов для поимки\n" + message += "\\* /pokedeks – получить список известных боту покемемов\n" + message += "\\* /reminders — настроить оповещения на Турнир лиг\n" + message += "\\* /academy — Академия Инстинкта\n" + message += "\\* /bastion — Бастион Инстинкта\n" if c.Users.PlayerBetterThan(playerRaw, "admin") { - message += "+ /send\\_all _текст_ — отправить сообщение всем пользователям бота\n" - message += "+ /send\\_league _текст_ — отправить сообщение всем пользователям бота, у которых профиль лиги Инстинкт\n" - message += "+ /chats — получить список групп, в которых работает бот.\n" - message += "+ /squads — получить список отрядов.\n" - message += "+ /pin _номера чатов_ _текст_ — отправить сообщение в чаты с номерами. Сообщение будет автоматичекси запинено. Пример: \"/pin 2,3,5 привет мир\". Внимание: между номерами чатов ставятся запятые без пробелов! Всё, что идёт после второго пробела в команде — сообщение\n" - message += "+ /pin\\_all _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n" - message += "+ /orders — просмотреть приказы на атаку\n" + message += "\\* /send\\_all _текст_ — отправить сообщение всем пользователям бота\n" + message += "\\* /send\\_league _текст_ — отправить сообщение всем пользователям бота, у которых профиль лиги Инстинкт\n" + message += "\\* /chats — получить список групп, в которых работает бот.\n" + message += "\\* /squads — получить список отрядов.\n" + message += "\\* /pin _номера чатов_ _текст_ — отправить сообщение в чаты с номерами. Сообщение будет автоматичекси запинено. Пример: \"/pin 2,3,5 привет мир\". Внимание: между номерами чатов ставятся запятые без пробелов! Всё, что идёт после второго пробела в команде — сообщение\n" + message += "\\* /pin\\_all _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n" + message += "\\* /orders — просмотреть приказы на атаку\n" } if c.Users.PlayerBetterThan(playerRaw, "academic") { - message += "+ /users — просмотреть зарегистрированных пользователей бота\n" - message += "+ /find\\_user _строка_ — найти игрока в боте по его нику или имени. Ник ищется без собачки в начале\n" + message += "\\* /users — просмотреть зарегистрированных пользователей бота\n" + message += "\\* /find\\_user _строка_ — найти игрока в боте по его нику или имени. Ник ищется без собачки в начале\n" } - message += "+ /help – выводит данное сообщение\n" + message += "\\* /help – выводит данное сообщение\n" message += "\n\n" message += "Связаться с автором: @fat0troll\n"