From b9977140e6ac9a96277366944da030e6645b58a4 Mon Sep 17 00:00:00 2001 From: Jack McGuire Date: Wed, 11 Nov 2026 16:31:37 +0000 Subject: [PATCH] Align with Twitch's 2026-11-10 docs changelog Add the chat_user_banned, guest_star_moderator_removed and conduit_deleted EventSub status constants, correct doc comments (Guest Star layouts, prediction window, video types/duration, conduit shard statuses, subscription total/points), note that Before is unsupported on Get Clips, Get Stream Markers, Get Top Games and Get Banned Users, and fix stale docs/ examples. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 4 ++++ docs/conduits.md | 2 +- docs/guest-star.md | 4 ++-- docs/polls.md | 44 +++++++++++++----------------------------- docs/predictions.md | 4 ++-- docs/schedule.md | 9 ++++----- helix/client.go | 2 +- helix/clips.go | 1 + helix/conduits.go | 2 +- helix/eventsub.go | 3 +++ helix/games.go | 1 + helix/guest_star.go | 2 +- helix/moderation.go | 1 + helix/predictions.go | 2 +- helix/streams.go | 1 + helix/subscriptions.go | 4 ++-- helix/videos.go | 4 ++-- 17 files changed, 41 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index da3bc05..f70c962 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,10 +8,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added +- EventSub status constants `EventSubStatusChatUserBanned` (`chat_user_banned`), `EventSubStatusGuestStarModeratorRemoved` (`guest_star_moderator_removed`) and `EventSubStatusConduitDeleted` (`conduit_deleted`), from Twitch's 2026-11-10 docs changelog ### Changed +- Doc comments brought in line with Twitch's 2026-11-10 docs changelog: Guest Star `group_layout` is `TILED` or `SCREENSHARE`; Create Prediction's window is 1-1800 seconds; Get Videos lists the `past_premiere` and `premiere_upload` types and the `duration` format; Get Conduit Shards lists `websocket_connection_unused`; Get Broadcaster Subscriptions omits `total` and `points` when filtering by user +- `PaginationParams.Before` is documented as unsupported on Get Clips, Get Stream Markers, Get Top Games and Get Banned Users ### Fixed +- Stale `docs/` examples: Guest Star layout values, prediction window range, conduit shard statuses (no `disabled`; adds `websocket_failed_to_reconnect`), polls (no `MODERATED` status or Bits voting fields), and Get Channel Stream Schedule (`StartTime` is a `time.Time`; `UTCOffset` is deprecated) ## [1.5.1] - 2026-11-11 ([#105](https://github.com/Its-donkey/kappopher/pull/105)) diff --git a/docs/conduits.md b/docs/conduits.md index 4ff4b7a..ef1d3d4 100644 --- a/docs/conduits.md +++ b/docs/conduits.md @@ -173,7 +173,7 @@ for _, shard := range resp.Data { **Parameters:** - `ConduitID` (string): The ID of the conduit -- `Status` (string, optional): Filter shards by status (e.g., `enabled`, `disabled`, `webhook_callback_verification_pending`, `webhook_callback_verification_failed`, `notification_failures_exceeded`, `websocket_disconnected`, `websocket_failed_ping_pong`, `websocket_received_inbound_traffic`, `websocket_connection_unused`, `websocket_internal_error`, `websocket_network_timeout`, `websocket_network_error`) +- `Status` (string, optional): Filter shards by status (e.g., `enabled`, `webhook_callback_verification_pending`, `webhook_callback_verification_failed`, `notification_failures_exceeded`, `websocket_disconnected`, `websocket_failed_ping_pong`, `websocket_received_inbound_traffic`, `websocket_connection_unused`, `websocket_internal_error`, `websocket_network_timeout`, `websocket_network_error`, `websocket_failed_to_reconnect`) - `PaginationParams` (optional): Pagination parameters **Returns:** diff --git a/docs/guest-star.md b/docs/guest-star.md index 4cb47bc..36cf2ee 100644 --- a/docs/guest-star.md +++ b/docs/guest-star.md @@ -28,7 +28,7 @@ if err != nil { "is_moderator_send_live_enabled": true, "slot_count": 6, "is_browser_source_audio_enabled": true, - "group_layout": "TILED_LAYOUT", + "group_layout": "TILED", "browser_source_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" } ] @@ -47,7 +47,7 @@ err := client.UpdateChannelGuestStarSettings(ctx, &helix.UpdateChannelGuestStarS IsModeratorSendLiveEnabled: true, SlotCount: 6, IsBrowserSourceAudioEnabled: true, - GroupLayout: "TILED_LAYOUT", // Options: TILED_LAYOUT, SCREENSHARE_LAYOUT, HORIZONTAL_LAYOUT, VERTICAL_LAYOUT + GroupLayout: "TILED", // Options: TILED, SCREENSHARE RegenerateBrowserSources: false, }) if err != nil { diff --git a/docs/polls.md b/docs/polls.md index 9219634..649f180 100644 --- a/docs/polls.md +++ b/docs/polls.md @@ -46,7 +46,7 @@ for _, poll := range resp.Data { - `Choices` - Array of poll choices - `BitsVotingEnabled` - Whether Bits voting is enabled - `ChannelPointsVotingEnabled` - Whether Channel Points voting is enabled -- `Status` - Poll status: `ACTIVE`, `COMPLETED`, `TERMINATED`, `ARCHIVED`, `MODERATED`, `INVALID` +- `Status` - Poll status: `ACTIVE`, `COMPLETED`, `TERMINATED`, `ARCHIVED`, `INVALID` - `Duration` - Poll duration in seconds - `StartedAt` - When the poll started - `EndedAt` - When the poll ended (if applicable) @@ -66,33 +66,27 @@ for _, poll := range resp.Data { "id": "4c123012-1351-4f33-84b7-43856e7a0f47", "title": "Minecraft", "votes": 127, - "channel_points_votes": 85, - "bits_votes": 42 + "channel_points_votes": 85 }, { "id": "d1ab80e5-1011-4882-8f4e-ce6d9e0d6f0f", "title": "Fortnite", "votes": 98, - "channel_points_votes": 63, - "bits_votes": 35 + "channel_points_votes": 63 }, { "id": "a2e9e4bc-4b7e-4d0c-8c5f-3e2d1f0c6a8b", "title": "Among Us", "votes": 156, - "channel_points_votes": 120, - "bits_votes": 36 + "channel_points_votes": 120 }, { "id": "f8d5c3e2-9b1a-4f2e-8d7c-6a5b4c3d2e1f", "title": "Valorant", "votes": 83, - "channel_points_votes": 55, - "bits_votes": 28 + "channel_points_votes": 55 } ], - "bits_voting_enabled": true, - "bits_per_vote": 10, "channel_points_voting_enabled": true, "channel_points_per_vote": 100, "status": "ACTIVE", @@ -154,33 +148,27 @@ fmt.Printf("Status: %s, Ends at: %s\n", resp.Data[0].Status, resp.Data[0].Starte "id": "4c123012-1351-4f33-84b7-43856e7a0f47", "title": "Minecraft", "votes": 0, - "channel_points_votes": 0, - "bits_votes": 0 + "channel_points_votes": 0 }, { "id": "d1ab80e5-1011-4882-8f4e-ce6d9e0d6f0f", "title": "Fortnite", "votes": 0, - "channel_points_votes": 0, - "bits_votes": 0 + "channel_points_votes": 0 }, { "id": "a2e9e4bc-4b7e-4d0c-8c5f-3e2d1f0c6a8b", "title": "Among Us", "votes": 0, - "channel_points_votes": 0, - "bits_votes": 0 + "channel_points_votes": 0 }, { "id": "f8d5c3e2-9b1a-4f2e-8d7c-6a5b4c3d2e1f", "title": "Valorant", "votes": 0, - "channel_points_votes": 0, - "bits_votes": 0 + "channel_points_votes": 0 } ], - "bits_voting_enabled": false, - "bits_per_vote": 0, "channel_points_voting_enabled": true, "channel_points_per_vote": 100, "status": "ACTIVE", @@ -235,33 +223,27 @@ fmt.Printf("Ended poll: %s with status %s\n", resp.Data[0].Title, resp.Data[0].S "id": "4c123012-1351-4f33-84b7-43856e7a0f47", "title": "Minecraft", "votes": 127, - "channel_points_votes": 85, - "bits_votes": 42 + "channel_points_votes": 85 }, { "id": "d1ab80e5-1011-4882-8f4e-ce6d9e0d6f0f", "title": "Fortnite", "votes": 98, - "channel_points_votes": 63, - "bits_votes": 35 + "channel_points_votes": 63 }, { "id": "a2e9e4bc-4b7e-4d0c-8c5f-3e2d1f0c6a8b", "title": "Among Us", "votes": 156, - "channel_points_votes": 120, - "bits_votes": 36 + "channel_points_votes": 120 }, { "id": "f8d5c3e2-9b1a-4f2e-8d7c-6a5b4c3d2e1f", "title": "Valorant", "votes": 83, - "channel_points_votes": 55, - "bits_votes": 28 + "channel_points_votes": 55 } ], - "bits_voting_enabled": true, - "bits_per_vote": 10, "channel_points_voting_enabled": true, "channel_points_per_vote": 100, "status": "TERMINATED", diff --git a/docs/predictions.md b/docs/predictions.md index c935d62..72b540a 100644 --- a/docs/predictions.md +++ b/docs/predictions.md @@ -130,7 +130,7 @@ resp, err := client.CreatePrediction(ctx, &helix.CreatePredictionParams{ {Title: "Yes"}, {Title: "No"}, }, - PredictionWindow: 300, // 5 minutes (30-1800 seconds) + PredictionWindow: 300, // 5 minutes (1-1800 seconds) }) fmt.Printf("Created prediction: %s (ID: %s)\n", resp.Data[0].Title, resp.Data[0].ID) @@ -155,7 +155,7 @@ resp, err = client.CreatePrediction(ctx, &helix.CreatePredictionParams{ - `Title` - Required. The prediction title - `Outcomes` - Required. Array of outcomes (2-10 outcomes) - `Title` - Required. The outcome title -- `PredictionWindow` - Required. Prediction window in seconds (30-1800) +- `PredictionWindow` - Required. Prediction window in seconds (1-1800) **Sample Response:** ```json diff --git a/docs/schedule.md b/docs/schedule.md index 49c2c4a..9e63472 100644 --- a/docs/schedule.md +++ b/docs/schedule.md @@ -22,11 +22,10 @@ resp, err = client.GetChannelStreamSchedule(ctx, &helix.GetChannelStreamSchedule IDs: []string{"segment-id-1", "segment-id-2"}, }) -// Get segments starting from a specific time with UTC offset +// Get segments starting from a specific time resp, err = client.GetChannelStreamSchedule(ctx, &helix.GetChannelStreamScheduleParams{ BroadcasterID: "12345", - StartTime: "2025-12-15T10:00:00Z", - UTCOffset: "-04:00", // e.g., Eastern Daylight Time + StartTime: time.Date(2025, 12, 15, 10, 0, 0, 0, time.UTC), PaginationParams: &helix.PaginationParams{ First: 20, }, @@ -47,8 +46,8 @@ for _, segment := range schedule.Segments { **Parameters:** - `BroadcasterID` - Required. ID of the broadcaster - `IDs` - Optional. Array of segment IDs to retrieve (max 100) -- `StartTime` - Optional. Start time for segments (RFC3339 format) -- `UTCOffset` - Optional. UTC offset for localization (e.g., "-04:00") +- `StartTime` - Optional. Start time for segments +- `UTCOffset` - Deprecated. Twitch documents `utc_offset` as not supported - `PaginationParams` - Optional. Pagination parameters **Response Fields:** diff --git a/helix/client.go b/helix/client.go index c715801..54de8d3 100644 --- a/helix/client.go +++ b/helix/client.go @@ -630,7 +630,7 @@ func (c *Client) delete(ctx context.Context, endpoint string, query url.Values, type PaginationParams struct { First int // Maximum number of items to return (1-100) After string // Cursor for forward pagination - Before string // Cursor for backward pagination + Before string // Cursor for backward pagination; not every endpoint supports it } // addPaginationParams adds pagination parameters to a query. diff --git a/helix/clips.go b/helix/clips.go index afc25c1..e1ced62 100644 --- a/helix/clips.go +++ b/helix/clips.go @@ -76,6 +76,7 @@ type GetClipsParams struct { StartedAt time.Time EndedAt time.Time IsFeatured *bool + // PaginationParams.Before is not supported by this endpoint; use After. *PaginationParams } diff --git a/helix/conduits.go b/helix/conduits.go index 3f4e7ea..4430739 100644 --- a/helix/conduits.go +++ b/helix/conduits.go @@ -89,7 +89,7 @@ type ConduitShardTransport struct { // GetConduitShardsParams contains parameters for GetConduitShards. type GetConduitShardsParams struct { ConduitID string - Status string // enabled, webhook_callback_verification_pending, webhook_callback_verification_failed, notification_failures_exceeded, websocket_disconnected, websocket_failed_ping_pong, websocket_received_inbound_traffic, websocket_internal_error, websocket_network_timeout, websocket_network_error, websocket_failed_to_reconnect + Status string // enabled, webhook_callback_verification_pending, webhook_callback_verification_failed, notification_failures_exceeded, websocket_disconnected, websocket_failed_ping_pong, websocket_received_inbound_traffic, websocket_connection_unused, websocket_internal_error, websocket_network_timeout, websocket_network_error, websocket_failed_to_reconnect *PaginationParams } diff --git a/helix/eventsub.go b/helix/eventsub.go index bc11d9a..482df23 100644 --- a/helix/eventsub.go +++ b/helix/eventsub.go @@ -349,8 +349,11 @@ const ( EventSubStatusAuthorizationRevoked = "authorization_revoked" EventSubStatusModeratorRemoved = "moderator_removed" EventSubStatusUserRemoved = "user_removed" + EventSubStatusChatUserBanned = "chat_user_banned" EventSubStatusVersionRemoved = "version_removed" EventSubStatusBetaMaintenance = "beta_maintenance" + EventSubStatusGuestStarModeratorRemoved = "guest_star_moderator_removed" + EventSubStatusConduitDeleted = "conduit_deleted" EventSubStatusWebsocketDisconnected = "websocket_disconnected" EventSubStatusWebsocketFailedPingPong = "websocket_failed_ping_pong" EventSubStatusWebsocketReceivedInboundTraffic = "websocket_received_inbound_traffic" diff --git a/helix/games.go b/helix/games.go index 1195cec..f007566 100644 --- a/helix/games.go +++ b/helix/games.go @@ -44,6 +44,7 @@ func (c *Client) GetGames(ctx context.Context, params *GetGamesParams) (*Respons // GetTopGamesParams contains parameters for GetTopGames. type GetTopGamesParams struct { + // PaginationParams.Before is not supported by this endpoint; use After. *PaginationParams } diff --git a/helix/guest_star.go b/helix/guest_star.go index fca42b4..fe79999 100644 --- a/helix/guest_star.go +++ b/helix/guest_star.go @@ -11,7 +11,7 @@ type GuestStarSettings struct { IsModeratorSendLiveEnabled bool `json:"is_moderator_send_live_enabled"` SlotCount int `json:"slot_count"` IsBrowserSourceAudioEnabled bool `json:"is_browser_source_audio_enabled"` - GroupLayout string `json:"group_layout"` // TILED_LAYOUT, SCREENSHARE_LAYOUT, HORIZONTAL_LAYOUT, VERTICAL_LAYOUT + GroupLayout string `json:"group_layout"` // TILED or SCREENSHARE; other layouts are reported as TILED BrowserSourceToken string `json:"browser_source_token,omitempty"` } diff --git a/helix/moderation.go b/helix/moderation.go index 2984d7e..fc46ba7 100644 --- a/helix/moderation.go +++ b/helix/moderation.go @@ -23,6 +23,7 @@ type BannedUser struct { type GetBannedUsersParams struct { BroadcasterID string UserIDs []string // Filter by user IDs (max 100) + // PaginationParams.Before is not supported by this endpoint; use After. *PaginationParams } diff --git a/helix/predictions.go b/helix/predictions.go index ad76e9b..eaf434a 100644 --- a/helix/predictions.go +++ b/helix/predictions.go @@ -70,7 +70,7 @@ type CreatePredictionParams struct { BroadcasterID string `json:"broadcaster_id"` Title string `json:"title"` Outcomes []CreatePredictionOutcome `json:"outcomes"` // 2-10 outcomes - PredictionWindow int `json:"prediction_window"` // 30-1800 seconds + PredictionWindow int `json:"prediction_window"` // 1-1800 seconds } // CreatePredictionOutcome represents an outcome when creating a prediction. diff --git a/helix/streams.go b/helix/streams.go index e6a6584..2848a93 100644 --- a/helix/streams.go +++ b/helix/streams.go @@ -147,6 +147,7 @@ type VideoStreamMarkers struct { type GetStreamMarkersParams struct { UserID string // Either UserID or VideoID is required VideoID string + // PaginationParams.Before is not supported by this endpoint; use After. *PaginationParams } diff --git a/helix/subscriptions.go b/helix/subscriptions.go index 445ad1f..93fef5a 100644 --- a/helix/subscriptions.go +++ b/helix/subscriptions.go @@ -32,8 +32,8 @@ type GetBroadcasterSubscriptionsParams struct { type SubscriptionsResponse struct { Data []Subscription `json:"data"` Pagination *Pagination `json:"pagination,omitempty"` - Total int `json:"total"` - Points int `json:"points"` // Subscriber points (based on tiers) + Total int `json:"total"` // omitted (0) when UserIDs is set + Points int `json:"points"` // Subscriber points (based on tiers); omitted (0) when UserIDs is set } // GetBroadcasterSubscriptions gets the list of subscribers for a channel. diff --git a/helix/videos.go b/helix/videos.go index 0a12f28..aa34a9b 100644 --- a/helix/videos.go +++ b/helix/videos.go @@ -22,8 +22,8 @@ type Video struct { Viewable string `json:"viewable"` ViewCount int `json:"view_count"` Language string `json:"language"` - Type string `json:"type"` // archive, highlight, upload - Duration string `json:"duration"` + Type string `json:"type"` // archive, highlight, upload; past_premiere and premiere_upload only when requested by ID + Duration string `json:"duration"` // e.g. "1h2m3s"; leading zero units are left out ("3m21s") MutedSegments []MutedSegment `json:"muted_segments,omitempty"` }