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