Add context to all implemented endpoints
This commit is contained in:
parent
4b44064fe5
commit
616cb935a0
|
@ -1,7 +1,9 @@
|
|||
package ads
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
@ -36,18 +38,23 @@ type GetAdScheduleData struct {
|
|||
//
|
||||
// Requires a user access token that includes the channel:read:ads scope.
|
||||
// The user_id in the user access token must match the broadcaster_id.
|
||||
func (e *Ads) GetAdSchedule(broadcasterID string) (*GetAdScheduleResponse, error) {
|
||||
func (e *Ads) GetAdSchedule(ctx context.Context, broadcasterID string) (*GetAdScheduleResponse, error) {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "channels/ads", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
resp, err := e.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetAdScheduleResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package ads
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
@ -27,18 +29,23 @@ type SnoozeNextAdData struct {
|
|||
//
|
||||
// Requires a user access token that includes the channel:manage:ads scope.
|
||||
// The user_id in the user access token must match the broadcaster_id.
|
||||
func (e *Ads) SnoozeNextAd(broadcasterID string) (*SnoozeNextAdResponse, error) {
|
||||
func (e *Ads) SnoozeNextAd(ctx context.Context, broadcasterID string) (*SnoozeNextAdResponse, error) {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "channels/ads/schedule/snooze", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
resp, err := e.client.Post(endpoint.String(), "application/json", nil)
|
||||
req, err := http.NewRequest(http.MethodPost, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data SnoozeNextAdResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package ads
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
|
@ -39,28 +41,33 @@ type StartCommercialData struct {
|
|||
// NOTE: Only the broadcaster may start a commercial; the broadcaster’s editors and moderators may not start commercials on behalf of the broadcaster.
|
||||
//
|
||||
// Requires a user access token that includes the channel:edit:commercial scope.
|
||||
func (e *Ads) StartCommercial(req *StartCommercialRequest) (*StartCommercialResponse, error) {
|
||||
func (e *Ads) StartCommercial(ctx context.Context, body *StartCommercialRequest) (*StartCommercialResponse, error) {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "channels/commercial"})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := e.client.Post(endpoint.String(), "application/json", r)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data StartCommercialResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package analytics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -78,19 +80,24 @@ type ExtensionAnalyticsReport struct {
|
|||
// Learn More: https://dev.twitch.tv/docs/insights
|
||||
//
|
||||
// Requires a user access token that includes the analytics:read:extensions scope.
|
||||
func (e *Analytics) GetExtensionAnalytics(params GetExtensionAnalyticsParams) (*GetExtensionAnalyticsResponse, error) {
|
||||
func (e *Analytics) GetExtensionAnalytics(ctx context.Context, params GetExtensionAnalyticsParams) (*GetExtensionAnalyticsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "analytics/extensions", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := e.client.Get(endpoint.String())
|
||||
req, err := http.NewRequest(http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetExtensionAnalyticsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package analytics
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -79,19 +81,24 @@ type GameAnalyticsReport struct {
|
|||
// Learn more: https://dev.twitch.tv/docs/insights
|
||||
//
|
||||
// Requires a user access token that includes the analytics:read:games scope.
|
||||
func (e *Analytics) GetGameAnalytics(params GetGameAnalyticsParams) (*GetGameAnalyticsResponse, error) {
|
||||
func (e *Analytics) GetGameAnalytics(ctx context.Context, params GetGameAnalyticsParams) (*GetGameAnalyticsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "analytics/games", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := e.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetGameAnalyticsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package bits
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -66,19 +68,24 @@ type LeaderboardEntry struct {
|
|||
// Gets the Bits leaderboard for the authenticated broadcaster.
|
||||
//
|
||||
// Requires a user access token that includes the bits:read scope.
|
||||
func (b *Bits) GetBitsLeaderboard(params *GetBitsLeaderboardParams) (*GetBitsLeaderboardResponse, error) {
|
||||
func (b *Bits) GetBitsLeaderboard(ctx context.Context, params *GetBitsLeaderboardParams) (*GetBitsLeaderboardResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := b.baseUrl.ResolveReference(&url.URL{Path: "bits/leaderboard", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := b.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := b.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetBitsLeaderboardResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package bits
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
@ -79,18 +81,23 @@ type CheermoteImageSizes struct {
|
|||
// Gets a list of Cheermotes that users can use to cheer Bits in any Bits-enabled channel’s chat room. Cheermotes are animated emotes that viewers can assign Bits to.
|
||||
//
|
||||
// Requires an app access token or user access token.
|
||||
func (b *Bits) GetCheermotes(broadcasterID string) (*GetCheermotesResponse, error) {
|
||||
func (b *Bits) GetCheermotes(ctx context.Context, broadcasterID string) (*GetCheermotesResponse, error) {
|
||||
endpoint := b.baseUrl.ResolveReference(&url.URL{Path: "bits/cheermotes", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
resp, err := b.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := b.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetCheermotesResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package bits
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -93,19 +95,24 @@ type ProductDataCost struct {
|
|||
// Gets an extension’s list of transactions. A transaction records the exchange of a currency (for example, Bits) for a digital product.
|
||||
//
|
||||
// Requires an app access token.
|
||||
func (b *Bits) GetExtensionTransactions(params *GetExtensionTransactionsParams) (*GetExtensionTransactionsResponse, error) {
|
||||
func (b *Bits) GetExtensionTransactions(ctx context.Context, params *GetExtensionTransactionsParams) (*GetExtensionTransactionsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := b.baseUrl.ResolveReference(&url.URL{Path: "extensions/transactions", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := b.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := b.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetExtensionTransactionsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
|
@ -67,28 +69,33 @@ type CreateCustomRewardsResponse struct {
|
|||
// Creates a Custom Reward in the broadcaster’s channel. The maximum number of custom rewards per channel is 50, which includes both enabled and disabled rewards.
|
||||
//
|
||||
// Requires a user access token that includes the channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) CreateCustomRewards(broadcastID string, req *CreateCustomRewardsRequest) (*CreateCustomRewardsResponse, error) {
|
||||
func (c *ChannelPoints) CreateCustomRewards(ctx context.Context, broadcastID string, body *CreateCustomRewardsRequest) (*CreateCustomRewardsResponse, error) {
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards", RawQuery: "broadcaster_id=" + broadcastID})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := c.client.Post(endpoint.String(), "application/json", r)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data CreateCustomRewardsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
|
@ -20,20 +21,22 @@ type DeleteCustomRewardParams struct {
|
|||
// The app used to create the reward is the only app that may delete it.
|
||||
// If the reward’s redemption status is UNFULFILLED at the time the reward is deleted, its redemption status is marked as FULFILLED.
|
||||
//
|
||||
// / Requires a user access token that includes the channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) DeleteCustomReward(params *DeleteCustomRewardParams) error {
|
||||
// Requires a user access token that includes the channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) DeleteCustomReward(ctx context.Context, params *DeleteCustomRewardParams) error {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Do(&http.Request{
|
||||
Method: http.MethodDelete,
|
||||
URL: endpoint,
|
||||
})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
|
@ -33,19 +35,24 @@ type GetCustomRewardResponse struct {
|
|||
// NOTE: A channel may offer a maximum of 50 rewards, which includes both enabled and disabled rewards.
|
||||
//
|
||||
// Requires a user access token that includes the channel:read:redemptions or channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) GetCustomReward(params *GetCustomRewardParams) (*GetCustomRewardResponse, error) {
|
||||
func (c *ChannelPoints) GetCustomReward(ctx context.Context, params *GetCustomRewardParams) (*GetCustomRewardResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetCustomRewardResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
|
@ -49,19 +51,24 @@ type GetCustomRewardRedemptionResponse struct {
|
|||
// Gets a list of redemptions for the specified custom reward. The app used to create the reward is the only app that may get the redemptions.
|
||||
//
|
||||
// Requires a user access token that includes the channel:read:redemptions or channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) GetCustomRewardRedemption(params *GetCustomRewardRedemptionParams) (*GetCustomRewardRedemptionResponse, error) {
|
||||
func (c *ChannelPoints) GetCustomRewardRedemption(ctx context.Context, params *GetCustomRewardRedemptionParams) (*GetCustomRewardRedemptionResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards/redemptions", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetCustomRewardRedemptionResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -79,33 +80,34 @@ type UpdateCustomRewardResponse struct {
|
|||
// Updates a custom reward. The app used to create the reward is the only app that may update the reward.
|
||||
//
|
||||
// Requires a user access token that includes the channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) UpdateCustomReward(params *UpdateCustomRewardParams, req *UpdateCustomRewardRequest) (*UpdateCustomRewardResponse, error) {
|
||||
v, _ := query.Values(req)
|
||||
func (c *ChannelPoints) UpdateCustomReward(ctx context.Context, params *UpdateCustomRewardParams, body *UpdateCustomRewardRequest) (*UpdateCustomRewardResponse, error) {
|
||||
v, _ := query.Values(body)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards", RawQuery: v.Encode()})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := c.client.Do(&http.Request{
|
||||
Method: http.MethodPatch,
|
||||
URL: endpoint,
|
||||
Body: r,
|
||||
})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data UpdateCustomRewardResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package channelpoints
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -39,33 +40,34 @@ type UpdateRedemptionStatusResponse struct {
|
|||
// The app used to create the reward is the only app that may update the redemption.
|
||||
//
|
||||
// Requires a user access token that includes the channel:manage:redemptions scope.
|
||||
func (c *ChannelPoints) UpdateRedemptionStatus(params *UpdateRedemptionStatusParams, req *UpdateRedemptionStatusRequest) (*UpdateRedemptionStatusResponse, error) {
|
||||
v, _ := query.Values(req)
|
||||
func (c *ChannelPoints) UpdateRedemptionStatus(ctx context.Context, params *UpdateRedemptionStatusParams, body *UpdateRedemptionStatusRequest) (*UpdateRedemptionStatusResponse, error) {
|
||||
v, _ := query.Values(body)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channel_points/custom_rewards/redemptions", RawQuery: v.Encode()})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := c.client.Do(&http.Request{
|
||||
Method: http.MethodPatch,
|
||||
URL: endpoint,
|
||||
Body: r,
|
||||
})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data UpdateRedemptionStatusResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
@ -25,18 +27,23 @@ type ChannelEditor struct {
|
|||
// Gets the broadcaster’s list editors.
|
||||
//
|
||||
// Requires a user access token that includes the channel:read:editors scope.
|
||||
func (c *Channels) GetChannelEditors(broadcasterID string) (*GetChannelEditorsResponse, error) {
|
||||
func (c *Channels) GetChannelEditors(ctx context.Context, broadcasterID string) (*GetChannelEditorsResponse, error) {
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channels/editors", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetChannelEditorsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -67,19 +69,24 @@ type ChannelFollower struct {
|
|||
// This endpoint will return specific follower information only if both of the above are true.
|
||||
// If a scope is not provided or the user isn’t the broadcaster or a moderator for the specified channel,
|
||||
// only the total follower count will be included in the response.
|
||||
func (c *Channels) GetChannelFollowers(params *GetChannelFollowersParams) (*GetChannelFollowersResponse, error) {
|
||||
func (c *Channels) GetChannelFollowers(ctx context.Context, params *GetChannelFollowersParams) (*GetChannelFollowersResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channels/followers", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetChannelFollowersResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
|
@ -66,19 +68,24 @@ type ChannelInformation struct {
|
|||
// Gets information about one or more channels.
|
||||
//
|
||||
// Requires an app access token or user access token.
|
||||
func (c *Channels) GetChannelInformation(params *GetChannelInformationParams) (*GetChannelInformdationResponse, error) {
|
||||
func (c *Channels) GetChannelInformation(ctx context.Context, params *GetChannelInformationParams) (*GetChannelInformdationResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channels", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetChannelInformdationResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
|
@ -58,19 +60,24 @@ type FollowedChannel struct {
|
|||
// Gets a list of broadcasters that the specified user follows. You can also use this endpoint to see whether a user follows a specific broadcaster.
|
||||
//
|
||||
// Requires a user access token that includes the user:read:follows scope.
|
||||
func (c *Channels) GetFollowedChannels(params *GetFollowedChannelsParams) (*GetFollowedChannelsResponse, error) {
|
||||
func (c *Channels) GetFollowedChannels(ctx context.Context, params *GetFollowedChannelsParams) (*GetFollowedChannelsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "users/follows", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetFollowedChannelsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package channels
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
@ -52,24 +53,27 @@ type ModifyContentClassificationLabel struct {
|
|||
// Updates a channel’s properties.
|
||||
//
|
||||
// Requires a user access token that includes the channel:manage:broadcast scope.
|
||||
func (c *Channels) ModifyChannelInformation(broadcasterID string, req *ModifyChannelInformationRequest) error {
|
||||
func (c *Channels) ModifyChannelInformation(ctx context.Context, broadcasterID string, body *ModifyChannelInformationRequest) error {
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "channels", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
if err := json.NewEncoder(w).Encode(body); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
_, err := c.client.Do(&http.Request{
|
||||
Method: http.MethodPatch,
|
||||
URL: endpoint,
|
||||
Body: r,
|
||||
})
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
if _, err := c.client.Do(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package charity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"go.fifitido.net/twitch/api/types"
|
||||
|
@ -52,18 +54,23 @@ type CharityCampaign struct {
|
|||
// subscribe to the channel.charity_campaign.progress subscription type.
|
||||
//
|
||||
// Requires a user access token that includes the channel:read:charity scope.
|
||||
func (c *Charity) GetCharityCampaign(broadcasterID string) (*GetCharityCampaignResponse, error) {
|
||||
func (c *Charity) GetCharityCampaign(ctx context.Context, broadcasterID string) (*GetCharityCampaignResponse, error) {
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "charity/campaigns", RawQuery: "broadcaster_id=" + broadcasterID})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
res, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetCharityCampaignResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package charity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
|
@ -56,17 +58,22 @@ type CharityCampaignDonation struct {
|
|||
// To receive events as donations occur, subscribe to the channel.charity_campaign.donate subscription type.
|
||||
//
|
||||
// Requires a user access token that includes the channel:read:charity scope.
|
||||
func (c *Charity) GetCharityCampaignDonations(params *GetCharityCampaignDonationsParams) (*GetCharityCampaignDonationsResponse, error) {
|
||||
func (c *Charity) GetCharityCampaignDonations(ctx context.Context, params *GetCharityCampaignDonationsParams) (*GetCharityCampaignDonationsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := c.baseUrl.ResolveReference(&url.URL{Path: "charity/campaigns/donations", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := c.client.Get(endpoint.String())
|
||||
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
|
||||
}
|
||||
|
||||
var respBody GetCharityCampaignDonationsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
|
||||
if err := json.NewDecoder(res.Body).Decode(&respBody); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type CreateEventSubSubscriptionRequest struct {
|
||||
// The type of subscription to create.
|
||||
SubscriptionType
|
||||
|
||||
// A JSON object that contains the parameter values that are specific to the specified subscription type.
|
||||
//For the object’s required and optional fields, see the subscription type’s documentation.
|
||||
Condition Condition `json:"condition"`
|
||||
|
||||
// The transport details that you want Twitch to use when sending you notifications.
|
||||
Transport *Transport `json:"transport"`
|
||||
}
|
||||
|
||||
type CreateEventSubSubscriptionResponse struct {
|
||||
// A list that contains the single subscription that you created.
|
||||
Data []*Subscription `json:"data"`
|
||||
|
||||
// The total number of subscriptions you’ve created.
|
||||
Total int `json:"total"`
|
||||
|
||||
// The sum of all of your subscription costs. Learn More: https://dev.twitch.tv/docs/eventsub/manage-subscriptions/#subscription-limits
|
||||
TotalCost int `json:"total_cost"`
|
||||
|
||||
// The maximum total cost that you’re allowed to incur for all subscriptions you create.
|
||||
MaxTotalCost int `json:"max_total_cost"`
|
||||
}
|
||||
|
||||
// Creates an EventSub subscription.
|
||||
//
|
||||
// If you use webhooks to receive events, the request must specify an app access token.
|
||||
// The request will fail if you use a user access token. If the subscription type requires user authorization,
|
||||
// the user must have granted your app (client ID) permissions to receive those events before you subscribe to them.
|
||||
// For example, to subscribe to channel.subscribe events, your app must get a user access token that includes the
|
||||
// channel:read:subscriptions scope, which adds the required permission to your app access token’s client ID.
|
||||
//
|
||||
// If you use WebSockets to receive events, the request must specify a user access token.
|
||||
// The request will fail if you use an app access token. If the subscription type requires user authorization,
|
||||
// the token must include the required scope. However, if the subscription type doesn’t include user authorization,
|
||||
// the token may include any scopes or no scopes.
|
||||
//
|
||||
// If you use Conduits to receive events, the request must specify an app access token.
|
||||
// The request will fail if you use a user access token.
|
||||
func (e *EventSub) CreateEventSubSubscription(ctx context.Context, body *CreateEventSubSubscriptionRequest) (*CreateEventSubSubscriptionResponse, error) {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions"})
|
||||
|
||||
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.MethodPost, endpoint.String(), r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data CreateEventSubSubscriptionResponse
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
type CreateSubscriptionRequest struct {
|
||||
SubscriptionType
|
||||
Condition Condition `json:"condition"`
|
||||
Transport *Transport `json:"transport"`
|
||||
}
|
||||
|
||||
type CreateSubscriptionResponse struct {
|
||||
Data []*Subscription `json:"data"`
|
||||
Total int `json:"total"`
|
||||
TotalCost int `json:"total_cost"`
|
||||
MaxTotalCost int `json:"max_total_cost"`
|
||||
}
|
||||
|
||||
func (e *EventSub) CreateSubscription(req *CreateSubscriptionRequest) (*CreateSubscriptionResponse, error) {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions"})
|
||||
|
||||
r, w := io.Pipe()
|
||||
|
||||
go func() {
|
||||
if err := json.NewEncoder(w).Encode(req); err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
resp, err := e.client.Post(endpoint.String(), "application/json", r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
var data CreateSubscriptionResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// Deletes an EventSub subscription.
|
||||
//
|
||||
// If you use webhooks to receive events, the request must specify an app access token.
|
||||
// The request will fail if you use a user access token.
|
||||
//
|
||||
// If you use WebSockets to receive events, the request must specify a user access token.
|
||||
// The request will fail if you use an app access token. The token may include any scopes.
|
||||
func (e *EventSub) DeleteEventSubSubscription(ctx context.Context, id string) error {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions", RawQuery: "id=" + id})
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := e.client.Do(req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func (e *EventSub) DeleteSubscription(id string) error {
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions", RawQuery: "id=" + id})
|
||||
|
||||
_, err := e.client.Do(&http.Request{
|
||||
Method: http.MethodDelete,
|
||||
URL: endpoint,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
"go.fifitido.net/twitch/api/types"
|
||||
)
|
||||
|
||||
type GetEventSubSubscriptionsParams struct {
|
||||
// Filter subscriptions by its status.
|
||||
Status *Status `url:"status,omitempty"`
|
||||
|
||||
// Filter subscriptions by subscription type. For a list of subscription types.
|
||||
// See Subscription Types: https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#subscription-types
|
||||
Type *SubscriptionType `url:"type,omitempty"`
|
||||
|
||||
// Filter subscriptions by user ID.
|
||||
// The response contains subscriptions where this ID matches a user ID that you specified in the Condition object when you created the subscription.
|
||||
UserID *string `url:"user_id,omitempty"`
|
||||
|
||||
// The cursor used to get the next page of results.
|
||||
// The pagination object in the response contains the cursor's value.
|
||||
After *types.Cursor `url:"after,omitempty"`
|
||||
}
|
||||
|
||||
type GetEventSubSubscriptionsResponse struct {
|
||||
// The list of subscriptions. The list is ordered by the oldest subscription first.
|
||||
// The list is empty if the client hasn't created subscriptions or there are no subscriptions that match the specified filter criteria.
|
||||
Data []Subscription `json:"data"`
|
||||
|
||||
// The total number of subscriptions that you've created.
|
||||
Total int `json:"total"`
|
||||
|
||||
// The sum of all of your subscription costs.
|
||||
// Learn More: https://dev.twitch.tv/docs/eventsub/manage-subscriptions/#subscription-limits
|
||||
TotalCost int `json:"total_cost"`
|
||||
|
||||
// The maximum total cost that you're allowed to incur for all subscriptions that you create.
|
||||
MaxTotalCost int `json:"max_total_cost"`
|
||||
|
||||
// An object that contains the cursor used to get the next page of subscriptions.
|
||||
// The object is empty if there are no more pages to get.
|
||||
// The number of subscriptions returned per page is undertermined.
|
||||
Pagination types.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
// Gets a list of EventSub subscriptions that the client in the access token created.
|
||||
//
|
||||
// If you use webhooks to receive events, the request must specify an app access token.
|
||||
// The request will fail if you use a user access token.
|
||||
//
|
||||
// If you use WebSockets to receive events, the request must specify a user access token.
|
||||
// The request will fail if you use an app access token. The token may include any scopes.
|
||||
func (e *EventSub) GetEventSubSubscriptions(ctx context.Context, params *GetEventSubSubscriptionsParams) (*GetEventSubSubscriptionsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions", RawQuery: v.Encode()})
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint.String(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
res, err := e.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer res.Body.Close()
|
||||
|
||||
var data GetEventSubSubscriptionsResponse
|
||||
if err := json.NewDecoder(res.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-querystring/query"
|
||||
"go.fifitido.net/twitch/api/types"
|
||||
)
|
||||
|
||||
type GetSubscriptionsParams struct {
|
||||
Status *Status `url:"status,omitempty"`
|
||||
Type *SubscriptionType `url:"type,omitempty"`
|
||||
UserID *string `url:"user_id,omitempty"`
|
||||
After *types.Cursor `url:"after,omitempty"`
|
||||
}
|
||||
|
||||
type GetSubscriptionsResponse struct {
|
||||
Data []Subscription `json:"data"`
|
||||
Total int `json:"total"`
|
||||
TotalCost int `json:"total_cost"`
|
||||
MaxTotalCost int `json:"max_total_cost"`
|
||||
Pagination types.Pagination `json:"pagination"`
|
||||
}
|
||||
|
||||
func (e *EventSub) GetSubscriptions(params *GetSubscriptionsParams) (*GetSubscriptionsResponse, error) {
|
||||
v, _ := query.Values(params)
|
||||
endpoint := e.baseUrl.ResolveReference(&url.URL{Path: "eventsub/subscriptions", RawQuery: v.Encode()})
|
||||
|
||||
resp, err := e.client.Get(endpoint.String())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
var data GetSubscriptionsResponse
|
||||
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
}
|
|
@ -5,42 +5,116 @@ import "time"
|
|||
type Condition map[string]any
|
||||
|
||||
type Subscription struct {
|
||||
ID string `json:"id"`
|
||||
Status string `json:"status"`
|
||||
Type string `json:"type"`
|
||||
Version string `json:"version"`
|
||||
Condition Condition `json:"condition"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
// An ID that identifies the subscription.
|
||||
ID string `json:"id"`
|
||||
|
||||
// The subscription’s status. The subscriber receives events only for enabled subscriptions. Possible values are:
|
||||
//
|
||||
// enabled — The subscription is enabled.
|
||||
//
|
||||
// webhook_callback_verification_pending — The subscription is pending verification of the specified callback URL (see Responding to a challenge request).
|
||||
Status string `json:"status"`
|
||||
|
||||
// The subscription’s type.
|
||||
// See Subscription Types: https://dev.twitch.tv/docs/eventsub/eventsub-subscription-types#subscription-types
|
||||
Type string `json:"type"`
|
||||
|
||||
// The version number that identifies this definition of the subscription’s data.
|
||||
Version string `json:"version"`
|
||||
|
||||
// The subscription’s parameter values. This is a string-encoded JSON object whose contents are determined by the subscription type.
|
||||
Condition Condition `json:"condition"`
|
||||
|
||||
// The date and time (in RFC3339 format) of when the subscription was created.
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
// The transport details used to send the notifications.
|
||||
Transport *Transport `json:"transport"`
|
||||
Cost int `json:"cost"`
|
||||
|
||||
// The amount that the subscription counts against your limit.
|
||||
// Learn More: https://dev.twitch.tv/docs/eventsub/manage-subscriptions/#subscription-limits
|
||||
Cost int `json:"cost"`
|
||||
}
|
||||
|
||||
type Status string
|
||||
|
||||
const (
|
||||
StatusEnabled = "enabled"
|
||||
// enabled — The subscription is enabled.
|
||||
StatusEnabled = "enabled"
|
||||
|
||||
// webhook_callback_verification_pending — The subscription is pending verification of the specified callback URL.
|
||||
StatusWebhookCallbackVerificationPending = "webhook_callback_verification_pending"
|
||||
StatusWebhookCallbackVerificationFailed = "webhook_callback_verification_failed"
|
||||
NotificationFailuresExceeded = "notification_failures_exceeded"
|
||||
AuthorizationRevoked = "authorization_revoked"
|
||||
ModeratorRemoved = "moderator_removed"
|
||||
USerRemoved = "user_removed"
|
||||
VersionRemoved = "version_removed"
|
||||
BetaMaintenance = "beta_maintenance"
|
||||
WebsocketDisconnected = "websocket_disconnected"
|
||||
WebsocketFailedPingPong = "websocket_failed_ping_pong"
|
||||
WebsocketReceivedInboundTraffic = "websocket_received_inbound_traffic"
|
||||
WebsocketConnectionUnused = "websocket_connection_unused"
|
||||
WebsocketInternalError = "websocket_internal_error"
|
||||
WebsocketNetworkTimeout = "websocket_network_timeout"
|
||||
WebsocketnetworkError = "websocket_network_error"
|
||||
|
||||
// webhook_callback_verification_failed — The specified callback URL failed verification.
|
||||
StatusWebhookCallbackVerificationFailed = "webhook_callback_verification_failed"
|
||||
|
||||
// notification_failures_exceeded — The notification delivery failure rate was too high.
|
||||
NotificationFailuresExceeded = "notification_failures_exceeded"
|
||||
|
||||
// authorization_revoked — The authorization was revoked for one or more users specified in the Condition object.
|
||||
AuthorizationRevoked = "authorization_revoked"
|
||||
|
||||
// moderator_removed — The moderator that authorized the subscription is no longer one of the broadcaster's moderators.
|
||||
ModeratorRemoved = "moderator_removed"
|
||||
|
||||
// user_removed — One of the users specified in the Condition object was removed.
|
||||
UserRemoved = "user_removed"
|
||||
|
||||
// version_removed — The subscription to subscription type and version is no longer supported.
|
||||
VersionRemoved = "version_removed"
|
||||
|
||||
// beta_maintenance — The subscription to the beta subscription type was removed due to maintenance.
|
||||
BetaMaintenance = "beta_maintenance"
|
||||
|
||||
// websocket_disconnected — The client closed the connection.
|
||||
WebsocketDisconnected = "websocket_disconnected"
|
||||
|
||||
// websocket_failed_ping_pong — The client failed to respond to a ping message.
|
||||
WebsocketFailedPingPong = "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 = "websocket_received_inbound_traffic"
|
||||
|
||||
// websocket_connection_unused — The client failed to subscribe to events within the required time.
|
||||
WebsocketConnectionUnused = "websocket_connection_unused"
|
||||
|
||||
// websocket_internal_error — The Twitch WebSocket server experienced an unexpected error.
|
||||
WebsocketInternalError = "websocket_internal_error"
|
||||
|
||||
// websocket_network_timeout — The Twitch WebSocket server timed out writing the message to the client.
|
||||
WebsocketNetworkTimeout = "websocket_network_timeout"
|
||||
|
||||
// websocket_network_error — The Twitch WebSocket server experienced a network error writing the message to the client.
|
||||
WebsocketnetworkError = "websocket_network_error"
|
||||
)
|
||||
|
||||
type Transport struct {
|
||||
Method string `json:"method"`
|
||||
Callback *string `json:"callback,omitempty"`
|
||||
Secret *string `json:"secret,omitempty"`
|
||||
// The transport method. Possible values are:
|
||||
//
|
||||
// webhook, websocket, conduit
|
||||
Method string `json:"method"`
|
||||
|
||||
// The callback URL where the notifications are sent. The URL must use the HTTPS protocol and port 443.
|
||||
// See Processing an event. Specify this field only if method is set to webhook.
|
||||
//
|
||||
// NOTE: Redirects are not followed.
|
||||
Callback *string `json:"callback,omitempty"`
|
||||
|
||||
// The secret used to verify the signature.
|
||||
// The secret must be an ASCII string that’s a minimum of 10 characters long and a maximum of 100 characters long.
|
||||
// For information about how the secret is used,
|
||||
// see Verifying the event message: https://dev.twitch.tv/docs/eventsub/handling-webhook-events#verifying-the-event-message
|
||||
// Specify this field only if method is set to webhook.
|
||||
Secret *string `json:"secret,omitempty"`
|
||||
|
||||
// An ID that identifies the WebSocket to send notifications to. When you connect to EventSub using WebSockets,
|
||||
// the server returns the ID in the Welcome message. Specify this field only if method is set to websocket.
|
||||
SessionID *string `json:"session_id,omitempty"`
|
||||
|
||||
// An ID that identifies the conduit to send notifications to.
|
||||
// When you create a conduit, the server returns the conduit ID.
|
||||
// Specify this field only if method is set to conduit.
|
||||
ConduitID *string `json:"conduit_id,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -75,7 +149,10 @@ func ConduitTransport(conduitID string) *Transport {
|
|||
}
|
||||
|
||||
type SubscriptionType struct {
|
||||
Name string `json:"type"`
|
||||
// The type of subscription.
|
||||
Name string `json:"type"`
|
||||
|
||||
// The version number that identifies the definition of the subscription type that you want the response to use.
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package eventsub
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go.fifitido.net/twitch/api"
|
||||
"go.fifitido.net/twitch/api/eventsub"
|
||||
)
|
||||
|
@ -19,8 +21,8 @@ func New(api *api.API, trans *eventsub.Transport) *EventSub {
|
|||
}
|
||||
}
|
||||
|
||||
func (e *EventSub) Subscribe(subType eventsub.SubscriptionType, cond eventsub.Condition) error {
|
||||
res, err := e.api.EventSub.CreateSubscription(&eventsub.CreateSubscriptionRequest{
|
||||
func (e *EventSub) Subscribe(ctx context.Context, subType eventsub.SubscriptionType, cond eventsub.Condition) error {
|
||||
res, err := e.api.EventSub.CreateEventSubSubscription(ctx, &eventsub.CreateEventSubSubscriptionRequest{
|
||||
SubscriptionType: subType,
|
||||
Condition: cond,
|
||||
Transport: e.transport,
|
||||
|
@ -39,7 +41,7 @@ func (e *EventSub) Subscribe(subType eventsub.SubscriptionType, cond eventsub.Co
|
|||
|
||||
func (e *EventSub) Close() error {
|
||||
for _, sub := range e.subscriptions {
|
||||
if err := e.api.EventSub.DeleteSubscription(sub.ID); err != nil {
|
||||
if err := e.api.EventSub.DeleteEventSubSubscription(context.Background(), sub.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue