Add conduit endpoints to API
This commit is contained in:
parent
990b1da80c
commit
e1b6b5ce88
|
@ -11,6 +11,7 @@ import (
|
||||||
"go.fifitido.net/twitch/api/channels"
|
"go.fifitido.net/twitch/api/channels"
|
||||||
"go.fifitido.net/twitch/api/charity"
|
"go.fifitido.net/twitch/api/charity"
|
||||||
"go.fifitido.net/twitch/api/chat"
|
"go.fifitido.net/twitch/api/chat"
|
||||||
|
"go.fifitido.net/twitch/api/conduit"
|
||||||
"go.fifitido.net/twitch/api/eventsub"
|
"go.fifitido.net/twitch/api/eventsub"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ type API struct {
|
||||||
ChannelPoints *channelpoints.ChannelPoints
|
ChannelPoints *channelpoints.ChannelPoints
|
||||||
Charity *charity.Charity
|
Charity *charity.Charity
|
||||||
Chat *chat.Chat
|
Chat *chat.Chat
|
||||||
|
Conduit *conduit.Conduit
|
||||||
EventSub *eventsub.EventSub
|
EventSub *eventsub.EventSub
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +47,7 @@ func New() *API {
|
||||||
ChannelPoints: channelpoints.New(client, baseUrl),
|
ChannelPoints: channelpoints.New(client, baseUrl),
|
||||||
Charity: charity.New(client, baseUrl),
|
Charity: charity.New(client, baseUrl),
|
||||||
Chat: chat.New(client, baseUrl),
|
Chat: chat.New(client, baseUrl),
|
||||||
|
Conduit: conduit.New(client, baseUrl),
|
||||||
EventSub: eventsub.New(client, baseUrl),
|
EventSub: eventsub.New(client, baseUrl),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Conduit struct {
|
||||||
|
client *http.Client
|
||||||
|
baseUrl *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(client *http.Client, baseUrl *url.URL) *Conduit {
|
||||||
|
return &Conduit{
|
||||||
|
client: client,
|
||||||
|
baseUrl: baseUrl,
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreateConduitsResponse struct {
|
||||||
|
Data []ConduitData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new conduit.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) CreateConduits(ctx context.Context, shareCount int) (*CreateConduitsResponse, error) {
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits", RawQuery: "share_count=" + fmt.Sprint(shareCount)})
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data CreateConduitsResponse
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Deletes a specified conduit.
|
||||||
|
// Note that it may take some time for Eventsub subscriptions on a deleted conduit to show as disabled when calling Get Eventsub Subscriptions.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) DeleteConduit(ctx context.Context, id string) error {
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits", RawQuery: "id=" + id})
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, endpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/google/go-querystring/query"
|
||||||
|
"go.fifitido.net/twitch/api/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetConduitShardsParams struct {
|
||||||
|
// Conduit ID.
|
||||||
|
ConduitID string `url:"conduit_id"`
|
||||||
|
|
||||||
|
// Status to filter by.
|
||||||
|
Status *Status `url:"status,omitempty"`
|
||||||
|
|
||||||
|
// The cursor used to get the next page of results. The pagination object in the response contains the cursor’s value.
|
||||||
|
Cursor *types.Cursor `url:"cursor,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type GetConduitShardsResponse struct {
|
||||||
|
// List of information about a conduit's shards.
|
||||||
|
Data []Shard `json:"data"`
|
||||||
|
|
||||||
|
// The cursor used to get the next page of results. Use the cursor to set the request’s after query parameter.
|
||||||
|
Pagination types.Pagination `json:"pagination"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets a lists of all shards for a conduit.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) GetConduitShards(ctx context.Context, params *GetConduitShardsParams) (*GetConduitShardsResponse, error) {
|
||||||
|
v, _ := query.Values(params)
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits/shards", RawQuery: v.Encode()})
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data GetConduitShardsResponse
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GetConduitsResponse struct {
|
||||||
|
// List of information about the client’s conduits.
|
||||||
|
Data []ConduitData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the conduits for a client ID.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) GetConduits(ctx context.Context) (*GetConduitsResponse, error) {
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits"})
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data GetConduitsResponse
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
type ConduitData struct {
|
||||||
|
// Conduit ID.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// Number of shards associated with this conduit.
|
||||||
|
ShardCount int `json:"shard_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Shard struct {
|
||||||
|
// Shard ID.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// The shard status. The subscriber receives events only for enabled shards
|
||||||
|
Status Status `json:"status"`
|
||||||
|
|
||||||
|
// The transport details used to send the notifications.
|
||||||
|
Transport *Transport `json:"transport"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Status string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// enabled — The shard is enabled.
|
||||||
|
StatusEnabled Status = "enabled"
|
||||||
|
|
||||||
|
// webhook_callback_verification_pending — The shard is pending verification of the specified callback URL.
|
||||||
|
StatusWebhookCallbackVerificationPending Status = "webhook_callback_verification_pending"
|
||||||
|
|
||||||
|
// webhook_callback_verification_failed — The specified callback URL failed verification.
|
||||||
|
StatusWebhookCallbackVerificationFailed Status = "webhook_callback_verification_failed"
|
||||||
|
|
||||||
|
// notification_failures_exceeded — The notification delivery failure rate was too high.
|
||||||
|
NotificationFailuresExceeded Status = "notification_failures_exceeded"
|
||||||
|
|
||||||
|
// websocket_disconnected — The client closed the connection.
|
||||||
|
WebsocketDisconnected Status = "websocket_disconnected"
|
||||||
|
|
||||||
|
// websocket_failed_ping_pong — The client failed to respond to a ping message.
|
||||||
|
WebsocketFailedPingPong Status = "websocket_failed_ping_pong"
|
||||||
|
|
||||||
|
// websocket_received_inbound_traffic — The client sent a non-pong message.
|
||||||
|
// Clients may only send pong messages (and only in response to a ping message).
|
||||||
|
WebsocketReceivedInboundTraffic Status = "websocket_received_inbound_traffic"
|
||||||
|
|
||||||
|
// websocket_connection_unused — The client failed to subscribe to events within the required time.
|
||||||
|
WebsocketConnectionUnused Status = "websocket_connection_unused"
|
||||||
|
|
||||||
|
// websocket_internal_error — The Twitch WebSocket server experienced an unexpected error.
|
||||||
|
WebsocketInternalError Status = "websocket_internal_error"
|
||||||
|
|
||||||
|
// websocket_network_timeout — The Twitch WebSocket server timed out writing the message to the client.
|
||||||
|
WebsocketNetworkTimeout Status = "websocket_network_timeout"
|
||||||
|
|
||||||
|
// websocket_network_error — The Twitch WebSocket server experienced a network error writing the message to the client.
|
||||||
|
WebsocketnetworkError Status = "websocket_network_error"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Transport struct {
|
||||||
|
// The transport method. Possible values are:
|
||||||
|
//
|
||||||
|
// webhook, websocket
|
||||||
|
Method string `json:"method"`
|
||||||
|
|
||||||
|
// The callback URL where the notifications are sent. Included only if method is set to webhook.
|
||||||
|
Callback *string `json:"callback,omitempty"`
|
||||||
|
|
||||||
|
// The UTC date and time that the WebSocket connection was established. Included only if method is set to websocket.
|
||||||
|
ConnectedAt *time.Time `json:"connected_at,omitempty"`
|
||||||
|
|
||||||
|
// The UTC date and time that the WebSocket connection was lost. Included only if method is set to websocket.
|
||||||
|
DisconnectedAt *time.Time `json:"disconnected_at,omitempty"`
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateConduitShardsRequest struct {
|
||||||
|
// Conduit ID.
|
||||||
|
ConduitID string `json:"conduit_id"`
|
||||||
|
|
||||||
|
// List of Shards to update.
|
||||||
|
Shards []ShardUpdate `json:"shards"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShardUpdate struct {
|
||||||
|
// Shard ID.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// The transport details that you want Twitch to use when sending you notifications.
|
||||||
|
Transport *Transport `json:"transport"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateConduitShardsResponse struct {
|
||||||
|
// List of successful shard updates.
|
||||||
|
Data []ConduitData `json:"data"`
|
||||||
|
|
||||||
|
// List of unsuccessful updates.
|
||||||
|
Errors []UpdateConduitShardsError `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateConduitShardsError struct {
|
||||||
|
// Shard ID.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// The error that occurred while updating the shard.
|
||||||
|
// Possible errors:
|
||||||
|
//
|
||||||
|
// The length of the string in the secret field is not valid.
|
||||||
|
//
|
||||||
|
// The URL in the transport's callback field is not valid. The URL must use the HTTPS protocol and the 443 port number.
|
||||||
|
//
|
||||||
|
// The value specified in the method field is not valid.
|
||||||
|
//
|
||||||
|
// The callback field is required if you specify the webhook transport method.
|
||||||
|
//
|
||||||
|
// The session_id field is required if you specify the WebSocket transport method.
|
||||||
|
//
|
||||||
|
// The websocket session is not connected.
|
||||||
|
//
|
||||||
|
// The shard id is outside of the conduit’s range.
|
||||||
|
Message string `json:"message"`
|
||||||
|
|
||||||
|
// Error codes used to represent a specific error condition while attempting to update shards.
|
||||||
|
Code string `json:"code"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates shard(s) for a conduit.
|
||||||
|
//
|
||||||
|
// NOTE: Shard IDs are indexed starting at 0, so a conduit with a shard_count of 5 will have shards with IDs 0 through 4.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) UpdateConduitShards(ctx context.Context, body *UpdateConduitShardsRequest) (*UpdateConduitShardsResponse, error) {
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits/shards"})
|
||||||
|
|
||||||
|
r, w := io.Pipe()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
} else {
|
||||||
|
w.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, endpoint.String(), r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data UpdateConduitShardsResponse
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
package conduit
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UpdateConduitsRequest struct {
|
||||||
|
// Conduit ID.
|
||||||
|
ID string `json:"id"`
|
||||||
|
|
||||||
|
// The new number of shards for this conduit.
|
||||||
|
ShardCount int `json:"shard_count"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UpdateConduitsResponse struct {
|
||||||
|
// List of information about the client’s conduits.
|
||||||
|
Data []ConduitData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates a conduit’s shard count. To delete shards, update the count to a lower number, and the shards above the count will be deleted.
|
||||||
|
// For example, if the existing shard count is 100, by resetting shard count to 50, shards 50-99 are disabled.
|
||||||
|
//
|
||||||
|
// Requires an app access token.
|
||||||
|
func (c *Conduit) UpdateConduits(ctx context.Context, body *UpdateConduitsRequest) (*UpdateConduitsResponse, error) {
|
||||||
|
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "eventsub/conduits"})
|
||||||
|
|
||||||
|
r, w := io.Pipe()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||||
|
w.CloseWithError(err)
|
||||||
|
} else {
|
||||||
|
w.Close()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, endpoint.String(), r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := c.client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
var data UpdateConduitsResponse
|
||||||
|
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &data, nil
|
||||||
|
}
|
12
ptr_types.go
12
ptr_types.go
|
@ -5,6 +5,7 @@ import (
|
||||||
|
|
||||||
"go.fifitido.net/twitch/api/bits"
|
"go.fifitido.net/twitch/api/bits"
|
||||||
"go.fifitido.net/twitch/api/channelpoints"
|
"go.fifitido.net/twitch/api/channelpoints"
|
||||||
|
"go.fifitido.net/twitch/api/conduit"
|
||||||
"go.fifitido.net/twitch/api/types"
|
"go.fifitido.net/twitch/api/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -161,3 +162,14 @@ func ToAccentColor(s *types.AccentColor) types.AccentColor {
|
||||||
}
|
}
|
||||||
return *s
|
return *s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ConduitStatus(s conduit.Status) *conduit.Status {
|
||||||
|
return &s
|
||||||
|
}
|
||||||
|
|
||||||
|
func ToConduitStatus(s *conduit.Status) conduit.Status {
|
||||||
|
if s == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return *s
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue