69 Commits

Author SHA1 Message Date
irlndts
bcf5c89215 Minor improvements 2020-03-24 13:11:04 +03:00
irlndts
417d6d51e6 Removed vendor 2020-03-02 12:03:22 +03:00
irlndts
54c186c94e Travis go version updated 2020-02-28 14:56:52 +03:00
Artem Piskun
b61a3c137a DSCGS-36 Go mod updated, test updated (#38) 2020-02-28 14:50:43 +03:00
Nigel Garside
e287c7d9b3 Release series object (#37) 2020-02-28 14:32:23 +03:00
Artem Piskun
f499b48b2f DSCGS-35 More and fixed data from database, tests (#36) 2019-11-05 20:56:02 +03:00
Artem Piskun
d987189090 DSCGS-33 Added MasterID to Search.Result (#34) 2019-11-05 13:40:34 +03:00
Artem Piskun
77c264c993 DSCGS-31 Search fix (#32) 2019-10-29 13:34:43 +03:00
Abe Massry
84a3ecd4c5 add cover_image to search results (#30) 2019-09-02 18:15:44 +03:00
Abe Massry
f9bfcf8fba Update search example for current code behavior (#29) 2019-08-28 12:53:11 +03:00
irlndts
664896b3dd Golangci-lint fix 2019-06-18 15:08:55 +03:00
Artem Piskun
3c48a3e6d4 Merge pull request #28 from irlndts/RemoveVendor 2019-06-06 15:24:00 +03:00
irlndts
271bbe8b83 Travis version updated 2019-06-06 15:20:17 +03:00
irlndts
35dfbe02d1 Vendor removed, some cleanups 2019-06-06 15:18:10 +03:00
irlndts
618b882634 Use go mod 2018-12-11 16:47:31 +03:00
Artem Piskun
a4b6e4193a Merge pull request #27 from pluyckx/master
Add 'Artists' field to 'Track'
2018-04-30 21:27:27 +03:00
Philip Luyckx
e1e0446c29 Add 'Artists' field to 'Track'
Some tracks contain different artists than specified in the release. In
this case there is a field 'artists' in the JSON response. This field is
added to the 'Track' struct. When the field 'artists' is available in the
JSON response, the length of 'Artists' is not 0. Otherwise the 'Artists'
from the release should be used.

Signed-off-by: Philip Luyckx <philip.luyckx@gmail.com>
2018-04-30 10:37:04 +02:00
irlndts
dd501a3f65 fix 2018-04-10 15:39:54 +03:00
irlndts
110a37661a goreportcard 2018-03-28 20:18:24 +03:00
irlndts
3775bc39c7 travis pic 2018-03-28 20:13:31 +03:00
irlndts
e9ad282056 added travis-ci.yml 2018-03-28 20:11:47 +03:00
Artem Piskun
31a2e3b959 Merge pull request #26 from irlndts/APIErrors 2018-03-24 16:19:05 +03:00
irlndts
8e69f9334b Added several tests 2018-03-24 16:17:35 +03:00
irlndts
788518e3e2 Added several tests 2018-03-24 16:14:54 +03:00
irlndts
0a3a17b69d Lint errors fixed 2018-03-24 13:46:20 +03:00
Artem Piskun
ebfd052f67 Merge pull request #24 from irlndts/DSCGS-23
Move services to database
2018-03-21 21:18:54 +03:00
irlndts
c526ccd692 Move services to database 2018-03-21 21:17:40 +03:00
Artem Piskun
91d056b186 Merge pull request #22 from irlndts/DSCGS-20
Fix govet errors
2018-03-21 20:58:14 +03:00
irlndts
441de35813 Fix govet errors 2018-03-21 20:57:39 +03:00
Artem Piskun
872ff94673 Merge pull request #21 from irlndts/DSCGS-19
DSCGS-19 fix lint
2018-03-20 13:57:39 +03:00
irlndts
afd778f11c Cleanup 2018-03-20 13:56:17 +03:00
irlndts
dd29f70850 DSCGS-19 Fix golint errors 2018-03-17 23:12:25 +03:00
irlndts
d5ddddc09d Doc fixed 2018-03-17 22:41:43 +03:00
Artem Piskun
ede8271b88 Merge pull request #18 from irlndts/DSCGS-17 2018-03-17 22:01:09 +03:00
irlndts
b2674eb55e DSCGS-17 Use github.com/google/go-querystring/ 2018-03-17 21:58:56 +03:00
Artem Piskun
2bc2347afc Merge pull request #16 from irlndts/DSCGS-11 2018-03-17 21:00:22 +03:00
irlndts
62ba69198d DSCGS-11 Cleanup 2018-03-17 20:59:51 +03:00
irlndts
33699d6ad5 DSCGS-11 Cleanup 2018-03-17 20:57:41 +03:00
irlndts
4b824487ea DSCGS-11 Improve SearchService 2018-03-13 00:12:37 +03:00
irlndts
1091d9be02 DSCGS-11 Improve SearchService 2018-03-13 00:12:06 +03:00
Artem Piskun
b8ec73e2a0 Merge pull request #15 from irlndts/DSCGS-10 2018-03-12 23:33:10 +03:00
irlndts
7a214b4b15 DSCGS-10 Rewrite LabelService 2018-03-12 23:31:47 +03:00
Artem Piskun
fcb075f0f4 Merge pull request #13 from irlndts/DSCGS-9 2018-03-12 21:14:16 +03:00
irlndts
615c7561ad DSCGS-9 Rewrite MasterService 2018-03-12 21:13:09 +03:00
Artem Piskun
93ddab1b21 Merge pull request #12 from irlndts/DSCGS-7 2018-03-12 20:54:54 +03:00
irlndts
ad267389f6 DSCGS-7 Rewrite ArtistService like release service 2018-03-12 20:51:06 +03:00
Artem Piskun
8d359bb193 Merge pull request #6 from irlndts/Rewrite
Improvement and Rating
2018-03-12 20:00:30 +03:00
irlndts
4a80c3cc39 Rating 2018-03-12 19:51:37 +03:00
irlndts
69ef2a5d9a Release 2018-03-12 19:31:50 +03:00
irlndts
d1095bc769 Release improvement 2018-03-12 19:30:58 +03:00
irlndts
7d6af61b78 TEST 2018-02-20 20:00:24 +03:00
irlndts
6af125badd Improvements 2018-02-20 19:26:00 +03:00
irlndts
916e1f0bd6 Improvement token 2018-02-20 18:16:34 +03:00
irlndts
d0f617733a Some Improvements 2018-02-20 18:13:04 +03:00
irlndts
055007c459 improvement 2018-01-22 21:15:06 +03:00
irlndts
72a2e61894 Doc fixed 2018-01-22 21:03:06 +03:00
irlndts
87747a846f Doc fixed 2018-01-22 21:01:29 +03:00
irlndts
795cdb9f79 doc updated 2018-01-05 22:52:20 +03:00
irlndts
6a5e9d0a6b fix 2017-05-10 18:02:10 +03:00
irlndts
7536e26d28 merge 2017-05-09 18:54:15 +03:00
irlndts
5f77b45281 merge 2017-05-09 18:53:47 +03:00
irlndts
0f41f45197 minor comment fix 2017-05-09 18:52:58 +03:00
irlndts
efff71f46e minor comments 2017-05-09 17:07:11 +03:00
Artem Piskun
86244f6665 Merge pull request #5 from irlndts/DSCG-4
DSCGS-4
2017-04-26 16:02:07 +03:00
irlndts
78b3d0b0ad DSCGS-4 fix 2017-04-26 16:01:06 +03:00
irlndts
44db789a6b DSCGS-4 Logic improved 2017-04-26 15:57:03 +03:00
irlndts
dd4fa14f61 DSCGS-4 enough for today 2017-04-25 19:39:32 +03:00
irlndts
26dbacfe44 Minor fixings 2017-04-17 00:09:01 +03:00
irlndts
bce16b5ed1 Some comments edited 2017-04-16 23:49:50 +03:00
21 changed files with 819 additions and 575 deletions

3
.travis.yml Normal file
View File

@@ -0,0 +1,3 @@
language: go
go:
- "1.14"

View File

@@ -1,19 +1,17 @@
# REST API 2.0 Discogs.com client # REST API 2.0 Discogs.com client
[![Build Status](https://travis-ci.org/irlndts/go-discogs.svg?branch=master)](https://travis-ci.org/irlndts/go-discogs)[![Go Report Card](https://goreportcard.com/badge/github.com/irlndts/go-discogs)](https://goreportcard.com/report/github.com/irlndts/go-discogs)
go-discogs is a Go client library for the [Discogs API](https://www.discogs.com/developers/). Check the usage section to see how to access the Discogs API. go-discogs is a Go client library for the [Discogs API](https://www.discogs.com/developers/). Check the usage section to see how to access the Discogs API.
### Changelog The lib is under MIT but be sure you are familiar with [Discogs API Terms of Use](https://support.discogs.com/hc/en-us/articles/360009334593-API-Terms-of-Use).
```
14.02.2017
- search is implemented
- minor improvements
```
### Feauteres ### Feauteres
* Database * Database
* [Releases](#releases) * [Releases](#releases)
* Release Rating
* Master Releases * Master Releases
* Release Versions * Master Versions
* Artists * Artists
* Artist Releases * Artist Releases
* Label * Label
@@ -22,7 +20,7 @@ go-discogs is a Go client library for the [Discogs API](https://www.discogs.com/
Install Install
-------- --------
go get github.com/irlndts/go-discogs go get -u github.com/irlndts/go-discogs
Usage Usage
--------- ---------
@@ -31,49 +29,36 @@ First of all import library and init client variable. According to discogs api d
```go ```go
import "github.com/irlndts/go-discogs" import "github.com/irlndts/go-discogs"
``` ```
Some requests require authentification (as any user). According to [Discogs](https://www.discogs.com/developers/#page:authentication,header:authentication-discogs-auth-flow), to send requests with Discogs Auth, you have two options: sending your credentials in the query string with key and secret parameters or a [token parameter](https://www.discogs.com/settings/developers).
This is token way example:
```go ```go
client := discogs.NewClient("TestDiscogsClient/0.0.1 +example.com", "") client, err := discogs.New(&discogs.Options{
``` UserAgent: "Some Name",
Some requests require authentication (as any user). According to [Discogs](https://www.discogs.com/developers/#page:authentication,header:authentication-discogs-auth-flow), to send requests with Discogs Auth, you have two options: sending your credentials in the query string with key and secret parameters or a token parameter. Key-secret doesn't implemented yet, but token is yes. Currency: "EUR", // optional, "USD" (default), "GBP", "EUR", "CAD", "AUD", "JPY", "CHF", "MXN", "BRL", "NZD", "SEK", "ZAR" are allowed
```go Token: "Some Token", // optional
client := discogs.NewClient("TestDiscogsClient/0.0.1 +example.com", "sometoken") URL: "https://api.discogs.com", // optional
})
``` ```
#### Releases #### Releases
```go ```go
params := &discogs.ReleaseParams{Release_id: "8138518"} release, _ := client.Database.Release(9893847)
release, _, err := client.Release.Release(params) fmt.Println(release.Artists[0].Name, " - ", release.Title)
// St. Petersburg Ska-Jazz Review - Elephant Riddim
fmt.Println(fmt.Println(release.Artists[0].Name, " - ", release.Title)) // St. Petersburg Ska-Jazz Review - Elephant Riddim
```
#### Artists
```go
params := &discogs.LabelParams{Label_id: "890477", Page: 2, Per_page: 3}
label, _, err := client.Label.Releases(params)
for _, release := range label.Releases {
fmt.Println(release.Title)
}
/*
Someday / I Hate Everything About You
Spy Potion
Surf Attack From Russia
*/
``` ```
#### Search #### Search
Issue a search query to discogs database. This endpoint accepts pagination parameters Issue a search query to discogs database. This endpoint accepts pagination parameters.
Authentication (as any user) is required. Authentication (as any user) is required.
Use `SearchRequest` struc to create a request Use `SearchRequest` struct to create a request.
```go ```go
type SearchRequest struct { type SearchRequest struct {
Q string // search query (optional) Q string // search query (optional)
Type string // one of release, master, artist, label (optional) Type string // one of release, master, artist, label (optional)
Title string // search by combined “Artist Name - Release Title” title field (optional) Title string // search by combined “Artist Name - Release Title” title field (optional)
Release_title string // search release titles (optional) ReleaseTitle string // search release titles (optional)
Credit string // search release credits (optional) Credit string // search release credits (optional)
Artist string // search artist names (optional) Artist string // search artist names (optional)
Anv string // search artist ANV (optional) Anv string // search artist ANV (optional)
@@ -90,19 +75,16 @@ type SearchRequest struct {
Contributer string // search contributor usernames (optional) Contributer string // search contributor usernames (optional)
Page int // optional Page int // optional
Per_page int // optional PerPage int // optional
} }
``` ```
Example Example
```go ```go
request:= &discogs.SearchRequest{Artist: "reggaenauts", Release_title: "river rock", Page: 0, Per_page: 1} request := discogs.SearchRequest{Artist: "reggaenauts", ReleaseTitle: "river rock", Page: 0, PerPage: 1}
search, _, err := client.Search(request) search, _ := client.Search.Search(request)
for _, r := range search.Results { for _, r := range search.Results {
fmt.Println(r.Title) fmt.Println(r.Title)
} }
``` ```
etc.
More examples - soon

View File

@@ -1,58 +0,0 @@
package discogs
import (
"github.com/irlndts/go-apirequest"
"net/http"
)
type ArtistService struct {
api *apirequest.API
}
type ArtistParams struct {
Artist_id string
Sort string // year, title, format
Sort_order string // asc, desc
Page int
Per_page int
}
type Artist struct {
Namevariations []string `json:"namevariations"`
Profile string `json:"profile"`
Releases_url string `json:"releases_url"`
Resource_url string `json:"resource_url"`
Uri string `json:"uri"`
Urls []string `json:"urls"`
Data_quality string `json:"data_quality"`
Id int `json:"id"`
Images []Image `json:"images"`
Members []Member `json:"members"`
}
type ArtistReleases struct {
Paginastion Page `json:"pagination"`
Releases []ReleaseSource `json:"releases"`
}
func newArtistService(api *apirequest.API) *ArtistService {
return &ArtistService{
api: api.Path("artists/"),
}
}
func (self *ArtistService) Artist(params *ArtistParams) (*Artist, *http.Response, error) {
artist := new(Artist)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Artist_id).Receive(artist, apiError)
return artist, resp, relevantError(err, *apiError)
}
func (self *ArtistService) Releases(params *ArtistParams) (*ArtistReleases, *http.Response, error) {
releases := new(ArtistReleases)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Artist_id+"/releases").QueryStruct(params).Receive(releases, apiError)
return releases, resp, relevantError(err, *apiError)
}

View File

@@ -1,26 +0,0 @@
package discogs
import (
"fmt"
"testing"
)
func TestArtistService_Artist(t *testing.T) {
expectedId := 1000
d := NewClient(testUserAgent, testToken)
artist, _, err := d.Artist.Artist(&ArtistParams{Artist_id: "1000"})
check(t, err)
assert(t, artist.Id == expectedId, fmt.Sprintf("Release.Title looked for %s, and received %s ", expectedId, artist.Id))
}
func TestArtistService_Releases(t *testing.T) {
expectedArtist := "Dave Clarke"
d := NewClient(testUserAgent, testToken)
releases, _, err := d.Artist.Releases(&ArtistParams{Artist_id: "1000", Sort: "year", Sort_order: "desc"})
check(t, err)
assert(t, releases.Releases[0].Artist == expectedArtist, fmt.Sprintf("Releses.Artist looked for %s, and received %s ", expectedArtist, releases.Releases[0].Artist))
}

208
database.go Normal file
View File

@@ -0,0 +1,208 @@
package discogs
import (
"net/url"
"strconv"
)
const (
releasesURI = "/releases/"
artistsURI = "/artists/"
labelsURI = "/labels/"
mastersURI = "/masters/"
)
// DatabaseService ...
type DatabaseService struct {
url string
currency string
}
func newDatabaseService(url string, currency string) *DatabaseService {
return &DatabaseService{
url: url,
currency: currency,
}
}
// Release serves relesase response from discogs
type Release struct {
Title string `json:"title"`
ID int `json:"id"`
Artists []ArtistSource `json:"artists"`
ArtistsSort string `json:"artists_sort"`
DataQuality string `json:"data_quality"`
Thumb string `json:"thumb"`
Community Community `json:"community"`
Companies []Company `json:"companies"`
Country string `json:"country"`
DateAdded string `json:"date_added"`
DateChanged string `json:"date_changed"`
EstimatedWeight int `json:"estimated_weight"`
ExtraArtists []ArtistSource `json:"extraartists"`
FormatQuantity int `json:"format_quantity"`
Formats []Format `json:"formats"`
Genres []string `json:"genres"`
Identifiers []Identifier `json:"identifiers"`
Images []Image `json:"images"`
Labels []LabelSource `json:"labels"`
LowestPrice float64 `json:"lowest_price"`
MasterID int `json:"master_id"`
MasterURL string `json:"master_url"`
Notes string `json:"notes,omitempty"`
NumForSale int `json:"num_for_sale,omitempty"`
Released string `json:"released"`
ReleasedFormatted string `json:"released_formatted"`
ResourceURL string `json:"resource_url"`
Series []Series `json:"series"`
Status string `json:"status"`
Styles []string `json:"styles"`
Tracklist []Track `json:"tracklist"`
URI string `json:"uri"`
Videos []Video `json:"videos"`
Year int `json:"year"`
}
// Release returns release by release's ID
func (s *DatabaseService) Release(releaseID int) (*Release, error) {
params := url.Values{}
params.Set("curr_abbr", s.currency)
var release *Release
err := request(s.url+releasesURI+strconv.Itoa(releaseID), params, &release)
return release, err
}
// ReleaseRating serves response for community release rating request
type ReleaseRating struct {
ID int `json:"release_id"`
Rating Rating `json:"rating"`
}
// ReleaseRating retruns community release rating
func (s *DatabaseService) ReleaseRating(releaseID int) (*ReleaseRating, error) {
var rating *ReleaseRating
err := request(s.url+releasesURI+strconv.Itoa(releaseID)+"/rating", nil, &rating)
return rating, err
}
// Artist resource represents a person in the Discogs database
// who contributed to a Release in some capacity.
// More information https://www.discogs.com/developers#page:database,header:database-artist
type Artist struct {
ID int `json:"id"`
Name string `json:"name"`
Realname string `json:"realname"`
Members []Member `json:"members,omitempty"`
Aliases []Alias `json:"aliases,omitempty"`
Namevariations []string `json:"namevariations"`
Images []Image `json:"images"`
Profile string `json:"profile"`
ReleasesURL string `json:"releases_url"`
ResourceURL string `json:"resource_url"`
URI string `json:"uri"`
URLs []string `json:"urls"`
DataQuality string `json:"data_quality"`
}
// Artist represents a person in the discogs database
func (s *DatabaseService) Artist(artistID int) (*Artist, error) {
var artist *Artist
err := request(s.url+artistsURI+strconv.Itoa(artistID), nil, &artist)
return artist, err
}
// ArtistReleases ...
type ArtistReleases struct {
Pagination Page `json:"pagination"`
Releases []ReleaseSource `json:"releases"`
}
// ArtistReleases returns a list of releases and masters associated with the artist.
func (s *DatabaseService) ArtistReleases(artistID int, pagination *Pagination) (*ArtistReleases, error) {
var releases *ArtistReleases
err := request(s.url+artistsURI+strconv.Itoa(artistID)+"/releases", pagination.params(), &releases)
return releases, err
}
// Label resource represents a label, company, recording studio, location,
// or other entity involved with artists and releases.
type Label struct {
Profile string `json:"profile"`
ReleasesURL string `json:"releases_url"`
Name string `json:"name"`
ContactInfo string `json:"contact_info"`
URI string `json:"uri"`
Sublabels []Sublable `json:"sublabels"`
URLs []string `json:"urls"`
Images []Image `json:"images"`
ResourceURL string `json:"resource_url"`
ID int `json:"id"`
DataQuality string `json:"data_quality"`
}
// Label returns a label.
func (s *DatabaseService) Label(labelID int) (*Label, error) {
var label *Label
err := request(s.url+labelsURI+strconv.Itoa(labelID), nil, &label)
return label, err
}
// LabelReleases is a list of Releases associated with the label.
type LabelReleases struct {
Pagination Page `json:"pagination"`
Releases []ReleaseSource `json:"releases"`
}
// LabelReleases returns a list of Releases associated with the label.
func (s *DatabaseService) LabelReleases(labelID int, pagination *Pagination) (*LabelReleases, error) {
var releases *LabelReleases
err := request(s.url+labelsURI+strconv.Itoa(labelID)+"/releases", pagination.params(), &releases)
return releases, err
}
// Master resource represents a set of similar releases.
// Masters (also known as `master releases`) have a `main release` which is often the chronologically earliest.
// More information https://www.discogs.com/developers#page:database,header:database-master-release
type Master struct {
ID int `json:"id"`
Styles []string `json:"styles"`
Genres []string `json:"genres"`
Title string `json:"title"`
Year int `json:"year"`
Tracklist []Track `json:"tracklist"`
Notes string `json:"notes"`
Artists []ArtistSource `json:"artists"`
Images []Image `json:"images"`
Videos []Video `json:"videos"`
NumForSale int `json:"num_for_sale"`
LowestPrice float64 `json:"lowest_price"`
URI string `json:"uri"`
MainRelease int `json:"main_release"`
MainReleaseURL string `json:"main_release_url"`
MostRecentRelease int `json:"most_recent_release"`
MostRecentReleaseURL string `json:"most_recent_release_url"`
VersionsURL string `json:"versions_url"`
ResourceURL string `json:"resource_url"`
DataQuality string `json:"data_quality"`
}
// Master returns a master release
func (s *DatabaseService) Master(masterID int) (*Master, error) {
var master *Master
err := request(s.url+mastersURI+strconv.Itoa(masterID), nil, &master)
return master, err
}
// MasterVersions retrieves a list of all releases that are versions of this master.
type MasterVersions struct {
Pagination Page `json:"pagination"`
Versions []Version `json:"versions"`
}
// MasterVersions retrieves a list of all Releases that are versions of this master
func (s *DatabaseService) MasterVersions(masterID int, pagination *Pagination) (*MasterVersions, error) {
var versions *MasterVersions
err := request(s.url+mastersURI+strconv.Itoa(masterID)+"/versions", pagination.params(), &versions)
return versions, err
}

108
database_test.go Normal file
View File

@@ -0,0 +1,108 @@
package discogs
import (
"encoding/json"
"io"
"log"
"net/http"
"net/http/httptest"
"testing"
"github.com/google/go-cmp/cmp"
)
func DatabaseServer(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
switch r.URL.Path {
case "/releases/8138518":
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, releaseJson); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
case "/masters/718441":
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, masterJson); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
case "/artists/38661":
w.WriteHeader(http.StatusOK)
if _, err := io.WriteString(w, artistJson); err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}
func compareJson(t *testing.T, got, want string) {
var g, w interface{}
if err := json.Unmarshal([]byte(got), &g); err != nil {
log.Fatalf("failed to unmarshal json: %s", err)
}
if err := json.Unmarshal([]byte(want), &w); err != nil {
log.Fatalf("failed to unmarshal json: %s", err)
}
if diff := cmp.Diff(g, w); diff != "" {
t.Errorf("(-want +got)\n%s", diff)
}
}
func TestDatabaseServiceRelease(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(DatabaseServer))
defer ts.Close()
d := initDiscogsClient(t, &Options{URL: ts.URL})
release, err := d.Database.Release(8138518)
if err != nil {
t.Fatalf("failed to get release: %s", err)
}
json, err := json.Marshal(release)
if err != nil {
t.Fatalf("failed to marshal release: %s", err)
}
compareJson(t, string(json), releaseJson)
}
func TestDatabaseServiceMaster(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(DatabaseServer))
defer ts.Close()
d := initDiscogsClient(t, &Options{URL: ts.URL})
master, err := d.Database.Master(718441)
if err != nil {
t.Fatalf("failed to get master: %s", err)
}
json, err := json.Marshal(master)
if err != nil {
t.Fatalf("failed to marshal release: %s", err)
}
compareJson(t, string(json), masterJson)
}
func TestDatabaseServiceArtist(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(DatabaseServer))
defer ts.Close()
d := initDiscogsClient(t, &Options{URL: ts.URL})
artist, err := d.Database.Artist(38661)
if err != nil {
t.Fatalf("failed to get master: %s", err)
}
json, err := json.Marshal(artist)
if err != nil {
t.Fatalf("failed to marshal artist: %s", err)
}
compareJson(t, string(json), artistJson)
}

View File

@@ -1,48 +1,108 @@
package discogs package discogs
import ( import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http" "net/http"
"net/url"
"github.com/irlndts/go-apirequest"
) )
const ( const (
discogsAPI = "https://api.discogs.com/" discogsAPI = "https://api.discogs.com"
) )
// Client is a Discogs client for making Discogs API requests. // Options is a set of options to use discogs API client
type Client struct { type Options struct {
api *apirequest.API // Discogs API endpoint (optional).
Release *ReleaseService URL string
Master *MasterService // Currency to use (optional, default is USD).
Artist *ArtistService Currency string
Label *LabelService // UserAgent to to call discogs api with.
UserAgent string
// Token provided by discogs (optional).
Token string
}
// Discogs is a Discogs' client for making Discogs API requests.
type Discogs struct {
Database *DatabaseService
Search *SearchService Search *SearchService
} }
// NewClient returns a new Client. var header *http.Header
func NewClient(useragent, token string) *Client {
base := apirequest.New().Client(&http.Client{}).Base(discogsAPI).Add("User-Agent", useragent).Add("Authorization", "Discogs token="+token)
return &Client{ // New returns a new discogs API client.
api: base, func New(o *Options) (*Discogs, error) {
Artist: newArtistService(base.New()), header = &http.Header{}
Label: newLabelService(base.New()),
Master: newMasterService(base.New()), if o == nil || o.UserAgent == "" {
Release: newReleaseService(base.New()), return nil, ErrUserAgentInvalid
Search: newSearchService(base.New()), }
header.Add("User-Agent", o.UserAgent)
cur, err := currency(o.Currency)
if err != nil {
return nil, err
}
// set token, it's required for some queries like search
if o.Token != "" {
header.Add("Authorization", "Discogs token="+o.Token)
}
if o.URL == "" {
o.URL = discogsAPI
}
return &Discogs{
Database: newDatabaseService(o.URL, cur),
Search: newSearchService(o.URL + "/database/search"),
}, nil
}
// currency validates currency for marketplace data.
// Defaults to the authenticated users currency. Must be one of the following:
// USD GBP EUR CAD AUD JPY CHF MXN BRL NZD SEK ZAR
func currency(c string) (string, error) {
switch c {
case "USD", "GBP", "EUR", "CAD", "AUD", "JPY", "CHF", "MXN", "BRL", "NZD", "SEK", "ZAR":
return c, nil
case "":
return "USD", nil
default:
return "", ErrCurrencyNotSupported
} }
} }
// UserAgent sets specified user agent func request(path string, params url.Values, resp interface{}) error {
// Discogs required it r, err := http.NewRequest("GET", path+"?"+params.Encode(), nil)
func (c *Client) UserAgent(useragent string) *Client { if err != nil {
c.api.Set("User-Agent", useragent) return err
return c }
r.Header = *header
client := &http.Client{}
response, err := client.Do(r)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
switch response.StatusCode {
case http.StatusUnauthorized:
return ErrUnauthorized
default:
return fmt.Errorf("unknown error: %s", response.Status)
}
} }
// Token sets tokens, it's required for some queries like search body, err := ioutil.ReadAll(response.Body)
func (c *Client) Token(token string) *Client { if err != nil {
c.api.Set("Authorization", "Discogs token="+token) return err
return c }
return json.Unmarshal(body, &resp)
} }

View File

@@ -9,14 +9,85 @@ const (
testToken = "" testToken = ""
) )
func check(t *testing.T, e error) { func initDiscogsClient(t *testing.T, options *Options) *Discogs {
if e != nil { if options == nil {
t.Error(e) options = &Options{
UserAgent: testUserAgent,
Currency: "USD",
Token: testToken,
} }
} }
func assert(t *testing.T, condition bool, assertion string) { if options.UserAgent == "" {
if !condition { options.UserAgent = testUserAgent
t.Errorf("Assertion failed: %v", assertion) }
client, err := New(options)
if err != nil {
t.Fatalf("failed to create client: %s", err)
}
return client
}
func TestNew(t *testing.T) {
tests := map[string]struct {
options *Options
err error
}{
"normal": {&Options{
UserAgent: testUserAgent,
Currency: "USD",
Token: "some token",
}, nil},
"incorrect user-agent": {&Options{
UserAgent: "",
Currency: "USD",
}, ErrUserAgentInvalid},
"incorrect currency": {&Options{
UserAgent: testUserAgent,
Currency: "RUR",
}, ErrCurrencyNotSupported},
}
for name := range tests {
tt := tests[name]
t.Run(name, func(t *testing.T) {
if _, err := New(tt.options); err != tt.err {
t.Errorf("err got=%s; want=%s", err, tt.err)
}
})
}
}
func TestCurrency(t *testing.T) {
tests := []struct {
currency string
want string
err error
}{
{currency: "", want: "USD", err: nil},
{currency: "USD", want: "USD", err: nil},
{currency: "GBP", want: "GBP", err: nil},
{currency: "EUR", want: "EUR", err: nil},
{currency: "CAD", want: "CAD", err: nil},
{currency: "AUD", want: "AUD", err: nil},
{currency: "JPY", want: "JPY", err: nil},
{currency: "CHF", want: "CHF", err: nil},
{currency: "MXN", want: "MXN", err: nil},
{currency: "BRL", want: "BRL", err: nil},
{currency: "NZD", want: "NZD", err: nil},
{currency: "SEK", want: "SEK", err: nil},
{currency: "ZAR", want: "ZAR", err: nil},
{currency: "RUR", want: "", err: ErrCurrencyNotSupported},
}
for i, tt := range tests {
cur, err := currency(tt.currency)
if err != tt.err {
t.Errorf("#%d err got=%s; want=%s", i, err, tt.err)
}
if cur != tt.want {
t.Errorf("#%d currency got=%s; want=%s", i, cur, tt.want)
}
} }
} }

View File

@@ -2,38 +2,21 @@ package discogs
import ( import (
"fmt" "fmt"
"strings"
) )
// APIError represents a Discogs API Error response // Error represents a Discogs API error
type APIError struct { type Error struct {
Message string `json:"message"` Message string
} }
func (e APIError) Error() string { func (e *Error) Error() string {
if e.Message != "" { return fmt.Sprintf("discogs error: %s", strings.ToLower(e.Message))
return fmt.Sprintf("discogs: %v", e.Message)
}
return ""
} }
// Empty returns true if empty. Otherwise, at least 1 error message/code is // APIErrors
// present and false is returned. var (
func (e APIError) Empty() bool { ErrUnauthorized = &Error{"authentication required"}
if e.Message == "" { ErrCurrencyNotSupported = &Error{"currency does not supported"}
return true ErrUserAgentInvalid = &Error{"invalid user-agent"}
} )
return false
}
// relevantError returns any non-nil http-related error (creating the request,
// getting the response, decoding) if any. If the decoded apiError is non-zero
// the apiError is returned. Otherwise, no errors occurred, returns nil.
func relevantError(httpError error, apiError APIError) error {
if httpError != nil {
return httpError
}
if apiError.Empty() {
return nil
}
return apiError
}

View File

@@ -7,17 +7,20 @@ import (
) )
func main() { func main() {
d := discogs.NewClient("TestDiscogsClient/0.0.1 +http://irlndts.moscow", "") d, err := discogs.New(&discogs.Options{
UserAgent: "TestDiscogsClient/0.0.1 +http://example.com",
request := &discogs.SearchRequest{Q: "The Reggaenauts - River Rock / Thursday Kick-off", Page: 0, Per_page: 1} Currency: "USD",
search, _, err := d.Search.Search(request) Token: "",
})
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
return return
} }
for _, r := range search.Results { master, err := d.Database.Master(718441)
fmt.Println(r.Id, r.Title) if err != nil {
fmt.Println(err)
return
} }
fmt.Printf("%+v\n", master)
} }

5
go.mod Normal file
View File

@@ -0,0 +1,5 @@
module github.com/irlndts/go-discogs
go 1.14
require github.com/google/go-cmp v0.4.0

4
go.sum Normal file
View File

@@ -0,0 +1,4 @@
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -1,58 +0,0 @@
package discogs
import (
"net/http"
"github.com/irlndts/go-apirequest"
)
type LabelService struct {
api *apirequest.API
}
type LabelParams struct {
Label_id string
Page int
Per_Page int
}
type Label struct {
Profile string `json:"profile"`
Releases_url string `json:"releases_url"`
Name string `json:"name"`
Contact_info string `json:"contact_info"`
Uri string `json:"uri"`
Sublabels []Sublable `json:"sublabels"`
Urls []string `json:"urls"`
Images []Image `json:"images"`
Resource_url string `json:"resource_url"`
Id int `json:"id"`
Data_quality string `json:"data_quality"`
}
type LabelReleases struct {
Pagination Page `json:"pagination"`
Releases []ReleaseSource `json:"releases"`
}
func newLabelService(api *apirequest.API) *LabelService {
return &LabelService{
api: api.Path("labels/"),
}
}
func (self *LabelService) Label(params *LabelParams) (*Label, *http.Response, error) {
label := new(Label)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Label_id).Receive(label, apiError)
return label, resp, relevantError(err, *apiError)
}
func (self *LabelService) Releases(params *LabelParams) (*LabelReleases, *http.Response, error) {
releases := new(LabelReleases)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Label_id+"/releases").QueryStruct(params).Receive(releases, apiError)
return releases, resp, relevantError(err, *apiError)
}

View File

@@ -1,26 +0,0 @@
package discogs
import (
"fmt"
"testing"
)
func TestLabelService_Label(t *testing.T) {
expectedId := 1000
d := NewClient(testUserAgent, testToken)
label, _, err := d.Label.Label(&LabelParams{Label_id: "1000"})
check(t, err)
assert(t, label.Id == expectedId, fmt.Sprintf("Release.Title looked for %s, and received %s ", expectedId, label.Id))
}
func TestLabelService_Releases(t *testing.T) {
expectedId := "Cha Cha Twist"
d := NewClient(testUserAgent, testToken)
label, _, err := d.Label.Releases(&LabelParams{Label_id: "1000"})
check(t, err)
assert(t, label.Releases[0].Title == expectedId, fmt.Sprintf("Release.Title looked for %s, and received %s ", expectedId, label.Releases[0].Title))
}

View File

@@ -1,63 +0,0 @@
package discogs
import (
"github.com/irlndts/go-apirequest"
"net/http"
)
type MasterService struct {
api *apirequest.API
}
type MasterParams struct {
Master_id string
}
type MasterVersionParams struct {
Master_id string
Page int
Per_page int
}
type Master struct {
Styles []string `json:"styles"`
Genres []string `json:"genres"`
Videos []Video `json:"videos"`
Title string `json:"title"`
Main_release int `json:"main_release"`
Main_release_url string `json:"main_release_url"`
Uri string `json:"uri"`
Artists []Artist `json:"artists"`
Version_url string `json:"version_url"`
Year int `json:"year"`
Images []Image `json:"images"`
Resource_url string `json:"resource_url"`
Tracklist []Track `json:"tracklist"`
Id int `json:"id"`
Data_quality string `json:"data_quality"`
}
type MasterVersions struct {
Pagination Page `json:"pagination"`
Versions []Version `json:"versions"`
}
func newMasterService(api *apirequest.API) *MasterService {
return &MasterService{
api: api.Path("masters/"),
}
}
func (self *MasterService) Master(params *MasterParams) (*Master, *http.Response, error) {
master := new(Master)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Master_id).Receive(master, apiError)
return master, resp, relevantError(err, *apiError)
}
func (self *MasterService) Versions(params *MasterVersionParams) (*MasterVersions, *http.Response, error) {
versions := new(MasterVersions)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Master_id+"/versions").QueryStruct(params).Receive(versions, apiError)
return versions, resp, relevantError(err, *apiError)
}

View File

@@ -1,26 +0,0 @@
package discogs
import (
"fmt"
"testing"
)
func TestMasterService_Master(t *testing.T) {
expectedTitle := "Elephant Riddim"
d := NewClient(testUserAgent, testToken)
master, _, err := d.Master.Master(&MasterParams{Master_id: "960657"})
check(t, err)
assert(t, master.Title == expectedTitle, fmt.Sprintf("master.Title looked for %s, and received %s ", expectedTitle, master.Title))
}
func TestMasterService_Versions(t *testing.T) {
expectedTitle := "Stardiver"
d := NewClient(testUserAgent, testToken)
versions, _, err := d.Master.Versions(&MasterVersionParams{Master_id: "1000", Page: 1, Per_page: 1})
check(t, err)
assert(t, versions.Versions[0].Title == expectedTitle, fmt.Sprintf("master.Title looked for %s, and received %s ", expectedTitle, versions.Versions[0].Title))
}

126
models.go
View File

@@ -1,71 +1,99 @@
package discogs package discogs
import (
"net/url"
"strconv"
)
// Video ...
type Video struct { type Video struct {
Description string `json:"description"` Description string `json:"description"`
Duration int `json:"duration"` Duration int `json:"duration"`
Embed bool `json:"embed"` Embed bool `json:"embed"`
Title string `json:"title"` Title string `json:"title"`
Uri string `json:"uri"` URI string `json:"uri"`
} }
// Series ...
type Series struct {
Catno string `json:"catno"`
EntityType string `json:"entity_type"`
EntityTypeName string `json:"entity_type_name"`
ID int `json:"id"`
Name string `json:"name"`
ResourceURL string `json:"resource_url"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
}
// ArtistSource ...
type ArtistSource struct { type ArtistSource struct {
Anv string `json:"anv"` Anv string `json:"anv"`
Id int `json:"id"` ID int `json:"id"`
Join string `json:"join"` Join string `json:"join"`
Name string `json:"name:` Name string `json:"name"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Role string `json:"role"` Role string `json:"role"`
Tracks string `json:"tracks"` Tracks string `json:"tracks"`
} }
// Image ...
type Image struct { type Image struct {
Height int `json:"height"` Height int `json:"height"`
Width int `json:"width"` Width int `json:"width"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Type string `json:"type"` Type string `json:"type"`
Uri string `json:"uri"` URI string `json:"uri"`
Uri150 string `json:"uri150"` URI150 string `json:"uri150"`
} }
// Track ...
type Track struct { type Track struct {
Duration string `json:"duration"` Duration string `json:"duration"`
Position string `json:"position"` Position string `json:"position"`
Title string `json:"title"` Title string `json:"title"`
Type string `json:"type_"` Type string `json:"type_"`
Extraartists []ArtistSource `json:"extraartists"` Extraartists []ArtistSource `json:"extraartists,omitempty"`
Artists []ArtistSource `json:"artists,omitempty"`
} }
// LabelSource ...
type LabelSource struct { type LabelSource struct {
Catno string `json:"catno"` Catno string `json:"catno"`
Entity_type string `json:"entity_type"` EntityType string `json:"entity_type"`
Id int `json:"id"` EntityTypeName string `json:"entity_type_name"`
ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
} }
// Identifier ...
type Identifier struct { type Identifier struct {
Description string `json:"description,omitempty"`
Type string `json:"type"` Type string `json:"type"`
Value string `json:"value"` Value string `json:"value"`
} }
// Format ...
type Format struct { type Format struct {
Descriptions []string `json:"descriptions"` Descriptions []string `json:"descriptions"`
Name string `json:"name"` Name string `json:"name"`
Qty string `json:"qty"` Qty string `json:"qty"`
} }
// Company ...
type Company struct { type Company struct {
Catno string `json:"catno"` Catno string `json:"catno"`
Entity_type string `json:"entity_type"` EntityType string `json:"entity_type"`
Entity_type_name string `json:"entity_type_name"` EntityTypeName string `json:"entity_type_name"`
Id int `json:"id"` ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
} }
// Community ...
type Community struct { type Community struct {
Contributors []Contributor `json:"contributors"` Contributors []Contributor `json:"contributors"`
Data_quality string `json:"string"` DataQuality string `json:"data_quality"`
Have int `json:"have"` Have int `json:"have"`
Rating Rating `json:"rating"` Rating Rating `json:"rating"`
Status string `json:"status"` Status string `json:"status"`
@@ -73,71 +101,109 @@ type Community struct {
Want int `json:"want"` Want int `json:"want"`
} }
// Submitter ...
type Submitter struct { type Submitter struct {
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Username string `json:"username"` Username string `json:"username"`
} }
// Rating ...
type Rating struct { type Rating struct {
Average float32 `json:"average"` Average float32 `json:"average"`
Count int `json:"count"` Count int `json:"count"`
} }
// Contributor ...
type Contributor struct { type Contributor struct {
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Username string `json:"username"` Username string `json:"username"`
} }
// Page ...
type Page struct { type Page struct {
Per_page int `json:"per_page"` PerPage int `json:"per_page"`
Items int `json:"items"` Items int `json:"items"`
Page int `json:"page"` Page int `json:"page"`
Urls URLS `json:"urls"` URLs URLsList `json:"urls"`
Pages int `json:"pages"` Pages int `json:"pages"`
} }
type URLS struct { // URLsList ...
type URLsList struct {
Last string `json:"last"` Last string `json:"last"`
Next string `json:"next"` Next string `json:"next"`
} }
// Version ...
type Version struct { type Version struct {
Catno string `json:"catno"` Catno string `json:"catno"`
Country string `json:"country"` Country string `json:"country"`
Format string `json:"format"` Format string `json:"format"`
Id int `json:"id"` ID int `json:"id"`
Label string `json:"label"` Label string `json:"label"`
Released string `json:"released"` Released string `json:"released"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Status string `json:"status"` Status string `json:"status"`
Thumb string `json:"thumb"` Thumb string `json:"thumb"`
Title string `json:"title"` Title string `json:"title"`
} }
// Member ...
type Member struct { type Member struct {
Active bool `json:"active"` Active bool `json:"active"`
Id int `json:"id"` ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
} }
// Alias ...
type Alias struct {
ID int `json:"id"`
Name string `json:"name"`
ResourceURL string `json:"resource_url"`
}
// Sublable ...
type Sublable struct { type Sublable struct {
Resource_url string `json:"url"` ResourceURL string `json:"url"`
Id int `json:"id"` ID int `json:"id"`
Name string `json:"name"` Name string `json:"name"`
} }
// ReleaseSource ...
type ReleaseSource struct { type ReleaseSource struct {
Artist string `json:"artist"` Artist string `json:"artist"`
Catno string `json:"catno"` Catno string `json:"catno"`
Format string `json:"format"` Format string `json:"format"`
Id int `json:"id"` ID int `json:"id"`
Resource_url string `json:"resource_url"` ResourceURL string `json:"resource_url"`
Status string `json:"status"` Status string `json:"status"`
Thumb string `json:"thumb"` Thumb string `json:"thumb"`
Title string `json:"title"` Title string `json:"title"`
Year int `json:"year"` Year int `json:"year"`
Main_release int `json:"main_release"` MainRelease int `json:"main_release"`
Role string `json:"role"` Role string `json:"role"`
Type string `json:"type"` Type string `json:"type"`
} }
// Pagination ...
type Pagination struct {
Sort string // year, title, format
SortOrder string // asc, desc
Page int
PerPage int
}
// toParams converts pagaination params to request values
func (p *Pagination) params() url.Values {
if p == nil {
return nil
}
params := url.Values{}
params.Set("sort", p.Sort)
params.Set("sort_order", p.SortOrder)
params.Set("page", strconv.Itoa(p.Page))
params.Set("per_page", strconv.Itoa(p.PerPage))
return params
}

View File

@@ -1,61 +0,0 @@
package discogs
import (
"github.com/irlndts/go-apirequest"
"net/http"
)
type ReleaseService struct {
api *apirequest.API
}
type ReleaseParams struct {
Release_id string
}
type Release struct {
Title string `json:"title"`
Id int `json:"id"`
Artists []ArtistSource `json:"artists"`
Data_quality string `json:"data_quality"`
Thumb string `json:"thumb"`
Community Community `json:"community"`
Companies []Company `json:"companies"`
Country string `json:"country"`
Date_added string `json:"date_added"`
Date_changed string `json:"date_changed"`
Estimated_weight int `json:"estimated_weight"`
Extraartists []ArtistSource `json:"extraartists"`
Format_quantity int `json:"format_quantity"`
Formats []Format `json:"formats"`
Genres []string `json:"genres"`
Identifiers []Identifier `json:"identifiers"`
Images []Image `json:"images"`
Labels []LabelSource `json:"labels"`
Master_id int `json:"master_id"`
Master_url string `json:"master_url"`
Notes string `josn:"notes"`
Released string `json:"released"`
Released_formatted string `json:"released_formatted"`
Resource_url string `json:"resource_url"`
Status string `json:"status"`
Styles []string `json:"styles"`
Tracklist []Track `json:"tracklist"`
Uri string `json:"uri"`
Videos []Video `json:"videos"`
Year int `json:"year"`
}
func newReleaseService(api *apirequest.API) *ReleaseService {
return &ReleaseService{
api: api.Path("releases/"),
}
}
func (self *ReleaseService) Release(params *ReleaseParams) (*Release, *http.Response, error) {
release := new(Release)
apiError := new(APIError)
resp, err := self.api.New().Get(params.Release_id).Receive(release, apiError)
return release, resp, relevantError(err, *apiError)
}

View File

@@ -1,16 +0,0 @@
package discogs
import (
"fmt"
"testing"
)
func TestReleaseService_Release(t *testing.T) {
expectedTitle := "Elephant Riddim"
d := NewClient(testUserAgent, testToken)
release, _, err := d.Release.Release(&ReleaseParams{Release_id: "8138518"})
check(t, err)
assert(t, release.Title == expectedTitle, fmt.Sprintf("Release.Title looked for %s, and received %s ", expectedTitle, release.Title))
}

178
search.go
View File

@@ -1,71 +1,147 @@
package discogs package discogs
import ( import (
"net/http" "net/url"
"strconv"
"github.com/irlndts/go-apirequest"
) )
// SearchService ...
type SearchService struct { type SearchService struct {
api *apirequest.API url string
} }
func newSearchService(url string) *SearchService {
return &SearchService{
url: url,
}
}
// SearchRequest describes search request
type SearchRequest struct { type SearchRequest struct {
Q string // search query (optional) Q string // search query
Type string // one of release, master, artist, label (optional) Type string // one of release, master, artist, label
Title string // search by combined “Artist Name - Release Title” title field (optional) Title string // search by combined “Artist Name - Release Title” title field
Release_title string // search release titles (optional) ReleaseTitle string // search release titles
Credit string // search release credits (optional) Credit string // search release credits
Artist string // search artist names (optional) Artist string // search artist names
Anv string // search artist ANV (optional) Anv string // search artist ANV
Label string // search label names (optional) Label string // search label names
Genre string // search genres (optional) Genre string // search genres
Style string // search styles (optional) Style string // search styles
Country string // search release country (optional) Country string // search release country
Year string // search release year (optional) Year string // search release year
Format string // search formats (optional) Format string // search formats
Catno string // search catalog number (optional) Catno string // search catalog number
Barcode string // search barcodes (optional) Barcode string // search barcodes
Track string // search track titles (optional) Track string // search track titles
Submitter string // search submitter username (optional) Submitter string // search submitter username
Contributer string // search contributor usernames (optional) Contributor string // search contributor usernames
Page int // optional Page int
Per_page int // optional PerPage int
} }
func (r *SearchRequest) params() url.Values {
if r == nil {
return nil
}
params := url.Values{}
if r.Q != "" {
params.Set("q", r.Q)
}
if r.Type != "" {
params.Set("type", r.Type)
}
if r.Title != "" {
params.Set("title", r.Title)
}
if r.ReleaseTitle != "" {
params.Set("release_title", r.ReleaseTitle)
}
if r.Credit != "" {
params.Set("credit", r.Credit)
}
if r.Artist != "" {
params.Set("artist", r.Artist)
}
if r.Anv != "" {
params.Set("anv", r.Anv)
}
if r.Label != "" {
params.Set("label", r.Label)
}
if r.Genre != "" {
params.Set("genre", r.Genre)
}
if r.Style != "" {
params.Set("style", r.Style)
}
if r.Country != "" {
params.Set("country", r.Country)
}
if r.Year != "" {
params.Set("year", r.Year)
}
if r.Format != "" {
params.Set("format", r.Format)
}
if r.Catno != "" {
params.Set("catno", r.Catno)
}
if r.Barcode != "" {
params.Set("barcode", r.Barcode)
}
if r.Track != "" {
params.Set("track", r.Track)
}
if r.Submitter != "" {
params.Set("submitter", r.Submitter)
}
if r.Contributor != "" {
params.Set("contributor", r.Contributor)
}
params.Set("page", strconv.Itoa(r.Page))
if r.PerPage != 0 {
params.Set("per_page", strconv.Itoa(r.PerPage))
}
return params
}
// Search describes search response
type Search struct { type Search struct {
Pagination Page `json:"pagination"` Pagination Page `json:"pagination"`
Results []Result `json:"results"` Results []Result `json:"results,omitempty"`
} }
// Result describes a part of search result
type Result struct { type Result struct {
Style []string `json:"style"` Style []string `json:"style,omitempty"`
Thumb string `json:"thumb"` Thumb string `json:"thumb,omitempty"`
Title string `json:"title"` CoverImage string `json:"cover_image,omitempty"`
Country string `json:"country"` Title string `json:"title,omitempty"`
Format []string `json:"format"` Country string `json:"country,omitempty"`
Uri string `json:"uri"` Format []string `json:"format,omitempty"`
Community Community `json:"community"` URI string `json:"uri,omitempty"`
Label []string `json:"label"` Community Community `json:"community,omitempty"`
Catno string `json:"catno"` Label []string `json:"label,omitempty"`
Year string `json:"year"` Catno string `json:"catno,omitempty"`
Genre []string `json:"genre"` Year string `json:"year,omitempty"`
Resource_url string `json:"resource_url"` Genre []string `json:"genre,omitempty"`
Type string `json:"type"` ResourceURL string `json:"resource_url,omitempty"`
Id int `json:"id"` Type string `json:"type,omitempty"`
ID int `json:"id,omitempty"`
MasterID int `json:"master_id,omitempty"`
} }
func newSearchService(api *apirequest.API) *SearchService { // Search makes search request to discogs.
return &SearchService{ // Issue a search query to our database. This endpoint accepts pagination parameters.
api: api.Path("database/search"), // Authentication (as any user) is required.
} // https://www.discogs.com/developers/#page:database,header:database-search
} func (s *SearchService) Search(req SearchRequest) (*Search, error) {
var search *Search
func (self *SearchService) Search(params *SearchRequest) (*Search, *http.Response, error) { err := request(s.url, req.params(), &search)
search := new(Search) return search, err
apiError := new(APIError)
resp, err := self.api.New().QueryStruct(params).Receive(search, apiError)
return search, resp, relevantError(err, *apiError)
} }

9
testing_data.go Normal file

File diff suppressed because one or more lines are too long