DataCache and changes for game update
Recent game update changed pokememes view in pokedeks, so we need to reflect it by updating parser. Introducing DataCache - a silver bullet for eliminating lags linked to database queries. Less queries, more in RAM, faster work. Needs testing in production environment.
This commit is contained in:
parent
074fc4a1e3
commit
b8226d8aa8
61
Gopkg.lock
generated
61
Gopkg.lock
generated
@ -1,6 +1,18 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "bitbucket.org/pztrn/flagger"
|
||||
packages = ["."]
|
||||
revision = "c9b4726e1787adb01126cdf9a7932e2bccbb51a7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "bitbucket.org/pztrn/mogrus"
|
||||
packages = ["."]
|
||||
revision = "2e3a9d38c8e4b0036f714f88ef0fe9fc14b4c6b8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
packages = ["."]
|
||||
@ -16,8 +28,11 @@
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jmoiron/sqlx"
|
||||
packages = [".","reflectx"]
|
||||
revision = "3379e5993990b1f927fc8db926485e6f6becf2d2"
|
||||
packages = [
|
||||
".",
|
||||
"reflectx"
|
||||
]
|
||||
revision = "05cef0741ade10ca668982355b3f3f0bcf0ff0a8"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pressly/goose"
|
||||
@ -34,8 +49,8 @@
|
||||
[[projects]]
|
||||
name = "github.com/sirupsen/logrus"
|
||||
packages = ["."]
|
||||
revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e"
|
||||
version = "v1.0.3"
|
||||
revision = "d682213848ed68c0a260ca37d6dd5ace8423f5ba"
|
||||
version = "v1.0.4"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/technoweenie/multipartstreamer"
|
||||
@ -47,35 +62,39 @@
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "9f005a07e0d31d45e6656d241bb5c0f2efd4bc94"
|
||||
revision = "0efb9460aaf800c6376acf625be2853bceac2e06"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix","windows"]
|
||||
revision = "665f6529cca930e27b831a0d1dafffbe1c172924"
|
||||
packages = [
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "ff2a66f350cefa5c93a634eadb5d25bb60c85a9c"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
packages = [
|
||||
"internal/gen",
|
||||
"internal/triegen",
|
||||
"internal/ucd",
|
||||
"transform",
|
||||
"unicode/cldr",
|
||||
"unicode/norm"
|
||||
]
|
||||
revision = "e19ae1496984b1c655b8044a65c0300a3c878dd3"
|
||||
|
||||
[[projects]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
packages = ["."]
|
||||
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "lab.pztrn.name/golibs/flagger"
|
||||
packages = ["."]
|
||||
revision = "5cf6a6dd8fe8a4f37d1bb1e3deb5121c6e923668"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "lab.pztrn.name/golibs/mogrus"
|
||||
packages = ["."]
|
||||
revision = "a888e29e1fff06c2e6ebc607055a02de22a6ddae"
|
||||
revision = "d670f9405373e636a5a2765eea47fac0c9bc91a4"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "e26a19cb9a3e96a96b1d51599ead99341edc2278667ddf8a7dac4cd197fbe09d"
|
||||
inputs-digest = "99811036e66782056cb66f37e4a2570ac81f0e3da2fe399c4d54d83acc5a368d"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
40
Gopkg.toml
40
Gopkg.toml
@ -1,4 +1,3 @@
|
||||
|
||||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||
@ -19,14 +18,49 @@
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
required = ["github.com/go-sql-driver/mysql", "github.com/jmoiron/sqlx", "github.com/pressly/goose"]
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "bitbucket.org/pztrn/flagger"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "bitbucket.org/pztrn/mogrus"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
version = "1.3.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
version = "4.6.0"
|
||||
version = "4.6.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/jmoiron/sqlx"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pressly/goose"
|
||||
version = "2.1.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/robfig/cron"
|
||||
version = "1.0.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "golang.org/x/text"
|
||||
|
||||
[[constraint]]
|
||||
branch = "v2"
|
||||
name = "gopkg.in/yaml.v2"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
@ -4,10 +4,10 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/appcontext"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/broadcaster"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/chatter"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/datacache"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/forwarder"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/migrations"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/orders"
|
||||
@ -20,6 +20,7 @@ import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/talkers"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/users"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/welcomer"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -34,6 +35,7 @@ func main() {
|
||||
router.New(c)
|
||||
migrations.New(c)
|
||||
c.RunDatabaseMigrations()
|
||||
datacache.New(c)
|
||||
forwarder.New(c)
|
||||
pokedexer.New(c)
|
||||
pinner.New(c)
|
||||
|
@ -4,13 +4,13 @@
|
||||
package appcontext
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/robfig/cron"
|
||||
"bitbucket.org/pztrn/flagger"
|
||||
"bitbucket.org/pztrn/mogrus"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/broadcaster/broadcasterinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/chatter/chatterinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/config"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/connections"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/datacache/datacacheinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/forwarder/forwarderinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/migrations/migrationsinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/orders/ordersinterface"
|
||||
@ -23,8 +23,9 @@ import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/talkers/talkersinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/users/usersinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/welcomer/welcomerinterface"
|
||||
"lab.pztrn.name/golibs/flagger"
|
||||
"lab.pztrn.name/golibs/mogrus"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/robfig/cron"
|
||||
"os"
|
||||
)
|
||||
|
||||
@ -35,6 +36,7 @@ type Context struct {
|
||||
Cron *cron.Cron
|
||||
Log *mogrus.LoggerHandler
|
||||
Bot *tgbotapi.BotAPI
|
||||
DataCache datacacheinterface.DataCacheInterface
|
||||
Forwarder forwarderinterface.ForwarderInterface
|
||||
Migrations migrationsinterface.MigrationsInterface
|
||||
Router routerinterface.RouterInterface
|
||||
@ -157,6 +159,12 @@ func (c *Context) RegisterChatterInterface(ci chatterinterface.ChatterInterface)
|
||||
c.Chatter.Init()
|
||||
}
|
||||
|
||||
// RegisterDataCacheInterface registers datacache interface in application
|
||||
func (c *Context) RegisterDataCacheInterface(di datacacheinterface.DataCacheInterface) {
|
||||
c.DataCache = di
|
||||
c.DataCache.Init()
|
||||
}
|
||||
|
||||
// RegisterSquaderInterface registers squader interface in application
|
||||
func (c *Context) RegisterSquaderInterface(si squaderinterface.SquaderInterface) {
|
||||
c.Squader = si
|
||||
|
@ -4,8 +4,8 @@
|
||||
package chatter
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -31,12 +31,13 @@ func (ct *Chatter) userPrivilegesCheck(update *tgbotapi.Update, user *tgbotapi.U
|
||||
}
|
||||
}
|
||||
|
||||
playerRaw, ok := c.Users.GetOrCreatePlayer(user.ID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetPlayerByTelegramID(user.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
if c.Users.PlayerBetterThan(&playerRaw, "admin") {
|
||||
if c.Users.PlayerBetterThan(playerRaw, "admin") {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -51,7 +52,7 @@ func (ct *Chatter) userPrivilegesCheck(update *tgbotapi.Update, user *tgbotapi.U
|
||||
return true
|
||||
}
|
||||
default:
|
||||
availableChatsForUser, _ := c.Squader.GetAvailableSquadChatsForUser(&playerRaw)
|
||||
availableChatsForUser, _ := c.Squader.GetAvailableSquadChatsForUser(playerRaw)
|
||||
for i := range availableChatsForUser {
|
||||
if update.Message.Chat.ID == availableChatsForUser[i].TelegramID {
|
||||
return true
|
||||
|
@ -4,9 +4,9 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"bitbucket.org/pztrn/mogrus"
|
||||
"gopkg.in/yaml.v2"
|
||||
"io/ioutil"
|
||||
"lab.pztrn.name/golibs/mogrus"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
|
@ -4,11 +4,11 @@
|
||||
package connections
|
||||
|
||||
import (
|
||||
"bitbucket.org/pztrn/mogrus"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/config"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/config"
|
||||
"lab.pztrn.name/golibs/mogrus"
|
||||
)
|
||||
|
||||
// BotInit initializes connection to Telegram
|
||||
|
34
lib/datacache/datacacheinterface/datacacheinterface.go
Normal file
34
lib/datacache/datacacheinterface/datacacheinterface.go
Normal file
@ -0,0 +1,34 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacacheinterface
|
||||
|
||||
import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
)
|
||||
|
||||
// DataCacheInterface implements DataCache for importing via appcontext.
|
||||
type DataCacheInterface interface {
|
||||
Init()
|
||||
|
||||
AddPlayer(player *dbmapping.Player) (int, error)
|
||||
GetOrCreatePlayerByTelegramID(telegramID int) (*dbmapping.Player, error)
|
||||
GetPlayerByID(playerID int) (*dbmapping.Player, error)
|
||||
GetPlayerByTelegramID(telegramID int) (*dbmapping.Player, error)
|
||||
UpdatePlayerFields(player *dbmapping.Player) (*dbmapping.Player, error)
|
||||
UpdatePlayerTimestamp(playerID int) error
|
||||
|
||||
AddProfile(profile *dbmapping.Profile) (int, error)
|
||||
GetPlayersWithCurrentProfiles() map[int]*dbmapping.PlayerProfile
|
||||
GetProfileByID(profileID int) (*dbmapping.Profile, error)
|
||||
GetProfileByPlayerID(playerID int) (*dbmapping.Profile, error)
|
||||
|
||||
AddPokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error)
|
||||
GetAllPokememes() map[int]*dbmapping.PokememeFull
|
||||
GetPokememeByID(pokememeID int) (*dbmapping.PokememeFull, error)
|
||||
GetPokememeByName(name string) (*dbmapping.PokememeFull, error)
|
||||
DeletePokememeByID(pokememeID int) error
|
||||
|
||||
GetLeagueBySymbol(symbol string) (*dbmapping.League, error)
|
||||
GetWeaponTypeByName(name string) (*dbmapping.Weapon, error)
|
||||
}
|
45
lib/datacache/elements.go
Normal file
45
lib/datacache/elements.go
Normal file
@ -0,0 +1,45 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initElements() {
|
||||
c.Log.Info("Initializing Elements storage...")
|
||||
dc.elements = make(map[int]*dbmapping.Element)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadElements() {
|
||||
c.Log.Info("Load current Elements data from database to DataCache...")
|
||||
elements := []dbmapping.Element{}
|
||||
err := c.Db.Select(&elements, "SELECT * FROM elements")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.elementsMutex.Lock()
|
||||
for i := range elements {
|
||||
dc.elements[elements[i].ID] = &elements[i]
|
||||
}
|
||||
c.Log.Info("Loaded elements in DataCache: " + strconv.Itoa(len(dc.elements)))
|
||||
dc.elementsMutex.Unlock()
|
||||
}
|
||||
|
||||
func (dc *DataCache) findElementIDBySymbol(symbol string) (int, error) {
|
||||
dc.elementsMutex.Lock()
|
||||
for i := range dc.elements {
|
||||
if dc.elements[i].Symbol == symbol {
|
||||
dc.elementsMutex.Unlock()
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
dc.elementsMutex.Unlock()
|
||||
return 0, errors.New("There is no element with symbol = " + symbol)
|
||||
}
|
76
lib/datacache/exported.go
Normal file
76
lib/datacache/exported.go
Normal file
@ -0,0 +1,76 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/appcontext"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/datacache/datacacheinterface"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
c *appcontext.Context
|
||||
)
|
||||
|
||||
// DataCache is a function-handling struct for package datacache.
|
||||
// Also, it's a data cache: it handles all data, powered by DataCache functions.
|
||||
type DataCache struct {
|
||||
// Players — users of bot
|
||||
players map[int]*dbmapping.Player
|
||||
playersMutex sync.Mutex
|
||||
// Profiles - game profiles, no matter, actual or not
|
||||
profiles map[int]*dbmapping.Profile
|
||||
profilesMutex sync.Mutex
|
||||
// Current profiles - actual profiles for players, mostly used by bot
|
||||
// Note: int in this array for player ID, not for profile ID
|
||||
currentProfiles map[int]*dbmapping.Profile
|
||||
currentProfilesMutex sync.Mutex
|
||||
// Pokememes
|
||||
pokememes map[int]*dbmapping.Pokememe
|
||||
pokememesMutex sync.Mutex
|
||||
// Pokememes with all supported data
|
||||
fullPokememes map[int]*dbmapping.PokememeFull
|
||||
fullPokememesMutex sync.Mutex
|
||||
|
||||
// Elements
|
||||
elements map[int]*dbmapping.Element
|
||||
elementsMutex sync.Mutex
|
||||
// Leagues
|
||||
leagues map[int]*dbmapping.League
|
||||
leaguesMutex sync.Mutex
|
||||
// Locations
|
||||
locations map[int]*dbmapping.Location
|
||||
locationsMutex sync.Mutex
|
||||
// Weapons
|
||||
weapons map[int]*dbmapping.Weapon
|
||||
weaponsMutex sync.Mutex
|
||||
}
|
||||
|
||||
// New is an initialization function for appcontext
|
||||
func New(ac *appcontext.Context) {
|
||||
c = ac
|
||||
dc := &DataCache{}
|
||||
c.RegisterDataCacheInterface(datacacheinterface.DataCacheInterface(dc))
|
||||
}
|
||||
|
||||
// Init is a initialization function for package
|
||||
func (dc *DataCache) Init() {
|
||||
c.Log.Info("Initializing DataCache...")
|
||||
|
||||
dc.initElements()
|
||||
dc.loadElements()
|
||||
dc.initLeagues()
|
||||
dc.loadLeagues()
|
||||
dc.initLocations()
|
||||
dc.loadLocations()
|
||||
dc.initWeapons()
|
||||
dc.loadWeapons()
|
||||
dc.initPokememes()
|
||||
dc.loadPokememes()
|
||||
dc.initPlayers()
|
||||
dc.loadPlayers()
|
||||
dc.initProfiles()
|
||||
dc.loadProfiles()
|
||||
}
|
48
lib/datacache/leagues.go
Normal file
48
lib/datacache/leagues.go
Normal file
@ -0,0 +1,48 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initLeagues() {
|
||||
c.Log.Info("Initializing Leagues storage...")
|
||||
dc.leagues = make(map[int]*dbmapping.League)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadLeagues() {
|
||||
c.Log.Info("Load current Leagues data from database to DataCache...")
|
||||
leagues := []dbmapping.League{}
|
||||
err := c.Db.Select(&leagues, "SELECT * FROM leagues")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.leaguesMutex.Lock()
|
||||
for i := range leagues {
|
||||
dc.leagues[leagues[i].ID] = &leagues[i]
|
||||
}
|
||||
c.Log.Info("Loaded leagues in DataCache: " + strconv.Itoa(len(dc.leagues)))
|
||||
dc.leaguesMutex.Unlock()
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// GetLeagueBySymbol returns league from datacache by emoji
|
||||
func (dc *DataCache) GetLeagueBySymbol(symbol string) (*dbmapping.League, error) {
|
||||
dc.leaguesMutex.Lock()
|
||||
for i := range dc.leagues {
|
||||
if dc.leagues[i].Symbol == symbol {
|
||||
dc.leaguesMutex.Unlock()
|
||||
return dc.leagues[i], nil
|
||||
}
|
||||
}
|
||||
|
||||
dc.leaguesMutex.Unlock()
|
||||
return nil, errors.New("There is no league with symbol = " + symbol)
|
||||
}
|
45
lib/datacache/locations.go
Normal file
45
lib/datacache/locations.go
Normal file
@ -0,0 +1,45 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initLocations() {
|
||||
c.Log.Info("Initializing Locations storage...")
|
||||
dc.locations = make(map[int]*dbmapping.Location)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadLocations() {
|
||||
c.Log.Info("Load current Locations data from database to DataCache...")
|
||||
locations := []dbmapping.Location{}
|
||||
err := c.Db.Select(&locations, "SELECT * FROM locations")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.locationsMutex.Lock()
|
||||
for i := range locations {
|
||||
dc.locations[locations[i].ID] = &locations[i]
|
||||
}
|
||||
c.Log.Info("Loaded locations in DataCache: " + strconv.Itoa(len(dc.locations)))
|
||||
dc.locationsMutex.Unlock()
|
||||
}
|
||||
|
||||
func (dc *DataCache) findLocationIDByName(name string) (int, error) {
|
||||
dc.locationsMutex.Lock()
|
||||
for i := range dc.locations {
|
||||
if dc.locations[i].Name == name {
|
||||
dc.locationsMutex.Unlock()
|
||||
return i, nil
|
||||
}
|
||||
}
|
||||
|
||||
dc.locationsMutex.Unlock()
|
||||
return 0, errors.New("There is no location with name = " + name)
|
||||
}
|
157
lib/datacache/players.go
Normal file
157
lib/datacache/players.go
Normal file
@ -0,0 +1,157 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initPlayers() {
|
||||
c.Log.Info("Initializing Players storage...")
|
||||
dc.players = make(map[int]*dbmapping.Player)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadPlayers() {
|
||||
c.Log.Info("Load current Players data from database to DataCache...")
|
||||
players := []dbmapping.Player{}
|
||||
err := c.Db.Select(&players, "SELECT * FROM players")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.playersMutex.Lock()
|
||||
for i := range players {
|
||||
dc.players[players[i].ID] = &players[i]
|
||||
}
|
||||
c.Log.Info("Loaded players in DataCache: " + strconv.Itoa(len(dc.players)))
|
||||
dc.playersMutex.Unlock()
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// AddPlayer creates new player in database
|
||||
func (dc *DataCache) AddPlayer(player *dbmapping.Player) (int, error) {
|
||||
c.Log.Info("DataCache: Creating new user...")
|
||||
_, err := c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :status, :created_at, :updated_at)", &player)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return 0, err
|
||||
}
|
||||
|
||||
insertedPlayer := dbmapping.Player{}
|
||||
err = c.Db.Get(&insertedPlayer, c.Db.Rebind("SELECT * FROM players WHERE telegram_id=:telegram_id, league_id=:league_id, status=:status, created_at=:created_at, updated_at=:updated_at"), &player)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return 0, err
|
||||
}
|
||||
|
||||
dc.playersMutex.Lock()
|
||||
dc.players[insertedPlayer.ID] = &insertedPlayer
|
||||
dc.playersMutex.Unlock()
|
||||
|
||||
return insertedPlayer.ID, nil
|
||||
}
|
||||
|
||||
// GetOrCreatePlayerByTelegramID finds user by Telegram ID and creates one if not exist
|
||||
func (dc *DataCache) GetOrCreatePlayerByTelegramID(telegramID int) (*dbmapping.Player, error) {
|
||||
c.Log.Info("DataCache: Getting player with Telegram ID=", telegramID)
|
||||
|
||||
var player *dbmapping.Player
|
||||
dc.playersMutex.Lock()
|
||||
for i := range dc.players {
|
||||
if dc.players[i].TelegramID == telegramID {
|
||||
player = dc.players[i]
|
||||
}
|
||||
}
|
||||
dc.playersMutex.Unlock()
|
||||
|
||||
if player == nil {
|
||||
c.Log.Info("There is no such user, creating one...")
|
||||
newPlayer := dbmapping.Player{}
|
||||
newPlayer.TelegramID = telegramID
|
||||
newPlayer.LeagueID = 0
|
||||
newPlayer.Status = "nobody"
|
||||
newPlayer.CreatedAt = time.Now().UTC()
|
||||
newPlayer.UpdatedAt = time.Now().UTC()
|
||||
|
||||
newPlayerID, err := dc.AddPlayer(&newPlayer)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
player = dc.players[newPlayerID]
|
||||
}
|
||||
|
||||
return player, nil
|
||||
}
|
||||
|
||||
// GetPlayerByID returns player from datacache by ID
|
||||
func (dc *DataCache) GetPlayerByID(playerID int) (*dbmapping.Player, error) {
|
||||
c.Log.Info("DataCache: Getting player with ID=", playerID)
|
||||
if dc.players[playerID] != nil {
|
||||
return dc.players[playerID], nil
|
||||
}
|
||||
|
||||
return nil, errors.New("There is no user with ID = " + strconv.Itoa(playerID))
|
||||
}
|
||||
|
||||
// GetPlayerByTelegramID returns player with such Telegram ID
|
||||
func (dc *DataCache) GetPlayerByTelegramID(telegramID int) (*dbmapping.Player, error) {
|
||||
c.Log.Info("DataCache: Getting player with Telegram ID=", telegramID)
|
||||
|
||||
var player *dbmapping.Player
|
||||
dc.playersMutex.Lock()
|
||||
for i := range dc.players {
|
||||
if dc.players[i].TelegramID == telegramID {
|
||||
player = dc.players[i]
|
||||
}
|
||||
}
|
||||
dc.playersMutex.Unlock()
|
||||
|
||||
if player != nil {
|
||||
return player, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("There is no user with Telegram ID = " + strconv.Itoa(telegramID))
|
||||
}
|
||||
|
||||
// UpdatePlayerFields writes new fields to player
|
||||
func (dc *DataCache) UpdatePlayerFields(player *dbmapping.Player) (*dbmapping.Player, error) {
|
||||
if dc.players[player.ID] != nil {
|
||||
_, err := c.Db.NamedExec("UPDATE `players` SET league_id=:league_id, status=:status WHERE id=:id", player)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return dc.players[player.ID], err
|
||||
}
|
||||
dc.playersMutex.Lock()
|
||||
dc.players[player.ID].LeagueID = player.LeagueID
|
||||
dc.players[player.ID].Status = player.Status
|
||||
dc.playersMutex.Unlock()
|
||||
return dc.players[player.ID], nil
|
||||
}
|
||||
|
||||
return nil, errors.New("There is no user with ID = " + strconv.Itoa(player.ID))
|
||||
}
|
||||
|
||||
// UpdatePlayerTimestamp writes current update time to player
|
||||
func (dc *DataCache) UpdatePlayerTimestamp(playerID int) error {
|
||||
if dc.players[playerID] != nil {
|
||||
dc.playersMutex.Lock()
|
||||
dc.players[playerID].UpdatedAt = time.Now().UTC()
|
||||
_, err := c.Db.NamedExec("UPDATE `players` SET updated_at=:updated_at WHERE id=:id", dc.players[playerID])
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
dc.playersMutex.Unlock()
|
||||
return err
|
||||
}
|
||||
dc.playersMutex.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("There is no user with ID = " + strconv.Itoa(playerID))
|
||||
}
|
297
lib/datacache/pokememes.go
Normal file
297
lib/datacache/pokememes.go
Normal file
@ -0,0 +1,297 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initPokememes() {
|
||||
c.Log.Info("Initializing Pokememes storage...")
|
||||
dc.pokememes = make(map[int]*dbmapping.Pokememe)
|
||||
dc.fullPokememes = make(map[int]*dbmapping.PokememeFull)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadPokememes() {
|
||||
c.Log.Info("Load current Pokememes data from database to DataCache...")
|
||||
pokememes := []dbmapping.Pokememe{}
|
||||
err := c.Db.Select(&pokememes, "SELECT * FROM pokememes")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
pokememesElements := []dbmapping.PokememeElement{}
|
||||
err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err)
|
||||
}
|
||||
pokememesLocations := []dbmapping.PokememeLocation{}
|
||||
err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err)
|
||||
}
|
||||
|
||||
dc.pokememesMutex.Lock()
|
||||
dc.fullPokememesMutex.Lock()
|
||||
for i := range pokememes {
|
||||
dc.pokememes[pokememes[i].ID] = &pokememes[i]
|
||||
|
||||
// Filling fullPokememes
|
||||
fullPokememe := dbmapping.PokememeFull{}
|
||||
elementsListed := []dbmapping.Element{}
|
||||
locationsListed := []dbmapping.Location{}
|
||||
|
||||
for j := range pokememesLocations {
|
||||
if pokememesLocations[j].PokememeID == pokememes[i].ID {
|
||||
for l := range dc.locations {
|
||||
if pokememesLocations[j].LocationID == dc.locations[l].ID {
|
||||
locationsListed = append(locationsListed, *dc.locations[l])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range pokememesElements {
|
||||
if pokememesElements[k].PokememeID == pokememes[i].ID {
|
||||
for e := range dc.elements {
|
||||
if pokememesElements[k].ElementID == dc.elements[e].ID {
|
||||
elementsListed = append(elementsListed, *dc.elements[e])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullPokememe.Pokememe = pokememes[i]
|
||||
fullPokememe.Elements = elementsListed
|
||||
fullPokememe.Locations = locationsListed
|
||||
|
||||
dc.fullPokememes[pokememes[i].ID] = &fullPokememe
|
||||
}
|
||||
c.Log.Info("Loaded pokememes with all additional information in DataCache: " + strconv.Itoa(len(dc.fullPokememes)))
|
||||
dc.pokememesMutex.Unlock()
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// AddPokememe adds pokememe from parser
|
||||
func (dc *DataCache) AddPokememe(pokememeData map[string]string, pokememeLocations map[string]string, pokememeElements map[string]string) (int, error) {
|
||||
_, noerr := dc.GetPokememeByName(pokememeData["name"])
|
||||
if noerr == nil {
|
||||
return 0, errors.New("This pokememe already exists")
|
||||
}
|
||||
|
||||
gradeInt := c.Statistics.GetPoints(pokememeData["grade"])
|
||||
attackInt := c.Statistics.GetPoints(pokememeData["attack"])
|
||||
hpInt := c.Statistics.GetPoints(pokememeData["hp"])
|
||||
mpInt := c.Statistics.GetPoints(pokememeData["mp"])
|
||||
defenceInt := attackInt
|
||||
if pokememeData["defence"] != "" {
|
||||
defenceInt = c.Statistics.GetPoints(pokememeData["defence"])
|
||||
}
|
||||
priceInt := c.Statistics.GetPoints(pokememeData["price"])
|
||||
creatorID := c.Statistics.GetPoints(pokememeData["creator_id"])
|
||||
|
||||
if !(gradeInt != 0 && attackInt != 0 && hpInt != 0 && mpInt != 0 && defenceInt != 0 && priceInt != 0 && creatorID != 0) {
|
||||
return 0, errors.New("Some of the required numerical values are empty")
|
||||
}
|
||||
|
||||
pokememe := dbmapping.Pokememe{}
|
||||
pokememe.Grade = gradeInt
|
||||
pokememe.Name = pokememeData["name"]
|
||||
pokememe.Description = pokememeData["description"]
|
||||
pokememe.Attack = attackInt
|
||||
pokememe.HP = hpInt
|
||||
pokememe.MP = mpInt
|
||||
pokememe.Defence = defenceInt
|
||||
pokememe.Price = priceInt
|
||||
if pokememeData["purchaseable"] == "true" {
|
||||
pokememe.Purchaseable = true
|
||||
} else {
|
||||
pokememe.Purchaseable = false
|
||||
}
|
||||
pokememe.ImageURL = pokememeData["image"]
|
||||
pokememe.PlayerID = creatorID
|
||||
pokememe.CreatedAt = time.Now().UTC()
|
||||
|
||||
locations := []dbmapping.Location{}
|
||||
elements := []dbmapping.Element{}
|
||||
|
||||
for i := range pokememeLocations {
|
||||
locationID, err := dc.findLocationIDByName(pokememeLocations[i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
locations = append(locations, *dc.locations[locationID])
|
||||
}
|
||||
|
||||
for i := range pokememeElements {
|
||||
elementID, err := dc.findElementIDBySymbol(pokememeElements[i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
elements = append(elements, *dc.elements[elementID])
|
||||
}
|
||||
|
||||
// All objects are prepared, let's fill database with it!
|
||||
c.Log.Debug("Filling pokememe...")
|
||||
_, err := c.Db.NamedExec("INSERT INTO pokememes VALUES(NULL, :grade, :name, :description, :attack, :hp, :mp, :defence, :price, :purchaseable, :image_url, :player_id, :created_at)", &pokememe)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
c.Log.Debug("Finding newly added pokememe...")
|
||||
insertedPokememe := dbmapping.Pokememe{}
|
||||
err = c.Db.Get(&insertedPokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE grade=? AND name=?"), pokememe.Grade, pokememe.Name)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// Now we creating locations and elements links
|
||||
locationsAndElementsFilledSuccessfully := true
|
||||
c.Log.Debug("Filling locations...")
|
||||
for i := range locations {
|
||||
link := dbmapping.PokememeLocation{}
|
||||
link.PokememeID = insertedPokememe.ID
|
||||
link.LocationID = locations[i].ID
|
||||
link.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err := c.Db.NamedExec("INSERT INTO pokememes_locations VALUES(NULL, :pokememe_id, :location_id, :created_at)", &link)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
locationsAndElementsFilledSuccessfully = false
|
||||
}
|
||||
}
|
||||
|
||||
c.Log.Debug("Filling elements...")
|
||||
for i := range elements {
|
||||
link := dbmapping.PokememeElement{}
|
||||
link.PokememeID = insertedPokememe.ID
|
||||
link.ElementID = elements[i].ID
|
||||
link.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err := c.Db.NamedExec("INSERT INTO pokememes_elements VALUES(NULL, :pokememe_id, :element_id, :created_at)", &link)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
locationsAndElementsFilledSuccessfully = false
|
||||
}
|
||||
}
|
||||
|
||||
if !locationsAndElementsFilledSuccessfully {
|
||||
c.Log.Debug("All fucked up, removing what we have already added...")
|
||||
// There is something fucked up. In normal state we're should never reach this code
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &insertedPokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &insertedPokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes where id=:id", &insertedPokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
return 0, errors.New("Failed to add pokememe to database")
|
||||
}
|
||||
|
||||
fullPokememe := dbmapping.PokememeFull{}
|
||||
fullPokememe.Pokememe = insertedPokememe
|
||||
fullPokememe.Locations = locations
|
||||
fullPokememe.Elements = elements
|
||||
|
||||
// Filling data cache
|
||||
dc.pokememesMutex.Lock()
|
||||
dc.fullPokememesMutex.Lock()
|
||||
dc.pokememes[insertedPokememe.ID] = &insertedPokememe
|
||||
dc.fullPokememes[insertedPokememe.ID] = &fullPokememe
|
||||
dc.pokememesMutex.Unlock()
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
|
||||
return insertedPokememe.ID, nil
|
||||
}
|
||||
|
||||
// GetAllPokememes returns all pokememes
|
||||
// Index in resulted map counts all pokememes ordered by grade and alphabetically
|
||||
func (dc *DataCache) GetAllPokememes() map[int]*dbmapping.PokememeFull {
|
||||
pokememes := make(map[int]*dbmapping.PokememeFull)
|
||||
dc.fullPokememesMutex.Lock()
|
||||
|
||||
var keys []string
|
||||
keysToIDs := make(map[string]int)
|
||||
for i := range dc.fullPokememes {
|
||||
keys = append(keys, strconv.Itoa(dc.fullPokememes[i].Pokememe.Grade)+"_"+dc.fullPokememes[i].Pokememe.Name)
|
||||
keysToIDs[strconv.Itoa(dc.fullPokememes[i].Pokememe.Grade)+"_"+dc.fullPokememes[i].Pokememe.Name] = i
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
idx := 0
|
||||
for _, k := range keys {
|
||||
pokememes[idx] = dc.fullPokememes[keysToIDs[k]]
|
||||
idx++
|
||||
}
|
||||
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return pokememes
|
||||
}
|
||||
|
||||
// GetPokememeByID returns pokememe with additional information by ID
|
||||
func (dc *DataCache) GetPokememeByID(pokememeID int) (*dbmapping.PokememeFull, error) {
|
||||
dc.fullPokememesMutex.Lock()
|
||||
if dc.fullPokememes[pokememeID] != nil {
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return dc.fullPokememes[pokememeID], nil
|
||||
}
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return nil, errors.New("There is no pokememe with ID = " + strconv.Itoa(pokememeID))
|
||||
}
|
||||
|
||||
// GetPokememeByName returns pokememe from datacache by name
|
||||
func (dc *DataCache) GetPokememeByName(name string) (*dbmapping.PokememeFull, error) {
|
||||
dc.fullPokememesMutex.Lock()
|
||||
for i := range dc.fullPokememes {
|
||||
if strings.HasPrefix(dc.fullPokememes[i].Pokememe.Name, name) {
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return dc.fullPokememes[i], nil
|
||||
}
|
||||
}
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return nil, errors.New("There is no pokememe with name = " + name)
|
||||
}
|
||||
|
||||
// DeletePokememeByID removes pokememe from database
|
||||
func (dc *DataCache) DeletePokememeByID(pokememeID int) error {
|
||||
pokememe, err := dc.GetPokememeByID(pokememeID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes where id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
|
||||
dc.pokememesMutex.Lock()
|
||||
dc.fullPokememesMutex.Lock()
|
||||
delete(dc.pokememes, pokememe.Pokememe.ID)
|
||||
delete(dc.fullPokememes, pokememe.Pokememe.ID)
|
||||
dc.pokememesMutex.Unlock()
|
||||
dc.fullPokememesMutex.Unlock()
|
||||
return nil
|
||||
}
|
118
lib/datacache/profiles.go
Normal file
118
lib/datacache/profiles.go
Normal file
@ -0,0 +1,118 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initProfiles() {
|
||||
c.Log.Info("Initializing Profiles storage...")
|
||||
dc.profiles = make(map[int]*dbmapping.Profile)
|
||||
dc.currentProfiles = make(map[int]*dbmapping.Profile)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadProfiles() {
|
||||
c.Log.Info("Load current Profiles data from database to DataCache...")
|
||||
profiles := []dbmapping.Profile{}
|
||||
err := c.Db.Select(&profiles, "SELECT * FROM profiles")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.profilesMutex.Lock()
|
||||
dc.currentProfilesMutex.Lock()
|
||||
for i := range profiles {
|
||||
dc.profiles[profiles[i].ID] = &profiles[i]
|
||||
|
||||
// Filling current profiles
|
||||
if dc.currentProfiles[profiles[i].PlayerID] != nil {
|
||||
if dc.currentProfiles[profiles[i].PlayerID].CreatedAt.Before(profiles[i].CreatedAt) {
|
||||
dc.currentProfiles[profiles[i].PlayerID] = &profiles[i]
|
||||
}
|
||||
}
|
||||
|
||||
dc.currentProfiles[profiles[i].PlayerID] = &profiles[i]
|
||||
}
|
||||
c.Log.Info("Loaded profiles in DataCache: " + strconv.Itoa(len(dc.profiles)))
|
||||
c.Log.Info("Loaded current profiles in DataCache: " + strconv.Itoa(len(dc.currentProfiles)))
|
||||
dc.profilesMutex.Unlock()
|
||||
dc.currentProfilesMutex.Unlock()
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// AddProfile creates new profile in database
|
||||
func (dc *DataCache) AddProfile(profile *dbmapping.Profile) (int, error) {
|
||||
_, err := c.Db.NamedExec("INSERT INTO `profiles` VALUES(NULL, :player_id, :nickname, :telegram_nickname, :level_id, :pokeballs, :wealth, :pokememes_wealth, :exp, :egg_exp, :power, :weapon_id, :crystalls, :created_at)", &profile)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return 0, err
|
||||
}
|
||||
insertedProfile := dbmapping.Profile{}
|
||||
err = c.Db.Get(&insertedProfile, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? AND created_at=?"), profile.PlayerID, profile.CreatedAt)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return 0, err
|
||||
}
|
||||
|
||||
dc.profilesMutex.Lock()
|
||||
dc.currentProfilesMutex.Lock()
|
||||
dc.profiles[insertedProfile.ID] = &insertedProfile
|
||||
dc.currentProfiles[insertedProfile.PlayerID] = &insertedProfile
|
||||
dc.currentProfilesMutex.Unlock()
|
||||
dc.profilesMutex.Unlock()
|
||||
|
||||
return insertedProfile.ID, nil
|
||||
}
|
||||
|
||||
// GetPlayersWithCurrentProfiles returns users with profiles, if exist
|
||||
func (dc *DataCache) GetPlayersWithCurrentProfiles() map[int]*dbmapping.PlayerProfile {
|
||||
dc.currentProfilesMutex.Lock()
|
||||
dc.playersMutex.Lock()
|
||||
|
||||
users := make(map[int]*dbmapping.PlayerProfile)
|
||||
|
||||
for i := range dc.players {
|
||||
user := dbmapping.PlayerProfile{}
|
||||
user.Player = *dc.players[i]
|
||||
if dc.players[i].LeagueID != 0 {
|
||||
user.League = *dc.leagues[dc.players[i].LeagueID]
|
||||
}
|
||||
|
||||
if dc.currentProfiles[dc.players[i].ID] != nil {
|
||||
user.HaveProfile = true
|
||||
user.Profile = *dc.currentProfiles[dc.players[i].ID]
|
||||
} else {
|
||||
user.HaveProfile = false
|
||||
}
|
||||
|
||||
users[dc.players[i].ID] = &user
|
||||
}
|
||||
|
||||
dc.currentProfilesMutex.Unlock()
|
||||
dc.playersMutex.Unlock()
|
||||
return users
|
||||
}
|
||||
|
||||
// GetProfileByID returns profile from datacache by ID
|
||||
func (dc *DataCache) GetProfileByID(profileID int) (*dbmapping.Profile, error) {
|
||||
if dc.profiles[profileID] != nil {
|
||||
return dc.profiles[profileID], nil
|
||||
}
|
||||
|
||||
return nil, errors.New("There is no profile with ID = " + strconv.Itoa(profileID))
|
||||
}
|
||||
|
||||
// GetProfileByPlayerID returns current profile for player
|
||||
func (dc *DataCache) GetProfileByPlayerID(playerID int) (*dbmapping.Profile, error) {
|
||||
if dc.currentProfiles[playerID] != nil {
|
||||
return dc.currentProfiles[playerID], nil
|
||||
}
|
||||
|
||||
return nil, errors.New("There is no profile for user with ID = " + strconv.Itoa(playerID))
|
||||
}
|
48
lib/datacache/weapons.go
Normal file
48
lib/datacache/weapons.go
Normal file
@ -0,0 +1,48 @@
|
||||
// i2_bot – Instinct PokememBro Bot
|
||||
// Copyright (c) 2018 Vladimir "fat0troll" Hodakov
|
||||
|
||||
package datacache
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (dc *DataCache) initWeapons() {
|
||||
c.Log.Info("Initializing Weapons storage...")
|
||||
dc.weapons = make(map[int]*dbmapping.Weapon)
|
||||
}
|
||||
|
||||
func (dc *DataCache) loadWeapons() {
|
||||
c.Log.Info("Load current Weapons data from database to DataCache...")
|
||||
weapons := []dbmapping.Weapon{}
|
||||
err := c.Db.Select(&weapons, "SELECT * FROM weapons")
|
||||
if err != nil {
|
||||
// This is critical error and we need to stop immediately!
|
||||
c.Log.Fatal(err.Error())
|
||||
}
|
||||
|
||||
dc.weaponsMutex.Lock()
|
||||
for i := range weapons {
|
||||
dc.weapons[weapons[i].ID] = &weapons[i]
|
||||
}
|
||||
c.Log.Info("Loaded weapon types in DataCache: " + strconv.Itoa(len(dc.weapons)))
|
||||
dc.weaponsMutex.Unlock()
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// GetWeaponTypeByName returns weapon type from datacache by weapon name
|
||||
func (dc *DataCache) GetWeaponTypeByName(name string) (*dbmapping.Weapon, error) {
|
||||
dc.weaponsMutex.Lock()
|
||||
for i := range dc.weapons {
|
||||
if dc.weapons[i].Name == name {
|
||||
dc.weaponsMutex.Unlock()
|
||||
return dc.weapons[i], nil
|
||||
}
|
||||
}
|
||||
|
||||
dc.weaponsMutex.Unlock()
|
||||
return nil, errors.New("There is no weapon type with name = " + name)
|
||||
}
|
@ -24,24 +24,3 @@ type Profile struct {
|
||||
Crystalls int `db:"crystalls"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
}
|
||||
|
||||
// ProfileWithAddons is a struct, which represents `profiles` table item in database and some good external fields.
|
||||
type ProfileWithAddons struct {
|
||||
ID int `db:"id"`
|
||||
PlayerID int `db:"player_id"`
|
||||
TelegramID int `db:"telegram_id"`
|
||||
LeagueID int `db:"league_id"`
|
||||
LeagueSymbol string `db:"league_symbol"`
|
||||
Nickname string `db:"nickname"`
|
||||
TelegramNickname string `db:"telegram_nickname"`
|
||||
LevelID int `db:"level_id"`
|
||||
Pokeballs int `db:"pokeballs"`
|
||||
Wealth int `db:"wealth"`
|
||||
PokememesWealth int `db:"pokememes_wealth"`
|
||||
Exp int `db:"exp"`
|
||||
EggExp int `db:"egg_exp"`
|
||||
Power int `db:"power"`
|
||||
WeaponID int `db:"weapon_id"`
|
||||
Crystalls int `db:"crystalls"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
}
|
||||
|
@ -15,32 +15,12 @@ func (p *Pokedexer) DeletePokememe(update *tgbotapi.Update) string {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
pokememe, ok := p.GetPokememeByID(strconv.Itoa(pokememeNum))
|
||||
if !ok {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
_, err := c.Db.NamedExec("DELETE FROM pokememes WHERE id=:id", &pokememe.Pokememe)
|
||||
err := c.DataCache.DeletePokememeByID(pokememeNum)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_elements WHERE pokememe_id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Debug(err.Error())
|
||||
}
|
||||
|
||||
_, err = c.Db.NamedExec("DELETE FROM pokememes_locations WHERE pokememe_id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Debug(err.Error())
|
||||
}
|
||||
|
||||
_, err = c.Db.NamedExec("DELETE FROM profiles_pokememes WHERE pokememe_id=:id", &pokememe.Pokememe)
|
||||
if err != nil {
|
||||
c.Log.Debug(err.Error())
|
||||
}
|
||||
|
||||
message := "Покемем удалён."
|
||||
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
|
||||
|
@ -5,184 +5,50 @@ package pokedexer
|
||||
|
||||
import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Internal functions
|
||||
|
||||
func (p *Pokedexer) formFullPokememes(pokememes []dbmapping.Pokememe) ([]dbmapping.PokememeFull, bool) {
|
||||
pokememesArray := []dbmapping.PokememeFull{}
|
||||
elements := []dbmapping.Element{}
|
||||
err := c.Db.Select(&elements, "SELECT * FROM elements")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
}
|
||||
locations := []dbmapping.Location{}
|
||||
err = c.Db.Select(&locations, "SELECT * FROM locations")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
}
|
||||
pokememesElements := []dbmapping.PokememeElement{}
|
||||
err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
}
|
||||
pokememesLocations := []dbmapping.PokememeLocation{}
|
||||
err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
}
|
||||
|
||||
for i := range pokememes {
|
||||
fullPokememe := dbmapping.PokememeFull{}
|
||||
elementsListed := []dbmapping.Element{}
|
||||
locationsListed := []dbmapping.Location{}
|
||||
|
||||
for j := range pokememesLocations {
|
||||
if pokememesLocations[j].PokememeID == pokememes[i].ID {
|
||||
for l := range locations {
|
||||
if pokememesLocations[j].LocationID == locations[l].ID {
|
||||
locationsListed = append(locationsListed, locations[l])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range pokememesElements {
|
||||
if pokememesElements[k].PokememeID == pokememes[i].ID {
|
||||
for e := range elements {
|
||||
if pokememesElements[k].ElementID == elements[e].ID {
|
||||
elementsListed = append(elementsListed, elements[e])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullPokememe.Pokememe = pokememes[i]
|
||||
fullPokememe.Elements = elementsListed
|
||||
fullPokememe.Locations = locationsListed
|
||||
|
||||
pokememesArray = append(pokememesArray, fullPokememe)
|
||||
}
|
||||
|
||||
return pokememesArray, true
|
||||
}
|
||||
|
||||
// External functions
|
||||
|
||||
// GetPokememes returns all existing pokememes, known by bot
|
||||
func (p *Pokedexer) GetPokememes() ([]dbmapping.PokememeFull, bool) {
|
||||
pokememesArray := []dbmapping.PokememeFull{}
|
||||
pokememes := []dbmapping.Pokememe{}
|
||||
err := c.Db.Select(&pokememes, "SELECT * FROM pokememes ORDER BY grade asc, name asc")
|
||||
func (p *Pokedexer) getBestPokememes(playerID int) (map[int]*dbmapping.PokememeFull, bool) {
|
||||
pokememesArray := make(map[int]*dbmapping.PokememeFull)
|
||||
|
||||
playerRaw, err := c.DataCache.GetPlayerByID(playerID)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
c.Log.Error(err.Error())
|
||||
return pokememesArray, false
|
||||
}
|
||||
|
||||
pokememesArray, ok := p.formFullPokememes(pokememes)
|
||||
return pokememesArray, ok
|
||||
}
|
||||
|
||||
func (p *Pokedexer) getBestPokememes(playerID int) ([]dbmapping.PokememeFull, bool) {
|
||||
pokememesArray := []dbmapping.PokememeFull{}
|
||||
playerRaw, ok := c.Users.GetPlayerByID(playerID)
|
||||
if !ok {
|
||||
return pokememesArray, ok
|
||||
}
|
||||
profileRaw, ok := c.Users.GetProfile(playerID)
|
||||
if !ok {
|
||||
return pokememesArray, ok
|
||||
profileRaw, err := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return pokememesArray, false
|
||||
}
|
||||
|
||||
if playerRaw.LeagueID == 0 {
|
||||
return pokememesArray, false
|
||||
}
|
||||
|
||||
// TODO: make it more complicated
|
||||
pokememes := []dbmapping.Pokememe{}
|
||||
allPokememes := c.DataCache.GetAllPokememes()
|
||||
if profileRaw.LevelID < 4 {
|
||||
err := c.Db.Select(&pokememes, c.Db.Rebind("SELECT * FROM pokememes WHERE grade = ? ORDER BY attack DESC"), profileRaw.LevelID+1)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
for i := range allPokememes {
|
||||
if allPokememes[i].Pokememe.Grade == profileRaw.LevelID+1 {
|
||||
pokememesArray[allPokememes[i].Pokememe.Attack] = allPokememes[i]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err := c.Db.Select(&pokememes, c.Db.Rebind("SELECT p.* FROM pokememes p, pokememes_elements pe, elements e WHERE e.league_id = ? AND p.grade = ? AND pe.element_id = e.id AND pe.pokememe_id = p.id ORDER BY p.attack DESC"), playerRaw.LeagueID, profileRaw.LevelID+1)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return pokememesArray, false
|
||||
for i := range allPokememes {
|
||||
if allPokememes[i].Pokememe.Grade == profileRaw.LevelID+1 {
|
||||
matchLeague := false
|
||||
for j := range allPokememes[i].Elements {
|
||||
if allPokememes[i].Elements[j].LeagueID == playerRaw.LeagueID {
|
||||
matchLeague = true
|
||||
}
|
||||
}
|
||||
|
||||
pokememesArray, ok = p.formFullPokememes(pokememes)
|
||||
return pokememesArray, ok
|
||||
}
|
||||
|
||||
// GetPokememeByID returns single pokememe based on internal ID in database
|
||||
func (p *Pokedexer) GetPokememeByID(pokememeID string) (dbmapping.PokememeFull, bool) {
|
||||
fullPokememe := dbmapping.PokememeFull{}
|
||||
pokememe := dbmapping.Pokememe{}
|
||||
err := c.Db.Get(&pokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE id=?"), pokememeID)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return fullPokememe, false
|
||||
}
|
||||
elements := []dbmapping.Element{}
|
||||
err = c.Db.Select(&elements, "SELECT * FROM elements")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return fullPokememe, false
|
||||
}
|
||||
locations := []dbmapping.Location{}
|
||||
err = c.Db.Select(&locations, "SELECT * FROM locations")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return fullPokememe, false
|
||||
}
|
||||
pokememesElements := []dbmapping.PokememeElement{}
|
||||
err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements WHERE pokememe_id='"+strconv.Itoa(pokememe.ID)+"'")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return fullPokememe, false
|
||||
}
|
||||
pokememesLocations := []dbmapping.PokememeLocation{}
|
||||
err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations WHERE pokememe_id='"+strconv.Itoa(pokememe.ID)+"'")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return fullPokememe, false
|
||||
}
|
||||
|
||||
elementsListed := []dbmapping.Element{}
|
||||
locationsListed := []dbmapping.Location{}
|
||||
|
||||
for j := range pokememesLocations {
|
||||
if pokememesLocations[j].PokememeID == pokememe.ID {
|
||||
for l := range locations {
|
||||
if pokememesLocations[j].LocationID == locations[l].ID {
|
||||
locationsListed = append(locationsListed, locations[l])
|
||||
if matchLeague {
|
||||
pokememesArray[allPokememes[i].Pokememe.Attack] = allPokememes[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for k := range pokememesElements {
|
||||
if pokememesElements[k].PokememeID == pokememe.ID {
|
||||
for e := range elements {
|
||||
if pokememesElements[k].ElementID == elements[e].ID {
|
||||
elementsListed = append(elementsListed, elements[e])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fullPokememe.Pokememe = pokememe
|
||||
fullPokememe.Elements = elementsListed
|
||||
fullPokememe.Locations = locationsListed
|
||||
|
||||
return fullPokememe, true
|
||||
return pokememesArray, true
|
||||
}
|
||||
|
@ -4,248 +4,143 @@
|
||||
package pokedexer
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
// "time"
|
||||
)
|
||||
|
||||
// ParsePokememe parses pokememe, forwarded from PokememeBroBot, to database
|
||||
func (p *Pokedexer) ParsePokememe(update *tgbotapi.Update, playerRaw *dbmapping.Player) string {
|
||||
text := update.Message.Text
|
||||
var defendablePokememe = false
|
||||
pokememeStringsArray := strings.Split(text, "\n")
|
||||
pokememeStringsArray := strings.Split(update.Message.Text, "\n")
|
||||
pokememeRunesArray := make([][]rune, 0)
|
||||
for i := range pokememeStringsArray {
|
||||
pokememeRunesArray = append(pokememeRunesArray, []rune(pokememeStringsArray[i]))
|
||||
}
|
||||
|
||||
if len(pokememeRunesArray) == 13 {
|
||||
defendablePokememe = true
|
||||
pokememeData := make(map[string]string)
|
||||
pokememeLocations := make(map[string]string)
|
||||
pokememeElements := make(map[string]string)
|
||||
|
||||
hitPointsRx := regexp.MustCompile("(\\d|\\.)+(K|M)?")
|
||||
|
||||
for i := range pokememeStringsArray {
|
||||
c.Log.Debug("Processing string: " + pokememeStringsArray[i])
|
||||
if strings.Contains(pokememeStringsArray[i], "⃣") {
|
||||
// Strings with name and grade
|
||||
pokememeData["grade"] = string(pokememeRunesArray[i][0])
|
||||
pokememeData["name"] = string(pokememeRunesArray[i][3:])
|
||||
}
|
||||
|
||||
// Getting elements
|
||||
elements := []dbmapping.Element{}
|
||||
elementEmojis := make([]string, 0)
|
||||
elementEmojis = append(elementEmojis, string(pokememeRunesArray[4][11]))
|
||||
if len(pokememeRunesArray[4]) > 12 {
|
||||
elementEmojis = append(elementEmojis, string(pokememeRunesArray[4][13]))
|
||||
}
|
||||
if len(pokememeRunesArray[4]) > 14 {
|
||||
elementEmojis = append(elementEmojis, string(pokememeRunesArray[4][15]))
|
||||
if i == 1 {
|
||||
pokememeData["description"] = string(pokememeRunesArray[i])
|
||||
}
|
||||
|
||||
err := c.Db.Select(&elements, "SELECT * FROM elements WHERE symbol IN ('"+strings.Join(elementEmojis, "', '")+"')")
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "Обитает: ") {
|
||||
// Elements
|
||||
locationsString := strings.TrimPrefix(pokememeStringsArray[i], "Обитает: ")
|
||||
locationsArray := strings.Split(locationsString, ", ")
|
||||
for i := range locationsArray {
|
||||
pokememeLocations[strconv.Itoa(i)] = locationsArray[i]
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "Элементы: ") {
|
||||
// Elements
|
||||
elementsString := strings.TrimPrefix(pokememeStringsArray[i], "Элементы: ")
|
||||
elementsArray := strings.Split(elementsString, " ")
|
||||
for i := range elementsArray {
|
||||
pokememeElements[strconv.Itoa(i)] = elementsArray[i]
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "⚔Атака: ") {
|
||||
// Attack, HP, MP
|
||||
hitPoints := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
|
||||
if len(hitPoints) != 3 {
|
||||
c.Log.Error("Can't parse hitpoints!")
|
||||
c.Log.Debug("Points string was: " + string(pokememeRunesArray[i]))
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
pokememeData["attack"] = hitPoints[0]
|
||||
pokememeData["hp"] = hitPoints[1]
|
||||
pokememeData["mp"] = hitPoints[2]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "🛡Защита ") {
|
||||
// Defence for top-level pokememes
|
||||
defence := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
|
||||
if len(defence) != 1 {
|
||||
c.Log.Error("Can't parse defence!")
|
||||
c.Log.Debug("Defence string was: " + string(pokememeRunesArray[i]))
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
pokememeData["defence"] = defence[0]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "Стоимость :") {
|
||||
// Price
|
||||
price := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
|
||||
if len(price) != 1 {
|
||||
c.Log.Error("Can't parse price!")
|
||||
c.Log.Debug("Price string was: " + string(pokememeRunesArray[i]))
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
pokememeData["price"] = price[0]
|
||||
}
|
||||
|
||||
if strings.HasPrefix(pokememeStringsArray[i], "Купить: ") {
|
||||
// Purchaseability
|
||||
pokememeData["purchaseable"] = "false"
|
||||
if strings.Contains(pokememeStringsArray[i], "Можно") {
|
||||
pokememeData["purchaseable"] = "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Image
|
||||
for _, entity := range *update.Message.Entities {
|
||||
if entity.Type == "text_link" && entity.URL != "" {
|
||||
pokememeData["image"] = entity.URL
|
||||
}
|
||||
}
|
||||
|
||||
// Checking grade to be integer
|
||||
_, err := strconv.Atoi(pokememeData["grade"])
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
// Getting hit-points
|
||||
hitPointsRx := regexp.MustCompile("(\\d|\\.)+(K|M)?")
|
||||
hitPoints := hitPointsRx.FindAllString(string(pokememeRunesArray[5]), -1)
|
||||
if len(hitPoints) != 3 {
|
||||
c.Log.Error("Can't parse hitpoints!")
|
||||
c.Log.Debug(pokememeRunesArray[5])
|
||||
pokememeData["creator_id"] = strconv.Itoa(playerRaw.ID)
|
||||
|
||||
c.Log.Debugln("Pokememe data: ", pokememeData)
|
||||
c.Log.Debugln("Elements: ", pokememeElements)
|
||||
c.Log.Debugln("Locations: ", pokememeLocations)
|
||||
|
||||
if len(pokememeElements) == 0 {
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
defence := "0"
|
||||
price := "0"
|
||||
|
||||
locations := []dbmapping.Location{}
|
||||
|
||||
purchaseable := false
|
||||
image := ""
|
||||
|
||||
if defendablePokememe {
|
||||
// Actions for high-grade pokememes
|
||||
defenceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[6]), -1)
|
||||
if len(defenceMatch) < 1 {
|
||||
c.Log.Error("Can't parse defence!")
|
||||
c.Log.Debug(pokememeRunesArray[6])
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
defence = defenceMatch[0]
|
||||
priceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[7]), -1)
|
||||
if len(priceMatch) < 1 {
|
||||
c.Log.Error("Can't parse price!")
|
||||
c.Log.Debug(pokememeRunesArray[7])
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
price = priceMatch[0]
|
||||
locationsPrepare := strings.Split(string(pokememeRunesArray[8]), ": ")
|
||||
if len(locationsPrepare) < 2 {
|
||||
c.Log.Error("Can't parse locations!")
|
||||
c.Log.Debug(pokememeRunesArray[8])
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
locationsNames := strings.Split(locationsPrepare[1], ", ")
|
||||
if len(locationsNames) < 1 {
|
||||
c.Log.Error("Can't parse locations!")
|
||||
c.Log.Debug(locationsPrepare)
|
||||
if len(pokememeLocations) == 0 {
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
err2 := c.Db.Select(&locations, "SELECT * FROM locations WHERE name IN ('"+strings.Join(locationsNames, "', '")+"')")
|
||||
if err2 != nil {
|
||||
c.Log.Error(err2.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
if strings.HasSuffix(string(pokememeRunesArray[9]), "Можно") {
|
||||
purchaseable = true
|
||||
}
|
||||
image = strings.Replace(string(pokememeRunesArray[12]), " ", "", -1)
|
||||
} else {
|
||||
// Actions for low-grade pokememes
|
||||
defence = hitPoints[0]
|
||||
priceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[6]), -1)
|
||||
if len(priceMatch) < 1 {
|
||||
c.Log.Error("Can't parse price!")
|
||||
c.Log.Debug(pokememeRunesArray[6])
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
price = priceMatch[0]
|
||||
locationsPrepare := strings.Split(string(pokememeRunesArray[7]), ": ")
|
||||
if len(locationsPrepare) < 2 {
|
||||
c.Log.Error("Can't parse locations!")
|
||||
c.Log.Debug(pokememeRunesArray[7])
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
locationsNames := strings.Split(locationsPrepare[1], ", ")
|
||||
if len(locationsNames) < 1 {
|
||||
c.Log.Error("Can't parse locations!")
|
||||
c.Log.Debug(locationsPrepare)
|
||||
newPokememeID, err := c.DataCache.AddPokememe(pokememeData, pokememeLocations, pokememeElements)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
err2 := c.Db.Select(&locations, "SELECT * FROM locations WHERE name IN ('"+strings.Join(locationsNames, "', '")+"')")
|
||||
if err2 != nil {
|
||||
c.Log.Error(err2.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
if strings.HasSuffix(string(pokememeRunesArray[8]), "Можно") {
|
||||
purchaseable = true
|
||||
}
|
||||
image = strings.Replace(string(pokememeRunesArray[11]), " ", "", -1)
|
||||
}
|
||||
|
||||
grade := string(pokememeRunesArray[0][0])
|
||||
name := string(pokememeRunesArray[0][3:])
|
||||
description := string(pokememeRunesArray[1])
|
||||
c.Log.Debug("Pokememe grade: " + grade)
|
||||
c.Log.Debug("Pokememe name: " + name)
|
||||
c.Log.Debug("Pokememe description: " + description)
|
||||
c.Log.Debug("Elements:")
|
||||
for i := range elements {
|
||||
c.Log.Debug(elements[i].Symbol + " " + elements[i].Name)
|
||||
}
|
||||
c.Log.Debug("Attack: " + hitPoints[0])
|
||||
c.Log.Debug("HP: " + hitPoints[1])
|
||||
c.Log.Debug("MP: " + hitPoints[2])
|
||||
c.Log.Debug("Defence: " + defence)
|
||||
c.Log.Debug("Price: " + price)
|
||||
c.Log.Debug("Locations:")
|
||||
for i := range locations {
|
||||
c.Log.Debug(locations[i].Symbol + " " + locations[i].Name)
|
||||
}
|
||||
if purchaseable {
|
||||
c.Log.Debug("Purchaseable")
|
||||
} else {
|
||||
c.Log.Debug("Non-purchaseable")
|
||||
}
|
||||
c.Log.Debug("Image: " + image)
|
||||
|
||||
// Building pokememe
|
||||
pokememe := dbmapping.Pokememe{}
|
||||
// Checking if pokememe exists in database
|
||||
err3 := c.Db.Get(&pokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE grade='"+grade+"' AND name='"+name+"';"))
|
||||
if err3 != nil {
|
||||
c.Log.Debug("Adding new pokememe...")
|
||||
} else {
|
||||
c.Log.Info("This pokememe already exist. Return specific error.")
|
||||
p.pokememeAddDuplicateMessage(update)
|
||||
return "dup"
|
||||
}
|
||||
|
||||
gradeInt, _ := strconv.Atoi(grade)
|
||||
attackInt := c.Statistics.GetPoints(hitPoints[0])
|
||||
hpInt := c.Statistics.GetPoints(hitPoints[1])
|
||||
mpInt := c.Statistics.GetPoints(hitPoints[2])
|
||||
defenceInt := c.Statistics.GetPoints(defence)
|
||||
priceInt := c.Statistics.GetPoints(price)
|
||||
|
||||
pokememe.Grade = gradeInt
|
||||
pokememe.Name = name
|
||||
pokememe.Description = description
|
||||
pokememe.Attack = attackInt
|
||||
pokememe.HP = hpInt
|
||||
pokememe.MP = mpInt
|
||||
pokememe.Defence = defenceInt
|
||||
pokememe.Price = priceInt
|
||||
if purchaseable {
|
||||
pokememe.Purchaseable = true
|
||||
} else {
|
||||
pokememe.Purchaseable = false
|
||||
}
|
||||
pokememe.ImageURL = image
|
||||
pokememe.PlayerID = playerRaw.ID
|
||||
pokememe.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err4 := c.Db.NamedExec("INSERT INTO pokememes VALUES(NULL, :grade, :name, :description, :attack, :hp, :mp, :defence, :price, :purchaseable, :image_url, :player_id, :created_at)", &pokememe)
|
||||
if err4 != nil {
|
||||
c.Log.Error(err4.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
// Getting new pokememe
|
||||
err5 := c.Db.Get(&pokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE grade='"+grade+"' AND name='"+name+"';"))
|
||||
if err5 != nil {
|
||||
c.Log.Error("Pokememe isn't added!")
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
for i := range elements {
|
||||
link := dbmapping.PokememeElement{}
|
||||
link.PokememeID = pokememe.ID
|
||||
link.ElementID = elements[i].ID
|
||||
link.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err6 := c.Db.NamedExec("INSERT INTO pokememes_elements VALUES(NULL, :pokememe_id, :element_id, :created_at)", &link)
|
||||
if err6 != nil {
|
||||
c.Log.Error(err6.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
}
|
||||
for i := range locations {
|
||||
link := dbmapping.PokememeLocation{}
|
||||
link.PokememeID = pokememe.ID
|
||||
link.LocationID = locations[i].ID
|
||||
link.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err7 := c.Db.NamedExec("INSERT INTO pokememes_locations VALUES(NULL, :pokememe_id, :location_id, :created_at)", &link)
|
||||
if err7 != nil {
|
||||
c.Log.Error(err7.Error())
|
||||
p.pokememeAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
}
|
||||
|
||||
p.pokememeAddSuccessMessage(update)
|
||||
p.pokememeAddSuccessMessage(update, newPokememeID)
|
||||
return "ok"
|
||||
}
|
||||
|
@ -4,15 +4,16 @@
|
||||
package pokedexer
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"sort"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememesArray []dbmapping.PokememeFull) {
|
||||
func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememesArray map[int]*dbmapping.PokememeFull) {
|
||||
message := "*Известные боту покемемы*\n"
|
||||
message += "Список отсортирован по грейду и алфавиту.\n"
|
||||
message += "Покедекс: " + strconv.Itoa(len(pokememesArray)) + " / 249\n"
|
||||
message += "Покедекс: " + strconv.Itoa(len(pokememesArray)) + " / 274\n"
|
||||
message += "Отображаем покемемов с " + strconv.Itoa(((page-1)*50)+1) + " по " + strconv.Itoa(page*50) + "\n"
|
||||
if len(pokememesArray) > page*50 {
|
||||
message += "Переход на следующую страницу: /pokedeks" + strconv.Itoa(page+1)
|
||||
@ -22,7 +23,13 @@ func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememe
|
||||
}
|
||||
message += "\n\n"
|
||||
|
||||
var keys []int
|
||||
for i := range pokememesArray {
|
||||
keys = append(keys, i)
|
||||
}
|
||||
sort.Ints(keys)
|
||||
|
||||
for _, i := range keys {
|
||||
if (i+1 > 50*(page-1)) && (i+1 < (50*page)+1) {
|
||||
pk := pokememesArray[i].Pokememe
|
||||
pkE := pokememesArray[i].Elements
|
||||
@ -52,9 +59,10 @@ func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememe
|
||||
c.Bot.Send(msg)
|
||||
}
|
||||
|
||||
func (p *Pokedexer) pokememeAddSuccessMessage(update *tgbotapi.Update) {
|
||||
func (p *Pokedexer) pokememeAddSuccessMessage(update *tgbotapi.Update, newPokememeID int) {
|
||||
message := "*Покемем успешно добавлен.*\n\n"
|
||||
message += "Посмотреть всех известных боту покемемов можно командой /pokedeks"
|
||||
message += "Посмотреть всех известных боту покемемов можно командой /pokedeks\n"
|
||||
message += "Посмотреть свежедобавленного покемема можно командой /pk" + strconv.Itoa(newPokememeID)
|
||||
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
|
||||
msg.ParseMode = "Markdown"
|
||||
|
@ -4,8 +4,8 @@
|
||||
package pokedexerinterface
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
)
|
||||
|
||||
// PokedexerInterface implements Pokedexer for importing via appcontext.
|
||||
@ -16,8 +16,5 @@ type PokedexerInterface interface {
|
||||
PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
|
||||
BestPokememesList(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
|
||||
|
||||
GetPokememes() ([]dbmapping.PokememeFull, bool)
|
||||
GetPokememeByID(pokememeID string) (dbmapping.PokememeFull, bool)
|
||||
|
||||
DeletePokememe(update *tgbotapi.Update) string
|
||||
}
|
||||
|
@ -4,8 +4,9 @@
|
||||
package pokedexer
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
@ -18,8 +19,14 @@ func (p *Pokedexer) BestPokememesList(update *tgbotapi.Update, playerRaw *dbmapp
|
||||
return "fail"
|
||||
}
|
||||
|
||||
message := "*Лучшие покемемы для ловли*\n\n"
|
||||
var attacks []int
|
||||
for i := range pokememes {
|
||||
attacks = append(attacks, i)
|
||||
}
|
||||
sort.Sort(sort.Reverse(sort.IntSlice(attacks)))
|
||||
|
||||
message := "*Лучшие покемемы для ловли*\n\n"
|
||||
for _, i := range attacks {
|
||||
pk := pokememes[i].Pokememe
|
||||
pkL := pokememes[i].Locations
|
||||
pkE := pokememes[i].Elements
|
||||
@ -63,25 +70,24 @@ func (p *Pokedexer) PokememesList(update *tgbotapi.Update) {
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
pokememesArray, ok := p.GetPokememes()
|
||||
if !ok {
|
||||
c.Talkers.BotError(update)
|
||||
} else {
|
||||
pokememesArray := c.DataCache.GetAllPokememes()
|
||||
p.pokememesListing(update, page, pokememesArray)
|
||||
}
|
||||
}
|
||||
|
||||
// PokememeInfo shows information about single pokememe based on internal ID
|
||||
func (p *Pokedexer) PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.Player) string {
|
||||
pokememeNumber := strings.Replace(update.Message.Text, "/pk", "", 1)
|
||||
var calculatePossibilites = true
|
||||
profileRaw, ok := c.Users.GetProfile(playerRaw.ID)
|
||||
if !ok {
|
||||
profileRaw, err := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
calculatePossibilites = false
|
||||
}
|
||||
|
||||
pokememe, ok := p.GetPokememeByID(pokememeNumber)
|
||||
if !ok {
|
||||
pokememeID, _ := strconv.Atoi(pokememeNumber)
|
||||
pokememe, err := c.DataCache.GetPokememeByID(pokememeID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,9 @@ import (
|
||||
|
||||
// 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 {
|
||||
playerRaw, err := c.DataCache.GetOrCreatePlayerByTelegramID(update.CallbackQuery.From.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
@ -20,9 +21,9 @@ func (r *Router) RouteCallback(update *tgbotapi.Update) string {
|
||||
|
||||
switch {
|
||||
case enableAlarmCallback.MatchString(update.CallbackQuery.Data):
|
||||
return c.Reminder.CreateAlarmSetting(update, &playerRaw)
|
||||
return c.Reminder.CreateAlarmSetting(update, playerRaw)
|
||||
case disableAlarmCallback.MatchString(update.CallbackQuery.Data):
|
||||
return c.Reminder.DestroyAlarmSetting(update, &playerRaw)
|
||||
return c.Reminder.DestroyAlarmSetting(update, playerRaw)
|
||||
}
|
||||
|
||||
return "ok"
|
||||
|
@ -11,8 +11,9 @@ import (
|
||||
|
||||
// RouteInline routes inline requests to bot
|
||||
func (r *Router) RouteInline(update *tgbotapi.Update) string {
|
||||
playerRaw, ok := c.Users.GetOrCreatePlayer(update.InlineQuery.From.ID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetOrCreatePlayerByTelegramID(update.InlineQuery.From.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
@ -73,7 +74,7 @@ func (r *Router) RouteInline(update *tgbotapi.Update) string {
|
||||
Results: results,
|
||||
}
|
||||
|
||||
_, err := c.Bot.AnswerInlineQuery(inlineConf)
|
||||
_, err = c.Bot.AnswerInlineQuery(inlineConf)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ import (
|
||||
|
||||
// RouteRequest decides, what to do with user input
|
||||
func (r *Router) RouteRequest(update *tgbotapi.Update) string {
|
||||
playerRaw, ok := c.Users.GetOrCreatePlayer(update.Message.From.ID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetOrCreatePlayerByTelegramID(update.Message.From.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
// Silently fail
|
||||
return "fail"
|
||||
}
|
||||
@ -20,13 +21,10 @@ func (r *Router) RouteRequest(update *tgbotapi.Update) string {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
c.Log.Debug("Received message from chat ")
|
||||
c.Log.Debugln(chatRaw.TelegramID)
|
||||
|
||||
if update.Message.Chat.IsGroup() || update.Message.Chat.IsSuperGroup() {
|
||||
return r.routeGroupRequest(update, &playerRaw, &chatRaw)
|
||||
return r.routeGroupRequest(update, playerRaw, &chatRaw)
|
||||
} else if update.Message.Chat.IsPrivate() {
|
||||
return r.routePrivateRequest(update, &playerRaw, &chatRaw)
|
||||
return r.routePrivateRequest(update, playerRaw, &chatRaw)
|
||||
}
|
||||
|
||||
return "ok"
|
||||
|
@ -144,13 +144,13 @@ func (s *Squader) GetUserRolesInSquads(playerRaw *dbmapping.Player) ([]dbmapping
|
||||
for i := range userRolesRaw {
|
||||
userRoleFull := dbmapping.SquadPlayerFull{}
|
||||
userRoleFull.Player = *playerRaw
|
||||
userProfile, profileOk := c.Users.GetProfile(playerRaw.ID)
|
||||
userRoleFull.Profile = userProfile
|
||||
userProfile, profileError := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
userRoleFull.Profile = *userProfile
|
||||
userRoleFull.UserRole = userRolesRaw[i].UserType
|
||||
squad, squadOk := s.GetSquadByID(userRolesRaw[i].SquadID)
|
||||
userRoleFull.Squad = squad
|
||||
|
||||
if profileOk && squadOk {
|
||||
if profileError == nil && squadOk {
|
||||
userRoles = append(userRoles, userRoleFull)
|
||||
}
|
||||
}
|
||||
|
@ -4,16 +4,17 @@
|
||||
package squader
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
)
|
||||
|
||||
// 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 {
|
||||
talker, err := c.DataCache.GetPlayerByTelegramID(update.Message.From.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
s.deleteFloodMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
@ -4,8 +4,8 @@
|
||||
package squader
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -38,8 +38,8 @@ func (s *Squader) getPlayersForSquad(squadID int) ([]dbmapping.SquadPlayerFull,
|
||||
for ii := range squadPlayers {
|
||||
if squadPlayers[ii].PlayerID == playersRaw[i].ID {
|
||||
playerWithProfile := dbmapping.SquadPlayerFull{}
|
||||
profile, _ := c.Users.GetProfile(playersRaw[i].ID)
|
||||
playerWithProfile.Profile = profile
|
||||
profile, _ := c.DataCache.GetProfileByPlayerID(playersRaw[i].ID)
|
||||
playerWithProfile.Profile = *profile
|
||||
playerWithProfile.Player = playersRaw[i]
|
||||
playerWithProfile.Squad = squad
|
||||
playerWithProfile.UserRole = squadPlayers[ii].UserType
|
||||
@ -114,8 +114,9 @@ func (s *Squader) createSquad(update *tgbotapi.Update, chatID int, floodChatID i
|
||||
if err != nil {
|
||||
c.Log.Debug(err)
|
||||
|
||||
playerRaw, ok := c.Users.GetOrCreatePlayer(update.Message.From.ID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetPlayerByTelegramID(update.Message.From.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return squad, "fail"
|
||||
}
|
||||
|
||||
@ -287,20 +288,22 @@ func (s *Squader) AddUserToSquad(update *tgbotapi.Update, adderRaw *dbmapping.Pl
|
||||
return s.squadUserAdditionFailure(update)
|
||||
}
|
||||
|
||||
playerRaw, ok := c.Users.GetPlayerByID(playerID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetPlayerByID(playerID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return s.squadUserAdditionFailure(update)
|
||||
}
|
||||
squadRaw := dbmapping.Squad{}
|
||||
err := c.Db.Get(&squadRaw, c.Db.Rebind("SELECT * FROM squads WHERE id=?"), squadID)
|
||||
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)
|
||||
}
|
||||
|
||||
if !c.Users.PlayerBetterThan(&playerRaw, "admin") {
|
||||
_, ok = c.Users.GetProfile(playerRaw.ID)
|
||||
if !ok {
|
||||
if !c.Users.PlayerBetterThan(playerRaw, "admin") {
|
||||
_, err = c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return s.squadUserAdditionFailure(update)
|
||||
}
|
||||
}
|
||||
@ -315,7 +318,7 @@ func (s *Squader) AddUserToSquad(update *tgbotapi.Update, adderRaw *dbmapping.Pl
|
||||
}
|
||||
}
|
||||
|
||||
if !c.Users.PlayerBetterThan(&playerRaw, "admin") {
|
||||
if !c.Users.PlayerBetterThan(playerRaw, "admin") {
|
||||
if playerRaw.LeagueID != 1 {
|
||||
return s.squadUserAdditionFailure(update)
|
||||
}
|
||||
|
@ -27,12 +27,18 @@ func (s *Statistics) SquadStatictics(squadID int) string {
|
||||
for i := range squadMembers {
|
||||
fullInfo := dbmapping.SquadPlayerFull{}
|
||||
|
||||
playerRaw, _ := c.Users.GetPlayerByID(squadMembers[i].PlayerID)
|
||||
profileRaw, _ := c.Users.GetProfile(playerRaw.ID)
|
||||
playerRaw, err := c.DataCache.GetPlayerByID(squadMembers[i].PlayerID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
profileRaw, err := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
|
||||
fullInfo.Squad = squad
|
||||
fullInfo.Player = playerRaw
|
||||
fullInfo.Profile = profileRaw
|
||||
fullInfo.Player = *playerRaw
|
||||
fullInfo.Profile = *profileRaw
|
||||
|
||||
squadMembersWithInformation = append(squadMembersWithInformation, fullInfo)
|
||||
}
|
||||
|
@ -4,62 +4,10 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"time"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
)
|
||||
|
||||
// GetProfile returns last saved profile of player
|
||||
func (u *Users) GetProfile(playerID int) (dbmapping.Profile, bool) {
|
||||
profileRaw := dbmapping.Profile{}
|
||||
err := c.Db.Get(&profileRaw, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? ORDER BY created_at DESC LIMIT 1"), playerID)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return profileRaw, false
|
||||
}
|
||||
|
||||
return profileRaw, true
|
||||
}
|
||||
|
||||
// GetPlayerByID returns dbmapping.Player instance with given ID.
|
||||
func (u *Users) GetPlayerByID(playerID int) (dbmapping.Player, bool) {
|
||||
playerRaw := dbmapping.Player{}
|
||||
err := c.Db.Get(&playerRaw, c.Db.Rebind("SELECT * FROM players WHERE id=?"), playerID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return playerRaw, false
|
||||
}
|
||||
|
||||
return playerRaw, true
|
||||
}
|
||||
|
||||
// GetOrCreatePlayer seeks for player in database via Telegram ID.
|
||||
// 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=? 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())
|
||||
|
||||
// Create "nobody" user
|
||||
playerRaw.TelegramID = telegramID
|
||||
playerRaw.LeagueID = 0
|
||||
playerRaw.Status = "nobody"
|
||||
playerRaw.CreatedAt = time.Now().UTC()
|
||||
playerRaw.UpdatedAt = time.Now().UTC()
|
||||
_, err = c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :status, :created_at, :updated_at)", &playerRaw)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return playerRaw, false
|
||||
}
|
||||
} else {
|
||||
c.Log.Debug("Message user found in database.")
|
||||
}
|
||||
|
||||
return playerRaw, true
|
||||
}
|
||||
|
||||
// GetPrettyName returns "pretty" name of user (first_name + last name or username)
|
||||
func (u *Users) GetPrettyName(user *tgbotapi.User) string {
|
||||
userName := user.FirstName
|
||||
|
@ -15,15 +15,14 @@ import (
|
||||
// Internal functions
|
||||
|
||||
func (u *Users) fillProfilePokememe(profileID int, meme string, attack string, rarity string) {
|
||||
spkRaw := dbmapping.Pokememe{}
|
||||
err := c.Db.Get(&spkRaw, c.Db.Rebind("SELECT * FROM pokememes WHERE name='"+meme+"';"))
|
||||
spkRaw, err := c.DataCache.GetPokememeByName(meme)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
} else {
|
||||
attackInt := c.Statistics.GetPoints(attack)
|
||||
ppk := dbmapping.ProfilePokememe{}
|
||||
ppk.ProfileID = profileID
|
||||
ppk.PokememeID = spkRaw.ID
|
||||
ppk.PokememeID = spkRaw.Pokememe.ID
|
||||
ppk.PokememeAttack = attackInt
|
||||
ppk.PokememeRarity = rarity
|
||||
ppk.CreatedAt = time.Now().UTC()
|
||||
@ -75,12 +74,13 @@ func (u *Users) ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Playe
|
||||
currentString := string(profileRunesArray[i])
|
||||
currentRunes := profileRunesArray[i]
|
||||
if strings.HasPrefix(currentString, "🈸") || strings.HasPrefix(currentString, "🈳 ") || strings.HasPrefix(currentString, "🈵") {
|
||||
err1 := c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE symbol='"+string(currentRunes[0])+"'"))
|
||||
if err1 != nil {
|
||||
c.Log.Error(err1.Error())
|
||||
leagueRaw, err := c.DataCache.GetLeagueBySymbol(string(currentRunes[0]))
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
league = *leagueRaw
|
||||
for j := range currentRunes {
|
||||
if j > 1 {
|
||||
nickname += string(currentRunes[j])
|
||||
@ -209,10 +209,9 @@ func (u *Users) ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Playe
|
||||
}
|
||||
|
||||
// Information is gathered, let's create profile in database!
|
||||
weaponRaw := dbmapping.Weapon{}
|
||||
err2 := c.Db.Get(&weaponRaw, c.Db.Rebind("SELECT * FROM weapons WHERE name='"+weapon+"'"))
|
||||
if err2 != nil {
|
||||
c.Log.Error(err2.Error())
|
||||
weaponRaw, err := c.DataCache.GetWeaponTypeByName(weapon)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
}
|
||||
|
||||
if playerRaw.LeagueID == 0 {
|
||||
@ -221,26 +220,17 @@ func (u *Users) ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Playe
|
||||
if playerRaw.Status == "nobody" {
|
||||
playerRaw.Status = "common"
|
||||
}
|
||||
_, err4 := c.Db.NamedExec("UPDATE `players` SET league_id=:league_id, status=:status WHERE id=:id", &playerRaw)
|
||||
if err4 != nil {
|
||||
c.Log.Error(err4.Error())
|
||||
_, err = c.DataCache.UpdatePlayerFields(playerRaw)
|
||||
if err != nil {
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
} else if playerRaw.LeagueID != league.ID {
|
||||
// Duplicate profile: user changed league, beware!
|
||||
// User changed league, beware!
|
||||
playerRaw.LeagueID = league.ID
|
||||
playerRaw.Status = "league_changed"
|
||||
playerRaw.CreatedAt = time.Now().UTC()
|
||||
_, err5 := c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :status, :created_at, :updated_at)", &playerRaw)
|
||||
if err5 != nil {
|
||||
c.Log.Error(err5.Error())
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
err6 := c.Db.Get(&playerRaw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id='"+strconv.Itoa(playerRaw.TelegramID)+"' AND league_id='"+strconv.Itoa(league.ID)+"';"))
|
||||
if err6 != nil {
|
||||
c.Log.Error(err6.Error())
|
||||
_, err = c.DataCache.UpdatePlayerFields(playerRaw)
|
||||
if err != nil {
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
@ -261,25 +251,22 @@ func (u *Users) ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Playe
|
||||
profileRaw.Crystalls = crystallsInt
|
||||
profileRaw.CreatedAt = time.Now().UTC()
|
||||
|
||||
_, err3 := c.Db.NamedExec("INSERT INTO `profiles` VALUES(NULL, :player_id, :nickname, :telegram_nickname, :level_id, :pokeballs, :wealth, :pokememes_wealth, :exp, :egg_exp, :power, :weapon_id, :crystalls, :created_at)", &profileRaw)
|
||||
if err3 != nil {
|
||||
c.Log.Error(err3.Error())
|
||||
newProfileID, err := c.DataCache.AddProfile(&profileRaw)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
err8 := c.Db.Get(&profileRaw, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? AND created_at=?"), profileRaw.PlayerID, profileRaw.CreatedAt)
|
||||
if err8 != nil {
|
||||
c.Log.Error(err8.Error())
|
||||
c.Log.Error("Profile isn't added!")
|
||||
_, err = c.DataCache.GetProfileByID(newProfileID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
|
||||
playerRaw.UpdatedAt = time.Now().UTC()
|
||||
_, err7 := c.Db.NamedExec("UPDATE `players` SET updated_at=:updated_at WHERE id=:id", &playerRaw)
|
||||
if err7 != nil {
|
||||
c.Log.Error(err7.Error())
|
||||
err = c.DataCache.UpdatePlayerTimestamp(playerRaw.ID)
|
||||
if err != nil {
|
||||
u.profileAddFailureMessage(update)
|
||||
return "fail"
|
||||
}
|
||||
@ -304,11 +291,11 @@ func (u *Users) ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Playe
|
||||
rarity = "super liber"
|
||||
meme = strings.Replace(meme, "🔷", "", 1)
|
||||
}
|
||||
if strings.HasPrefix(meme, "❄️") {
|
||||
if strings.HasPrefix(meme, "❄") {
|
||||
rarity = "new year"
|
||||
meme = strings.Replace(meme, "❄️", "", 1)
|
||||
meme = strings.Replace(meme, "❄", "", 1)
|
||||
}
|
||||
u.fillProfilePokememe(profileRaw.ID, meme, attack, rarity)
|
||||
u.fillProfilePokememe(newProfileID, meme, attack, rarity)
|
||||
}
|
||||
|
||||
u.profileAddSuccessMessage(update, league.ID, profileRaw.LevelID)
|
||||
|
@ -29,12 +29,9 @@ func (u *Users) FindByLevel(update *tgbotapi.Update) string {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
usersArray, ok := u.findUsersByLevel(levelID)
|
||||
if !ok {
|
||||
return "fail"
|
||||
}
|
||||
users := u.findUsersByLevel(levelID)
|
||||
|
||||
u.foundUsersMessage(update, usersArray)
|
||||
u.foundUsersMessage(update, users)
|
||||
|
||||
return "ok"
|
||||
}
|
||||
@ -47,12 +44,9 @@ func (u *Users) FindByName(update *tgbotapi.Update) string {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
usersArray, ok := u.findUserByName(commandArgs)
|
||||
if !ok {
|
||||
return "fail"
|
||||
}
|
||||
users := u.findUserByName(commandArgs)
|
||||
|
||||
u.foundUsersMessage(update, usersArray)
|
||||
u.foundUsersMessage(update, users)
|
||||
|
||||
return "ok"
|
||||
}
|
||||
@ -66,20 +60,22 @@ func (u *Users) ForeignProfileMessage(update *tgbotapi.Update) string {
|
||||
return "fail"
|
||||
}
|
||||
|
||||
playerRaw, ok := u.GetPlayerByID(userID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetPlayerByID(userID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
_, ok = u.GetProfile(playerRaw.ID)
|
||||
if !ok {
|
||||
_, err = c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return c.Talkers.BotError(update)
|
||||
}
|
||||
|
||||
return u.ProfileMessage(update, &playerRaw)
|
||||
return u.ProfileMessage(update, playerRaw)
|
||||
}
|
||||
|
||||
// ProfileAddEffectsMesage shows when user tries to post profile with effects enabled
|
||||
// ProfileAddEffectsMessage shows when user tries to post profile with effects enabled
|
||||
func (u *Users) ProfileAddEffectsMessage(update *tgbotapi.Update) string {
|
||||
message := "*Наркоман, штоле?*\n\n"
|
||||
message += "Бот не принимает профили во время активированных эффектов. Закончи свои дела и принеси чистый профиль через полчаса."
|
||||
@ -94,12 +90,13 @@ func (u *Users) ProfileAddEffectsMessage(update *tgbotapi.Update) string {
|
||||
|
||||
// ProfileMessage shows current player's profile
|
||||
func (u *Users) ProfileMessage(update *tgbotapi.Update, playerRaw *dbmapping.Player) string {
|
||||
profileRaw, ok := u.GetProfile(playerRaw.ID)
|
||||
if !ok {
|
||||
profileRaw, err := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return c.Talkers.AnyMessageUnauthorized(update)
|
||||
}
|
||||
league := dbmapping.League{}
|
||||
err := c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE id=?"), playerRaw.LeagueID)
|
||||
err = c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE id=?"), playerRaw.LeagueID)
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
}
|
||||
@ -210,11 +207,8 @@ func (u *Users) UsersList(update *tgbotapi.Update) string {
|
||||
if page == 0 {
|
||||
page = 1
|
||||
}
|
||||
usersArray, ok := u.getUsersWithProfiles()
|
||||
if !ok {
|
||||
return c.Talkers.BotError(update)
|
||||
}
|
||||
users := c.DataCache.GetPlayersWithCurrentProfiles()
|
||||
|
||||
u.usersList(update, page, usersArray)
|
||||
u.usersList(update, page, users)
|
||||
return "ok"
|
||||
}
|
||||
|
@ -6,84 +6,70 @@ package users
|
||||
import (
|
||||
"git.wtfteam.pro/fat0troll/i2_bot/lib/dbmapping"
|
||||
"github.com/go-telegram-bot-api/telegram-bot-api"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Internal functions for Users package
|
||||
|
||||
func (u *Users) getUsersWithProfiles() ([]dbmapping.PlayerProfile, bool) {
|
||||
usersArray := []dbmapping.PlayerProfile{}
|
||||
players := []dbmapping.Player{}
|
||||
err := c.Db.Select(&players, "SELECT * FROM players")
|
||||
if err != nil {
|
||||
c.Log.Error(err)
|
||||
return usersArray, false
|
||||
}
|
||||
func (u *Users) findUsersByLevel(levelID int) map[int]*dbmapping.PlayerProfile {
|
||||
selectedUsers := make(map[int]*dbmapping.PlayerProfile)
|
||||
allUsers := c.DataCache.GetPlayersWithCurrentProfiles()
|
||||
|
||||
for i := range players {
|
||||
playerWithProfile := dbmapping.PlayerProfile{}
|
||||
profile, ok := u.GetProfile(players[i].ID)
|
||||
if !ok {
|
||||
playerWithProfile.HaveProfile = false
|
||||
} else {
|
||||
playerWithProfile.HaveProfile = true
|
||||
}
|
||||
playerWithProfile.Profile = profile
|
||||
playerWithProfile.Player = players[i]
|
||||
|
||||
league := dbmapping.League{}
|
||||
if players[i].LeagueID != 0 {
|
||||
err = c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE id=?"), players[i].LeagueID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return usersArray, false
|
||||
for i := range allUsers {
|
||||
if allUsers[i].Profile.LevelID == levelID {
|
||||
if allUsers[i].Player.UpdatedAt.After(time.Now().UTC().Add(-72 * time.Hour)) {
|
||||
selectedUsers[i] = allUsers[i]
|
||||
}
|
||||
}
|
||||
playerWithProfile.League = league
|
||||
|
||||
usersArray = append(usersArray, playerWithProfile)
|
||||
}
|
||||
|
||||
return usersArray, true
|
||||
return selectedUsers
|
||||
}
|
||||
|
||||
func (u *Users) findUsersByLevel(levelID int) ([]dbmapping.ProfileWithAddons, bool) {
|
||||
selectedUsers := []dbmapping.ProfileWithAddons{}
|
||||
func (u *Users) findUserByName(pattern string) map[int]*dbmapping.PlayerProfile {
|
||||
selectedUsers := make(map[int]*dbmapping.PlayerProfile)
|
||||
allUsers := c.DataCache.GetPlayersWithCurrentProfiles()
|
||||
|
||||
err := c.Db.Select(&selectedUsers, c.Db.Rebind("SELECT p.*, l.symbol AS league_symbol, l.id AS league_id, pl.telegram_id FROM players pl, profiles p, leagues l WHERE pl.id = p.player_id AND l.id = pl.league_id AND p.created_at > NOW() - INTERVAL 72 HOUR AND p.level_id = ? GROUP BY player_id"), levelID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return selectedUsers, false
|
||||
for i := range allUsers {
|
||||
matchedPattern := false
|
||||
if strings.Contains(strings.ToLower(allUsers[i].Profile.Nickname), strings.ToLower(pattern)) {
|
||||
matchedPattern = true
|
||||
}
|
||||
if strings.Contains(strings.ToLower(allUsers[i].Profile.TelegramNickname), strings.ToLower(pattern)) {
|
||||
matchedPattern = true
|
||||
}
|
||||
if matchedPattern {
|
||||
selectedUsers[i] = allUsers[i]
|
||||
}
|
||||
}
|
||||
|
||||
return selectedUsers, true
|
||||
return selectedUsers
|
||||
}
|
||||
|
||||
func (u *Users) findUserByName(pattern string) ([]dbmapping.ProfileWithAddons, bool) {
|
||||
selectedUsers := []dbmapping.ProfileWithAddons{}
|
||||
|
||||
err := c.Db.Select(&selectedUsers, c.Db.Rebind("SELECT * FROM (SELECT p.*, l.symbol AS league_symbol, l.id AS league_id, pl.telegram_id FROM players pl, profiles p, leagues l WHERE p.player_id = pl.id AND l.id = pl.league_id AND (p.nickname LIKE ? OR p.telegram_nickname LIKE ?) ORDER BY p.id DESC LIMIT 100000) AS find_users_table GROUP BY player_id"), "%"+pattern+"%", "%"+pattern+"%")
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return selectedUsers, false
|
||||
func (u *Users) foundUsersMessage(update *tgbotapi.Update, users map[int]*dbmapping.PlayerProfile) {
|
||||
var keys []int
|
||||
for i := range users {
|
||||
keys = append(keys, i)
|
||||
}
|
||||
sort.Ints(keys)
|
||||
|
||||
return selectedUsers, true
|
||||
}
|
||||
|
||||
func (u *Users) foundUsersMessage(update *tgbotapi.Update, usersArray []dbmapping.ProfileWithAddons) {
|
||||
message := "*Найденные игроки:*\n"
|
||||
|
||||
for i := range usersArray {
|
||||
message += "#" + strconv.Itoa(usersArray[i].PlayerID)
|
||||
message += " " + usersArray[i].LeagueSymbol
|
||||
message += " " + usersArray[i].Nickname
|
||||
if usersArray[i].TelegramNickname != "" {
|
||||
message += " (@" + u.FormatUsername(usersArray[i].TelegramNickname) + ")"
|
||||
for _, i := range keys {
|
||||
message += "#" + strconv.Itoa(users[i].Player.ID)
|
||||
if users[i].HaveProfile {
|
||||
message += " " + users[i].League.Symbol
|
||||
message += " " + users[i].Profile.Nickname
|
||||
if users[i].Profile.TelegramNickname != "" {
|
||||
message += " (@" + u.FormatUsername(users[i].Profile.TelegramNickname) + ")"
|
||||
}
|
||||
message += " /profile" + strconv.Itoa(usersArray[i].PlayerID) + "\n"
|
||||
message += "Telegram ID: " + strconv.Itoa(usersArray[i].TelegramID) + "\n"
|
||||
message += "Последнее обновление: " + usersArray[i].CreatedAt.Format("02.01.2006 15:04:05") + "\n"
|
||||
}
|
||||
message += " /profile" + strconv.Itoa(users[i].Player.ID) + "\n"
|
||||
message += "Telegram ID: " + strconv.Itoa(users[i].Player.TelegramID) + "\n"
|
||||
message += "Последнее обновление: " + users[i].Player.CreatedAt.Format("02.01.2006 15:04:05") + "\n"
|
||||
|
||||
if len(message) > 2000 {
|
||||
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
|
||||
@ -130,12 +116,12 @@ func (u *Users) profileAddFailureMessage(update *tgbotapi.Update) {
|
||||
c.Bot.Send(msg)
|
||||
}
|
||||
|
||||
func (u *Users) usersList(update *tgbotapi.Update, page int, usersArray []dbmapping.PlayerProfile) {
|
||||
func (u *Users) usersList(update *tgbotapi.Update, page int, users map[int]*dbmapping.PlayerProfile) {
|
||||
message := "*Зарегистрированные пользователи бота*\n"
|
||||
message += "Список отсортирован по ID регистрации.\n"
|
||||
message += "Количество зарегистрированных пользователей: " + strconv.Itoa(len(usersArray)) + "\n"
|
||||
message += "Количество зарегистрированных пользователей: " + strconv.Itoa(len(users)) + "\n"
|
||||
message += "Отображаем пользователей с " + strconv.Itoa(((page-1)*25)+1) + " по " + strconv.Itoa(page*25) + "\n"
|
||||
if len(usersArray) > page*25 {
|
||||
if len(users) > page*25 {
|
||||
message += "Переход на следующую страницу: /users" + strconv.Itoa(page+1)
|
||||
}
|
||||
if page > 1 {
|
||||
@ -143,30 +129,36 @@ func (u *Users) usersList(update *tgbotapi.Update, page int, usersArray []dbmapp
|
||||
}
|
||||
message += "\n\n"
|
||||
|
||||
for i := range usersArray {
|
||||
if (i+1 > 25*(page-1)) && (i+1 < (25*page)+1) {
|
||||
message += "#" + strconv.Itoa(usersArray[i].Player.ID)
|
||||
if usersArray[i].HaveProfile {
|
||||
message += " " + usersArray[i].League.Symbol
|
||||
message += " " + usersArray[i].Profile.Nickname
|
||||
if usersArray[i].Profile.TelegramNickname != "" {
|
||||
message += " (@" + u.FormatUsername(usersArray[i].Profile.TelegramNickname) + ")"
|
||||
var keys []int
|
||||
for i := range users {
|
||||
keys = append(keys, i)
|
||||
}
|
||||
message += " /profile" + strconv.Itoa(usersArray[i].Player.ID) + "\n"
|
||||
message += "Telegram ID: " + strconv.Itoa(usersArray[i].Player.TelegramID) + "\n"
|
||||
message += "Последнее обновление: " + usersArray[i].Profile.CreatedAt.Format("02.01.2006 15:04:05") + "\n"
|
||||
sort.Ints(keys)
|
||||
|
||||
for _, i := range keys {
|
||||
if (i+1 > 25*(page-1)) && (i+1 < (25*page)+1) {
|
||||
message += "#" + strconv.Itoa(users[i].Player.ID)
|
||||
if users[i].HaveProfile {
|
||||
message += " " + users[i].League.Symbol
|
||||
message += " " + users[i].Profile.Nickname
|
||||
if users[i].Profile.TelegramNickname != "" {
|
||||
message += " (@" + u.FormatUsername(users[i].Profile.TelegramNickname) + ")"
|
||||
}
|
||||
message += " /profile" + strconv.Itoa(users[i].Player.ID) + "\n"
|
||||
message += "Telegram ID: " + strconv.Itoa(users[i].Player.TelegramID) + "\n"
|
||||
message += "Последнее обновление: " + users[i].Profile.CreatedAt.Format("02.01.2006 15:04:05") + "\n"
|
||||
} else {
|
||||
if usersArray[i].Player.Status == "special" {
|
||||
if users[i].Player.Status == "special" {
|
||||
message += " _суперюзер_\n"
|
||||
} else {
|
||||
message += " _без профиля_\n"
|
||||
}
|
||||
message += "Telegram ID: " + strconv.Itoa(usersArray[i].Player.TelegramID) + "\n"
|
||||
message += "Telegram ID: " + strconv.Itoa(users[i].Player.TelegramID) + "\n"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(usersArray) > page*25 {
|
||||
if len(users) > page*25 {
|
||||
message += "\n"
|
||||
message += "Переход на следующую страницу: /users" + strconv.Itoa(page+1)
|
||||
}
|
||||
|
@ -15,9 +15,6 @@ type UsersInterface interface {
|
||||
ParseProfile(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
|
||||
|
||||
GetPrettyName(user *tgbotapi.User) string
|
||||
GetProfile(playerID int) (dbmapping.Profile, bool)
|
||||
GetOrCreatePlayer(telegramID int) (dbmapping.Player, bool)
|
||||
GetPlayerByID(playerID int) (dbmapping.Player, bool)
|
||||
PlayerBetterThan(playerRaw *dbmapping.Player, powerLevel string) bool
|
||||
|
||||
FindByLevel(update *tgbotapi.Update) string
|
||||
|
@ -9,22 +9,25 @@ import (
|
||||
)
|
||||
|
||||
func (w *Welcomer) groupWelcomeUser(update *tgbotapi.Update, newUser *tgbotapi.User) string {
|
||||
playerRaw, ok := c.Users.GetOrCreatePlayer(newUser.ID)
|
||||
if !ok {
|
||||
playerRaw, err := c.DataCache.GetPlayerByTelegramID(newUser.ID)
|
||||
if err != nil {
|
||||
c.Log.Error(err.Error())
|
||||
return "fail"
|
||||
}
|
||||
|
||||
_, profileExist := c.Users.GetProfile(playerRaw.ID)
|
||||
_, profileExist := c.DataCache.GetProfileByPlayerID(playerRaw.ID)
|
||||
|
||||
message := "*Бот Инстинкта приветствует тебя, *"
|
||||
message += c.Users.GetPrettyName(newUser)
|
||||
message += "*!*\n\n"
|
||||
|
||||
if profileExist {
|
||||
if profileExist == nil {
|
||||
if playerRaw.LeagueID != 1 {
|
||||
w.alertSpyUser(update, newUser)
|
||||
}
|
||||
} else {
|
||||
c.Log.Info("Following profile error is OK.")
|
||||
c.Log.Info(err.Error())
|
||||
w.alertUserWithoutProfile(update, newUser)
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user