Skip to content

Commit 78620aa

Browse files
committed
Reformat GQL operations into request and response files
Added a notification channel to the rewards app Redemption errors are now propagated back to the user
1 parent 703c9ec commit 78620aa

File tree

10 files changed

+255
-114
lines changed

10 files changed

+255
-114
lines changed

internal/app/rewards/tui/model.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Model struct {
2121
itemsById map[string]*item
2222
rewardsUpdateChannel chan communitypointschannel.Response
2323
pointsUpdateChannel chan communitypointsuser.PointsSpentData
24+
notificationsChannel chan string
2425
pubsubClient *pubsub.Client
2526
}
2627

@@ -40,6 +41,7 @@ func NewModel(pubsubClient *pubsub.Client, config config.Config, streamer string
4041
itemsById: make(map[string]*item),
4142
rewardsUpdateChannel: make(chan communitypointschannel.Response, 8),
4243
pointsUpdateChannel: make(chan communitypointsuser.PointsSpentData, 8),
44+
notificationsChannel: make(chan string, 8),
4345
}
4446

4547
channelPointsContext, err := channelpointscontext.Get(c.Name, config.AuthToken)
@@ -59,7 +61,7 @@ func NewModel(pubsubClient *pubsub.Client, config config.Config, streamer string
5961
func (m Model) Init() tea.Cmd {
6062
go m.subscribeToRewards()
6163
go m.subscribeToPoints()
62-
return tea.Batch(m.getInitialRewards, m.processPointsUpdates, m.tick())
64+
return tea.Batch(m.getInitialRewards, m.processPointsUpdates, m.processNotificationUpdates, m.tick())
6365
}
6466

6567
func (m Model) View() string {

internal/app/rewards/tui/update.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"github.com/charmbracelet/bubbles/list"
77
tea "github.com/charmbracelet/bubbletea"
8+
"github.com/fatih/color"
89
"log"
910
"time"
1011
"ttv-cli/internal/pkg/twitch/gql/operation/redeemcustomreward"
@@ -15,7 +16,8 @@ import (
1516
type initialRewards []list.Item
1617
type updatedReward communitypointschannel.UpdatedReward
1718
type tick int
18-
type newBalance int
19+
type pointsBalance int
20+
type notification string
1921

2022
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
2123
switch msg := msg.(type) {
@@ -37,10 +39,14 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
3739
}
3840
return m, m.processRewardUpdates
3941

40-
case newBalance:
42+
case pointsBalance:
4143
m.list.Title = fmt.Sprintf("%s's Rewards (%d points)", m.twitchChannel.DisplayName, msg)
4244
return m, m.processPointsUpdates
4345

46+
case notification:
47+
cmd := m.list.NewStatusMessage(string(msg))
48+
return m, tea.Batch(cmd, m.processNotificationUpdates)
49+
4450
case tick:
4551
cmd := m.list.SetItems(m.list.Items()) // Force re-render
4652
return m, tea.Batch(cmd, m.tick())
@@ -54,8 +60,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
5460
return m, cmd
5561
}
5662
go m.redeemReward(selected)
57-
cmd := m.list.NewStatusMessage(fmt.Sprintf("Redeeming '%s'", selected.Title_))
58-
return m, cmd
5963
}
6064

6165
if msg.String() == "ctrl+c" {
@@ -133,7 +137,12 @@ func (m Model) processRewardUpdates() tea.Msg {
133137

134138
func (m Model) processPointsUpdates() tea.Msg {
135139
update := <-m.pointsUpdateChannel
136-
return newBalance(update.Balance.Balance)
140+
return pointsBalance(update.Balance.Balance)
141+
}
142+
143+
func (m Model) processNotificationUpdates() tea.Msg {
144+
update := <-m.notificationsChannel
145+
return notification(update)
137146
}
138147

139148
func (m Model) tick() tea.Cmd {
@@ -155,8 +164,17 @@ func (m Model) redeemReward(i *item) {
155164
input.TextInput = ":)" // FIXME
156165
}
157166

158-
_, err := redeemcustomreward.Redeem(input, m.config.AuthToken)
167+
response, err := redeemcustomreward.Redeem(input, m.config.AuthToken)
159168
if err != nil {
160169
fmt.Println("could not redeem reward: ", err)
161170
}
171+
172+
respError := response.Data.RedeemCommunityPointsCustomReward.Error
173+
if response.Data.RedeemCommunityPointsCustomReward.Error == nil {
174+
m.notificationsChannel <- fmt.Sprintf("Redeemed '%s'", i.Title_)
175+
} else {
176+
style := color.New(color.BgMagenta).SprintfFunc()
177+
msg := redeemcustomreward.ErrorToDisplay(respError.Code)
178+
m.notificationsChannel <- style(" %s ", msg)
179+
}
162180
}

internal/pkg/twitch/gql/operation/channelfollows/channelfollows.go renamed to internal/pkg/twitch/gql/operation/channelfollows/request.go

Lines changed: 0 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package channelfollows
33
import (
44
"encoding/json"
55
"fmt"
6-
"time"
76
"ttv-cli/internal/pkg/twitch/gql"
87
)
98

@@ -43,51 +42,6 @@ func makeRequest() channelFollowsRequest {
4342
}
4443
}
4544

46-
type response struct {
47-
Data struct {
48-
User struct {
49-
Id string `json:"id"`
50-
Follows struct {
51-
Edges []struct {
52-
Cursor string `json:"cursor"`
53-
Node struct {
54-
Id string `json:"id"`
55-
BannerImageURL *string `json:"bannerImageURL"`
56-
DisplayName string `json:"displayName"`
57-
Login string `json:"login"`
58-
ProfileImageURL string `json:"profileImageURL"`
59-
Self struct {
60-
CanFollow bool `json:"canFollow"`
61-
Follower struct {
62-
DisableNotifications bool `json:"disableNotifications"`
63-
FollowedAt time.Time `json:"followedAt"`
64-
Typename string `json:"__typename"`
65-
} `json:"follower"`
66-
Typename string `json:"__typename"`
67-
Friendship interface{} `json:"friendship"`
68-
} `json:"self"`
69-
Typename string `json:"__typename"`
70-
Activity interface{} `json:"activity"`
71-
Availability interface{} `json:"availability"`
72-
} `json:"node"`
73-
Typename string `json:"__typename"`
74-
} `json:"edges"`
75-
PageInfo struct {
76-
HasNextPage bool `json:"hasNextPage"`
77-
Typename string `json:"__typename"`
78-
} `json:"pageInfo"`
79-
Typename string `json:"__typename"`
80-
} `json:"follows"`
81-
Typename string `json:"__typename"`
82-
} `json:"user"`
83-
} `json:"data"`
84-
Extensions struct {
85-
DurationMilliseconds int `json:"durationMilliseconds"`
86-
OperationName string `json:"operationName"`
87-
RequestID string `json:"requestID"`
88-
} `json:"extensions"`
89-
}
90-
9145
type ChannelFollow struct {
9246
DisplayName string
9347
Login string
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package channelfollows
2+
3+
import "time"
4+
5+
type response struct {
6+
Data struct {
7+
User struct {
8+
Id string `json:"id"`
9+
Follows struct {
10+
Edges []struct {
11+
Cursor string `json:"cursor"`
12+
Node struct {
13+
Id string `json:"id"`
14+
BannerImageURL *string `json:"bannerImageURL"`
15+
DisplayName string `json:"displayName"`
16+
Login string `json:"login"`
17+
ProfileImageURL string `json:"profileImageURL"`
18+
Self struct {
19+
CanFollow bool `json:"canFollow"`
20+
Follower struct {
21+
DisableNotifications bool `json:"disableNotifications"`
22+
FollowedAt time.Time `json:"followedAt"`
23+
Typename string `json:"__typename"`
24+
} `json:"follower"`
25+
Typename string `json:"__typename"`
26+
Friendship interface{} `json:"friendship"`
27+
} `json:"self"`
28+
Typename string `json:"__typename"`
29+
Activity interface{} `json:"activity"`
30+
Availability interface{} `json:"availability"`
31+
} `json:"node"`
32+
Typename string `json:"__typename"`
33+
} `json:"edges"`
34+
PageInfo struct {
35+
HasNextPage bool `json:"hasNextPage"`
36+
Typename string `json:"__typename"`
37+
} `json:"pageInfo"`
38+
Typename string `json:"__typename"`
39+
} `json:"follows"`
40+
Typename string `json:"__typename"`
41+
} `json:"user"`
42+
} `json:"data"`
43+
Extensions struct {
44+
DurationMilliseconds int `json:"durationMilliseconds"`
45+
OperationName string `json:"operationName"`
46+
RequestID string `json:"requestID"`
47+
} `json:"extensions"`
48+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package channelpointscontext
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"ttv-cli/internal/pkg/twitch/gql"
7+
)
8+
9+
type persistedQuery struct {
10+
Version int `json:"version"`
11+
Sha256Hash string `json:"sha256Hash"`
12+
}
13+
14+
type extensions struct {
15+
PersistedQuery persistedQuery `json:"persistedQuery"`
16+
}
17+
18+
type variables struct {
19+
ChannelLogin string `json:"channelLogin"`
20+
}
21+
22+
type request struct {
23+
OperationName string `json:"operationName"`
24+
Variables variables `json:"variables"`
25+
Extensions extensions `json:"extensions"`
26+
}
27+
28+
func makeRequest(channelLogin string) request {
29+
return request{
30+
OperationName: "ChannelPointsContext",
31+
Variables: variables{
32+
ChannelLogin: channelLogin,
33+
},
34+
Extensions: extensions{
35+
PersistedQuery: persistedQuery{
36+
Version: 1,
37+
Sha256Hash: "9988086babc615a918a1e9a722ff41d98847acac822645209ac7379eecb27152",
38+
},
39+
},
40+
}
41+
}
42+
43+
func Get(channelLogin string, authToken string) (Response, error) {
44+
req := makeRequest(channelLogin)
45+
resp, err := gql.PostWithAuth(req, authToken)
46+
if err != nil {
47+
return Response{}, fmt.Errorf("error with GQL request: %w", err)
48+
}
49+
50+
var c Response
51+
if err := json.Unmarshal(resp, &c); err != nil {
52+
return c, fmt.Errorf("error unmarshalling GQL response: %w", err)
53+
}
54+
55+
return c, err
56+
}

internal/pkg/twitch/gql/operation/channelpointscontext/channelpointscontext.go renamed to internal/pkg/twitch/gql/operation/channelpointscontext/response.go

Lines changed: 2 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,8 @@
11
package channelpointscontext
22

3-
import (
4-
"encoding/json"
5-
"fmt"
6-
"time"
7-
"ttv-cli/internal/pkg/twitch/gql"
8-
)
3+
import "time"
94

10-
type persistedQuery struct {
11-
Version int `json:"version"`
12-
Sha256Hash string `json:"sha256Hash"`
13-
}
14-
15-
type extensions struct {
16-
PersistedQuery persistedQuery `json:"persistedQuery"`
17-
}
18-
19-
type variables struct {
20-
ChannelLogin string `json:"channelLogin"`
21-
}
22-
23-
type request struct {
24-
OperationName string `json:"operationName"`
25-
Variables variables `json:"variables"`
26-
Extensions extensions `json:"extensions"`
27-
}
28-
29-
func makeRequest(channelLogin string) request {
30-
return request{
31-
OperationName: "ChannelPointsContext",
32-
Variables: variables{
33-
ChannelLogin: channelLogin,
34-
},
35-
Extensions: extensions{
36-
PersistedQuery: persistedQuery{
37-
Version: 1,
38-
Sha256Hash: "9988086babc615a918a1e9a722ff41d98847acac822645209ac7379eecb27152",
39-
},
40-
},
41-
}
42-
}
43-
44-
type ChannelPointsContext struct {
5+
type Response struct {
456
Data struct {
467
Community struct {
478
Id string `json:"id"`
@@ -180,18 +141,3 @@ type ChannelPointsContext struct {
180141
RequestID string `json:"requestID"`
181142
} `json:"extensions"`
182143
}
183-
184-
func Get(channelLogin string, authToken string) (ChannelPointsContext, error) {
185-
req := makeRequest(channelLogin)
186-
resp, err := gql.PostWithAuth(req, authToken)
187-
if err != nil {
188-
return ChannelPointsContext{}, fmt.Errorf("error with GQL request: %w", err)
189-
}
190-
191-
var c ChannelPointsContext
192-
if err := json.Unmarshal(resp, &c); err != nil {
193-
return c, fmt.Errorf("error unmarshalling GQL response: %w", err)
194-
}
195-
196-
return c, err
197-
}

internal/pkg/twitch/gql/operation/communitymomentcalloutclaim/communitymomentcalloutclaim.go renamed to internal/pkg/twitch/gql/operation/communitymomentcalloutclaim/request.go

File renamed without changes.

internal/pkg/twitch/gql/operation/redeemcustomreward/redeemcustomreward.go renamed to internal/pkg/twitch/gql/operation/redeemcustomreward/request.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package redeemcustomreward
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"ttv-cli/internal/pkg/twitch/gql"
67
"ttv-cli/internal/pkg/utils"
@@ -56,16 +57,21 @@ func makeRequest(input Input) (request, error) {
5657
}, nil
5758
}
5859

59-
func Redeem(input Input, authToken string) ([]byte, error) {
60+
func Redeem(input Input, authToken string) (Response, error) {
61+
var response Response
6062
req, err := makeRequest(input)
6163
if err != nil {
62-
return nil, fmt.Errorf("error generating GQL request: %w", err)
64+
return response, fmt.Errorf("error generating GQL request: %w", err)
6365
}
6466

65-
resp, err := gql.PostWithAuth(req, authToken)
67+
body, err := gql.PostWithAuth(req, authToken)
6668
if err != nil {
67-
return nil, fmt.Errorf("error with GQL request: %w", err)
69+
return response, fmt.Errorf("error with GQL request: %w", err)
6870
}
6971

70-
return resp, nil
72+
if err := json.Unmarshal(body, &response); err != nil {
73+
return response, fmt.Errorf("could not unmarshal response: %s, error: %w", string(body), err)
74+
}
75+
76+
return response, nil
7177
}

0 commit comments

Comments
 (0)