Skip to content

Commit 828503a

Browse files
author
lleadbet
committed
Finished API parity update.
1 parent a3bea9e commit 828503a

15 files changed

+661
-20
lines changed

internal/database/drops.go

+6
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ func (q *Query) GetDropsEntitlements(de DropsEntitlement) (*DBResponse, error) {
4949
}
5050
func (q *Query) InsertDropsEntitlement(d DropsEntitlement) error {
5151
stmt := generateInsertSQL("drops_entitlements", "id", d, false)
52+
println(stmt)
5253
_, err := q.DB.NamedExec(stmt, d)
5354
return err
5455
}
56+
57+
func (q *Query) UpdateDropsEntitlement(d DropsEntitlement) error {
58+
_, err := q.DB.NamedExec(generateUpdateSQL("drops_entitlements", []string{"id"}, d), d)
59+
return err
60+
}

internal/database/schedule.go

+5
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
package database
44

55
import (
6+
"database/sql"
7+
"errors"
68
"time"
79
)
810

@@ -122,5 +124,8 @@ func (q *Query) UpdateSegment(p ScheduleSegment) error {
122124
func (q *Query) GetVacations(p ScheduleSegment) (ScheduleVacation, error) {
123125
v := ScheduleVacation{}
124126
err := q.DB.Get(&v, "select id,starttime,endtime from stream_schedule where is_vacation=true and datetime(endtime) > datetime('now') and broadcaster_id= $1 limit 1", p.UserID)
127+
if errors.As(err, &sql.ErrNoRows) {
128+
return v, nil
129+
}
125130
return v, err
126131
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package chat
4+
5+
import (
6+
"encoding/json"
7+
"fmt"
8+
"net/http"
9+
10+
"github.com/twitchdev/twitch-cli/internal/database"
11+
"github.com/twitchdev/twitch-cli/internal/mock_api/mock_errors"
12+
"github.com/twitchdev/twitch-cli/internal/models"
13+
"github.com/twitchdev/twitch-cli/internal/util"
14+
)
15+
16+
var channelEmotesMethodsSupported = map[string]bool{
17+
http.MethodGet: true,
18+
http.MethodPost: false,
19+
http.MethodDelete: false,
20+
http.MethodPatch: false,
21+
http.MethodPut: false,
22+
}
23+
24+
var channelEmotesScopesByMethod = map[string][]string{
25+
http.MethodGet: {},
26+
http.MethodPost: {},
27+
http.MethodDelete: {},
28+
http.MethodPatch: {},
29+
http.MethodPut: {},
30+
}
31+
32+
type ChannelEmotes struct{}
33+
34+
func (e ChannelEmotes) Path() string { return "/chat/emotes/channel" }
35+
36+
func (e ChannelEmotes) GetRequiredScopes(method string) []string {
37+
return channelEmotesScopesByMethod[method]
38+
}
39+
40+
func (e ChannelEmotes) ValidMethod(method string) bool {
41+
return channelEmotesMethodsSupported[method]
42+
}
43+
44+
func (e ChannelEmotes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
45+
db = r.Context().Value("db").(database.CLIDatabase)
46+
47+
switch r.Method {
48+
case http.MethodGet:
49+
getChannelEmotes(w, r)
50+
break
51+
default:
52+
w.WriteHeader(http.StatusMethodNotAllowed)
53+
}
54+
}
55+
func getChannelEmotes(w http.ResponseWriter, r *http.Request) {
56+
emotes := []EmotesResponse{}
57+
broadcaster := r.URL.Query().Get("broadcaster_id")
58+
if broadcaster == "" {
59+
mock_errors.WriteBadRequest(w, "Missing required parameter broadcaster_id")
60+
return
61+
}
62+
63+
setID := fmt.Sprint(util.RandomInt(10 * 1000))
64+
ownerID := util.RandomUserID()
65+
for _, v := range defaultEmoteTypes {
66+
emoteType := v
67+
for i := 0; i < 5; i++ {
68+
id := util.RandomInt(10 * 1000)
69+
name := util.RandomGUID()
70+
er := EmotesResponse{
71+
ID: fmt.Sprint(id),
72+
Name: name,
73+
Images: EmotesImages{
74+
ImageURL1X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/1.0", id),
75+
ImageURL2X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/2.0", id),
76+
ImageURL4X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/4.0", id),
77+
},
78+
EmoteType: &emoteType,
79+
EmoteSetID: &setID,
80+
OwnerID: &ownerID,
81+
}
82+
if emoteType == "subscription" {
83+
thousand := "1000"
84+
er.Tier = &thousand
85+
} else {
86+
es := ""
87+
er.Tier = &es
88+
}
89+
90+
emotes = append(emotes, er)
91+
}
92+
}
93+
94+
bytes, _ := json.Marshal(models.APIResponse{Data: emotes})
95+
w.Write(bytes)
96+
}

internal/mock_api/endpoints/chat/chat_test.go

+51
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,54 @@ func TestChannelBadges(t *testing.T) {
4141
a.Nil(err)
4242
a.Equal(200, resp.StatusCode)
4343
}
44+
45+
func TestGlobalEmotes(t *testing.T) {
46+
a := test_setup.SetupTestEnv(t)
47+
ts := test_server.SetupTestServer(GlobalEmotes{})
48+
49+
// get
50+
req, _ := http.NewRequest(http.MethodGet, ts.URL+GlobalEmotes{}.Path(), nil)
51+
q := req.URL.Query()
52+
req.URL.RawQuery = q.Encode()
53+
resp, err := http.DefaultClient.Do(req)
54+
a.Nil(err)
55+
a.Equal(200, resp.StatusCode)
56+
}
57+
58+
func TestChannelEmotes(t *testing.T) {
59+
a := test_setup.SetupTestEnv(t)
60+
ts := test_server.SetupTestServer(ChannelEmotes{})
61+
62+
// get
63+
req, _ := http.NewRequest(http.MethodGet, ts.URL+ChannelEmotes{}.Path(), nil)
64+
q := req.URL.Query()
65+
req.URL.RawQuery = q.Encode()
66+
resp, err := http.DefaultClient.Do(req)
67+
a.Nil(err)
68+
a.Equal(400, resp.StatusCode)
69+
70+
q.Set("broadcaster_id", "1")
71+
req.URL.RawQuery = q.Encode()
72+
resp, err = http.DefaultClient.Do(req)
73+
a.Nil(err)
74+
a.Equal(200, resp.StatusCode)
75+
}
76+
77+
func TestEmoteSets(t *testing.T) {
78+
a := test_setup.SetupTestEnv(t)
79+
ts := test_server.SetupTestServer(EmoteSets{})
80+
81+
// get
82+
req, _ := http.NewRequest(http.MethodGet, ts.URL+EmoteSets{}.Path(), nil)
83+
q := req.URL.Query()
84+
req.URL.RawQuery = q.Encode()
85+
resp, err := http.DefaultClient.Do(req)
86+
a.Nil(err)
87+
a.Equal(400, resp.StatusCode)
88+
89+
q.Set("emote_set_id", "1")
90+
req.URL.RawQuery = q.Encode()
91+
resp, err = http.DefaultClient.Do(req)
92+
a.Nil(err)
93+
a.Equal(200, resp.StatusCode)
94+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package chat
4+
5+
import (
6+
"encoding/json"
7+
"fmt"
8+
"net/http"
9+
10+
"github.com/twitchdev/twitch-cli/internal/database"
11+
"github.com/twitchdev/twitch-cli/internal/mock_api/mock_errors"
12+
"github.com/twitchdev/twitch-cli/internal/models"
13+
"github.com/twitchdev/twitch-cli/internal/util"
14+
)
15+
16+
var emoteSetsMethodsSupported = map[string]bool{
17+
http.MethodGet: true,
18+
http.MethodPost: false,
19+
http.MethodDelete: false,
20+
http.MethodPatch: false,
21+
http.MethodPut: false,
22+
}
23+
24+
var emoteSetsScopesByMethod = map[string][]string{
25+
http.MethodGet: {},
26+
http.MethodPost: {},
27+
http.MethodDelete: {},
28+
http.MethodPatch: {},
29+
http.MethodPut: {},
30+
}
31+
32+
type EmoteSets struct{}
33+
34+
func (e EmoteSets) Path() string { return "/chat/emotes/set" }
35+
36+
func (e EmoteSets) GetRequiredScopes(method string) []string {
37+
return emoteSetsScopesByMethod[method]
38+
}
39+
40+
func (e EmoteSets) ValidMethod(method string) bool {
41+
return emoteSetsMethodsSupported[method]
42+
}
43+
44+
func (e EmoteSets) ServeHTTP(w http.ResponseWriter, r *http.Request) {
45+
db = r.Context().Value("db").(database.CLIDatabase)
46+
47+
switch r.Method {
48+
case http.MethodGet:
49+
getEmoteSets(w, r)
50+
break
51+
default:
52+
w.WriteHeader(http.StatusMethodNotAllowed)
53+
}
54+
}
55+
func getEmoteSets(w http.ResponseWriter, r *http.Request) {
56+
emotes := []EmotesResponse{}
57+
setID := r.URL.Query().Get("emote_set_id")
58+
if setID == "" {
59+
mock_errors.WriteBadRequest(w, "Missing required parameter emote_set_id")
60+
return
61+
}
62+
63+
for _, v := range defaultEmoteTypes {
64+
emoteType := v
65+
for i := 0; i < 5; i++ {
66+
id := util.RandomInt(10 * 1000)
67+
name := util.RandomGUID()
68+
er := EmotesResponse{
69+
ID: fmt.Sprint(id),
70+
Name: name,
71+
Images: EmotesImages{
72+
ImageURL1X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/1.0", id),
73+
ImageURL2X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/2.0", id),
74+
ImageURL4X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/4.0", id),
75+
},
76+
EmoteType: &emoteType,
77+
EmoteSetID: &setID,
78+
}
79+
if emoteType == "subscription" {
80+
thousand := "1000"
81+
er.Tier = &thousand
82+
} else {
83+
es := ""
84+
er.Tier = &es
85+
}
86+
87+
emotes = append(emotes, er)
88+
}
89+
}
90+
91+
bytes, _ := json.Marshal(models.APIResponse{Data: emotes})
92+
w.Write(bytes)
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package chat
4+
5+
import (
6+
"encoding/json"
7+
"fmt"
8+
"net/http"
9+
10+
"github.com/twitchdev/twitch-cli/internal/database"
11+
"github.com/twitchdev/twitch-cli/internal/models"
12+
"github.com/twitchdev/twitch-cli/internal/util"
13+
)
14+
15+
var globalEmotesMethodsSupported = map[string]bool{
16+
http.MethodGet: true,
17+
http.MethodPost: false,
18+
http.MethodDelete: false,
19+
http.MethodPatch: false,
20+
http.MethodPut: false,
21+
}
22+
23+
var globalEmotesScopesByMethod = map[string][]string{
24+
http.MethodGet: {},
25+
http.MethodPost: {},
26+
http.MethodDelete: {},
27+
http.MethodPatch: {},
28+
http.MethodPut: {},
29+
}
30+
31+
type GlobalEmotes struct{}
32+
33+
func (e GlobalEmotes) Path() string { return "/chat/emotes/global" }
34+
35+
func (e GlobalEmotes) GetRequiredScopes(method string) []string {
36+
return globalEmotesScopesByMethod[method]
37+
}
38+
39+
func (e GlobalEmotes) ValidMethod(method string) bool {
40+
return globalEmotesMethodsSupported[method]
41+
}
42+
43+
func (e GlobalEmotes) ServeHTTP(w http.ResponseWriter, r *http.Request) {
44+
db = r.Context().Value("db").(database.CLIDatabase)
45+
46+
switch r.Method {
47+
case http.MethodGet:
48+
getGlobalEmotes(w, r)
49+
break
50+
default:
51+
w.WriteHeader(http.StatusMethodNotAllowed)
52+
}
53+
}
54+
55+
func getGlobalEmotes(w http.ResponseWriter, r *http.Request) {
56+
emotes := []EmotesResponse{}
57+
58+
for i := 0; i < 100; i++ {
59+
id := util.RandomInt(10 * 1000)
60+
name := util.RandomGUID()
61+
emotes = append(emotes, EmotesResponse{
62+
ID: fmt.Sprintf("%v", id),
63+
Name: name,
64+
Images: EmotesImages{
65+
ImageURL1X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/1.0", id),
66+
ImageURL2X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/2.0", id),
67+
ImageURL4X: fmt.Sprintf("https://static-cdn.jtvnw.net/emoticons/v1/%v/4.0", id),
68+
},
69+
})
70+
}
71+
72+
bytes, _ := json.Marshal(models.APIResponse{Data: emotes})
73+
w.Write(bytes)
74+
}

internal/mock_api/endpoints/chat/shared.go

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package chat
55
import "github.com/twitchdev/twitch-cli/internal/database"
66

77
var db database.CLIDatabase
8+
var defaultEmoteTypes = []string{"subscription", "bitstier", "follower"}
89

910
type BadgesResponse struct {
1011
SetID string `json:"set_id"`
@@ -17,3 +18,19 @@ type BadgesVersion struct {
1718
ImageURL2X string `json:"image_url_2x"`
1819
ImageURL4X string `json:"image_url_4x"`
1920
}
21+
22+
type EmotesResponse struct {
23+
ID string `json:"id"`
24+
Name string `json:"name"`
25+
Images EmotesImages `json:"images"`
26+
Tier *string `json:"tier,omitempty"`
27+
EmoteType *string `json:"emote_type,omitempty"`
28+
EmoteSetID *string `json:"emote_set_id,omitempty"`
29+
OwnerID *string `json:"owner_id,omitempty"`
30+
}
31+
32+
type EmotesImages struct {
33+
ImageURL1X string `json:"url_1x"`
34+
ImageURL2X string `json:"url_2x"`
35+
ImageURL4X string `json:"url_4x"`
36+
}

0 commit comments

Comments
 (0)