diff --git a/lib/chatter/chatterinterface/chatterinterface.go b/lib/chatter/chatterinterface/chatterinterface.go index 3742881..668004b 100644 --- a/lib/chatter/chatterinterface/chatterinterface.go +++ b/lib/chatter/chatterinterface/chatterinterface.go @@ -17,6 +17,7 @@ type ChatterInterface interface { GetAllPrivateChats() ([]dbmapping.Chat, bool) GetLeaguePrivateChats() ([]dbmapping.Chat, bool) GetAllGroupChats() ([]dbmapping.Chat, bool) + GetGroupChatsByIDs(chatsIDs string) ([]dbmapping.Chat, bool) UpdateChatTitle(chatRaw *dbmapping.Chat, newTitle string) (*dbmapping.Chat, bool) UpdateChatTelegramID(update *tgbotapi.Update) (*dbmapping.Chat, bool) diff --git a/lib/chatter/getters.go b/lib/chatter/getters.go index 920ac37..fccf90c 100644 --- a/lib/chatter/getters.go +++ b/lib/chatter/getters.go @@ -6,6 +6,8 @@ package chatter import ( "github.com/go-telegram-bot-api/telegram-bot-api" "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" + "strconv" + "strings" "time" ) @@ -140,3 +142,34 @@ func (ct *Chatter) GetAllGroupChats() ([]dbmapping.Chat, bool) { return groupChats, true } + +// GetGroupChatsByIDs returns group chats with selected IDs +func (ct *Chatter) GetGroupChatsByIDs(chatsIDs string) ([]dbmapping.Chat, bool) { + groupChats := []dbmapping.Chat{} + + queryIDs := make([]int, 0) + queryIDsStr := strings.Split(chatsIDs, ",") + for i := range queryIDsStr { + id, _ := strconv.Atoi(queryIDsStr[i]) + if id != 0 { + queryIDs = append(queryIDs, id) + } + } + + finalQueryIDs := "" + for i := range queryIDs { + finalQueryIDs += strconv.Itoa(queryIDs[i]) + if i < len(queryIDs)-1 { + finalQueryIDs += "," + } + } + c.Log.Debug("Chat query IDs: " + finalQueryIDs) + + err := c.Db.Select(&groupChats, "SELECT * FROM chats WHERE chat_type IN ('group', 'supergroup') AND id IN ("+finalQueryIDs+")") + if err != nil { + c.Log.Error(err) + return groupChats, false + } + + return groupChats, true +} diff --git a/lib/pinner/exported.go b/lib/pinner/exported.go index 85560db..231d2ea 100644 --- a/lib/pinner/exported.go +++ b/lib/pinner/exported.go @@ -26,5 +26,5 @@ func New(ac *appcontext.Context) { func (p *Pinner) Init() { c.Log.Info("Initializing Pinner...") - c.Cron.AddFunc("0 55 */2 * * *", p.PinBattleAlert) + c.Cron.AddFunc("0 55 4-23/2 * * *", p.PinBattleAlert) } diff --git a/lib/pinner/pinner.go b/lib/pinner/pinner.go index 3c5d595..76713d8 100644 --- a/lib/pinner/pinner.go +++ b/lib/pinner/pinner.go @@ -5,6 +5,8 @@ package pinner import ( "github.com/go-telegram-bot-api/telegram-bot-api" + "strconv" + "strings" ) // PinMessageToAllChats pins message to all groups where bot exist @@ -70,6 +72,77 @@ func (p *Pinner) PinMessageToAllChats(update *tgbotapi.Update) string { return "ok" } +// PinMessageToSomeChats pins message to selected groups where bot exist +func (p *Pinner) PinMessageToSomeChats(update *tgbotapi.Update) string { + commandArgs := update.Message.CommandArguments() + commandArgsList := strings.Split(commandArgs, " ") + if len(commandArgsList) < 2 { + return "fail" + } + + chatsToPin := commandArgsList[0] + messageToPin := commandArgsList[1] + + if messageToPin == "" { + return "fail" + } + + groupChats, ok := c.Chatter.GetGroupChatsByIDs(chatsToPin) + if !ok { + return "fail" + } + 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() { diff --git a/lib/pinner/pinnerinterface/pinnerinterface.go b/lib/pinner/pinnerinterface/pinnerinterface.go index f515676..efd8a02 100644 --- a/lib/pinner/pinnerinterface/pinnerinterface.go +++ b/lib/pinner/pinnerinterface/pinnerinterface.go @@ -12,5 +12,7 @@ type PinnerInterface interface { Init() PinBattleAlert() + + PinMessageToSomeChats(update *tgbotapi.Update) string PinMessageToAllChats(update *tgbotapi.Update) string } diff --git a/lib/router/private_request.go b/lib/router/private_request.go index 0a4e704..848041c 100644 --- a/lib/router/private_request.go +++ b/lib/router/private_request.go @@ -80,7 +80,7 @@ func (r *Router) routePrivateRequest(update *tgbotapi.Update, playerRaw *dbmappi } return c.Talkers.AnyMessageUnauthorized(update) - case update.Message.Command() == "group_chats": + case update.Message.Command() == "chats": if c.Users.PlayerBetterThan(playerRaw, "admin") { c.Chatter.GroupsList(update) return "ok" @@ -96,6 +96,12 @@ func (r *Router) routePrivateRequest(update *tgbotapi.Update, playerRaw *dbmappi return c.Talkers.AnyMessageUnauthorized(update) case update.Message.Command() == "pin": + if c.Users.PlayerBetterThan(playerRaw, "admin") { + return c.Pinner.PinMessageToSomeChats(update) + } + + return c.Talkers.AnyMessageUnauthorized(update) + case update.Message.Command() == "pin_all": if c.Users.PlayerBetterThan(playerRaw, "admin") { return c.Pinner.PinMessageToAllChats(update) } diff --git a/lib/talkers/help.go b/lib/talkers/help.go index 9b73a73..f4efaae 100644 --- a/lib/talkers/help.go +++ b/lib/talkers/help.go @@ -20,9 +20,10 @@ func (t *Talkers) HelpMessage(update *tgbotapi.Update, playerRaw *dbmapping.Play if c.Users.PlayerBetterThan(playerRaw, "admin") { message += "+ /send\\_all _текст_ — отправить сообщение всем пользователям бота\n" message += "+ /send\\_league _текст_ — отправить сообщение всем пользователям бота, у которых профиль лиги Инстинкт\n" - message += "+ /group\\_chats — получить список групп, в которых работает бот.\n" + message += "+ /chats — получить список групп, в которых работает бот.\n" message += "+ /squads — получить список отрядов.\n" - message += "+ /pin _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n" + message += "+ /pin _номера чатов_ _текст_ — отправить сообщение в чаты с номерами. Сообщение будет автоматичекси запинено. Пример: \"/pin 2,3,5 привет мир\". Внимание: между номерами чатов ставятся запятые без пробелов! Всё, что идёт после второго пробела в команде — сообщение\n" + message += "+ /pin\\_all _текст_ — отправить сообщение во все группы, где находится бот. Сообщение будет автоматически запинено.\n" message += "+ /users — просмотреть зарегистрированных пользователей бота\n" } message += "+ /help – выводит данное сообщение\n"