Add marketplace APIs (#43)

* Add marketplace APIs
This commit is contained in:
Thibault Maekelbergh 2021-02-18 15:16:09 +01:00 committed by GitHub
parent d77d28b101
commit 7704281b49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 178 additions and 5 deletions

View File

@ -22,6 +22,9 @@ The lib is under MIT but be sure you are familiar with [Discogs API Terms of Use
* Folder * Folder
* Collection Items by Folder * Collection Items by Folder
* Collection Items by Release * Collection Items by Release
* [Marketplace](#marketplace)
* Price Suggestions
* Release Statistics
Install Install
-------- --------
@ -84,7 +87,6 @@ type SearchRequest struct {
} }
``` ```
Example
```go ```go
request := discogs.SearchRequest{Artist: "reggaenauts", ReleaseTitle: "river rock", Page: 0, PerPage: 1} request := discogs.SearchRequest{Artist: "reggaenauts", ReleaseTitle: "river rock", Page: 0, PerPage: 1}
search, _ := client.Search(request) search, _ := client.Search(request)
@ -99,22 +101,38 @@ Example
Query a users [collection](https://www.discogs.com/developers#page:user-collection). Query a users [collection](https://www.discogs.com/developers#page:user-collection).
##### Collection Folders ##### Collection Folders
Example
```go ```go
collection, err := client.CollectionFolders("my_user") collection, err := client.CollectionFolders("my_user")
``` ```
##### Folder ##### Folder
Example
```go ```go
folder, err := client.Folder("my_user", 0) folder, err := client.Folder("my_user", 0)
``` ```
##### Collection Items by Folder ##### Collection Items by Folder
Example
```go ```go
items, err := client.CollectionItemsByFolder("my_user", 0, &Pagination{Sort: "artist", SortOrder: "desc", PerPage: 2}) items, err := client.CollectionItemsByFolder("my_user", 0, &Pagination{Sort: "artist", SortOrder: "desc", PerPage: 2})
``` ```
##### Collection Items by Release ##### Collection Items by Release
Example
```go ```go
items, err := client.CollectionItemsByRelease("my_user", 12934893) items, err := client.CollectionItemsByRelease("my_user", 12934893)
``` ```
#### Marketplace
Query a user's [marketplace](https://www.discogs.com/developers/#page:marketplace)
##### Price Suggestions
Retrieve price suggestions for the provided Release ID
```go
suggestions, err := client.PriceSuggestions(12345)
```
##### Release Statistics
Retrieve marketplace statistics for the provided Release ID
```go
stats, err := client.ReleaseStatisctics(12345)
```

View File

@ -28,6 +28,7 @@ type Options struct {
type Discogs interface { type Discogs interface {
CollectionService CollectionService
DatabaseService DatabaseService
MarketPlaceService
SearchService SearchService
} }
@ -35,6 +36,7 @@ type discogs struct {
CollectionService CollectionService
DatabaseService DatabaseService
SearchService SearchService
MarketPlaceService
} }
var header *http.Header var header *http.Header
@ -67,6 +69,7 @@ func New(o *Options) (Discogs, error) {
newCollectionService(o.URL + "/users"), newCollectionService(o.URL + "/users"),
newDatabaseService(o.URL, cur), newDatabaseService(o.URL, cur),
newSearchService(o.URL + "/database/search"), newSearchService(o.URL + "/database/search"),
newMarketPlaceService(o.URL+"/marketplace", cur),
}, nil }, nil
} }

72
marketplace.go Normal file
View File

@ -0,0 +1,72 @@
package discogs
import (
"net/url"
"strconv"
)
const (
priceSuggestionsURI = "/price_suggestions/"
releaseStatsURI = "/stats/"
)
type marketPlaceService struct {
url string
currency string
}
type MarketPlaceService interface {
// The best price suggestions according to grading
// Authentication is required.
PriceSuggestions(releaseID int) (*PriceListing, error)
// Short summary of marketplace listings
// Authentication is optional.
ReleaseStatistics(releaseID int) (*Stats, error)
}
func newMarketPlaceService(url string, currency string) MarketPlaceService {
return &marketPlaceService{
url: url,
currency: currency,
}
}
// Listing is a marketplace listing with the user's currency and a price value
type Listing struct {
Currency string `json:"currency"`
Value float64 `json:"value"`
}
// PriceListings are Listings per grading quality
type PriceListing struct {
VeryGood *Listing `json:"Very Good (VG),omitempty"`
GoodPlus *Listing `json:"Good Plus (G+),omitempty"`
NearMint *Listing `json:"Near Mint (NM or M-)"`
Good *Listing `json:"Good (G),omitempty"`
VeryGoodPlus *Listing `json:"Very Good Plus (VG+),omitempty"`
Mint *Listing `json:"Mint (M),omitempty"`
Fair *Listing `json:"Fair (F),omitempty"`
Poor *Listing `json:"Poor (P),omitempty"`
}
// Stats returns the marketplace stats summary for a release containing
type Stats struct {
LowestPrice *Listing `json:"lowest_price"`
ForSale int `json:"num_for_sale"`
Blocked bool `json:"blocked_from_sale"`
}
func (s *marketPlaceService) ReleaseStatistics(releaseID int) (*Stats, error) {
params := url.Values{}
params.Set("curr_abbr", s.currency)
var stats *Stats
err := request(s.url+releaseStatsURI+strconv.Itoa(releaseID), params, &stats)
return stats, err
}
func (s *marketPlaceService) PriceSuggestions(releaseID int) (*PriceListing, error) {
var listings *PriceListing
err := request(s.url+priceSuggestionsURI+strconv.Itoa(releaseID), nil, &listings)
return listings, err
}

76
marketplace_test.go Normal file
View File

@ -0,0 +1,76 @@
package discogs
import (
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strconv"
"testing"
)
const testReleaseID = 9893847
func MarketplaceServer(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
switch r.URL.Path {
case "/marketplace" + priceSuggestionsURI + strconv.Itoa(testReleaseID):
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, priceSuggestionJson); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
case "/marketplace" + releaseStatsURI + strconv.Itoa(testReleaseID):
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, releaseStatsJson); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func TestMarketplacePriceSuggestions(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(MarketplaceServer))
defer ts.Close()
d := initDiscogsClient(t, &Options{URL: ts.URL})
suggestion, err := d.PriceSuggestions(testReleaseID)
if err != nil {
t.Fatalf("failed to get price suggestion: %s", err)
}
json, err := json.Marshal(suggestion)
if err != nil {
t.Fatalf("failed to marshal folder: %s", err)
}
compareJson(t, string(json), priceSuggestionJson)
}
func TestMarketplaceReleaseStatistics(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(MarketplaceServer))
defer ts.Close()
d := initDiscogsClient(t, &Options{URL: ts.URL})
stats, err := d.ReleaseStatistics(testReleaseID)
if err != nil {
t.Fatalf("failed to get price suggestion: %s", err)
}
json, err := json.Marshal(stats)
if err != nil {
t.Fatalf("failed to marshal folder: %s", err)
}
compareJson(t, string(json), releaseStatsJson)
}

View File

@ -15,3 +15,7 @@ const collectionJson = `{"folders": [{"id": 0, "name": "All", "count": 95, "reso
const collectionItemsByFolderJson = `{"pagination": {"page": 1, "pages": 48, "per_page": 2, "items": 95, "urls": {"last": "https://api.discogs.com/users/test_user/collection/folders/0/releases?sort=artist&sort_order=desc&per_page=2&page=48", "next": "https://api.discogs.com/users/test_user/collection/folders/0/releases?sort=artist&sort_order=desc&per_page=2&page=2"}}, "releases": [{"id": 12934893, "instance_id": 431009995, "date_added": "2020-01-19T14:19:11-08:00", "rating": 0, "basic_information": {"id": 12934893, "master_id": 0, "master_url": null, "resource_url": "https://api.discogs.com/releases/12934893", "thumb": "", "cover_image": "", "title": "Zonk", "year": 2018, "formats": [{"name": "Vinyl", "qty": "1", "text": "Purple", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Permanent Record", "catno": "PR014", "entity_type": "1", "entity_type_name": "Label", "id": 833694, "resource_url": "https://api.discogs.com/labels/833694"}], "artists": [{"name": "Zoo Lake", "anv": "", "join": "", "role": "", "tracks": "", "id": 6868154, "resource_url": "https://api.discogs.com/artists/6868154"}], "genres": ["Rock"], "styles": ["Post-Punk", "Shoegaze", "Psychedelic Rock", "Noise", "Garage Rock", "Lo-Fi"]}}, {"id": 4825435, "instance_id": 146424864, "date_added": "2015-11-08T14:42:02-08:00", "rating": 0, "basic_information": {"id": 4825435, "master_id": 17200, "master_url": "https://api.discogs.com/masters/17200", "resource_url": "https://api.discogs.com/releases/4825435", "thumb": "", "cover_image": "", "title": "You And Me Both", "year": 1983, "formats": [{"name": "Vinyl", "qty": "1", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Mute", "catno": "STUMM 12", "entity_type": "1", "entity_type_name": "Label", "id": 26391, "resource_url": "https://api.discogs.com/labels/26391"}, {"name": "CBS", "catno": "DNW 2885", "entity_type": "1", "entity_type_name": "Label", "id": 3072, "resource_url": "https://api.discogs.com/labels/3072"}], "artists": [{"name": "Yazoo", "anv": "", "join": "", "role": "", "tracks": "", "id": 2713, "resource_url": "https://api.discogs.com/artists/2713"}], "genres": ["Electronic"], "styles": ["Synth-pop"]}}]}` const collectionItemsByFolderJson = `{"pagination": {"page": 1, "pages": 48, "per_page": 2, "items": 95, "urls": {"last": "https://api.discogs.com/users/test_user/collection/folders/0/releases?sort=artist&sort_order=desc&per_page=2&page=48", "next": "https://api.discogs.com/users/test_user/collection/folders/0/releases?sort=artist&sort_order=desc&per_page=2&page=2"}}, "releases": [{"id": 12934893, "instance_id": 431009995, "date_added": "2020-01-19T14:19:11-08:00", "rating": 0, "basic_information": {"id": 12934893, "master_id": 0, "master_url": null, "resource_url": "https://api.discogs.com/releases/12934893", "thumb": "", "cover_image": "", "title": "Zonk", "year": 2018, "formats": [{"name": "Vinyl", "qty": "1", "text": "Purple", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Permanent Record", "catno": "PR014", "entity_type": "1", "entity_type_name": "Label", "id": 833694, "resource_url": "https://api.discogs.com/labels/833694"}], "artists": [{"name": "Zoo Lake", "anv": "", "join": "", "role": "", "tracks": "", "id": 6868154, "resource_url": "https://api.discogs.com/artists/6868154"}], "genres": ["Rock"], "styles": ["Post-Punk", "Shoegaze", "Psychedelic Rock", "Noise", "Garage Rock", "Lo-Fi"]}}, {"id": 4825435, "instance_id": 146424864, "date_added": "2015-11-08T14:42:02-08:00", "rating": 0, "basic_information": {"id": 4825435, "master_id": 17200, "master_url": "https://api.discogs.com/masters/17200", "resource_url": "https://api.discogs.com/releases/4825435", "thumb": "", "cover_image": "", "title": "You And Me Both", "year": 1983, "formats": [{"name": "Vinyl", "qty": "1", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Mute", "catno": "STUMM 12", "entity_type": "1", "entity_type_name": "Label", "id": 26391, "resource_url": "https://api.discogs.com/labels/26391"}, {"name": "CBS", "catno": "DNW 2885", "entity_type": "1", "entity_type_name": "Label", "id": 3072, "resource_url": "https://api.discogs.com/labels/3072"}], "artists": [{"name": "Yazoo", "anv": "", "join": "", "role": "", "tracks": "", "id": 2713, "resource_url": "https://api.discogs.com/artists/2713"}], "genres": ["Electronic"], "styles": ["Synth-pop"]}}]}`
const collectionItemsByRelease = `{"pagination": {"page": 1, "pages": 1, "per_page": 50, "items": 1, "urls": {}}, "releases": [{"id": 12934893, "instance_id": 431009995, "date_added": "2020-01-19T14:19:11-08:00", "rating": 0, "basic_information": {"id": 12934893, "master_id": 0, "master_url": null, "resource_url": "https://api.discogs.com/releases/12934893", "thumb": "", "cover_image": "", "title": "Zonk", "year": 2018, "formats": [{"name": "Vinyl", "qty": "1", "text": "Purple", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Permanent Record", "catno": "PR014", "entity_type": "1", "entity_type_name": "Label", "id": 833694, "resource_url": "https://api.discogs.com/labels/833694"}], "artists": [{"name": "Zoo Lake", "anv": "", "join": "", "role": "", "tracks": "", "id": 6868154, "resource_url": "https://api.discogs.com/artists/6868154"}], "genres": ["Rock"], "styles": ["Post-Punk", "Shoegaze", "Psychedelic Rock", "Noise", "Garage Rock", "Lo-Fi"]}}]}` const collectionItemsByRelease = `{"pagination": {"page": 1, "pages": 1, "per_page": 50, "items": 1, "urls": {}}, "releases": [{"id": 12934893, "instance_id": 431009995, "date_added": "2020-01-19T14:19:11-08:00", "rating": 0, "basic_information": {"id": 12934893, "master_id": 0, "master_url": null, "resource_url": "https://api.discogs.com/releases/12934893", "thumb": "", "cover_image": "", "title": "Zonk", "year": 2018, "formats": [{"name": "Vinyl", "qty": "1", "text": "Purple", "descriptions": ["LP", "Album"]}], "labels": [{"name": "Permanent Record", "catno": "PR014", "entity_type": "1", "entity_type_name": "Label", "id": 833694, "resource_url": "https://api.discogs.com/labels/833694"}], "artists": [{"name": "Zoo Lake", "anv": "", "join": "", "role": "", "tracks": "", "id": 6868154, "resource_url": "https://api.discogs.com/artists/6868154"}], "genres": ["Rock"], "styles": ["Post-Punk", "Shoegaze", "Psychedelic Rock", "Noise", "Garage Rock", "Lo-Fi"]}}]}`
const priceSuggestionJson = `{"Mint (M)": {"currency": "EUR", "value": 16.625}, "Near Mint (NM or M-)": {"currency": "EUR", "value": 14.875000000000002}, "Very Good Plus (VG+)": {"currency": "EUR", "value": 11.375000000000002}, "Very Good (VG)": {"currency": "EUR", "value": 7.875000000000001}, "Good Plus (G+)": {"currency": "EUR", "value": 4.375}, "Good (G)": {"currency": "EUR", "value": 2.625}, "Fair (F)": {"currency": "EUR", "value": 1.7500000000000002}, "Poor (P)": {"currency": "EUR", "value": 0.8750000000000001}}`
const releaseStatsJson = `{"num_for_sale": 4, "lowest_price": {"value": 18.07, "currency": "USD"}, "blocked_from_sale": false}`