diff --git a/config.yml.example b/config.yml.example index 107d36b..2d1f24f 100644 --- a/config.yml.example +++ b/config.yml.example @@ -7,6 +7,7 @@ database_connection: password: "i2_bot" database: "i2_bot" special_chats: + academy_id: "group_id" bastion_id: "group_id" default_id: "group_id" headquarters_id: "group_id" diff --git a/lib/chatter/chatterinterface/chatterinterface.go b/lib/chatter/chatterinterface/chatterinterface.go index 668004b..d05d9b9 100644 --- a/lib/chatter/chatterinterface/chatterinterface.go +++ b/lib/chatter/chatterinterface/chatterinterface.go @@ -12,6 +12,9 @@ import ( type ChatterInterface interface { Init() + BanUserFromChat(user *tgbotapi.User, chatRaw *dbmapping.Chat) + ProtectChat(update *tgbotapi.Update, playerRaw *dbmapping.Player, chatRaw *dbmapping.Chat) string + GetOrCreateChat(update *tgbotapi.Update) (dbmapping.Chat, bool) GetChatByID(chatID int64) (dbmapping.Chat, bool) GetAllPrivateChats() ([]dbmapping.Chat, bool) diff --git a/lib/chatter/getters.go b/lib/chatter/getters.go index fccf90c..3046ae1 100644 --- a/lib/chatter/getters.go +++ b/lib/chatter/getters.go @@ -121,7 +121,7 @@ func (ct *Chatter) GetAllPrivateChats() ([]dbmapping.Chat, bool) { func (ct *Chatter) GetLeaguePrivateChats() ([]dbmapping.Chat, bool) { privateChats := []dbmapping.Chat{} - err := c.Db.Select(&privateChats, "SELECT c.* FROM chats c, players p WHERE c.chat_type='private' AND p.telegram_id = c.telegram_id AND p.league_id = 1") + err := c.Db.Select(&privateChats, "SELECT c.* FROM chats c, players p WHERE c.chat_type='private' AND p.telegram_id = c.telegram_id AND p.league_id = 1 AND p.status != 'spy' AND p.status != 'league_changed'") if err != nil { c.Log.Error(err) return privateChats, false diff --git a/lib/chatter/responders.go b/lib/chatter/responders.go index 9193e3c..3b6861c 100644 --- a/lib/chatter/responders.go +++ b/lib/chatter/responders.go @@ -15,6 +15,7 @@ func (ct *Chatter) GroupsList(update *tgbotapi.Update) string { return "fail" } + academyChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.AcademyID, 10, 64) bastionChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) defaultChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.DefaultID, 10, 64) hqChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.HeadquartersID, 10, 64) @@ -31,6 +32,9 @@ func (ct *Chatter) GroupsList(update *tgbotapi.Update) string { } else if groupChats[i].ChatRole == "flood" { message += "Является флудочатом отряда №" + strconv.Itoa(groupChats[i].Squad.ID) + "\n" } else { + if groupChats[i].Chat.TelegramID == academyChatID { + message += "Является академией лиги\n" + } if groupChats[i].Chat.TelegramID == bastionChatID { message += "Является бастионом лиги\n" } diff --git a/lib/chatter/restricters.go b/lib/chatter/restricters.go new file mode 100644 index 0000000..5611f53 --- /dev/null +++ b/lib/chatter/restricters.go @@ -0,0 +1,120 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package chatter + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" + "strconv" + "strings" +) + +func (ct *Chatter) userPrivilegesCheck(update *tgbotapi.Update, user *tgbotapi.User) bool { + // There are two special chats, pointed by config, where any member of league may be + bastionChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) + academyChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.AcademyID, 10, 64) + // There are special users, which will bypass these checks + specialUsers := []string{"gantz_yaka", "agentpb", "pbhelp"} + + for j := range specialUsers { + if strings.ToLower(user.UserName) == specialUsers[j] { + // This is for PokememBro admins, they can join any chat at any time + return true + } + } + + playerRaw, ok := c.Users.GetOrCreatePlayer(user.ID) + if !ok { + return false + } + + // So, user is not a PokememBro admin. For Bastion and Academy she needs to be league player + switch update.Message.Chat.ID { + case academyChatID: + if playerRaw.LeagueID == 1 && playerRaw.Status != "spy" && playerRaw.Status != "league_changed" { + return true + } + case bastionChatID: + if playerRaw.LeagueID == 1 && playerRaw.Status != "spy" && playerRaw.Status != "league_changed" { + return true + } + default: + availableChatsForUser, _ := c.Squader.GetAvailableSquadChatsForUser(&playerRaw) + for i := range availableChatsForUser { + if update.Message.Chat.ID == availableChatsForUser[i].TelegramID { + return true + } + } + } + + return false +} + +// BanUserFromChat removes user from chat +func (ct *Chatter) BanUserFromChat(user *tgbotapi.User, chatRaw *dbmapping.Chat) { + chatUserConfig := tgbotapi.ChatMemberConfig{ + ChatID: chatRaw.TelegramID, + UserID: user.ID, + } + + kickConfig := tgbotapi.KickChatMemberConfig{ + ChatMemberConfig: chatUserConfig, + UntilDate: 1893456000, + } + + c.Log.Info("Trying to ban user...") + + _, err := c.Bot.KickChatMember(kickConfig) + if err != nil { + c.Log.Error(err.Error()) + } + + bastionChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) + academyChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.AcademyID, 10, 64) + hqChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.HeadquartersID, 10, 64) + if (chatRaw.TelegramID != bastionChatID) || (chatRaw.TelegramID != academyChatID) { + // In Bastion notifications are public in default chat + commanders, ok := c.Squader.GetCommandersForSquadViaChat(chatRaw) + if ok { + for i := range commanders { + message := "Некто " + c.Users.GetPrettyName(user) + " попытался зайти в чат _" + chatRaw.Name + "_ и был изгнан ботом, так как не имеет права посещать этот чат." + + msg := tgbotapi.NewMessage(int64(commanders[i].TelegramID), message) + msg.ParseMode = "Markdown" + c.Bot.Send(msg) + } + } + } else { + message := "Некто " + c.Users.GetPrettyName(user) + " попытался зайти в один из общих чатов лиги и был изгнан ботом, так как не имеет права посещать этот чат." + + msg := tgbotapi.NewMessage(hqChatID, message) + msg.ParseMode = "Markdown" + c.Bot.Send(msg) + } +} + +// ProtectChat protects chats from unauthorized access +// Returns "protection_passed" if all protection checks passed +func (ct *Chatter) ProtectChat(update *tgbotapi.Update, playerRaw *dbmapping.Player, chatRaw *dbmapping.Chat) string { + // Check on new user addition + if update.Message.NewChatMembers != nil { + newUsers := *update.Message.NewChatMembers + if len(newUsers) > 0 { + for i := range newUsers { + newUserPassed := ct.userPrivilegesCheck(update, &newUsers[i]) + if !newUserPassed { + ct.BanUserFromChat(&newUsers[i], chatRaw) + } + } + } + } + + existingUserPassed := ct.userPrivilegesCheck(update, update.Message.From) + if !existingUserPassed { + ct.BanUserFromChat(update.Message.From, chatRaw) + return "fail" + } + + return c.Squader.CleanFlood(update, chatRaw) +} diff --git a/lib/config/config.go b/lib/config/config.go index 28eec17..075b267 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -29,6 +29,7 @@ type TelegramConnection struct { // SpecialChats handles settings for special chats type SpecialChats struct { + AcademyID string `yaml:"academy_id"` BastionID string `yaml:"bastion_id"` DefaultID string `yaml:"default_id"` HeadquartersID string `yaml:"headquarters_id"` diff --git a/lib/router/group_request.go b/lib/router/group_request.go index 07d2e18..65cf73a 100644 --- a/lib/router/group_request.go +++ b/lib/router/group_request.go @@ -8,7 +8,6 @@ import ( "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" "math/rand" "regexp" - "strconv" ) func (r *Router) routeGroupRequest(update *tgbotapi.Update, playerRaw *dbmapping.Player, chatRaw *dbmapping.Chat) string { @@ -20,14 +19,9 @@ func (r *Router) routeGroupRequest(update *tgbotapi.Update, playerRaw *dbmapping var ebMsg = regexp.MustCompile("(\\s|^|ЗА|За|зА|за)(Е|е|Ё|ё)(Б|б)(\\s|Л|л|А|а|Т|т|У|у|Е|е|Ё|ё|И|и)") var piMsg = regexp.MustCompile("(П|п)(И|и)(З|з)(Д|д)") - squadHandled := c.Squader.ProcessMessage(update, chatRaw) - if squadHandled != "ok" { - return squadHandled - } - - bastionChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) - if update.Message.Chat.ID == bastionChatID { - c.Squader.FilterBastion(update) + restrictionStatus := c.Chatter.ProtectChat(update, playerRaw, chatRaw) + if restrictionStatus != "protection_passed" { + return restrictionStatus } // Welcomes diff --git a/lib/squader/getters.go b/lib/squader/getters.go index 2514b1e..6de0dba 100644 --- a/lib/squader/getters.go +++ b/lib/squader/getters.go @@ -9,6 +9,18 @@ import ( "strings" ) +// GetCommandersForSquadViaChat gets commanders for selected chat +func (s *Squader) GetCommandersForSquadViaChat(chatRaw *dbmapping.Chat) ([]dbmapping.Player, bool) { + commanders := []dbmapping.Player{} + err := c.Db.Select(&commanders, c.Db.Rebind("SELECT p.* FROM players p, squads_players sp, squads s WHERE (s.chat_id=? OR s.flood_chat_id=?) AND sp.squad_id = s.id AND sp.user_type = 'commander' AND sp.player_id = p.id"), chatRaw.ID, chatRaw.ID) + if err != nil { + c.Log.Debug(err.Error()) + return commanders, false + } + + return commanders, true +} + // GetSquadByID returns squad will all support information func (s *Squader) GetSquadByID(squadID int) (dbmapping.SquadChat, bool) { squadFull := dbmapping.SquadChat{} @@ -44,10 +56,12 @@ func (s *Squader) GetSquadByID(squadID int) (dbmapping.SquadChat, bool) { func (s *Squader) GetAvailableSquadChatsForUser(playerRaw *dbmapping.Player) ([]dbmapping.Chat, bool) { groupChats := []dbmapping.Chat{} - err := c.Db.Select(&groupChats, c.Db.Rebind("SELECT ch.* FROM chats ch, squads s, squads_players sp WHERE (s.chat_id=ch.id OR s.flood_chat_id=ch.id) AND sp.player_id = ? AND s.id = sp.squad_id"), playerRaw.ID) - if err != nil { - c.Log.Error(err) - return groupChats, false + if playerRaw.LeagueID == 1 && playerRaw.Status != "spy" && playerRaw.Status != "league_changed" { + err := c.Db.Select(&groupChats, c.Db.Rebind("SELECT ch.* FROM chats ch, squads s, squads_players sp WHERE (s.chat_id=ch.id OR s.flood_chat_id=ch.id) AND sp.player_id = ? AND s.id = sp.squad_id"), playerRaw.ID) + if err != nil { + c.Log.Error(err) + return groupChats, false + } } return groupChats, true diff --git a/lib/squader/restricter.go b/lib/squader/restricter.go deleted file mode 100644 index 8f2fdf7..0000000 --- a/lib/squader/restricter.go +++ /dev/null @@ -1,49 +0,0 @@ -// i2_bot – Instinct PokememBro Bot -// Copyright (c) 2017 Vladimir "fat0troll" Hodakov - -package squader - -import ( - "github.com/go-telegram-bot-api/telegram-bot-api" - "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" - "strconv" -) - -func (s *Squader) kickUserFromSquadChat(user *tgbotapi.User, chatRaw *dbmapping.Chat) { - chatUserConfig := tgbotapi.ChatMemberConfig{ - ChatID: chatRaw.TelegramID, - UserID: user.ID, - } - - kickConfig := tgbotapi.KickChatMemberConfig{ - ChatMemberConfig: chatUserConfig, - UntilDate: 1893456000, - } - - _, err := c.Bot.KickChatMember(kickConfig) - if err != nil { - c.Log.Error(err.Error()) - } - - bastionChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) - hqChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.HeadquartersID, 10, 64) - if chatRaw.TelegramID != bastionChatID { - // In Bastion notifications are public in default chat - commanders, ok := s.getCommandersForSquadViaChat(chatRaw) - if ok { - for i := range commanders { - message := "Некто " + c.Users.GetPrettyName(user) + " попытался зайти в чат _" + chatRaw.Name + "_ и был изгнан ботом, так как не имеет права посещать этот чат." - - msg := tgbotapi.NewMessage(int64(commanders[i].TelegramID), message) - msg.ParseMode = "Markdown" - c.Bot.Send(msg) - } - } - } else { - message := "Некто " + c.Users.GetPrettyName(user) + " попытался зайти в чат _Бастион Инстинкта_ и был изгнан ботом, так как не имеет права посещать этот чат." - - msg := tgbotapi.NewMessage(hqChatID, message) - msg.ParseMode = "Markdown" - c.Bot.Send(msg) - } -} diff --git a/lib/squader/restricters.go b/lib/squader/restricters.go new file mode 100644 index 0000000..9311547 --- /dev/null +++ b/lib/squader/restricters.go @@ -0,0 +1,27 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package squader + +import ( + "github.com/go-telegram-bot-api/telegram-bot-api" + "lab.pztrn.name/fat0troll/i2_bot/lib/dbmapping" +) + +// CleanFlood will clean flood from squads +func (s *Squader) CleanFlood(update *tgbotapi.Update, chatRaw *dbmapping.Chat) string { + switch s.IsChatASquadEnabled(chatRaw) { + case "main": + talker, ok := c.Users.GetOrCreatePlayer(update.Message.From.ID) + if !ok { + s.deleteFloodMessage(update) + return "fail" + } + if (update.Message.From.UserName != "i2_bot") && (update.Message.From.UserName != "i2_bot_dev") && !s.isUserAnyCommander(talker.ID) { + s.deleteFloodMessage(update) + return "fail" + } + } + + return "protection_passed" +} diff --git a/lib/squader/squader.go b/lib/squader/squader.go index 5cdda3d..9445a2c 100644 --- a/lib/squader/squader.go +++ b/lib/squader/squader.go @@ -199,17 +199,6 @@ func (s *Squader) isUserAnyCommander(playerID int) bool { return false } -func (s *Squader) getCommandersForSquadViaChat(chatRaw *dbmapping.Chat) ([]dbmapping.Player, bool) { - commanders := []dbmapping.Player{} - err := c.Db.Select(&commanders, c.Db.Rebind("SELECT p.* FROM players p, squads_players sp, squads s WHERE (s.chat_id=? OR s.flood_chat_id=?) AND sp.squad_id = s.id AND sp.user_type = 'commander' AND sp.player_id = p.id"), chatRaw.ID, chatRaw.ID) - if err != nil { - c.Log.Debug(err.Error()) - return commanders, false - } - - return commanders, true -} - func (s *Squader) squadCreationDuplicate(update *tgbotapi.Update) string { message := "*Отряд уже существует*\n" message += "Проверьте, правильно ли вы ввели команду, и повторите попытку." @@ -380,192 +369,3 @@ func (s *Squader) CreateSquad(update *tgbotapi.Update) string { return s.squadCreationSuccess(update) } - -// ProcessMessage handles all squad-specified administration actions -func (s *Squader) ProcessMessage(update *tgbotapi.Update, chatRaw *dbmapping.Chat) string { - // It will pass message or do some extra actions - // If it returns "ok", we can pass message to router, otherwise we will stop here - processMain := false - processFlood := false - messageProcessed := false - switch s.IsChatASquadEnabled(chatRaw) { - case "main": - processMain = true - case "flood": - processFlood = true - default: - return "ok" - } - - // Kicking non-squad members from any chat - if processMain || processFlood { - if update.Message.NewChatMembers != nil { - newUsers := *update.Message.NewChatMembers - if len(newUsers) > 0 { - for i := range newUsers { - switch strings.ToLower(newUsers[i].UserName) { - case "gantz_yaka": - messageProcessed = true - case "agentpb": - messageProcessed = true - case "pbhelp": - messageProcessed = true - default: - playerRaw, ok := c.Users.GetOrCreatePlayer(newUsers[i].ID) - if !ok { - s.kickUserFromSquadChat(&newUsers[i], chatRaw) - messageProcessed = true - } - - availableChats, ok := s.GetAvailableSquadChatsForUser(&playerRaw) - if !ok { - s.kickUserFromSquadChat(&newUsers[i], chatRaw) - messageProcessed = true - } - isChatValid := false - for i := range availableChats { - if *chatRaw == availableChats[i] { - isChatValid = true - } - } - if !isChatValid { - s.kickUserFromSquadChat(&newUsers[i], chatRaw) - messageProcessed = true - } - } - } - } - } - } - - if processMain { - c.Log.Debug("Message found in one of squad's main chats.") - talker, ok := c.Users.GetOrCreatePlayer(update.Message.From.ID) - if !ok { - s.deleteFloodMessage(update) - messageProcessed = true - } - - if (update.Message.From.UserName != "i2_bot") && (update.Message.From.UserName != "i2_bot_dev") && !s.isUserAnyCommander(talker.ID) { - s.deleteFloodMessage(update) - messageProcessed = true - } - } - - if messageProcessed { - return "fail" - } - - return "ok" -} - -// ProtectBastion avoids spies and no-profile players to join Bastion -func (s *Squader) ProtectBastion(update *tgbotapi.Update, newUser *tgbotapi.User) string { - defaultChatID, _ := strconv.ParseInt(c.Cfg.SpecialChats.DefaultID, 10, 64) - - chatRaw, ok := c.Chatter.GetOrCreateChat(update) - if !ok { - return "fail" - } - - playerRaw, ok := c.Users.GetOrCreatePlayer(newUser.ID) - if !ok { - switch strings.ToLower(newUser.UserName) { - case "gantz_yaka": - // do nothing - case "agentpb": - // do nothing - case "pbhelp": - // do nothing - default: - s.kickUserFromSquadChat(newUser, &chatRaw) - return "fail" - } - } - - if playerRaw.LeagueID != 1 { - switch newUser.UserName { - case "gantz_yaka": - message := "Здравствуй, " + newUser.UserName + "!\n" - message += "Инстинкт рад приветствовать Бога мира ПокемемБро! Проходите, располагайтесь, чувствуйте себя, как дома.\n" - - msg := tgbotapi.NewMessage(chatRaw.TelegramID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - case "agentpb": - message := "Здравствуй, " + newUser.UserName + "!\n" - message += "Инстинкт рад приветствовать одного из богов мира ПокемемБро! Проходите, располагайтесь, чувствуйте себя, как дома.\n" - - msg := tgbotapi.NewMessage(chatRaw.TelegramID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - case "pbhelp": - message := "Здравствуй, " + newUser.UserName + "!\n" - message += "Инстинкт рад приветствовать одного из богов мира ПокемемБро! Проходите, располагайтесь, чувствуйте себя, как дома.\n" - - msg := tgbotapi.NewMessage(chatRaw.TelegramID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - default: - // Check for profile - _, profileOK := c.Users.GetProfile(playerRaw.ID) - if !profileOK { - message := "Привет, " + c.Users.GetPrettyName(newUser) + "! Напиши мне и скинь профиль для доступа в чаты Лиги!" - - msg := tgbotapi.NewMessage(defaultChatID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - } else { - message := "Привет, " + c.Users.GetPrettyName(newUser) + "! Там переход между лигами не завезли случайно? Переходи в нашу Лигу, будем рады тебя видеть... а пока — вход в наши чаты закрыт!" - - msg := tgbotapi.NewMessage(defaultChatID, message) - msg.ParseMode = "Markdown" - - c.Bot.Send(msg) - } - s.kickUserFromSquadChat(newUser, &chatRaw) - return "fail" - } - } - - return "ok" -} - -// FilterBastion kicks already joined user if he changed league -func (s *Squader) FilterBastion(update *tgbotapi.Update) string { - user := update.Message.From - chatRaw, ok := c.Chatter.GetOrCreateChat(update) - if !ok { - return "fail" - } - - playerRaw, playerOK := c.Users.GetOrCreatePlayer(update.Message.From.ID) - if !playerOK { - s.kickUserFromSquadChat(user, &chatRaw) - return "fail" - } - _, profileOK := c.Users.GetProfile(playerRaw.ID) - if !profileOK { - s.kickUserFromSquadChat(user, &chatRaw) - return "fail" - } - if playerRaw.LeagueID != 1 { - switch strings.ToLower(user.UserName) { - case "gantz_yaka": - // do nothing - case "agentpb": - // do nothing - case "pbhelp": - // do nothing - default: - s.kickUserFromSquadChat(user, &chatRaw) - return "fail" - } - } - - return "ok" -} diff --git a/lib/squader/squaderinterface/squaderinterface.go b/lib/squader/squaderinterface/squaderinterface.go index 55df281..e7e41fa 100644 --- a/lib/squader/squaderinterface/squaderinterface.go +++ b/lib/squader/squaderinterface/squaderinterface.go @@ -15,6 +15,7 @@ type SquaderInterface interface { GetAllSquadChats() ([]dbmapping.Chat, bool) GetAllSquadFloodChats() ([]dbmapping.Chat, bool) GetAvailableSquadChatsForUser(playerRaw *dbmapping.Player) ([]dbmapping.Chat, bool) + GetCommandersForSquadViaChat(chatRaw *dbmapping.Chat) ([]dbmapping.Player, bool) GetSquadByID(squadID int) (dbmapping.SquadChat, bool) GetSquadChatsBySquadsIDs(squadsID string) ([]dbmapping.Chat, bool) GetUserRolesInSquads(playerRaw *dbmapping.Player) ([]dbmapping.SquadPlayerFull, bool) @@ -26,7 +27,5 @@ type SquaderInterface interface { SquadInfo(update *tgbotapi.Update, playerRaw *dbmapping.Player) string SquadsList(update *tgbotapi.Update, playerRaw *dbmapping.Player) string - ProcessMessage(update *tgbotapi.Update, chatRaw *dbmapping.Chat) string - ProtectBastion(update *tgbotapi.Update, newUser *tgbotapi.User) string - FilterBastion(update *tgbotapi.Update) string + CleanFlood(update *tgbotapi.Update, chatRaw *dbmapping.Chat) string } diff --git a/lib/users/getters.go b/lib/users/getters.go index f7f3d86..7f907f1 100644 --- a/lib/users/getters.go +++ b/lib/users/getters.go @@ -37,7 +37,7 @@ func (u *Users) GetPlayerByID(playerID int) (dbmapping.Player, bool) { // In case, when there is no player with such ID, new player will be created. func (u *Users) GetOrCreatePlayer(telegramID int) (dbmapping.Player, bool) { playerRaw := dbmapping.Player{} - err := c.Db.Get(&playerRaw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id=?"), telegramID) + err := c.Db.Get(&playerRaw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id=? ORDER BY created_at desc LIMIT 1"), telegramID) if err != nil { c.Log.Error("Message user not found in database.") c.Log.Error(err.Error()) diff --git a/lib/users/responders.go b/lib/users/responders.go index 3e0d92e..6c35cd4 100644 --- a/lib/users/responders.go +++ b/lib/users/responders.go @@ -12,7 +12,7 @@ import ( // FormatUsername formats Telegram username for posting func (u *Users) FormatUsername(userName string) string { - return strings.Replace(userName, "_", "\\_", -1) + return strings.Replace(userName, "_", `\_`, -1) } // FindByName finds user with such username or nickname diff --git a/lib/welcomer/responders.go b/lib/welcomer/responders.go index 4face35..3a665f0 100644 --- a/lib/welcomer/responders.go +++ b/lib/welcomer/responders.go @@ -55,15 +55,10 @@ func (w *Welcomer) GroupWelcomeMessage(update *tgbotapi.Update) string { w.groupStartMessage(update) } else { defaultGroupID, _ := strconv.ParseInt(c.Cfg.SpecialChats.DefaultID, 10, 64) - bastionGroupID, _ := strconv.ParseInt(c.Cfg.SpecialChats.BastionID, 10, 64) if update.Message.Chat.ID == defaultGroupID { w.groupWelcomeUser(update, &newUser) } - - if update.Message.Chat.ID == bastionGroupID { - c.Squader.ProtectBastion(update, &newUser) - } } }