diff --git a/cmd/cli/main.go b/cmd/cli/main.go index 71f1228..95ff86f 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -9,6 +9,7 @@ import ( "github.com/cptpingu/poe-stash/generate" "github.com/cptpingu/poe-stash/misc" "github.com/cptpingu/poe-stash/scraper" + "github.com/pkg/errors" ) // mandatoryOption ensure an option is not empty. @@ -30,7 +31,7 @@ func scrapData(account, poeSessID, realm, league string, demo, cache bool, verbo scraper.SetVerbosity(verbosity) data, err := scraper.ScrapEverything() if err != nil { - return nil, err + return nil, errors.Wrap(err, "ScrapEverything") } return data, nil @@ -46,12 +47,12 @@ func generateData(data *scraper.ScrapedData, output string) (resErr error) { } else { file, err = os.Create(output) if err != nil { - return err + return errors.Wrap(err, "os.Create") } defer func() { if err := file.Close(); err != nil { if resErr != nil { - resErr = err + resErr = errors.Wrap(err, "file.Close") } } }() @@ -60,10 +61,10 @@ func generateData(data *scraper.ScrapedData, output string) (resErr error) { w := bufio.NewWriter(file) gen := generate.NewGenerator(w) if errGen := gen.GenerateHTML(data); errGen != nil { - return err + return errors.Wrap(err, "GenerateHTML") } if errFlush := w.Flush(); err != nil { - return errFlush + return errors.Wrap(errFlush, "Flush") } return nil @@ -127,7 +128,7 @@ func main() { data, errScrap := scrapData(*account, *poeSessID, *realm, *league, *demo, *cache, *verbosity) if errScrap != nil { - fmt.Println("can't scrap data", errScrap) + fmt.Println("can't scrap data", errors.WithStack(errScrap)) os.Exit(2) } diff --git a/cmd/server/main.go b/cmd/server/main.go index 62cd05a..bb5027a 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -11,6 +11,7 @@ import ( "strings" "github.com/gin-gonic/gin" + "github.com/pkg/errors" "github.com/cptpingu/poe-stash/cmd/server/page" "github.com/cptpingu/poe-stash/generate" @@ -127,7 +128,7 @@ func main() { var err error _, err = loadPasswords(*passwordFile) if err != nil { - panic(err) + panic(errors.Wrap(err, "loadPasswords")) } } diff --git a/data/cache/.dummy b/data/cache/.dummy deleted file mode 100644 index e69de29..0000000 diff --git a/data/template/parts/header.tmpl b/data/template/parts/header.tmpl index d56a393..e03431a 100644 --- a/data/template/parts/header.tmpl +++ b/data/template/parts/header.tmpl @@ -7,16 +7,17 @@ PoE Stash{{ $title }} - - - - - - - - - + + + + + + + + + + {{ template "style.css" }} diff --git a/data/template/parts/item.tmpl b/data/template/parts/item.tmpl index dd71edc..89a14dc 100644 --- a/data/template/parts/item.tmpl +++ b/data/template/parts/item.tmpl @@ -79,8 +79,8 @@ {{ $layout = .CurrencyLayout }} {{ $layoutType = "currency" }}
- {{ else if .FragmentLayout }} - {{ $layout = .FragmentLayout }} + {{ else if .FragmentLayout.Layouts }} + {{ $layout = .FragmentLayout.Layouts }} {{ $layoutType = "fragment" }}
{{ else if .EssenceLayout }} diff --git a/generate/generator.go b/generate/generator.go index f5d547b..8bf684a 100644 --- a/generate/generator.go +++ b/generate/generator.go @@ -80,7 +80,7 @@ func LoadAllTemplates() (*template.Template, error) { return template.HTMLAttr(s) }, "ieq": func(a, b string) bool { - return strings.ToLower(a) == strings.ToLower(b) + return strings.EqualFold(a, b) }, "safe": func(s string) template.HTML { return template.HTML(s) @@ -179,7 +179,7 @@ func FindAndParseTemplates(rootDir, ext string, funcMap template.FuncMap) (*temp name := path[pfx:] t := root.New(name).Funcs(funcMap) - t, e2 = t.Parse(string(b)) + _, e2 = t.Parse(string(b)) if e2 != nil { return e2 } @@ -487,7 +487,7 @@ func PoEMarkup(raw string, small bool) template.HTML { // It is expexcted to only have lines separated by end of lines. func PoEMarkupLinesOnly(lines []string, small bool) template.HTML { res := ReplacePoEMarkup(strings.Join(lines, "\n"), small) - strings.Replace(res, "\n", "
", -1) + res = strings.Replace(res, "\n", "
", -1) return template.HTML(res) } @@ -674,7 +674,7 @@ func extractWords(line string) []string { // GenNaiveSearchIndex generates very naive indexing for an item description. // It's just a list of selected unique sorted words. func GenNaiveSearchIndex(item models.Item) string { - words := make(map[string]struct{}, 0) + words := make(map[string]struct{}) // Extract name. for _, v := range extractWords(item.Name) { @@ -794,45 +794,31 @@ func itemCategoryType(categories models.Category) []string { if categories.Armor != nil { res = append(res, models.Armors...) - for _, v := range *categories.Armor { - res = append(res, v) - } + res = append(res, *categories.Armor...) } if categories.Accessories != nil { res = append(res, models.Accessories...) - for _, v := range *categories.Accessories { - res = append(res, v) - } + res = append(res, *categories.Accessories...) } if categories.Currency != nil { res = append(res, models.Currencies...) - for _, v := range *categories.Currency { - res = append(res, v) - } + res = append(res, *categories.Currency...) } if categories.Jewels != nil { res = append(res, models.Jewels...) - for _, v := range *categories.Jewels { - res = append(res, v) - } + res = append(res, *categories.Jewels...) } if categories.Weapons != nil { res = append(res, models.Weapons...) - for _, v := range *categories.Weapons { - res = append(res, v) - } + res = append(res, *categories.Weapons...) } if categories.Gems != nil { res = append(res, models.Gems...) - for _, v := range *categories.Gems { - res = append(res, v) - } + res = append(res, *categories.Gems...) } if categories.Maps != nil { res = append(res, models.Maps...) - for _, v := range *categories.Maps { - res = append(res, v) - } + res = append(res, *categories.Maps...) } return res diff --git a/generate/generator_test.go b/generate/generator_test.go index 7fd77b2..1c6ed28 100644 --- a/generate/generator_test.go +++ b/generate/generator_test.go @@ -5,19 +5,6 @@ import ( "testing" ) -func mapEqual(a, b map[string][]string) bool { - if len(a) != len(b) { - return false - } - for k, v := range a { - if w, ok := b[k]; !ok { //|| v != w { - _, _ = v, w - return false - } - } - return true -} - // TestPoEMarkup tests parsing custom langage works. func TestPoEMarkup(t *testing.T) { tests := []struct { diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..645a518 --- /dev/null +++ b/go.mod @@ -0,0 +1,8 @@ +module github.com/cptpingu/poe-stash + +go 1.16 + +require ( + github.com/gin-gonic/gin v1.7.7 + github.com/pkg/errors v0.9.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..a9c1838 --- /dev/null +++ b/go.sum @@ -0,0 +1,56 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= +github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7aM3F26W0hOn+GE= +github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= +github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42 h1:vEOn+mP2zCOVzKckCZy6YsCtDblrpj/w7B9nxGNELpg= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/misc/version.go b/misc/version.go index 66d0472..2d5412c 100644 --- a/misc/version.go +++ b/misc/version.go @@ -1,4 +1,4 @@ package misc // Version of the application. -const Version = "v1.0" +const Version = "v1.1" diff --git a/models/item.go b/models/item.go index d04bad1..ae00cc8 100644 --- a/models/item.go +++ b/models/item.go @@ -138,13 +138,13 @@ type LayoutType string // Layout is the type of layout to use (type of grid to place items). const ( DefaultLayout LayoutType = "" - CurrencyLayout = "currency" - InventoryLayout = "inventory" - JewelLayout = "jewel" - FragmentLayout = "fragment" - MapLayout = "map" - QuadLayout = "quad" - EssenceLayout = "essence" - DivinationLayout = "divination" - UniqueLayout = "unique" + CurrencyLayout LayoutType = "currency" + InventoryLayout LayoutType = "inventory" + JewelLayout LayoutType = "jewel" + FragmentLayout LayoutType = "fragment" + MapLayout LayoutType = "map" + QuadLayout LayoutType = "quad" + EssenceLayout LayoutType = "essence" + DivinationLayout LayoutType = "divination" + UniqueLayout LayoutType = "unique" ) diff --git a/models/stash.go b/models/stash.go index 9cf26fe..181c969 100644 --- a/models/stash.go +++ b/models/stash.go @@ -29,11 +29,13 @@ type Tab struct { // Layout is used for custom layout like currency. type Layout struct { - Type LayoutType // Not mapped used internally. - X float64 `json:"x"` - Y float64 `json:"y"` - W int `json:"w"` - H int `json:"h"` + Type LayoutType // Not mapped used internally. + Section string `json:"section"` + X float64 `json:"x"` + Y float64 `json:"y"` + W int `json:"w"` + H int `json:"h"` + Scale float64 `json:"scale"` } // CardLayout is used for the divination card layout. @@ -51,16 +53,22 @@ type DivineLayout struct { Cards []CardLayout `json:"cards"` } +// FragmentLayoutType hold fragment layout information. +type FragmentLayoutType struct { + Sections []string `json:"sections"` + Layouts map[string]Layout `json:"layout"` +} + // StashTab holds all stash tabulations (thus all items). type StashTab struct { - NumTabs int `json:"numTabs"` - QuadLayout bool `json:"quadLayout"` - Items []Item `json:"items"` - Tabs []Tab `json:"tabs"` - CurrencyLayout map[string]Layout `json:"currencyLayout"` - FragmentLayout map[string]Layout `json:"fragmentLayout"` - EssenceLayout map[string]Layout `json:"essenceLayout"` - DivinationLayout DivineLayout `json:"divinationLayout"` + NumTabs int `json:"numTabs"` + QuadLayout bool `json:"quadLayout"` + Items []Item `json:"items"` + Tabs []Tab `json:"tabs"` + CurrencyLayout map[string]Layout `json:"currencyLayout"` + FragmentLayout FragmentLayoutType `json:"fragmentLayout"` + EssenceLayout map[string]Layout `json:"essenceLayout"` + DivinationLayout DivineLayout `json:"divinationLayout"` // Can be empty, hence the *, for allowing to be nullable. MapLayout *map[string]Layout `json:"mapLayout"` diff --git a/scraper/scraper.go b/scraper/scraper.go index 761590d..b3c08d0 100644 --- a/scraper/scraper.go +++ b/scraper/scraper.go @@ -9,6 +9,7 @@ import ( "time" "github.com/cptpingu/poe-stash/models" + "github.com/pkg/errors" ) const ( @@ -157,7 +158,7 @@ func (s *Scraper) CallAPI(apiURL string) ([]byte, error) { req, err := http.NewRequest("GET", apiURL, nil) if err != nil { - return nil, err + return nil, errors.Wrap(err, "NewRequest") } cookie := http.Cookie{ Name: "POESESSID", @@ -173,7 +174,7 @@ func (s *Scraper) CallAPI(apiURL string) ([]byte, error) { resp, errResponse := s.client.Do(req) queryDone() if errResponse != nil { - return nil, errResponse + return nil, errors.Wrap(errResponse, "client.") } s.updateRateLimit(resp, baseURL) @@ -181,7 +182,7 @@ func (s *Scraper) CallAPI(apiURL string) ([]byte, error) { defer func() { localErr := resp.Body.Close() if err == nil { - err = localErr + err = errors.Wrap(localErr, "Body.Close") } }() @@ -191,7 +192,7 @@ func (s *Scraper) CallAPI(apiURL string) ([]byte, error) { body, errRead := ioutil.ReadAll(resp.Body) if errRead != nil { - return nil, errRead + return nil, errors.Wrap(errRead, "ioutil.ReadAll") } if s.cache { @@ -219,7 +220,7 @@ func (s *Scraper) ScrapEverything() (*ScrapedData, error) { // Get the list of all characters of a user. characters, errChar := s.ScrapCharacters() if errChar != nil { - return nil, errChar + return nil, errors.Wrap(errChar, "ScrapCharacters") } // Get inventory of every characters found. @@ -227,12 +228,12 @@ func (s *Scraper) ScrapEverything() (*ScrapedData, error) { if !character.Expired { charInventory, errInventory := s.ScrapCharacterInventory(character.Name) if errInventory != nil { - return nil, errInventory + return nil, errors.Wrap(errInventory, "ScrapCharacterInventory") } data.Characters = append(data.Characters, charInventory) charSkills, errSkills := s.ScrapCharacterSkills(character.Name) if errSkills != nil { - return nil, errSkills + return nil, errors.Wrap(errSkills, "ScrapCharacterSkills") } data.Skills = append(data.Skills, charSkills) } @@ -241,7 +242,7 @@ func (s *Scraper) ScrapEverything() (*ScrapedData, error) { // Retrieves the stash of an account. tabsDesc, stash, errStash := s.ScrapWholeStash() if errStash != nil { - return nil, errStash + return nil, errors.Wrap(errStash, "ScrapWholeStash") } data.TabsDesc = tabsDesc data.Stash = stash @@ -254,11 +255,11 @@ func (s *Scraper) ScrapEverything() (*ScrapedData, error) { func (s *Scraper) GetLeagues() ([]*models.League, error) { body, errRequest := s.CallAPI(LeaguesURL) if errRequest != nil { - return nil, errRequest + return nil, errors.Wrap(errRequest, "CallAPI") } leagues, errLeagues := models.ParseLeagues(body) if errLeagues != nil { - return nil, errLeagues + return nil, errors.Wrap(errLeagues, "ParseLeagues") } return leagues, nil diff --git a/scraper/stash.go b/scraper/stash.go index c4e1618..18f180a 100644 --- a/scraper/stash.go +++ b/scraper/stash.go @@ -7,6 +7,7 @@ import ( "strconv" "github.com/cptpingu/poe-stash/models" + "github.com/pkg/errors" ) // ScrapStash scraps a stash from the official website. @@ -17,19 +18,19 @@ func (s *Scraper) ScrapStash(indexID int) (*models.StashTab, error) { filename := DemoDir + s.accountName + "/stash_" + strconv.Itoa(indexID) + ".json" body, err = ioutil.ReadFile(filename) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "ioutil.ReadFile(%s)", filename) } } else { url := fmt.Sprintf(StashURL, url.QueryEscape(s.accountName), url.QueryEscape(s.realm), url.QueryEscape(s.league), 1, indexID) body, err = s.CallAPI(url) if err != nil { - return nil, err + return nil, errors.Wrapf(err, "CallAPI(%s)", url) } } stash, errStash := models.ParseStashTab(body) if errStash != nil { - return nil, errStash + return nil, errors.Wrap(errStash, "ParseStashTab") } return stash, nil @@ -42,7 +43,7 @@ func (s *Scraper) ScrapWholeStash() ([]models.Tab, []*models.StashTab, error) { // Scrap first stash to get the number of stash. firstStash, err := s.ScrapStash(0) if err != nil { - return nil, nil, err + return nil, nil, errors.Wrap(err, "ScrapStash(0)") } stashTab = append(stashTab, firstStash) @@ -50,7 +51,7 @@ func (s *Scraper) ScrapWholeStash() ([]models.Tab, []*models.StashTab, error) { for i := 1; i < firstStash.NumTabs; i++ { stash, err := s.ScrapStash(i) if err != nil { - return nil, nil, err + return nil, nil, errors.Wrapf(err, "ScrapStash(%d)", i) } stashTab = append(stashTab, stash) }