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/charity"
 | 
			
		||||
	"go.fifitido.net/twitch/api/chat"
 | 
			
		||||
	"go.fifitido.net/twitch/api/conduit"
 | 
			
		||||
	"go.fifitido.net/twitch/api/eventsub"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -27,6 +28,7 @@ type API struct {
 | 
			
		|||
	ChannelPoints *channelpoints.ChannelPoints
 | 
			
		||||
	Charity       *charity.Charity
 | 
			
		||||
	Chat          *chat.Chat
 | 
			
		||||
	Conduit       *conduit.Conduit
 | 
			
		||||
	EventSub      *eventsub.EventSub
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +47,7 @@ func New() *API {
 | 
			
		|||
		ChannelPoints: channelpoints.New(client, baseUrl),
 | 
			
		||||
		Charity:       charity.New(client, baseUrl),
 | 
			
		||||
		Chat:          chat.New(client, baseUrl),
 | 
			
		||||
		Conduit:       conduit.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/channelpoints"
 | 
			
		||||
	"go.fifitido.net/twitch/api/conduit"
 | 
			
		||||
	"go.fifitido.net/twitch/api/types"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -161,3 +162,14 @@ func ToAccentColor(s *types.AccentColor) types.AccentColor {
 | 
			
		|||
	}
 | 
			
		||||
	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