diff --git a/api/ads/get_ad_schedule.go b/api/ads/get_ad_schedule.go index a827ccf..5c7feba 100644 --- a/api/ads/get_ad_schedule.go +++ b/api/ads/get_ad_schedule.go @@ -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 } diff --git a/api/ads/snooze_next_ad.go b/api/ads/snooze_next_ad.go index c815745..ca6b0f7 100644 --- a/api/ads/snooze_next_ad.go +++ b/api/ads/snooze_next_ad.go @@ -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 } diff --git a/api/ads/start_commercial.go b/api/ads/start_commercial.go index d886a39..6053dbb 100644 --- a/api/ads/start_commercial.go +++ b/api/ads/start_commercial.go @@ -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 } diff --git a/api/analytics/get_extension_analytics.go b/api/analytics/get_extension_analytics.go index 141a320..a19e1ce 100644 --- a/api/analytics/get_extension_analytics.go +++ b/api/analytics/get_extension_analytics.go @@ -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 } diff --git a/api/analytics/get_game_analytics.go b/api/analytics/get_game_analytics.go index 1e41971..4a78713 100644 --- a/api/analytics/get_game_analytics.go +++ b/api/analytics/get_game_analytics.go @@ -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 } diff --git a/api/bits/get_bits_leaderboard.go b/api/bits/get_bits_leaderboard.go index cda4096..2d8864d 100644 --- a/api/bits/get_bits_leaderboard.go +++ b/api/bits/get_bits_leaderboard.go @@ -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 } diff --git a/api/bits/get_cheermotes.go b/api/bits/get_cheermotes.go index 83cfc65..ed07706 100644 --- a/api/bits/get_cheermotes.go +++ b/api/bits/get_cheermotes.go @@ -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 } diff --git a/api/bits/get_extension_transactions.go b/api/bits/get_extension_transactions.go index 5aafc24..bbe03b3 100644 --- a/api/bits/get_extension_transactions.go +++ b/api/bits/get_extension_transactions.go @@ -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 } diff --git a/api/channelpoints/create_custom_rewards.go b/api/channelpoints/create_custom_rewards.go index 0fe30ca..90760c9 100644 --- a/api/channelpoints/create_custom_rewards.go +++ b/api/channelpoints/create_custom_rewards.go @@ -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 } diff --git a/api/channelpoints/delete_custom_reward.go b/api/channelpoints/delete_custom_reward.go index 587b7c7..e5cc4d3 100644 --- a/api/channelpoints/delete_custom_reward.go +++ b/api/channelpoints/delete_custom_reward.go @@ -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 } diff --git a/api/channelpoints/get_custom_reward.go b/api/channelpoints/get_custom_reward.go index fae6f22..1e285b0 100644 --- a/api/channelpoints/get_custom_reward.go +++ b/api/channelpoints/get_custom_reward.go @@ -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 } diff --git a/api/channelpoints/get_custom_reward_redemption.go b/api/channelpoints/get_custom_reward_redemption.go index a63d876..10873cd 100644 --- a/api/channelpoints/get_custom_reward_redemption.go +++ b/api/channelpoints/get_custom_reward_redemption.go @@ -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 } diff --git a/api/channelpoints/update_custom_reward.go b/api/channelpoints/update_custom_reward.go index b336e4f..f0b3359 100644 --- a/api/channelpoints/update_custom_reward.go +++ b/api/channelpoints/update_custom_reward.go @@ -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 } diff --git a/api/channelpoints/update_redemption_status.go b/api/channelpoints/update_redemption_status.go index f5e0f94..208bf86 100644 --- a/api/channelpoints/update_redemption_status.go +++ b/api/channelpoints/update_redemption_status.go @@ -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 } diff --git a/api/channels/get_channel_editors.go b/api/channels/get_channel_editors.go index c058e9e..4128289 100644 --- a/api/channels/get_channel_editors.go +++ b/api/channels/get_channel_editors.go @@ -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 } diff --git a/api/channels/get_channel_followers.go b/api/channels/get_channel_followers.go index f8f11b3..2d93508 100644 --- a/api/channels/get_channel_followers.go +++ b/api/channels/get_channel_followers.go @@ -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 } diff --git a/api/channels/get_channel_information.go b/api/channels/get_channel_information.go index e4bce9d..98bc8c9 100644 --- a/api/channels/get_channel_information.go +++ b/api/channels/get_channel_information.go @@ -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 } diff --git a/api/channels/get_followed_channels.go b/api/channels/get_followed_channels.go index 6b8b808..c9a74bb 100644 --- a/api/channels/get_followed_channels.go +++ b/api/channels/get_followed_channels.go @@ -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 } diff --git a/api/channels/modify_channel_information.go b/api/channels/modify_channel_information.go index dee49fa..1141650 100644 --- a/api/channels/modify_channel_information.go +++ b/api/channels/modify_channel_information.go @@ -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 } diff --git a/api/charity/get_charity_campaign.go b/api/charity/get_charity_campaign.go index b5616f7..ee6f3b0 100644 --- a/api/charity/get_charity_campaign.go +++ b/api/charity/get_charity_campaign.go @@ -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 } diff --git a/api/charity/get_charity_campaign_donations.go b/api/charity/get_charity_campaign_donations.go index a856398..58e99b2 100644 --- a/api/charity/get_charity_campaign_donations.go +++ b/api/charity/get_charity_campaign_donations.go @@ -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 } diff --git a/api/eventsub/create_eventsub_subscription.go b/api/eventsub/create_eventsub_subscription.go new file mode 100644 index 0000000..8962310 --- /dev/null +++ b/api/eventsub/create_eventsub_subscription.go @@ -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 +} diff --git a/api/eventsub/create_subscription.go b/api/eventsub/create_subscription.go deleted file mode 100644 index d98ff9a..0000000 --- a/api/eventsub/create_subscription.go +++ /dev/null @@ -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 -} diff --git a/api/eventsub/delete_eventsub_subscription.go b/api/eventsub/delete_eventsub_subscription.go new file mode 100644 index 0000000..0edcb48 --- /dev/null +++ b/api/eventsub/delete_eventsub_subscription.go @@ -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 +} diff --git a/api/eventsub/delete_subscription.go b/api/eventsub/delete_subscription.go deleted file mode 100644 index 3e677a5..0000000 --- a/api/eventsub/delete_subscription.go +++ /dev/null @@ -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 -} diff --git a/api/eventsub/get_eventsub_subscriptions.go b/api/eventsub/get_eventsub_subscriptions.go new file mode 100644 index 0000000..86ef9fc --- /dev/null +++ b/api/eventsub/get_eventsub_subscriptions.go @@ -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 +} diff --git a/api/eventsub/get_subscriptions.go b/api/eventsub/get_subscriptions.go deleted file mode 100644 index 72001ce..0000000 --- a/api/eventsub/get_subscriptions.go +++ /dev/null @@ -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 -} diff --git a/api/eventsub/models.go b/api/eventsub/models.go index ac27c04..6ab3f71 100644 --- a/api/eventsub/models.go +++ b/api/eventsub/models.go @@ -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"` } diff --git a/eventsub/eventsub.go b/eventsub/eventsub.go index ee86933..b16bcd0 100644 --- a/eventsub/eventsub.go +++ b/eventsub/eventsub.go @@ -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 } }