Reminders for league. Now just reminders, without attack button
This commit is contained in:
parent
a2e70332de
commit
706dc3e944
@ -13,6 +13,7 @@ import (
|
|||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/orders"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/orders"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/pinner"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/pinner"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/pokedexer"
|
"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/router"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/squader"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/squader"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/statistics"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/statistics"
|
||||||
@ -44,6 +45,7 @@ func main() {
|
|||||||
users.New(c)
|
users.New(c)
|
||||||
statistics.New(c)
|
statistics.New(c)
|
||||||
orders.New(c)
|
orders.New(c)
|
||||||
|
reminder.New(c)
|
||||||
|
|
||||||
c.Log.Info("=======================")
|
c.Log.Info("=======================")
|
||||||
c.Log.Info("= i2_bot initialized. =")
|
c.Log.Info("= i2_bot initialized. =")
|
||||||
@ -66,6 +68,8 @@ func main() {
|
|||||||
}
|
}
|
||||||
} else if update.InlineQuery != nil {
|
} else if update.InlineQuery != nil {
|
||||||
c.Router.RouteInline(&update)
|
c.Router.RouteInline(&update)
|
||||||
|
} else if update.CallbackQuery != nil {
|
||||||
|
c.Router.RouteCallback(&update)
|
||||||
} else if update.ChosenInlineResult != nil {
|
} else if update.ChosenInlineResult != nil {
|
||||||
c.Log.Debug(update.ChosenInlineResult.ResultID)
|
c.Log.Debug(update.ChosenInlineResult.ResultID)
|
||||||
} else {
|
} else {
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/orders/ordersinterface"
|
"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/pinner/pinnerinterface"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/pokedexer/pokedexerinterface"
|
"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/router/routerinterface"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/squader/squaderinterface"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/squader/squaderinterface"
|
||||||
"lab.pztrn.name/fat0troll/i2_bot/lib/statistics/statisticsinterface"
|
"lab.pztrn.name/fat0troll/i2_bot/lib/statistics/statisticsinterface"
|
||||||
@ -43,6 +44,7 @@ type Context struct {
|
|||||||
Broadcaster broadcasterinterface.BroadcasterInterface
|
Broadcaster broadcasterinterface.BroadcasterInterface
|
||||||
Welcomer welcomerinterface.WelcomerInterface
|
Welcomer welcomerinterface.WelcomerInterface
|
||||||
Pinner pinnerinterface.PinnerInterface
|
Pinner pinnerinterface.PinnerInterface
|
||||||
|
Reminder reminderinterface.ReminderInterface
|
||||||
Chatter chatterinterface.ChatterInterface
|
Chatter chatterinterface.ChatterInterface
|
||||||
Squader squaderinterface.SquaderInterface
|
Squader squaderinterface.SquaderInterface
|
||||||
Users usersinterface.UsersInterface
|
Users usersinterface.UsersInterface
|
||||||
@ -137,6 +139,12 @@ func (c *Context) RegisterPinnerInterface(pi pinnerinterface.PinnerInterface) {
|
|||||||
c.Pinner.Init()
|
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
|
// RegisterForwarderInterface registers forwarder interface in application
|
||||||
func (c *Context) RegisterForwarderInterface(fi forwarderinterface.ForwarderInterface) {
|
func (c *Context) RegisterForwarderInterface(fi forwarderinterface.ForwarderInterface) {
|
||||||
c.Forwarder = fi
|
c.Forwarder = fi
|
||||||
|
@ -10,8 +10,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VERSION is the urrent bot's version
|
// VERSION is the current bot's version
|
||||||
const VERSION = "0.6"
|
const VERSION = "0.6.5"
|
||||||
|
|
||||||
// DatabaseConnection handles database connection settings in config.yaml
|
// DatabaseConnection handles database connection settings in config.yaml
|
||||||
type DatabaseConnection struct {
|
type DatabaseConnection struct {
|
||||||
|
16
lib/dbmapping/alarms.go
Normal file
16
lib/dbmapping/alarms.go
Normal file
@ -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"`
|
||||||
|
}
|
38
lib/migrations/30_create_alarms.go
Normal file
38
lib/migrations/30_create_alarms.go
Normal file
@ -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
|
||||||
|
}
|
@ -40,6 +40,7 @@ func (m *Migrations) Init() {
|
|||||||
goose.AddNamedMigration("27_add_new_weapon.go", AddNewWeaponUp, AddNewWeaponDown)
|
goose.AddNamedMigration("27_add_new_weapon.go", AddNewWeaponUp, AddNewWeaponDown)
|
||||||
goose.AddNamedMigration("28_fix_locations.go", FixLocationsUp, FixLocationsDown)
|
goose.AddNamedMigration("28_fix_locations.go", FixLocationsUp, FixLocationsDown)
|
||||||
goose.AddNamedMigration("29_fix_leagues_names.go", FixLeaguesNamesUp, FixLeaguesNamesDown)
|
goose.AddNamedMigration("29_fix_leagues_names.go", FixLeaguesNamesUp, FixLeaguesNamesDown)
|
||||||
|
goose.AddNamedMigration("30_create_alarms.go", CreateAlarmsUp, CreateAlarmsUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate migrates database to current version
|
// Migrate migrates database to current version
|
||||||
|
@ -25,6 +25,4 @@ func New(ac *appcontext.Context) {
|
|||||||
// Init is an initialization function for pinner
|
// Init is an initialization function for pinner
|
||||||
func (p *Pinner) Init() {
|
func (p *Pinner) Init() {
|
||||||
c.Log.Info("Initializing Pinner...")
|
c.Log.Info("Initializing Pinner...")
|
||||||
|
|
||||||
c.Cron.AddFunc("0 55 4-23/2 * * *", p.PinBattleAlert)
|
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,17 @@ package pinner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||||
|
"lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PinMessageToAllChats pins message to all groups where bot exist
|
func (p *Pinner) execMassMessagePin(update *tgbotapi.Update, groupChats []dbmapping.Chat) string {
|
||||||
func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string {
|
|
||||||
messageToPin := update.Message.CommandArguments()
|
messageToPin := update.Message.CommandArguments()
|
||||||
|
|
||||||
if messageToPin == "" {
|
|
||||||
return "fail"
|
|
||||||
}
|
|
||||||
|
|
||||||
groupChats, ok := c.Chatter.GetAllGroupChats()
|
|
||||||
if !ok {
|
|
||||||
return "fail"
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range groupChats {
|
for i := range groupChats {
|
||||||
if groupChats[i].ChatType == "supergroup" {
|
if groupChats[i].ChatType == "supergroup" {
|
||||||
message := messageToPin + "\n\n"
|
message := messageToPin + "\n\n"
|
||||||
message += "© " + update.Message.From.FirstName + " " + update.Message.From.LastName
|
message += "© " + c.Users.GetPrettyName(update.Message.From)
|
||||||
message += " (@" + update.Message.From.UserName + ")"
|
|
||||||
|
|
||||||
msg := tgbotapi.NewMessage(groupChats[i].TelegramID, message)
|
msg := tgbotapi.NewMessage(groupChats[i].TelegramID, message)
|
||||||
msg.ParseMode = "Markdown"
|
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 += "Текст отправленного сообщения:\n\n"
|
||||||
message += messageToPin
|
message += messageToPin
|
||||||
|
|
||||||
@ -72,6 +61,22 @@ func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string {
|
|||||||
return "ok"
|
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
|
// PinMessageToSomeChats pins message to selected groups where bot exist
|
||||||
func (p *Pinner) PinMessageToSomeChats(update *tgbotapi.Update) string {
|
func (p *Pinner) PinMessageToSomeChats(update *tgbotapi.Update) string {
|
||||||
commandArgs := update.Message.CommandArguments()
|
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...")
|
c.Log.Debug("Got " + strconv.Itoa(len(groupChats)) + " group chats...")
|
||||||
|
|
||||||
for i := range groupChats {
|
return p.execMassMessagePin(update, 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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,10 @@ import (
|
|||||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
"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 {
|
type PinnerInterface interface {
|
||||||
Init()
|
Init()
|
||||||
|
|
||||||
PinBattleAlert()
|
|
||||||
|
|
||||||
PinMessageToSomeChats(update *tgbotapi.Update) string
|
PinMessageToSomeChats(update *tgbotapi.Update) string
|
||||||
PinMessageToAllChats(update *tgbotapi.Update) string
|
PinMessageToAllChats(update *tgbotapi.Update) string
|
||||||
}
|
}
|
||||||
|
30
lib/reminder/exported.go
Normal file
30
lib/reminder/exported.go
Normal file
@ -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)
|
||||||
|
}
|
73
lib/reminder/reminder.go
Normal file
73
lib/reminder/reminder.go
Normal file
@ -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
|
||||||
|
}
|
21
lib/reminder/reminderinterface/reminderinterface.go
Normal file
21
lib/reminder/reminderinterface/reminderinterface.go
Normal file
@ -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()
|
||||||
|
}
|
25
lib/reminder/responders.go
Normal file
25
lib/reminder/responders.go
Normal file
@ -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"
|
||||||
|
}
|
32
lib/reminder/sender.go
Normal file
32
lib/reminder/sender.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
60
lib/reminder/updaters.go
Normal file
60
lib/reminder/updaters.go
Normal file
@ -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"
|
||||||
|
}
|
29
lib/router/callback_request.go
Normal file
29
lib/router/callback_request.go
Normal file
@ -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"
|
||||||
|
}
|
@ -80,6 +80,9 @@ func (r *Router) routePrivateRequest(update *tgbotapi.Update, playerRaw *dbmappi
|
|||||||
case update.Message.Command() == "best":
|
case update.Message.Command() == "best":
|
||||||
c.Pokedexer.BestPokememesList(update, playerRaw)
|
c.Pokedexer.BestPokememesList(update, playerRaw)
|
||||||
return "ok"
|
return "ok"
|
||||||
|
case update.Message.Command() == "reminders":
|
||||||
|
return c.Reminder.AlarmsList(update, playerRaw)
|
||||||
|
|
||||||
case update.Message.Command() == "send_all":
|
case update.Message.Command() == "send_all":
|
||||||
if c.Users.PlayerBetterThan(playerRaw, "admin") {
|
if c.Users.PlayerBetterThan(playerRaw, "admin") {
|
||||||
c.Broadcaster.AdminBroadcastMessageCompose(update, playerRaw)
|
c.Broadcaster.AdminBroadcastMessageCompose(update, playerRaw)
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
type RouterInterface interface {
|
type RouterInterface interface {
|
||||||
Init()
|
Init()
|
||||||
|
|
||||||
|
RouteCallback(update *tgbotapi.Update) string
|
||||||
RouteInline(update *tgbotapi.Update) string
|
RouteInline(update *tgbotapi.Update) string
|
||||||
RouteRequest(update *tgbotapi.Update) string
|
RouteRequest(update *tgbotapi.Update) string
|
||||||
}
|
}
|
||||||
|
@ -52,25 +52,26 @@ func (t *Talkers) HelpMessage(update *tgbotapi.Update, playerRaw *dbmapping.Play
|
|||||||
message := "*Бот Инстинкта Enchanched.*\n\n"
|
message := "*Бот Инстинкта Enchanched.*\n\n"
|
||||||
message += "Текущая версия: *" + config.VERSION + "*\n\n"
|
message += "Текущая версия: *" + config.VERSION + "*\n\n"
|
||||||
message += "Список команд\n\n"
|
message += "Список команд\n\n"
|
||||||
message += "+ /me – посмотреть свой сохраненный профиль в боте\n"
|
message += "\\* /me – посмотреть свой сохраненный профиль в боте\n"
|
||||||
message += "+ /best – посмотреть лучших покемонов для поимки\n"
|
message += "\\* /best – посмотреть лучших покемонов для поимки\n"
|
||||||
message += "+ /pokedeks – получить список известных боту покемемов\n"
|
message += "\\* /pokedeks – получить список известных боту покемемов\n"
|
||||||
message += "+ /academy — Академия Инстинкта\n"
|
message += "\\* /reminders — настроить оповещения на Турнир лиг\n"
|
||||||
message += "+ /bastion — Бастион Инстинкта\n"
|
message += "\\* /academy — Академия Инстинкта\n"
|
||||||
|
message += "\\* /bastion — Бастион Инстинкта\n"
|
||||||
if c.Users.PlayerBetterThan(playerRaw, "admin") {
|
if c.Users.PlayerBetterThan(playerRaw, "admin") {
|
||||||
message += "+ /send\\_all _текст_ — отправить сообщение всем пользователям бота\n"
|
message += "\\* /send\\_all _текст_ — отправить сообщение всем пользователям бота\n"
|
||||||
message += "+ /send\\_league _текст_ — отправить сообщение всем пользователям бота, у которых профиль лиги Инстинкт\n"
|
message += "\\* /send\\_league _текст_ — отправить сообщение всем пользователям бота, у которых профиль лиги Инстинкт\n"
|
||||||
message += "+ /chats — получить список групп, в которых работает бот.\n"
|
message += "\\* /chats — получить список групп, в которых работает бот.\n"
|
||||||
message += "+ /squads — получить список отрядов.\n"
|
message += "\\* /squads — получить список отрядов.\n"
|
||||||
message += "+ /pin _номера чатов_ _текст_ — отправить сообщение в чаты с номерами. Сообщение будет автоматичекси запинено. Пример: \"/pin 2,3,5 привет мир\". Внимание: между номерами чатов ставятся запятые без пробелов! Всё, что идёт после второго пробела в команде — сообщение\n"
|
message += "\\* /pin _номера чатов_ _текст_ — отправить сообщение в чаты с номерами. Сообщение будет автоматичекси запинено. Пример: \"/pin 2,3,5 привет мир\". Внимание: между номерами чатов ставятся запятые без пробелов! Всё, что идёт после второго пробела в команде — сообщение\n"
|
||||||
message += "+ /pin\\_all _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n"
|
message += "\\* /pin\\_all _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n"
|
||||||
message += "+ /orders — просмотреть приказы на атаку\n"
|
message += "\\* /orders — просмотреть приказы на атаку\n"
|
||||||
}
|
}
|
||||||
if c.Users.PlayerBetterThan(playerRaw, "academic") {
|
if c.Users.PlayerBetterThan(playerRaw, "academic") {
|
||||||
message += "+ /users — просмотреть зарегистрированных пользователей бота\n"
|
message += "\\* /users — просмотреть зарегистрированных пользователей бота\n"
|
||||||
message += "+ /find\\_user _строка_ — найти игрока в боте по его нику или имени. Ник ищется без собачки в начале\n"
|
message += "\\* /find\\_user _строка_ — найти игрока в боте по его нику или имени. Ник ищется без собачки в начале\n"
|
||||||
}
|
}
|
||||||
message += "+ /help – выводит данное сообщение\n"
|
message += "\\* /help – выводит данное сообщение\n"
|
||||||
|
|
||||||
message += "\n\n"
|
message += "\n\n"
|
||||||
message += "Связаться с автором: @fat0troll\n"
|
message += "Связаться с автором: @fat0troll\n"
|
||||||
|
Reference in New Issue
Block a user