This repository has been archived by the owner on Nov 16, 2019. It is now read-only.
/
rpc.go
79 lines (65 loc) · 2.01 KB
/
rpc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package api
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"github.com/golang/protobuf/proto"
"golang.org/x/net/context/ctxhttp"
protos "github.com/pogodevorg/POGOProtos-go"
)
const rpcUserAgent = "Niantic App"
func raise(message string) error {
return fmt.Errorf("rpc/client: %s", message)
}
// RPC is used to communicate with the Pokémon Go API
type RPC struct {
http *http.Client
}
// NewRPC constructs a Pokémon Go RPC API client
func NewRPC() *RPC {
options := &cookiejar.Options{}
jar, _ := cookiejar.New(options)
httpClient := &http.Client{
Jar: jar,
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return raise("Did not follow redirect")
},
}
return &RPC{
http: httpClient,
}
}
// Request queries the Pokémon Go API will all pending requests
func (c *RPC) Request(ctx context.Context, endpoint string, requestEnvelope *protos.RequestEnvelope) (responseEnvelope *protos.ResponseEnvelope, err error) {
responseEnvelope = &protos.ResponseEnvelope{}
// Build request
requestBytes, err := proto.Marshal(requestEnvelope)
if err != nil {
return responseEnvelope, raise("Could not encode request body")
}
requestReader := bytes.NewReader(requestBytes)
request, err := http.NewRequest("POST", endpoint, requestReader)
if err != nil {
return responseEnvelope, raise("Unable to create the request")
}
request.Header.Add("User-Agent", rpcUserAgent)
// Perform call to API
response, err := ctxhttp.Do(ctx, c.http, request)
if err != nil {
return responseEnvelope, raise(fmt.Sprintf("There was an error requesting the API: %s", err))
}
defer response.Body.Close()
if response.StatusCode != 200 {
return responseEnvelope, raise(fmt.Sprintf("Status code was %d, expected 200", response.StatusCode))
}
// Read the response
responseBytes, err := ioutil.ReadAll(response.Body)
if err != nil {
return responseEnvelope, raise("Could not decode response body")
}
proto.Unmarshal(responseBytes, responseEnvelope)
return responseEnvelope, nil
}