/
context.go
163 lines (128 loc) · 3.44 KB
/
context.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package mansion
import (
"fmt"
"net/http"
"github.com/itchio/butler/comm"
itchio "github.com/itchio/go-itchio"
"github.com/itchio/httpkit/timeout"
"github.com/itchio/wharf/pwr"
kingpin "gopkg.in/alecthomas/kingpin.v2"
)
type DoCommand func(ctx *Context)
type Context struct {
App *kingpin.Application
Commands map[string]DoCommand
// Identity is the path to the credentials file
Identity string
// String to include in our user-agent
UserAgentAddition string
// VersionString is the complete version string
VersionString string
// Version is just the version number, as a string
Version string
// The git commit hash
Commit string
// Quiet silences all output
Quiet bool
// Verbose enables chatty output
Verbose bool
// Verbose enables JSON output
JSON bool
// Path to the local sqlite database
DBPath string
CompressionAlgorithm string
CompressionQuality int
HTTPClient *http.Client
HTTPTransport *http.Transport
// url of the itch.io API server we're talking to
apiAddress string
// url of the itch.io web instance we're talking to
webAddress string
}
func NewContext(app *kingpin.Application) *Context {
client := timeout.NewDefaultClient()
originalTransport := client.Transport.(*http.Transport)
ctx := &Context{
App: app,
Commands: make(map[string]DoCommand),
HTTPClient: client,
HTTPTransport: originalTransport,
}
client.Transport = &UserAgentSetter{
OriginalTransport: originalTransport,
Context: ctx,
}
return ctx
}
func (ctx *Context) Register(clause *kingpin.CmdClause, do DoCommand) {
ctx.Commands[clause.FullCommand()] = do
}
func (ctx *Context) Must(err error) {
if err != nil {
if ctx.Verbose || ctx.JSON {
comm.Dief("%+v", err)
} else {
comm.Dief("%s", err)
}
}
}
func (ctx *Context) UserAgent() string {
version := ctx.Version
if version == "head" && ctx.Commit != "" {
version = ctx.Commit
}
res := fmt.Sprintf("butler/%s", version)
if ctx.UserAgentAddition != "" {
res = fmt.Sprintf("%s %s", res, ctx.UserAgentAddition)
}
return res
}
func (ctx *Context) CompressionSettings() pwr.CompressionSettings {
var algo pwr.CompressionAlgorithm
switch ctx.CompressionAlgorithm {
case "none":
algo = pwr.CompressionAlgorithm_NONE
case "brotli":
algo = pwr.CompressionAlgorithm_BROTLI
case "gzip":
algo = pwr.CompressionAlgorithm_GZIP
case "zstd":
algo = pwr.CompressionAlgorithm_ZSTD
default:
panic(fmt.Errorf("Unknown compression algorithm: %s", algo))
}
return pwr.CompressionSettings{
Algorithm: algo,
Quality: int32(ctx.CompressionQuality),
}
}
func (ctx *Context) NewClient(key string) *itchio.Client {
client := itchio.ClientWithKey(key)
client.HTTPClient = ctx.HTTPClient
client.SetServer(ctx.APIAddress())
client.UserAgent = ctx.UserAgent()
return client
}
func (ctx *Context) WebAddress() string {
return ctx.webAddress
}
func (ctx *Context) APIAddress() string {
return ctx.apiAddress
}
func (ctx *Context) SetAddress(address string) {
var err error
ctx.webAddress, err = stripApiSubdomain(address)
ctx.Must(err)
ctx.apiAddress, err = addApiSubdomain(address)
ctx.Must(err)
}
//
type UserAgentSetter struct {
OriginalTransport http.RoundTripper
Context *Context
}
var _ http.RoundTripper = (*UserAgentSetter)(nil)
func (uas *UserAgentSetter) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Set("User-Agent", uas.Context.UserAgent())
return uas.OriginalTransport.RoundTrip(req)
}