mirror of
https://github.com/Luzifer/twitch-bot.git
synced 2024-12-20 20:01:17 +00:00
[eventsub] Fix: Properly handle 409 error
by fetching the existing subscription instead of failing to access the expected response which is not there in case of a collision Signed-off-by: Knut Ahlers <knut@ahlers.me>
This commit is contained in:
parent
0e4a963bc7
commit
1d4cbd9a66
1 changed files with 54 additions and 6 deletions
|
@ -6,10 +6,12 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/hashstructure/v2"
|
"github.com/mitchellh/hashstructure/v2"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Collection of known EventSub event-types
|
// Collection of known EventSub event-types
|
||||||
|
@ -277,8 +279,10 @@ func (c *Client) createEventSubSubscriptionWebsocket(ctx context.Context, sub ev
|
||||||
|
|
||||||
func (c *Client) createEventSubSubscription(ctx context.Context, auth AuthType, sub eventSubSubscription) (*eventSubSubscription, error) {
|
func (c *Client) createEventSubSubscription(ctx context.Context, auth AuthType, sub eventSubSubscription) (*eventSubSubscription, error) {
|
||||||
var (
|
var (
|
||||||
buf = new(bytes.Buffer)
|
buf = new(bytes.Buffer)
|
||||||
resp struct {
|
err error
|
||||||
|
mustFetchSubsctiption bool
|
||||||
|
resp struct {
|
||||||
Total int64 `json:"total"`
|
Total int64 `json:"total"`
|
||||||
Data []eventSubSubscription `json:"data"`
|
Data []eventSubSubscription `json:"data"`
|
||||||
Pagination struct {
|
Pagination struct {
|
||||||
|
@ -287,11 +291,16 @@ func (c *Client) createEventSubSubscription(ctx context.Context, auth AuthType,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := json.NewEncoder(buf).Encode(sub); err != nil {
|
conHash, err := sub.Condition.Hash()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("hashing input condition: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = json.NewEncoder(buf).Encode(sub); err != nil {
|
||||||
return nil, errors.Wrap(err, "assemble subscribe payload")
|
return nil, errors.Wrap(err, "assemble subscribe payload")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := c.Request(ctx, ClientRequestOpts{
|
if err = c.Request(ctx, ClientRequestOpts{
|
||||||
AuthType: auth,
|
AuthType: auth,
|
||||||
Body: buf,
|
Body: buf,
|
||||||
Method: http.MethodPost,
|
Method: http.MethodPost,
|
||||||
|
@ -301,6 +310,7 @@ func (c *Client) createEventSubSubscription(ctx context.Context, auth AuthType,
|
||||||
ValidateFunc: func(opts ClientRequestOpts, resp *http.Response) error {
|
ValidateFunc: func(opts ClientRequestOpts, resp *http.Response) error {
|
||||||
if resp.StatusCode == http.StatusConflict {
|
if resp.StatusCode == http.StatusConflict {
|
||||||
// This is fine: We needed that subscription, it exists
|
// This is fine: We needed that subscription, it exists
|
||||||
|
mustFetchSubsctiption = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,8 +318,46 @@ func (c *Client) createEventSubSubscription(ctx context.Context, auth AuthType,
|
||||||
return ValidateStatus(opts, resp)
|
return ValidateStatus(opts, resp)
|
||||||
},
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, errors.Wrap(err, "executing request")
|
return nil, fmt.Errorf("creating subscription: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &resp.Data[0], nil
|
if mustFetchSubsctiption {
|
||||||
|
params := make(url.Values)
|
||||||
|
params.Set("status", "enabled")
|
||||||
|
params.Set("type", sub.Type)
|
||||||
|
|
||||||
|
if err = c.Request(ctx, ClientRequestOpts{
|
||||||
|
AuthType: auth,
|
||||||
|
Method: http.MethodGet,
|
||||||
|
OKStatus: http.StatusOK,
|
||||||
|
Out: &resp,
|
||||||
|
URL: fmt.Sprintf("https://api.twitch.tv/helix/eventsub/subscriptions?%s", params.Encode()),
|
||||||
|
}); err != nil {
|
||||||
|
return nil, fmt.Errorf("fetching subscription: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range resp.Data {
|
||||||
|
s := resp.Data[i]
|
||||||
|
|
||||||
|
if s.Type != sub.Type || s.Version != sub.Version {
|
||||||
|
// Not the subscription we're searching for
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
sConHash, err := s.Condition.Hash()
|
||||||
|
if err != nil {
|
||||||
|
logrus.WithError(err).Error("hashing eventsub subscription condition")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if sConHash != conHash {
|
||||||
|
// Different conditions
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return &s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("no subscription matching input found")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue