Archived
1

Add pokememes info, convert it to new format and drop unnecessary database tables

This commit introduces pokememes information storage in source code (because they're rarely changed and I always update them manually).

All information about pokememes updated after nerf of 25 April. Also, added buttons to /pokedeks command for changing pages (there are 21 pages already!), and limited one page to 35 pokememes.
This commit is contained in:
2018-05-02 00:47:55 +04:00
parent b1975a161c
commit a9f1d25c7b
46 changed files with 10391 additions and 722 deletions

View File

@@ -1,32 +0,0 @@
// i2_bot Instinct PokememBro Bot
// Copyright (c) 2017 Vladimir "fat0troll" Hodakov
package pokedexer
import (
"github.com/go-telegram-bot-api/telegram-bot-api"
"strconv"
)
// DeletePokememe deletes pokememe by its ID
func (p *Pokedexer) DeletePokememe(update *tgbotapi.Update) string {
pokememeNum, _ := strconv.Atoi(update.Message.CommandArguments())
if pokememeNum == 0 {
return "fail"
}
err := c.DataCache.DeletePokememeByID(pokememeNum)
if err != nil {
c.Log.Error(err.Error())
return "fail"
}
message := "Покемем удалён."
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
msg.ParseMode = "Markdown"
c.Bot.Send(msg)
return "ok"
}

View File

@@ -5,14 +5,14 @@ package pokedexer
import (
"sort"
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
"source.wtfteam.pro/i2_bot/i2_bot/lib/datamapping"
"strconv"
"strings"
)
func (p *Pokedexer) getAdvicePokememes(playerID int, adviceType string) ([]*dbmapping.PokememeFull, bool) {
func (p *Pokedexer) getAdvicePokememes(playerID int, adviceType string) ([]*datamapping.PokememeFull, bool) {
c.Log.Debug("Getting advice for pokememes...")
pokememesArray := make([]*dbmapping.PokememeFull, 0)
pokememesArray := make([]*datamapping.PokememeFull, 0)
playerRaw, err := c.DataCache.GetPlayerByID(playerID)
if err != nil {
@@ -90,7 +90,7 @@ func (p *Pokedexer) getAdvicePokememes(playerID int, adviceType string) ([]*dbma
case "best", "advice", "best_nofilter":
if len(pokememesArray) > 5 {
idx := 0
pokememesArrayShorted := make([]*dbmapping.PokememeFull, 0)
pokememesArrayShorted := make([]*datamapping.PokememeFull, 0)
for i := range pokememesArray {
if idx < 5 {
pokememesArrayShorted = append(pokememesArrayShorted, pokememesArray[i])

View File

@@ -5,15 +5,14 @@ package pokedexer
import (
"github.com/go-telegram-bot-api/telegram-bot-api"
"regexp"
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
"strconv"
"strings"
// "time"
)
// ParsePokememe parses pokememe, forwarded from PokememeBroBot, to database
func (p *Pokedexer) ParsePokememe(update *tgbotapi.Update, playerRaw *dbmapping.Player) string {
c.Log.Info("Starting pokememe parsing...")
pokememeStringsArray := strings.Split(update.Message.Text, "\n")
pokememeRunesArray := make([][]rune, 0)
for i := range pokememeStringsArray {
@@ -21,149 +20,55 @@ func (p *Pokedexer) ParsePokememe(update *tgbotapi.Update, playerRaw *dbmapping.
}
pokememeData := make(map[string]string)
pokememeLocations := make(map[string]string)
pokememeElements := make(map[string]string)
hitPointsRx := regexp.MustCompile("(\\d|\\.)+(K|M)?")
for i := range pokememeStringsArray {
c.Log.Debug("Processing string: " + pokememeStringsArray[i])
if strings.Contains(pokememeStringsArray[i], "⃣") {
// Strings with name and grade
splitGradeAndName := strings.Split(string(pokememeRunesArray[i]), " ")
gradeNumberRegexp := regexp.MustCompile("[0-9]+")
pokememeData["grade"] = strings.Join(gradeNumberRegexp.FindAllString(splitGradeAndName[0], -1), "")
pokememeData["name"] = strings.Join(splitGradeAndName[1:], " ")
}
// Special case: "10" emoji
if strings.Contains(pokememeStringsArray[i], "🔟") {
// Strings with name and grade
pokememeData["grade"] = "10"
pokememeData["name"] = string(pokememeStringsArray[i][5:])
}
if i == 1 {
pokememeData["description"] = string(pokememeRunesArray[i])
}
if strings.HasPrefix(pokememeStringsArray[i], "Обитает: ") {
// Elements
locationsString := strings.TrimPrefix(pokememeStringsArray[i], "Обитает: ")
locationsArray := strings.Split(locationsString, ", ")
for i := range locationsArray {
pokememeLocations[strconv.Itoa(i)] = locationsArray[i]
infoString := pokememeStringsArray[i]
c.Log.Debug("Processing string: " + infoString)
if strings.HasPrefix(infoString, "Elements ") {
infoString = strings.Replace(infoString, "Elements ", "", -1)
elements := strings.Split(infoString, " ")
elementsIDs := make([]string, 0)
for ii := range elements {
element, _ := c.DataCache.FindElementIDBySymbol(elements[ii])
elementsIDs = append(elementsIDs, strconv.Itoa(element))
}
}
if strings.HasPrefix(pokememeStringsArray[i], "Элементы: ") {
// Elements
elementsString := strings.TrimPrefix(pokememeStringsArray[i], "Элементы: ")
elementsArray := strings.Split(elementsString, " ")
for i := range elementsArray {
pokememeElements[strconv.Itoa(i)] = elementsArray[i]
pokememeData["elements"] = "\\[" + strings.Join(elementsIDs, ", ") + "]"
} else if strings.HasPrefix(infoString, "Place ") {
infoString = strings.Replace(infoString, "Place ", "", -1)
places := strings.Split(infoString, ",")
locationIDs := make([]string, 0)
for ii := range places {
locationID, _ := c.DataCache.FindLocationIDByName(places[ii])
locationIDs = append(locationIDs, strconv.Itoa(locationID))
}
}
if strings.HasPrefix(pokememeStringsArray[i], "⚔Атака: ") {
// Attack, HP, MP
hitPoints := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
if len(hitPoints) != 3 {
c.Log.Error("Can't parse hitpoints!")
c.Log.Debug("Points string was: " + string(pokememeRunesArray[i]))
p.pokememeAddFailureMessage(update)
return "fail"
}
pokememeData["attack"] = hitPoints[0]
pokememeData["hp"] = hitPoints[1]
pokememeData["mp"] = hitPoints[2]
}
if strings.HasPrefix(pokememeStringsArray[i], "🛡Защита ") {
// Defence for top-level pokememes
defence := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
if len(defence) != 1 {
c.Log.Error("Can't parse defence!")
c.Log.Debug("Defence string was: " + string(pokememeRunesArray[i]))
p.pokememeAddFailureMessage(update)
return "fail"
}
pokememeData["defence"] = defence[0]
}
if strings.HasPrefix(pokememeStringsArray[i], "Стоимость :") {
// Price
price := hitPointsRx.FindAllString(string(pokememeRunesArray[i]), -1)
if len(price) != 1 {
c.Log.Error("Can't parse price!")
c.Log.Debug("Price string was: " + string(pokememeRunesArray[i]))
p.pokememeAddFailureMessage(update)
return "fail"
}
pokememeData["price"] = price[0]
}
if strings.HasPrefix(pokememeStringsArray[i], "Купить: ") {
// Purchaseability
pokememeData["locations"] = "\\[" + strings.Join(locationIDs, ", ") + "]"
} else if strings.HasPrefix(infoString, "Buyable ") {
pokememeData["purchaseable"] = "false"
if strings.Contains(pokememeStringsArray[i], "Можно") {
if strings.HasSuffix(infoString, "Yes") {
pokememeData["purchaseable"] = "true"
}
} else {
pokememeData[strings.Split(infoString, " ")[0]] = strings.Join(strings.Split(infoString, " ")[1:], " ")
}
}
// Image
for _, entity := range *update.Message.Entities {
if entity.Type == "text_link" && entity.URL != "" {
pokememeData["image"] = entity.URL
}
}
// Checking grade to be integer
_, err := strconv.Atoi(pokememeData["grade"])
if err != nil {
c.Log.Error(err.Error())
p.pokememeAddFailureMessage(update)
return "fail"
}
pokememeData["creator_id"] = strconv.Itoa(playerRaw.ID)
c.Log.Debugln("Pokememe data: ", pokememeData)
c.Log.Debugln("Elements: ", pokememeElements)
c.Log.Debugln("Locations: ", pokememeLocations)
if len(pokememeElements) == 0 {
p.pokememeAddFailureMessage(update)
return "fail"
}
message := "- id: " + pokememeData["Dex"]
message += "\n grade: " + pokememeData["Grade"]
message += "\n name: \"" + pokememeData["Name"] + "\""
message += "\n description: \"" + pokememeData["Description"] + "\""
message += "\n attack: " + pokememeData["Attack"]
message += "\n defence: " + pokememeData["Def"]
message += "\n health: " + pokememeData["HP"]
message += "\n mana: " + pokememeData["MP"]
message += "\n cost: " + pokememeData["Cost"]
message += "\n purchaseable: " + pokememeData["purchaseable"]
message += "\n image: \"" + pokememeData["Image"] + "\""
message += "\n elements: " + pokememeData["elements"]
message += "\n locations: " + pokememeData["locations"]
if len(pokememeLocations) == 0 {
p.pokememeAddFailureMessage(update)
return "fail"
}
c.Sender.SendMarkdownAnswer(update, message)
_, err = c.DataCache.GetPokememeByName(pokememeData["name"])
if err == nil {
// There is already a pokememe with such name, updating
pokememeID, err := c.DataCache.UpdatePokememe(pokememeData, pokememeLocations, pokememeElements)
if err != nil {
c.Log.Error(err.Error())
p.pokememeAddFailureMessage(update)
return "fail"
}
p.pokememeAddDuplicateMessage(update, pokememeID)
return "ok"
}
newPokememeID, err := c.DataCache.AddPokememe(pokememeData, pokememeLocations, pokememeElements)
if err != nil {
c.Log.Error(err.Error())
p.pokememeAddFailureMessage(update)
return "fail"
}
p.pokememeAddSuccessMessage(update, newPokememeID)
return "ok"
}

View File

@@ -6,22 +6,13 @@ package pokedexer
import (
"github.com/go-telegram-bot-api/telegram-bot-api"
"sort"
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
"source.wtfteam.pro/i2_bot/i2_bot/lib/datamapping"
"strconv"
)
func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememesArray map[int]*dbmapping.PokememeFull) {
message := "*Известные боту покемемы*\n"
message += "Список отсортирован по грейду и алфавиту.\n"
message += "Покедекс: " + strconv.Itoa(len(pokememesArray)) + " / 296\n"
message += "Отображаем покемемов с " + strconv.Itoa(((page-1)*50)+1) + " по " + strconv.Itoa(page*50) + "\n"
if len(pokememesArray) > page*50 {
message += "Переход на следующую страницу: /pokedeks" + strconv.Itoa(page+1)
}
if page > 1 {
message += "\nПереход на предыдущую страницу: /pokedeks" + strconv.Itoa(page-1)
}
message += "\n\n"
func (p *Pokedexer) pokememesListingMessage(update *tgbotapi.Update, page int, pokememesArray map[int]*datamapping.PokememeFull) string {
message := "📕*Покедекс: " + strconv.Itoa(len(pokememesArray)) + " / 733*\n"
message += "```\nВсе виды покемемов, которые известны боту. [" + strconv.Itoa(page) + "] (" + strconv.Itoa(((page-1)*35)+1) + "-" + strconv.Itoa(page*35) + ")```"
var keys []int
for i := range pokememesArray {
@@ -30,13 +21,13 @@ func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememe
sort.Ints(keys)
for _, i := range keys {
if (i+1 > 50*(page-1)) && (i+1 < (50*page)+1) {
if (i > 35*(page-1)) && (i < (35*page)+1) {
pk := pokememesArray[i].Pokememe
pkE := pokememesArray[i].Elements
message += strconv.Itoa(i+1) + ". *[" + strconv.Itoa(pk.Grade)
message += strconv.Itoa(pk.ID) + ". *[" + strconv.Itoa(pk.Grade)
message += "]* *" + pk.Name
message += "* (" + c.Statistics.GetPrintablePoints(pk.HP) + "-" + c.Statistics.GetPrintablePoints(pk.MP) + ") ⚔️ *"
message += c.Statistics.GetPrintablePoints(pk.Attack) + "* \\["
message += "* ❤️" + c.Statistics.GetPrintablePoints(pk.HP) + " ⚔️ "
message += c.Statistics.GetPrintablePoints(pk.Attack) + " 🛡" + c.Statistics.GetPrintablePoints(pk.Defence) + " \\["
for j := range pkE {
message += pkE[j].Symbol
}
@@ -45,49 +36,47 @@ func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememe
}
}
if len(pokememesArray) > page*50 {
message += "\n"
message += "Переход на следующую страницу: /pokedeks" + strconv.Itoa(page+1)
return message
}
func (p *Pokedexer) pokememesListingKeyboard(pokememesArray map[int]*datamapping.PokememeFull) *tgbotapi.InlineKeyboardMarkup {
keyboard := tgbotapi.InlineKeyboardMarkup{}
rows := make(map[int][]tgbotapi.InlineKeyboardButton)
rows[0] = []tgbotapi.InlineKeyboardButton{}
if len(pokememesArray) > 35*7 {
rows[1] = []tgbotapi.InlineKeyboardButton{}
}
if page > 1 {
message += "\nПереход на предыдущую страницу: /pokedeks" + strconv.Itoa(page-1)
if len(pokememesArray) > 35*14 {
rows[2] = []tgbotapi.InlineKeyboardButton{}
}
totalPages := int(len(pokememesArray)/35) + 1
for i := 1; i <= totalPages; i++ {
btn := tgbotapi.NewInlineKeyboardButtonData(strconv.Itoa(i), "pokedeks"+strconv.Itoa(i))
rows[(i-1)/7] = append(rows[(i-1)/7], btn)
}
for i := range rows {
keyboard.InlineKeyboard = append(keyboard.InlineKeyboard, rows[i])
}
return &keyboard
}
func (p *Pokedexer) pokememesListing(update *tgbotapi.Update, page int, pokememesArray map[int]*datamapping.PokememeFull) {
message := p.pokememesListingMessage(update, page, pokememesArray)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
msg.ParseMode = "Markdown"
msg.ReplyMarkup = p.pokememesListingKeyboard(pokememesArray)
c.Bot.Send(msg)
}
func (p *Pokedexer) pokememeAddSuccessMessage(update *tgbotapi.Update, newPokememeID int) {
message := "*Покемем успешно добавлен.*\n\n"
message += "Посмотреть всех известных боту покемемов можно командой /pokedeks\n"
message += "Посмотреть свежедобавленного покемема можно командой /pk" + strconv.Itoa(newPokememeID)
func (p *Pokedexer) pokememesListingUpdate(update *tgbotapi.Update, page int, pokememesArray map[int]*datamapping.PokememeFull) {
message := p.pokememesListingMessage(update, page, pokememesArray)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
msg.ParseMode = "Markdown"
messageUpdate := tgbotapi.NewEditMessageText(update.CallbackQuery.Message.Chat.ID, update.CallbackQuery.Message.MessageID, message)
messageUpdate.ParseMode = "Markdown"
messageUpdate.ReplyMarkup = p.pokememesListingKeyboard(pokememesArray)
c.Bot.Send(msg)
}
func (p *Pokedexer) pokememeAddDuplicateMessage(update *tgbotapi.Update, pokememeID int) {
message := "*Покемем успешно обновлён.*\n\n"
message += "Посмотреть всех известных боту покемемов можно командой /pokedeks\n"
message += "Посмотреть свежеобновлённого покемема можно командой /pk" + strconv.Itoa(pokememeID)
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
msg.ParseMode = "Markdown"
c.Bot.Send(msg)
}
func (p *Pokedexer) 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)
c.Bot.Send(messageUpdate)
}

View File

@@ -4,8 +4,8 @@
package pokedexerinterface
import (
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
"github.com/go-telegram-bot-api/telegram-bot-api"
"source.wtfteam.pro/i2_bot/i2_bot/lib/dbmapping"
)
// PokedexerInterface implements Pokedexer for importing via appcontext.
@@ -13,8 +13,7 @@ type PokedexerInterface interface {
ParsePokememe(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
PokememesList(update *tgbotapi.Update)
PokememesListUpdater(update *tgbotapi.Update) string
PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
AdvicePokememesList(update *tgbotapi.Update, playerRaw *dbmapping.Player) string
DeletePokememe(update *tgbotapi.Update) string
}

View File

@@ -99,6 +99,19 @@ func (p *Pokedexer) PokememesList(update *tgbotapi.Update) {
p.pokememesListing(update, page, pokememesArray)
}
// PokememesListUpdater updates page in pokedeks message
func (p *Pokedexer) PokememesListUpdater(update *tgbotapi.Update) string {
pageNumber := strings.Replace(update.CallbackQuery.Data, "pokedeks", "", 1)
page, _ := strconv.Atoi(pageNumber)
if page == 0 {
page = 1
}
pokememesArray := c.DataCache.GetAllPokememes()
p.pokememesListingUpdate(update, page, pokememesArray)
return "ok"
}
// PokememeInfo shows information about single pokememe based on internal ID
func (p *Pokedexer) PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.Player) string {
pokememeNumber := strings.Replace(update.Message.Text, "/pk", "", 1)
@@ -150,7 +163,7 @@ func (p *Pokedexer) PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.P
if c.Users.PlayerBetterThan(playerRaw, "academic") {
message += "\nВероятность поимки:"
idx := 1
for idx < 10 {
for idx < 23 {
levelHeaderPosted := false
for i := range pokememe.Locations {
percentile, pokeballs := c.Statistics.PossibilityRequiredPokeballs(pokememe.Locations[i].ID, pk.Grade, idx)
@@ -183,6 +196,7 @@ func (p *Pokedexer) PokememeInfo(update *tgbotapi.Update, playerRaw *dbmapping.P
msg := tgbotapi.NewMessage(update.Message.Chat.ID, message)
keyboard := tgbotapi.InlineKeyboardMarkup{}
for i := range pokememe.Locations {
c.Log.Info("wow, location")
var row []tgbotapi.InlineKeyboardButton
btn := tgbotapi.NewInlineKeyboardButtonSwitch(pokememe.Locations[i].Symbol+pokememe.Locations[i].Name, pokememe.Locations[i].Symbol+pokememe.Locations[i].Name)
row = append(row, btn)