package apiact import ( "encoding/json" "errors" "fmt" "io/ioutil" "log" "net/http" "net/url" "strconv" "strings" "time" "git.trj.tw/golang/mtgbot/modules/config" ) // TCGPlayer - type TCGPlayer struct { URL string APIVersion string AccessToken string UserName string Expire time.Time } // TCGPlayerAPIRes - type TCGPlayerAPIRes struct { Success bool `json:"success"` Errors []string `json:"errors"` Results []map[string]interface{} `json:"results"` } func (p *TCGPlayer) getAPIURL(urlPath string, requireVersion bool) (apiURL string, err error) { u, err := url.Parse(p.URL) if err != nil { return "", err } u, err = u.Parse(p.APIVersion) if err != nil { return "", err } u, err = u.Parse(urlPath) if err != nil { return "", err } return u.String(), nil } func (p *TCGPlayer) getHeader() map[string]string { m := make(map[string]string) m["Content-Type"] = "application/json" if len(p.AccessToken) > 0 { m["Authorization"] = fmt.Sprintf("Bearer %s", p.AccessToken) } return m } // NewTCGApi - func NewTCGApi(apiVersion string) (api *TCGPlayer, err error) { if len(apiVersion) == 0 { apiVersion = "v1.19.0" } api = &TCGPlayer{} api.APIVersion = apiVersion api.URL = "https://api.tcgplayer.com" return } // GetToken - func (p *TCGPlayer) GetToken() (err error) { conf := config.GetConf() apiURL, err := p.getAPIURL("/token", false) dataReader := strings.NewReader(fmt.Sprintf("grant_type=client_credentials&client_id=%s&client_secret=%s", conf.TCGPlayer.PublicKey, conf.TCGPlayer.PrivateKey)) reqObj := RequestObject{} reqObj.Method = "POST" reqObj.URL = apiURL reqObj.Body = dataReader reqObj.Headers = p.getHeader() req, err := GetRequest(reqObj) if err != nil { return err } resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() tokenStruct := struct { AccessToken string `json:"access_token"` TokenType string `json:"token_type"` ExpiresIn int `json:"expires_in"` UserName string `json:"userName"` Issued string `json:".issued"` Exipres string `json:"expires"` }{} respByte, err := ioutil.ReadAll(resp.Body) if err != nil { return err } err = json.Unmarshal(respByte, &tokenStruct) if err != nil { return err } if len(tokenStruct.AccessToken) == 0 { return errors.New("get access token fail") } p.AccessToken = tokenStruct.AccessToken return } // TCGPlayerCategory - type TCGPlayerCategory struct { CaegoryID int `json:"categoryId"` Name string `json:"name"` DisplayName string `json:"displayName"` ModifiedOn string `json:"modifiedOn"` SEOCategoryName string `json:"seoCategoryName"` SealedLabel string `json:"sealedLabel"` NonSealedLabel string `json:"nonSealedLabel"` ConditionGuideURL string `json:"conditionGuideUrl"` IsScannable bool `json:"isScannable"` Popularity int `json:"popularity"` } // ListCategory - func (p *TCGPlayer) ListCategory(limit, offset int) (category []*TCGPlayerCategory, err error) { apiURL, err := p.getAPIURL("/catalog/categories", true) if err != nil { return nil, err } tmpStruct := struct { TCGPlayerAPIRes Results []*TCGPlayerCategory `json:"results"` }{} if limit < 1 { limit = 1 } if offset < 0 { offset = 0 } qsVal := url.Values{} qsVal.Add("limit", strconv.Itoa(limit)) qsVal.Add("offset", strconv.Itoa(offset)) apiURL += fmt.Sprintf("?%s", qsVal.Encode()) reqObj := RequestObject{ Method: "GET", Headers: p.getHeader(), URL: apiURL, } req, err := GetRequest(reqObj) if err != nil { return nil, err } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() respByte, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } err = json.Unmarshal(respByte, &tmpStruct) if err != nil { return nil, err } if tmpStruct.Success != true { if len(tmpStruct.Errors) > 0 { return nil, errors.New(tmpStruct.Errors[0]) } return nil, errors.New("get category fail") } return tmpStruct.Results, nil } // TCGPlayerCategoryGroup - type TCGPlayerCategoryGroup struct { GroupID int `json:"groupId"` Name string `json:"name"` Abbreviation string `json:"abbreviation"` Supplemental bool `json:"supplemental"` PublishedOn string `json:"publishedOn"` ModifiedOn string `json:"modifiedOn"` CategoryID int `json:"categoryId"` } // ListCategoryGroups - func (p *TCGPlayer) ListCategoryGroups(categoryID, limit, offset int) (groups []*TCGPlayerCategoryGroup, err error) { apiURL, err := p.getAPIURL(fmt.Sprintf("/catalog/categories/%d/groups", categoryID), true) if err != nil { return nil, err } if limit < 1 { limit = 1 } if offset < 0 { offset = 0 } qsVal := url.Values{} qsVal.Add("limit", strconv.Itoa(limit)) qsVal.Add("offset", strconv.Itoa(offset)) apiURL += fmt.Sprintf("?%s", qsVal.Encode()) tmpStruct := struct { TCGPlayerAPIRes TotalItems int `json:"totalItems"` Results []*TCGPlayerCategoryGroup `json:"results"` }{} _ = tmpStruct reqObj := RequestObject{ Method: "GET", Headers: p.getHeader(), URL: apiURL, } req, err := GetRequest(reqObj) if err != nil { return nil, err } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() respByte, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } log.Println(string(respByte)) err = json.Unmarshal(respByte, &tmpStruct) if err != nil { return nil, err } if tmpStruct.Success != true { if len(tmpStruct.Errors) > 0 { return nil, errors.New(tmpStruct.Errors[0]) } return nil, errors.New("get category groups fail") } return tmpStruct.Results, nil } // TCGPlayerProductPrice - type TCGPlayerProductPrice struct { ProductID int `json:"productId"` LowPrice float32 `json:"lowPrice"` MidPrice float32 `json:"midPrice"` HighPrice float32 `json:"highPrice"` MarketPrice float32 `json:"marketPrice"` DirectLowPrice float32 `json:"directLowPrice"` SubTypeName string `json:"subTypeName"` } // ListGroupProductPrice - func (p *TCGPlayer) ListGroupProductPrice(groupID int) (prices []*TCGPlayerProductPrice, err error) { apiURL, err := p.getAPIURL(fmt.Sprintf("/pricing/group/%d", groupID), true) if err != nil { return nil, err } tmpStruct := struct { TCGPlayerAPIRes Results []*TCGPlayerProductPrice `json:"results"` }{} reqObj := RequestObject{ URL: apiURL, Headers: p.getHeader(), Method: "GET", } req, err := GetRequest(reqObj) if err != nil { return nil, err } resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() respByte, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } err = json.Unmarshal(respByte, &tmpStruct) if err != nil { return nil, err } if tmpStruct.Success != true { if len(tmpStruct.Errors) > 0 { return nil, errors.New(tmpStruct.Errors[0]) } return nil, errors.New("get product price fail") } return tmpStruct.Results, nil }