2017-11-19 22:16:11 +04:00
// 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"
"regexp"
"strconv"
"strings"
"time"
)
2017-11-24 00:16:22 +04:00
func ( s * Squader ) getPlayersForSquad ( squadID int ) ( [ ] dbmapping . SquadPlayerFull , bool ) {
players := [ ] dbmapping . SquadPlayerFull { }
playersRaw := [ ] dbmapping . Player { }
squadPlayers := [ ] dbmapping . SquadPlayer { }
squad , ok := s . GetSquadByID ( squadID )
if ! ok {
return players , false
}
err := c . Db . Select ( & playersRaw , c . Db . Rebind ( "SELECT p.* FROM players p, squads_players sp WHERE p.id = sp.player_id AND sp.squad_id=?" ) , squad . Squad . ID )
if err != nil {
c . Log . Error ( err . Error ( ) )
return players , false
}
err = c . Db . Select ( & squadPlayers , c . Db . Rebind ( "SELECT * FROM squads_players WHERE squad_id=?" ) , squad . Squad . ID )
if err != nil {
c . Log . Error ( err . Error ( ) )
return players , false
}
for i := range playersRaw {
for ii := range squadPlayers {
if squadPlayers [ ii ] . PlayerID == playersRaw [ i ] . ID {
playerWithProfile := dbmapping . SquadPlayerFull { }
profile , _ := c . Users . GetProfile ( playersRaw [ i ] . ID )
playerWithProfile . Profile = profile
playerWithProfile . Player = playersRaw [ i ]
playerWithProfile . Squad = squad
playerWithProfile . UserRole = squadPlayers [ ii ] . UserType
players = append ( players , playerWithProfile )
}
}
}
return players , true
}
2017-11-19 22:16:11 +04:00
func ( s * Squader ) getAllSquadsWithChats ( ) ( [ ] dbmapping . SquadChat , bool ) {
squadsWithChats := [ ] dbmapping . SquadChat { }
squads := [ ] dbmapping . Squad { }
err := c . Db . Select ( & squads , "SELECT * FROM squads" )
if err != nil {
c . Log . Error ( err )
return squadsWithChats , false
}
for i := range squads {
chatSquad := dbmapping . SquadChat { }
chat := dbmapping . Chat { }
floodChat := dbmapping . Chat { }
err = c . Db . Get ( & chat , c . Db . Rebind ( "SELECT * FROM chats WHERE id=?" ) , squads [ i ] . ChatID )
if err != nil {
c . Log . Error ( err )
return squadsWithChats , false
}
err = c . Db . Get ( & floodChat , c . Db . Rebind ( "SELECT * FROM chats WHERE id=?" ) , squads [ i ] . FloodChatID )
if err != nil {
c . Log . Error ( err )
return squadsWithChats , false
}
chatSquad . Squad = squads [ i ]
chatSquad . Chat = chat
chatSquad . FloodChat = floodChat
squadsWithChats = append ( squadsWithChats , chatSquad )
}
return squadsWithChats , true
}
func ( s * Squader ) createSquad ( update * tgbotapi . Update , chatID int , floodChatID int ) ( dbmapping . Squad , string ) {
squad := dbmapping . Squad { }
chat := dbmapping . Chat { }
floodChat := dbmapping . Chat { }
// Checking if chats in database exist
err := c . Db . Get ( & chat , c . Db . Rebind ( "SELECT * FROM chats WHERE id=?" ) , chatID )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
err = c . Db . Get ( & floodChat , c . Db . Rebind ( "SELECT * FROM chats WHERE id=?" ) , floodChatID )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
err2 := c . Db . Get ( & squad , c . Db . Rebind ( "SELECT * FROM squads WHERE chat_id IN (?, ?) OR flood_chat_id IN (?, ?)" ) , chat . ID , floodChat . ID , chat . ID , floodChat . ID )
if err2 == nil {
return squad , "dup"
}
c . Log . Debug ( err2 )
err = c . Db . Get ( & squad , c . Db . Rebind ( "SELECT * FROM squads WHERE chat_id=? AND flood_chat_id=?" ) , chatID , floodChatID )
if err != nil {
c . Log . Debug ( err )
2017-11-21 06:06:32 +04:00
playerRaw , ok := c . Users . GetOrCreatePlayer ( update . Message . From . ID )
2017-11-19 22:16:11 +04:00
if ! ok {
return squad , "fail"
}
squad . AuthorID = playerRaw . ID
squad . ChatID = chatID
squad . FloodChatID = floodChatID
squad . CreatedAt = time . Now ( ) . UTC ( )
_ , err = c . Db . NamedExec ( "INSERT INTO `squads` VALUES(NULL, :chat_id, :flood_chat_id, :author_id, :created_at)" , & squad )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
err = c . Db . Get ( & squad , c . Db . Rebind ( "SELECT * FROM squads WHERE chat_id=? AND flood_chat_id=?" ) , chatID , floodChatID )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
return squad , "ok"
}
return squad , "dup"
}
func ( s * Squader ) getSquadByChatID ( update * tgbotapi . Update , chatID int ) ( dbmapping . Squad , string ) {
squad := dbmapping . Squad { }
chat := dbmapping . Chat { }
// Checking if chat in database exist
err := c . Db . Get ( & chat , c . Db . Rebind ( "SELECT * FROM chats WHERE id=?" ) , chatID )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
err = c . Db . Get ( & squad , c . Db . Rebind ( "SELECT * FROM squads WHERE chat_id=?" ) , chat . ID )
if err != nil {
c . Log . Error ( err )
return squad , "fail"
}
return squad , "ok"
}
2017-11-24 00:16:22 +04:00
func ( s * Squader ) getUserRoleForSquad ( squadID int , playerID int ) string {
squadPlayer := dbmapping . SquadPlayer { }
err := c . Db . Get ( & squadPlayer , c . Db . Rebind ( "SELECT * FROM squads_players WHERE squad_id=? AND player_id=?" ) , squadID , playerID )
if err != nil {
c . Log . Debug ( err . Error ( ) )
return "nobody"
}
return squadPlayer . UserType
}
func ( s * Squader ) isUserAnyCommander ( playerID int ) bool {
squadPlayers := [ ] dbmapping . SquadPlayer { }
err := c . Db . Select ( & squadPlayers , c . Db . Rebind ( "SELECT * FROM squads_players WHERE player_id=?" ) , playerID )
if err != nil {
c . Log . Debug ( err . Error ( ) )
}
if len ( squadPlayers ) > 0 {
return true
}
return false
}
2017-11-19 22:16:11 +04:00
func ( s * Squader ) squadCreationDuplicate ( update * tgbotapi . Update ) string {
message := "*Отряд уже существует*\n"
message += "Проверьте, правильно ли вы ввели команду, и повторите попытку."
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , message )
msg . ParseMode = "Markdown"
c . Bot . Send ( msg )
return "fail"
}
func ( s * Squader ) squadCreationFailure ( update * tgbotapi . Update ) string {
message := "*Н е удалось добавить отряд в базу*\n"
message += "Проверьте, правильно ли вы ввели команду, и повторите попытку."
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , message )
msg . ParseMode = "Markdown"
c . Bot . Send ( msg )
return "fail"
}
func ( s * Squader ) squadCreationSuccess ( update * tgbotapi . Update ) string {
message := "*Отряд успешно добавлен в базу*\n"
message += "Просмотреть список отрядов можно командой /squads."
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , message )
msg . ParseMode = "Markdown"
c . Bot . Send ( msg )
return "fail"
}
2017-11-24 00:16:22 +04:00
func ( s * Squader ) squadUserAdditionFailure ( update * tgbotapi . Update ) string {
message := "*Н е удалось добавить игрока в отряд*\n"
message += "Проверьте, правильно ли вы ввели команду, и повторите попытку. Кроме того, возможно, что у пользователя нет профиля в боте."
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , message )
msg . ParseMode = "Markdown"
c . Bot . Send ( msg )
return "fail"
}
func ( s * Squader ) squadUserAdditionSuccess ( update * tgbotapi . Update ) string {
message := "*Игрок добавлен в отряд*\n"
message += "Теперь вы можете дать ему ссылку для входа в чаты отряда."
msg := tgbotapi . NewMessage ( update . Message . Chat . ID , message )
msg . ParseMode = "Markdown"
c . Bot . Send ( msg )
return "ok"
}
2017-11-19 22:16:11 +04:00
// External functions
2017-11-24 00:16:22 +04:00
// AddUserToSquad adds user to squad
func ( s * Squader ) AddUserToSquad ( update * tgbotapi . Update , adderRaw * dbmapping . Player ) string {
command := update . Message . Command ( )
commandArugments := update . Message . CommandArguments ( )
userType := "user"
if command == "squad_add_commander" {
userType = "commander"
}
argumentsRx := regexp . MustCompile ( ` (\d+)\s(\d+) ` )
if ! argumentsRx . MatchString ( commandArugments ) {
return s . squadUserAdditionFailure ( update )
}
argumentNumbers := strings . Split ( commandArugments , " " )
if len ( argumentNumbers ) < 2 {
return s . squadUserAdditionFailure ( update )
}
squadID , _ := strconv . Atoi ( argumentNumbers [ 0 ] )
if squadID == 0 {
return s . squadUserAdditionFailure ( update )
}
playerID , _ := strconv . Atoi ( argumentNumbers [ 1 ] )
if playerID == 0 {
return s . squadUserAdditionFailure ( update )
}
playerRaw , ok := c . Users . GetPlayerByID ( playerID )
if ! ok {
return s . squadUserAdditionFailure ( update )
}
squadRaw := dbmapping . Squad { }
err := c . Db . Get ( & squadRaw , c . Db . Rebind ( "SELECT * FROM squads WHERE id=?" ) , squadID )
if err != nil {
c . Log . Error ( err . Error ( ) )
return s . squadUserAdditionFailure ( update )
}
_ , ok = c . Users . GetProfile ( playerRaw . ID )
if ! ok {
return s . squadUserAdditionFailure ( update )
}
if ! c . Users . PlayerBetterThan ( adderRaw , "admin" ) {
if userType == "commander" {
2017-11-25 03:00:34 +04:00
return c . Talkers . AnyMessageUnauthorized ( update )
2017-11-24 00:16:22 +04:00
}
if s . getUserRoleForSquad ( squadRaw . ID , adderRaw . ID ) != "commander" {
2017-11-25 03:00:34 +04:00
return c . Talkers . AnyMessageUnauthorized ( update )
2017-11-24 00:16:22 +04:00
}
}
if ! c . Users . PlayerBetterThan ( & playerRaw , "admin" ) {
if playerRaw . LeagueID != 1 {
return s . squadUserAdditionFailure ( update )
}
}
// All checks are passed here, creating new item in database
playerSquad := dbmapping . SquadPlayer { }
playerSquad . SquadID = squadRaw . ID
playerSquad . PlayerID = playerRaw . ID
playerSquad . UserType = userType
playerSquad . AuthorID = adderRaw . ID
playerSquad . CreatedAt = time . Now ( ) . UTC ( )
_ , err = c . Db . NamedExec ( "INSERT INTO squads_players VALUES(NULL, :squad_id, :player_id, :user_type, :author_id, :created_at)" , & playerSquad )
if err != nil {
c . Log . Error ( err . Error ( ) )
return s . squadUserAdditionFailure ( update )
}
return s . squadUserAdditionSuccess ( update )
}
2017-11-19 22:16:11 +04:00
// CreateSquad creates new squad from chat if not already exist
func ( s * Squader ) CreateSquad ( update * tgbotapi . Update ) string {
commandArugments := update . Message . CommandArguments ( )
argumentsRx := regexp . MustCompile ( ` (\d+)\s(\d+) ` )
if ! argumentsRx . MatchString ( commandArugments ) {
return s . squadCreationFailure ( update )
}
chatNumbers := strings . Split ( commandArugments , " " )
if len ( chatNumbers ) < 2 {
return s . squadCreationFailure ( update )
}
chatID , _ := strconv . Atoi ( chatNumbers [ 0 ] )
if chatID == 0 {
return s . squadCreationFailure ( update )
}
floodChatID , _ := strconv . Atoi ( chatNumbers [ 1 ] )
if floodChatID == 0 {
return s . squadCreationFailure ( update )
}
_ , ok := s . createSquad ( update , chatID , floodChatID )
if ok == "fail" {
return s . squadCreationFailure ( update )
} else if ok == "dup" {
return s . squadCreationDuplicate ( update )
}
return s . squadCreationSuccess ( update )
}