2019-01-14 10:06:10 +00:00
|
|
|
package apiact
|
|
|
|
|
|
|
|
import (
|
2019-01-15 07:56:01 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2019-01-14 10:06:10 +00:00
|
|
|
"fmt"
|
2019-01-15 07:56:01 +00:00
|
|
|
"io/ioutil"
|
2019-01-15 09:58:46 +00:00
|
|
|
"log"
|
2019-01-15 07:56:01 +00:00
|
|
|
"net/http"
|
2019-01-14 10:06:10 +00:00
|
|
|
"net/url"
|
2019-01-15 07:56:01 +00:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2019-01-14 10:06:10 +00:00
|
|
|
"time"
|
2019-01-15 07:56:01 +00:00
|
|
|
|
|
|
|
"git.trj.tw/golang/mtgbot/modules/config"
|
2019-01-14 10:06:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// TCGPlayer -
|
|
|
|
type TCGPlayer struct {
|
|
|
|
URL string
|
|
|
|
APIVersion string
|
|
|
|
AccessToken string
|
|
|
|
UserName string
|
|
|
|
Expire time.Time
|
|
|
|
}
|
|
|
|
|
2019-01-15 07:56:01 +00:00
|
|
|
// 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) {
|
2019-01-14 10:06:10 +00:00
|
|
|
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"
|
2019-01-15 07:56:01 +00:00
|
|
|
if len(p.AccessToken) > 0 {
|
|
|
|
m["Authorization"] = fmt.Sprintf("Bearer %s", p.AccessToken)
|
|
|
|
}
|
2019-01-14 10:06:10 +00:00
|
|
|
|
|
|
|
return m
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewTCGApi -
|
|
|
|
func NewTCGApi(apiVersion string) (api *TCGPlayer, err error) {
|
|
|
|
if len(apiVersion) == 0 {
|
2019-01-15 09:58:46 +00:00
|
|
|
apiVersion = "v1.19.0"
|
2019-01-14 10:06:10 +00:00
|
|
|
}
|
|
|
|
api = &TCGPlayer{}
|
|
|
|
api.APIVersion = apiVersion
|
|
|
|
api.URL = "https://api.tcgplayer.com"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetToken -
|
|
|
|
func (p *TCGPlayer) GetToken() (err error) {
|
2019-01-15 07:56:01 +00:00
|
|
|
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
|
|
|
|
|
2019-01-14 10:06:10 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// TCGPlayerCategory -
|
|
|
|
type TCGPlayerCategory struct {
|
2019-01-15 09:58:46 +00:00
|
|
|
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"`
|
2019-01-14 10:06:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ListCategory -
|
|
|
|
func (p *TCGPlayer) ListCategory(limit, offset int) (category []*TCGPlayerCategory, err error) {
|
2019-01-15 07:56:01 +00:00
|
|
|
apiURL, err := p.getAPIURL("/catalog/categories", true)
|
2019-01-14 10:06:10 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
tmpStruct := struct {
|
2019-01-15 07:56:01 +00:00
|
|
|
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 {
|
2019-01-15 09:58:46 +00:00
|
|
|
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"`
|
2019-01-15 07:56:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// ListCategoryGroups -
|
|
|
|
func (p *TCGPlayer) ListCategoryGroups(categoryID, limit, offset int) (groups []*TCGPlayerCategoryGroup, err error) {
|
2019-01-15 09:58:46 +00:00
|
|
|
apiURL, err := p.getAPIURL(fmt.Sprintf("/catalog/categories/%d/groups", categoryID), true)
|
2019-01-15 07:56:01 +00:00
|
|
|
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"`
|
2019-01-14 10:06:10 +00:00
|
|
|
}{}
|
|
|
|
_ = tmpStruct
|
2019-01-15 07:56:01 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-01-15 09:58:46 +00:00
|
|
|
log.Println(string(respByte))
|
|
|
|
|
2019-01-15 07:56:01 +00:00
|
|
|
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
|
2019-01-14 10:06:10 +00:00
|
|
|
}
|
2019-01-15 09:58:46 +00:00
|
|
|
|
|
|
|
// 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) {
|
|
|
|
return
|
|
|
|
}
|