From 2724970e3d8ff22c22acf682930c0cf001a42f58 Mon Sep 17 00:00:00 2001 From: Vladimir Hodakov Date: Sat, 7 Oct 2017 02:23:25 +0400 Subject: [PATCH] Pokememes database saving. Now we're stable --- i2_bot.go | 2 + lib/appcontext/appcontext.go | 6 + lib/config/config.go | 2 +- lib/dbmappings/locations.go | 4 +- lib/dbmappings/players.go | 4 +- lib/dbmappings/pokememes.go | 6 +- lib/dbmappings/pokememes_elements.go | 2 +- lib/dbmappings/pokememes_locations.go | 2 +- lib/dbmappings/profiles.go | 2 +- .../parsersinterface/parsersinterface.go | 1 + lib/parsers/pokememe.go | 215 +++++++++++++++++- lib/router/router.go | 63 ++++- lib/talkers/easter.go | 8 +- lib/talkers/errors.go | 4 +- lib/talkers/exported.go | 28 +++ lib/talkers/hello.go | 8 +- lib/talkers/help.go | 4 +- lib/talkers/pokedex.go | 118 ++++++++++ lib/talkers/pokememe_add.go | 41 ++++ .../talkersinterface/talkersinterface.go | 32 +++ 20 files changed, 516 insertions(+), 36 deletions(-) create mode 100644 lib/talkers/exported.go create mode 100644 lib/talkers/pokedex.go create mode 100644 lib/talkers/pokememe_add.go create mode 100644 lib/talkers/talkersinterface/talkersinterface.go diff --git a/i2_bot.go b/i2_bot.go index cdc8f20..a77ca86 100644 --- a/i2_bot.go +++ b/i2_bot.go @@ -13,6 +13,7 @@ import ( "./lib/migrations" "./lib/parsers" "./lib/router" + "./lib/talkers" ) var ( @@ -26,6 +27,7 @@ func main() { migrations.New(c) c.RunDatabaseMigrations() parsers.New(c) + talkers.New(c) u := tgbotapi.NewUpdate(0) u.Timeout = 60 diff --git a/lib/appcontext/appcontext.go b/lib/appcontext/appcontext.go index 9f413f9..9d92e2a 100644 --- a/lib/appcontext/appcontext.go +++ b/lib/appcontext/appcontext.go @@ -14,6 +14,7 @@ import ( "../migrations/migrationsinterface" "../parsers/parsersinterface" "../router/routerinterface" + "../talkers/talkersinterface" ) type Context struct { @@ -23,6 +24,7 @@ type Context struct { Router routerinterface.RouterInterface Parsers parsersinterface.ParsersInterface Db *sqlx.DB + Talkers talkersinterface.TalkersInterface } func (c *Context) Init() { @@ -46,6 +48,10 @@ func (c *Context) RegisterParsersInterface(pi parsersinterface.ParsersInterface) c.Parsers = pi } +func (c *Context) RegisterTalkersInterface(ti talkersinterface.TalkersInterface) { + c.Talkers = ti +} + func (c *Context) RunDatabaseMigrations() { c.Migrations.SetDialect("mysql") c.Migrations.Migrate() diff --git a/lib/config/config.go b/lib/config/config.go index e45da6c..f64437d 100644 --- a/lib/config/config.go +++ b/lib/config/config.go @@ -12,7 +12,7 @@ import ( "gopkg.in/yaml.v2" ) -const VERSION = "0.03" +const VERSION = "0.1" type DatabaseConnection struct { Host string `yaml:"host"` diff --git a/lib/dbmappings/locations.go b/lib/dbmappings/locations.go index 4ebff50..b8ec1b3 100644 --- a/lib/dbmappings/locations.go +++ b/lib/dbmappings/locations.go @@ -11,6 +11,6 @@ import ( type Locations struct { Id int `db:"id"` Symbol string `db:"symbol"` - Name string `db:"league_id"` - Created_at *time.Time `db:"created_at"` + Name string `db:"name"` + Created_at time.Time `db:"created_at"` } diff --git a/lib/dbmappings/players.go b/lib/dbmappings/players.go index aa01d69..c0ad2bf 100644 --- a/lib/dbmappings/players.go +++ b/lib/dbmappings/players.go @@ -14,6 +14,6 @@ type Players struct { 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"` + Created_at time.Time `db:"created_at"` + Updated_at time.Time `db:"updated_at"` } diff --git a/lib/dbmappings/pokememes.go b/lib/dbmappings/pokememes.go index e496274..ebabdf1 100644 --- a/lib/dbmappings/pokememes.go +++ b/lib/dbmappings/pokememes.go @@ -11,15 +11,15 @@ import ( type Pokememes struct { Id int `db:"id"` Grade int `db:"grade"` - Name string `db:"league_id"` + Name string `db:"name"` Description string `db:"description"` Attack int `db:"attack"` - HP int `db:"int"` + HP int `db:"hp"` MP int `db:"mp"` 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"` + Created_at time.Time `db:"created_at"` } diff --git a/lib/dbmappings/pokememes_elements.go b/lib/dbmappings/pokememes_elements.go index 5baf1c8..6fd3af8 100644 --- a/lib/dbmappings/pokememes_elements.go +++ b/lib/dbmappings/pokememes_elements.go @@ -12,5 +12,5 @@ type PokememesElements struct { Id int `db:"id"` Pokememe_id int `db:"pokememe_id"` Element_id int `db:"element_id"` - Created_at *time.Time `db:"created_at"` + Created_at time.Time `db:"created_at"` } diff --git a/lib/dbmappings/pokememes_locations.go b/lib/dbmappings/pokememes_locations.go index 1ae6df2..110dc7b 100644 --- a/lib/dbmappings/pokememes_locations.go +++ b/lib/dbmappings/pokememes_locations.go @@ -12,5 +12,5 @@ type PokememesLocations struct { Id int `db:"id"` Pokememe_id int `db:"pokememe_id"` Location_id int `db:"location_id"` - Created_at *time.Time `db:"created_at"` + Created_at time.Time `db:"created_at"` } diff --git a/lib/dbmappings/profiles.go b/lib/dbmappings/profiles.go index 2213977..f55b7ee 100644 --- a/lib/dbmappings/profiles.go +++ b/lib/dbmappings/profiles.go @@ -19,5 +19,5 @@ type Profiles struct { Power int `db:"power"` Weapon_id int `db:"weapon_id"` Crystalls int `db:"crystalls"` - Created_at *time.Time `db:"created_at"` + Created_at time.Time `db:"created_at"` } diff --git a/lib/parsers/parsersinterface/parsersinterface.go b/lib/parsers/parsersinterface/parsersinterface.go index 1559470..0155f46 100644 --- a/lib/parsers/parsersinterface/parsersinterface.go +++ b/lib/parsers/parsersinterface/parsersinterface.go @@ -11,4 +11,5 @@ import ( type ParsersInterface interface { ParsePokememe(text string, player_raw dbmappings.Players) string + ReturnPoints(points int) string } diff --git a/lib/parsers/pokememe.go b/lib/parsers/pokememe.go index d4cc050..3d64b2c 100644 --- a/lib/parsers/pokememe.go +++ b/lib/parsers/pokememe.go @@ -5,13 +5,35 @@ package parsers import ( // stdlib - "fmt" "log" + "regexp" "strings" + "strconv" + "time" // local "../dbmappings" ) +// Internal functions + +func (p *Parsers) getPoints(points_str 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) + } else { + value, _ = strconv.Atoi(points_str) + } + return value +} + +// External functions + func (p *Parsers) ParsePokememe(text string, player_raw dbmappings.Players) string { var defendable_pokememe bool = false pokememe_info_strings := strings.Split(text, "\n") @@ -23,7 +45,6 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmappings.Players) stri if len(pokememe_info_runed_strings) == 13 { defendable_pokememe = true } - fmt.Println(defendable_pokememe) // Getting elements elements := []dbmappings.Elements{} @@ -42,6 +63,96 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmappings.Players) stri return "fail" } + // Getting hit-points + hitPointsRx := regexp.MustCompile("(\\d|\\.)+(K|M)?") + hitPoints := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[5]), -1) + if len(hitPoints) != 3 { + log.Printf("Can't parse hitpoints!") + log.Println(pokememe_info_runed_strings[5]) + return "fail" + } + + defence := "0" + price := "0" + + locations := []dbmappings.Locations{} + + purchaseable := false + image := "" + + if defendable_pokememe { + // Actions for high-grade pokememes + defenceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[6]), -1) + if len(defenceMatch) < 1 { + log.Printf("Can't parse defence!") + log.Println(pokememe_info_runed_strings[6]) + return "fail" + } + defence = defenceMatch[0] + priceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[7]), -1) + if len(priceMatch) < 1 { + log.Printf("Can't parse price!") + log.Println(pokememe_info_runed_strings[7]) + return "fail" + } + price = priceMatch[0] + locationsPrepare := strings.Split(string(pokememe_info_runed_strings[8]), ": ") + if len(locationsPrepare) < 2 { + log.Printf("Can't parse locations!") + log.Println(pokememe_info_runed_strings[8]) + return "fail" + } + locationsNames := strings.Split(locationsPrepare[1], ", ") + if len(locationsNames) < 1 { + log.Printf("Can't parse locations!") + log.Println(locationsPrepare) + return "fail" + } + + err2 := c.Db.Select(&locations, "SELECT * FROM locations WHERE name IN ('" + strings.Join(locationsNames, "', '") + "')") + if err2 != nil { + log.Printf(err2.Error()) + return "fail" + } + if strings.HasSuffix(string(pokememe_info_runed_strings[9]), "Можно") { + purchaseable = true + } + image = strings.Replace(string(pokememe_info_runed_strings[12]), " ", "", -1) + } else { + // Actions for low-grade pokememes + defence = hitPoints[0] + priceMatch := hitPointsRx.FindAllString(string(pokememe_info_runed_strings[6]), -1) + if len(priceMatch) < 1 { + log.Printf("Can't parse price!") + log.Println(pokememe_info_runed_strings[6]) + return "fail" + } + price = priceMatch[0] + locationsPrepare := strings.Split(string(pokememe_info_runed_strings[7]), ": ") + if len(locationsPrepare) < 2 { + log.Printf("Can't parse locations!") + log.Println(pokememe_info_runed_strings[7]) + return "fail" + } + locationsNames := strings.Split(locationsPrepare[1], ", ") + if len(locationsNames) < 1 { + log.Printf("Can't parse locations!") + log.Println(locationsPrepare) + return "fail" + } + + err2 := c.Db.Select(&locations, "SELECT * FROM locations WHERE name IN ('" + strings.Join(locationsNames, "', '") + "')") + if err2 != nil { + log.Printf(err2.Error()) + return "fail" + } + if strings.HasSuffix(string(pokememe_info_runed_strings[8]), "Можно") { + purchaseable = true + } + image = strings.Replace(string(pokememe_info_runed_strings[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]) @@ -52,6 +163,106 @@ func (p *Parsers) ParsePokememe(text string, player_raw dbmappings.Players) stri for i := range(elements) { log.Printf(elements[i].Symbol + " " + elements[i].Name) } + log.Printf("Attack: " + hitPoints[0]) + log.Printf("HP: " + hitPoints[1]) + log.Printf("MP: " + hitPoints[2]) + log.Printf("Defence: " + defence) + log.Printf("Price: " + price) + log.Printf("Locations:") + for i := range(locations) { + log.Printf(locations[i].Symbol + " " + locations[i].Name) + } + if purchaseable { + log.Printf("Purchaseable") + } else { + log.Printf("Non-purchaseable") + } + log.Printf("Image: " + image) + + // Building pokememe + pokememe := dbmappings.Pokememes{} + // 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 { + log.Printf("Adding new pokememe...") + } else { + log.Printf("This pokememe already exist. Return specific error.") + 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) + + pokememe.Grade = grade_int + 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 + 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() + + _, 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 { + log.Printf(err4.Error()) + 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 { + log.Printf("Pokememe isn't added!") + return "fail" + } + for i := range(elements) { + link := dbmappings.PokememesElements{} + link.Pokememe_id = pokememe.Id + link.Element_id = elements[i].Id + link.Created_at = time.Now().UTC() + + _, err6 := c.Db.NamedExec("INSERT INTO pokememes_elements VALUES(NULL, :pokememe_id, :element_id, :created_at)", &link) + if err6 != nil { + log.Printf(err6.Error()) + return "fail" + } + } + for i := range(locations) { + link := dbmappings.PokememesLocations{} + link.Pokememe_id = pokememe.Id + link.Location_id = locations[i].Id + link.Created_at = time.Now().UTC() + + _, err7 := c.Db.NamedExec("INSERT INTO pokememes_locations VALUES(NULL, :pokememe_id, :location_id, :created_at)", &link) + if err7 != nil { + log.Printf(err7.Error()) + return "fail" + } + } + return "ok" } + +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" + } else { + float_num := float64(points) / 1000000.0 + return strconv.FormatFloat(float_num, 'f', -1, 64) + "M" + } +} diff --git a/lib/router/router.go b/lib/router/router.go index d2d449a..bb668f7 100644 --- a/lib/router/router.go +++ b/lib/router/router.go @@ -8,11 +8,12 @@ import ( "fmt" "log" "regexp" + "strings" + "time" // 3rd party "gopkg.in/telegram-bot-api.v4" // local "../dbmappings" - "../talkers" ) type Router struct {} @@ -29,6 +30,19 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { if err != nil { log.Printf("Message user not found in database.") log.Printf(err.Error()) + + // Create "nobody" user + player_raw.Telegram_id = user_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() + _, erradd := c.Db.NamedExec("INSERT INTO players VALUES(NULL, :telegram_id, :league_id, :squad_id, :status, :created_at, :updated_at)", &player_raw) + if erradd != nil { + log.Printf(erradd.Error()) + return "fail" + } } else { log.Printf("Message user found in database.") } @@ -41,9 +55,13 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { var blMsg = regexp.MustCompile("\\s(Б|б)(Л|л)(Я|я)(Т|т|Д|д)") var ebMsg = regexp.MustCompile("(Е|е|Ё|ё)(Б|б)(\\s|А|а|Т|т|У|у|Е|е|Ё|ё|И|и)") var piMsg = regexp.MustCompile("(П|п)(И|и)(З|з)(Д|д)") + + // Commands var helpMsg = regexp.MustCompile("/help\\z") var helloMsg = regexp.MustCompile("/start\\z") + var pokedexMsg = regexp.MustCompile("/pokede(x|ks)\\d?\\z") + // Forwards var pokememeMsg = regexp.MustCompile("(Уровень)(.+)(Опыт)(.+)\n(Элементы:)(.+)\n(.+)(💙MP)") if update.Message.ForwardFrom != nil { @@ -54,9 +72,17 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { if pokememeMsg.MatchString(text) { if player_raw.Id != 0 { log.Printf("Pokememe posted!") - c.Parsers.ParsePokememe(text, player_raw) + status := c.Parsers.ParsePokememe(text, player_raw) + switch status { + case "ok": + c.Talkers.PokememeAddSuccessMessage(update) + case "dup": + c.Talkers.PokememeAddDuplicateMessage(update) + case "fail": + c.Talkers.PokememeAddFailureMessage(update) + } } else { - talkers.AnyMessageUnauthorized(c.Bot, update) + c.Talkers.AnyMessageUnauthorized(update) } } else { log.Printf(text) @@ -67,24 +93,39 @@ func (r *Router) RouteRequest(update tgbotapi.Update) string { switch { case helloMsg.MatchString(text): if player_raw.Id != 0 { - talkers.HelloMessageAuthorized(c.Bot, update, player_raw) + c.Talkers.HelloMessageAuthorized(update, player_raw) } else { - talkers.HelloMessageUnauthorized(c.Bot, update) + c.Talkers.HelloMessageUnauthorized(update) } // Help case helpMsg.MatchString(text): - talkers.HelpMessage(c.Bot, update) + c.Talkers.HelpMessage(update) + // Pokememes info + case pokedexMsg.MatchString(text): + if strings.HasSuffix(text, "1") { + c.Talkers.PokememesList(update, 1) + } else if strings.HasSuffix(text, "2") { + c.Talkers.PokememesList(update, 2) + } else if strings.HasSuffix(text, "3") { + c.Talkers.PokememesList(update, 3) + } else if strings.HasSuffix(text, "4") { + c.Talkers.PokememesList(update, 4) + } else if strings.HasSuffix(text, "5") { + c.Talkers.PokememesList(update, 5) + } else { + c.Talkers.PokememesList(update, 1) + } // Easter eggs case huMsg.MatchString(text): - talkers.MatMessage(c.Bot, update) + c.Talkers.MatMessage(update) case blMsg.MatchString(text): - talkers.MatMessage(c.Bot, update) + c.Talkers.MatMessage(update) case ebMsg.MatchString(text): - talkers.MatMessage(c.Bot, update) + c.Talkers.MatMessage(update) case piMsg.MatchString(text): - talkers.MatMessage(c.Bot, update) + c.Talkers.MatMessage(update) case durakMsg.MatchString(text): - talkers.DurakMessage(c.Bot, update) + c.Talkers.DurakMessage(update) default: log.Printf("User posted unknown command.") return "fail" diff --git a/lib/talkers/easter.go b/lib/talkers/easter.go index eef0e82..8835852 100644 --- a/lib/talkers/easter.go +++ b/lib/talkers/easter.go @@ -12,7 +12,7 @@ import ( "gopkg.in/telegram-bot-api.v4" ) -func DurakMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { +func (t *Talkers) DurakMessage(update tgbotapi.Update) { log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) reactions := make([]string, 0) @@ -27,10 +27,10 @@ func DurakMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { msg := tgbotapi.NewMessage(update.Message.Chat.ID, reactions[rand.Intn(len(reactions))]) msg.ReplyToMessageID = update.Message.MessageID - bot.Send(msg) + c.Bot.Send(msg) } -func MatMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { +func (t *Talkers) MatMessage(update tgbotapi.Update) { log.Printf("[%s] %s", update.Message.From.UserName, update.Message.Text) reactions := make([]string, 0) @@ -44,5 +44,5 @@ func MatMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { msg := tgbotapi.NewMessage(update.Message.Chat.ID, reactions[rand.Intn(len(reactions))]) msg.ReplyToMessageID = update.Message.MessageID - bot.Send(msg) + c.Bot.Send(msg) } diff --git a/lib/talkers/errors.go b/lib/talkers/errors.go index 6d020bf..e78a1a6 100644 --- a/lib/talkers/errors.go +++ b/lib/talkers/errors.go @@ -8,12 +8,12 @@ import ( "gopkg.in/telegram-bot-api.v4" ) -func AnyMessageUnauthorized(bot *tgbotapi.BotAPI, update tgbotapi.Update) { +func (t *Talkers) AnyMessageUnauthorized(update tgbotapi.Update) { error_message := "Извини, действие для тебя недоступно. Возможно, у меня нет твоего профиля или же твои права недостаточны для совершения данного действия\n\n" error_message += "Если тебе кажется, что это ошибка, пиши @fat0troll.\n" msg := tgbotapi.NewMessage(update.Message.Chat.ID, error_message) msg.ParseMode = "Markdown" - bot.Send(msg) + c.Bot.Send(msg) } diff --git a/lib/talkers/exported.go b/lib/talkers/exported.go new file mode 100644 index 0000000..917f8f4 --- /dev/null +++ b/lib/talkers/exported.go @@ -0,0 +1,28 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package talkers + +import ( + // stdlib + "log" + // local + "../appcontext" + "../talkers/talkersinterface" +) + +var ( + c *appcontext.Context +) + +type Talkers struct {} + +func New(ac *appcontext.Context) { + c = ac + m := &Talkers{} + c.RegisterTalkersInterface(talkersinterface.TalkersInterface(m)) +} + +func (t *Talkers) Init() { + log.Printf("Initializing responders...") +} diff --git a/lib/talkers/hello.go b/lib/talkers/hello.go index 26831d0..706d5d5 100644 --- a/lib/talkers/hello.go +++ b/lib/talkers/hello.go @@ -10,7 +10,7 @@ import ( "../dbmappings" ) -func HelloMessageUnauthorized(bot *tgbotapi.BotAPI, update tgbotapi.Update) { +func (t *Talkers) HelloMessageUnauthorized(update tgbotapi.Update) { hello_message := "*Бот Инстинкта приветствует тебя!*\n\n" hello_message += "Для начала работы с ботом, пожалуйста, перешли от бота игры @PokememBroBot профиль героя.\n" hello_message += "Все дальнейшие действия с ботом возможны лишь при наличии профиля игрока." @@ -18,15 +18,15 @@ func HelloMessageUnauthorized(bot *tgbotapi.BotAPI, update tgbotapi.Update) { msg := tgbotapi.NewMessage(update.Message.Chat.ID, hello_message) msg.ParseMode = "Markdown" - bot.Send(msg) + c.Bot.Send(msg) } -func HelloMessageAuthorized(bot *tgbotapi.BotAPI, update tgbotapi.Update, player_raw dbmappings.Players) { +func (t *Talkers) HelloMessageAuthorized(update tgbotapi.Update, player_raw dbmappings.Players) { 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") msg := tgbotapi.NewMessage(update.Message.Chat.ID, hello_message) msg.ParseMode = "Markdown" - bot.Send(msg) + c.Bot.Send(msg) } diff --git a/lib/talkers/help.go b/lib/talkers/help.go index f3fae7c..f00b65d 100644 --- a/lib/talkers/help.go +++ b/lib/talkers/help.go @@ -10,7 +10,7 @@ import ( "../config" ) -func HelpMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { +func (t *Talkers) HelpMessage(update tgbotapi.Update) { help_message := "*Бот Инстинкта Enchanched.*\n\n" help_message += "Текущая версия: *" + config.VERSION + "*\n\n" help_message += "Список команд:\n\n" @@ -21,5 +21,5 @@ func HelpMessage(bot *tgbotapi.BotAPI, update tgbotapi.Update) { msg := tgbotapi.NewMessage(update.Message.Chat.ID, help_message) msg.ParseMode = "Markdown" - bot.Send(msg) + c.Bot.Send(msg) } diff --git a/lib/talkers/pokedex.go b/lib/talkers/pokedex.go new file mode 100644 index 0000000..3f1d956 --- /dev/null +++ b/lib/talkers/pokedex.go @@ -0,0 +1,118 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package talkers + +import ( + // stdlib + "log" + "strconv" + // 3rd party + "gopkg.in/telegram-bot-api.v4" + // local + "../dbmappings" +) + +type PokememeFull struct { + Pokememe dbmappings.Pokememes + Elements []dbmappings.Elements + Locations []dbmappings.Locations +} + +func (t *Talkers) PokememesList(update tgbotapi.Update, page int) { + pokememes := []dbmappings.Pokememes{} + err := c.Db.Select(&pokememes, "SELECT * FROM pokememes"); + if err != nil { + log.Println(err) + } + pokememes_limited := []dbmappings.Pokememes{} + err = c.Db.Select(&pokememes_limited, "SELECT * FROM pokememes ORDER BY grade asc, name asc LIMIT 50 OFFSET " + strconv.Itoa(50*(page-1))); + if err != nil { + log.Println(err) + } + elements := []dbmappings.Elements{} + err = c.Db.Select(&elements, "SELECT * FROM elements"); + if err != nil { + log.Println(err) + } + locations := []dbmappings.Locations{} + err = c.Db.Select(&locations, "SELECT * FROM locations"); + if err != nil { + log.Println(err) + } + pokememes_elements := []dbmappings.PokememesElements{} + err = c.Db.Select(&pokememes_elements, "SELECT * FROM pokememes_elements"); + if err != nil { + log.Println(err) + } + pokememes_locations := []dbmappings.PokememesLocations{} + err = c.Db.Select(&pokememes_locations, "SELECT * FROM pokememes_locations"); + if err != nil { + log.Println(err) + } + + pokememes_full := []PokememeFull{} + + for i := range(pokememes_limited) { + full_pokememe := PokememeFull{} + elements_listed := []dbmappings.Elements{} + locations_listed := []dbmappings.Locations{} + + for j := range(pokememes_locations) { + if pokememes_locations[j].Pokememe_id == pokememes_limited[i].Id { + for l := range(locations) { + if pokememes_locations[j].Location_id == locations[l].Id { + locations_listed = append(locations_listed, locations[l]) + } + } + } + } + + for k := range(pokememes_elements) { + if pokememes_elements[k].Pokememe_id == pokememes_limited[i].Id { + for e := range(elements) { + if pokememes_elements[k].Element_id == elements[e].Id { + elements_listed = append(elements_listed, elements[e]) + } + } + } + } + + full_pokememe.Pokememe = pokememes_limited[i] + full_pokememe.Elements = elements_listed + full_pokememe.Locations = locations_listed + + pokememes_full = append(pokememes_full, full_pokememe) + } + + message := "*Известные боту покемемы*\n" + message += "Список отсортирован по грейду и алфавиту.\n" + message += "Покедекс: " + strconv.Itoa(len(pokememes)) + " / 206\n" + message += "Отображаем покемемов с " + strconv.Itoa(((page - 1)*50)+1) + " по " + strconv.Itoa(page*50) + "\n" + if len(pokememes) > page*50 { + message += "Переход на следующую страницу: /pokedeks" + strconv.Itoa(page + 1) + } + if page > 1 { + message += "\nПереход на предыдущую страницу: /pokedeks" + strconv.Itoa(page - 1) + } + message += "\n\n" + + for i := range(pokememes_full) { + pk := pokememes_full[i].Pokememe + pk_e := pokememes_full[i].Elements + message += strconv.Itoa(i + 1 + (50*(page-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 + } + message += "] " + c.Parsers.ReturnPoints(pk.Price) + "$ /pk" + strconv.Itoa(pk.Id) + message += "\n" + } + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) + msg.ParseMode = "Markdown" + + c.Bot.Send(msg) +} diff --git a/lib/talkers/pokememe_add.go b/lib/talkers/pokememe_add.go new file mode 100644 index 0000000..be1370d --- /dev/null +++ b/lib/talkers/pokememe_add.go @@ -0,0 +1,41 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package talkers + +import ( + // 3rd party + "gopkg.in/telegram-bot-api.v4" +) + +func (t *Talkers) PokememeAddSuccessMessage(update tgbotapi.Update) { + message := "*Покемем успешно добавлен.*\n\n" + message += "Посмотреть всех известных боту покемемов можно командой /pokedeks" + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) + msg.ParseMode = "Markdown" + + c.Bot.Send(msg) +} + +func (t *Talkers) PokememeAddDuplicateMessage(update tgbotapi.Update) { + message := "*Мы уже знаем об этом покемеме*\n\n" + message += "Посмотреть всех известных боту покемемов можно командой /pokedeks\n\n" + message += "Если у покемема изменились описание или характеристики, напиши @fat0troll для обновления базы." + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) + msg.ParseMode = "Markdown" + + c.Bot.Send(msg) +} + +func (t *Talkers) PokememeAddFailureMessage(update tgbotapi.Update) { + message := "*Неудачно получилось :(*\n\n" + message += "Случилась жуткая ошибка, и мы не смогли записать бота в базу. Напиши @fat0troll, он разбер]тся.\n\n" + message += "Посмотреть всех известных боту покемемов можно командой /pokedeks" + + msg := tgbotapi.NewMessage(update.Message.Chat.ID, message) + msg.ParseMode = "Markdown" + + c.Bot.Send(msg) +} diff --git a/lib/talkers/talkersinterface/talkersinterface.go b/lib/talkers/talkersinterface/talkersinterface.go new file mode 100644 index 0000000..f1a78b9 --- /dev/null +++ b/lib/talkers/talkersinterface/talkersinterface.go @@ -0,0 +1,32 @@ +// i2_bot – Instinct PokememBro Bot +// Copyright (c) 2017 Vladimir "fat0troll" Hodakov + +package talkersinterface + +import ( + // 3rd party + "gopkg.in/telegram-bot-api.v4" + // local + "../../dbmappings" +) + +type TalkersInterface interface { + Init() + // Commands + HelloMessageUnauthorized(update tgbotapi.Update) + HelloMessageAuthorized(update tgbotapi.Update, player_raw dbmappings.Players) + HelpMessage(update tgbotapi.Update) + PokememesList(update tgbotapi.Update, page int) + + // Returns + PokememeAddSuccessMessage(update tgbotapi.Update) + PokememeAddDuplicateMessage(update tgbotapi.Update) + PokememeAddFailureMessage(update tgbotapi.Update) + + // Errors + AnyMessageUnauthorized(update tgbotapi.Update) + + // Easter eggs + DurakMessage(update tgbotapi.Update) + MatMessage(update tgbotapi.Update) +}