<commit_before>package stash

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

// Item represents a single item found from the stash api
type Item struct {
	Verified     bool     `json:"verified"`
	Ilvl         int      `json:"ilvl"`
	Icon         string   `json:"icon"`
	League       string   `json:"league"`
	ID           string   `json:"id"`
	Name         string   `json:"name"`
	TypeLine     string   `json:"typeLine"`
	Identified   bool     `json:"identified"`
	Corrupted    bool     `json:"corrupted"`
	ImplicitMods []string `json:"implicitMods,omitempty"`
	ExplicitMods []string `json:"explicitMods,omitempty"`
	FlavourText  []string `json:"flavourText,omitempty"`
	Note         string   `json:"note,omitempty"`
	Properties   []struct {
		Name        string        `json:"name"`
		Values      []interface{} `json:"values"`
		DisplayMode int           `json:"displayMode"`
	} `json:"properties,omitempty"`
	UtilityMods []string `json:"utilityMods,omitempty"`
	DescrText   string   `json:"descrText,omitempty"`
}

// Response represents expected structure of a stash api call
type Response struct {
	NextChangeID string `json:"next_change_id"`
	Stashes      []struct {
		AccountName       string `json:"accountName"`<commit_msg>stash custom unmarshal<commit_after>package stash

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
)

// PropertyValue holds a string value alongside an
// associated PrintKey
type PropertyValue struct {
	Value    string
	PrintKey int
}

// UnmarshalJSON implements custom deserialization for this type
//
// Typically, the GGG api will return [string, int] which is very unhelpful,
// so we take care of that right here
func (v *PropertyValue) UnmarshalJSON(b []byte) error {
	var raw []interface{}

	err := json.Unmarshal(b, &raw)
	if err != nil {
		return fmt.Errorf("invalid property pair, unparseable, err=%s", err)
	}

	if len(raw) != 2 {
		return fmt.Errorf("invalid property pair, (len()==%d)!=2", len(raw))
	}

	var ok bool
	v.Value, ok = raw[0].(string)
	if !ok {
		return fmt.Errorf("invalid property pair, first element not string")
	}

	// We have to use the widest possible type here and narrow...
	var broad float64
	broad, ok = raw[1].(float64)
	if !ok {
		return fmt.Errorf("invalid property pair, second element not float64")
	}
	v.PrintKey = int(broad)

	return nil
}

// Item represents a single item found from the stash api
type Item struct {
	Verified     bool     `json:"verified"`
	Ilvl         int      `json:"ilvl"`
	Icon         string   `json:"icon"`
	League       string   `json:"league"`
	ID           string   `json:"id"`
	Name         string   `json:"name"`
	TypeLine     string   `json:"typeLine"`
	Identified   bool     `json:"identified"`
	Corrupted    bool     `json:"corrupted"`
	ImplicitMods []string `json:"implicitMods,omitempty"`
	ExplicitMods []string `json:"explicitMods,omitempty"`
	FlavourText  []string `json:"flavourText,omitempty"`
	Note         string   `json:"note,omitempty"`
	Properties   []struct {
		Name        string          `json:"name"`
		Values      []PropertyValue `json:"values"`
		DisplayMode int             `json:"displayMode"`
	} `json:"properties,omitempty"`
	UtilityMods []string `json:"utilityMods,omitempty"`
	DescrText   string   `json:"descrText,omitempty"`
}

// Response represents expected structure of a stash api call
type Response struct {
	NextChangeID string `json:"next_change_id"`
	Stashes      []struct {
		AccountName       string `json:"accountName"`
{'fraction_non_alphanumeric': 0.12246645732229518, 'fraction_numerical': 0.0028546959748786756, 'mean_word_length': 3.446700507614213, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1723461', 'n_tokens_mistral': 1122, 'n_tokens_neox': 1091, 'n_words': 318}