Skip to content

Commit 7056cda

Browse files
authored
Merge pull request #66 from twitchdev/feature/api-mock
RFC:15
2 parents 150e1e1 + 4ca0cd3 commit 7056cda

File tree

161 files changed

+13353
-443
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

161 files changed

+13353
-443
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ twitch-cli
1414

1515
# Output of the go coverage tool, specifically when used with LiteIDE
1616
*.out
17+
*.html
1718

1819
# Editor configs
1920
.vsvode/

.goreleaser.yml

+8-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ before:
55
- go mod download
66
builds:
77
- id: twitch-darwin
8-
ldflags: -X main.buildVersion={{ .Version }}
8+
ldflags:
9+
- -s -w -X main.buildVersion={{ .Version }}
910
binary: twitch
1011
env:
1112
- CGO_ENABLED=1
@@ -16,7 +17,8 @@ builds:
1617
goarch:
1718
- amd64
1819
- id: twitch-linux
19-
ldflags: -X main.buildVersion={{ .Version }}
20+
ldflags:
21+
- -s -w -X main.buildVersion={{ .Version }}
2022
binary: twitch
2123
env:
2224
- CGO_ENABLED=1
@@ -25,7 +27,8 @@ builds:
2527
goarch:
2628
- amd64
2729
- id: twitch-windows-x64
28-
ldflags: -X main.buildVersion={{ .Version }}
30+
ldflags:
31+
- -s -w -X main.buildVersion={{ .Version }}
2932
binary: twitch
3033
main: ./main.go
3134
env:
@@ -37,7 +40,8 @@ builds:
3740
goarch:
3841
- amd64
3942
- id: twitch-windows-i386
40-
ldflags: -X main.buildVersion={{ .Version }}
43+
ldflags:
44+
- -s -w -X main.buildVersion={{ .Version }}
4145
binary: twitch
4246
main: ./main.go
4347
env:

.vscode/settings.json

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"cSpell.words": [
3+
"SPDX"
4+
]
5+
}

Makefile

+5-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ test-release:
1717
twitch-cli:latest --rm-dist --skip-publish --snapshot
1818

1919
build:
20-
go build --ldflags "-X main.buildVersion=source"
20+
go build --ldflags "-s -w -X main.buildVersion=source"
2121

2222
build_all:
23-
xgo -out build/twitch --targets "darwin/amd64,windows/amd64,linux/amd64" --ldflags "-X main.buildVersion=source" ./
23+
xgo -out build/twitch --targets "darwin/amd64,windows/amd64,linux/amd64" --ldflags "-s -w -X main.buildVersion=source" ./
24+
25+
clean:
26+
rm -rf ~/.twitch-cli/eventCache.db

cmd/api.go

+36-1
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
package cmd
44

55
import (
6+
"fmt"
67
"io/ioutil"
78
"log"
89
"strings"
910

1011
"github.com/twitchdev/twitch-cli/internal/api"
12+
"github.com/twitchdev/twitch-cli/internal/mock_api/generate"
13+
"github.com/twitchdev/twitch-cli/internal/mock_api/mock_server"
1114

1215
"github.com/spf13/cobra"
1316
)
@@ -17,6 +20,7 @@ var queryParameters []string
1720
var body string
1821
var prettyPrint bool
1922
var autoPaginate bool
23+
var port int
2024

2125
var apiCmd = &cobra.Command{
2226
Use: "api",
@@ -59,8 +63,25 @@ var putCmd = &cobra.Command{
5963
Run: cmdRun,
6064
}
6165

66+
var mockCmd = &cobra.Command{
67+
Use: "mock-api",
68+
Short: "Used to interface with the mock Twitch API.",
69+
}
70+
71+
var startCmd = &cobra.Command{
72+
Use: "start",
73+
Short: "Used to start the server for the mock API.",
74+
Run: mockStartRun,
75+
}
76+
77+
var generateCmd = &cobra.Command{
78+
Use: "generate",
79+
Short: "Used to randomly generate data for use with the mock API. By default, this is run on the first invocation of the start command, however this allows you to generate further primitives.",
80+
Run: generateMockRun,
81+
}
82+
6283
func init() {
63-
rootCmd.AddCommand(apiCmd)
84+
rootCmd.AddCommand(apiCmd, mockCmd)
6485

6586
apiCmd.AddCommand(getCmd, postCmd, patchCmd, deleteCmd, putCmd)
6687

@@ -75,6 +96,11 @@ func init() {
7596

7697
getCmd.PersistentFlags().BoolVarP(&autoPaginate, "autopaginate", "P", false, "Whether to have API requests automatically paginate. Default is false.")
7798

99+
mockCmd.AddCommand(startCmd, generateCmd)
100+
101+
startCmd.Flags().IntVarP(&port, "port", "p", 8080, "Defines the port that the mock API will run on.")
102+
103+
generateCmd.Flags().IntVarP(&count, "count", "c", 10, "Defines the number of fake users to generate.")
78104
}
79105

80106
func cmdRun(cmd *cobra.Command, args []string) {
@@ -99,3 +125,12 @@ func getBodyFromFile(filename string) string {
99125

100126
return string(content)
101127
}
128+
129+
func mockStartRun(cmd *cobra.Command, args []string) {
130+
log.Println(fmt.Sprintf("Starting mock API server on http://localhost:%v", port))
131+
mock_server.StartServer(port)
132+
}
133+
134+
func generateMockRun(cmd *cobra.Command, args []string) {
135+
generate.Generate(count)
136+
}

docs/mock-api.md

+174
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
# mock-api
2+
3+
- [mock-api](#mock-api)
4+
- [Description](#description)
5+
- [generate](#generate)
6+
- [start](#start)
7+
- [mock namespace](#mock-namespace)
8+
- [units namespace](#units-namespace)
9+
- [auth namespace](#auth-namespace)
10+
11+
## Description
12+
13+
The `mock-api` product has two primary functions. The first is to generate so-called `units`- those are core building blocks on Twitch. These are, for now:
14+
15+
* Application Clients
16+
* Categories
17+
* Streams
18+
* Subscriptions
19+
* Tags
20+
* Teams
21+
* Users
22+
23+
The second is the actual server used to mock the endpoints. In the next iteration, you will be able to edit these and add further ones manually (for example, making a user with specific attributes), but for the beta we won't be providing this functionality as the current `generate` feature will make all of these (and more),
24+
25+
26+
## generate
27+
28+
This command will generate a specified number of users with associated relationships (e.g. subscriptions/mods/blocks).
29+
30+
**Args**
31+
32+
None.
33+
34+
**Flags**
35+
36+
| Flag | Shorthand | Description | Example | Required? (Y/N) |
37+
|-----------|-----------|-----------------------------------------------------------------------------|---------|-----------------|
38+
| `--count` | `-c` | Number of users to generate (and associated relationships). Defaults to 10. | `-c 25` | N |
39+
40+
41+
## start
42+
43+
The `start` function starts a new mock server for use with testing functionality. Currently, this replicates a large majority of the current API endpoints on the new API, but are ommitting:
44+
45+
* GET /analytics/extensions
46+
* GET /analytics/games
47+
* GET /extensions/transactions
48+
* POST /eventsub/subscriptions
49+
* DELETE /eventsub/subscriptions
50+
* GET /eventsub/subscriptions
51+
* GET /users/extensions/list
52+
* GET /users/extensions
53+
* PUT /users/extensions
54+
* GET /webhooks/subscriptions
55+
56+
For many of these, we are exploring how to better integrate this with existing features (for example, allowing events to be triggered on unit creation or otherwise), and for others, the value is minimal compared to the docs. All other endpoints should be currently supported, however it is possible to be out of date- if so, [please raise an issue](https://github.com/twitchdev/twitch-cli/issues).
57+
58+
To access these endpoints, you will point your code to `http://localhost:<port>/mock`, where port is either the default port (8080) or one you specified using the flag. For example, to access the users endpoint:
59+
60+
```sh
61+
curl -i -H "Accept: application/json" http://localhost:8080/mock/users
62+
```
63+
64+
For information on accessing those endpoints, please see [the documentation on the Developer site](https://dev.twitch.tv/docs/api/reference).
65+
66+
In total, there are three namespaces (top-level folder) that are used:
67+
68+
### mock namespace
69+
70+
Example URL: `http://localhost:8080/mock/users`
71+
72+
This namespace houses all mock endpoints. For information on accessing those endpoints, please see [the documentation on the Developer site](https://dev.twitch.tv/docs/api/reference).
73+
74+
### units namespace
75+
76+
Example URL: `http://localhost:8080/units/users`
77+
78+
This endpoint gives an unauthenticated peek into the list of units in the database- used for debugging or finding units for testing. Endpoints include:
79+
80+
* GET /categories
81+
* GET /clients
82+
* GET /streams
83+
* GET /subscriptions
84+
* GET /tags
85+
* GET /teams
86+
* GET /users
87+
* GET /videos
88+
89+
More will be added in the future.
90+
91+
### auth namespace
92+
93+
This endpoint is a light implementation of OAuth, without support for OIDC. These endpoints are used to generate either an app access token or user token. The two endpoints are below, with documentation and examples using cURL. All tokens expire after 24 hours.
94+
95+
**POST /authorize**
96+
97+
This endpoint generates a user token, similar to OAuth authorization code.
98+
99+
| Query Parameter | Description | Example | Required? (Y/N) |
100+
|-----------------|----------------------------------------------------------------------|--------------------------|-----------------|
101+
| `client_id` | Application client ID, which is output by the `generate` command. | `?client_id=1234` | Y |
102+
| `client_secret` | Application client secret, which is output by the `generate` command | `?client_secret=1234` | Y |
103+
| `grant_type` | Must be `user_token` | `?grant_type=user_token` | Y |
104+
| `user_id` | User to get the token for. | `?user_id=1234` | Y |
105+
| `scope` | Space seperated list of scopes to request for the given user. | `?scope=bits:read` | N |
106+
107+
The response is identical to the OAuth `authorization_code` with the omission of a refresh token.
108+
109+
Example request for user 78910 with no scopes:
110+
111+
```sh
112+
curl -X POST http://localhost:8080/auth/authorize?client_id=123&client_secret=456&grant_type=user_token&user_id=78910
113+
```
114+
115+
Example response:
116+
117+
```json
118+
{
119+
"access_token": "ff4231a5befca12",
120+
"refresh_token": "",
121+
"expires_in": 86399,
122+
"scope": [],
123+
"token_type": "bearer"
124+
}
125+
```
126+
127+
Docs: https://dev.twitch.tv/docs/authentication/getting-tokens-oauth#oauth-authorization-code-flow
128+
129+
**POST /token**
130+
131+
This endpoint generates an app access token using the `client_credentials` flow as documented.
132+
133+
134+
| Query Parameter | Description | Example | Required? (Y/N) |
135+
|-----------------|----------------------------------------------------------------------|--------------------------|-----------------|
136+
| `client_id` | Application client ID, which is output by the `generate` command. | `?client_id=1234` | Y |
137+
| `client_secret` | Application client secret, which is output by the `generate` command | `?client_secret=1234` | Y |
138+
| `grant_type` | Must be `client_credentials` | `?grant_type=user_token` | Y |
139+
| `scope` | Space seperated list of scopes to request for the given user. | `?scope=bits:read` | N |
140+
141+
142+
The response is identical to the OAuth `client_credentials` flow with the omission of a refresh token.
143+
144+
Example request with no scopes:
145+
146+
```sh
147+
curl -X POST http://localhost:8080/auth/token?client_id=123&client_secret=456&grant_type=client_credentials
148+
```
149+
150+
Example response:
151+
152+
```json
153+
{
154+
"access_token": "4f5dce6cea626cb",
155+
"refresh_token": "",
156+
"expires_in": 86399,
157+
"scope": [],
158+
"token_type": "bearer"
159+
}
160+
```
161+
162+
Docs: https://dev.twitch.tv/docs/authentication/getting-tokens-oauth#oauth-client-credentials-flow
163+
164+
**Args**
165+
166+
None.
167+
168+
**Flags**
169+
170+
| Flag | Shorthand | Description | Example | Required? (Y/N) |
171+
|----------|-----------|------------------------------------------|-----------|-----------------|
172+
| `--port` | `-p` | Port number to use with the mock server. | `-p 8000` | N |
173+
174+

go.mod

100644100755
+19-6
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,27 @@ go 1.14
44

55
require (
66
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2
7-
github.com/fatih/color v1.10.0
7+
github.com/fatih/color v1.12.0
8+
github.com/fsnotify/fsnotify v1.4.9 // indirect
89
github.com/hokaccha/go-prettyjson v0.0.0-20201222001619-a42f9ac2ec8e // indirect
9-
github.com/karalabe/xgo v0.0.0-20191115072854-c5ccff8648a7 // indirect
10+
github.com/jmoiron/sqlx v1.3.4
11+
github.com/lunixbochs/vtclean v1.0.0 // indirect
12+
github.com/magiconair/properties v1.8.5 // indirect
1013
github.com/manifoldco/promptui v0.8.0
11-
github.com/mattn/go-sqlite3 v1.14.5
14+
github.com/mattn/go-isatty v0.0.13 // indirect
15+
github.com/mattn/go-sqlite3 v1.14.7
1216
github.com/mitchellh/go-homedir v1.1.0
13-
github.com/spf13/cobra v1.1.1
17+
github.com/mitchellh/mapstructure v1.4.1 // indirect
18+
github.com/pelletier/go-toml v1.9.2 // indirect
19+
github.com/spf13/afero v1.6.0 // indirect
20+
github.com/spf13/cast v1.3.1 // indirect
21+
github.com/spf13/cobra v1.1.3
22+
github.com/spf13/jwalterweatherman v1.1.0 // indirect
1423
github.com/spf13/viper v1.7.1
15-
github.com/stretchr/testify v1.6.1
16-
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
24+
github.com/stretchr/testify v1.7.0
25+
golang.org/x/sys v0.0.0-20210611083646-a4fc73990273 // indirect
26+
golang.org/x/text v0.3.6 // indirect
27+
golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6
28+
gopkg.in/ini.v1 v1.62.0 // indirect
29+
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
1730
)

0 commit comments

Comments
 (0)