Skip to content

Commit fd16e4c

Browse files
committed
Added endpoints /charity/campaigns, /charity/donations, /chat/chatters, /chat/settings, /c*/announcements, /c*/color, /goals, /moderation/bans, /m*/chat, /m*/moderators, /m*/shield_mode, /m*/vips, /raids, /whispers
1 parent 975d223 commit fd16e4c

36 files changed

+3080
-32
lines changed

internal/database/chat.go

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package database
4+
5+
type ChatSettings struct {
6+
BroadcasterID string `db:"broadcaster_id" json:"broadcaster_id"`
7+
SlowMode *bool `db:"slow_mode" json:"slow_mode"`
8+
SlowModeWaitTime *int `db:"slow_mode_wait_time" json:"slow_mode_wait_time"`
9+
FollowerMode *bool `db:"follower_mode" json:"follower_mode"`
10+
FollowerModeDuration *int `db:"follower_mode_duration" json:"follower_mode_duration"`
11+
SubscriberMode *bool `db:"subscriber_mode" json:"subscriber_mode"`
12+
EmoteMode *bool `db:"emote_mode" json:"emote_mode"`
13+
UniqueChatMode *bool `db:"unique_chat_mode" json:"unique_chat_mode"`
14+
NonModeratorChatDelay *bool `db:"non_moderator_chat_delay" json:"non_moderator_chat_delay"`
15+
NonModeratorChatDelayDuration *int `db:"non_moderator_chat_delay_duration" json:"non_moderator_chat_delay_duration"`
16+
17+
// Shield mode
18+
ShieldModeIsActive bool `db:"shieldmode_is_active" json:"-"`
19+
ShieldModeModeratorID string `db:"shieldmode_moderator_id" json:"-"`
20+
ShieldModeModeratorLogin string `db:"shieldmode_moderator_login" json:"-"`
21+
ShieldModeModeratorName string `db:"shieldmode_moderator_name" json:"-"`
22+
ShieldModeLastActivated string `db:"shieldmode_last_activated" json:"-"`
23+
}
24+
25+
func (q *Query) GetChatSettingsByBroadcaster(broadcaster string) (*DBResponse, error) {
26+
var r []ChatSettings
27+
28+
err := q.DB.Select(&r, "SELECT * FROM chat_settings WHERE broadcaster_id = $1", broadcaster)
29+
if err != nil {
30+
return nil, err
31+
}
32+
33+
dbr := DBResponse{
34+
Data: r,
35+
Limit: q.Limit,
36+
Total: len(r),
37+
}
38+
39+
// No cursor because there should only ever be one result
40+
41+
return &dbr, err
42+
}
43+
44+
func (q *Query) InsertChatSettings(s ChatSettings) error {
45+
stmt := generateInsertSQL("chat_settings", "broadcaster_id", s, true)
46+
_, err := q.DB.NamedExec(stmt, s)
47+
return err
48+
}
49+
50+
func (q *Query) UpdateChatSettings(s ChatSettings) error {
51+
sql := generateUpdateSQL("chat_settings", []string{"broadcaster_id"}, s)
52+
_, err := q.DB.NamedExec(sql, s)
53+
return err
54+
}

internal/database/database_test.go

+22-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const TEST_USER_ID = "1"
2323
const TEST_USER_LOGIN = "testing_user1"
2424
const TEST_USER_ID_2 = "2"
2525
const TEST_USER_LOGIN_2 = "second_user"
26+
const TEST_USER_ID_99 = "99"
27+
const TEST_USER_LOGIN_99 = "non_mod_user"
2628
const CATEGORY_ID = "1"
2729
const IGDB_ID = "123"
2830

@@ -87,6 +89,23 @@ func TestMain(m *testing.M) {
8789
}, false)
8890
log.Print(err)
8991

92+
err = q.InsertUser(User{
93+
ID: TEST_USER_ID_99,
94+
UserLogin: TEST_USER_LOGIN_99,
95+
DisplayName: TEST_USER_LOGIN_99,
96+
Email: "",
97+
BroadcasterType: "partner",
98+
UserType: "testing",
99+
UserDescription: "hi mom",
100+
CreatedAt: util.GetTimestamp().Format(time.RFC3339),
101+
ModifiedAt: util.GetTimestamp().Format(time.RFC3339),
102+
CategoryID: sql.NullString{String: "", Valid: false},
103+
Title: "hello",
104+
Language: "en",
105+
Delay: 0,
106+
}, false)
107+
log.Print(err)
108+
90109
os.Exit(m.Run())
91110
db.DB.Close()
92111
}
@@ -215,7 +234,7 @@ func TestUsers(t *testing.T) {
215234
Title: "hello",
216235
Language: "en",
217236
Delay: 0,
218-
}, false)
237+
}, true)
219238
a.Nil(err)
220239

221240
err = q.InsertUser(User{
@@ -232,7 +251,7 @@ func TestUsers(t *testing.T) {
232251
Title: "hello",
233252
Language: "en",
234253
Delay: 0,
235-
}, false)
254+
}, true)
236255
a.Nil(err)
237256

238257
u, err := q.GetUser(User{ID: TEST_USER_ID})
@@ -408,7 +427,7 @@ func TestModeration(t *testing.T) {
408427
moderators := dbr.Data.([]Moderator)
409428
a.GreaterOrEqual(len(moderators), 1)
410429

411-
dbr, err = q.GetModeratorsForBroadcaster(TEST_USER_ID, "2")
430+
dbr, err = q.GetModeratorsForBroadcaster(TEST_USER_ID)
412431
a.Nil(err)
413432
moderators = dbr.Data.([]Moderator)
414433
a.GreaterOrEqual(len(moderators), 1)

internal/database/init.go

+44-2
Large diffs are not rendered by default.

internal/database/moderation.go

+9-2
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (q *Query) AddModerator(p UserRequestParams) error {
118118
return tx.Commit()
119119
}
120120

121-
func (q *Query) GetModeratorsForBroadcaster(broadcasterID string, userID string) (*DBResponse, error) {
121+
func (q *Query) GetModeratorsForBroadcaster(broadcasterID string) (*DBResponse, error) {
122122
var r []Moderator
123123

124124
err := q.DB.Select(&r, "SELECT u1.id as user_id, u1.user_login as user_login, u1.display_name as user_name FROM moderators as m JOIN users u1 ON m.user_id = u1.id where broadcaster_id = $1 ORDER BY m.created_at DESC", broadcasterID)
@@ -162,7 +162,7 @@ func (q *Query) RemoveModerator(broadcaster string, user string) error {
162162
}
163163

164164
func (q *Query) InsertBan(p UserRequestParams) error {
165-
stmt := generateInsertSQL("bans", "id", p, false)
165+
stmt := generateInsertSQL("bans", "broadcaster_id", p, false)
166166
p.CreatedAt = util.GetTimestamp().UTC().Format(time.RFC3339)
167167

168168
ma := BanEvent{
@@ -219,6 +219,13 @@ func (q *Query) GetBans(p UserRequestParams) (*DBResponse, error) {
219219
return &dbr, nil
220220
}
221221

222+
func (q *Query) DeleteBan(p UserRequestParams) error {
223+
tx := q.DB.MustBegin()
224+
tx.Exec("DELETE FROM bans WHERE broadcaster_id=$1 AND user_id=$2", p.BroadcasterID, p.UserID)
225+
err := tx.Commit()
226+
return err
227+
}
228+
222229
func (q *Query) GetBanEvents(p UserRequestParams) (*DBResponse, error) {
223230
r := []BanEvent{}
224231
stmt := generateSQL("SELECT u1.id as user_id, u1.user_login as user_login, u1.display_name as user_name, u2.id as broadcaster_id, u2.user_login as broadcaster_login, u2.display_name as broadcaster_name, be.event_type, be.event_version, be.event_timestamp, be.id FROM ban_events as be JOIN users u1 ON be.user_id = u1.id JOIN users u2 ON be.broadcaster_id = u2.id", p, SEP_AND)

internal/database/query.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ type Query struct {
2121

2222
// NewQuery handles the logic for generating the pagination token to pass alongside the DB queries for easier access
2323
func (c CLIDatabase) NewQuery(r *http.Request, max_limit int) *Query {
24+
return c.NewQueryWithDefaultLimit(r, max_limit, 20)
25+
}
26+
27+
func (c CLIDatabase) NewQueryWithDefaultLimit(r *http.Request, max_limit int, default_limit int) *Query {
2428
p := Query{DB: c.DB}
2529
if r == nil {
2630
return &p
@@ -44,7 +48,7 @@ func (c CLIDatabase) NewQuery(r *http.Request, max_limit int) *Query {
4448

4549
first, _ := strconv.Atoi(f)
4650
if first > max_limit || first <= 0 {
47-
first = 20
51+
first = default_limit
4852
}
4953
p.Limit = int(first)
5054

internal/database/user.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ type User struct {
3030
Title string `db:"title" json:"title"`
3131
Language string `db:"stream_language" json:"stream_language"`
3232
Delay int `db:"delay" json:"delay" dbi:"force"`
33+
ChatColor string `db:"chat_color" json:"-"`
3334
}
3435

3536
type Follow struct {
@@ -76,6 +77,12 @@ type SearchChannel struct {
7677
ThumbNailURL string `json:"thumbnail_url"`
7778
}
7879

80+
type VIP struct {
81+
BroadcasterID string `db:"broadcaster_id"`
82+
UserID string `db:"user_id"`
83+
CreatedAt string `db:"created_at"`
84+
}
85+
7986
func (q *Query) GetUser(u User) (User, error) {
8087
var r User
8188
sql := generateSQL("select * from users u1", u, SEP_AND)
@@ -161,7 +168,7 @@ func (q *Query) GetChannels(u User) (*DBResponse, error) {
161168
}
162169

163170
func (q *Query) InsertUser(u User, upsert bool) error {
164-
stmt := generateInsertSQL("users", "id", u, true)
171+
stmt := generateInsertSQL("users", "id", u, upsert)
165172
_, err := q.DB.NamedExec(stmt, u)
166173
return err
167174
}
@@ -346,3 +353,40 @@ func (q *Query) SearchChannels(query string, live_only bool) (*DBResponse, error
346353

347354
return &dbr, err
348355
}
356+
357+
func (q *Query) GetVIPsByBroadcaster(broadcaster string) (*DBResponse, error) {
358+
var r []VIP
359+
360+
err := q.DB.Select(&r, "SELECT * FROM vips WHERE broadcaster_id=$1", broadcaster)
361+
if errors.Is(err, sql.ErrNoRows) {
362+
return nil, nil
363+
} else if err != nil {
364+
return nil, err
365+
}
366+
367+
dbr := DBResponse{
368+
Data: r,
369+
Limit: q.Limit,
370+
Total: len(r),
371+
}
372+
373+
if len(r) != q.Limit {
374+
q.PaginationCursor = ""
375+
}
376+
377+
dbr.Cursor = q.PaginationCursor
378+
379+
return &dbr, err
380+
}
381+
382+
func (q *Query) AddVIP(p UserRequestParams) error {
383+
stmt := generateInsertSQL("vips", "user_id", p, false)
384+
p.CreatedAt = util.GetTimestamp().UTC().Format(time.RFC3339)
385+
_, err := q.DB.NamedExec(stmt, p)
386+
return err
387+
}
388+
389+
func (q *Query) DeleteVIP(broadcaster string, user string) error {
390+
_, err := q.DB.Exec(`delete from vips where broadcaster_id=$1 and user_id=$2`, broadcaster, user)
391+
return err
392+
}

internal/mock_api/authentication/authentication.go

+14-2
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,20 @@ func (u UserAuthentication) HasOneOfRequiredScope(scopes []string) bool {
131131
}
132132

133133
func (u *UserAuthentication) MatchesBroadcasterIDParam(r *http.Request) bool {
134-
bid := r.URL.Query().Get("broadcaster_id")
135-
if bid == "" || bid != u.UserID {
134+
return u.MatchesSpecifiedIDParam(r, "broadcaster_id")
135+
}
136+
137+
func (u *UserAuthentication) MatchesModeratorIDParam(r *http.Request) bool {
138+
return u.MatchesSpecifiedIDParam(r, "moderator_id")
139+
}
140+
141+
func (u *UserAuthentication) MatchesUserIDParam(r *http.Request) bool {
142+
return u.MatchesSpecifiedIDParam(r, "user_id")
143+
}
144+
145+
func (u *UserAuthentication) MatchesSpecifiedIDParam(r *http.Request, param string) bool {
146+
id := r.URL.Query().Get(param)
147+
if id == "" || id != u.UserID {
136148
return false
137149
}
138150
return true

internal/mock_api/endpoints/channels/channels_test.go

+43-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ package channels
55
import (
66
"bytes"
77
"encoding/json"
8-
"log"
98
"net/http"
109
"os"
1110
"testing"
@@ -92,6 +91,49 @@ func TestEditors(t *testing.T) {
9291
a.Equal(200, resp.StatusCode)
9392
}
9493

94+
func TestVIPs(t *testing.T) {
95+
a := test_setup.SetupTestEnv(t)
96+
ts := test_server.SetupTestServer(Vips{})
97+
98+
// get
99+
req, _ := http.NewRequest(http.MethodGet, ts.URL+Vips{}.Path(), nil)
100+
q := req.URL.Query()
101+
req.URL.RawQuery = q.Encode()
102+
resp, err := http.DefaultClient.Do(req)
103+
a.Nil(err)
104+
a.Equal(400, resp.StatusCode)
105+
106+
q.Set("broadcaster_id", "1")
107+
q.Set("user_id", "3")
108+
req.URL.RawQuery = q.Encode()
109+
resp, err = http.DefaultClient.Do(req)
110+
a.Nil(err)
111+
a.Equal(200, resp.StatusCode)
112+
113+
// post
114+
req, _ = http.NewRequest(http.MethodPost, ts.URL+Vips{}.Path(), nil)
115+
q.Set("broadcaster_id", "1")
116+
q.Set("user_id", "2")
117+
req.URL.RawQuery = q.Encode()
118+
resp, err = http.DefaultClient.Do(req)
119+
a.Nil(err)
120+
a.Equal(422, resp.StatusCode)
121+
122+
req, _ = http.NewRequest(http.MethodPost, ts.URL+Vips{}.Path(), nil)
123+
q.Set("user_id", "-1")
124+
req.URL.RawQuery = q.Encode()
125+
resp, err = http.DefaultClient.Do(req)
126+
a.Nil(err)
127+
a.Equal(404, resp.StatusCode)
128+
129+
req, _ = http.NewRequest(http.MethodPost, ts.URL+Vips{}.Path(), nil)
130+
q.Del("user_id")
131+
req.URL.RawQuery = q.Encode()
132+
resp, err = http.DefaultClient.Do(req)
133+
a.Nil(err)
134+
a.Equal(400, resp.StatusCode)
135+
}
136+
95137
func TestInformation(t *testing.T) {
96138
a := test_setup.SetupTestEnv(t)
97139
ts := test_server.SetupTestServer(InformationEndpoint{})
@@ -129,7 +171,6 @@ func TestInformation(t *testing.T) {
129171
q.Set("broadcaster_id", "2")
130172
req.URL.RawQuery = q.Encode()
131173
resp, err = http.DefaultClient.Do(req)
132-
log.Print(resp.StatusCode)
133174
a.Nil(err, resp.StatusCode)
134175
a.Equal(401, resp.StatusCode)
135176

0 commit comments

Comments
 (0)