irc-medialink/parsers/soundcloud/v2_methods.go

166 lines
3.6 KiB
Go

package soundcloud
//go:generate go run ../../util/apigen/main.go --pkg soundcloud v2.yml
import (
"bytes"
"encoding/json"
"errors"
"io"
"log"
"net/http"
"net/url"
"time"
)
type v2Kind string
const (
// FIXME - not yet supported
//v2KindApp v2Kind = "app"
v2KindGroup v2Kind = "group"
v2KindPlaylist v2Kind = "playlist"
v2KindTrack v2Kind = "track"
v2KindUser v2Kind = "user"
)
var (
ErrUnsupportedKind = errors.New("Unsupported kind")
)
func (p *Parser) v2url(path string, urlvalues url.Values) *url.URL {
u := &url.URL{
Scheme: "https",
Host: "api-v2.soundcloud.com",
RawQuery: urlvalues.Encode(),
Path: path,
}
q := u.Query()
q.Set("client_id", p.Config.ClientId)
q.Set("app_version", "0.0") // TODO - Versioning
u.RawQuery = q.Encode()
log.Printf("SoundCloud parser: v2url: %s", u.String())
return u
}
func (p *Parser) v2call(path string, urlvalues url.Values) (v2Result, error) {
resp, err := p.http.Do(&http.Request{
URL: p.v2url(path, urlvalues),
Method: "GET",
Header: http.Header{
"Accept": []string{"application/json"},
"User-Agent": []string{"Icedream-YouTubeIRC/0.0"}, // TODO - Versioning
},
})
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return nil, errors.New(resp.Status)
}
b := new(bytes.Buffer)
io.Copy(b, resp.Body)
log.Printf("v2call: Response is %s", b.String())
return b.Bytes(), nil
}
func (p *Parser) v2resolve(u string) (*v2ResolveResult, error) {
r, err := p.v2call("/resolve", url.Values{
"url": []string{u},
})
if err != nil {
return nil, err
}
// First find out the kind via the most generic type possible
obj := new(v2Object)
if err := r.Decoder().Decode(obj); err != nil {
return nil, err
}
// Now decode as correct type
switch obj.Kind {
case v2KindTrack:
exactObj := new(v2Track)
if err := r.Decoder().Decode(exactObj); err != nil {
return nil, err
}
return &v2ResolveResult{exactObj, obj.Kind}, nil
case v2KindUser:
exactObj := new(v2User)
if err := r.Decoder().Decode(exactObj); err != nil {
return nil, err
}
return &v2ResolveResult{exactObj, obj.Kind}, nil
case v2KindGroup:
exactObj := new(v2Group)
if err := r.Decoder().Decode(exactObj); err != nil {
return nil, err
}
return &v2ResolveResult{exactObj, obj.Kind}, nil
case v2KindPlaylist:
exactObj := new(v2Playlist)
if err := r.Decoder().Decode(exactObj); err != nil {
return nil, err
}
return &v2ResolveResult{exactObj, obj.Kind}, nil
default:
return nil, ErrUnsupportedKind
}
}
type v2Result []byte
func (r v2Result) Decoder() *json.Decoder {
return json.NewDecoder(bytes.NewReader([]byte(r)))
}
type v2ResolveResult struct {
result interface{}
Kind v2Kind
}
func (r *v2ResolveResult) AsUser() *v2User {
return r.result.(*v2User)
}
// FIXME - not supported yet
/*func (r *v2ResolveResult) AsApp() *v2App {
return r.result.(*v2App)
}*/
func (r *v2ResolveResult) AsTrack() *v2Track {
return r.result.(*v2Track)
}
func (r *v2ResolveResult) AsPlaylist() *v2Playlist {
return r.result.(*v2Playlist)
}
func (r *v2ResolveResult) AsGroup() *v2Group {
return r.result.(*v2Group)
}
// FIXME - See https://github.com/golang/go/issues/9037 - Revert to using time.Time in the API as soon as this is fixed!
type timeString string
func (t timeString) ToTime(layout string) (parsedTime time.Time) {
if t == "" {
return // default time value
}
if len(layout) == 0 {
layout = time.RFC3339
}
parsedTime, err := time.Parse(layout, string(t))
if err != nil {
// It's just a temporary fix anyways
panic(err)
}
return
}