tmdb - tmdb.go
1 // Package tmdb is a simple interface to the themoviedb.org database
2 package tmdb // import "vimagination.zapto.org/tmdb"
3
4 import (
5 "encoding/json"
6 "net/http"
7 "net/url"
8 )
9
10 var (
11 contentType = []string{"application/json;charset=utf-8"}
12 defaultURL, _ = url.Parse("https://api.themoviedb.org/")
13 v3Header = http.Header{
14 "Content-Type": contentType,
15 }
16 )
17
18 // APIKey is used to set the API key for a request
19 type APIKey interface {
20 setAPIKey(r *http.Request, params url.Values)
21 }
22
23 type v4Key struct {
24 headers http.Header
25 }
26
27 func (v v4Key) setAPIKey(r *http.Request, _ url.Values) {
28 r.Header = v.headers
29 }
30
31 // V4Key creates a new TMDB APIv4 key
32 func V4Key(v4key string) APIKey {
33 return &v4Key{
34 headers: http.Header{
35 "Authorization": []string{"Bearer " + v4key},
36 "Content-Type": contentType,
37 },
38 }
39 }
40
41 type v3Key struct {
42 key string
43 }
44
45 func (v v3Key) setAPIKey(r *http.Request, query url.Values) {
46 r.Header = v3Header
47 query.Set("api_key", v.key)
48 }
49
50 // V3Key create new TVDM APIv3 key
51 func V3Key(v3key string) APIKey {
52 return v3Key{v3key}
53 }
54
55 // TMDB holds an API Key to allow connection to TMDB
56 type TMDB struct {
57 apiKey APIKey
58 }
59
60 // New takes a TMDB API key to create a TMDB connection
61 func New(apiKey APIKey) *TMDB {
62 return &TMDB{apiKey}
63 }
64
65 // Error represents an error repsonse (401, 404) from the API
66 type Error struct {
67 Message string `json:"status_message"`
68 Code int64 `json:"status_code"`
69 }
70
71 func (e *Error) Error() string {
72 return e.Message
73 }
74
75 func (t *TMDB) get(result interface{}, path string, query url.Values, params ...option) error {
76 for _, param := range params {
77 param.setParam(query)
78 }
79 var req http.Request
80 t.apiKey.setAPIKey(&req, query)
81 url := defaultURL
82 url.Path = path
83 url.RawQuery = query.Encode()
84 req.URL = url
85 r, err := http.DefaultClient.Do(&req)
86 if err != nil {
87 return err
88 }
89 if r.StatusCode == http.StatusUnauthorized || r.StatusCode == http.StatusNotFound {
90 e := new(Error)
91 err = json.NewDecoder(r.Body).Decode(result)
92 r.Body.Close()
93 if err != nil {
94 return err
95 }
96 return e
97 }
98 err = json.NewDecoder(r.Body).Decode(result)
99 r.Body.Close()
100 return err
101 }