diff --git a/README b/README deleted file mode 100644 index dc11bf0..0000000 --- a/README +++ /dev/null @@ -1,3 +0,0 @@ -#### i2_bot: бот лиги Инстинкт игры @PokememBroBot - -Миграции базы данных рулит гусь (``goose``). diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa2e67a --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# i2_bot: бот лиги Инстинкт игры @PokememBroBot + +Для запуска нужен правильный ``config.json`` и выполнить ``./dependencies.sh``. diff --git a/SPECS b/SPECS index 94781d3..bdc1152 100644 --- a/SPECS +++ b/SPECS @@ -26,7 +26,6 @@ 3. Хелп * Многоуровневый! - 4. /exp_day – выводим опыт юзера за сутки 5. /exp_week – экспа за неделю с понедельника 01-00 6. Писькомерки: diff --git a/lib/appcontext/appcontext.go b/lib/appcontext/appcontext.go index 235f046..0bdd0f7 100644 --- a/lib/appcontext/appcontext.go +++ b/lib/appcontext/appcontext.go @@ -18,6 +18,7 @@ import ( "../talkers/talkersinterface" ) +// Context is an application context struct type Context struct { Cfg *config.Config Bot *tgbotapi.BotAPI @@ -29,6 +30,7 @@ type Context struct { Getters gettersinterface.GettersInterface } +// Init is a initialization function for context func (c *Context) Init() { c.Cfg = config.New() c.Cfg.Init() @@ -36,28 +38,34 @@ func (c *Context) Init() { c.Db = connections.DBInit(c.Cfg) } +// RegisterRouterInterface registering router interface in application func (c *Context) RegisterRouterInterface(ri routerinterface.RouterInterface) { c.Router = ri c.Router.Init() } +// RegisterMigrationsInterface registering migrations interface in application func (c *Context) RegisterMigrationsInterface(mi migrationsinterface.MigrationsInterface) { c.Migrations = mi c.Migrations.Init() } +// RegisterParsersInterface registering parsers interface in application func (c *Context) RegisterParsersInterface(pi parsersinterface.ParsersInterface) { c.Parsers = pi } +// RegisterTalkersInterface registering talkers interface in application func (c *Context) RegisterTalkersInterface(ti talkersinterface.TalkersInterface) { c.Talkers = ti } +// RegisterGettersInterface registering getters interface in application func (c *Context) RegisterGettersInterface(gi gettersinterface.GettersInterface) { c.Getters = gi } +// RunDatabaseMigrations applies migrations on bot's startup func (c *Context) RunDatabaseMigrations() { c.Migrations.SetDialect("mysql") c.Migrations.Migrate() diff --git a/lib/appcontext/exported.go b/lib/appcontext/exported.go index 000b184..7ed4c2d 100644 --- a/lib/appcontext/exported.go +++ b/lib/appcontext/exported.go @@ -7,6 +7,7 @@ var ( a *Context ) +// New is a Context creation function func New() *Context { c := &Context{} return c diff --git a/lib/config/config.go b/lib/config/config.go index e088b94..ea4f1aa 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -12,8 +12,9 @@ import ( "gopkg.in/yaml.v2" ) -const VERSION = "0.29" +const VERSION = "0.295" +// DatabaseConnection handles database connection settings in config.yaml type DatabaseConnection struct { Host string `yaml:"host"` Port string `yaml:"port"` @@ -22,15 +23,18 @@ type DatabaseConnection struct { Database string `yaml:"database"` } +// TelegramConnection handles settings for Telegram connection in config.yaml type TelegramConnection struct { APIToken string `yaml:"api_token"` } +// Config is a struct which represents config.yaml structure type Config struct { Telegram TelegramConnection `yaml:"telegram_connection"` Database DatabaseConnection `yaml:"database_connection"` } +// Init is a configuration initializer func (c *Config) Init() { fname, _ := filepath.Abs("./config.yml") yamlFile, yerr := ioutil.ReadFile(fname) @@ -44,6 +48,7 @@ func (c *Config) Init() { } } +// New creates new empty Config object func New() *Config { c := &Config{} return c diff --git a/lib/connections/connections.go b/lib/connections/connections.go index 07db47f..bf1ef7b 100644 --- a/lib/connections/connections.go +++ b/lib/connections/connections.go @@ -14,6 +14,7 @@ import ( "../config" ) +// BotInit initializes connection to Telegram func BotInit(cfg *config.Config) *tgbotapi.BotAPI { bot, err := tgbotapi.NewBotAPI(cfg.Telegram.APIToken) if err != nil { @@ -28,6 +29,7 @@ func BotInit(cfg *config.Config) *tgbotapi.BotAPI { return bot } +// DBInit initializes database connection func DBInit(cfg *config.Config) *sqlx.DB { database, err := sqlx.Connect("mysql", cfg.Database.User+":"+cfg.Database.Password+"@tcp("+cfg.Database.Host+":"+cfg.Database.Port+")/"+cfg.Database.Database+"?parseTime=true&charset=utf8mb4,utf8") if err != nil { diff --git a/lib/dbmapping/chats.go b/lib/dbmapping/chats.go new file mode 100644 index 0000000..40ee88c --- /dev/null +++ b/lib/dbmapping/chats.go @@ -0,0 +1,18 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package dbmapping + +import ( + // stdlib + "time" +) + +// Chat is a struct, which represents `chats` table item in databse. +type Chat struct { + ID int `db:"id"` + Name string `db:"name"` + ChatType bool `db:"chat_type"` + TelegramID int `db:"telegram_id"` + CreatedAt *time.Time `db:"created_at"` +} diff --git a/lib/dbmapping/elements.go b/lib/dbmapping/elements.go index 5a6ac49..6159364 100644 --- a/lib/dbmapping/elements.go +++ b/lib/dbmapping/elements.go @@ -8,10 +8,11 @@ import ( "time" ) +// Element is a struct, which represents `elements` table item in databse. type Element struct { - Id int `db:"id"` - Symbol string `db:"symbol"` - Name string `db:"name"` - League_id int `db:"league_id"` - Created_at *time.Time `db:"created_at"` + ID int `db:"id"` + Symbol string `db:"symbol"` + Name string `db:"name"` + LeagueID int `db:"league_id"` + CreatedAt *time.Time `db:"created_at"` } diff --git a/lib/dbmapping/leagues.go b/lib/dbmapping/leagues.go index 4a91a4a..e9c8da9 100644 --- a/lib/dbmapping/leagues.go +++ b/lib/dbmapping/leagues.go @@ -8,9 +8,10 @@ import ( "time" ) +// League is a struct, which represents `leagues` table item in databse. type League struct { - Id int `db:"id"` - Symbol string `db:"symbol"` - Name string `db:"name"` - Created_at *time.Time `db:"created_at"` + ID int `db:"id"` + Symbol string `db:"symbol"` + Name string `db:"name"` + CreatedAt *time.Time `db:"created_at"` } diff --git a/lib/dbmapping/levels.go b/lib/dbmapping/levels.go index 6216f51..59999c7 100644 --- a/lib/dbmapping/levels.go +++ b/lib/dbmapping/levels.go @@ -8,9 +8,10 @@ import ( "time" ) +// Level is a struct, which represents `levels` table item in databse. type Level struct { - Id int `db:"id"` - Max_exp int `db:"max_exp"` - Max_egg int `db:"max_egg"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + MaxExp int `db:"max_exp"` + MaxEgg int `db:"max_egg"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/locations.go b/lib/dbmapping/locations.go index 92de236..25b8f3d 100644 --- a/lib/dbmapping/locations.go +++ b/lib/dbmapping/locations.go @@ -8,9 +8,10 @@ import ( "time" ) +// Location is a struct, which represents `locations` table item in databse. type Location struct { - Id int `db:"id"` - Symbol string `db:"symbol"` - Name string `db:"name"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + Symbol string `db:"symbol"` + Name string `db:"name"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/players.go b/lib/dbmapping/players.go index 6712cf3..dad549a 100644 --- a/lib/dbmapping/players.go +++ b/lib/dbmapping/players.go @@ -8,12 +8,13 @@ import ( "time" ) +// Player is a struct, which represents `players` table item in databse. type Player struct { - Id int `db:"id"` - Telegram_id int `db:"telegram_id"` - League_id int `db:"league_id"` - Squad_id int `db:"squad_id"` - Status string `db:"status"` - Created_at time.Time `db:"created_at"` - Updated_at time.Time `db:"updated_at"` + ID int `db:"id"` + TelegramID int `db:"telegram_id"` + LeagueID int `db:"league_id"` + SquadID int `db:"squad_id"` + Status string `db:"status"` + CreatedAt time.Time `db:"created_at"` + UpdatedAt time.Time `db:"updated_at"` } diff --git a/lib/dbmapping/pokememes.go b/lib/dbmapping/pokememes.go index 8bf8a38..a95054c 100644 --- a/lib/dbmapping/pokememes.go +++ b/lib/dbmapping/pokememes.go @@ -8,8 +8,9 @@ import ( "time" ) +// Pokememe is a struct, which represents `pokememes` table item in databse. type Pokememe struct { - Id int `db:"id"` + ID int `db:"id"` Grade int `db:"grade"` Name string `db:"name"` Description string `db:"description"` @@ -19,13 +20,12 @@ type Pokememe struct { Defence int `db:"defence"` Price int `db:"price"` Purchaseable bool `db:"purchaseable"` - Image_url string `db:"image_url"` - Player_id int `db:"player_id"` - Created_at time.Time `db:"created_at"` + ImageURL string `db:"image_url"` + PlayerID int `db:"player_id"` + CreatedAt time.Time `db:"created_at"` } -// Type for handling pokememe with all informations about locations and elements - +// PokememeFull is a struct for handling pokememe with all informations about locations and elements type PokememeFull struct { Pokememe Pokememe Locations []Location diff --git a/lib/dbmapping/pokememes_elements.go b/lib/dbmapping/pokememes_elements.go index 6535ac3..62e7c78 100644 --- a/lib/dbmapping/pokememes_elements.go +++ b/lib/dbmapping/pokememes_elements.go @@ -8,9 +8,10 @@ import ( "time" ) +// PokememeElement is a struct, which represents `pokememes_elements` table item in databse. type PokememeElement struct { - Id int `db:"id"` - Pokememe_id int `db:"pokememe_id"` - Element_id int `db:"element_id"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + PokememeID int `db:"pokememe_id"` + ElementID int `db:"element_id"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/pokememes_locations.go b/lib/dbmapping/pokememes_locations.go index 36a2ea5..3a889c1 100644 --- a/lib/dbmapping/pokememes_locations.go +++ b/lib/dbmapping/pokememes_locations.go @@ -8,9 +8,10 @@ import ( "time" ) +// PokememeLocation is a struct, which represents `pokememes_locations` table item in databse. type PokememeLocation struct { - Id int `db:"id"` - Pokememe_id int `db:"pokememe_id"` - Location_id int `db:"location_id"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + PokememeID int `db:"pokememe_id"` + LocationID int `db:"location_id"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/profiles.go b/lib/dbmapping/profiles.go index 7422192..1bdb074 100644 --- a/lib/dbmapping/profiles.go +++ b/lib/dbmapping/profiles.go @@ -8,18 +8,19 @@ import ( "time" ) +// Profile is a struct, which represents `profiles` table item in databse. type Profile struct { - Id int `db:"id"` - Player_id int `db:"player_id"` + ID int `db:"id"` + PlayerID int `db:"player_id"` Nickname string `db:"nickname"` TelegramNickname string `db:"telegram_nickname"` - Level_id int `db:"level_id"` + LevelID int `db:"level_id"` Pokeballs int `db:"pokeballs"` Wealth int `db:"wealth"` Exp int `db:"exp"` - Egg_exp int `db:"egg_exp"` + EggExp int `db:"egg_exp"` Power int `db:"power"` - Weapon_id int `db:"weapon_id"` + WeaponID int `db:"weapon_id"` Crystalls int `db:"crystalls"` - Created_at time.Time `db:"created_at"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/profiles_pokememes.go b/lib/dbmapping/profiles_pokememes.go index 57b4571..71806ce 100644 --- a/lib/dbmapping/profiles_pokememes.go +++ b/lib/dbmapping/profiles_pokememes.go @@ -8,11 +8,12 @@ import ( "time" ) +// ProfilePokememe is a struct, which represents `profiles_pokememes` table item in databse. type ProfilePokememe struct { - Id int `db:"id"` - Profile_id int `db:"profile_id"` - Pokememe_id int `db:"pokememe_id"` - Pokememe_lvl int `db:"pokememe_lvl"` - Pokememe_rarity string `db:"pokememe_rarity"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + ProfileID int `db:"profile_id"` + PokememeID int `db:"pokememe_id"` + PokememeLevel int `db:"pokememe_lvl"` + PokememeRarity string `db:"pokememe_rarity"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/dbmapping/weapons.go b/lib/dbmapping/weapons.go index f46c0d3..4c1111d 100644 --- a/lib/dbmapping/weapons.go +++ b/lib/dbmapping/weapons.go @@ -8,10 +8,11 @@ import ( "time" ) +// Weapon is a struct, which represents `weapons` table item in databse. type Weapon struct { - Id int `db:"id"` - Name string `db:"name"` - Power int `db:"power"` - Price int `db:"price"` - Created_at time.Time `db:"created_at"` + ID int `db:"id"` + Name string `db:"name"` + Power int `db:"power"` + Price int `db:"price"` + CreatedAt time.Time `db:"created_at"` } diff --git a/lib/getters/exported.go b/lib/getters/exported.go index 319573b..33af2f3 100644 --- a/lib/getters/exported.go +++ b/lib/getters/exported.go @@ -15,14 +15,17 @@ var ( c *appcontext.Context ) +// Getters is a function-handling struct for package getters. type Getters struct{} +// New is an initialization function for appcontext func New(ac *appcontext.Context) { c = ac g := &Getters{} c.RegisterGettersInterface(gettersinterface.GettersInterface(g)) } +// Init is a initialization function for package func (g *Getters) Init() { log.Printf("Initializing getters...") } diff --git a/lib/getters/gettersinterface/gettersinterface.go b/lib/getters/gettersinterface/gettersinterface.go index ecc16c1..a5b8ea7 100644 --- a/lib/getters/gettersinterface/gettersinterface.go +++ b/lib/getters/gettersinterface/gettersinterface.go @@ -8,17 +8,14 @@ import ( "../../dbmapping" ) +// GettersInterface implements Getters for importing via appcontext. type GettersInterface interface { Init() - // Player GetOrCreatePlayer(telegram_id int) (dbmapping.Player, bool) GetPlayerByID(player_id int) (dbmapping.Player, bool) - // Profile GetProfile(player_id int) (dbmapping.Profile, bool) - // Pokememes GetPokememes() ([]dbmapping.PokememeFull, bool) GetBestPokememes(player_id int) ([]dbmapping.PokememeFull, bool) GetPokememeByID(pokememe_id string) (dbmapping.PokememeFull, bool) - // Possibilities PossibilityRequiredPokeballs(location int, grade int, lvl int) (float64, int) } diff --git a/lib/getters/player.go b/lib/getters/player.go index 2e166f1..6d4b628 100644 --- a/lib/getters/player.go +++ b/lib/getters/player.go @@ -11,39 +11,42 @@ import ( "../dbmapping" ) -func (g *Getters) GetPlayerByID(player_id int) (dbmapping.Player, bool) { - player_raw := dbmapping.Player{} - err := c.Db.Get(&player_raw, c.Db.Rebind("SELECT * FROM players WHERE id=?"), player_id) +// GetPlayerByID returns dbmapping.Player instance with given ID. +func (g *Getters) 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 { log.Println(err) - return player_raw, false + return playerRaw, false } - return player_raw, true + return playerRaw, true } -func (g *Getters) GetOrCreatePlayer(telegram_id int) (dbmapping.Player, bool) { - player_raw := dbmapping.Player{} - err := c.Db.Get(&player_raw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id=?"), telegram_id) +// 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 (g *Getters) GetOrCreatePlayer(telegramID int) (dbmapping.Player, bool) { + playerRaw := dbmapping.Player{} + err := c.Db.Get(&playerRaw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id=?"), telegramID) if err != nil { log.Printf("Message user not found in database.") log.Printf(err.Error()) // Create "nobody" user - player_raw.Telegram_id = telegram_id - player_raw.League_id = 0 - player_raw.Squad_id = 0 - player_raw.Status = "nobody" - player_raw.Created_at = time.Now().UTC() - player_raw.Updated_at = time.Now().UTC() - _, err = c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :squad_id, :status, :created_at, :updated_at)", &player_raw) + playerRaw.TelegramID = telegramID + playerRaw.LeagueID = 0 + playerRaw.SquadID = 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, :squad_id, :status, :created_at, :updated_at)", &playerRaw) if err != nil { log.Printf(err.Error()) - return player_raw, false + return playerRaw, false } } else { log.Printf("Message user found in database.") } - return player_raw, true + return playerRaw, true } diff --git a/lib/getters/pokememes.go b/lib/getters/pokememes.go index fc08a48..6f40656 100644 --- a/lib/getters/pokememes.go +++ b/lib/getters/pokememes.go @@ -14,168 +14,171 @@ import ( // Internal functions func (g *Getters) formFullPokememes(pokememes []dbmapping.Pokememe) ([]dbmapping.PokememeFull, bool) { - pokememes_full := []dbmapping.PokememeFull{} + pokememesArray := []dbmapping.PokememeFull{} elements := []dbmapping.Element{} err := c.Db.Select(&elements, "SELECT * FROM elements") if err != nil { log.Println(err) - return pokememes_full, false + return pokememesArray, false } locations := []dbmapping.Location{} err = c.Db.Select(&locations, "SELECT * FROM locations") if err != nil { log.Println(err) - return pokememes_full, false + return pokememesArray, false } - pokememes_elements := []dbmapping.PokememeElement{} - err = c.Db.Select(&pokememes_elements, "SELECT * FROM pokememes_elements") + pokememesElements := []dbmapping.PokememeElement{} + err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements") if err != nil { log.Println(err) - return pokememes_full, false + return pokememesArray, false } - pokememes_locations := []dbmapping.PokememeLocation{} - err = c.Db.Select(&pokememes_locations, "SELECT * FROM pokememes_locations") + pokememesLocations := []dbmapping.PokememeLocation{} + err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations") if err != nil { log.Println(err) - return pokememes_full, false + return pokememesArray, false } for i := range pokememes { - full_pokememe := dbmapping.PokememeFull{} - elements_listed := []dbmapping.Element{} - locations_listed := []dbmapping.Location{} + fullPokememe := dbmapping.PokememeFull{} + elementsListed := []dbmapping.Element{} + locationsListed := []dbmapping.Location{} - for j := range pokememes_locations { - if pokememes_locations[j].Pokememe_id == pokememes[i].Id { + for j := range pokememesLocations { + if pokememesLocations[j].PokememeID == pokememes[i].ID { for l := range locations { - if pokememes_locations[j].Location_id == locations[l].Id { - locations_listed = append(locations_listed, locations[l]) + if pokememesLocations[j].LocationID == locations[l].ID { + locationsListed = append(locationsListed, locations[l]) } } } } - for k := range pokememes_elements { - if pokememes_elements[k].Pokememe_id == pokememes[i].Id { + for k := range pokememesElements { + if pokememesElements[k].PokememeID == pokememes[i].ID { for e := range elements { - if pokememes_elements[k].Element_id == elements[e].Id { - elements_listed = append(elements_listed, elements[e]) + if pokememesElements[k].ElementID == elements[e].ID { + elementsListed = append(elementsListed, elements[e]) } } } } - full_pokememe.Pokememe = pokememes[i] - full_pokememe.Elements = elements_listed - full_pokememe.Locations = locations_listed + fullPokememe.Pokememe = pokememes[i] + fullPokememe.Elements = elementsListed + fullPokememe.Locations = locationsListed - pokememes_full = append(pokememes_full, full_pokememe) + pokememesArray = append(pokememesArray, fullPokememe) } - return pokememes_full, true + return pokememesArray, true } // External functions +// GetPokememes returns all existing pokememes, known by bot func (g *Getters) GetPokememes() ([]dbmapping.PokememeFull, bool) { - pokememes_full := []dbmapping.PokememeFull{} + pokememesArray := []dbmapping.PokememeFull{} pokememes := []dbmapping.Pokememe{} err := c.Db.Select(&pokememes, "SELECT * FROM pokememes ORDER BY grade asc, name asc") if err != nil { log.Println(err) - return pokememes_full, false + return pokememesArray, false } - pokememes_full, ok := g.formFullPokememes(pokememes) - return pokememes_full, ok + pokememesArray, ok := g.formFullPokememes(pokememes) + return pokememesArray, ok } -func (g *Getters) GetBestPokememes(player_id int) ([]dbmapping.PokememeFull, bool) { - pokememes_full := []dbmapping.PokememeFull{} - player_raw, ok := g.GetPlayerByID(player_id) +// GetBestPokememes returns all pokememes, which will be good for player to catch +func (g *Getters) GetBestPokememes(playerID int) ([]dbmapping.PokememeFull, bool) { + pokememesArray := []dbmapping.PokememeFull{} + playerRaw, ok := g.GetPlayerByID(playerID) if !ok { - return pokememes_full, ok + return pokememesArray, ok } - profile_raw, ok := g.GetProfile(player_id) + profileRaw, ok := g.GetProfile(playerID) if !ok { - return pokememes_full, ok + return pokememesArray, ok } - if player_raw.League_id == 0 { - return pokememes_full, false + if playerRaw.LeagueID == 0 { + return pokememesArray, false } // TODO: make it more complicated pokememes := []dbmapping.Pokememe{} - 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"), player_raw.League_id, profile_raw.Level_id+1) + 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 { log.Println(err) - return pokememes_full, false + return pokememesArray, false } - pokememes_full, ok = g.formFullPokememes(pokememes) - return pokememes_full, ok + pokememesArray, ok = g.formFullPokememes(pokememes) + return pokememesArray, ok } -func (g *Getters) GetPokememeByID(pokememe_id string) (dbmapping.PokememeFull, bool) { - pokememe_full := dbmapping.PokememeFull{} +// GetPokememeByUD returns single pokememe based on internal ID in database +func (g *Getters) 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=?"), pokememe_id) + err := c.Db.Get(&pokememe, c.Db.Rebind("SELECT * FROM pokememes WHERE id=?"), pokememeID) if err != nil { log.Println(err) - return pokememe_full, false + return fullPokememe, false } elements := []dbmapping.Element{} err = c.Db.Select(&elements, "SELECT * FROM elements") if err != nil { log.Println(err) - return pokememe_full, false + return fullPokememe, false } locations := []dbmapping.Location{} err = c.Db.Select(&locations, "SELECT * FROM locations") if err != nil { log.Println(err) - return pokememe_full, false + return fullPokememe, false } - pokememes_elements := []dbmapping.PokememeElement{} - err = c.Db.Select(&pokememes_elements, "SELECT * FROM pokememes_elements WHERE pokememe_id='"+strconv.Itoa(pokememe.Id)+"'") + pokememesElements := []dbmapping.PokememeElement{} + err = c.Db.Select(&pokememesElements, "SELECT * FROM pokememes_elements WHERE pokememe_id='"+strconv.Itoa(pokememe.ID)+"'") if err != nil { log.Println(err) - return pokememe_full, false + return fullPokememe, false } - pokememes_locations := []dbmapping.PokememeLocation{} - err = c.Db.Select(&pokememes_locations, "SELECT * FROM pokememes_locations WHERE pokememe_id='"+strconv.Itoa(pokememe.Id)+"'") + pokememesLocations := []dbmapping.PokememeLocation{} + err = c.Db.Select(&pokememesLocations, "SELECT * FROM pokememes_locations WHERE pokememe_id='"+strconv.Itoa(pokememe.ID)+"'") if err != nil { log.Println(err) - return pokememe_full, false + return fullPokememe, false } - elements_listed := []dbmapping.Element{} - locations_listed := []dbmapping.Location{} + elementsListed := []dbmapping.Element{} + locationsListed := []dbmapping.Location{} - for j := range pokememes_locations { - if pokememes_locations[j].Pokememe_id == pokememe.Id { + for j := range pokememesLocations { + if pokememesLocations[j].PokememeID == pokememe.ID { for l := range locations { - if pokememes_locations[j].Location_id == locations[l].Id { - locations_listed = append(locations_listed, locations[l]) + if pokememesLocations[j].LocationID == locations[l].ID { + locationsListed = append(locationsListed, locations[l]) } } } } - for k := range pokememes_elements { - if pokememes_elements[k].Pokememe_id == pokememe.Id { + for k := range pokememesElements { + if pokememesElements[k].PokememeID == pokememe.ID { for e := range elements { - if pokememes_elements[k].Element_id == elements[e].Id { - elements_listed = append(elements_listed, elements[e]) + if pokememesElements[k].ElementID == elements[e].ID { + elementsListed = append(elementsListed, elements[e]) } } } } - pokememe_full.Pokememe = pokememe - pokememe_full.Elements = elements_listed - pokememe_full.Locations = locations_listed + fullPokememe.Pokememe = pokememe + fullPokememe.Elements = elementsListed + fullPokememe.Locations = locationsListed - return pokememe_full, true + return fullPokememe, true } diff --git a/lib/getters/possibility.go b/lib/getters/possibility.go index 5ac6be4..efea354 100644 --- a/lib/getters/possibility.go +++ b/lib/getters/possibility.go @@ -8,72 +8,74 @@ import ( "log" ) +// PossibilityRequiredPokeballs returns possibility of catching pokememe +// It's based on location, grade of pokememe and current level of player func (g *Getters) PossibilityRequiredPokeballs(location int, grade int, lvl int) (float64, int) { - var base_possibility float64 = 0.00 - var required_pokeballs int = 0 - var percentile = 0.00 + var basePossibility float64 + var requiredPokeballs int + var percentile float64 if lvl > 3 { switch { case grade == (lvl + 1): - base_possibility = 0.05 + basePossibility = 0.05 case grade == lvl: - base_possibility = 0.5 + basePossibility = 0.5 case grade == (lvl - 1): - base_possibility = 0.3 + basePossibility = 0.3 case grade == (lvl - 2): - base_possibility = 0.1 + basePossibility = 0.1 case grade == (lvl - 3): - base_possibility = 0.05 + basePossibility = 0.05 default: - base_possibility = 0.00 + basePossibility = 0.00 } } else if lvl == 3 { switch grade { case 4: - base_possibility = 0.05 + basePossibility = 0.05 case 3: - base_possibility = 0.5 + basePossibility = 0.5 case 2: - base_possibility = 0.3 + basePossibility = 0.3 case 1: - base_possibility = 0.15 + basePossibility = 0.15 default: - base_possibility = 0.00 + basePossibility = 0.00 } } else if lvl == 2 { switch grade { case 3: - base_possibility = 0.05 + basePossibility = 0.05 case 2: - base_possibility = 0.70 + basePossibility = 0.70 case 1: - base_possibility = 0.25 + basePossibility = 0.25 default: - base_possibility = 0.00 + basePossibility = 0.00 } } else if lvl == 1 { switch grade { case 2: - base_possibility = 0.80 + basePossibility = 0.80 case 1: - base_possibility = 0.20 + basePossibility = 0.20 default: - base_possibility = 0.00 + basePossibility = 0.00 } } - var number_of_pokememes int = 0 + var pokememesCount int - err := c.Db.Get(&number_of_pokememes, c.Db.Rebind("SELECT count(*) FROM pokememes p, pokememes_locations pl WHERE p.grade = ? AND pl.location_id = ? AND pl.pokememe_id = p.id;"), grade, location) + err := c.Db.Get(&pokememesCount, c.Db.Rebind("SELECT count(*) FROM pokememes p, pokememes_locations pl WHERE p.grade = ? AND pl.location_id = ? AND pl.pokememe_id = p.id;"), grade, location) if err != nil { log.Println(err) } - if base_possibility != 0 && number_of_pokememes != 0 { - percentile = base_possibility * 100.0 / float64(number_of_pokememes) - required_pokeballs = int(100.0 / percentile) + if basePossibility != 0 && pokememesCount != 0 { + percentile = basePossibility * 100.0 / float64(pokememesCount) + requiredPokeballs = int(100.0 / percentile) } - return percentile, required_pokeballs + return percentile, requiredPokeballs } diff --git a/lib/getters/profile.go b/lib/getters/profile.go index b39741b..33b2586 100644 --- a/lib/getters/profile.go +++ b/lib/getters/profile.go @@ -10,13 +10,14 @@ import ( "../dbmapping" ) -func (g *Getters) GetProfile(player_id int) (dbmapping.Profile, bool) { - profile_raw := dbmapping.Profile{} - err := c.Db.Get(&profile_raw, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? ORDER BY created_at DESC LIMIT 1"), player_id) +// GetProfile returns last saved profile of player +func (g *Getters) 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 { log.Println(err) - return profile_raw, false + return profileRaw, false } - return profile_raw, true + return profileRaw, true } diff --git a/lib/migrations/15_create_chats.go b/lib/migrations/15_create_chats.go new file mode 100644 index 0000000..ac231a4 --- /dev/null +++ b/lib/migrations/15_create_chats.go @@ -0,0 +1,36 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package migrations + +import ( + // stdlib + "database/sql" +) + +func CreateChatsUp(tx *sql.Tx) error { + create_request := "CREATE TABLE `chats` (" + create_request += "`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID чата'," + create_request += "`name` varchar(191) NOT NULL COMMENT 'Имя чата'," + create_request += "`chat_type` bool NOT NULL COMMENT 'Тип чата'," + create_request += "`telegram_id` int(11) NOT NULL COMMENT 'ID чата в Телеграме'," + create_request += "`created_at` datetime NOT NULL COMMENT 'Добавлен в базу'," + create_request += "PRIMARY KEY (`id`)," + create_request += "UNIQUE KEY `id` (`id`)," + create_request += "KEY `chats_created_at` (`created_at`)" + create_request += ") ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='Чаты';" + _, err := tx.Exec(create_request) + if err != nil { + return err + } + + return nil +} + +func CreateChatsDown(tx *sql.Tx) error { + _, err := tx.Exec("DROP TABLE `chats`;") + if err != nil { + return err + } + return nil +} diff --git a/lib/migrations/migrations.go b/lib/migrations/migrations.go index 512c522..2a178c2 100644 --- a/lib/migrations/migrations.go +++ b/lib/migrations/migrations.go @@ -29,6 +29,7 @@ func (m *Migrations) Init() { goose.AddNamedMigration("12_create_profile_relations.go", CreateProfileRelationsUp, CreateProfileRelationsDown) goose.AddNamedMigration("13_create_weapons_and_add_wealth.go", CreateWeaponsAndAddWealthUp, CreateWeaponsAndAddWealthDown) goose.AddNamedMigration("14_fix_time_element.go", FixTimeElementUp, FixTimeElementDown) + goose.AddNamedMigration("15_create_chats.go", CreateChatsUp, CreateChatsDown) } func (m *Migrations) Migrate() error { diff --git a/lib/migrations/migrationsinterface/migrationsinterface.go b/lib/migrations/migrationsinterface/migrationsinterface.go index 0618c8c..4de3939 100644 --- a/lib/migrations/migrationsinterface/migrationsinterface.go +++ b/lib/migrations/migrationsinterface/migrationsinterface.go @@ -3,6 +3,7 @@ package migrationsinterface +// MigrationsInterface implements Migrations for importing via appcontext. type MigrationsInterface interface { Init() Migrate() error diff --git a/lib/parsers/exported.go b/lib/parsers/exported.go index 501e53b..f074d8a 100644 --- a/lib/parsers/exported.go +++ b/lib/parsers/exported.go @@ -13,8 +13,10 @@ var ( c *appcontext.Context ) +// Parsers is a function-handling struct for package parsers type Parsers struct{} +// New is an initialization function for appcontext func New(ac *appcontext.Context) { c = ac p := &Parsers{} diff --git a/lib/parsers/parsersinterface/parsersinterface.go b/lib/parsers/parsersinterface/parsersinterface.go index 7f33d16..c7690f2 100644 --- a/lib/parsers/parsersinterface/parsersinterface.go +++ b/lib/parsers/parsersinterface/parsersinterface.go @@ -10,8 +10,9 @@ import ( "../../dbmapping" ) +// ParsersInterface implements Parsers for importing via appcontext. type ParsersInterface interface { - ParsePokememe(text string, player_raw dbmapping.Player) string - ParseProfile(update tgbotapi.Update, player_raw dbmapping.Player) string + ParsePokememe(text string, playerRaw dbmapping.Player) string + ParseProfile(update tgbotapi.Update, playerRaw dbmapping.Player) string ReturnPoints(points int) string } diff --git a/lib/parsers/pokememe.go b/lib/parsers/pokememe.go index ac01408..25d765d 100644 --- a/lib/parsers/pokememe.go +++ b/lib/parsers/pokememe.go @@ -16,48 +16,49 @@ import ( // Internal functions -func (p *Parsers) getPoints(points_str string) int { +func (p *Parsers) getPoints(pointsStr string) int { value := 0 - if strings.HasSuffix(points_str, "K") { - value_num := strings.Replace(points_str, "K", "", 1) - value_float, _ := strconv.ParseFloat(value_num, 64) - value = int(value_float * 1000) - } else if strings.HasSuffix(points_str, "M") { - value_num := strings.Replace(points_str, "M", "", 1) - value_float, _ := strconv.ParseFloat(value_num, 64) - value = int(value_float * 1000000) + if strings.HasSuffix(pointsStr, "K") { + valueNumber := strings.Replace(pointsStr, "K", "", 1) + valueFloat, _ := strconv.ParseFloat(valueNumber, 64) + value = int(valueFloat * 1000) + } else if strings.HasSuffix(pointsStr, "M") { + valueNumber := strings.Replace(pointsStr, "M", "", 1) + valueFloat, _ := strconv.ParseFloat(valueNumber, 64) + value = int(valueFloat * 1000000) } else { - value, _ = strconv.Atoi(points_str) + value, _ = strconv.Atoi(pointsStr) } return value } // External functions -func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string { - var defendable_pokememe bool = false - pokememe_info_strings := strings.Split(text, "\n") - pokememe_info_runed_strings := make([][]rune, 0) - for i := range pokememe_info_strings { - pokememe_info_runed_strings = append(pokememe_info_runed_strings, []rune(pokememe_info_strings[i])) +// ParsePokememe parses pokememe, forwarded from PokememeBroBot, to database +func (p *Parsers) ParsePokememe(text string, playerRaw dbmapping.Player) string { + var defendablePokememe = false + pokememeStringsArray := strings.Split(text, "\n") + pokememeRunesArray := make([][]rune, 0) + for i := range pokememeStringsArray { + pokememeRunesArray = append(pokememeRunesArray, []rune(pokememeStringsArray[i])) } - if len(pokememe_info_runed_strings) == 13 { - defendable_pokememe = true + if len(pokememeRunesArray) == 13 { + defendablePokememe = true } // Getting elements elements := []dbmapping.Element{} - element_emojis := make([]string, 0) - element_emojis = append(element_emojis, string(pokememe_info_runed_strings[4][11])) - if len(pokememe_info_runed_strings[4]) > 12 { - element_emojis = append(element_emojis, string(pokememe_info_runed_strings[4][13])) + 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(pokememe_info_runed_strings[4]) > 14 { - element_emojis = append(element_emojis, string(pokememe_info_runed_strings[4][15])) + if len(pokememeRunesArray[4]) > 14 { + elementEmojis = append(elementEmojis, string(pokememeRunesArray[4][15])) } - err := c.Db.Select(&elements, "SELECT * FROM elements WHERE symbol IN ('"+strings.Join(element_emojis, "', '")+"')") + err := c.Db.Select(&elements, "SELECT * FROM elements WHERE symbol IN ('"+strings.Join(elementEmojis, "', '")+"')") if err != nil { log.Printf(err.Error()) return "fail" @@ -65,10 +66,10 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string // Getting hit-points hitPointsRx := regexp.MustCompile("(\\d|\\.)+(K|M)?") - hitPoints := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[5]), -1) + hitPoints := hitPointsRx.FindAllString(string(pokememeRunesArray[5]), -1) if len(hitPoints) != 3 { log.Printf("Can't parse hitpoints!") - log.Println(pokememe_info_runed_strings[5]) + log.Println(pokememeRunesArray[5]) return "fail" } @@ -80,26 +81,26 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string purchaseable := false image := "" - if defendable_pokememe { + if defendablePokememe { // Actions for high-grade pokememes - defenceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[6]), -1) + defenceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[6]), -1) if len(defenceMatch) < 1 { log.Printf("Can't parse defence!") - log.Println(pokememe_info_runed_strings[6]) + log.Println(pokememeRunesArray[6]) return "fail" } defence = defenceMatch[0] - priceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[7]), -1) + priceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[7]), -1) if len(priceMatch) < 1 { log.Printf("Can't parse price!") - log.Println(pokememe_info_runed_strings[7]) + log.Println(pokememeRunesArray[7]) return "fail" } price = priceMatch[0] - locationsPrepare := strings.Split(string(pokememe_info_runed_strings[8]), ": ") + locationsPrepare := strings.Split(string(pokememeRunesArray[8]), ": ") if len(locationsPrepare) < 2 { log.Printf("Can't parse locations!") - log.Println(pokememe_info_runed_strings[8]) + log.Println(pokememeRunesArray[8]) return "fail" } locationsNames := strings.Split(locationsPrepare[1], ", ") @@ -114,24 +115,24 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string log.Printf(err2.Error()) return "fail" } - if strings.HasSuffix(string(pokememe_info_runed_strings[9]), "Можно") { + if strings.HasSuffix(string(pokememeRunesArray[9]), "Можно") { purchaseable = true } - image = strings.Replace(string(pokememe_info_runed_strings[12]), " ", "", -1) + image = strings.Replace(string(pokememeRunesArray[12]), " ", "", -1) } else { // Actions for low-grade pokememes defence = hitPoints[0] - priceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[6]), -1) + priceMatch := hitPointsRx.FindAllString(string(pokememeRunesArray[6]), -1) if len(priceMatch) < 1 { log.Printf("Can't parse price!") - log.Println(pokememe_info_runed_strings[6]) + log.Println(pokememeRunesArray[6]) return "fail" } price = priceMatch[0] - locationsPrepare := strings.Split(string(pokememe_info_runed_strings[7]), ": ") + locationsPrepare := strings.Split(string(pokememeRunesArray[7]), ": ") if len(locationsPrepare) < 2 { log.Printf("Can't parse locations!") - log.Println(pokememe_info_runed_strings[7]) + log.Println(pokememeRunesArray[7]) return "fail" } locationsNames := strings.Split(locationsPrepare[1], ", ") @@ -146,15 +147,15 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string log.Printf(err2.Error()) return "fail" } - if strings.HasSuffix(string(pokememe_info_runed_strings[8]), "Можно") { + if strings.HasSuffix(string(pokememeRunesArray[8]), "Можно") { purchaseable = true } - image = strings.Replace(string(pokememe_info_runed_strings[11]), " ", "", -1) + image = strings.Replace(string(pokememeRunesArray[11]), " ", "", -1) } - grade := string(pokememe_info_runed_strings[0][0]) - name := string(pokememe_info_runed_strings[0][3:]) - description := string(pokememe_info_runed_strings[1]) + grade := string(pokememeRunesArray[0][0]) + name := string(pokememeRunesArray[0][3:]) + description := string(pokememeRunesArray[1]) log.Printf("Pokememe grade: " + grade) log.Printf("Pokememe name: " + name) log.Printf("Pokememe description: " + description) @@ -189,29 +190,29 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string return "dup" } - grade_int, _ := strconv.Atoi(grade) - attack_int := p.getPoints(hitPoints[0]) - hp_int := p.getPoints(hitPoints[1]) - mp_int := p.getPoints(hitPoints[2]) - defence_int := p.getPoints(defence) - price_int := p.getPoints(price) + gradeInt, _ := strconv.Atoi(grade) + attackInt := p.getPoints(hitPoints[0]) + hpInt := p.getPoints(hitPoints[1]) + mpInt := p.getPoints(hitPoints[2]) + defenceInt := p.getPoints(defence) + priceInt := p.getPoints(price) - pokememe.Grade = grade_int + pokememe.Grade = gradeInt pokememe.Name = name pokememe.Description = description - pokememe.Attack = attack_int - pokememe.HP = hp_int - pokememe.MP = mp_int - pokememe.Defence = defence_int - pokememe.Price = price_int + 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.Image_url = image - pokememe.Player_id = player_raw.Id - pokememe.Created_at = time.Now().UTC() + 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 { @@ -227,9 +228,9 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string } for i := range elements { link := dbmapping.PokememeElement{} - link.Pokememe_id = pokememe.Id - link.Element_id = elements[i].Id - link.Created_at = time.Now().UTC() + 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 { @@ -239,9 +240,9 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string } for i := range locations { link := dbmapping.PokememeLocation{} - link.Pokememe_id = pokememe.Id - link.Location_id = locations[i].Id - link.Created_at = time.Now().UTC() + 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 { @@ -253,14 +254,16 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmapping.Player) string return "ok" } +// ReturnPoints returns to output points (ht, attack, mp...) formatted +// like in PokememBroBot itself. func (p *Parsers) ReturnPoints(points int) string { if points < 1000 { return strconv.Itoa(points) } else if points < 1000000 { - float_num := float64(points) / 1000.0 - return strconv.FormatFloat(float_num, 'f', -1, 64) + "K" + floatNum := float64(points) / 1000.0 + return strconv.FormatFloat(floatNum, 'f', -1, 64) + "K" } else { - float_num := float64(points) / 1000000.0 - return strconv.FormatFloat(float_num, 'f', -1, 64) + "M" + floatNum := float64(points) / 1000000.0 + return strconv.FormatFloat(floatNum, 'f', -1, 64) + "M" } } diff --git a/lib/parsers/profile.go b/lib/parsers/profile.go index e10e54f..0298c00 100644 --- a/lib/parsers/profile.go +++ b/lib/parsers/profile.go @@ -18,26 +18,26 @@ import ( // Internal functions -func (p *Parsers) fillProfilePokememe(profile_id int, meme string, attack string, rarity string) { - spk_raw := dbmapping.Pokememe{} - err := c.Db.Get(&spk_raw, c.Db.Rebind("SELECT * FROM pokememes WHERE name='"+meme+"';")) +func (p *Parsers) 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+"';")) if err != nil { log.Println(err) } else { - attack_int := p.getPoints(attack) + attackInt := p.getPoints(attack) // Improve it. Game's precision is unstable - orig_attack := float64(spk_raw.Attack) + origAttack := float64(spkRaw.Attack) if rarity == "rare" { - orig_attack = orig_attack * 1.1 + origAttack = origAttack * 1.1 } - level := int(float64(attack_int) / orig_attack) + level := int(float64(attackInt) / origAttack) ppk := dbmapping.ProfilePokememe{} - ppk.Profile_id = profile_id - ppk.Pokememe_id = spk_raw.Id - ppk.Pokememe_lvl = level - ppk.Pokememe_rarity = rarity - ppk.Created_at = time.Now().UTC() + ppk.ProfileID = profileID + ppk.PokememeID = spkRaw.ID + ppk.PokememeLevel = level + ppk.PokememeRarity = rarity + ppk.CreatedAt = time.Now().UTC() _, err2 := c.Db.NamedExec("INSERT INTO `profiles_pokememes` VALUES(NULL, :profile_id, :pokememe_id, :pokememe_lvl, :pokememe_rarity, :created_at)", &ppk) if err2 != nil { log.Println(err2) @@ -47,148 +47,149 @@ func (p *Parsers) fillProfilePokememe(profile_id int, meme string, attack string // External functions -func (p *Parsers) ParseProfile(update tgbotapi.Update, player_raw dbmapping.Player) string { +// ParseProfile parses user profile, forwarded from PokememBroBot, to database +func (p *Parsers) ParseProfile(update tgbotapi.Update, playerRaw dbmapping.Player) string { text := update.Message.Text log.Println(text) - profile_info_strings := strings.Split(text, "\n") - profile_info_runed_strings := make([][]rune, 0) - for i := range profile_info_strings { - profile_info_runed_strings = append(profile_info_runed_strings, []rune(profile_info_strings[i])) + profileStringsArray := strings.Split(text, "\n") + profileRunesArray := make([][]rune, 0) + for i := range profileStringsArray { + profileRunesArray = append(profileRunesArray, []rune(profileStringsArray[i])) } league := dbmapping.League{} - telegram_nickname := update.Message.From.UserName + telegramNickname := update.Message.From.UserName nickname := "" level := "" - level_int := 0 + levelInt := 0 exp := "" - exp_int := 0 - egg_exp := "" - egg_exp_int := 0 + expInt := 0 + eggexp := "" + eggexpInt := 0 pokeballs := "" - pokeballs_int := 0 + pokeballsInt := 0 wealth := "" - wealth_int := 0 + wealthInt := 0 crystalls := "" - crystalls_int := 0 + crystallsInt := 0 weapon := "" pokememes := make(map[string]string) - power_int := 1 + powerInt := 1 // Filling information // We don't know how many strings we got, so we iterating each other - for i := range profile_info_runed_strings { - current_string := string(profile_info_runed_strings[i]) - current_runes := profile_info_runed_strings[i] - if strings.HasPrefix(current_string, "🈸") || strings.HasPrefix(current_string, "🈳 ") || strings.HasPrefix(current_string, "🈵") { - err1 := c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE symbol='"+string(current_runes[0])+"'")) + for i := range profileRunesArray { + 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 { log.Println(err1) return "fail" } - for j := range current_runes { + for j := range currentRunes { if j > 1 { - nickname += string(current_runes[j]) + nickname += string(currentRunes[j]) } } } - if strings.HasPrefix(current_string, "👤Уровень:") { + if strings.HasPrefix(currentString, "👤Уровень:") { levelRx := regexp.MustCompile("\\d+") - level_array := levelRx.FindAllString(current_string, -1) - if len(level_array) < 1 { + levelArray := levelRx.FindAllString(currentString, -1) + if len(levelArray) < 1 { log.Println("Level string broken") return "fail" } - level = level_array[0] - level_int, _ = strconv.Atoi(level) + level = levelArray[0] + levelInt, _ = strconv.Atoi(level) } - if strings.HasPrefix(current_string, "🎓Опыт") { + if strings.HasPrefix(currentString, "🎓Опыт") { expRx := regexp.MustCompile("\\d+") - exp_array := expRx.FindAllString(current_string, -1) - if len(exp_array) < 4 { + expArray := expRx.FindAllString(currentString, -1) + if len(expArray) < 4 { log.Println("Exp string broken") return "fail" } - exp = exp_array[0] - exp_int, _ = strconv.Atoi(exp) - egg_exp = exp_array[2] - egg_exp_int, _ = strconv.Atoi(egg_exp) + exp = expArray[0] + expInt, _ = strconv.Atoi(exp) + eggexp = expArray[2] + eggexpInt, _ = strconv.Atoi(eggexp) } - if strings.HasPrefix(current_string, "⭕Покеболы") { + if strings.HasPrefix(currentString, "⭕Покеболы") { pkbRx := regexp.MustCompile("\\d+") - pkb_array := pkbRx.FindAllString(current_string, -1) - if len(pkb_array) < 2 { + pkbArray := pkbRx.FindAllString(currentString, -1) + if len(pkbArray) < 2 { log.Println("Pokeballs string broken") return "fail" } - pokeballs = pkb_array[1] - pokeballs_int, _ = strconv.Atoi(pokeballs) + pokeballs = pkbArray[1] + pokeballsInt, _ = strconv.Atoi(pokeballs) } - if strings.HasPrefix(current_string, "💲") { + if strings.HasPrefix(currentString, "💲") { wealthRx := regexp.MustCompile("(\\d|\\.|K|M)+") - wealth_array := wealthRx.FindAllString(current_string, -1) - if len(wealth_array) < 2 { + wealthArray := wealthRx.FindAllString(currentString, -1) + if len(wealthArray) < 2 { log.Println("Wealth string broken") return "fail" } - wealth = wealth_array[0] - wealth_int = p.getPoints(wealth) - crystalls = wealth_array[1] - crystalls_int = p.getPoints(crystalls) + wealth = wealthArray[0] + wealthInt = p.getPoints(wealth) + crystalls = wealthArray[1] + crystallsInt = p.getPoints(crystalls) } - if strings.HasPrefix(current_string, "🔫") { + if strings.HasPrefix(currentString, "🔫") { // We need NEXT string! - weapon_type_string := strings.Replace(current_string, "🔫 ", "", 1) + weaponType := strings.Replace(currentString, "🔫 ", "", 1) wnRx := regexp.MustCompile("(.+)(ита)") - weapon = wnRx.FindString(weapon_type_string) + weapon = wnRx.FindString(weaponType) } - if strings.HasPrefix(current_string, "🐱Покемемы: ") { + if strings.HasPrefix(currentString, "🐱Покемемы: ") { pkmnumRx := regexp.MustCompile("\\d+") - pk_num_array := pkmnumRx.FindAllString(current_string, -1) - if len(pk_num_array) < 2 { + pkNumArray := pkmnumRx.FindAllString(currentString, -1) + if len(pkNumArray) < 2 { log.Println("Pokememes count broken") return "fail" } - pokememes_count, _ := strconv.Atoi(pk_num_array[0]) - if pokememes_count > 0 { - for pi := 0; pi < pokememes_count; pi++ { - pokememe_string := string(profile_info_runed_strings[i+1+pi]) + pokememesCount, _ := strconv.Atoi(pkNumArray[0]) + if pokememesCount > 0 { + for pi := 0; pi < pokememesCount; pi++ { + pokememeString := string(profileRunesArray[i+1+pi]) attackRx := regexp.MustCompile("(\\d|\\.|K|M)+") - pk_points_array := attackRx.FindAllString(pokememe_string, -1) - pk_attack := pk_points_array[1] - pk_name := strings.Split(pokememe_string, "+")[0] - pk_name = strings.Replace(pk_name, " ⭐", "", 1) - pk_name = strings.TrimSuffix(pk_name, " ") - pk_name = strings.Split(pk_name, "⃣ ")[1] - pokememes[pk_name] = pk_attack - power_int += p.getPoints(pk_attack) + pkPointsArray := attackRx.FindAllString(pokememeString, -1) + pkAttack := pkPointsArray[1] + pkName := strings.Split(pokememeString, "+")[0] + pkName = strings.Replace(pkName, " ⭐", "", 1) + pkName = strings.TrimSuffix(pkName, " ") + pkName = strings.Split(pkName, "⃣ ")[1] + pokememes[pkName] = pkAttack + powerInt += p.getPoints(pkAttack) } } } } - log.Printf("Telegram nickname: " + telegram_nickname) + log.Printf("Telegram nickname: " + telegramNickname) log.Printf("Nickname: " + nickname) log.Printf("League: " + league.Name) log.Printf("Level: " + level) - log.Println(level_int) + log.Println(levelInt) log.Printf("Exp: " + exp) - log.Println(exp_int) - log.Printf("Egg exp: " + egg_exp) - log.Println(egg_exp_int) + log.Println(expInt) + log.Printf("Egg exp: " + eggexp) + log.Println(eggexpInt) log.Printf("Pokeballs: " + pokeballs) - log.Println(pokeballs_int) + log.Println(pokeballsInt) log.Printf("Wealth: " + wealth) - log.Println(wealth_int) + log.Println(wealthInt) log.Printf("Crystalls: " + crystalls) - log.Println(crystalls_int) + log.Println(crystallsInt) log.Printf("Weapon: " + weapon) if len(pokememes) > 0 { for meme, attack := range pokememes { @@ -199,70 +200,70 @@ func (p *Parsers) ParseProfile(update tgbotapi.Update, player_raw dbmapping.Play } // Information is gathered, let's create profile in database! - weapon_raw := dbmapping.Weapon{} - err2 := c.Db.Get(&weapon_raw, c.Db.Rebind("SELECT * FROM weapons WHERE name='"+weapon+"'")) + weaponRaw := dbmapping.Weapon{} + err2 := c.Db.Get(&weaponRaw, c.Db.Rebind("SELECT * FROM weapons WHERE name='"+weapon+"'")) if err2 != nil { log.Println(err2) } - if player_raw.League_id == 0 { + if playerRaw.LeagueID == 0 { // Updating player with league - player_raw.League_id = league.Id - if player_raw.Status == "nobody" { - player_raw.Status = "common" + playerRaw.LeagueID = league.ID + if playerRaw.Status == "nobody" { + playerRaw.Status = "common" } - _, err4 := c.Db.NamedExec("UPDATE `players` SET league_id=:league_id, status=:status WHERE id=:id", &player_raw) + _, err4 := c.Db.NamedExec("UPDATE `players` SET league_id=:league_id, status=:status WHERE id=:id", &playerRaw) if err4 != nil { log.Println(err4) return "fail" } - } else if player_raw.League_id != league.Id { + } else if playerRaw.LeagueID != league.ID { // Duplicate profile: user changed league, beware! - player_raw.League_id = league.Id - player_raw.Squad_id = 0 - player_raw.Status = "league_changed" - player_raw.Created_at = time.Now().UTC() - _, err5 := c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :squad_id, :status, :created_at, :updated_at)", &player_raw) + playerRaw.LeagueID = league.ID + playerRaw.SquadID = 0 + playerRaw.Status = "league_changed" + playerRaw.CreatedAt = time.Now().UTC() + _, err5 := c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :squad_id, :status, :created_at, :updated_at)", &playerRaw) if err5 != nil { log.Println(err5) return "fail" } - err6 := c.Db.Get(&player_raw, c.Db.Rebind("SELECT * FROM players WHERE telegram_id='"+strconv.Itoa(player_raw.Telegram_id)+"' AND league_id='"+strconv.Itoa(league.Id)+"';")) + 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 { log.Println(err6) return "fail" } } - profile_raw := dbmapping.Profile{} - profile_raw.Player_id = player_raw.Id - profile_raw.Nickname = nickname - profile_raw.TelegramNickname = telegram_nickname - profile_raw.Level_id = level_int - profile_raw.Pokeballs = pokeballs_int - profile_raw.Wealth = wealth_int - profile_raw.Exp = exp_int - profile_raw.Egg_exp = egg_exp_int - profile_raw.Power = power_int - profile_raw.Weapon_id = weapon_raw.Id - profile_raw.Crystalls = crystalls_int - profile_raw.Created_at = time.Now().UTC() + profileRaw := dbmapping.Profile{} + profileRaw.PlayerID = playerRaw.ID + profileRaw.Nickname = nickname + profileRaw.TelegramNickname = telegramNickname + profileRaw.LevelID = levelInt + profileRaw.Pokeballs = pokeballsInt + profileRaw.Wealth = wealthInt + profileRaw.Exp = expInt + profileRaw.EggExp = eggexpInt + profileRaw.Power = powerInt + profileRaw.WeaponID = weaponRaw.ID + 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, :exp, :egg_exp, :power, :weapon_id, :crystalls, :created_at)", &profile_raw) + _, err3 := c.Db.NamedExec("INSERT INTO `profiles` VALUES(NULL, :player_id, :nickname, :telegram_nickname, :level_id, :pokeballs, :wealth, :exp, :egg_exp, :power, :weapon_id, :crystalls, :created_at)", &profileRaw) if err3 != nil { log.Println(err3) return "fail" } - err8 := c.Db.Get(&profile_raw, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? AND created_at=?"), profile_raw.Player_id, profile_raw.Created_at) + err8 := c.Db.Get(&profileRaw, c.Db.Rebind("SELECT * FROM profiles WHERE player_id=? AND created_at=?"), profileRaw.PlayerID, profileRaw.CreatedAt) if err8 != nil { log.Println(err8) log.Printf("Profile isn't added!") return "fail" } - player_raw.Updated_at = time.Now().UTC() - _, err7 := c.Db.NamedExec("UPDATE `players` SET updated_at=:updated_at WHERE id=:id", &player_raw) + playerRaw.UpdatedAt = time.Now().UTC() + _, err7 := c.Db.NamedExec("UPDATE `players` SET updated_at=:updated_at WHERE id=:id", &playerRaw) if err7 != nil { log.Println(err7) return "fail" @@ -274,7 +275,7 @@ func (p *Parsers) ParseProfile(update tgbotapi.Update, player_raw dbmapping.Play rarity = "rare" meme = strings.Replace(meme, "🔸", "", 1) } - p.fillProfilePokememe(profile_raw.Id, meme, attack, rarity) + p.fillProfilePokememe(profileRaw.ID, meme, attack, rarity) } return "ok" diff --git a/lib/router/exported.go b/lib/router/exported.go index f9e4fea..7a61a8d 100644 --- a/lib/router/exported.go +++ b/lib/router/exported.go @@ -15,12 +15,14 @@ var ( r *Router ) +// New is an initialization function for appcontext func New(ac *appcontext.Context) { c = ac rh := RouterHandler{} c.RegisterRouterInterface(rh) } +// Init is an initialization function for package router func (r *Router) Init() { log.Printf("Initialized request router...") } diff --git a/lib/router/handler.go b/lib/router/handler.go index 450b6ad..9db84b7 100644 --- a/lib/router/handler.go +++ b/lib/router/handler.go @@ -8,12 +8,15 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// RouterHandler is a handler for router package type RouterHandler struct{} +// Init is an initialization function of router func (rh RouterHandler) Init() { r.Init() } +// RouteRequest decides, what to do with user input func (rh RouterHandler) RouteRequest(update tgbotapi.Update) string { return r.RouteRequest(update) } diff --git a/lib/router/router.go b/lib/router/router.go index 5cd044a..8504c79 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -12,20 +12,29 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// Router is a function-handling struct for router type Router struct{} -// This function will route requests to appropriative modules -// It will return "ok" or "fail" -// If command doesn't exist, it's "fail" +// RouteRequest decides, what to do with user input func (r *Router) RouteRequest(update tgbotapi.Update) string { text := update.Message.Text - player_raw, ok := c.Getters.GetOrCreatePlayer(update.Message.From.ID) + playerRaw, ok := c.Getters.GetOrCreatePlayer(update.Message.From.ID) if !ok { // Silently fail return "fail" } + chatID := update.Message.Chat.ID + fromID := int64(update.Message.From.ID) + log.Println(chatID) + log.Println(fromID) + if chatID == fromID { + log.Println("Private chat") + } else { + log.Println("Group") + } + // Regular expressions var durakMsg = regexp.MustCompile("(Д|д)(У|у)(Р|р)(А|а|Е|е|О|о)") var huMsg = regexp.MustCompile("(Х|х)(У|у)(Й|й|Я|я|Ю|ю|Е|е)") @@ -50,11 +59,11 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { log.Printf("Forward from another user or bot. Ignoring") } else { log.Printf("Forward from PokememBro bot! Processing...") - if player_raw.Id != 0 { + if playerRaw.ID != 0 { switch { case pokememeMsg.MatchString(text): log.Printf("Pokememe posted!") - status := c.Parsers.ParsePokememe(text, player_raw) + status := c.Parsers.ParsePokememe(text, playerRaw) switch status { case "ok": c.Talkers.PokememeAddSuccessMessage(update) @@ -65,7 +74,7 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { } case profileMsg.MatchString(text): log.Printf("Profile posted!") - status := c.Parsers.ParseProfile(update, player_raw) + status := c.Parsers.ParseProfile(update, playerRaw) switch status { case "ok": c.Talkers.ProfileAddSuccessMessage(update) @@ -83,8 +92,8 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { // Direct messages from user switch { case helloMsg.MatchString(text): - if player_raw.Id != 0 { - c.Talkers.HelloMessageAuthorized(update, player_raw) + if playerRaw.ID != 0 { + c.Talkers.HelloMessageAuthorized(update, playerRaw) } else { c.Talkers.HelloMessageUnauthorized(update) } @@ -107,17 +116,17 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { c.Talkers.PokememesList(update, 1) } case pokememeInfoMsg.MatchString(text): - c.Talkers.PokememeInfo(update, player_raw) + c.Talkers.PokememeInfo(update, playerRaw) // Profile info case meMsg.MatchString(text): - if player_raw.Id != 0 { - c.Talkers.ProfileMessage(update, player_raw) + if playerRaw.ID != 0 { + c.Talkers.ProfileMessage(update, playerRaw) } else { c.Talkers.AnyMessageUnauthorized(update) } // Suggestions case bestMsg.MatchString(text): - c.Talkers.BestPokememesList(update, player_raw) + c.Talkers.BestPokememesList(update, playerRaw) // Easter eggs case huMsg.MatchString(text): c.Talkers.MatMessage(update) diff --git a/lib/router/routerinterface/routerinterface.go b/lib/router/routerinterface/routerinterface.go index 2c49f91..4146c33 100644 --- a/lib/router/routerinterface/routerinterface.go +++ b/lib/router/routerinterface/routerinterface.go @@ -8,6 +8,7 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// RouterInterface implements Router for importing via appcontext. type RouterInterface interface { Init() RouteRequest(update tgbotapi.Update) string diff --git a/lib/talkers/easter.go b/lib/talkers/easter.go index 5f40e6c..a15bdfb 100644 --- a/lib/talkers/easter.go +++ b/lib/talkers/easter.go @@ -12,6 +12,7 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// DurakMessage is an easter egg func (t *Talkers) DurakMessage(update tgbotapi.Update) { log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) @@ -30,6 +31,7 @@ func (t *Talkers) DurakMessage(update tgbotapi.Update) { c.Bot.Send(msg) } +// MatMessage is an easter rgg func (t *Talkers) MatMessage(update tgbotapi.Update) { log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) diff --git a/lib/talkers/errors.go b/lib/talkers/errors.go index a78e365..b037ffc 100644 --- a/lib/talkers/errors.go +++ b/lib/talkers/errors.go @@ -8,21 +8,23 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// AnyMessageUnauthorized throws when user can't do something func (t *Talkers) AnyMessageUnauthorized(update tgbotapi.Update) { - error_message := "Извини, действие для тебя недоступно. Возможно, у меня нет твоего профиля или же твои права недостаточны для совершения данного действия\n\n" - error_message += "Если тебе кажется, что это ошибка, пиши @fat0troll.\n" + message := "Извини, действие для тебя недоступно. Возможно, у меня нет твоего профиля или же твои права недостаточны для совершения данного действия\n\n" + message += "Если тебе кажется, что это ошибка, пиши @fat0troll.\n" - msg := tgbotapi.NewMessage(update.Message.Chat.ID, error_message) + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) msg.ParseMode = "Markdown" c.Bot.Send(msg) } +// GetterError throws when bot can't get something func (t *Talkers) GetterError(update tgbotapi.Update) { - error_message := "Ой, внутренняя ошибка в боте :(\n\n" - error_message += "Напиши @fat0troll, приложив форвардом последние сообщения до этого.\n" + message := "Ой, внутренняя ошибка в боте :(\n\n" + message += "Напиши @fat0troll, приложив форвардом последние сообщения до этого.\n" - msg := tgbotapi.NewMessage(update.Message.Chat.ID, error_message) + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) msg.ParseMode = "Markdown" c.Bot.Send(msg) diff --git a/lib/talkers/exported.go b/lib/talkers/exported.go index b4b154d..d25edd3 100644 --- a/lib/talkers/exported.go +++ b/lib/talkers/exported.go @@ -15,14 +15,17 @@ var ( c *appcontext.Context ) +// Talkers is a function-handling struct for talkers type Talkers struct{} +// New is a appcontext initialization function func New(ac *appcontext.Context) { c = ac m := &Talkers{} c.RegisterTalkersInterface(talkersinterface.TalkersInterface(m)) } +// Init is an initialization function for talkers func (t *Talkers) Init() { log.Printf("Initializing responders...") } diff --git a/lib/talkers/hello.go b/lib/talkers/hello.go index c84d2e5..68c7fee 100644 --- a/lib/talkers/hello.go +++ b/lib/talkers/hello.go @@ -10,23 +10,25 @@ import ( "../dbmapping" ) +// HelloMessageUnauthorized tell new user what to do. func (t *Talkers) HelloMessageUnauthorized(update tgbotapi.Update) { - hello_message := "*Бот Инстинкта приветствует тебя!*\n\n" - hello_message += "Для начала работы с ботом, пожалуйста, перешли от бота игры @PokememBroBot профиль героя.\n" - hello_message += "Все дальнейшие действия с ботом возможны лишь при наличии профиля игрока." + message := "*Бот Инстинкта приветствует тебя!*\n\n" + message += "Для начала работы с ботом, пожалуйста, перешли от бота игры @PokememBroBot профиль героя.\n" + message += "Все дальнейшие действия с ботом возможны лишь при наличии профиля игрока." - msg := tgbotapi.NewMessage(update.Message.Chat.ID, hello_message) + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) msg.ParseMode = "Markdown" c.Bot.Send(msg) } -func (t *Talkers) HelloMessageAuthorized(update tgbotapi.Update, player_raw dbmapping.Player) { - hello_message := "*Бот Инстинкта приветствует тебя. Снова.*\n\n" - hello_message += "Привет, " + update.Message.From.FirstName + " " + update.Message.From.LastName + "!\n" - hello_message += "Последнее обновление информации о тебе: " + player_raw.Updated_at.Format("02.01.2006 15:04:05 -0700") - hello_message += "\nПосмотреть информацию о себе: /me" - msg := tgbotapi.NewMessage(update.Message.Chat.ID, hello_message) +// HelloMessageAuthorized greets existing user +func (t *Talkers) HelloMessageAuthorized(update tgbotapi.Update, playerRaw dbmapping.Player) { + message := "*Бот Инстинкта приветствует тебя. Снова.*\n\n" + message += "Привет, " + update.Message.From.FirstName + " " + update.Message.From.LastName + "!\n" + message += "Последнее обновление информации о тебе: " + playerRaw.UpdatedAt.Format("02.01.2006 15:04:05 -0700") + message += "\nПосмотреть информацию о себе: /me" + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) msg.ParseMode = "Markdown" c.Bot.Send(msg) diff --git a/lib/talkers/help.go b/lib/talkers/help.go index ce6fa23..abfd28a 100644 --- a/lib/talkers/help.go +++ b/lib/talkers/help.go @@ -10,18 +10,19 @@ import ( "../config" ) +// HelpMessage gives user all available commands func (t *Talkers) HelpMessage(update tgbotapi.Update) { - help_message := "*Бот Инстинкта Enchanched.*\n\n" - help_message += "Текущая версия: *" + config.VERSION + "*\n\n" - help_message += "Список команд:\n\n" - help_message += "+ /me – посмотреть свой сохраненный профиль в боте\n" - help_message += "+ /best – посмотреть лучших покемонов для поимки\n" - help_message += "+ /pokedeks – получить список известных боту покемемов\n" - help_message += "+ /help – выводит данное сообщение\n" - help_message += "\n\n" - help_message += "Связаться с автором: @fat0troll\n" + message := "*Бот Инстинкта Enchanched.*\n\n" + message += "Текущая версия: *" + config.VERSION + "*\n\n" + message += "Список команд:\n\n" + message += "+ /me – посмотреть свой сохраненный профиль в боте\n" + message += "+ /best – посмотреть лучших покемонов для поимки\n" + message += "+ /pokedeks – получить список известных боту покемемов\n" + message += "+ /help – выводит данное сообщение\n" + message += "\n\n" + message += "Связаться с автором: @fat0troll\n" - msg := tgbotapi.NewMessage(update.Message.Chat.ID, help_message) + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) msg.ParseMode = "Markdown" c.Bot.Send(msg) diff --git a/lib/talkers/pokedex.go b/lib/talkers/pokedex.go index 8d7b661..113b047 100644 --- a/lib/talkers/pokedex.go +++ b/lib/talkers/pokedex.go @@ -15,12 +15,12 @@ import ( // Internal functions -func (t *Talkers) pokememesListing(update tgbotapi.Update, page int, pokememes_full []dbmapping.PokememeFull) { +func (t *Talkers) pokememesListing(update tgbotapi.Update, page int, pokememesArray []dbmapping.PokememeFull) { message := "*Известные боту покемемы*\n" message += "Список отсортирован по грейду и алфавиту.\n" - message += "Покедекс: " + strconv.Itoa(len(pokememes_full)) + " / 206\n" + message += "Покедекс: " + strconv.Itoa(len(pokememesArray)) + " / 206\n" message += "Отображаем покемемов с " + strconv.Itoa(((page-1)*50)+1) + " по " + strconv.Itoa(page*50) + "\n" - if len(pokememes_full) > page*50 { + if len(pokememesArray) > page*50 { message += "Переход на следующую страницу: /pokedeks" + strconv.Itoa(page+1) } if page > 1 { @@ -28,18 +28,18 @@ func (t *Talkers) pokememesListing(update tgbotapi.Update, page int, pokememes_f } message += "\n\n" - for i := range pokememes_full { + for i := range pokememesArray { if (i+1 > 50*(page-1)) && (i+1 < (50*page)+1) { - pk := pokememes_full[i].Pokememe - pk_e := pokememes_full[i].Elements + pk := pokememesArray[i].Pokememe + pkE := pokememesArray[i].Elements message += strconv.Itoa(i+1) + ". " + strconv.Itoa(pk.Grade) message += "⃣ *" + pk.Name message += "* (" + c.Parsers.ReturnPoints(pk.HP) + "-" + c.Parsers.ReturnPoints(pk.MP) + ") ⚔️ *" message += c.Parsers.ReturnPoints(pk.Attack) + "* \\[" - for j := range pk_e { - message += pk_e[j].Symbol + for j := range pkE { + message += pkE[j].Symbol } - message += "] " + c.Parsers.ReturnPoints(pk.Price) + "$ /pk" + strconv.Itoa(pk.Id) + message += "] " + c.Parsers.ReturnPoints(pk.Price) + "$ /pk" + strconv.Itoa(pk.ID) message += "\n" } } @@ -53,24 +53,26 @@ func (t *Talkers) pokememesListing(update tgbotapi.Update, page int, pokememes_f // External functions +// PokememesList lists all known pokememes func (t *Talkers) PokememesList(update tgbotapi.Update, page int) { - pokememes_full, ok := c.Getters.GetPokememes() + pokememesArray, ok := c.Getters.GetPokememes() if !ok { t.GetterError(update) } else { - t.pokememesListing(update, page, pokememes_full) + t.pokememesListing(update, page, pokememesArray) } } -func (t *Talkers) PokememeInfo(update tgbotapi.Update, player_raw dbmapping.Player) string { - pokememe_number := strings.Replace(update.Message.Text, "/pk", "", 1) - var calculate_possibilites bool = true - profile_raw, ok := c.Getters.GetProfile(player_raw.Id) +// PokememeInfo shows information about single pokememe based on internal ID +func (t *Talkers) PokememeInfo(update tgbotapi.Update, playerRaw dbmapping.Player) string { + pokememeNumber := strings.Replace(update.Message.Text, "/pk", "", 1) + var calculatePossibilites = true + profileRaw, ok := c.Getters.GetProfile(playerRaw.ID) if !ok { - calculate_possibilites = false + calculatePossibilites = false } - pokememe, ok := c.Getters.GetPokememeByID(pokememe_number) + pokememe, ok := c.Getters.GetPokememeByID(pokememeNumber) if !ok { return "fail" } @@ -106,11 +108,11 @@ func (t *Talkers) PokememeInfo(update tgbotapi.Update, player_raw dbmapping.Play } } - if calculate_possibilites { - if (pk.Grade < profile_raw.Level_id+2) && (pk.Grade > profile_raw.Level_id-3) { + if calculatePossibilites { + if (pk.Grade < profileRaw.LevelID+2) && (pk.Grade > profileRaw.LevelID-3) { message += "\nВероятность поимки:" for i := range pokememe.Locations { - percentile, pokeballs := c.Getters.PossibilityRequiredPokeballs(pokememe.Locations[i].Id, pk.Grade, profile_raw.Level_id) + percentile, pokeballs := c.Getters.PossibilityRequiredPokeballs(pokememe.Locations[i].ID, pk.Grade, profileRaw.LevelID) message += "\n" + pokememe.Locations[i].Name + " – " message += strconv.FormatFloat(percentile, 'f', 2, 64) + "% или " message += strconv.Itoa(pokeballs) + "⭕" @@ -118,7 +120,7 @@ func (t *Talkers) PokememeInfo(update tgbotapi.Update, player_raw dbmapping.Play } } - message += "\n" + pk.Image_url + message += "\n" + pk.ImageURL msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) keyboard := tgbotapi.InlineKeyboardMarkup{} diff --git a/lib/talkers/pokememe_add.go b/lib/talkers/pokememe_add.go index 39da01c..0ca357b 100644 --- a/lib/talkers/pokememe_add.go +++ b/lib/talkers/pokememe_add.go @@ -8,6 +8,7 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// PokememeAddSuccessMessage shows pokememe adding success message func (t *Talkers) PokememeAddSuccessMessage(update tgbotapi.Update) { message := "*Покемем успешно добавлен.*\n\n" message += "Посмотреть всех известных боту покемемов можно командой /pokedeks" @@ -18,6 +19,7 @@ func (t *Talkers) PokememeAddSuccessMessage(update tgbotapi.Update) { c.Bot.Send(msg) } +// PokememeAddDuplicateMessage shows pokememe add duplication message func (t *Talkers) PokememeAddDuplicateMessage(update tgbotapi.Update) { message := "*Мы уже знаем об этом покемеме*\n\n" message += "Посмотреть всех известных боту покемемов можно командой /pokedeks\n\n" @@ -29,6 +31,7 @@ func (t *Talkers) PokememeAddDuplicateMessage(update tgbotapi.Update) { c.Bot.Send(msg) } +// PokememeAddFailureMessage shows pokememe add error message func (t *Talkers) PokememeAddFailureMessage(update tgbotapi.Update) { message := "*Неудачно получилось :(*\n\n" message += "Случилась жуткая ошибка, и мы не смогли записать покемема в базу. Напиши @fat0troll, он разберется.\n\n" diff --git a/lib/talkers/profile.go b/lib/talkers/profile.go index 85a8935..421c306 100644 --- a/lib/talkers/profile.go +++ b/lib/talkers/profile.go @@ -13,31 +13,32 @@ import ( "../dbmapping" ) -func (t *Talkers) ProfileMessage(update tgbotapi.Update, player_raw dbmapping.Player) string { - profile_raw, ok := c.Getters.GetProfile(player_raw.Id) +// ProfileMessage shows current player's profile +func (t *Talkers) ProfileMessage(update tgbotapi.Update, playerRaw dbmapping.Player) string { + profileRaw, ok := c.Getters.GetProfile(playerRaw.ID) if !ok { c.Talkers.AnyMessageUnauthorized(update) return "fail" } league := dbmapping.League{} - err := c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE id=?"), player_raw.League_id) + err := c.Db.Get(&league, c.Db.Rebind("SELECT * FROM leagues WHERE id=?"), playerRaw.LeagueID) if err != nil { log.Println(err) } level := dbmapping.Level{} - err = c.Db.Get(&level, c.Db.Rebind("SELECT * FROM levels WHERE id=?"), profile_raw.Level_id) + err = c.Db.Get(&level, c.Db.Rebind("SELECT * FROM levels WHERE id=?"), profileRaw.LevelID) if err != nil { log.Println(err) } weapon := dbmapping.Weapon{} - if profile_raw.Weapon_id != 0 { - err = c.Db.Get(&weapon, c.Db.Rebind("SELECT * FROM weapons WHERE id=?"), profile_raw.Weapon_id) + if profileRaw.WeaponID != 0 { + err = c.Db.Get(&weapon, c.Db.Rebind("SELECT * FROM weapons WHERE id=?"), profileRaw.WeaponID) if err != nil { log.Println(err) } } - p_pk := []dbmapping.ProfilePokememe{} - err = c.Db.Select(&p_pk, c.Db.Rebind("SELECT * FROM profiles_pokememes WHERE profile_id=?"), profile_raw.Id) + profilePokememes := []dbmapping.ProfilePokememe{} + err = c.Db.Select(&profilePokememes, c.Db.Rebind("SELECT * FROM profiles_pokememes WHERE profile_id=?"), profileRaw.ID) if err != nil { log.Println(err) } @@ -47,53 +48,53 @@ func (t *Talkers) ProfileMessage(update tgbotapi.Update, player_raw dbmapping.Pl log.Println(err) } - attack_pm := 0 - for i := range p_pk { + attackPokememes := 0 + for i := range profilePokememes { for j := range pokememes { - if p_pk[i].Pokememe_id == pokememes[j].Id { - single_attack := float64(pokememes[j].Attack) - single_attack = single_attack * float64(p_pk[i].Pokememe_lvl) - if p_pk[i].Pokememe_rarity == "rare" { - single_attack = single_attack * 1.15 + if profilePokememes[i].PokememeID == pokememes[j].ID { + singleAttack := float64(pokememes[j].Attack) + singleAttack = singleAttack * float64(profilePokememes[i].PokememeLevel) + if profilePokememes[i].PokememeRarity == "rare" { + singleAttack = singleAttack * 1.15 } - attack_pm += int(single_attack) + attackPokememes += int(singleAttack) } } } message := "*Профиль игрока " - message += profile_raw.Nickname + "* (@" + profile_raw.TelegramNickname + ")\n" + message += profileRaw.Nickname + "* (@" + profileRaw.TelegramNickname + ")\n" message += "\nЛига: " + league.Symbol + league.Name - message += "\n👤 " + strconv.Itoa(profile_raw.Level_id) - message += " | 🎓 " + strconv.Itoa(profile_raw.Exp) + "/" + strconv.Itoa(level.Max_exp) - message += " | 🥚 " + strconv.Itoa(profile_raw.Egg_exp) + "/" + strconv.Itoa(level.Max_egg) - message += "\n💲" + c.Parsers.ReturnPoints(profile_raw.Wealth) - message += " |💎" + strconv.Itoa(profile_raw.Crystalls) - message += " |⭕" + strconv.Itoa(profile_raw.Pokeballs) - message += "\n⚔Атака: 1 + " + c.Parsers.ReturnPoints(weapon.Power) + " + " + c.Parsers.ReturnPoints(attack_pm) + "\n" + message += "\n👤 " + strconv.Itoa(profileRaw.LevelID) + message += " | 🎓 " + strconv.Itoa(profileRaw.Exp) + "/" + strconv.Itoa(level.MaxExp) + message += " | 🥚 " + strconv.Itoa(profileRaw.EggExp) + "/" + strconv.Itoa(level.MaxEgg) + message += "\n💲" + c.Parsers.ReturnPoints(profileRaw.Wealth) + message += " |💎" + strconv.Itoa(profileRaw.Crystalls) + message += " |⭕" + strconv.Itoa(profileRaw.Pokeballs) + message += "\n⚔Атака: 1 + " + c.Parsers.ReturnPoints(weapon.Power) + " + " + c.Parsers.ReturnPoints(attackPokememes) + "\n" - if profile_raw.Weapon_id != 0 { + if profileRaw.WeaponID != 0 { message += "\n🔫Оружие: " + weapon.Name + " " + c.Parsers.ReturnPoints(weapon.Power) + "⚔" } message += "\n🐱Покемемы:" - for i := range p_pk { + for i := range profilePokememes { for j := range pokememes { - if p_pk[i].Pokememe_id == pokememes[j].Id { - single_attack := float64(pokememes[j].Attack) - single_attack = single_attack * float64(p_pk[i].Pokememe_lvl) - if p_pk[i].Pokememe_rarity == "rare" { - single_attack = single_attack * 1.15 + if profilePokememes[i].PokememeID == pokememes[j].ID { + singleAttack := float64(pokememes[j].Attack) + singleAttack = singleAttack * float64(profilePokememes[i].PokememeLevel) + if profilePokememes[i].PokememeRarity == "rare" { + singleAttack = singleAttack * 1.15 } message += "\n" + strconv.Itoa(pokememes[j].Grade) message += "⃣ " + pokememes[j].Name - message += " +" + c.Parsers.ReturnPoints(int(single_attack)) + "⚔" + message += " +" + c.Parsers.ReturnPoints(int(singleAttack)) + "⚔" } } } - message += "\n\n💳" + strconv.Itoa(player_raw.Telegram_id) - message += "\n⏰Последнее обновление профиля: " + profile_raw.Created_at.Format("02.01.2006 15:04:05") + message += "\n\n💳" + strconv.Itoa(playerRaw.TelegramID) + message += "\n⏰Последнее обновление профиля: " + profileRaw.CreatedAt.Format("02.01.2006 15:04:05") message += "\n\nНе забывай обновляться, это важно для получения актуальной информации.\n\n" message += "/best – посмотреть лучших покемемов для поимки" diff --git a/lib/talkers/profile_add.go b/lib/talkers/profile_add.go index 6d6981b..03af8dc 100644 --- a/lib/talkers/profile_add.go +++ b/lib/talkers/profile_add.go @@ -8,6 +8,7 @@ import ( "github.com/go-telegram-bot-api/telegram-bot-api" ) +// ProfileAddSuccessMessage shows profile addition success message func (t *Talkers) ProfileAddSuccessMessage(update tgbotapi.Update) { message := "*Профиль успешно обновлен.*\n\n" message += "Функциональность бота держится на актуальности профилей. Обновляйся почаще, и да пребудет с тобой Рандом!\n" @@ -20,6 +21,7 @@ func (t *Talkers) ProfileAddSuccessMessage(update tgbotapi.Update) { c.Bot.Send(msg) } +// ProfileAddFailureMessage shows profile addition failure message func (t *Talkers) ProfileAddFailureMessage(update tgbotapi.Update) { message := "*Неудачно получилось :(*\n\n" message += "Случилась жуткая ошибка, и мы не смогли записать профиль в базу. Напиши @fat0troll, он разберется." diff --git a/lib/talkers/suggestions.go b/lib/talkers/suggestions.go index 634fff2..296caca 100644 --- a/lib/talkers/suggestions.go +++ b/lib/talkers/suggestions.go @@ -13,8 +13,9 @@ import ( "../dbmapping" ) -func (t *Talkers) BestPokememesList(update tgbotapi.Update, player_raw dbmapping.Player) string { - pokememes, ok := c.Getters.GetBestPokememes(player_raw.Id) +// BestPokememesList shows list for catching based on player league and grade +func (t *Talkers) BestPokememesList(update tgbotapi.Update, playerRaw dbmapping.Player) string { + pokememes, ok := c.Getters.GetBestPokememes(playerRaw.ID) if !ok { log.Printf("Cannot get pokememes from getter!") return "fail" @@ -23,20 +24,20 @@ func (t *Talkers) BestPokememesList(update tgbotapi.Update, player_raw dbmapping message := "*Лучшие покемемы для ловли*\n\n" for i := range pokememes { pk := pokememes[i].Pokememe - pk_l := pokememes[i].Locations - pk_e := pokememes[i].Elements + pkL := pokememes[i].Locations + pkE := pokememes[i].Elements message += strconv.Itoa(pk.Grade) + "⃣ " message += pk.Name + " (⚔" message += c.Parsers.ReturnPoints(pk.Attack) message += ", 🛡" + c.Parsers.ReturnPoints(pk.Defence) + ")" - for i := range pk_e { - message += pk_e[i].Symbol + for i := range pkE { + message += pkE[i].Symbol } - message += " /pk" + strconv.Itoa(pk.Id) + "\n" + message += " /pk" + strconv.Itoa(pk.ID) + "\n" message += "Локации: " - for i := range pk_l { - message += pk_l[i].Symbol + pk_l[i].Name - if i+1 < len(pk_l) { + for i := range pkL { + message += pkL[i].Symbol + pkL[i].Name + if i+1 < len(pkL) { message += ", " } } diff --git a/lib/talkers/talkersinterface/talkersinterface.go b/lib/talkers/talkersinterface/talkersinterface.go index 59fe7ac..4bb1e5d 100644 --- a/lib/talkers/talkersinterface/talkersinterface.go +++ b/lib/talkers/talkersinterface/talkersinterface.go @@ -10,29 +10,26 @@ import ( "../../dbmapping" ) +// TalkersInterface implements Talkers for importing via appcontex type TalkersInterface interface { Init() - // Commands HelloMessageUnauthorized(update tgbotapi.Update) - HelloMessageAuthorized(update tgbotapi.Update, player_raw dbmapping.Player) + HelloMessageAuthorized(update tgbotapi.Update, playerRaw dbmapping.Player) HelpMessage(update tgbotapi.Update) PokememesList(update tgbotapi.Update, page int) - PokememeInfo(update tgbotapi.Update, player_raw dbmapping.Player) string - BestPokememesList(update tgbotapi.Update, player_raw dbmapping.Player) string + PokememeInfo(update tgbotapi.Update, playerRaw dbmapping.Player) string + BestPokememesList(update tgbotapi.Update, playerRaw dbmapping.Player) string - // Returns PokememeAddSuccessMessage(update tgbotapi.Update) PokememeAddDuplicateMessage(update tgbotapi.Update) PokememeAddFailureMessage(update tgbotapi.Update) ProfileAddSuccessMessage(update tgbotapi.Update) ProfileAddFailureMessage(update tgbotapi.Update) - ProfileMessage(update tgbotapi.Update, player_raw dbmapping.Player) string + ProfileMessage(update tgbotapi.Update, playerRaw dbmapping.Player) string - // Errors AnyMessageUnauthorized(update tgbotapi.Update) GetterError(update tgbotapi.Update) - // Easter eggs DurakMessage(update tgbotapi.Update) MatMessage(update tgbotapi.Update) }