Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 96 additions & 66 deletions src/TibiaBoostableBossesOverview.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package main

import (
"fmt"
"errors"
"net/http"
"regexp"
"strings"

"github.com/PuerkitoBio/goquery"
"github.com/TibiaData/tibiadata-api-go/src/validation"
)

// Child of BoostableBoss (used for list of boostable bosses and boosted boss section)
Expand All @@ -28,95 +27,126 @@ type BoostableBossesOverviewResponse struct {
Information Information `json:"information"`
}

var (
BoostedBossNameRegex = regexp.MustCompile(`<b>(.*)</b>`)
BoostedBossImageRegex = regexp.MustCompile(`<img[^>]+\bsrc=["']([^"']+)["']`)
BoostableBossInformationRegex = regexp.MustCompile(`<img src="(.*)" border.*div>(.*)<\/div>`)
)
func TibiaBoostableBossesOverviewImpl(BoxContentHTML string) (BoostableBossesOverviewResponse, error) {
const (
bodyIndexer = `<body`
endBodyIndexer = `</body>`

func TibiaBoostableBossesOverviewImpl(BoxContentHTML string) (*BoostableBossesOverviewResponse, error) {
// Creating empty vars
var (
BoostedBossName, BoostedBossImage string
todayChecker = `Today's boosted boss: `
bossesChecker = `<div class="CaptionContainer">`

todayBossIndexer = `title="` + todayChecker
endTodayBossIndexer = `" src="`

todayBossImgIndexer = `https://static.tibia.com/images/global/header/monsters/`
endTodayBossImgIndexer = `" onClick="`

bossesImgIndexer = `https://static.tibia.com/images/library/`
endBossesImgIndexer = `"`

bossesNameIndexer = `border=0 /> <div>`
endBossesNameIndexer = `</div>`
)

bodyIdx := strings.Index(
BoxContentHTML, bodyIndexer,
)
// Loading HTML data into ReaderHTML for goquery with NewReader
ReaderHTML, err := goquery.NewDocumentFromReader(strings.NewReader(BoxContentHTML))
if err != nil {
return nil, fmt.Errorf("[error] TibiaBoostableBossesOverviewImpl failed at goquery.NewDocumentFromReader, err: %s", err)
}

// Getting data from div.InnerTableContainer and then first p
InnerTableContainerTMPB, err := ReaderHTML.Find(".InnerTableContainer p").First().Html()
if err != nil {
return nil, fmt.Errorf("[error] TibiaBoostableBossesOverviewImpl failed at ReaderHTML.Find, error: %s", err)
if bodyIdx == -1 {
return BoostableBossesOverviewResponse{}, errors.New("[error] body passd to TibiaBoostableBossesOverviewImpl is not valid")
}

// Regex to get data for name for boosted boss
subma1b := BoostedBossNameRegex.FindAllStringSubmatch(InnerTableContainerTMPB, -1)
endBodyIdx := strings.Index(
BoxContentHTML[bodyIdx:], endBodyIndexer,
) + bodyIdx + len(endBodyIndexer)

if len(subma1b) > 0 {
// Settings vars for usage in JSONData
BoostedBossName = subma1b[0][1]
if endBodyIdx == -1 {
return BoostableBossesOverviewResponse{}, errors.New("[error] body passd to TibiaBoostableBossesOverviewImpl is not valid")
}

// Regex to get image of boosted boss
subma2b := BoostedBossImageRegex.FindAllStringSubmatch(InnerTableContainerTMPB, -1)
data := BoxContentHTML[bodyIdx:endBodyIdx]

if len(subma2b) > 0 {
// Settings vars for usage in JSONData
BoostedBossImage = subma2b[0][1]
}
var (
started bool

// Creating empty BoostableBossesData var
var BoostableBossesData []OverviewBoostableBoss
boostedBossName string
boostedBossImg string

var insideError error
bosses = make([]OverviewBoostableBoss, 0, validation.AmountOfBoostableBosses)
)

// Running query over each div
ReaderHTML.Find(".BoxContent div div").EachWithBreak(func(index int, s *goquery.Selection) bool {
split := strings.Split(data, "\n")
for _, cur := range split {
isTodaysLine := strings.Contains(cur, todayChecker) && !started
isBossesLine := strings.Contains(cur, bossesChecker)

// Storing HTML into BoostableBossDivHTML
BoostableBossDivHTML, err := s.Html()
if err != nil {
insideError = fmt.Errorf("[error] TibiaBoostableBossesOverviewImpl failed at BoostableBossDivHTML, err := s.Html(), err: %s", err)
return false
if !isTodaysLine && !isBossesLine {
continue
}

// Regex to get data for name, race and img src param for creature
subma1 := BoostableBossInformationRegex.FindAllStringSubmatch(BoostableBossDivHTML, -1)
if isTodaysLine {
started = true

// check if regex return length is over 0 and the match of name is over 1
if len(subma1) > 0 && len(subma1[0][2]) > 1 {
// Adding bool to indicate features in boostable_boss_list
FeaturedRace := false
if subma1[0][2] == BoostedBossName {
FeaturedRace = true
}
todayBossIdx := strings.Index(
cur, todayBossIndexer,
) + len(todayBossIndexer)
endTodayBossIdx := strings.Index(
cur[todayBossIdx:], endTodayBossIndexer,
) + todayBossIdx

// Creating data block to return
BoostableBossesData = append(BoostableBossesData, OverviewBoostableBoss{
Name: TibiaDataSanitizeEscapedString(subma1[0][2]),
ImageURL: subma1[0][1],
Featured: FeaturedRace,
})
boostedBossName = TibiaDataSanitizeEscapedString(
cur[todayBossIdx:endTodayBossIdx],
)

todayBossImgIdx := strings.Index(
cur[todayBossIdx:], todayBossImgIndexer,
) + todayBossIdx
endTodayBossImgIdx := strings.Index(
cur[todayBossImgIdx:], endTodayBossImgIndexer,
) + todayBossImgIdx

boostedBossImg = cur[todayBossImgIdx:endTodayBossImgIdx]
}

return true
})
if isBossesLine {
for idx := strings.Index(cur, bossesImgIndexer); idx != -1; idx = strings.Index(cur, bossesImgIndexer) {
imgIdx := strings.Index(
cur, bossesImgIndexer,
)
endImgIdx := strings.Index(
cur[imgIdx:], endBossesImgIndexer,
) + imgIdx
img := cur[imgIdx:endImgIdx]

nameIdx := strings.Index(
cur, bossesNameIndexer,
) + len(bossesNameIndexer)
endNameIdx := strings.Index(
cur[nameIdx:], endBossesNameIndexer,
) + nameIdx
name := TibiaDataSanitizeEscapedString(cur[nameIdx:endNameIdx])

bosses = append(bosses, OverviewBoostableBoss{
Name: name,
ImageURL: img,
Featured: name == boostedBossName,
})

cur = cur[endNameIdx-1:]
}

if insideError != nil {
return nil, insideError
break
}
}

// Build the data-blob
return &BoostableBossesOverviewResponse{
return BoostableBossesOverviewResponse{
BoostableBossesContainer{
Boosted: OverviewBoostableBoss{
Name: TibiaDataSanitizeEscapedString(BoostedBossName),
ImageURL: BoostedBossImage,
Name: boostedBossName,
ImageURL: boostedBossImg,
Featured: true,
},
BoostableBosses: BoostableBossesData,
BoostableBosses: bosses,
},
Information{
APIDetails: TibiaDataAPIDetails,
Expand Down
91 changes: 76 additions & 15 deletions src/TibiaBoostableBossesOverview_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,85 @@ func TestBoostableBossesOverview(t *testing.T) {

boostableBossesJson, _ := TibiaBoostableBossesOverviewImpl(string(data))
assert := assert.New(t)
boosted := boostableBossesJson.BoostableBosses.Boosted
bosses := boostableBossesJson.BoostableBosses.BoostableBosses

assert.Equal("Goshnar's Malice", boostableBossesJson.BoostableBosses.Boosted.Name)
assert.Equal("https://static.tibia.com/images/global/header/monsters/goshnarsmalice.gif", boostableBossesJson.BoostableBosses.Boosted.ImageURL)
assert.Equal(91, len(bosses))
assert.Equal("Sharpclaw", boosted.Name)
assert.Equal(
"https://static.tibia.com/images/global/header/monsters/sharpclaw.gif",
boosted.ImageURL,
)

assert.Equal(89, len(boostableBossesJson.BoostableBosses.BoostableBosses))
for _, tc := range []struct {
idx int
name string
featured bool
imageURL string
}{
{
idx: 19,
name: "Gnomevil",
featured: false,
imageURL: "https://static.tibia.com/images/library/gnomehorticulist.gif",
},
{
idx: 24,
name: "Goshnar's Malice",
featured: false,
imageURL: "https://static.tibia.com/images/library/goshnarsmalice.gif",
},
{
idx: 52,
name: "Sharpclaw",
featured: true,
imageURL: "https://static.tibia.com/images/library/sharpclaw.gif",
},
{
idx: 75,
name: "The Pale Worm",
featured: false,
imageURL: "https://static.tibia.com/images/library/paleworm.gif",
},
} {
boss := bosses[tc.idx]
assert.Equal(
tc.name, boss.Name,
"Wrong name\nidx: %d (%s)\nwant: %s\ngot: %s",
tc.idx, tc.name, tc.name, boss.Name,
)
assert.Equal(
tc.featured, boss.Featured,
"Wrong featured status\nidx: %d (%s)\nwant: %v\ngot: %v",
tc.idx, tc.name, tc.featured, boss.Featured,
)
assert.Equal(
tc.imageURL, boss.ImageURL,
"Wrong image URL\nidx: %d (%s)\nwant: %s\ngot: %s",
tc.idx, tc.name, tc.imageURL, boss.ImageURL,
)
}
}

gnomevil := boostableBossesJson.BoostableBosses.BoostableBosses[18]
assert.Equal("Gnomevil", gnomevil.Name)
assert.Equal("https://static.tibia.com/images/library/gnomehorticulist.gif", gnomevil.ImageURL)
assert.False(gnomevil.Featured)
var bossSink BoostableBossesOverviewResponse

goshnarsmalice := boostableBossesJson.BoostableBosses.BoostableBosses[23]
assert.Equal("Goshnar's Malice", goshnarsmalice.Name)
assert.Equal("https://static.tibia.com/images/library/goshnarsmalice.gif", goshnarsmalice.ImageURL)
assert.True(goshnarsmalice.Featured)
func BenchmarkTibiaBoostableBossesOverviewImpl(b *testing.B) {
file, err := static.TestFiles.Open("testdata/boostablebosses/boostablebosses.html")
if err != nil {
b.Fatalf("file opening error: %s", err)
}
defer file.Close()

paleworm := boostableBossesJson.BoostableBosses.BoostableBosses[73]
assert.Equal("The Pale Worm", paleworm.Name)
assert.Equal("https://static.tibia.com/images/library/paleworm.gif", paleworm.ImageURL)
assert.False(paleworm.Featured)
rawData, err := io.ReadAll(file)
if err != nil {
b.Fatalf("File reading error: %s", err)
}
data := string(rawData)

b.ReportAllocs()
b.ResetTimer()

for i := 0; i < b.N; i++ {
bossSink, _ = TibiaBoostableBossesOverviewImpl(data)
}
}
Loading