From cce3ab7275ff8f5b4b5a0e9e9d84c59287f074b4 Mon Sep 17 00:00:00 2001 From: Foretack <69414142+Foretack@users.noreply.github.com> Date: Wed, 1 Nov 2023 10:30:10 +0100 Subject: [PATCH] Add MiniTwitch.Helix (#44) --- .github/workflows/build-helix.yml | 30 + MiniTwitch.Helix/Enums/AnalyticsType.cs | 6 + MiniTwitch.Helix/Enums/AnnouncementColor.cs | 10 + .../Enums/BitsLeaderboardPeriod.cs | 10 + MiniTwitch.Helix/Enums/ChatColor.cs | 20 + MiniTwitch.Helix/Enums/ConfigSegmentType.cs | 8 + MiniTwitch.Helix/Enums/ContentLabelid.cs | 10 + MiniTwitch.Helix/Enums/EventSubStatus.cs | 20 + MiniTwitch.Helix/Enums/FulfillmentStatus.cs | 7 + MiniTwitch.Helix/Enums/LabelLocale.cs | 34 + .../Enums/RewardRedemptionStatus.cs | 8 + MiniTwitch.Helix/Enums/SortMethod.cs | 7 + MiniTwitch.Helix/Enums/StreamTypes.cs | 7 + MiniTwitch.Helix/Enums/VideoPeriod.cs | 9 + MiniTwitch.Helix/Enums/VideoSortMethod.cs | 8 + MiniTwitch.Helix/Enums/VideoType.cs | 9 + MiniTwitch.Helix/HelixWrapper.cs | 984 ++++++++ MiniTwitch.Helix/Interfaces/IHelixResult.cs | 11 + MiniTwitch.Helix/Interfaces/IPaginable.cs | 8 + MiniTwitch.Helix/Internal/HelixApiClient.cs | 176 ++ .../Internal/HelixResultFactory.cs | 125 + .../Internal/Json/EnumToString.cs | 30 + .../Internal/Json/ICaseConverter.cs | 7 + MiniTwitch.Helix/Internal/Json/IntToString.cs | 12 + .../Internal/Json/LongToString.cs | 12 + MiniTwitch.Helix/Internal/Json/SnakeCase.cs | 56 + .../Internal/Json/SnakeCaseNamingPolicy.cs | 32 + .../Internal/Json/TimeSpanToSeconds.cs | 12 + MiniTwitch.Helix/Internal/Models/Endpoints.cs | 1901 +++++++++++++++ .../Internal/Models/HelixEndpoint.cs | 11 + MiniTwitch.Helix/Internal/Models/HelixTask.cs | 8 + .../Internal/Models/InvalidToken.cs | 8 + .../Internal/Models/QueryParams.cs | 65 + .../Internal/Models/RequestData.cs | 72 + .../Internal/Models/ValidToken.cs | 15 + MiniTwitch.Helix/MiniTwitch.Helix.csproj | 46 + MiniTwitch.Helix/Models/AllCategories.cs | 2106 +++++++++++++++++ MiniTwitch.Helix/Models/AnalyticsCategory.cs | 33 + MiniTwitch.Helix/Models/BaseResponse.cs | 12 + MiniTwitch.Helix/Models/BitsCategory.cs | 39 + .../Models/ChannelPointsCategory.cs | 84 + MiniTwitch.Helix/Models/ChannelsCategory.cs | 91 + MiniTwitch.Helix/Models/CharityCategory.cs | 24 + MiniTwitch.Helix/Models/ChatCategory.cs | 99 + MiniTwitch.Helix/Models/ClipsCategory.cs | 41 + .../Models/ContentClassificationLabel.cs | 9 + .../Models/EntitlementsCategory.cs | 38 + MiniTwitch.Helix/Models/EventsubCategory.cs | 32 + MiniTwitch.Helix/Models/ExtensionsCategory.cs | 87 + MiniTwitch.Helix/Models/GamesCategory.cs | 32 + MiniTwitch.Helix/Models/GuestStarCategory.cs | 105 + MiniTwitch.Helix/Models/HelixResult.cs | 96 + .../Models/InvalidTokenException.cs | 11 + MiniTwitch.Helix/Models/ModerationCategory.cs | 135 ++ MiniTwitch.Helix/Models/PaginableResponse.cs | 10 + MiniTwitch.Helix/Models/Pagination.cs | 6 + MiniTwitch.Helix/Models/PollsCategory.cs | 40 + .../Models/PredictionsCategory.cs | 38 + MiniTwitch.Helix/Models/RaidsCategory.cs | 24 + MiniTwitch.Helix/Models/RequestRatelimit.cs | 17 + MiniTwitch.Helix/Models/ScheduleCategory.cs | 58 + MiniTwitch.Helix/Models/SearchCategory.cs | 26 + MiniTwitch.Helix/Models/SingleResponse.cs | 15 + MiniTwitch.Helix/Models/StreamsCategory.cs | 58 + .../Models/SubscriptionsCategory.cs | 33 + MiniTwitch.Helix/Models/TeamsCategory.cs | 24 + MiniTwitch.Helix/Models/UsersCategory.cs | 57 + MiniTwitch.Helix/Models/VideosCategory.cs | 48 + MiniTwitch.Helix/README.md | 94 + MiniTwitch.Helix/Requests/Announcement.cs | 12 + .../Requests/ConfigurationSegment.cs | 21 + .../Requests/ExtensionChatMessage.cs | 8 + .../Requests/ExtensionPubSubMessage.cs | 16 + .../ExtensionRequiredConfiguration.cs | 8 + MiniTwitch.Helix/Requests/MessageToCheck.cs | 13 + .../Requests/NewAutoModSettings.cs | 14 + .../Requests/NewChannelInformation.cs | 18 + MiniTwitch.Helix/Requests/NewChatSettings.cs | 14 + MiniTwitch.Helix/Requests/NewCommercial.cs | 11 + MiniTwitch.Helix/Requests/NewCustomReward.cs | 18 + .../Requests/NewGuestStarSettings.cs | 10 + MiniTwitch.Helix/Requests/NewPoll.cs | 21 + MiniTwitch.Helix/Requests/NewPrediction.cs | 19 + .../Requests/NewScheduleSegment.cs | 15 + MiniTwitch.Helix/Requests/NewSubscription.cs | 16 + MiniTwitch.Helix/Requests/PredictionToEnd.cs | 13 + .../Requests/UpdatedBitsProduct.cs | 17 + .../Requests/UpdatedCustomReward.cs | 19 + .../Requests/UpdatedScheduleSegment.cs | 15 + MiniTwitch.Helix/Requests/UserToBan.cs | 18 + .../Responses/ActiveExtensions.cs | 38 + MiniTwitch.Helix/Responses/AdSchedule.cs | 16 + MiniTwitch.Helix/Responses/AutoModSettings.cs | 21 + MiniTwitch.Helix/Responses/AutoModStatus.cs | 12 + MiniTwitch.Helix/Responses/BannedUser.cs | 15 + MiniTwitch.Helix/Responses/BannedUsers.cs | 19 + MiniTwitch.Helix/Responses/BitsLeaderboard.cs | 24 + MiniTwitch.Helix/Responses/BlockList.cs | 13 + MiniTwitch.Helix/Responses/BlockedTerm.cs | 7 + MiniTwitch.Helix/Responses/BlockedTerms.cs | 17 + .../Responses/BroadcasterSubscriptions.cs | 32 + MiniTwitch.Helix/Responses/Categories.cs | 13 + MiniTwitch.Helix/Responses/ChannelEditors.cs | 13 + .../Responses/ChannelFollowers.cs | 17 + .../Responses/ChannelGuestStarSettings.cs | 15 + MiniTwitch.Helix/Responses/ChannelTeams.cs | 22 + MiniTwitch.Helix/Responses/Channels.cs | 21 + .../Responses/ChannelsInformation.cs | 23 + MiniTwitch.Helix/Responses/CharityCampaign.cs | 32 + .../Responses/CharityCampaignDonations.cs | 25 + MiniTwitch.Helix/Responses/ChatBadges.cs | 23 + MiniTwitch.Helix/Responses/ChatSettings.cs | 20 + MiniTwitch.Helix/Responses/Chatters.cs | 16 + MiniTwitch.Helix/Responses/Cheermotes.cs | 32 + MiniTwitch.Helix/Responses/Clip.cs | 12 + MiniTwitch.Helix/Responses/Clips.cs | 27 + MiniTwitch.Helix/Responses/Commercial.cs | 13 + .../Responses/ContentClassificationLabels.cs | 13 + .../Responses/CreatedSubscription.cs | 34 + MiniTwitch.Helix/Responses/CreatorGoals.cs | 19 + MiniTwitch.Helix/Responses/CustomReward.cs | 51 + .../Responses/CustomRewardRedemptions.cs | 36 + .../Responses/DropsEntitlements.cs | 17 + MiniTwitch.Helix/Responses/EmoteSets.cs | 28 + MiniTwitch.Helix/Responses/Emotes.cs | 28 + .../Responses/EventSubSubscriptions.cs | 35 + .../Responses/ExtensionAnalytics.cs | 18 + .../Responses/ExtensionBitsProducts.cs | 21 + .../ExtensionConfigurationSegment.cs | 13 + .../Responses/ExtensionLiveChannels.cs | 15 + .../Responses/ExtensionSecrets.cs | 18 + .../Responses/ExtensionTransactions.cs | 33 + MiniTwitch.Helix/Responses/Extensions.cs | 76 + .../Responses/FollowedChannels.cs | 17 + MiniTwitch.Helix/Responses/FollowedStreams.cs | 21 + MiniTwitch.Helix/Responses/GameAnalytics.cs | 18 + MiniTwitch.Helix/Responses/Games.cs | 18 + .../Responses/GuestStarInvites.cs | 18 + .../Responses/GuestStarSession.cs | 36 + MiniTwitch.Helix/Responses/HypeTrainEvents.cs | 35 + MiniTwitch.Helix/Responses/Moderators.cs | 13 + MiniTwitch.Helix/Responses/Poll.cs | 29 + MiniTwitch.Helix/Responses/Polls.cs | 7 + MiniTwitch.Helix/Responses/Prediction.cs | 31 + MiniTwitch.Helix/Responses/Predictions.cs | 7 + MiniTwitch.Helix/Responses/Raid.cs | 12 + .../Responses/ReleasedExtensions.cs | 7 + MiniTwitch.Helix/Responses/ScheduleSegment.cs | 37 + .../Responses/ShieldModeStatus.cs | 15 + MiniTwitch.Helix/Responses/SnoozedAd.cs | 13 + MiniTwitch.Helix/Responses/StreamKey.cs | 11 + MiniTwitch.Helix/Responses/StreamMarker.cs | 14 + MiniTwitch.Helix/Responses/StreamMarkers.cs | 27 + MiniTwitch.Helix/Responses/StreamSchedule.cs | 37 + MiniTwitch.Helix/Responses/Streams.cs | 25 + MiniTwitch.Helix/Responses/Teams.cs | 25 + .../Responses/UpdatedDropsEntitlements.cs | 12 + .../Responses/UpdatedScheduleSegment.cs | 38 + MiniTwitch.Helix/Responses/UpdatedUser.cs | 20 + MiniTwitch.Helix/Responses/UserExtensions.cs | 15 + .../Responses/UserSubscription.cs | 15 + MiniTwitch.Helix/Responses/Users.cs | 24 + MiniTwitch.Helix/Responses/UsersChatColor.cs | 18 + MiniTwitch.Helix/Responses/VIPs.cs | 13 + MiniTwitch.Helix/Responses/Videos.cs | 31 + MiniTwitch.Helix/SortedHelixWrapper.cs | 71 + .../CompilerFeatureRequiredAttribute.cs | 33 + .../RequiredMemberAttribute.cs | 8 + MiniTwitch.sln | 6 + README.md | 98 + 170 files changed, 9600 insertions(+) create mode 100644 .github/workflows/build-helix.yml create mode 100644 MiniTwitch.Helix/Enums/AnalyticsType.cs create mode 100644 MiniTwitch.Helix/Enums/AnnouncementColor.cs create mode 100644 MiniTwitch.Helix/Enums/BitsLeaderboardPeriod.cs create mode 100644 MiniTwitch.Helix/Enums/ChatColor.cs create mode 100644 MiniTwitch.Helix/Enums/ConfigSegmentType.cs create mode 100644 MiniTwitch.Helix/Enums/ContentLabelid.cs create mode 100644 MiniTwitch.Helix/Enums/EventSubStatus.cs create mode 100644 MiniTwitch.Helix/Enums/FulfillmentStatus.cs create mode 100644 MiniTwitch.Helix/Enums/LabelLocale.cs create mode 100644 MiniTwitch.Helix/Enums/RewardRedemptionStatus.cs create mode 100644 MiniTwitch.Helix/Enums/SortMethod.cs create mode 100644 MiniTwitch.Helix/Enums/StreamTypes.cs create mode 100644 MiniTwitch.Helix/Enums/VideoPeriod.cs create mode 100644 MiniTwitch.Helix/Enums/VideoSortMethod.cs create mode 100644 MiniTwitch.Helix/Enums/VideoType.cs create mode 100644 MiniTwitch.Helix/HelixWrapper.cs create mode 100644 MiniTwitch.Helix/Interfaces/IHelixResult.cs create mode 100644 MiniTwitch.Helix/Interfaces/IPaginable.cs create mode 100644 MiniTwitch.Helix/Internal/HelixApiClient.cs create mode 100644 MiniTwitch.Helix/Internal/HelixResultFactory.cs create mode 100644 MiniTwitch.Helix/Internal/Json/EnumToString.cs create mode 100644 MiniTwitch.Helix/Internal/Json/ICaseConverter.cs create mode 100644 MiniTwitch.Helix/Internal/Json/IntToString.cs create mode 100644 MiniTwitch.Helix/Internal/Json/LongToString.cs create mode 100644 MiniTwitch.Helix/Internal/Json/SnakeCase.cs create mode 100644 MiniTwitch.Helix/Internal/Json/SnakeCaseNamingPolicy.cs create mode 100644 MiniTwitch.Helix/Internal/Json/TimeSpanToSeconds.cs create mode 100644 MiniTwitch.Helix/Internal/Models/Endpoints.cs create mode 100644 MiniTwitch.Helix/Internal/Models/HelixEndpoint.cs create mode 100644 MiniTwitch.Helix/Internal/Models/HelixTask.cs create mode 100644 MiniTwitch.Helix/Internal/Models/InvalidToken.cs create mode 100644 MiniTwitch.Helix/Internal/Models/QueryParams.cs create mode 100644 MiniTwitch.Helix/Internal/Models/RequestData.cs create mode 100644 MiniTwitch.Helix/Internal/Models/ValidToken.cs create mode 100644 MiniTwitch.Helix/MiniTwitch.Helix.csproj create mode 100644 MiniTwitch.Helix/Models/AllCategories.cs create mode 100644 MiniTwitch.Helix/Models/AnalyticsCategory.cs create mode 100644 MiniTwitch.Helix/Models/BaseResponse.cs create mode 100644 MiniTwitch.Helix/Models/BitsCategory.cs create mode 100644 MiniTwitch.Helix/Models/ChannelPointsCategory.cs create mode 100644 MiniTwitch.Helix/Models/ChannelsCategory.cs create mode 100644 MiniTwitch.Helix/Models/CharityCategory.cs create mode 100644 MiniTwitch.Helix/Models/ChatCategory.cs create mode 100644 MiniTwitch.Helix/Models/ClipsCategory.cs create mode 100644 MiniTwitch.Helix/Models/ContentClassificationLabel.cs create mode 100644 MiniTwitch.Helix/Models/EntitlementsCategory.cs create mode 100644 MiniTwitch.Helix/Models/EventsubCategory.cs create mode 100644 MiniTwitch.Helix/Models/ExtensionsCategory.cs create mode 100644 MiniTwitch.Helix/Models/GamesCategory.cs create mode 100644 MiniTwitch.Helix/Models/GuestStarCategory.cs create mode 100644 MiniTwitch.Helix/Models/HelixResult.cs create mode 100644 MiniTwitch.Helix/Models/InvalidTokenException.cs create mode 100644 MiniTwitch.Helix/Models/ModerationCategory.cs create mode 100644 MiniTwitch.Helix/Models/PaginableResponse.cs create mode 100644 MiniTwitch.Helix/Models/Pagination.cs create mode 100644 MiniTwitch.Helix/Models/PollsCategory.cs create mode 100644 MiniTwitch.Helix/Models/PredictionsCategory.cs create mode 100644 MiniTwitch.Helix/Models/RaidsCategory.cs create mode 100644 MiniTwitch.Helix/Models/RequestRatelimit.cs create mode 100644 MiniTwitch.Helix/Models/ScheduleCategory.cs create mode 100644 MiniTwitch.Helix/Models/SearchCategory.cs create mode 100644 MiniTwitch.Helix/Models/SingleResponse.cs create mode 100644 MiniTwitch.Helix/Models/StreamsCategory.cs create mode 100644 MiniTwitch.Helix/Models/SubscriptionsCategory.cs create mode 100644 MiniTwitch.Helix/Models/TeamsCategory.cs create mode 100644 MiniTwitch.Helix/Models/UsersCategory.cs create mode 100644 MiniTwitch.Helix/Models/VideosCategory.cs create mode 100644 MiniTwitch.Helix/README.md create mode 100644 MiniTwitch.Helix/Requests/Announcement.cs create mode 100644 MiniTwitch.Helix/Requests/ConfigurationSegment.cs create mode 100644 MiniTwitch.Helix/Requests/ExtensionChatMessage.cs create mode 100644 MiniTwitch.Helix/Requests/ExtensionPubSubMessage.cs create mode 100644 MiniTwitch.Helix/Requests/ExtensionRequiredConfiguration.cs create mode 100644 MiniTwitch.Helix/Requests/MessageToCheck.cs create mode 100644 MiniTwitch.Helix/Requests/NewAutoModSettings.cs create mode 100644 MiniTwitch.Helix/Requests/NewChannelInformation.cs create mode 100644 MiniTwitch.Helix/Requests/NewChatSettings.cs create mode 100644 MiniTwitch.Helix/Requests/NewCommercial.cs create mode 100644 MiniTwitch.Helix/Requests/NewCustomReward.cs create mode 100644 MiniTwitch.Helix/Requests/NewGuestStarSettings.cs create mode 100644 MiniTwitch.Helix/Requests/NewPoll.cs create mode 100644 MiniTwitch.Helix/Requests/NewPrediction.cs create mode 100644 MiniTwitch.Helix/Requests/NewScheduleSegment.cs create mode 100644 MiniTwitch.Helix/Requests/NewSubscription.cs create mode 100644 MiniTwitch.Helix/Requests/PredictionToEnd.cs create mode 100644 MiniTwitch.Helix/Requests/UpdatedBitsProduct.cs create mode 100644 MiniTwitch.Helix/Requests/UpdatedCustomReward.cs create mode 100644 MiniTwitch.Helix/Requests/UpdatedScheduleSegment.cs create mode 100644 MiniTwitch.Helix/Requests/UserToBan.cs create mode 100644 MiniTwitch.Helix/Responses/ActiveExtensions.cs create mode 100644 MiniTwitch.Helix/Responses/AdSchedule.cs create mode 100644 MiniTwitch.Helix/Responses/AutoModSettings.cs create mode 100644 MiniTwitch.Helix/Responses/AutoModStatus.cs create mode 100644 MiniTwitch.Helix/Responses/BannedUser.cs create mode 100644 MiniTwitch.Helix/Responses/BannedUsers.cs create mode 100644 MiniTwitch.Helix/Responses/BitsLeaderboard.cs create mode 100644 MiniTwitch.Helix/Responses/BlockList.cs create mode 100644 MiniTwitch.Helix/Responses/BlockedTerm.cs create mode 100644 MiniTwitch.Helix/Responses/BlockedTerms.cs create mode 100644 MiniTwitch.Helix/Responses/BroadcasterSubscriptions.cs create mode 100644 MiniTwitch.Helix/Responses/Categories.cs create mode 100644 MiniTwitch.Helix/Responses/ChannelEditors.cs create mode 100644 MiniTwitch.Helix/Responses/ChannelFollowers.cs create mode 100644 MiniTwitch.Helix/Responses/ChannelGuestStarSettings.cs create mode 100644 MiniTwitch.Helix/Responses/ChannelTeams.cs create mode 100644 MiniTwitch.Helix/Responses/Channels.cs create mode 100644 MiniTwitch.Helix/Responses/ChannelsInformation.cs create mode 100644 MiniTwitch.Helix/Responses/CharityCampaign.cs create mode 100644 MiniTwitch.Helix/Responses/CharityCampaignDonations.cs create mode 100644 MiniTwitch.Helix/Responses/ChatBadges.cs create mode 100644 MiniTwitch.Helix/Responses/ChatSettings.cs create mode 100644 MiniTwitch.Helix/Responses/Chatters.cs create mode 100644 MiniTwitch.Helix/Responses/Cheermotes.cs create mode 100644 MiniTwitch.Helix/Responses/Clip.cs create mode 100644 MiniTwitch.Helix/Responses/Clips.cs create mode 100644 MiniTwitch.Helix/Responses/Commercial.cs create mode 100644 MiniTwitch.Helix/Responses/ContentClassificationLabels.cs create mode 100644 MiniTwitch.Helix/Responses/CreatedSubscription.cs create mode 100644 MiniTwitch.Helix/Responses/CreatorGoals.cs create mode 100644 MiniTwitch.Helix/Responses/CustomReward.cs create mode 100644 MiniTwitch.Helix/Responses/CustomRewardRedemptions.cs create mode 100644 MiniTwitch.Helix/Responses/DropsEntitlements.cs create mode 100644 MiniTwitch.Helix/Responses/EmoteSets.cs create mode 100644 MiniTwitch.Helix/Responses/Emotes.cs create mode 100644 MiniTwitch.Helix/Responses/EventSubSubscriptions.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionAnalytics.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionBitsProducts.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionConfigurationSegment.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionLiveChannels.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionSecrets.cs create mode 100644 MiniTwitch.Helix/Responses/ExtensionTransactions.cs create mode 100644 MiniTwitch.Helix/Responses/Extensions.cs create mode 100644 MiniTwitch.Helix/Responses/FollowedChannels.cs create mode 100644 MiniTwitch.Helix/Responses/FollowedStreams.cs create mode 100644 MiniTwitch.Helix/Responses/GameAnalytics.cs create mode 100644 MiniTwitch.Helix/Responses/Games.cs create mode 100644 MiniTwitch.Helix/Responses/GuestStarInvites.cs create mode 100644 MiniTwitch.Helix/Responses/GuestStarSession.cs create mode 100644 MiniTwitch.Helix/Responses/HypeTrainEvents.cs create mode 100644 MiniTwitch.Helix/Responses/Moderators.cs create mode 100644 MiniTwitch.Helix/Responses/Poll.cs create mode 100644 MiniTwitch.Helix/Responses/Polls.cs create mode 100644 MiniTwitch.Helix/Responses/Prediction.cs create mode 100644 MiniTwitch.Helix/Responses/Predictions.cs create mode 100644 MiniTwitch.Helix/Responses/Raid.cs create mode 100644 MiniTwitch.Helix/Responses/ReleasedExtensions.cs create mode 100644 MiniTwitch.Helix/Responses/ScheduleSegment.cs create mode 100644 MiniTwitch.Helix/Responses/ShieldModeStatus.cs create mode 100644 MiniTwitch.Helix/Responses/SnoozedAd.cs create mode 100644 MiniTwitch.Helix/Responses/StreamKey.cs create mode 100644 MiniTwitch.Helix/Responses/StreamMarker.cs create mode 100644 MiniTwitch.Helix/Responses/StreamMarkers.cs create mode 100644 MiniTwitch.Helix/Responses/StreamSchedule.cs create mode 100644 MiniTwitch.Helix/Responses/Streams.cs create mode 100644 MiniTwitch.Helix/Responses/Teams.cs create mode 100644 MiniTwitch.Helix/Responses/UpdatedDropsEntitlements.cs create mode 100644 MiniTwitch.Helix/Responses/UpdatedScheduleSegment.cs create mode 100644 MiniTwitch.Helix/Responses/UpdatedUser.cs create mode 100644 MiniTwitch.Helix/Responses/UserExtensions.cs create mode 100644 MiniTwitch.Helix/Responses/UserSubscription.cs create mode 100644 MiniTwitch.Helix/Responses/Users.cs create mode 100644 MiniTwitch.Helix/Responses/UsersChatColor.cs create mode 100644 MiniTwitch.Helix/Responses/VIPs.cs create mode 100644 MiniTwitch.Helix/Responses/Videos.cs create mode 100644 MiniTwitch.Helix/SortedHelixWrapper.cs create mode 100644 MiniTwitch.Helix/net6-compatibility/CompilerFeatureRequiredAttribute.cs create mode 100644 MiniTwitch.Helix/net6-compatibility/RequiredMemberAttribute.cs diff --git a/.github/workflows/build-helix.yml b/.github/workflows/build-helix.yml new file mode 100644 index 0000000..410a888 --- /dev/null +++ b/.github/workflows/build-helix.yml @@ -0,0 +1,30 @@ +name: Build (Helix) + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + + runs-on: windows-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install .NET 6 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 6.0.x + + - name: Build + run: | + cd .\MiniTwitch.Helix\ + dotnet build -v d -c Release + \ No newline at end of file diff --git a/MiniTwitch.Helix/Enums/AnalyticsType.cs b/MiniTwitch.Helix/Enums/AnalyticsType.cs new file mode 100644 index 0000000..6e0c855 --- /dev/null +++ b/MiniTwitch.Helix/Enums/AnalyticsType.cs @@ -0,0 +1,6 @@ +namespace MiniTwitch.Helix.Enums; + +public enum AnalyticsType +{ + OverView_V2 +} diff --git a/MiniTwitch.Helix/Enums/AnnouncementColor.cs b/MiniTwitch.Helix/Enums/AnnouncementColor.cs new file mode 100644 index 0000000..8c9620d --- /dev/null +++ b/MiniTwitch.Helix/Enums/AnnouncementColor.cs @@ -0,0 +1,10 @@ +namespace MiniTwitch.Helix.Enums; + +public enum AnnouncementColor +{ + Primary, + Blue, + Green, + Orange, + Purple +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Enums/BitsLeaderboardPeriod.cs b/MiniTwitch.Helix/Enums/BitsLeaderboardPeriod.cs new file mode 100644 index 0000000..6fbe351 --- /dev/null +++ b/MiniTwitch.Helix/Enums/BitsLeaderboardPeriod.cs @@ -0,0 +1,10 @@ +namespace MiniTwitch.Helix.Enums; + +public enum BitsLeaderboardPeriod +{ + Day, + Week, + Month, + Year, + All +} diff --git a/MiniTwitch.Helix/Enums/ChatColor.cs b/MiniTwitch.Helix/Enums/ChatColor.cs new file mode 100644 index 0000000..1ae31b0 --- /dev/null +++ b/MiniTwitch.Helix/Enums/ChatColor.cs @@ -0,0 +1,20 @@ +namespace MiniTwitch.Helix.Enums; + +public enum ChatColor +{ + Blue, + BlueViolet, + CadetBlue, + Chocolate, + Coral, + DodgerBlue, + Firebrick, + GoldenRod, + Green, + HotPink, + OrangeRed, + Red, + SeaGreen, + SpringGreen, + YellowGreen +} diff --git a/MiniTwitch.Helix/Enums/ConfigSegmentType.cs b/MiniTwitch.Helix/Enums/ConfigSegmentType.cs new file mode 100644 index 0000000..0b60f1c --- /dev/null +++ b/MiniTwitch.Helix/Enums/ConfigSegmentType.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Enums; + +public enum ConfigSegmentType +{ + Broadcaster, + Developer, + Global +} diff --git a/MiniTwitch.Helix/Enums/ContentLabelid.cs b/MiniTwitch.Helix/Enums/ContentLabelid.cs new file mode 100644 index 0000000..2d041db --- /dev/null +++ b/MiniTwitch.Helix/Enums/ContentLabelid.cs @@ -0,0 +1,10 @@ +namespace MiniTwitch.Helix.Enums; + +public enum ContentLabelid +{ + DrugsIntoxication, + SexualThemes, + ViolentGraphic, + Gambling, + ProfanityVulgarity +} diff --git a/MiniTwitch.Helix/Enums/EventSubStatus.cs b/MiniTwitch.Helix/Enums/EventSubStatus.cs new file mode 100644 index 0000000..0ccac06 --- /dev/null +++ b/MiniTwitch.Helix/Enums/EventSubStatus.cs @@ -0,0 +1,20 @@ +namespace MiniTwitch.Helix.Enums; + +public enum EventSubStatus +{ + Enabled, + WebhookCallbackVerificationPending, + WebhookCallbackVerificationFailed, + NotificationFailuresExceeded, + AuthorizationRevoked, + ModeratorRemoved, + UserRemoved, + VersionRemoved, + WebsocketDisconnected, + WebsocketFailedPingPong, + WebsocketReceivedInboundTraffic, + WebsocketConnectionUnused, + WebsocketInternalError, + WebsocketNetworkTimeout, + WebsocketNetworkError +} diff --git a/MiniTwitch.Helix/Enums/FulfillmentStatus.cs b/MiniTwitch.Helix/Enums/FulfillmentStatus.cs new file mode 100644 index 0000000..f749027 --- /dev/null +++ b/MiniTwitch.Helix/Enums/FulfillmentStatus.cs @@ -0,0 +1,7 @@ +namespace MiniTwitch.Helix.Enums; + +public enum FulfillmentStatus +{ + CLAIMED, + FULFILLED +} diff --git a/MiniTwitch.Helix/Enums/LabelLocale.cs b/MiniTwitch.Helix/Enums/LabelLocale.cs new file mode 100644 index 0000000..94b970b --- /dev/null +++ b/MiniTwitch.Helix/Enums/LabelLocale.cs @@ -0,0 +1,34 @@ +namespace MiniTwitch.Helix.Enums; + +public enum LabelLocale +{ + bg_BG, + cs_CZ, + da_DK, + de_DE, + el_GR, + en_GB, + en_US, + es_ES, + es_MX, + fi_FI, + fr_FR, + hu_HU, + it_IT, + ja_JP, + ko_KR, + nl_NL, + no_NO, + pl_PL, + pt_BT, + pt_PT, + ro_RO, + ru_RU, + sk_SK, + sv_SE, + th_TH, + tr_TR, + vi_VN, + zh_CN, + zh_TW +} diff --git a/MiniTwitch.Helix/Enums/RewardRedemptionStatus.cs b/MiniTwitch.Helix/Enums/RewardRedemptionStatus.cs new file mode 100644 index 0000000..c477e27 --- /dev/null +++ b/MiniTwitch.Helix/Enums/RewardRedemptionStatus.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Enums; + +public enum RewardRedemptionStatus +{ + CANCELED, + FULFILLED, + UNFULFILLED +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Enums/SortMethod.cs b/MiniTwitch.Helix/Enums/SortMethod.cs new file mode 100644 index 0000000..5034a7f --- /dev/null +++ b/MiniTwitch.Helix/Enums/SortMethod.cs @@ -0,0 +1,7 @@ +namespace MiniTwitch.Helix.Enums; + +public enum SortMethod +{ + OLDEST, + NEWEST +} diff --git a/MiniTwitch.Helix/Enums/StreamTypes.cs b/MiniTwitch.Helix/Enums/StreamTypes.cs new file mode 100644 index 0000000..f22503f --- /dev/null +++ b/MiniTwitch.Helix/Enums/StreamTypes.cs @@ -0,0 +1,7 @@ +namespace MiniTwitch.Helix.Enums; + +public enum StreamTypes +{ + All, + Live +} diff --git a/MiniTwitch.Helix/Enums/VideoPeriod.cs b/MiniTwitch.Helix/Enums/VideoPeriod.cs new file mode 100644 index 0000000..49b4793 --- /dev/null +++ b/MiniTwitch.Helix/Enums/VideoPeriod.cs @@ -0,0 +1,9 @@ +namespace MiniTwitch.Helix.Enums; + +public enum VideoPeriod +{ + All, + Day, + Month, + Week +} diff --git a/MiniTwitch.Helix/Enums/VideoSortMethod.cs b/MiniTwitch.Helix/Enums/VideoSortMethod.cs new file mode 100644 index 0000000..2ac7c98 --- /dev/null +++ b/MiniTwitch.Helix/Enums/VideoSortMethod.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Enums; + +public enum VideoSortMethod +{ + Time, + Trending, + Views +} diff --git a/MiniTwitch.Helix/Enums/VideoType.cs b/MiniTwitch.Helix/Enums/VideoType.cs new file mode 100644 index 0000000..8d9af85 --- /dev/null +++ b/MiniTwitch.Helix/Enums/VideoType.cs @@ -0,0 +1,9 @@ +namespace MiniTwitch.Helix.Enums; + +public enum VideoType +{ + All, + Archive, + Highlight, + Upload +} diff --git a/MiniTwitch.Helix/HelixWrapper.cs b/MiniTwitch.Helix/HelixWrapper.cs new file mode 100644 index 0000000..ba38e78 --- /dev/null +++ b/MiniTwitch.Helix/HelixWrapper.cs @@ -0,0 +1,984 @@ +using Microsoft.Extensions.Logging; +using MiniTwitch.Common; +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Internal; +using MiniTwitch.Helix.Models; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix; + +/// +/// Wraps all Helix endpoints and exposes them directly as methods. +/// +public class HelixWrapper +{ + /// + /// The default logger for , only used when is not provided in the constructor + /// Can be toggled with + /// + public DefaultMiniTwitchLogger DefaultLogger => _all.ApiClient.Logger; + + private readonly AllCategories _all; + + public HelixWrapper(string bearerToken, string clientId, ILogger? logger = null, + string helixBaseUrl = "https://api.twitch.tv/helix", string tokenValidationUrl = "https://id.twitch.tv/oauth2/validate") + { + _all = new(new HelixApiClient(bearerToken, clientId, logger, tokenValidationUrl), helixBaseUrl); + } + + public Task> StartCommercial( + NewCommercial body, + CancellationToken cancellationToken = default) + => _all.StartCommercial(body, cancellationToken); + + public Task> GetExtensionAnalytics( + string? extensionId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionAnalytics(extensionId, type, startedAt, endedAt, first, cancellationToken); + + public Task> GetGameAnalytics( + string? gameId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetGameAnalytics(gameId, type, startedAt, endedAt, first, cancellationToken); + + public Task> GetBitsLeaderboard( + int? count = null, + BitsLeaderboardPeriod? period = null, + DateTime? startedAt = null, + long? UserId = null, + CancellationToken cancellationToken = default) + => _all.GetBitsLeaderboard(count, period, startedAt, UserId, cancellationToken); + + public Task> GetCheermotes( + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetCheermotes(broadcasterId, cancellationToken); + + public Task> GetExtensionTransactions( + string extensionId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionTransactions(extensionId, id, first, cancellationToken); + + public Task> GetExtensionTransactions( + string extensionId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionTransactions(extensionId, ids, first, cancellationToken); + + public Task> GetChannelInformation( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelInformation(broadcasterId, cancellationToken); + + public Task> GetChannelInformation( + IEnumerable broadcasterIds, + CancellationToken cancellationToken = default) + => _all.GetChannelInformation(broadcasterIds, cancellationToken); + + public Task ModifyChannelInformation( + long broadcasterId, + NewChannelInformation body, + CancellationToken cancellationToken = default) + => _all.ModifyChannelInformation(broadcasterId, body, cancellationToken); + + public Task> GetChannelEditors( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelEditors(broadcasterId, cancellationToken); + + public Task> GetFollowedChannels( + long userId, + long? broadcasterId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetFollowedChannels(userId, broadcasterId, first, cancellationToken); + + public Task> GetChannelFollowers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelFollowers(broadcasterId, userId, first, cancellationToken); + + public Task> CreateCustomReward( + long broadcasterId, + NewCustomReward body, + CancellationToken cancellationToken = default) + => _all.CreateCustomReward(broadcasterId, body, cancellationToken); + + public Task DeleteCustomReward( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + => _all.DeleteCustomReward(broadcasterId, id, cancellationToken); + + public Task> GetCustomReward( + long broadcasterId, + string? id = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + => _all.GetCustomReward(broadcasterId, id, onlyManageableRewards, cancellationToken); + + public Task> GetCustomReward( + long broadcasterId, + IEnumerable? ids = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + => _all.GetCustomReward(broadcasterId, ids, onlyManageableRewards, cancellationToken); + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + string? id = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCustomRewardRedemption(broadcasterId, rewardId, status, id, sort, first, cancellationToken); + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + IEnumerable? ids = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCustomRewardRedemption(broadcasterId, rewardId, status, ids, sort, first, cancellationToken); + + public Task> UpdateCustomReward( + long broadcasterId, + string id, + UpdatedCustomReward body, + CancellationToken cancellationToken = default) + => _all.UpdateCustomReward(broadcasterId, id, body, cancellationToken); + + public Task> UpdateRedemptionStatus( + long broadcasterId, + string id, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + => _all.UpdateRedemptionStatus(broadcasterId, id, rewardId, status, cancellationToken); + + public Task> UpdateRedemptionStatus( + long broadcasterId, + IEnumerable ids, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + => _all.UpdateRedemptionStatus(broadcasterId, ids, rewardId, status, cancellationToken); + + public Task> GetCharityCampaign( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetCharityCampaign(broadcasterId, cancellationToken); + + public Task> GetCharityCampaignDonations( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCharityCampaignDonations(broadcasterId, first, cancellationToken); + + public Task> GetChatters( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChatters(broadcasterId, moderatorId, first, cancellationToken); + + public Task> GetChannelEmotes( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelEmotes(broadcasterId, cancellationToken); + + public Task> GetGlobalEmotes( + CancellationToken cancellationToken = default) + => _all.GetGlobalEmotes(cancellationToken); + + public Task> GetEmoteSets( + string emoteSetId, + CancellationToken cancellationToken = default) + => _all.GetEmoteSets(emoteSetId, cancellationToken); + + public Task> GetEmoteSets( + IEnumerable emoteSetIds, + CancellationToken cancellationToken = default) + => _all.GetEmoteSets(emoteSetIds, cancellationToken); + + public Task> GetChatSettings( + long broadcasterId, + long? moderatorId = null, + CancellationToken cancellationToken = default) + => _all.GetChatSettings(broadcasterId, moderatorId, cancellationToken); + + public Task> UpdateChatSettings( + long broadcasterId, + long moderatorId, + NewChatSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateChatSettings(broadcasterId, moderatorId, body, cancellationToken); + + public Task> GetUserBlockList( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetUserBlockList(broadcasterId, first, cancellationToken); + + public Task SendChatAnnouncement( + long broadcasterId, + long moderatorId, + Announcement body, + CancellationToken cancellationToken = default) + => _all.SendChatAnnouncement(broadcasterId, moderatorId, body, cancellationToken); + + public Task SendAShoutout( + long fromBroadcasterId, + long toBroadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.SendAShoutout(fromBroadcasterId, toBroadcasterId, moderatorId, cancellationToken); + + public Task> GetUserChatColor( + long userId, + CancellationToken cancellationToken = default) + => _all.GetUserChatColor(userId, cancellationToken); + + public Task> GetUserChatColor( + IEnumerable userIds, + CancellationToken cancellationToken = default) + => _all.GetUserChatColor(userIds, cancellationToken); + + public Task UpdateUserChatColor( + long userId, + ChatColor color, + CancellationToken cancellationToken = default) + => _all.UpdateUserChatColor(userId, color, cancellationToken); + + public Task UpdateUserChatColor( + long userId, + string hexColor, + CancellationToken cancellationToken = default) + => _all.UpdateUserChatColor(userId, hexColor, cancellationToken); + + public Task> CreateClip( + long broadcasterId, + bool? hasDelay = null, + CancellationToken cancellationToken = default) + => _all.CreateClip(broadcasterId, hasDelay, cancellationToken); + + public Task> GetClips( + long broadcasterId, + long gameId, + string id, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + => _all.GetClips(broadcasterId, gameId, id, startedAt, endedAt, first, isFeatured, cancellationToken); + + public Task> GetClips( + long broadcasterId, + long gameId, + IEnumerable ids, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + => _all.GetClips(broadcasterId, gameId, ids, startedAt, endedAt, first, isFeatured, cancellationToken); + + public Task> GetContentClassificationLabels( + LabelLocale? locale = null, + CancellationToken cancellationToken = default) + => _all.GetContentClassificationLabels(locale, cancellationToken); + + public Task> GetDropsEntitlements( + string? id = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetDropsEntitlements(id, userId, gameId, fulfillmentStatus, first, cancellationToken); + + public Task> GetDropsEntitlements( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetDropsEntitlements(ids, userId, gameId, fulfillmentStatus, first, cancellationToken); + + public Task> UpdateDropsEntitlements( + IEnumerable? entitlementIds = null, + FulfillmentStatus? fulfillmentStatus = null, + CancellationToken cancellationToken = default) + => _all.UpdateDropsEntitlements(entitlementIds, fulfillmentStatus, cancellationToken); + + public Task> GetExtensionConfigurationSegment( + string extensionId, + ConfigSegmentType segment, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionConfigurationSegment(extensionId, segment, broadcasterId, cancellationToken); + + public Task> GetExtensionConfigurationSegment( + string extensionId, + IEnumerable segments, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionConfigurationSegment(extensionId, segments, broadcasterId, cancellationToken); + + public Task SetExtensionConfigurationSegment( + ConfigurationSegment body, + CancellationToken cancellationToken = default) + => _all.SetExtensionConfigurationSegment(body, cancellationToken); + + public Task SetExtensionRequiredConfiguration( + long broadcasterId, + ExtensionRequiredConfiguration body, + CancellationToken cancellationToken = default) + => _all.SetExtensionRequiredConfiguration(broadcasterId, body, cancellationToken); + + public Task SendExtensionPubSubMessage( + ExtensionPubSubMessage body, + CancellationToken cancellationToken = default) + => _all.SendExtensionPubSubMessage(body, cancellationToken); + + public Task> GetExtensionLiveChannels( + string extensionId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionLiveChannels(extensionId, first, cancellationToken); + + public Task> GetExtensionSecrets( + string extensionId, + CancellationToken cancellationToken = default) + => _all.GetExtensionSecrets(extensionId, cancellationToken); + + public Task> CreateExtensionSecret( + string extensionId, + int? delay = null, + CancellationToken cancellationToken = default) + => _all.CreateExtensionSecret(extensionId, delay, cancellationToken); + + public Task SendExtensionChatMessage( + long broadcasterId, + ExtensionChatMessage body, + CancellationToken cancellationToken = default) + => _all.SendExtensionChatMessage(broadcasterId, body, cancellationToken); + + public Task> GetExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + => _all.GetExtensions(extensionId, extensionVersion, cancellationToken); + + public Task> GetReleasedExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + => _all.GetReleasedExtensions(extensionId, extensionVersion, cancellationToken); + + public Task> GetExtensionBitsProducts( + bool? shouldIncludeAll = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionBitsProducts(shouldIncludeAll, cancellationToken); + + public Task> UpdateExtensionBitsProduct( + UpdatedBitsProduct body, + CancellationToken cancellationToken = default) + => _all.UpdateExtensionBitsProduct(body, cancellationToken); + + public Task> CreateEventSubSubscription( + NewSubscription body, + CancellationToken cancellationToken = default) + => _all.CreateEventSubSubscription(body, cancellationToken); + + public Task DeleteEventSubSubscription( + string id, + CancellationToken cancellationToken = default) + => _all.DeleteEventSubSubscription(id, cancellationToken); + + public Task> GetEventSubSubscriptions( + EventSubStatus? status = null, + string? type = null, + long? userId = null, + CancellationToken cancellationToken = default) + => _all.GetEventSubSubscriptions(status, type, userId, cancellationToken); + + public Task> GetTopGames( + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetTopGames(first, cancellationToken); + + public Task> GetGames( + string? id = null, + string? name = null, + string? igdbId = null, + CancellationToken cancellationToken = default) + => _all.GetGames(id, name, igdbId, cancellationToken); + + public Task> GetGames( + IEnumerable? ids = null, + IEnumerable? names = null, + IEnumerable? igdbIds = null, + CancellationToken cancellationToken = default) + => _all.GetGames(ids, names, igdbIds, cancellationToken); + + public Task> GetCreatorGoals( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetCreatorGoals(broadcasterId, cancellationToken); + + public Task> GetChannelGuestStarSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetChannelGuestStarSettings(broadcasterId, moderatorId, cancellationToken); + + public Task UpdateChannelGuestStarSettings( + NewGuestStarSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateChannelGuestStarSettings(body, cancellationToken); + + public Task> GetGuestStarSession( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetGuestStarSession(broadcasterId, moderatorId, cancellationToken); + + public Task> CreateGuestStarSession( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.CreateGuestStarSession(broadcasterId, cancellationToken); + + public Task> EndGuestStarSession( + long broadcasterId, + string sessionId, + CancellationToken cancellationToken = default) + => _all.EndGuestStarSession(broadcasterId, sessionId, cancellationToken); + + public Task> GetGuestStarInvites( + long broadcasterId, + long moderatorId, + string sessionId, + CancellationToken cancellationToken = default) + => _all.GetGuestStarInvites(broadcasterId, moderatorId, sessionId, cancellationToken); + + public Task SendGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + => _all.SendGuestStarInvite(broadcasterId, moderatorId, sessionId, guestId, cancellationToken); + + public Task DeleteGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + => _all.DeleteGuestStarInvite(broadcasterId, moderatorId, sessionId, guestId, cancellationToken); + + public Task AssignGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + CancellationToken cancellationToken = default) + => _all.AssignGuestStarSlot(broadcasterId, moderatorId, sessionId, guestId, slotId, cancellationToken); + + public Task UpdateGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + string sourceSlotId, + string? destinationSlotId = null, + CancellationToken cancellationToken = default) + => _all.UpdateGuestStarSlot(broadcasterId, moderatorId, sessionId, sourceSlotId, destinationSlotId, cancellationToken); + + public Task DeleteGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + string? shouldReinviteGuest = null, + CancellationToken cancellationToken = default) + => _all.DeleteGuestStarSlot(broadcasterId, moderatorId, sessionId, guestId, slotId, shouldReinviteGuest, cancellationToken); + + public Task UpdateGuestStarSlotSettings( + long broadcasterId, + long moderatorId, + string sessionId, + string slotId, + bool? isAudioEnabled = null, + bool? isVideoEnabled = null, + bool? isLive = null, + int? volume = null, + CancellationToken cancellationToken = default) + => _all.UpdateGuestStarSlotSettings(broadcasterId, moderatorId, sessionId, slotId, isAudioEnabled, isVideoEnabled, isLive, volume, cancellationToken); + + public Task> GetHypeTrainEvents( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetHypeTrainEvents(broadcasterId, first, cancellationToken); + + public Task> CheckAutoModStatus( + long broadcasterId, + MessageToCheck body, + CancellationToken cancellationToken = default) + => _all.CheckAutoModStatus(broadcasterId, body, cancellationToken); + + public Task ManageHeldAutoModMessages( + long userId, + string msgId, + string action, + CancellationToken cancellationToken = default) + => _all.ManageHeldAutoModMessages(userId, msgId, action, cancellationToken); + + public Task> GetAutoModSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetAutoModSettings(broadcasterId, moderatorId, cancellationToken); + + public Task> UpdateAutoModSettings( + long broadcasterId, + long moderatorId, + NewAutoModSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateAutoModSettings(broadcasterId, moderatorId, body, cancellationToken); + + public Task> GetBannedUsers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBannedUsers(broadcasterId, userId, first, cancellationToken); + + public Task> GetBannedUsers( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBannedUsers(broadcasterId, userIds, first, cancellationToken); + + public Task> BanUser( + long broadcasterId, + long moderatorId, + UserToBan body, + CancellationToken cancellationToken = default) + => _all.BanUser(broadcasterId, moderatorId, body, cancellationToken); + + public Task UnbanUser( + long broadcasterId, + long moderatorId, + long userId, + CancellationToken cancellationToken = default) + => _all.UnbanUser(broadcasterId, moderatorId, userId, cancellationToken); + + public Task> GetBlockedTerms( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBlockedTerms(broadcasterId, moderatorId, first, cancellationToken); + + public Task> AddBlockedTerm( + long broadcasterId, + long moderatorId, + string text, + CancellationToken cancellationToken = default) + => _all.AddBlockedTerm(broadcasterId, moderatorId, text, cancellationToken); + + public Task RemoveBlockedTerm( + long broadcasterId, + long moderatorId, + string id, + CancellationToken cancellationToken = default) + => _all.RemoveBlockedTerm(broadcasterId, moderatorId, id, cancellationToken); + + public Task DeleteChatMessages( + long broadcasterId, + long moderatorId, + string? messageId = null, + CancellationToken cancellationToken = default) + => _all.DeleteChatMessages(broadcasterId, moderatorId, messageId, cancellationToken); + + public Task> GetModerators( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetModerators(broadcasterId, userId, first, cancellationToken); + + public Task> GetModerators( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetModerators(broadcasterId, userIds, first, cancellationToken); + + public Task AddChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.AddChannelModerator(broadcasterId, userId, cancellationToken); + + public Task RemoveChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.RemoveChannelModerator(broadcasterId, userId, cancellationToken); + + public Task> GetVIPs( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVIPs(broadcasterId, userId, first, cancellationToken); + + public Task> GetVIPs( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVIPs(broadcasterId, userIds, first, cancellationToken); + + public Task AddChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.AddChannelVIP(broadcasterId, userId, cancellationToken); + + public Task RemoveChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.RemoveChannelVIP(broadcasterId, userId, cancellationToken); + + public Task> UpdateShieldModeStatus( + long broadcasterId, + long moderatorId, + bool isActive, + CancellationToken cancellationToken = default) + => _all.UpdateShieldModeStatus(broadcasterId, moderatorId, isActive, cancellationToken); + + public Task> GetShieldModeStatus( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetShieldModeStatus(broadcasterId, moderatorId, cancellationToken); + + public Task> GetPolls( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPolls(broadcasterId, id, first, cancellationToken); + + public Task> GetPolls( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPolls(broadcasterId, ids, first, cancellationToken); + + public Task> CreatePoll( + NewPoll body, + CancellationToken cancellationToken = default) + => _all.CreatePoll(body, cancellationToken); + + public Task> EndPoll( + long broadcasterId, + string id, + string status, + CancellationToken cancellationToken = default) + => _all.EndPoll(broadcasterId, id, status, cancellationToken); + + public Task> GetPredictions( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPredictions(broadcasterId, id, first, cancellationToken); + + public Task> GetPredictions( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPredictions(broadcasterId, ids, first, cancellationToken); + + public Task> CreatePrediction( + NewPrediction body, + CancellationToken cancellationToken = default) + => _all.CreatePrediction(body, cancellationToken); + + public Task> EndPrediction( + PredictionToEnd body, + CancellationToken cancellationToken = default) + => _all.EndPrediction(body, cancellationToken); + + public Task> StartARaid( + long fromBroadcasterId, + long toBroadcasterId, + CancellationToken cancellationToken = default) + => _all.StartARaid(fromBroadcasterId, toBroadcasterId, cancellationToken); + + public Task CancelARaid( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.CancelARaid(broadcasterId, cancellationToken); + + public Task> GetChannelStreamSchedule( + long broadcasterId, + string? id = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelStreamSchedule(broadcasterId, id, startTime, first, cancellationToken); + + public Task> GetChannelStreamSchedule( + long broadcasterId, + IEnumerable? ids = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelStreamSchedule(broadcasterId, ids, startTime, first, cancellationToken); + + public Task UpdateChannelStreamSchedule( + long broadcasterId, + bool? isVacationEnabled = null, + DateTime? vacationStartTime = null, + DateTime? vacationEndTime = null, + string? timezone = null, + CancellationToken cancellationToken = default) + => _all.UpdateChannelStreamSchedule(broadcasterId, isVacationEnabled, vacationStartTime, vacationEndTime, timezone, cancellationToken); + + public Task> CreateChannelStreamScheduleSegment( + long broadcasterId, + NewScheduleSegment body, + CancellationToken cancellationToken = default) + => _all.CreateChannelStreamScheduleSegment(broadcasterId, body, cancellationToken); + + public Task> UpdateChannelStreamScheduleSegment( + long broadcasterId, + string id, + Requests.UpdatedScheduleSegment Body, + CancellationToken cancellationToken = default) + => _all.UpdateChannelStreamScheduleSegment(broadcasterId, id, Body, cancellationToken); + + public Task DeleteChannelStreamScheduleSegment( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + => _all.DeleteChannelStreamScheduleSegment(broadcasterId, id, cancellationToken); + + public Task> SearchCategories( + string query, + int? first = null, + CancellationToken cancellationToken = default) + => _all.SearchCategories(query, first, cancellationToken); + + public Task> SearchChannels( + string query, + bool? liveOnly = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.SearchChannels(query, liveOnly, first, cancellationToken); + + public Task> GetStreamKey( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetStreamKey(broadcasterId, cancellationToken); + + public Task> GetStreams( + long? userId = null, + string? userLogin = null, + string? gameId = null, + StreamTypes? type = null, + string? language = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreams(userId, userLogin, gameId, type, language, first, cancellationToken); + + public Task> GetStreams( + IEnumerable? userIds = null, + IEnumerable? userLogins = null, + IEnumerable? gameIds = null, + StreamTypes? type = null, + IEnumerable? languages = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreams(userIds, userLogins, gameIds, type, languages, first, cancellationToken); + + public Task> GetFollowedStreams( + long userId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetFollowedStreams(userId, first, cancellationToken); + + public Task> CreateStreamMarker( + long userId, + string? description = null, + CancellationToken cancellationToken = default) + => _all.CreateStreamMarker(userId, description, cancellationToken); + + public Task> GetStreamMarkers( + long userId, + string? videoId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreamMarkers(userId, videoId, first, cancellationToken); + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBroadcasterSubscriptions(broadcasterId, userId, first, cancellationToken); + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBroadcasterSubscriptions(broadcasterId, userIds, first, cancellationToken); + + public Task> CheckUserSubscription( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.CheckUserSubscription(broadcasterId, userId, cancellationToken); + + public Task> GetChannelTeams( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelTeams(broadcasterId, cancellationToken); + + public Task> GetTeams( + string name, + string id, + CancellationToken cancellationToken = default) + => _all.GetTeams(name, id, cancellationToken); + + public Task> GetUsers( + long? id = null, + string? login = null, + CancellationToken cancellationToken = default) + => _all.GetUsers(id, login, cancellationToken); + + public Task> GetUsers( + IEnumerable? id = null, + IEnumerable? login = null, + CancellationToken cancellationToken = default) + => _all.GetUsers(id, login, cancellationToken); + + public Task> UpdateUser( + string? description = null, + CancellationToken cancellationToken = default) + => _all.UpdateUser(description, cancellationToken); + + public Task BlockUser( + long targetUserId, + string? sourceContext = null, + string? reason = null, + CancellationToken cancellationToken = default) + => _all.BlockUser(targetUserId, sourceContext, reason, cancellationToken); + + public Task UnblockUser( + long targetUserId, + CancellationToken cancellationToken = default) + => _all.UnblockUser(targetUserId, cancellationToken); + + public Task> GetUserExtensions( + CancellationToken cancellationToken = default) + => _all.GetUserExtensions(cancellationToken); + + public Task> GetUserActiveExtensions( + long? userId = null, + CancellationToken cancellationToken = default) + => _all.GetUserActiveExtensions(userId, cancellationToken); + + public Task> GetVideos( + string? id = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVideos(id, userId, gameId, language, period, sort, type, first, cancellationToken); + + public Task> GetVideos( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVideos(ids, userId, gameId, language, period, sort, type, first, cancellationToken); + + public Task DeleteVideos( + string id, + CancellationToken cancellationToken = default) + => _all.DeleteVideos(id, cancellationToken); + + public Task DeleteVideos( + IEnumerable ids, + CancellationToken cancellationToken = default) + => _all.DeleteVideos(ids, cancellationToken); + + public Task SendWhisper( + long fromUserId, + long toUserId, + string message, + CancellationToken cancellationToken = default) + => _all.SendWhisper(fromUserId, toUserId, message, cancellationToken); + + public Task> GetAdSchedule( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetAdSchedule(broadcasterId, cancellationToken); + + public Task> SnoozeNextAd( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.SnoozeNextAd(broadcasterId, cancellationToken); + + public Task> GetChannelChatBadges( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelChatBadges(broadcasterId, cancellationToken); + + public Task> GetGlobalChatBadges( + CancellationToken cancellationToken = default) + => _all.GetGlobalChatBadges(cancellationToken); + +} diff --git a/MiniTwitch.Helix/Interfaces/IHelixResult.cs b/MiniTwitch.Helix/Interfaces/IHelixResult.cs new file mode 100644 index 0000000..ebb094a --- /dev/null +++ b/MiniTwitch.Helix/Interfaces/IHelixResult.cs @@ -0,0 +1,11 @@ +using System.Net; + +namespace MiniTwitch.Helix.Interfaces; + +public interface IHelixResult +{ + HttpStatusCode StatusCode { get; } + string Message { get; } + TimeSpan Elapsed { get; } + bool Success { get; } +} diff --git a/MiniTwitch.Helix/Interfaces/IPaginable.cs b/MiniTwitch.Helix/Interfaces/IPaginable.cs new file mode 100644 index 0000000..803ab50 --- /dev/null +++ b/MiniTwitch.Helix/Interfaces/IPaginable.cs @@ -0,0 +1,8 @@ +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Interfaces; + +public interface IPaginable +{ + public Pagination Pagination { get; } +} diff --git a/MiniTwitch.Helix/Internal/HelixApiClient.cs b/MiniTwitch.Helix/Internal/HelixApiClient.cs new file mode 100644 index 0000000..2c9ef2e --- /dev/null +++ b/MiniTwitch.Helix/Internal/HelixApiClient.cs @@ -0,0 +1,176 @@ +using System.Diagnostics; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.Logging; +using MiniTwitch.Common; +using MiniTwitch.Helix.Internal.Json; +using MiniTwitch.Helix.Internal.Models; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Internal; + +internal sealed class HelixApiClient +{ + public DefaultMiniTwitchLogger Logger { get; } = new(); + public JsonSerializerOptions SerializerOptions { get; init; } = new() + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + NumberHandling = JsonNumberHandling.AllowReadingFromString, + PropertyNamingPolicy = new SnakeCaseNamingPolicy() + }; + + private readonly HttpClient _httpClient = new(); + private readonly string _tokenValidationUrl; + private readonly ILogger? _logger; + private ValidToken? _tokenInfo; + + public HelixApiClient(string token, string clientId, ILogger? logger, string tokenValidationUrl) + { + _httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {token}"); + _httpClient.DefaultRequestHeaders.Add("Client-Id", $"{clientId}"); + _tokenValidationUrl = tokenValidationUrl; + _logger = logger; + } + + public Task<(HttpResponseMessage, long)> RequestAsync(RequestData requestObject, CancellationToken ct) => requestObject._method switch + { + "POST" => PostAsync(requestObject, ct), + "GET" => GetAsync(requestObject, ct), + "PUT" => PutAsync(requestObject, ct), + "DELETE" => DeleteAsync(requestObject, ct), + "PATCH" => PatchAsync(requestObject, ct), + _ => throw new NotImplementedException($"HTTP method {requestObject._method} is not supported") + }; + + private async Task<(HttpResponseMessage, long)> PostAsync(RequestData requestObject, CancellationToken ct) + { + await ValidateToken(); + string url = requestObject.GetUrl(); + var sw = Stopwatch.StartNew(); + HttpResponseMessage response = await _httpClient.PostAsJsonAsync(url, requestObject.Body, this.SerializerOptions, ct); + sw.Stop(); + long elapsedMs = sw.ElapsedMilliseconds; + LogLevel logLevel = response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning; + Log(logLevel, "POST [{Code}] {Url} {ElapsedMs}ms", response.StatusCode, url, elapsedMs); + return (response, elapsedMs); + } + + private async Task<(HttpResponseMessage, long)> GetAsync(RequestData requestObject, CancellationToken ct) + { + await ValidateToken(); + string url = requestObject.GetUrl(); + var sw = Stopwatch.StartNew(); + HttpResponseMessage response = await _httpClient.GetAsync(url, ct); + sw.Stop(); + long elapsedMs = sw.ElapsedMilliseconds; + LogLevel logLevel = response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning; + Log(logLevel, "GET [{Code}] {Url} {ElapsedMs}ms", response.StatusCode, url, elapsedMs); + return (response, elapsedMs); + } + + private async Task<(HttpResponseMessage, long)> PutAsync(RequestData requestObject, CancellationToken ct) + { + await ValidateToken(); + string url = requestObject.GetUrl(); + var sw = Stopwatch.StartNew(); + HttpResponseMessage response = await _httpClient.PutAsJsonAsync(url, requestObject.Body, this.SerializerOptions, ct); + sw.Stop(); + long elapsedMs = sw.ElapsedMilliseconds; + LogLevel logLevel = response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning; + Log(logLevel, "PUT [{Code}] {Url} {ElapsedMs}ms", response.StatusCode, url, elapsedMs); + return (response, elapsedMs); + } + + private async Task<(HttpResponseMessage, long)> DeleteAsync(RequestData requestObject, CancellationToken ct) + { + await ValidateToken(); + string url = requestObject.GetUrl(); + var sw = Stopwatch.StartNew(); + HttpResponseMessage response = await _httpClient.DeleteAsync(url, ct); + sw.Stop(); + long elapsedMs = sw.ElapsedMilliseconds; + LogLevel logLevel = response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning; + Log(logLevel, "DELETE [{Code}] {Url} {ElapsedMs}ms", response.StatusCode, url, elapsedMs); + return (response, elapsedMs); + } + + private async Task<(HttpResponseMessage, long)> PatchAsync(RequestData requestObject, CancellationToken ct) + { + await ValidateToken(); + string url = requestObject.GetUrl(); + string rawContent = JsonSerializer.Serialize(requestObject.Body, this.SerializerOptions); + var content = new StringContent(rawContent, Encoding.UTF8, "application/json"); + var sw = Stopwatch.StartNew(); + HttpResponseMessage response = await _httpClient.PatchAsync(url, content, ct); + sw.Stop(); + long elapsedMs = sw.ElapsedMilliseconds; + LogLevel logLevel = response.IsSuccessStatusCode ? LogLevel.Debug : LogLevel.Warning; + Log(logLevel, "PATCH [{Code}] {Url} {ElapsedMs}ms", response.StatusCode, url, elapsedMs); + return (response, elapsedMs); + } + + private async ValueTask ValidateToken() + { + long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + if (_tokenInfo is not null) + { + var expiresIn = TimeSpan.FromSeconds(_tokenInfo.ReceivedAt + _tokenInfo.ExpiresIn - now); + if (_tokenInfo.IsPermaToken) + { + Log(LogLevel.Trace, "Request sent with access token from user {Username} [No expiry]", _tokenInfo.Login); + return; + } + + switch (expiresIn) + { + case { TotalSeconds: <= -1 }: + throw new InvalidTokenException(null, $"Access token for user \"{_tokenInfo.Login}\" has expired"); + case { TotalHours: < 0 }: + Log(LogLevel.Warning, "Access token for user {Username} expires in {ExpiresInMinutes} minutes", expiresIn.Minutes); + break; + case { TotalDays: < 0 }: + Log(LogLevel.Warning, "Access token for user {Username} expires in {ExpiresInHours} hours", expiresIn.Hours); + break; + default: + Log(LogLevel.Trace, "Request sent with access token from user {Username} [Expires in: {ExpiresIn}]", expiresIn); + break; + } + + return; + } + + HttpResponseMessage response = await _httpClient.GetAsync(_tokenValidationUrl); + if (!response.IsSuccessStatusCode) + { + InvalidToken? invalid = await response.Content.ReadFromJsonAsync(); + throw new InvalidTokenException(invalid?.Message, "Provided access token is either invalid or has expired"); + } + + _tokenInfo = await response.Content.ReadFromJsonAsync(); + if (_tokenInfo is null) + return; + + _tokenInfo.ReceivedAt = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + if (_tokenInfo.IsPermaToken) + { + Log( + LogLevel.Information, + "Validated permanent access token from user {Username} with {ScopeCount} scopes", + _tokenInfo.Login, _tokenInfo.Scopes.Count + ); + + return; + } + + Log( + LogLevel.Information, + "Validated access token from user {Username} with {ScopeCount} scopes. The token expires at {ExpiresAt}", + _tokenInfo.Login, _tokenInfo.Scopes.Count, DateTimeOffset.FromUnixTimeSeconds(_tokenInfo.ReceivedAt + _tokenInfo.ExpiresIn) + ); + } + + private void Log(LogLevel level, string template, params object[] properties) => GetLogger().Log(level, "[MiniTwitch.Helix] " + template, properties); + private ILogger GetLogger() => _logger ?? this.Logger; +} diff --git a/MiniTwitch.Helix/Internal/HelixResultFactory.cs b/MiniTwitch.Helix/Internal/HelixResultFactory.cs new file mode 100644 index 0000000..fb2a9e7 --- /dev/null +++ b/MiniTwitch.Helix/Internal/HelixResultFactory.cs @@ -0,0 +1,125 @@ +using System.Net.Http.Json; +using MiniTwitch.Helix.Internal.Models; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Internal; + +internal static class HelixResultFactory +{ + private const string HEADER_RL_LIMIT = "Ratelimit-Limit"; + private const string HEADER_RL_REMAINING = "Ratelimit-Remaining"; + private const string HEADER_RL_RESET = "Ratelimit-Reset"; + + public static async Task> Create(HelixApiClient client, RequestData request, HelixEndpoint endpoint, + CancellationToken cancellationToken) + { + (HttpResponseMessage response, long elapsedMs) = await client.RequestAsync(request, cancellationToken); + // Because some endpoints don't have appropriate success status codes, .IsSuccessStatusCode should be checked first + if (!response.IsSuccessStatusCode && response.StatusCode != endpoint.SuccessStatusCode) + { + return new HelixResult() + { + Success = false, + Message = endpoint.GetResponseMessage(response.StatusCode), + StatusCode = response.StatusCode, + Elapsed = TimeSpan.FromMilliseconds(elapsedMs), + Value = default! + }; + } + + T? toObject; + try + { + toObject = await response.Content.ReadFromJsonAsync(cancellationToken: cancellationToken); + if (toObject is null) + { + return new HelixResult() + { + Success = false, + Message = "Unknown deserialization failure.\n\n" + + await response.Content.ReadAsStringAsync(cancellationToken), + StatusCode = response.StatusCode, + Elapsed = TimeSpan.FromMilliseconds(elapsedMs), + Value = toObject!, + Ratelimit = GetRateLimit(response) + }; + } + } + catch (Exception ex) + { + return new HelixResult() + { + Success = false, + Message = $"Deserialization failure.\n" + + $"{ex.Message}\n" + + $"{ex.StackTrace}\n\n" + + await response.Content.ReadAsStringAsync(cancellationToken), + StatusCode = response.StatusCode, + Elapsed = TimeSpan.FromMilliseconds(elapsedMs), + Value = default! + }; + } + + return new HelixResult() + { + Success = true, + Message = endpoint.GetResponseMessage(response.StatusCode), + StatusCode = response.StatusCode, + Elapsed = TimeSpan.FromMilliseconds(elapsedMs), + Value = toObject, + HelixTask = new() { Endpoint = endpoint, Client = client, Request = request }, + Ratelimit = GetRateLimit(response) + }; + } + + public static async Task Create(HelixApiClient client, RequestData request, HelixEndpoint endpoint, + CancellationToken cancellationToken) + { + (HttpResponseMessage response, long elapsedMs) = await client.RequestAsync(request, cancellationToken); + return new HelixResult() + { + Success = response.StatusCode == endpoint.SuccessStatusCode, + Message = endpoint.GetResponseMessage(response.StatusCode), + StatusCode = response.StatusCode, + Elapsed = TimeSpan.FromMilliseconds(elapsedMs), + Ratelimit = GetRateLimit(response) + }; + } + + private static RequestRatelimit GetRateLimit(HttpResponseMessage response) + { + long now = DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + int limit = 0; + int remaining = 0; + int resets = 0; + int val; + foreach (KeyValuePair> header in response.Headers) + { + switch (header.Key) + { + case HEADER_RL_LIMIT: + limit = int.TryParse(header.Value.FirstOrDefault(), out val) ? val : 0; + break; + + case HEADER_RL_REMAINING: + remaining = int.TryParse(header.Value.FirstOrDefault(), out val) ? val : 0; + break; + + case HEADER_RL_RESET: + resets = int.TryParse(header.Value.FirstOrDefault(), out val) ? val : 0; + break; + + default: + continue; + } + } + + TimeSpan resetsIn = resets - now < 0 ? TimeSpan.Zero : TimeSpan.FromSeconds(resets - now); + return new() + { + Limit = limit, + Remaining = remaining, + ResetsIn = resetsIn + }; + } +} diff --git a/MiniTwitch.Helix/Internal/Json/EnumToString.cs b/MiniTwitch.Helix/Internal/Json/EnumToString.cs new file mode 100644 index 0000000..e411739 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/EnumToString.cs @@ -0,0 +1,30 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Json; + +internal class EnumToString : JsonConverter + where ICase : ICaseConverter, new() +{ + private static readonly ICaseConverter _case = new ICase(); + + public override TEnum Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + string? enumAsString = reader.GetString(); + if (Enum.TryParse(typeof(TEnum), _case.ConvertFromCase(enumAsString), out object? enumMember)) + return (TEnum)enumMember!; + } + + throw new JsonException(); + } + + public override void Write(Utf8JsonWriter writer, TEnum value, JsonSerializerOptions options) + { + if (value is null) + writer.WriteNullValue(); + else + writer.WriteStringValue(_case.ConvertToCase(value.ToString())); + } +} diff --git a/MiniTwitch.Helix/Internal/Json/ICaseConverter.cs b/MiniTwitch.Helix/Internal/Json/ICaseConverter.cs new file mode 100644 index 0000000..2cb8ff8 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/ICaseConverter.cs @@ -0,0 +1,7 @@ +namespace MiniTwitch.Helix.Internal.Json; + +internal interface ICaseConverter +{ + string? ConvertToCase(string? str); + string? ConvertFromCase(string? str); +} diff --git a/MiniTwitch.Helix/Internal/Json/IntToString.cs b/MiniTwitch.Helix/Internal/Json/IntToString.cs new file mode 100644 index 0000000..46593ff --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/IntToString.cs @@ -0,0 +1,12 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Json; + +internal class IntToString : JsonConverter +{ + public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => throw new NotSupportedException("Converter should only be used for writing"); + + public override void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString()); +} diff --git a/MiniTwitch.Helix/Internal/Json/LongToString.cs b/MiniTwitch.Helix/Internal/Json/LongToString.cs new file mode 100644 index 0000000..8ae24c1 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/LongToString.cs @@ -0,0 +1,12 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Json; + +internal class LongToString : JsonConverter +{ + public override long Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => throw new NotSupportedException("Converter should only be used for writing"); + + public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) => writer.WriteStringValue(value.ToString()); +} diff --git a/MiniTwitch.Helix/Internal/Json/SnakeCase.cs b/MiniTwitch.Helix/Internal/Json/SnakeCase.cs new file mode 100644 index 0000000..d96efe5 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/SnakeCase.cs @@ -0,0 +1,56 @@ +namespace MiniTwitch.Helix.Internal.Json; + +internal class SnakeCase : ICaseConverter +{ + public static SnakeCase Instance { get; } = new(); + + public string? ConvertFromCase(string? str) + { + if (str is null) + return null; + + const char underscore = '_'; + + ReadOnlySpan chars = str; + Span replacement = stackalloc char[chars.Length]; + int i = 1; + int offset = 0; + replacement[0] = char.ToUpper(chars[0]); + for (; i < chars.Length - offset; i++) + { + char c = chars[i + offset]; + replacement[i] = c == underscore ? char.ToUpper(chars[i + ++offset]) : c; + } + + return replacement[..i].ToString(); + } + + public string? ConvertToCase(string? str) + { + if (str is null) + return null; + + const char underscore = '_'; + + ReadOnlySpan chars = str; + Span replacement = stackalloc char[chars.Length * 2]; + int i = 1; + int offset = 0; + replacement[0] = char.ToLower(chars[0]); + for (; i < chars.Length; i++) + { + char c = chars[i]; + if (char.IsUpper(c)) + { + replacement[i + offset++] = underscore; + replacement[i + offset] = char.ToLower(c); + } + else + { + replacement[i + offset] = c; + } + } + + return replacement[..(i + offset)].ToString(); + } +} diff --git a/MiniTwitch.Helix/Internal/Json/SnakeCaseNamingPolicy.cs b/MiniTwitch.Helix/Internal/Json/SnakeCaseNamingPolicy.cs new file mode 100644 index 0000000..6e3f8d8 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/SnakeCaseNamingPolicy.cs @@ -0,0 +1,32 @@ +using System.Text.Json; + +namespace MiniTwitch.Helix.Internal.Json; + +internal class SnakeCaseNamingPolicy : JsonNamingPolicy +{ + public override string ConvertName(string name) + { + const char underscore = '_'; + + ReadOnlySpan chars = name; + Span replacement = stackalloc char[chars.Length * 2]; + int i = 1; + int offset = 0; + replacement[0] = char.ToLower(chars[0]); + for (; i < chars.Length; i++) + { + char c = chars[i]; + if (char.IsUpper(c)) + { + replacement[i + offset++] = underscore; + replacement[i + offset] = char.ToLower(c); + } + else + { + replacement[i + offset] = c; + } + } + + return replacement[..(i + offset)].ToString(); + } +} diff --git a/MiniTwitch.Helix/Internal/Json/TimeSpanToSeconds.cs b/MiniTwitch.Helix/Internal/Json/TimeSpanToSeconds.cs new file mode 100644 index 0000000..8a7f508 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Json/TimeSpanToSeconds.cs @@ -0,0 +1,12 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Json; + +internal class TimeSpanToSeconds : JsonConverter +{ + public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => throw new NotSupportedException("Converter should only be used for writing"); + + public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) => writer.WriteNumberValue((int)value.TotalSeconds); +} diff --git a/MiniTwitch.Helix/Internal/Models/Endpoints.cs b/MiniTwitch.Helix/Internal/Models/Endpoints.cs new file mode 100644 index 0000000..9383662 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/Endpoints.cs @@ -0,0 +1,1901 @@ +using System.Net; + +namespace MiniTwitch.Helix.Internal.Models; + +// Values scraped from https://dev.twitch.tv/docs/api/reference/ +// If you see anything wrong, please open an issue! +internal static class Endpoints +{ + public static readonly HelixEndpoint StartCommercial = new() + { + Method = HttpMethod.Post, + Route = "/channels/commercial", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully started the commercial.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe length query parameter is required.\r\nThe ID in broadcaster_id is not valid.\r\nTo start a commercial, the broadcaster must be streaming live.\r\nThe broadcaster may not run another commercial until the cooldown period expires.\r\n The retry_after field in the previous start commercial response specifies the amount of time the broadcaster must wait between running commercials.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the request's OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:edit:commercial scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.NotFound => "The ID in broadcaster_id was not found.", + HttpStatusCode.TooManyRequests => "The broadcaster may not run another commercial until the cooldown period expires.\r\n The retry_after field in the previous start commercial response specifies the amount of time the broadcaster must wait between running commercials.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionAnalytics = new() + { + Method = HttpMethod.Get, + Route = "/analytics/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's analytics reports.", + HttpStatusCode.BadRequest => "The start and end dates are optional but if you specify one, you must specify the other.\r\nThe end date must be equal to or later than the start date.\r\nThe cursor specified in the after query parameter is not valid.\r\nThe resource supports only forward pagination (use the after query parameter).\r\nThe first query parameter is outside the allowed range of values.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the analytics:read:extensions scope.\r\nThe OAuth token is not valid.\r\nThe Client-Id header is required.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.NotFound => "The extension specified in the extension_id query parameter was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGameAnalytics = new() + { + Method = HttpMethod.Get, + Route = "/analytics/games", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's analytics reports.", + HttpStatusCode.BadRequest => "The start and end dates are optional but if you specify one, you must specify the other.\r\nThe end date must be equal to or later than the start date.\r\nThe cursor specified in the after query parameter is not valid.\r\nThe resource supports only forward pagination (use the after query parameter).\r\nThe first query parameter is outside the allowed range of values.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the analytics:read:games scope.\r\nThe OAuth token is not valid.\r\nThe Client-Id header is required.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.NotFound => "The game specified in the game_id query parameter was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetBitsLeaderboard = new() + { + Method = HttpMethod.Get, + Route = "/bits/leaderboard", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's Bits leaderboard.", + HttpStatusCode.BadRequest => "The time period specified in the period query parameter is not valid.\r\nThe started_at query parameter is required if period is not set to all.\r\nThe value in the count query parameter is outside the range of allowed values.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token must include the the bits:read scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCheermotes = new() + { + Method = HttpMethod.Get, + Route = "/bits/cheermotes", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the Cheermotes.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionTransactions = new() + { + Method = HttpMethod.Get, + Route = "/extensions/transactions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of transactions.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.\r\nThe request specified too many id query parameters.\r\nThe pagination cursor is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token.\r\nThe access token is not valid.\r\nThe ID in the extension_id query parameter must match the client ID in the access token.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "One or more of the transaction IDs specified using the id query parameter were not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelInformation = new() + { + Method = HttpMethod.Get, + Route = "/channels", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of channels.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe broadcaster ID is not valid.\r\nThe number of broadcaster_id query parameters exceeds the maximum allowed.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.TooManyRequests => "The application exceeded the number of calls it may make per minute.\r\n For details, see Rate Limits.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint ModifyChannelInformation = new() + { + Method = HttpMethod.Patch, + Route = "/channels", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated the channel's properties.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe request must update at least one property.\r\nThe title field may not contain an empty string.\r\nThe ID in game_id is not valid.\r\nTo update the delay field, the broadcaster must have partner status.\r\nThe list in the tags field exceeds the maximum number of tags allowed.\r\nA tag in the tags field exceeds the maximum length allowed.\r\nA tag in the tags field is empty.\r\nA tag in the tags field contains special characters or spaces.\r\nOne or more tags in the tags field failed AutoMod review.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the OAuth token.\r\nThe Authorization header is required and must specify a user access token.\r\nThe OAuth token must include the channel:manage:broadcast scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelEditors = new() + { + Method = HttpMethod.Get, + Route = "/channels/editors", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of editors.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID found in the OAuth token.\r\nThe Authorization header is required and must specify a user access token.\r\nThe OAuth token must include the channel:read:editors scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetFollowedChannels = new() + { + Method = HttpMethod.Get, + Route = "/channels/followed", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of followers.", + HttpStatusCode.BadRequest => "Possible reasons:The user_id query parameter is required.\r\nThe broadcaster_id query parameter is not valid.\r\nThe user_id query parameter is required.", + HttpStatusCode.Unauthorized => "Possible reasons:The ID in the user_id query parameter must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token is missing the user:read:follows scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelFollowers = new() + { + Method = HttpMethod.Get, + Route = "/channels/followers", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of followers.", + HttpStatusCode.BadRequest => "Possible reasons:The broadcaster_id query parameter is required.\r\nThe broadcaster_id query parameter is not valid.\r\nThe user_id query parameter is required.", + HttpStatusCode.Unauthorized => "Possible reasons:The ID in the broadcaster_id query parameter must match the user ID in the access token or the user must be a moderator for the specified broadcaster.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token is missing the moderator:read:followers scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateCustomRewards = new() + { + Method = HttpMethod.Post, + Route = "/channel_points/custom_rewards", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the custom reward.", + HttpStatusCode.BadRequest => "The request exceeds the maximum number of rewards allowed per channel.\r\nThe broadcaster_id query parameter is required.\r\nThe title field is required.\r\nThe title must contain a minimum of 1 character and a maximum of 45 characters.\r\nThe title must be unique amongst all of the broadcaster's custom rewards.\r\nThe cost field is required.\r\nThe cost field must contain a minimum of 1 point.\r\nThe prompt field is limited to a maximum of 200 characters.\r\nIf is_max_per_stream_enabled is true, the minimum value for max_per_stream is 1.\r\nIf is_max_per_user_per_stream_enabled is true, the minimum value for max_per_user_per_stream is 1.\r\nIf is_global_cooldown_enabled is true, the minimum value for global_cooldown_seconds is 1.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token is missing the channel:manage:redemptions scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The broadcaster is not a partner or affiliate.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteCustomReward = new() + { + Method = HttpMethod.Delete, + Route = "/channel_points/custom_rewards", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully deleted the custom reward.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token must include the channel:manage:redemptions scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The ID in the Client-Id header must match the client ID used to create the custom reward.\r\nThe broadcaster is not a partner or affiliate.", + HttpStatusCode.NotFound => "The custom reward specified in the id query parameter was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCustomReward = new() + { + Method = HttpMethod.Get, + Route = "/channel_points/custom_rewards", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of custom rewards.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe request exceeds the maximum number of id query parameters that you may specify.", + HttpStatusCode.Unauthorized => "The Authorization header must specify a user access token.\r\nThe user access token must include the channel:read:redemptions scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The broadcaster is not a partner or affiliate.", + HttpStatusCode.NotFound => "All of the custom rewards specified using the id query parameter were not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCustomRewardRedemption = new() + { + Method = HttpMethod.Get, + Route = "/channel_points/custom_rewards/redemptions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of redeemed custom rewards.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe reward_id query parameter is required.\r\nThe status query parameter is required if you didn't specify the id query parameter.\r\nThe value in the status query parameter is not valid.\r\nThe value in the sort query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token must include the channel:read:redemptions scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The ID in the Client-Id header must match the client ID used to create the custom reward.\r\nThe broadcaster is not a partner or affiliate.", + HttpStatusCode.NotFound => "All of the redemptions specified using the id query parameter were not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateCustomReward = new() + { + Method = HttpMethod.Patch, + Route = "/channel_points/custom_rewards", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the custom reward.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe id query parameter is required.\r\nThe title must contain a minimum of 1 character and a maximum of 45 characters.\r\nThe title must be unique amongst all of the broadcaster's custom rewards.\r\nThe cost field must contain a minimum of 1 point.\r\nThe prompt field is limited to a maximum of 200 characters.\r\nIf is_max_per_stream_enabled is true, the minimum value for max_per_stream is 1.\r\nIf is_max_per_user_per_stream_enabled is true, the minimum value for max_per_user_per_stream is 1.\r\nIf is_global_cooldown_enabled is true, the minimum value for global_cooldown_seconds is 1 and the maximum is 604800.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token must include the channel:manage:redemptions scope.\r\nThe OAuth token is not valide.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The ID in the Client-Id header must match the client ID used to create the custom reward.\r\nThe broadcaster is not a partner or affiliate.", + HttpStatusCode.NotFound => "The custom reward specified in the id query parameter was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateRedemptionStatus = new() + { + Method = HttpMethod.Patch, + Route = "/channel_points/custom_rewards/redemptions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the redemption's status.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe reward_id query parameter is required.\r\nThe id query parameter is required.\r\nThe value in the status query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a user access token.\r\nThe user access token must include the channel:manage:redemptions scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The ID in the Client-Id header must match the client ID used to create the custom reward.\r\nThe broadcaster is not a partner or affiliate.", + HttpStatusCode.NotFound => "The custom reward specified in the reward_id query parameter was not found.\r\nThe redemptions specified using the id query parameter were not found or their statuses weren't marked as UNFULFILLED.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCharityCampaign = new() + { + Method = HttpMethod.Get, + Route = "/charity/campaigns", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved information about the broadcaster's active charity campaign.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe broadcaster_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:charity scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header must match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The broadcaster is not a partner or affiliate.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCharityCampaignDonations = new() + { + Method = HttpMethod.Get, + Route = "/charity/donations", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of donations that users contributed to the broadcaster's charity campaign.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe broadcaster_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:charity scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header must match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The broadcaster is not a partner or affiliate.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChatters = new() + { + Method = HttpMethod.Get, + Route = "/chat/chatters", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of chatters.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe moderator_id query parameter is required.\r\nThe ID in the moderator_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in the moderator_id query parameter must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:read:chatters scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in the moderator_id query parameter is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelEmotes = new() + { + Method = HttpMethod.Get, + Route = "/chat/emotes", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved broadcaster's list of custom emotes.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGlobalEmotes = new() + { + Method = HttpMethod.Get, + Route = "/chat/emotes/global", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved Twitch's list of global emotes.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetEmoteSets = new() + { + Method = HttpMethod.Get, + Route = "/chat/emotes/set", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the emotes for the specified emote sets.", + HttpStatusCode.BadRequest => "The emote_set_id query parameter is required.\r\nThe number of emote_set_id query parameters exceeds the maximum allowed.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelChatBadges = new() + { + Method = HttpMethod.Get, + Route = "/chat/badges", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's custom chat badges.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGlobalChatBadges = new() + { + Method = HttpMethod.Get, + Route = "/chat/badges/global", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of global chat badges.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChatSettings = new() + { + Method = HttpMethod.Get, + Route = "/chat/settings", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's chat settings.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateChatSettings = new() + { + Method = HttpMethod.Patch, + Route = "/chat/settings", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the broadcaster's chat settings.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.\r\nIf slow_mode is true, the slow_mode_wait_time field must be set to a valid value.\r\nIf follower_mode is true, the follower_mode_duration field must be set to a valid value.\r\nIf non_moderator_chat_delay is true, the non_moderator_chat_delay_duration field must be set to a valid value.", + HttpStatusCode.Unauthorized => "The ID in the moderator_id query parameter must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:chat_settings scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.Forbidden => "The user in the moderator_id query parameter must have moderator privileges in the broadcaster's channel.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendChatAnnouncement = new() + { + Method = HttpMethod.Post, + Route = "/chat/announcements", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully sent the announcement.", + HttpStatusCode.BadRequest => "The message field in the request's body is required.\r\nThe message field may not contain an empty string.\r\nThe message field may not contain an empty string.\r\nThe string in the message field failed review.\r\nThe specified color is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token is missing the moderator:manage:announcements scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendAShoutout = new() + { + Method = HttpMethod.Post, + Route = "/chat/shoutouts", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully sent the specified broadcaster a Shoutout.", + HttpStatusCode.BadRequest => "The from_broadcaster_id query parameter is required.\r\nThe ID in the from_broadcaster_id query parameter is not valid.\r\nThe to_broadcaster_id query parameter is required.\r\nThe ID in the to_broadcaster_id query parameter is not valid.\r\nThe broadcaster may not give themselves a Shoutout.\r\nThe broadcaster is not streaming live or does not have one or more viewers.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:shoutouts scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.\r\nThe broadcaster may not send the specified broadcaster a Shoutout.", + HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of Shoutouts they may send within a given window.\r\n See the endpoint's Rate Limits.\r\nThe broadcaster exceeded the number of Shoutouts they may send the same broadcaster within a given window.\r\n See the endpoint's Rate Limits.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUserChatColor = new() + { + Method = HttpMethod.Get, + Route = "/chat/color", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the chat color used by the specified users.", + HttpStatusCode.BadRequest => "The ID in the user_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateUserChatColor = new() + { + Method = HttpMethod.Put, + Route = "/chat/color", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated the user's chat color.", + HttpStatusCode.BadRequest => "The ID in the user_id query parameter is not valid.\r\nThe color query parameter is required.\r\nThe named color in the color query parameter is not valid.\r\nTo specify a Hex color code, the user must be a Turbo or Prime user.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:manage:chat_color scope.\r\nThe OAuth token is not valid.\r\nThe ID in the user_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateClip = new() + { + Method = HttpMethod.Post, + Route = "/clips", + SuccessStatusCode = HttpStatusCode.Accepted, + GetResponseMessage = code => code switch + { + HttpStatusCode.Accepted => "Successfully started the clip process.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter was not found.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify user access token.\r\nThe user access token must include the clips:edit scope.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + HttpStatusCode.Forbidden => "The broadcaster has restricted the ability to capture clips to followers and/or subscribers only.\r\nThe specified broadcaster has not enabled clips on their channel.", + HttpStatusCode.NotFound => "The broadcaster in the broadcaster_id query parameter must be broadcasting live.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetClips = new() + { + Method = HttpMethod.Get, + Route = "/clips", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of video clips.", + HttpStatusCode.BadRequest => "The id or game_id or broadcaster_id query parameter is required.\r\nThe id, game_id, and broadcaster_id query parameters are mutually exclusive; you may specify only one of them.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.NotFound => "The ID in game_id was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetContentClassificationLabels = new() + { + Method = HttpMethod.Get, + Route = "/content_classification_labels", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code.ToString() + }; + + public static readonly HelixEndpoint GetDropsEntitlements = new() + { + Method = HttpMethod.Get, + Route = "/entitlements/drops", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the entitlements.", + HttpStatusCode.BadRequest => "The value in the fulfillment_status query parameter is not valid.\r\nThe ID in the user_id query parameter must match the user ID in the user access token.\r\nThe client in the access token is not associated with a known organization.\r\nThe owner of the client in the access token is not a member of the organization.", + HttpStatusCode.Unauthorized => "The ID in the Client-Id header must match the Client ID in the access token.\r\nThe Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.", + HttpStatusCode.Forbidden => "The organization associated with the client in the access token must own the game specified in the game_id query parameter.\r\nThe organization associated with the client in the access token must own the entitlements specified in the id query parameter.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateDropsEntitlements = new() + { + Method = HttpMethod.Patch, + Route = "/entitlements/drops", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully requested the updates.\r\n Check the response to determine which updates succeeded.", + HttpStatusCode.BadRequest => "The value in the fulfillment_status field is not valid.\r\nThe client in the access token is not associated with a known organization.\r\nThe owner of the client in the access token is not a member of the organization.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionConfigurationSegment = new() + { + Method = HttpMethod.Get, + Route = "/extensions/configurations", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the configurations.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.\r\nThe value in the segment query parameter is not valid.\r\nThe broadcaster_id query parameter is required if the segment query parameter is set to broadcaster or developer.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + HttpStatusCode.TooManyRequests => "The app exceeded the number of requests that it may make per minute.\r\n See Rate Limits above.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SetExtensionConfigurationSegment = new() + { + Method = HttpMethod.Put, + Route = "/extensions/configurations", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated the configuration.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required if segment is set to developer or broadcaster.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SetExtensionRequiredConfiguration = new() + { + Method = HttpMethod.Put, + Route = "/extensions/required_configuration", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated the extension's required_configuration string.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe extension_id field is required.\r\nThe extension_version field is required.\r\nThe required_configuration field is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendExtensionPubSubMessage = new() + { + Method = HttpMethod.Post, + Route = "/extensions/pubsub", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully sent the message.", + HttpStatusCode.BadRequest => "The broadcaster_id field in the request's body may only be set if the is_global_broadcast field is set to false.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + HttpStatusCode.UnprocessableEntity => "The message is too large.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionLiveChannels = new() + { + Method = HttpMethod.Get, + Route = "/extensions/live", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of broadcasters.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.\r\nThe pagination cursor is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The extension specified in the extension_id query parameter was not found or it's not being used in a live stream.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionSecrets = new() + { + Method = HttpMethod.Get, + Route = "/extensions/jwt/secrets", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of secrets.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateExtensionSecret = new() + { + Method = HttpMethod.Post, + Route = "/extensions/jwt/secrets", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the new secret.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.\r\nThe delay specified in the delay query parameter is too short.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendExtensionChatMessage = new() + { + Method = HttpMethod.Post, + Route = "/extensions/chat", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully sent the chat message.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe extension_id field in the request's body is required.\r\nThe extension_version field in the request's body is required.\r\nThe text field in the request's body is required.\r\nThe message is too long.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a JWT token.\r\nThe ID in the broadcaster_id query parameter must match the channel_id claim in the JWT.\r\nThe JWT token is not valid.\r\nThe Client-Id header is required.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensions = new() + { + Method = HttpMethod.Get, + Route = "/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of extensions.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.", + HttpStatusCode.Unauthorized => "The request must specify the Authorization header.\r\nThe Authorization header is required and must specify a JWT token.\r\nThe JWT token is not valid.\r\nThe request must specify the Client-Id header.", + HttpStatusCode.NotFound => "The extension in the extension_id query parameter was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetReleasedExtensions = new() + { + Method = HttpMethod.Get, + Route = "/extensions/released", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the extension.", + HttpStatusCode.BadRequest => "The extension_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The extension specified in the extension_id query parameter was not found or is not released.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetExtensionBitsProducts = new() + { + Method = HttpMethod.Get, + Route = "/bits/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of products.", + HttpStatusCode.BadRequest => "The ID in the Client-Id header must belong to an extension.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token; you may not specify a user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateExtensionBitsProduct = new() + { + Method = HttpMethod.Put, + Route = "/bits/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the product.", + HttpStatusCode.BadRequest => "The sku field is required.\r\nThe value in the sku field is not valid.\r\n The SKU may contain only alphanumeric characters, dashes (-), underscores (_), and periods (.\r\n).\r\nThe cost object's amount field is required.\r\nThe value in the cost object's amount field is not valid.\r\nThe cost object's type field is required.\r\nThe value in the cost object's type field is not valid.\r\nThe display_name field is required.\r\nThe ID in the Client-Id header must belong to the extension.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token; you may not specify a user access token.\r\nThe OAuth token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateEventSubSubscription = new() + { + Method = HttpMethod.Post, + Route = "/eventsub/subscriptions", + SuccessStatusCode = HttpStatusCode.Accepted, + GetResponseMessage = code => code switch + { + HttpStatusCode.Accepted => "Successfully accepted the subscription request.", + HttpStatusCode.BadRequest => "The condition field is required.\r\nThe user specified in the condition object does not exist.\r\nThe condition object is missing one or more required fields.\r\nThe combination of values in the version and type fields is not valid.\r\nThe length of the string in the secret field is not valid.\r\nThe URL in the transport's callback field is not valid.\r\n The URL must use the HTTPS protocol and the 443 port number.\r\nThe value specified in the method field is not valid.\r\nThe callback field is required if you specify the webhook transport method.\r\nThe session_id field is required if you specify the WebSocket transport method.\r\nThe combination of subscription type and version is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token if the transport method is webhook.\r\nThe Authorization header is required and must specify a user access token if the transport method is WebSocket.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.Forbidden => "The access token is missing the required scopes.", + HttpStatusCode.Conflict => "A subscription already exists for the specified event type and condition combination.", + HttpStatusCode.TooManyRequests => "The request exceeds the number of subscriptions that you may create with the same combination of type and condition values.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteEventSubSubscription = new() + { + Method = HttpMethod.Delete, + Route = "/eventsub/subscriptions", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully deleted the subscription.", + HttpStatusCode.BadRequest => "The id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The subscription was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetEventSubSubscriptions = new() + { + Method = HttpMethod.Get, + Route = "/eventsub/subscriptions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the subscriptions.", + HttpStatusCode.BadRequest => "The request may specify only one filter query parameter.\r\n For example, either type or status or user_id.\r\nThe value in the type query parameter is not valid.\r\nThe value in the status query parameter is not valid.\r\nThe cursor specified in the after query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetTopGames = new() + { + Method = HttpMethod.Get, + Route = "/games/top", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of broadcasts.", + HttpStatusCode.BadRequest => "The value in the first query parameter is not valid.\r\nThe cursor in the after or before query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGames = new() + { + Method = HttpMethod.Get, + Route = "/games", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the specified games.", + HttpStatusCode.BadRequest => "The request must specify the id or name or igdb_id query parameter.\r\nThe combined number of game IDs (id and igdb_id) and game names that you specify in the request must not exceed 100.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetCreatorGoals = new() + { + Method = HttpMethod.Get, + Route = "/goals", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's goals.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:goals scope.\r\nThe ID in broadcaster_id must match the user ID in the user access token.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelGuestStarSettings = new() + { + Method = HttpMethod.Get, + Route = "/guest_star/channel_settings", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id", + HttpStatusCode.Forbidden => "Insufficient authorization for viewing channel's Guest Star settings", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateChannelGuestStarSettings = new() + { + Method = HttpMethod.Put, + Route = "/guest_star/channel_settings", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated channel settings", + HttpStatusCode.BadRequest => "Missing broadcaster_id Invalid slot_count Invalid group_layout", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGuestStarSession = new() + { + Method = HttpMethod.Get, + Route = "/guest_star/session", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id", + HttpStatusCode.Unauthorized => "moderator_id and user token do not match", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateGuestStarSession = new() + { + Method = HttpMethod.Post, + Route = "/guest_star/session", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Session limit reached (1 active call)", + HttpStatusCode.Unauthorized => "Phone verification missing", + HttpStatusCode.Forbidden => "Insufficient authorization for creating session", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint EndGuestStarSession = new() + { + Method = HttpMethod.Delete, + Route = "/guest_star/session", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing or invalid broadcaster_id Missing or invalid session_id Session has already been ended", + HttpStatusCode.Forbidden => "Insufficient authorization for ending session", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetGuestStarInvites = new() + { + Method = HttpMethod.Get, + Route = "/guest_star/invites", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing session_id", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendGuestStarInvite = new() + { + Method = HttpMethod.Post, + Route = "/guest_star/invites", + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id Missing session_id Missing guest_id Invalid session_id", + HttpStatusCode.Forbidden => "Unauthorized guest invited Guest already invited", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteGuestStarInvite = new() + { + Method = HttpMethod.Delete, + Route = "/guest_star/invites", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing session_id Missing guest_id Invalid session_id", + HttpStatusCode.NotFound => "No invite exists for specified guest_id", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint AssignGuestStarSlot = new() + { + Method = HttpMethod.Post, + Route = "/guest_star/slot", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfuly assigned guest to slot", + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id Missing guest_id Missing or invalid session_id Missing or invalid slot_id", + HttpStatusCode.Unauthorized => "moderator_id is not a guest star moderator", + HttpStatusCode.Forbidden => "Cannot assign host slot Guest not invited to session Guest already assigned to slot Guest is not ready to join", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateGuestStarSlot = new() + { + Method = HttpMethod.Patch, + Route = "/guest_star/slot", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfuly updated slot(s)", + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing or invalid session_id Missing or invalid slot_id", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteGuestStarSlot = new() + { + Method = HttpMethod.Delete, + Route = "/guest_star/slot", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfuly removed user from slot", + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id Missing or invalid session_id Missing or invalid slot_id", + HttpStatusCode.Forbidden => "moderator_id is not a Guest Star moderator The request is attempting to modify a restricted slot", + HttpStatusCode.NotFound => "guest_id or slot_id not found", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateGuestStarSlotSettings = new() + { + Method = HttpMethod.Patch, + Route = "/guest_star/slot_settings", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfuly updated slot settings", + HttpStatusCode.BadRequest => "Missing broadcaster_id Missing moderator_id Missing or invalid session_id Missing or invalid slot_id", + HttpStatusCode.Forbidden => "moderator_id is not a Guest Star moderator The request is attempting to modify a restricted slot", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetHypeTrainEvents = new() + { + Method = HttpMethod.Get, + Route = "/hypetrain/events", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's Hype Train events.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user_id in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:hype_train scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CheckAutoModStatus = new() + { + Method = HttpMethod.Post, + Route = "/moderation/enforcements/status", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully checked the messages.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe data field is required and the list must contain one or more messages to check.\r\nThe msg_id field is required.\r\nThe msg_text field is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderation:read scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The ID in broadcaster_id must match the user ID in the user access token.", + HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of chat message checks that they may make.\r\n See the endpoint's rate limits.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint ManageHeldAutoModMessages = new() + { + Method = HttpMethod.Post, + Route = "/moderation/automod/message", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully approved or denied the message.", + HttpStatusCode.BadRequest => "The value in the action field is not valid.\r\nThe user_id field is required.\r\nThe msg_id field is required.\r\nThe action field is required.", + HttpStatusCode.Unauthorized => "The ID in user_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:automod scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in user_id is not one of the broadcaster's moderators.", + HttpStatusCode.NotFound => "The message specified in the msg_id field was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetAutoModSettings = new() + { + Method = HttpMethod.Get, + Route = "/moderation/automod/settings", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's AutoMod settings.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:read:automod_settings scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateAutoModSettings = new() + { + Method = HttpMethod.Put, + Route = "/moderation/automod/settings", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the broadcaster's AutoMod settings.", + HttpStatusCode.BadRequest => "The broadcaster_id is required.\r\nThe moderator_id is required.\r\nThe overall_level setting or one or more individual settings like aggression is required; the overall and individual settings are mutually exclusive, so don't set both.\r\nThe value of one or more AutoMod settings is not valid.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:automod_settings scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetBannedUsers = new() + { + Method = HttpMethod.Get, + Route = "/moderation/banned", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of banned users.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderation:read scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint BanUser = new() + { + Method = HttpMethod.Post, + Route = "/moderation/bans", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully banned the user or placed them in a timeout.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.\r\nThe user_id field is required.\r\nThe text in the reason field is too long.\r\nThe value in the duration field is not valid.\r\nThe user specified in the user_id field may not be banned.\r\nThe user specified in the user_id field may not be put in a timeout.\r\nThe user specified in the user_id field is already banned.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:banned_users scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + HttpStatusCode.Conflict => "You may not update the user's ban state while someone else is updating the state.\r\n For example, someone else is currently banning the user or putting them in a timeout, moving the user from a timeout to a ban, or removing the user from a ban or timeout.\r\n Please retry your request.", + HttpStatusCode.TooManyRequests => "The app has exceeded the number of requests it may make per minute for this broadcaster.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UnbanUser = new() + { + Method = HttpMethod.Delete, + Route = "/moderation/bans", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the ban or timeout.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.\r\nThe user_id query parameter is required.\r\nThe user specified in the user_id query parameter is not banned.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:banned_users scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + HttpStatusCode.Conflict => "You may not update the user's ban state while someone else is updating the state.\r\n For example, someone else is currently removing the ban or timeout, or they're moving the user from a timeout to a ban.\r\n Please retry your request.", + HttpStatusCode.TooManyRequests => "The app has exceeded the number of requests it may make per minute for this broadcaster.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetBlockedTerms = new() + { + Method = HttpMethod.Get, + Route = "/moderation/blocked_terms", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of blocked terms.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header must contain a user access token.\r\nThe user access token must include the moderator:read:blocked_terms scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint AddBlockedTerm = new() + { + Method = HttpMethod.Post, + Route = "/moderation/blocked_terms", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of blocked terms.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.\r\nThe text field is required.\r\nThe length of the term in the text field is either too short or too long.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:blocked_terms scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint RemoveBlockedTerm = new() + { + Method = HttpMethod.Delete, + Route = "/moderation/blocked_terms", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the blocked term.\r\n Also returned if the ID is not found.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe moderator_id query parameter is required.\r\nThe id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:blocked_terms scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteChatMessages = new() + { + Method = HttpMethod.Delete, + Route = "/moderation/chat", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the specified messages.", + HttpStatusCode.BadRequest => "You may not delete another moderator's messages.\r\nYou may not delete the broadcaster's messages.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token is missing the moderator:manage:chat_messages scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + HttpStatusCode.NotFound => "The ID in message_id was not found.\r\nThe specified message was created more than 6 hours ago.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetModerators = new() + { + Method = HttpMethod.Get, + Route = "/moderation/moderators", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of moderators.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderation:read scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint AddChannelModerator = new() + { + Method = HttpMethod.Post, + Route = "/moderation/moderators", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully added the moderator.", + HttpStatusCode.BadRequest => "The ID in broadcaster_id was not found.\r\nThe ID in user_id was not found.\r\nThe user in user_id is already a moderator in the broadcaster's chat room.\r\nThe user in user_id cannot become a moderator because they're banned from the channel.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:moderators scope.\r\nThe access token is not valid.\r\nThe ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.UnprocessableEntity => "The user in user_id is a VIP.\r\n To make them a moderator, you must first remove them as a VIP (see Remove Channel VIP).", + HttpStatusCode.TooManyRequests => "The broadcaster has exceeded the number of requests allowed within a 10-second window.\r\n See this endpoint's rate limits.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint RemoveChannelModerator = new() + { + Method = HttpMethod.Delete, + Route = "/moderation/moderators", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the moderator.", + HttpStatusCode.BadRequest => "The ID in broadcaster_id was not found.\r\nThe ID in user_id was not found.\r\nThe user in user_id is not a moderator in the broadcaster's chat room.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:moderators scope.\r\nThe access token is not valid.\r\nThe ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.TooManyRequests => "The broadcaster has exceeded the number of requests allowed within a 10-second window.\r\n See this endpoint's rate limits.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetVIPs = new() + { + Method = HttpMethod.Get, + Route = "/channels/vips", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of VIPs.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the user_id query parameter is not valid.\r\nThe number of user_id query parameters exceeds the maximum allowed.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:vips or channel:manage:vips scope.\r\nThe OAuth token is not valid.\r\nThe ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint AddChannelVIP = new() + { + Method = HttpMethod.Post, + Route = "/channels/vips", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => (int)code switch + { + (int)HttpStatusCode.NoContent => "Successfully added the VIP.", + (int)HttpStatusCode.BadRequest => "The user in the user_id query parameter is blocked from the broadcaster's channel.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe ID in the user_id query parameter is not valid.", + (int)HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:vips scope.\r\nThe OAuth token is not valid.\r\nThe ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + (int)HttpStatusCode.Forbidden => "The ID in the broadcaster_id query parameter must match the user ID in the access token.", + (int)HttpStatusCode.NotFound => "The ID in broadcaster_id was not found.\r\nThe ID in user_id was not found.", + (int)HttpStatusCode.Conflict => "The broadcaster doesn't have available VIP slots.\r\n Read More", + (int)HttpStatusCode.UnprocessableEntity => "The user in user_id is a moderator.\r\n To make them a VIP, you must first remove them as a moderator (see Remove Channel Moderator).\r\nThe user in the user_id query parameter is already a VIP.", + 425 => "The broadcaster must complete the Build a Community requirement before they may assign VIPs.", + (int)HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of VIP that they may add within a 10-second window.\r\n See Rate Limits for this endpoint above.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint RemoveChannelVIP = new() + { + Method = HttpMethod.Delete, + Route = "/channels/vips", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the VIP status from the user.", + HttpStatusCode.BadRequest => "The ID in broadcaster_id is not valid.\r\nThe ID in user_id is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:vips scope.\r\nThe OAuth token is not valid.\r\nThe ID in the broadcaster_id query parameter must match the user ID in the access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the OAuth token.", + HttpStatusCode.Forbidden => "The user in broadcaster_id doesn't have permission to remove the user's VIP status.", + HttpStatusCode.NotFound => "The ID in broadcaster_id was not found.\r\nThe ID in user_id was not found.", + HttpStatusCode.UnprocessableEntity => "The user in user_id is not a VIP in the broadcaster's channel.", + HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of VIPs that they may remove within a 10-second window.\r\n See Rate Limits for this endpoint above.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateShieldModeStatus = new() + { + Method = HttpMethod.Put, + Route = "/moderation/shield_mode", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the broadcaster's Shield Mode status.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe is_active field is required.\r\nThe value in the is_active field is not valid.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:manage:shield_mode scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetShieldModeStatus = new() + { + Method = HttpMethod.Get, + Route = "/moderation/shield_mode", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's Shield Mode activation status.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in moderator_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the moderator:read:shield_mode or moderator:manage:shield_mode scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in moderator_id is not one of the broadcaster's moderators.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetPolls = new() + { + Method = HttpMethod.Get, + Route = "/polls", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's polls.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token is missing the channel:read:polls scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header must match the client ID specified in the access token.", + HttpStatusCode.NotFound => "None of the IDs in the id query parameters were found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreatePoll = new() + { + Method = HttpMethod.Post, + Route = "/polls", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the poll.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe title field is required.\r\nThe choices field is required.\r\nThe duration field is required.\r\nThe value in duration is outside the allowed range of values.\r\nThe value in channel_points_per_vote is outside the allowed range of values.\r\nThe value in bits_per_vote is outside the allowed range of values.\r\nThe poll's title is too long.\r\nThe choice's title is too long.\r\nThe choice's title failed AutoMod checks.\r\nThe number of choices in the poll may not be less than 2 or greater that 5.\r\nThe broadcaster already has a poll that's running; you may not create another poll until the current poll completes.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token is missing the channel:manage:polls scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint EndPoll = new() + { + Method = HttpMethod.Patch, + Route = "/polls", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully ended the poll.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe id field is required.\r\nThe status field is required.\r\nThe value in the status field is not valid.\r\nThe poll must be active to terminate or archive it.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:polls scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header must match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetPredictions = new() + { + Method = HttpMethod.Get, + Route = "/predictions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of predictions.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:predictions scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreatePrediction = new() + { + Method = HttpMethod.Post, + Route = "/predictions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the Channel Points Prediction.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe title field is required.\r\nThe outcomes field is required.\r\nThe prediction_window field is required.\r\nThe value in prediction_window is outside the allowed range of values.\r\nThe prediction's title is too long.\r\nThe outcome's title is too long.\r\nThe outcome's title failed AutoMod checks.\r\nThere must be 2 outcomes in the prediction.\r\nThe broadcaster already has a prediction that's running; you may not create another prediction until the current prediction is resolved or canceled.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:predictions scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint EndPrediction = new() + { + Method = HttpMethod.Patch, + Route = "/predictions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully ended the prediction.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe id field is required.\r\nThe status field is required.\r\nThe winning_outcome_id field is required if status is RESOLVED.\r\nThe value in the status field is not valid.\r\nTo update the prediction's status to RESOLVED or CANCELED, its current status must be ACTIVE or LOCKED.\r\nTo update the prediction's status to LOCKED, its current status must be ACTIVE.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:predictions scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The prediction in the id field was not found.\r\nThe outcome in the winning_outcome_id field was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint StartARaid = new() + { + Method = HttpMethod.Post, + Route = "/raids", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully requested to start a raid.\r\n To determine whether the raid successfully occurred (that is, the broadcaster clicked Raid Now or the countdown expired), you must subscribe to the Channel Raid event.", + HttpStatusCode.BadRequest => "The raiding broadcaster is blocked from the targeted channel.\r\nThe targeted channel doesn't accept raids from this broadcaster.\r\nThere are too many viewers in the raiding party.\r\nThe IDs in from_broadcaster_id and to_broadcaster_id cannot be the same ID.\r\nThe ID in the from_broadcaster_id query parameter is not valid.\r\nThe ID in the to_broadcaster_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in from_broadcaster_id must match the user ID found in the request's OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:raids scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The targeted channel was not found.", + HttpStatusCode.Conflict => "The broadcaster is already in the process of raiding another channel.", + HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of raid requests that they may make.\r\n The limit is 10 requests within a 10-minute window.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CancelARaid = new() + { + Method = HttpMethod.Delete, + Route = "/raids", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "The pending raid was successfully canceled.", + HttpStatusCode.BadRequest => "The ID in the broadcaster_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the request's OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:raids scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The broadcaster doesn't have a pending raid to cancel.", + HttpStatusCode.TooManyRequests => "The broadcaster exceeded the number of raid requests that they may make.\r\n The limit is 10 requests within a 10-minute window.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelStreamSchedule = new() + { + Method = HttpMethod.Get, + Route = "/schedule", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's streaming schedule.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe ID in the id query parameter is not valid.\r\nThe format of the date and time in the start_time query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify a valid app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the access token.", + HttpStatusCode.Forbidden => "Only partners and affiliates may add non-recurring broadcast segments.", + HttpStatusCode.NotFound => "The broadcaster has not created a streaming schedule.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelICalendar = new() + { + Method = HttpMethod.Get, + Route = "/schedule/icalendar", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's schedule as an iCalendar.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateChannelStreamSchedule = new() + { + Method = HttpMethod.Patch, + Route = "/schedule/settings", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully updated the broadcaster's schedule settings.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe format of the string in vacation_start_time is not valid.\r\nThe format of the string in vacation_end_time is not valid.\r\nThe date in vacation_end_time must be later than the date in vacation_start_time.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:schedule scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The broadcaster's schedule was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateChannelStreamScheduleSegment = new() + { + Method = HttpMethod.Post, + Route = "/schedule/segment", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully added the broadcast segment.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe format of the date and time in the start_time field is not valid.\r\nThe value in the timezone field is not valid.\r\nThe value in the duration field is not valid.\r\nThe ID in the category_id field is not valid.\r\nThe string in the title field is too long.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:schedule scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.Forbidden => "Only partners and affiliates may add non-recurring broadcast segments.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateChannelStreamScheduleSegment = new() + { + Method = HttpMethod.Patch, + Route = "/schedule/segment", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the broadcast segment.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe id query parameter is required.\r\nThe ID in the id query parameter is not valid.\r\nThe format of the date and time in the start_time field is not valid.\r\nThe value in the timezone field is not valid.\r\nThe value in the duration field is not valid.\r\nThe ID in the category_id field is not valid.\r\nThe string in the title field is too long.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:schedule scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The specified broadcast segment was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteChannelStreamScheduleSegment = new() + { + Method = HttpMethod.Delete, + Route = "/schedule/segment", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the broadcast segment.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe ID in the broadcaster_id query parameter is not valid.\r\nThe id query parameter is required.\r\nThe ID in the id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The ID in the broadcaster_id query parameter must match the user ID in the user access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:schedule scope.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the OAuth token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SearchCategories = new() + { + Method = HttpMethod.Get, + Route = "/search/categories", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of category names that matched the specified query string.", + HttpStatusCode.BadRequest => "The query query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SearchChannels = new() + { + Method = HttpMethod.Get, + Route = "/search/channels", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of category names that matched the specified query string.", + HttpStatusCode.BadRequest => "The query query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetSoundtrackCurrentTrack = new() + { + Method = HttpMethod.Get, + Route = "/soundtrack/current_track", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the track that the broadcaster is playing.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The broadcaster is not playing a track.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetSoundtrackPlaylist = new() + { + Method = HttpMethod.Get, + Route = "/soundtrack/playlist", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the playlist.", + HttpStatusCode.BadRequest => "The id query parameter is required.\r\nThe ID in the id query parameter is not a valid playlist ASIN.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + HttpStatusCode.NotFound => "The specified playlist was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetSoundtrackPlaylists = new() + { + Method = HttpMethod.Get, + Route = "/soundtrack/playlists", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of playlists.", + HttpStatusCode.BadRequest => "The ID in the id query parameter is not a valid playlist ASIN.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetStreamKey = new() + { + Method = HttpMethod.Get, + Route = "/streams/key", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the stream's key.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe ID in the broadcaster_id field is not valid.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:stream_key scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header must match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetStreams = new() + { + Method = HttpMethod.Get, + Route = "/streams", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of streams.", + HttpStatusCode.BadRequest => "The value in the type query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetFollowedStreams = new() + { + Method = HttpMethod.Get, + Route = "/streams/followed", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of broadcasters that the user follows and that are streaming live.", + HttpStatusCode.BadRequest => "The user_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in user_id must match the user ID found in the access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:follows scope.\r\nThe OAuth token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CreateStreamMarker = new() + { + Method = HttpMethod.Post, + Route = "/streams/markers", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully created the marker.", + HttpStatusCode.BadRequest => "The user_id field is required.\r\nThe length of the string in the description field is too long.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:manage:broadcast scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in the access token is not authorized to create video markers for the user in the user_id field.\r\n The user in the access token must own the video or they must be one of the broadcaster's editors.", + HttpStatusCode.NotFound => "The user in the user_id field is not streaming live.\r\nThe ID in the user_id field is not valid.\r\nThe user hasn't enabled video on demand (VOD).", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetStreamMarkers = new() + { + Method = HttpMethod.Get, + Route = "/streams/markers", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of markers.", + HttpStatusCode.BadRequest => "The request must specify either the user_id or video_id query parameter, but not both.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:broadcast or user:manage:broadcast scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "The user in the access token is not authorized to get the video's markers.\r\n The user in the access token must own the video or be one of the broadcaster's editors.", + HttpStatusCode.NotFound => "The user specified in the user_id query parameter doesn't have videos.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetBroadcasterSubscriptions = new() + { + Method = HttpMethod.Get, + Route = "/subscriptions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of subscribers.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the request's OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:read:subscriptions scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint CheckUserSubscription = new() + { + Method = HttpMethod.Get, + Route = "/subscriptions/user", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "The user subscribes to the broadcaster.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.\r\nThe user_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in user_id must match the user ID found in the request's OAuth token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:subscriptions scope.\r\nThe access token is not valid.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The user in user_id does not subscribe to the broadcaster in broadcaster_id.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetAllStreamTags = new() + { + Method = HttpMethod.Get, + Route = "/tags/streams", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of tags.", + HttpStatusCode.BadRequest => "The tag_id query parameter is empty (for example, &tag_id=).\r\nThe list of tag IDs is too long.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetStreamTags = new() + { + Method = HttpMethod.Get, + Route = "/streams/tags", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of tags.", + HttpStatusCode.BadRequest => "The broadcaster_id field is required.\r\nThe ID in the broadcaster_id field is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must specify an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID in the Client-Id header must match the Client ID in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetChannelTeams = new() + { + Method = HttpMethod.Get, + Route = "/teams/channel", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of teams.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The broadcaster was not found.\r\nThe broadcaster is not a member of a team.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetTeams = new() + { + Method = HttpMethod.Get, + Route = "/teams", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the team's information.", + HttpStatusCode.BadRequest => "The name or id query parameter is required.\r\nSpecify either the name or id query parameter but not both.\r\nThe ID in the id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The specified team was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUsers = new() + { + Method = HttpMethod.Get, + Route = "/users", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the specified users' information.", + HttpStatusCode.BadRequest => "The id or login query parameter is required unless the request uses a user access token.\r\nThe request exceeded the maximum allowed number of id and/or login query parameters.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateUser = new() + { + Method = HttpMethod.Put, + Route = "/users", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the specified user's information.", + HttpStatusCode.BadRequest => "The string in the description query parameter is too long.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:edit scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUsersFollows = new() + { + Method = HttpMethod.Get, + Route = "/users/follows", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the follows information.", + HttpStatusCode.BadRequest => "The from_id query parameter, to_id query parameter, or both parameters are required.\r\nThe ID in the from_id query parameter is not validThe ID in the to_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUserBlockList = new() + { + Method = HttpMethod.Get, + Route = "/users/blocks", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the broadcaster's list of blocked users.", + HttpStatusCode.BadRequest => "The broadcaster_id query parameter is required.", + HttpStatusCode.Unauthorized => "The ID in broadcaster_id must match the user ID found in the request's access token.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:blocked_users scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint BlockUser = new() + { + Method = HttpMethod.Put, + Route = "/users/blocks", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully blocked the user.", + HttpStatusCode.BadRequest => "The target_user_id query parameter is required.\r\nThe ID in target_user_id cannot be the same as the user ID in the access token.\r\nThe value in source_context is not valid.\r\nThe value in reason is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:manage:blocked_users scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UnblockUser = new() + { + Method = HttpMethod.Delete, + Route = "/users/blocks", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully removed the block.", + HttpStatusCode.BadRequest => "The target_user_id query parameter is required.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:blocked_users scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUserExtensions = new() + { + Method = HttpMethod.Get, + Route = "/users/extensions/list", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the user's installed extensions.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:read:broadcast scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetUserActiveExtensions = new() + { + Method = HttpMethod.Get, + Route = "/users/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the user's active extensions.", + HttpStatusCode.BadRequest => "The user_id query parameter is required if you specify an app access token.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint UpdateUserExtensions = new() + { + Method = HttpMethod.Put, + Route = "/users/extensions", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully updated the active extensions.", + HttpStatusCode.BadRequest => "The JSON payload is malformed.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:edit:broadcast scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "An extension with the specified id and version values was not found.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetVideos = new() + { + Method = HttpMethod.Get, + Route = "/videos", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully retrieved the list of videos.", + HttpStatusCode.BadRequest => "The request must specify either the id or user_id or game_id query parameter.\r\nThe id, user_id, and game_id query parameters are mutually exclusive; you must specify only one of them.\r\nThe value in the id query parameter is not valid.\r\nThe ID in the game_id query parameter is not valid.\r\nThe value in the type query parameter is not valid.\r\nThe value in the period query parameter is not valid.\r\nThe value in the sort query parameter is not valid.", + HttpStatusCode.Unauthorized => "The Authorization header is required and must contain an app access token or user access token.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.NotFound => "The ID in the game_id query parameter was not found.\r\nThe ID in the id query parameter was not found.\r\n Returned only if all the IDs were not found; otherwise, the ID is ignored.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint DeleteVideos = new() + { + Method = HttpMethod.Delete, + Route = "/videos", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Successfully deleted the list of videos.", + HttpStatusCode.BadRequest => "The id query parameter is required.\r\nThe request exceeded the number of allowed id query parameters.", + HttpStatusCode.Unauthorized => "The caller is not authorized to delete the specified video.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the channel:manage:videos scope.\r\nThe access token is not valid.\r\nThe ID specified in the Client-Id header does not match the client ID specified in the access token.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SendWhisper = new() + { + Method = HttpMethod.Post, + Route = "/whispers", + SuccessStatusCode = HttpStatusCode.NoContent, + GetResponseMessage = code => code switch + { + HttpStatusCode.NoContent => "Successfully sent the whisper message or the message was silently dropped.", + HttpStatusCode.BadRequest => "The ID in the from_user_id and to_user_id query parameters must be different.\r\nThe message field must not contain an empty string.\r\nThe user that you're sending the whisper to doesn't allow whisper messages (see the Block Whispers from Strangers setting in your Security and Privacy settings).\r\nWhisper messages may not be sent to suspended users.\r\nThe ID in the from_user_id query parameter is not valid.\r\nThe ID in the to_user_id query parameter is not valid.", + HttpStatusCode.Unauthorized => "The user in the from_user_id query parameter must have a verified phone number.\r\nThe Authorization header is required and must contain a user access token.\r\nThe user access token must include the user:manage:whispers scope.\r\nThe access token is not valid.\r\nThis ID in from_user_id must match the user ID in the user access token.\r\nThe client ID specified in the Client-Id header does not match the client ID specified in the access token.", + HttpStatusCode.Forbidden => "Suspended users may not send whisper messages.\r\nThe account that's sending the message doesn't allow sending whispers.", + HttpStatusCode.NotFound => "The ID in to_user_id was not found.", + HttpStatusCode.TooManyRequests => "The sending user exceeded the number of whisper requests that they may make.\r\n See Rate Limits for this endpoint above.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint SnoozeNextAd = new() + { + Method = HttpMethod.Post, + Route = "/channels/ads/schedule/snooze", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "User’s next ad is successfully snoozed. Their snooze_count is decremented and snooze_refresh_time and next_ad_at are both updated.", + HttpStatusCode.BadRequest => "The channel is not currently live.\r\nThe broadcaster ID is not valid.\r\nChannel does not have an upcoming scheduled ad break.", + HttpStatusCode.TooManyRequests => "Channel has no snoozes left.", + _ => "Unknown response code" + } + }; + + public static readonly HelixEndpoint GetAdSchedule = new() + { + Method = HttpMethod.Get, + Route = "/channels/ads", + SuccessStatusCode = HttpStatusCode.OK, + GetResponseMessage = code => code switch + { + HttpStatusCode.OK => "Returns the ad schedule information for the channel.", + HttpStatusCode.BadRequest => "The broadcaster ID is not valid.", + _ => "Unknown response code" + } + }; +} diff --git a/MiniTwitch.Helix/Internal/Models/HelixEndpoint.cs b/MiniTwitch.Helix/Internal/Models/HelixEndpoint.cs new file mode 100644 index 0000000..a8ae628 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/HelixEndpoint.cs @@ -0,0 +1,11 @@ +using System.Net; + +namespace MiniTwitch.Helix.Internal.Models; + +internal class HelixEndpoint +{ + public HttpMethod Method { get; init; } = default!; + public string Route { get; init; } = default!; + public HttpStatusCode SuccessStatusCode { get; init; } = HttpStatusCode.OK; + public Func GetResponseMessage { get; init; } = default!; +} diff --git a/MiniTwitch.Helix/Internal/Models/HelixTask.cs b/MiniTwitch.Helix/Internal/Models/HelixTask.cs new file mode 100644 index 0000000..84a7130 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/HelixTask.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Internal.Models; + +internal readonly struct HelixTask +{ + internal HelixEndpoint Endpoint { get; init; } + internal RequestData Request { get; init; } + internal HelixApiClient Client { get; init; } +} diff --git a/MiniTwitch.Helix/Internal/Models/InvalidToken.cs b/MiniTwitch.Helix/Internal/Models/InvalidToken.cs new file mode 100644 index 0000000..3cd7e3d --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/InvalidToken.cs @@ -0,0 +1,8 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Models; + +public record InvalidToken( + [property: JsonPropertyName("status")] int Status, + [property: JsonPropertyName("message")] string Message + ); diff --git a/MiniTwitch.Helix/Internal/Models/QueryParams.cs b/MiniTwitch.Helix/Internal/Models/QueryParams.cs new file mode 100644 index 0000000..2c0807a --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/QueryParams.cs @@ -0,0 +1,65 @@ +namespace MiniTwitch.Helix.Internal.Models; + +internal static class QueryParams +{ + public const string ExtensionId = "extension_id"; + public const string Type = "type"; + public const string StartedAt = "started_at"; + public const string EndedAt = "ended_at"; + public const string First = "first"; + public const string GameId = "game_id"; + public const string Count = "count"; + public const string Period = "period"; + public const string UserId = "user_id"; + public const string BroadcasterId = "broadcaster_id"; + public const string Id = "id"; + public const string OnlyManageableRewards = "only_manageable_rewards"; + public const string RewardId = "reward_id"; + public const string Status = "status"; + public const string Sort = "sort"; + public const string ModeratorId = "moderator_id"; + public const string FromBroadcasterId = "from_broadcaster_id"; + public const string ToBroadcasterId = "to_broadcaster_id"; + public const string Color = "color"; + public const string HasDelay = "has_delay"; + public const string IsFeatured = "is_featured"; + public const string Locale = "locale"; + public const string FulfillmentStatus = "fulfillment_status"; + public const string EntitlementIds = "entitlement_ids"; + public const string Segment = "segment"; + public const string Delay = "delay"; + public const string ExtensionVersion = "extension_version"; + public const string ShouldIncludeAll = "should_include_all"; + public const string Name = "name"; + public const string IgdbId = "igdb_id"; + public const string SessionId = "session_id"; + public const string GuestId = "guest_id"; + public const string SlotId = "slot_id"; + public const string SourceSlotId = "source_slot_id"; + public const string DestinationSlotId = "destination_slot_id"; + public const string ShouldReinviteGuest = "should_reinvite_guest"; + public const string IsAudioEnabled = "is_audio_enabled"; + public const string IsVideoEnabled = "is_video_enabled"; + public const string IsLive = "is_live"; + public const string Volume = "volume"; + public const string MsgId = "msg_id"; + public const string Action = "action"; + public const string MessageId = "message_id"; + public const string StartTime = "start_time"; + public const string IsVacationEnabled = "is_vacation_enabled"; + public const string VacationStartTime = "vacation_start_time"; + public const string VacationEndTime = "vacation_end_time"; + public const string Timezone = "timezone"; + public const string Query = "query"; + public const string LiveOnly = "live_only"; + public const string UserLogin = "user_login"; + public const string Language = "language"; + public const string VideoId = "video_id"; + public const string Login = "login"; + public const string TargetUserId = "target_user_id"; + public const string SourceContext = "source_context"; + public const string Reason = "reason"; + public const string FromUserId = "from_user_id"; + public const string ToUserId = "to_user_id"; + public const string After = "after"; +} diff --git a/MiniTwitch.Helix/Internal/Models/RequestData.cs b/MiniTwitch.Helix/Internal/Models/RequestData.cs new file mode 100644 index 0000000..380bfd1 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/RequestData.cs @@ -0,0 +1,72 @@ +using System.Text; + +namespace MiniTwitch.Helix.Internal.Models; + +internal class RequestData +{ + public object Body { get; set; } = default!; + + internal readonly string _method; + private readonly string _url; + private readonly StringBuilder _paramBuilder = new(); + + public RequestData(string requestUrl, HelixEndpoint endpoint) + { + _url = requestUrl + endpoint.Route; + _method = endpoint.Method.Method; + } + + public string GetUrl() => _url + _paramBuilder.ToString(); + + public RequestData AddParam(string key, object? value) + { + if (value is null) + return this; + + if (_paramBuilder.Length == 0) + _paramBuilder.Append('?'); + else + _paramBuilder.Append('&'); + + _paramBuilder.Append($"{key}={value}"); + return this; + } + + public RequestData AddMultiParam(string key, IEnumerable? value) + { + if (value is null) + return this; + + foreach (object obj in value) + { + if (_paramBuilder.Length == 0) + { + _paramBuilder.Append($"?{key}={obj}"); + continue; + } + + _paramBuilder.Append($"&{key}={obj}"); + } + + return this; + } + + public RequestData AddMultiParam(string key, IEnumerable? value) + { + if (value is null) + return this; + + foreach (T? obj in value) + { + if (_paramBuilder.Length == 0) + { + _paramBuilder.Append($"?{key}={obj}"); + continue; + } + + _paramBuilder.Append($"&{key}={obj}"); + } + + return this; + } +} diff --git a/MiniTwitch.Helix/Internal/Models/ValidToken.cs b/MiniTwitch.Helix/Internal/Models/ValidToken.cs new file mode 100644 index 0000000..6b3bbd5 --- /dev/null +++ b/MiniTwitch.Helix/Internal/Models/ValidToken.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Internal.Models; + +internal record ValidToken( + [property: JsonPropertyName("client_id")] string ClientId, + [property: JsonPropertyName("login")] string Login, + [property: JsonPropertyName("scopes")] IReadOnlyList Scopes, + [property: JsonPropertyName("user_id")] string UserId, + [property: JsonPropertyName("expires_in")] int ExpiresIn +) +{ + public long ReceivedAt { get; set; } + public bool IsPermaToken => this.ExpiresIn == 0; +}; diff --git a/MiniTwitch.Helix/MiniTwitch.Helix.csproj b/MiniTwitch.Helix/MiniTwitch.Helix.csproj new file mode 100644 index 0000000..ff33107 --- /dev/null +++ b/MiniTwitch.Helix/MiniTwitch.Helix.csproj @@ -0,0 +1,46 @@ + + + + latest + + net6.0;net7.0 + MiniTwitch.Helix + 0.1.0-prerelease + 0.1.0-prerelease + true + true + MiniTwitch.Helix + Convenient wrapper classes for Twitch's Helix API + Foretack + https://github.com/Foretack/MiniTwitch + git + Twitch;Bots;Helix;API;Wrapper + MIT + LICENSE + README.md + icon256.png + enable + enable + CS8618,IDE0058,CS1591 + + + + + True + \ + + + True + \ + + + True + \ + + + + + + + + diff --git a/MiniTwitch.Helix/Models/AllCategories.cs b/MiniTwitch.Helix/Models/AllCategories.cs new file mode 100644 index 0000000..bf8d669 --- /dev/null +++ b/MiniTwitch.Helix/Models/AllCategories.cs @@ -0,0 +1,2106 @@ +using System.Web; +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Internal; +using MiniTwitch.Helix.Internal.Json; +using MiniTwitch.Helix.Internal.Models; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class AllCategories +{ + internal HelixApiClient ApiClient { get; } + + private readonly string _baseUrl; + + internal AllCategories(HelixApiClient client, string baseUrl) + { + this.ApiClient = client; + _baseUrl = baseUrl; + } + + + public Task> StartCommercial( + NewCommercial body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.StartCommercial; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionAnalytics( + string? extensionId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionAnalytics; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddParam(QueryParams.StartedAt, startedAt) + .AddParam(QueryParams.EndedAt, endedAt) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGameAnalytics( + string? gameId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGameAnalytics; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddParam(QueryParams.StartedAt, startedAt) + .AddParam(QueryParams.EndedAt, endedAt) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBitsLeaderboard( + int? count = null, + BitsLeaderboardPeriod? period = null, + DateTime? startedAt = null, + long? UserId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBitsLeaderboard; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Count, count) + .AddParam(QueryParams.Period, period?.ToString().ToLower()) + .AddParam(QueryParams.StartedAt, startedAt) + .AddParam(QueryParams.UserId, UserId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCheermotes( + long? broadcasterId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCheermotes; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionTransactions( + string extensionId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionTransactions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionTransactions( + string extensionId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionTransactions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelInformation( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelInformation; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelInformation( + IEnumerable broadcasterIds, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelInformation; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.BroadcasterId, broadcasterIds); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task ModifyChannelInformation( + long broadcasterId, + NewChannelInformation body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.ModifyChannelInformation; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelEditors( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelEditors; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetFollowedChannels( + long userId, + long? broadcasterId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetFollowedChannels; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelFollowers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelFollowers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateCustomReward( + long broadcasterId, + NewCustomReward body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateCustomRewards; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteCustomReward( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteCustomReward; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCustomReward( + long broadcasterId, + string? id = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCustomReward; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.OnlyManageableRewards, onlyManageableRewards); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCustomReward( + long broadcasterId, + IEnumerable? ids = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCustomReward; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.OnlyManageableRewards, onlyManageableRewards); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + string? id = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCustomRewardRedemption; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.RewardId, rewardId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.Status, status.ToString()) + .AddParam(QueryParams.Sort, sort?.ToString()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + IEnumerable? ids = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCustomRewardRedemption; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.RewardId, rewardId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.Status, status.ToString()) + .AddParam(QueryParams.Sort, sort?.ToString()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateCustomReward( + long broadcasterId, + string id, + UpdatedCustomReward body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateCustomReward; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateRedemptionStatus( + long broadcasterId, + string id, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateRedemptionStatus; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.RewardId, rewardId); + + request.Body = new + { + status = status.ToString() + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateRedemptionStatus( + long broadcasterId, + IEnumerable ids, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateRedemptionStatus; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.RewardId, rewardId); + + request.Body = new + { + status = status.ToString() + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCharityCampaign( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCharityCampaign; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCharityCampaignDonations( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCharityCampaignDonations; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChatters( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChatters; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelEmotes( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelEmotes; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGlobalEmotes(CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGlobalEmotes; + var request = new RequestData(_baseUrl, endpoint); + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetEmoteSets( + string emoteSetId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetEmoteSets; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam("emote_set_id", emoteSetId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetEmoteSets( + IEnumerable emoteSetIds, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetEmoteSets; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam("emote_set_id", emoteSetIds); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChatSettings( + long broadcasterId, + long? moderatorId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChatSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateChatSettings( + long broadcasterId, + long moderatorId, + NewChatSettings body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateChatSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUserBlockList( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUserBlockList; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendChatAnnouncement( + long broadcasterId, + long moderatorId, + Announcement body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendChatAnnouncement; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendAShoutout( + long fromBroadcasterId, + long toBroadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendAShoutout; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.FromBroadcasterId, fromBroadcasterId) + .AddParam(QueryParams.ToBroadcasterId, toBroadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUserChatColor( + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUserChatColor; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUserChatColor( + IEnumerable userIds, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUserChatColor; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.UserId, userIds); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateUserChatColor( + long userId, + ChatColor color, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateUserChatColor; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.Color, SnakeCase.Instance.ConvertToCase(color.ToString())); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateUserChatColor( + long userId, + string hexColor, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateUserChatColor; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.Color, HttpUtility.UrlEncode(hexColor)); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateClip( + long broadcasterId, + bool? hasDelay = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateClip; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.HasDelay, hasDelay); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetClips( + long broadcasterId, + long gameId, + string id, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetClips; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.StartedAt, startedAt) + .AddParam(QueryParams.EndedAt, endedAt) + .AddParam(QueryParams.First, first) + .AddParam(QueryParams.IsFeatured, isFeatured); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetClips( + long broadcasterId, + long gameId, + IEnumerable ids, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetClips; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.GameId, gameId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.StartedAt, startedAt) + .AddParam(QueryParams.EndedAt, endedAt) + .AddParam(QueryParams.First, first) + .AddParam(QueryParams.IsFeatured, isFeatured); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetContentClassificationLabels( + LabelLocale? locale = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetContentClassificationLabels; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Locale, locale?.ToString().Replace('_', '-')); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetDropsEntitlements( + string? id = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetDropsEntitlements; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.FulfillmentStatus, fulfillmentStatus?.ToString()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetDropsEntitlements( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetDropsEntitlements; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.FulfillmentStatus, fulfillmentStatus?.ToString()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateDropsEntitlements( + IEnumerable? entitlementIds = null, + FulfillmentStatus? fulfillmentStatus = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateDropsEntitlements; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.EntitlementIds, entitlementIds) + .AddParam(QueryParams.FulfillmentStatus, fulfillmentStatus?.ToString()); + + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionConfigurationSegment( + string extensionId, + ConfigSegmentType segment, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionConfigurationSegment; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.Segment, segment.ToString().ToLower()) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionConfigurationSegment( + string extensionId, + IEnumerable segments, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionConfigurationSegment; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddMultiParam(QueryParams.Segment, segments.Select(x => x.ToString().ToLower())) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SetExtensionConfigurationSegment( + ConfigurationSegment body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SetExtensionConfigurationSegment; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SetExtensionRequiredConfiguration( + long broadcasterId, + ExtensionRequiredConfiguration body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SetExtensionRequiredConfiguration; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendExtensionPubSubMessage( + ExtensionPubSubMessage body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendExtensionPubSubMessage; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionLiveChannels( + string extensionId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionLiveChannels; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionSecrets( + string extensionId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionSecrets; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateExtensionSecret( + string extensionId, + int? delay = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateExtensionSecret; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.Delay, delay); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendExtensionChatMessage( + long broadcasterId, + ExtensionChatMessage body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendExtensionChatMessage; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.ExtensionVersion, extensionVersion); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetReleasedExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetReleasedExtensions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ExtensionId, extensionId) + .AddParam(QueryParams.ExtensionVersion, extensionVersion); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetExtensionBitsProducts( + bool? shouldIncludeAll = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetExtensionBitsProducts; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.ShouldIncludeAll, shouldIncludeAll); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateExtensionBitsProduct( + UpdatedBitsProduct body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateExtensionBitsProduct; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateEventSubSubscription( + NewSubscription body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateEventSubSubscription; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteEventSubSubscription( + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteEventSubSubscription; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetEventSubSubscriptions( + EventSubStatus? status = null, + string? type = null, + long? userId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetEventSubSubscriptions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Status, SnakeCase.Instance.ConvertToCase(status.ToString())) + .AddParam(QueryParams.Type, type) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetTopGames( + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetTopGames; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGames( + string? id = null, + string? name = null, + string? igdbId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGames; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.Name, name) + .AddParam(QueryParams.IgdbId, igdbId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGames( + IEnumerable? ids = null, + IEnumerable? names = null, + IEnumerable? igdbIds = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGames; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.Id, ids) + .AddMultiParam(QueryParams.Name, names) + .AddMultiParam(QueryParams.IgdbId, igdbIds); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetCreatorGoals( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetCreatorGoals; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelGuestStarSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelGuestStarSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateChannelGuestStarSettings( + NewGuestStarSettings body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateChannelGuestStarSettings; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGuestStarSession( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGuestStarSession; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateGuestStarSession( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateGuestStarSession; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> EndGuestStarSession( + long broadcasterId, + string sessionId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.EndGuestStarSession; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.SessionId, sessionId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGuestStarInvites( + long broadcasterId, + long moderatorId, + string sessionId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGuestStarInvites; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(sessionId, sessionId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendGuestStarInvite; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.GuestId, guestId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteGuestStarInvite; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.SessionId, sessionId) + .AddParam(QueryParams.GuestId, guestId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task AssignGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.AssignGuestStarSlot; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.SessionId, sessionId) + .AddParam(QueryParams.GuestId, guestId) + .AddParam(QueryParams.SlotId, slotId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + string sourceSlotId, + string? destinationSlotId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateGuestStarSlot; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.SessionId, sessionId) + .AddParam(QueryParams.SourceSlotId, sourceSlotId) + .AddParam(QueryParams.DestinationSlotId, destinationSlotId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + string? shouldReinviteGuest = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteGuestStarSlot; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.SessionId, sessionId) + .AddParam(QueryParams.GuestId, guestId) + .AddParam(QueryParams.SlotId, slotId) + .AddParam(QueryParams.ShouldReinviteGuest, shouldReinviteGuest); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateGuestStarSlotSettings( + long broadcasterId, + long moderatorId, + string sessionId, + string slotId, + bool? isAudioEnabled = null, + bool? isVideoEnabled = null, + bool? isLive = null, + int? volume = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateGuestStarSlotSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.SessionId, sessionId) + .AddParam(QueryParams.SlotId, slotId) + .AddParam(QueryParams.IsAudioEnabled, isAudioEnabled) + .AddParam(QueryParams.IsVideoEnabled, isVideoEnabled) + .AddParam(QueryParams.IsLive, isLive) + .AddParam(QueryParams.Volume, volume); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetHypeTrainEvents( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetHypeTrainEvents; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CheckAutoModStatus( + long broadcasterId, + MessageToCheck body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CheckAutoModStatus; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task ManageHeldAutoModMessages( + long userId, + string msgId, + string action, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.ManageHeldAutoModMessages; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.MsgId, msgId) + .AddParam(QueryParams.Action, action); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetAutoModSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetAutoModSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateAutoModSettings( + long broadcasterId, + long moderatorId, + NewAutoModSettings body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateAutoModSettings; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBannedUsers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBannedUsers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBannedUsers( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBannedUsers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.UserId, userIds) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> BanUser( + long broadcasterId, + long moderatorId, + UserToBan body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.BanUser; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = body; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UnbanUser( + long broadcasterId, + long moderatorId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UnbanUser; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBlockedTerms( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBlockedTerms; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> AddBlockedTerm( + long broadcasterId, + long moderatorId, + string text, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.AddBlockedTerm; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = new { text }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task RemoveBlockedTerm( + long broadcasterId, + long moderatorId, + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.RemoveBlockedTerm; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteChatMessages( + long broadcasterId, + long moderatorId, + string? messageId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteChatMessages; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId) + .AddParam(QueryParams.MessageId, messageId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetModerators( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetModerators; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetModerators( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetModerators; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.UserId, userIds) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task AddChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.AddChannelModerator; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task RemoveChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.RemoveChannelModerator; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetVIPs( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetVIPs; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetVIPs( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetVIPs; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.UserId, userIds) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task AddChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.AddChannelVIP; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task RemoveChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.RemoveChannelVIP; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateShieldModeStatus( + long broadcasterId, + long moderatorId, + bool isActive, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateShieldModeStatus; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + request.Body = new { is_active = isActive }; + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetShieldModeStatus( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetShieldModeStatus; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.ModeratorId, moderatorId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetPolls( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetPolls; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetPolls( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetPolls; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreatePoll( + NewPoll body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreatePoll; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> EndPoll( + long broadcasterId, + string id, + string status, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.EndPoll; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.Status, status); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetPredictions( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetPredictions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetPredictions( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetPredictions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreatePrediction( + NewPrediction body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreatePrediction; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> EndPrediction( + PredictionToEnd body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.EndPrediction; + var request = new RequestData(_baseUrl, endpoint) + { + Body = body + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> StartARaid( + long fromBroadcasterId, + long toBroadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.StartARaid; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.FromBroadcasterId, fromBroadcasterId) + .AddParam(QueryParams.ToBroadcasterId, toBroadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task CancelARaid( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CancelARaid; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelStreamSchedule( + long broadcasterId, + string? id = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelStreamSchedule; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.StartTime, startTime) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelStreamSchedule( + long broadcasterId, + IEnumerable? ids = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelStreamSchedule; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.StartTime, startTime) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UpdateChannelStreamSchedule( + long broadcasterId, + bool? isVacationEnabled = null, + DateTime? vacationStartTime = null, + DateTime? vacationEndTime = null, + string? timezone = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateChannelStreamSchedule; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.IsVacationEnabled, isVacationEnabled) + .AddParam(QueryParams.VacationStartTime, vacationStartTime) + .AddParam(QueryParams.VacationEndTime, vacationEndTime) + .AddParam(QueryParams.Timezone, timezone); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateChannelStreamScheduleSegment( + long broadcasterId, + NewScheduleSegment body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateChannelStreamScheduleSegment; + RequestData request = new RequestData(_baseUrl, endpoint) + { + Body = body + }.AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateChannelStreamScheduleSegment( + long broadcasterId, + string id, + Requests.UpdatedScheduleSegment Body, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateChannelStreamScheduleSegment; + RequestData request = new RequestData(_baseUrl, endpoint) + { + Body = Body + } + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteChannelStreamScheduleSegment( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteChannelStreamScheduleSegment; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> SearchCategories( + string query, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SearchCategories; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Query, HttpUtility.UrlEncode(query)) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> SearchChannels( + string query, + bool? liveOnly = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SearchChannels; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Query, query) + .AddParam(QueryParams.LiveOnly, liveOnly) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetStreamKey( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetStreamKey; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetStreams( + long? userId = null, + string? userLogin = null, + string? gameId = null, + StreamTypes? type = null, + string? language = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetStreams; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.UserLogin, userLogin) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddParam(QueryParams.Language, language) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetStreams( + IEnumerable? userIds = null, + IEnumerable? userLogins = null, + IEnumerable? gameIds = null, + StreamTypes? type = null, + IEnumerable? languages = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetStreams; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.UserId, userIds) + .AddMultiParam(QueryParams.UserLogin, userLogins) + .AddMultiParam(QueryParams.GameId, gameIds) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddMultiParam(QueryParams.Language, languages) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetFollowedStreams( + long userId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetFollowedStreams; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CreateStreamMarker( + long userId, + string? description = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CreateStreamMarker; + var request = new RequestData(_baseUrl, endpoint) + { + Body = new + { + user_id = userId, + description + } + }; + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetStreamMarkers( + long userId, + string? videoId, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetStreamMarkers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.VideoId, videoId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBroadcasterSubscriptions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetBroadcasterSubscriptions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddMultiParam(QueryParams.UserId, userIds) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> CheckUserSubscription( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.CheckUserSubscription; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelTeams( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelTeams; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetTeams( + string name, + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetTeams; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Name, name) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUsers( + long? id = null, + string? login = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUsers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.Login, login); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUsers( + IEnumerable? id = null, + IEnumerable? login = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUsers; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.Id, id) + .AddMultiParam(QueryParams.Login, login); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> UpdateUser( + string? description = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UpdateUser; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam("description", description); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task BlockUser( + long targetUserId, + string? sourceContext = null, + string? reason = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.BlockUser; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.TargetUserId, targetUserId) + .AddParam(QueryParams.SourceContext, sourceContext) + .AddParam(QueryParams.Reason, reason); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task UnblockUser( + long targetUserId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.UnblockUser; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.TargetUserId, targetUserId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUserExtensions(CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUserExtensions; + var request = new RequestData(_baseUrl, endpoint); + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetUserActiveExtensions( + long? userId = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetUserActiveExtensions; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.UserId, userId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetVideos( + string? id = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetVideos; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.Language, language) + .AddParam(QueryParams.Period, period?.ToString().ToLower()) + .AddParam(QueryParams.Sort, sort?.ToString().ToLower()) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetVideos( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetVideos; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.Id, ids) + .AddParam(QueryParams.UserId, userId) + .AddParam(QueryParams.GameId, gameId) + .AddParam(QueryParams.Language, language) + .AddParam(QueryParams.Period, period?.ToString().ToLower()) + .AddParam(QueryParams.Sort, sort?.ToString().ToLower()) + .AddParam(QueryParams.Type, type?.ToString().ToLower()) + .AddParam(QueryParams.First, first); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteVideos( + string id, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteVideos; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.Id, id); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task DeleteVideos( + IEnumerable ids, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.DeleteVideos; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddMultiParam(QueryParams.Id, ids); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task SendWhisper( + long fromUserId, + long toUserId, + string message, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SendWhisper; + RequestData request = new RequestData(_baseUrl, endpoint) + { + Body = new + { + message + } + } + .AddParam(QueryParams.FromUserId, fromUserId) + .AddParam(QueryParams.ToUserId, toUserId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetAdSchedule( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetAdSchedule; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> SnoozeNextAd( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.SnoozeNextAd; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetGlobalChatBadges(CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetGlobalChatBadges; + var request = new RequestData(_baseUrl, endpoint); + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } + + public Task> GetChannelChatBadges( + long broadcasterId, + CancellationToken cancellationToken = default) + { + HelixEndpoint endpoint = Endpoints.GetChannelChatBadges; + RequestData request = new RequestData(_baseUrl, endpoint) + .AddParam(QueryParams.BroadcasterId, broadcasterId); + + return HelixResultFactory.Create(this.ApiClient, request, endpoint, cancellationToken); + } +} diff --git a/MiniTwitch.Helix/Models/AnalyticsCategory.cs b/MiniTwitch.Helix/Models/AnalyticsCategory.cs new file mode 100644 index 0000000..829e59e --- /dev/null +++ b/MiniTwitch.Helix/Models/AnalyticsCategory.cs @@ -0,0 +1,33 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class AnalyticsCategory +{ + private readonly AllCategories _all; + + internal AnalyticsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetExtensionAnalytics( + string? extensionId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionAnalytics(extensionId, type, startedAt, endedAt, first, cancellationToken); + + public Task> GetGameAnalytics( + string? gameId = null, + AnalyticsType? type = null, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetGameAnalytics(gameId, type, startedAt, endedAt, first, cancellationToken); + +} diff --git a/MiniTwitch.Helix/Models/BaseResponse.cs b/MiniTwitch.Helix/Models/BaseResponse.cs new file mode 100644 index 0000000..24bde0d --- /dev/null +++ b/MiniTwitch.Helix/Models/BaseResponse.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Models; + +public abstract class BaseResponse +{ + [JsonPropertyName("data")] + public required IReadOnlyList Data { get; init; } + + [JsonIgnore] + public bool HasContent => this.Data is { Count: > 0 }; +} diff --git a/MiniTwitch.Helix/Models/BitsCategory.cs b/MiniTwitch.Helix/Models/BitsCategory.cs new file mode 100644 index 0000000..bbb132a --- /dev/null +++ b/MiniTwitch.Helix/Models/BitsCategory.cs @@ -0,0 +1,39 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class BitsCategory +{ + private readonly AllCategories _all; + + internal BitsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetBitsLeaderboard( + int? count = null, + BitsLeaderboardPeriod? period = null, + DateTime? startedAt = null, + long? UserId = null, + CancellationToken cancellationToken = default) + => _all.GetBitsLeaderboard(count, period, startedAt, UserId, cancellationToken); + + public Task> GetCheermotes( + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetCheermotes(broadcasterId, cancellationToken); + + public Task> GetExtensionBitsProducts( + bool? shouldIncludeAll = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionBitsProducts(shouldIncludeAll, cancellationToken); + + public Task> UpdateExtensionBitsProduct( + UpdatedBitsProduct body, + CancellationToken cancellationToken = default) + => _all.UpdateExtensionBitsProduct(body, cancellationToken); + +} diff --git a/MiniTwitch.Helix/Models/ChannelPointsCategory.cs b/MiniTwitch.Helix/Models/ChannelPointsCategory.cs new file mode 100644 index 0000000..e8de0f4 --- /dev/null +++ b/MiniTwitch.Helix/Models/ChannelPointsCategory.cs @@ -0,0 +1,84 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ChannelPointsCategory +{ + private readonly AllCategories _all; + + internal ChannelPointsCategory(AllCategories all) + { + _all = all; + } + + public Task> CreateCustomReward( + long broadcasterId, + NewCustomReward body, + CancellationToken cancellationToken = default) + => _all.CreateCustomReward(broadcasterId, body, cancellationToken); + + public Task DeleteCustomReward( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + => _all.DeleteCustomReward(broadcasterId, id, cancellationToken); + + public Task> GetCustomReward( + long broadcasterId, + string? id = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + => _all.GetCustomReward(broadcasterId, id, onlyManageableRewards, cancellationToken); + + public Task> GetCustomReward( + long broadcasterId, + IEnumerable? ids = null, + bool onlyManageableRewards = false, + CancellationToken cancellationToken = default) + => _all.GetCustomReward(broadcasterId, ids, onlyManageableRewards, cancellationToken); + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + string? id = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCustomRewardRedemption(broadcasterId, rewardId, status, id, sort, first, cancellationToken); + + public Task> GetCustomRewardRedemption( + long broadcasterId, + string rewardId, + RewardRedemptionStatus status, + IEnumerable? ids = null, + SortMethod? sort = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCustomRewardRedemption(broadcasterId, rewardId, status, ids, sort, first, cancellationToken); + + public Task> UpdateCustomReward( + long broadcasterId, + string id, + UpdatedCustomReward body, + CancellationToken cancellationToken = default) + => _all.UpdateCustomReward(broadcasterId, id, body, cancellationToken); + + public Task> UpdateRedemptionStatus( + long broadcasterId, + string id, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + => _all.UpdateRedemptionStatus(broadcasterId, id, rewardId, status, cancellationToken); + + public Task> UpdateRedemptionStatus( + long broadcasterId, + IEnumerable ids, + string rewardId, + RewardRedemptionStatus status, + CancellationToken cancellationToken = default) + => _all.UpdateRedemptionStatus(broadcasterId, ids, rewardId, status, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/ChannelsCategory.cs b/MiniTwitch.Helix/Models/ChannelsCategory.cs new file mode 100644 index 0000000..6493e80 --- /dev/null +++ b/MiniTwitch.Helix/Models/ChannelsCategory.cs @@ -0,0 +1,91 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ChannelsCategory +{ + private readonly AllCategories _all; + + internal ChannelsCategory(AllCategories all) + { + _all = all; + } + + public Task> StartCommercial( + NewCommercial body, + CancellationToken cancellationToken = default) + => _all.StartCommercial(body, cancellationToken); + + public Task> GetAdSchedule( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetAdSchedule(broadcasterId, cancellationToken); + + public Task> SnoozeNextAd( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.SnoozeNextAd(broadcasterId, cancellationToken); + + + public Task> GetChannelInformation( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelInformation(broadcasterId, cancellationToken); + + public Task> GetChannelInformation( + IEnumerable broadcasterIds, + CancellationToken cancellationToken = default) + => _all.GetChannelInformation(broadcasterIds, cancellationToken); + + public Task ModifyChannelInformation( + long broadcasterId, + NewChannelInformation body, + CancellationToken cancellationToken = default) + => _all.ModifyChannelInformation(broadcasterId, body, cancellationToken); + + public Task> GetChannelEditors( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelEditors(broadcasterId, cancellationToken); + + public Task> GetFollowedChannels( + long userId, + long? broadcasterId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetFollowedChannels(userId, broadcasterId, first, cancellationToken); + + public Task> GetChannelFollowers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelFollowers(broadcasterId, userId, first, cancellationToken); + + public Task> GetVIPs( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVIPs(broadcasterId, userId, first, cancellationToken); + + public Task> GetVIPs( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVIPs(broadcasterId, userIds, first, cancellationToken); + + public Task AddChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.AddChannelVIP(broadcasterId, userId, cancellationToken); + + public Task RemoveChannelVIP( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.RemoveChannelVIP(broadcasterId, userId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/CharityCategory.cs b/MiniTwitch.Helix/Models/CharityCategory.cs new file mode 100644 index 0000000..47c2fdb --- /dev/null +++ b/MiniTwitch.Helix/Models/CharityCategory.cs @@ -0,0 +1,24 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class CharityCategory +{ + private readonly AllCategories _all; + + internal CharityCategory(AllCategories all) + { + _all = all; + } + + public Task> GetCharityCampaign( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetCharityCampaign(broadcasterId, cancellationToken); + + public Task> GetCharityCampaignDonations( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetCharityCampaignDonations(broadcasterId, first, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/ChatCategory.cs b/MiniTwitch.Helix/Models/ChatCategory.cs new file mode 100644 index 0000000..a34a8b5 --- /dev/null +++ b/MiniTwitch.Helix/Models/ChatCategory.cs @@ -0,0 +1,99 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ChatCategory +{ + private readonly AllCategories _all; + + internal ChatCategory(AllCategories all) + { + _all = all; + } + + public Task> GetChatters( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChatters(broadcasterId, moderatorId, first, cancellationToken); + + public Task> GetChannelEmotes( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelEmotes(broadcasterId, cancellationToken); + + public Task> GetGlobalEmotes( + CancellationToken cancellationToken = default) + => _all.GetGlobalEmotes(cancellationToken); + + public Task> GetEmoteSets( + string emoteSetId, + CancellationToken cancellationToken = default) + => _all.GetEmoteSets(emoteSetId, cancellationToken); + + public Task> GetEmoteSets( + IEnumerable emoteSetIds, + CancellationToken cancellationToken = default) + => _all.GetEmoteSets(emoteSetIds, cancellationToken); + + public Task> GetChannelChatBadges( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelChatBadges(broadcasterId, cancellationToken); + + public Task> GetGlobalChatBadges( + CancellationToken cancellationToken = default) + => _all.GetGlobalChatBadges(cancellationToken); + + public Task> GetChatSettings( + long broadcasterId, + long? moderatorId = null, + CancellationToken cancellationToken = default) + => _all.GetChatSettings(broadcasterId, moderatorId, cancellationToken); + + public Task> UpdateChatSettings( + long broadcasterId, + long moderatorId, + NewChatSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateChatSettings(broadcasterId, moderatorId, body, cancellationToken); + + public Task SendChatAnnouncement( + long broadcasterId, + long moderatorId, + Announcement body, + CancellationToken cancellationToken = default) + => _all.SendChatAnnouncement(broadcasterId, moderatorId, body, cancellationToken); + + public Task SendAShoutout( + long fromBroadcasterId, + long toBroadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.SendAShoutout(fromBroadcasterId, toBroadcasterId, moderatorId, cancellationToken); + + public Task> GetUserChatColor( + long userId, + CancellationToken cancellationToken = default) + => _all.GetUserChatColor(userId, cancellationToken); + + public Task> GetUserChatColor( + IEnumerable userIds, + CancellationToken cancellationToken = default) + => _all.GetUserChatColor(userIds, cancellationToken); + + public Task UpdateUserChatColor( + long userId, + ChatColor color, + CancellationToken cancellationToken = default) + => _all.UpdateUserChatColor(userId, color, cancellationToken); + + public Task UpdateUserChatColor( + long userId, + string hexColor, + CancellationToken cancellationToken = default) + => _all.UpdateUserChatColor(userId, hexColor, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/ClipsCategory.cs b/MiniTwitch.Helix/Models/ClipsCategory.cs new file mode 100644 index 0000000..2840470 --- /dev/null +++ b/MiniTwitch.Helix/Models/ClipsCategory.cs @@ -0,0 +1,41 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ClipsCategory +{ + private readonly AllCategories _all; + + internal ClipsCategory(AllCategories all) + { + _all = all; + } + + public Task> CreateClip( + long broadcasterId, + bool? hasDelay = null, + CancellationToken cancellationToken = default) + => _all.CreateClip(broadcasterId, hasDelay, cancellationToken); + + public Task> GetClips( + long broadcasterId, + long gameId, + string id, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + => _all.GetClips(broadcasterId, gameId, id, startedAt, endedAt, first, isFeatured, cancellationToken); + + public Task> GetClips( + long broadcasterId, + long gameId, + IEnumerable ids, + DateTime? startedAt = null, + DateTime? endedAt = null, + int? first = null, + bool? isFeatured = null, + CancellationToken cancellationToken = default) + => _all.GetClips(broadcasterId, gameId, ids, startedAt, endedAt, first, isFeatured, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/ContentClassificationLabel.cs b/MiniTwitch.Helix/Models/ContentClassificationLabel.cs new file mode 100644 index 0000000..afd29a4 --- /dev/null +++ b/MiniTwitch.Helix/Models/ContentClassificationLabel.cs @@ -0,0 +1,9 @@ +using MiniTwitch.Helix.Enums; + +namespace MiniTwitch.Helix.Models; + +public readonly struct ContentClassificationLabel +{ + public required ContentLabelid Id { get; init; } + public required bool IsEnabled { get; init; } +} diff --git a/MiniTwitch.Helix/Models/EntitlementsCategory.cs b/MiniTwitch.Helix/Models/EntitlementsCategory.cs new file mode 100644 index 0000000..f21fe8c --- /dev/null +++ b/MiniTwitch.Helix/Models/EntitlementsCategory.cs @@ -0,0 +1,38 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class EntitlementsCategory +{ + private readonly AllCategories _all; + + internal EntitlementsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetDropsEntitlements( + string? id = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetDropsEntitlements(id, userId, gameId, fulfillmentStatus, first, cancellationToken); + + public Task> GetDropsEntitlements( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + FulfillmentStatus? fulfillmentStatus = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetDropsEntitlements(ids, userId, gameId, fulfillmentStatus, first, cancellationToken); + + public Task> UpdateDropsEntitlements( + IEnumerable? entitlementIds = null, + FulfillmentStatus? fulfillmentStatus = null, + CancellationToken cancellationToken = default) + => _all.UpdateDropsEntitlements(entitlementIds, fulfillmentStatus, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/EventsubCategory.cs b/MiniTwitch.Helix/Models/EventsubCategory.cs new file mode 100644 index 0000000..3bae3d1 --- /dev/null +++ b/MiniTwitch.Helix/Models/EventsubCategory.cs @@ -0,0 +1,32 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class EventSubCategory +{ + private readonly AllCategories _all; + + internal EventSubCategory(AllCategories all) + { + _all = all; + } + + public Task> CreateEventSubSubscription( + NewSubscription body, + CancellationToken cancellationToken = default) + => _all.CreateEventSubSubscription(body, cancellationToken); + + public Task DeleteEventSubSubscription( + string id, + CancellationToken cancellationToken = default) + => _all.DeleteEventSubSubscription(id, cancellationToken); + + public Task> GetEventSubSubscriptions( + EventSubStatus? status = null, + string? type = null, + long? userId = null, + CancellationToken cancellationToken = default) + => _all.GetEventSubSubscriptions(status, type, userId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/ExtensionsCategory.cs b/MiniTwitch.Helix/Models/ExtensionsCategory.cs new file mode 100644 index 0000000..d860793 --- /dev/null +++ b/MiniTwitch.Helix/Models/ExtensionsCategory.cs @@ -0,0 +1,87 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ExtensionsCategory +{ + private readonly AllCategories _all; + + internal ExtensionsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetExtensionTransactions( + string extensionId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionTransactions(extensionId, id, first, cancellationToken); + + public Task> GetExtensionConfigurationSegment( + string extensionId, + ConfigSegmentType segment, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionConfigurationSegment(extensionId, segment, broadcasterId, cancellationToken); + + public Task> GetExtensionConfigurationSegment( + string extensionId, + IEnumerable segments, + long? broadcasterId = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionConfigurationSegment(extensionId, segments, broadcasterId, cancellationToken); + + public Task SetExtensionConfigurationSegment( + ConfigurationSegment body, + CancellationToken cancellationToken = default) + => _all.SetExtensionConfigurationSegment(body, cancellationToken); + + public Task SetExtensionRequiredConfiguration( + long broadcasterId, + ExtensionRequiredConfiguration body, + CancellationToken cancellationToken = default) + => _all.SetExtensionRequiredConfiguration(broadcasterId, body, cancellationToken); + + public Task SendExtensionPubSubMessage( + ExtensionPubSubMessage body, + CancellationToken cancellationToken = default) + => _all.SendExtensionPubSubMessage(body, cancellationToken); + + public Task> GetExtensionLiveChannels( + string extensionId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetExtensionLiveChannels(extensionId, first, cancellationToken); + + public Task> GetExtensionSecrets( + string extensionId, + CancellationToken cancellationToken = default) + => _all.GetExtensionSecrets(extensionId, cancellationToken); + + public Task> CreateExtensionSecret( + string extensionId, + int? delay = null, + CancellationToken cancellationToken = default) + => _all.CreateExtensionSecret(extensionId, delay, cancellationToken); + + public Task SendExtensionChatMessage( + long broadcasterId, + ExtensionChatMessage body, + CancellationToken cancellationToken = default) + => _all.SendExtensionChatMessage(broadcasterId, body, cancellationToken); + + public Task> GetExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + => _all.GetExtensions(extensionId, extensionVersion, cancellationToken); + + public Task> GetReleasedExtensions( + string extensionId, + string? extensionVersion = null, + CancellationToken cancellationToken = default) + => _all.GetReleasedExtensions(extensionId, extensionVersion, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/GamesCategory.cs b/MiniTwitch.Helix/Models/GamesCategory.cs new file mode 100644 index 0000000..c6766f6 --- /dev/null +++ b/MiniTwitch.Helix/Models/GamesCategory.cs @@ -0,0 +1,32 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class GamesCategory +{ + private readonly AllCategories _all; + + internal GamesCategory(AllCategories all) + { + _all = all; + } + + public Task> GetTopGames( + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetTopGames(first, cancellationToken); + + public Task> GetGames( + string? id = null, + string? name = null, + string? igdbId = null, + CancellationToken cancellationToken = default) + => _all.GetGames(id, name, igdbId, cancellationToken); + + public Task> GetGames( + IEnumerable? ids = null, + IEnumerable? names = null, + IEnumerable? igdbIds = null, + CancellationToken cancellationToken = default) + => _all.GetGames(ids, names, igdbIds, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/GuestStarCategory.cs b/MiniTwitch.Helix/Models/GuestStarCategory.cs new file mode 100644 index 0000000..9918b36 --- /dev/null +++ b/MiniTwitch.Helix/Models/GuestStarCategory.cs @@ -0,0 +1,105 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class GuestStarCategory +{ + private readonly AllCategories _all; + + internal GuestStarCategory(AllCategories all) + { + _all = all; + } + + public Task> GetChannelGuestStarSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetChannelGuestStarSettings(broadcasterId, moderatorId, cancellationToken); + + public Task UpdateChannelGuestStarSettings( + NewGuestStarSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateChannelGuestStarSettings(body, cancellationToken); + + public Task> GetGuestStarSession( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetGuestStarSession(broadcasterId, moderatorId, cancellationToken); + + public Task> CreateGuestStarSession( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.CreateGuestStarSession(broadcasterId, cancellationToken); + + public Task> EndGuestStarSession( + long broadcasterId, + string sessionId, + CancellationToken cancellationToken = default) + => _all.EndGuestStarSession(broadcasterId, sessionId, cancellationToken); + + public Task> GetGuestStarInvites( + long broadcasterId, + long moderatorId, + string sessionId, + CancellationToken cancellationToken = default) + => _all.GetGuestStarInvites(broadcasterId, moderatorId, sessionId, cancellationToken); + + public Task SendGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + => _all.SendGuestStarInvite(broadcasterId, moderatorId, sessionId, guestId, cancellationToken); + + public Task DeleteGuestStarInvite( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + CancellationToken cancellationToken = default) + => _all.DeleteGuestStarInvite(broadcasterId, moderatorId, sessionId, guestId, cancellationToken); + + public Task AssignGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + CancellationToken cancellationToken = default) + => _all.AssignGuestStarSlot(broadcasterId, moderatorId, sessionId, guestId, slotId, cancellationToken); + + public Task UpdateGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + string sourceSlotId, + string? destinationSlotId = null, + CancellationToken cancellationToken = default) + => _all.UpdateGuestStarSlot(broadcasterId, moderatorId, sessionId, sourceSlotId, destinationSlotId, cancellationToken); + + public Task DeleteGuestStarSlot( + long broadcasterId, + long moderatorId, + string sessionId, + long guestId, + string slotId, + string? shouldReinviteGuest = null, + CancellationToken cancellationToken = default) + => _all.DeleteGuestStarSlot(broadcasterId, moderatorId, sessionId, guestId, slotId, shouldReinviteGuest, cancellationToken); + + public Task UpdateGuestStarSlotSettings( + long broadcasterId, + long moderatorId, + string sessionId, + string slotId, + bool? isAudioEnabled = null, + bool? isVideoEnabled = null, + bool? isLive = null, + int? volume = null, + CancellationToken cancellationToken = default) + => _all.UpdateGuestStarSlotSettings(broadcasterId, moderatorId, sessionId, slotId, isAudioEnabled, isVideoEnabled, isLive, volume, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/HelixResult.cs b/MiniTwitch.Helix/Models/HelixResult.cs new file mode 100644 index 0000000..e4f0a4a --- /dev/null +++ b/MiniTwitch.Helix/Models/HelixResult.cs @@ -0,0 +1,96 @@ +using System.Net; +using MiniTwitch.Helix.Interfaces; +using MiniTwitch.Helix.Internal; +using MiniTwitch.Helix.Internal.Models; + +namespace MiniTwitch.Helix.Models; + +/// +/// Contains the data about the result of a request to the Twitch Helix API. +/// +public readonly struct HelixResult : IHelixResult +{ + /// + /// Status code of the response + /// + public HttpStatusCode StatusCode { get; init; } + /// + /// Contains a message clarifying the meaning of the status code in + /// + public string Message { get; init; } + /// + /// The amount of time the request took to get a response + /// + public TimeSpan Elapsed { get; init; } + /// + /// Whether the request was successful + /// + public bool Success { get; init; } + /// + /// Ratelimit information about the request + /// Only applicable if is + /// + public RequestRatelimit Ratelimit { get; init; } +} + +/// +/// Contains the data about the result of a request to the Twitch Helix API. +/// +public readonly struct HelixResult : IHelixResult +{ + /// + /// The response's content as + /// This value should only be used if is + /// + public TResult Value { get; init; } + /// + /// Status code of the response + /// + public HttpStatusCode StatusCode { get; init; } + /// + /// Contains a message clarifying the meaning of the status code in + /// + public string Message { get; init; } + /// + /// The amount of time the request took to get a response + /// + public TimeSpan Elapsed { get; init; } + /// + /// Whether the request was successful + /// + public bool Success { get; init; } + /// + /// Ratelimit information about the request + /// Only applicable if is + /// + public RequestRatelimit Ratelimit { get; init; } + /// + /// Whether the request can fetch the next page of content + /// + public bool CanPaginate => + this.Value is IPaginable p + && p.Pagination.Cursor is { Length: > 0 } + && this.HelixTask is not null; + + internal HelixTask? HelixTask { get; init; } + + /// + /// Fetches the next page of content + /// The same object is returned if is + /// + public Task> Paginate(CancellationToken cancellationToken = default) + { + if (!this.CanPaginate) + return Task.FromResult(this); + + this.HelixTask!.Value.Request.AddParam(QueryParams.After, ((IPaginable)this.Value!).Pagination.Cursor!); + return HelixResultFactory.Create( + this.HelixTask.Value.Client, + this.HelixTask.Value.Request, + this.HelixTask.Value.Endpoint, + cancellationToken + ); + } + + public static implicit operator TResult(HelixResult result) => result.Value; +} diff --git a/MiniTwitch.Helix/Models/InvalidTokenException.cs b/MiniTwitch.Helix/Models/InvalidTokenException.cs new file mode 100644 index 0000000..18372ba --- /dev/null +++ b/MiniTwitch.Helix/Models/InvalidTokenException.cs @@ -0,0 +1,11 @@ +namespace MiniTwitch.Helix.Models; + +public class InvalidTokenException : Exception +{ + public string? TokenMessage { get; init; } + + internal InvalidTokenException(string? tokenMessage, string? message) : base(message) + { + this.TokenMessage = tokenMessage; + } +} diff --git a/MiniTwitch.Helix/Models/ModerationCategory.cs b/MiniTwitch.Helix/Models/ModerationCategory.cs new file mode 100644 index 0000000..8b79e9b --- /dev/null +++ b/MiniTwitch.Helix/Models/ModerationCategory.cs @@ -0,0 +1,135 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ModerationCategory +{ + private readonly AllCategories _all; + + internal ModerationCategory(AllCategories all) + { + _all = all; + } + + public Task> CheckAutoModStatus( + long broadcasterId, + MessageToCheck body, + CancellationToken cancellationToken = default) + => _all.CheckAutoModStatus(broadcasterId, body, cancellationToken); + + public Task ManageHeldAutoModMessages( + long userId, + string msgId, + string action, + CancellationToken cancellationToken = default) + => _all.ManageHeldAutoModMessages(userId, msgId, action, cancellationToken); + + public Task> GetAutoModSettings( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetAutoModSettings(broadcasterId, moderatorId, cancellationToken); + + public Task> UpdateAutoModSettings( + long broadcasterId, + long moderatorId, + NewAutoModSettings body, + CancellationToken cancellationToken = default) + => _all.UpdateAutoModSettings(broadcasterId, moderatorId, body, cancellationToken); + + public Task> GetBannedUsers( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBannedUsers(broadcasterId, userId, first, cancellationToken); + + public Task> GetBannedUsers( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBannedUsers(broadcasterId, userIds, first, cancellationToken); + + public Task> BanUser( + long broadcasterId, + long moderatorId, + UserToBan body, + CancellationToken cancellationToken = default) + => _all.BanUser(broadcasterId, moderatorId, body, cancellationToken); + + public Task UnbanUser( + long broadcasterId, + long moderatorId, + long userId, + CancellationToken cancellationToken = default) + => _all.UnbanUser(broadcasterId, moderatorId, userId, cancellationToken); + + public Task> GetBlockedTerms( + long broadcasterId, + long moderatorId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBlockedTerms(broadcasterId, moderatorId, first, cancellationToken); + + public Task> AddBlockedTerm( + long broadcasterId, + long moderatorId, + string text, + CancellationToken cancellationToken = default) + => _all.AddBlockedTerm(broadcasterId, moderatorId, text, cancellationToken); + + public Task RemoveBlockedTerm( + long broadcasterId, + long moderatorId, + string id, + CancellationToken cancellationToken = default) + => _all.RemoveBlockedTerm(broadcasterId, moderatorId, id, cancellationToken); + + public Task DeleteChatMessages( + long broadcasterId, + long moderatorId, + string? messageId = null, + CancellationToken cancellationToken = default) + => _all.DeleteChatMessages(broadcasterId, moderatorId, messageId, cancellationToken); + + public Task> GetModerators( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetModerators(broadcasterId, userId, first, cancellationToken); + + public Task> GetModerators( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetModerators(broadcasterId, userIds, first, cancellationToken); + + public Task AddChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.AddChannelModerator(broadcasterId, userId, cancellationToken); + + public Task RemoveChannelModerator( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.RemoveChannelModerator(broadcasterId, userId, cancellationToken); + + public Task> UpdateShieldModeStatus( + long broadcasterId, + long moderatorId, + bool isActive, + CancellationToken cancellationToken = default) + => _all.UpdateShieldModeStatus(broadcasterId, moderatorId, isActive, cancellationToken); + + public Task> GetShieldModeStatus( + long broadcasterId, + long moderatorId, + CancellationToken cancellationToken = default) + => _all.GetShieldModeStatus(broadcasterId, moderatorId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/PaginableResponse.cs b/MiniTwitch.Helix/Models/PaginableResponse.cs new file mode 100644 index 0000000..9967f29 --- /dev/null +++ b/MiniTwitch.Helix/Models/PaginableResponse.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Interfaces; + +namespace MiniTwitch.Helix.Models; + +public abstract class PaginableResponse : BaseResponse, IPaginable +{ + [JsonPropertyName("pagination")] + public required Pagination Pagination { get; init; } +} diff --git a/MiniTwitch.Helix/Models/Pagination.cs b/MiniTwitch.Helix/Models/Pagination.cs new file mode 100644 index 0000000..81ac51c --- /dev/null +++ b/MiniTwitch.Helix/Models/Pagination.cs @@ -0,0 +1,6 @@ +namespace MiniTwitch.Helix.Models; + +public readonly struct Pagination +{ + public string? Cursor { get; init; } +} diff --git a/MiniTwitch.Helix/Models/PollsCategory.cs b/MiniTwitch.Helix/Models/PollsCategory.cs new file mode 100644 index 0000000..209b397 --- /dev/null +++ b/MiniTwitch.Helix/Models/PollsCategory.cs @@ -0,0 +1,40 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class PollsCategory +{ + private readonly AllCategories _all; + + internal PollsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetPolls( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPolls(broadcasterId, id, first, cancellationToken); + + public Task> GetPolls( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPolls(broadcasterId, ids, first, cancellationToken); + + public Task> CreatePoll( + NewPoll body, + CancellationToken cancellationToken = default) + => _all.CreatePoll(body, cancellationToken); + + public Task> EndPoll( + long broadcasterId, + string id, + string status, + CancellationToken cancellationToken = default) + => _all.EndPoll(broadcasterId, id, status, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/PredictionsCategory.cs b/MiniTwitch.Helix/Models/PredictionsCategory.cs new file mode 100644 index 0000000..d14f9a9 --- /dev/null +++ b/MiniTwitch.Helix/Models/PredictionsCategory.cs @@ -0,0 +1,38 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class PredictionsCategory +{ + private readonly AllCategories _all; + + internal PredictionsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetPredictions( + long broadcasterId, + string? id = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPredictions(broadcasterId, id, first, cancellationToken); + + public Task> GetPredictions( + long broadcasterId, + IEnumerable? ids = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetPredictions(broadcasterId, ids, first, cancellationToken); + + public Task> CreatePrediction( + NewPrediction body, + CancellationToken cancellationToken = default) + => _all.CreatePrediction(body, cancellationToken); + + public Task> EndPrediction( + PredictionToEnd body, + CancellationToken cancellationToken = default) + => _all.EndPrediction(body, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/RaidsCategory.cs b/MiniTwitch.Helix/Models/RaidsCategory.cs new file mode 100644 index 0000000..9a713ac --- /dev/null +++ b/MiniTwitch.Helix/Models/RaidsCategory.cs @@ -0,0 +1,24 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class RaidsCategory +{ + private readonly AllCategories _all; + + internal RaidsCategory(AllCategories all) + { + _all = all; + } + + public Task> StartARaid( + long fromBroadcasterId, + long toBroadcasterId, + CancellationToken cancellationToken = default) + => _all.StartARaid(fromBroadcasterId, toBroadcasterId, cancellationToken); + + public Task CancelARaid( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.CancelARaid(broadcasterId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/RequestRatelimit.cs b/MiniTwitch.Helix/Models/RequestRatelimit.cs new file mode 100644 index 0000000..aa887b7 --- /dev/null +++ b/MiniTwitch.Helix/Models/RequestRatelimit.cs @@ -0,0 +1,17 @@ +namespace MiniTwitch.Helix.Models; + +public readonly record struct RequestRatelimit +{ + /// + /// Maximum amount of requests that can be made in period + /// + public required int Limit { get; init; } + /// + /// The remaining amount of requests allowed before the bucket refills + /// + public required int Remaining { get; init; } + /// + /// The amount of time before the request bucket refills + /// + public required TimeSpan ResetsIn { get; init; } +} diff --git a/MiniTwitch.Helix/Models/ScheduleCategory.cs b/MiniTwitch.Helix/Models/ScheduleCategory.cs new file mode 100644 index 0000000..51fc0f2 --- /dev/null +++ b/MiniTwitch.Helix/Models/ScheduleCategory.cs @@ -0,0 +1,58 @@ +using MiniTwitch.Helix.Requests; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class ScheduleCategory +{ + private readonly AllCategories _all; + + internal ScheduleCategory(AllCategories all) + { + _all = all; + } + + public Task> GetChannelStreamSchedule( + long broadcasterId, + string? id = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelStreamSchedule(broadcasterId, id, startTime, first, cancellationToken); + + public Task> GetChannelStreamSchedule( + long broadcasterId, + IEnumerable? ids = null, + DateTime? startTime = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetChannelStreamSchedule(broadcasterId, ids, startTime, first, cancellationToken); + + public Task UpdateChannelStreamSchedule( + long broadcasterId, + bool? isVacationEnabled = null, + DateTime? vacationStartTime = null, + DateTime? vacationEndTime = null, + string? timezone = null, + CancellationToken cancellationToken = default) + => _all.UpdateChannelStreamSchedule(broadcasterId, isVacationEnabled, vacationStartTime, vacationEndTime, timezone, cancellationToken); + + public Task> CreateChannelStreamScheduleSegment( + long broadcasterId, + NewScheduleSegment body, + CancellationToken cancellationToken = default) + => _all.CreateChannelStreamScheduleSegment(broadcasterId, body, cancellationToken); + + public Task> UpdateChannelStreamScheduleSegment( + long broadcasterId, + string id, + Requests.UpdatedScheduleSegment Body, + CancellationToken cancellationToken = default) + => _all.UpdateChannelStreamScheduleSegment(broadcasterId, id, Body, cancellationToken); + + public Task DeleteChannelStreamScheduleSegment( + long broadcasterId, + string id, + CancellationToken cancellationToken = default) + => _all.DeleteChannelStreamScheduleSegment(broadcasterId, id, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/SearchCategory.cs b/MiniTwitch.Helix/Models/SearchCategory.cs new file mode 100644 index 0000000..c2fe0d4 --- /dev/null +++ b/MiniTwitch.Helix/Models/SearchCategory.cs @@ -0,0 +1,26 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class SearchCategory +{ + private readonly AllCategories _all; + + internal SearchCategory(AllCategories all) + { + _all = all; + } + + public Task> SearchCategories( + string query, + int? first = null, + CancellationToken cancellationToken = default) + => _all.SearchCategories(query, first, cancellationToken); + + public Task> SearchChannels( + string query, + bool? liveOnly = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.SearchChannels(query, liveOnly, first, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/SingleResponse.cs b/MiniTwitch.Helix/Models/SingleResponse.cs new file mode 100644 index 0000000..0e4bb55 --- /dev/null +++ b/MiniTwitch.Helix/Models/SingleResponse.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Models; + +public abstract class SingleResponse +{ + [JsonPropertyName("data")] + internal IReadOnlyList I_Data { get; init; } + + [JsonIgnore] + public T Data => this.I_Data[0]; + + [JsonIgnore] + public bool HasContent => this.I_Data is { Count: > 0 }; +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Models/StreamsCategory.cs b/MiniTwitch.Helix/Models/StreamsCategory.cs new file mode 100644 index 0000000..6b90874 --- /dev/null +++ b/MiniTwitch.Helix/Models/StreamsCategory.cs @@ -0,0 +1,58 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class StreamsCategory +{ + private readonly AllCategories _all; + + internal StreamsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetStreamKey( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetStreamKey(broadcasterId, cancellationToken); + + public Task> GetStreams( + long? userId = null, + string? userLogin = null, + string? gameId = null, + StreamTypes? type = null, + string? language = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreams(userId, userLogin, gameId, type, language, first, cancellationToken); + + public Task> GetStreams( + IEnumerable? userIds = null, + IEnumerable? userLogins = null, + IEnumerable? gameIds = null, + StreamTypes? type = null, + IEnumerable? languages = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreams(userIds, userLogins, gameIds, type, languages, first, cancellationToken); + + public Task> GetFollowedStreams( + long userId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetFollowedStreams(userId, first, cancellationToken); + + public Task> CreateStreamMarker( + long userId, + string? description = null, + CancellationToken cancellationToken = default) + => _all.CreateStreamMarker(userId, description, cancellationToken); + + public Task> GetStreamMarkers( + long userId, + string? videoId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetStreamMarkers(userId, videoId, first, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/SubscriptionsCategory.cs b/MiniTwitch.Helix/Models/SubscriptionsCategory.cs new file mode 100644 index 0000000..38f3c6a --- /dev/null +++ b/MiniTwitch.Helix/Models/SubscriptionsCategory.cs @@ -0,0 +1,33 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class SubscriptionsCategory +{ + private readonly AllCategories _all; + + internal SubscriptionsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + long? userId = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBroadcasterSubscriptions(broadcasterId, userId, first, cancellationToken); + + public Task> GetBroadcasterSubscriptions( + long broadcasterId, + IEnumerable? userIds = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetBroadcasterSubscriptions(broadcasterId, userIds, first, cancellationToken); + + public Task> CheckUserSubscription( + long broadcasterId, + long userId, + CancellationToken cancellationToken = default) + => _all.CheckUserSubscription(broadcasterId, userId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/TeamsCategory.cs b/MiniTwitch.Helix/Models/TeamsCategory.cs new file mode 100644 index 0000000..f8da2f2 --- /dev/null +++ b/MiniTwitch.Helix/Models/TeamsCategory.cs @@ -0,0 +1,24 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class TeamsCategory +{ + private readonly AllCategories _all; + + internal TeamsCategory(AllCategories all) + { + _all = all; + } + + public Task> GetChannelTeams( + long broadcasterId, + CancellationToken cancellationToken = default) + => _all.GetChannelTeams(broadcasterId, cancellationToken); + + public Task> GetTeams( + string name, + string id, + CancellationToken cancellationToken = default) + => _all.GetTeams(name, id, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/UsersCategory.cs b/MiniTwitch.Helix/Models/UsersCategory.cs new file mode 100644 index 0000000..fd5857e --- /dev/null +++ b/MiniTwitch.Helix/Models/UsersCategory.cs @@ -0,0 +1,57 @@ +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class UsersCategory +{ + private readonly AllCategories _all; + + internal UsersCategory(AllCategories all) + { + _all = all; + } + + public Task> GetUsers( + long? id = null, + string? login = null, + CancellationToken cancellationToken = default) + => _all.GetUsers(id, login, cancellationToken); + + public Task> GetUsers( + IEnumerable? id = null, + IEnumerable? login = null, + CancellationToken cancellationToken = default) + => _all.GetUsers(id, login, cancellationToken); + + public Task> UpdateUser( + string? description = null, + CancellationToken cancellationToken = default) + => _all.UpdateUser(description, cancellationToken); + + public Task BlockUser( + long targetUserId, + string? sourceContext = null, + string? reason = null, + CancellationToken cancellationToken = default) + => _all.BlockUser(targetUserId, sourceContext, reason, cancellationToken); + + public Task UnblockUser( + long targetUserId, + CancellationToken cancellationToken = default) + => _all.UnblockUser(targetUserId, cancellationToken); + + public Task> GetUserBlockList( + long broadcasterId, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetUserBlockList(broadcasterId, first, cancellationToken); + + public Task> GetUserExtensions( + CancellationToken cancellationToken = default) + => _all.GetUserExtensions(cancellationToken); + + public Task> GetUserActiveExtensions( + long? userId = null, + CancellationToken cancellationToken = default) + => _all.GetUserActiveExtensions(userId, cancellationToken); +} diff --git a/MiniTwitch.Helix/Models/VideosCategory.cs b/MiniTwitch.Helix/Models/VideosCategory.cs new file mode 100644 index 0000000..46f33f3 --- /dev/null +++ b/MiniTwitch.Helix/Models/VideosCategory.cs @@ -0,0 +1,48 @@ +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitch.Helix.Models; + +public sealed class VideosCategory +{ + private readonly AllCategories _all; + + internal VideosCategory(AllCategories all) + { + _all = all; + } + + public Task> GetVideos( + string? id = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVideos(id, userId, gameId, language, period, sort, type, first, cancellationToken); + + public Task> GetVideos( + IEnumerable? ids = null, + long? userId = null, + string? gameId = null, + string? language = null, + VideoPeriod? period = null, + VideoSortMethod? sort = null, + VideoType? type = null, + int? first = null, + CancellationToken cancellationToken = default) + => _all.GetVideos(ids, userId, gameId, language, period, sort, type, first, cancellationToken); + + public Task DeleteVideos( + string id, + CancellationToken cancellationToken = default) + => _all.DeleteVideos(id, cancellationToken); + + public Task DeleteVideos( + IEnumerable ids, + CancellationToken cancellationToken = default) + => _all.DeleteVideos(ids, cancellationToken); +} diff --git a/MiniTwitch.Helix/README.md b/MiniTwitch.Helix/README.md new file mode 100644 index 0000000..afbd274 --- /dev/null +++ b/MiniTwitch.Helix/README.md @@ -0,0 +1,94 @@ +# MiniTwitch.Helix (Pre-release) + +MiniTwitch.Helix conveniently wraps the Twitch Helix API and exposes them through the `HelixWrapper` and `SortedHelixWrapper` classes. The difference between the two classes is that `HelixWrapper` exposes all endpoints as methods directly on the class, while `SortedHelixWrapper` exposes them through categories (i.e `HelixWrapper.BanUser()` vs `SortedHelixWrapper.Moderation.BanUser()`) + +## Features + +- Contains all generally available and beta Helix API endpoints +- Virtually no dependencies +- Returns meaningful information about responses with `HelixResult`: + - **HelixResult.Success**: Whether the request was successful + - **HelixResult.StatusCode**: Status code of the response + - **HelixResult.Message**: Contains a message clarifying the meaning of the status code + - **HelixResult.Elapsed**: The amount of time the request took to get a response + - **HelixResult.RateLimit.Limit**: Maximum amount of requests that can be made in a period + - **HelixResult.RateLimit.Remaining**: The amount of requests that can be made before the ratelimit resets + - **HelixResult.RateLimit.ResetsIn**: The amount of time before the ratelimit resets + +- Validates access tokens & warns before their expiry +- Easy pagination API for `HelixResult`: + - **HelixResult.CanPaginate**: Determines whether the next page of content can be requested + - **HelixResult.Paginate()**: Fetches the next page of content + +## Getting Started + +This example demonstrates the usage of `HelixWrapper` and `HelixResult.Paginate()` + +```csharp +using MiniTwitch.Helix; +using MiniTwitch.Helix.Models; +using MiniTwitch.Helix.Responses; + +namespace MiniTwitchExample; + +public class Program +{ + public static HelixWrapper Helix { get; set; } + + static async Task Main() + { + Helix = new HelixWrapper("Access token", "Client ID"); + + await GetFirst1000Usernames(12345678, 12345678); + await GetAllUsernames(12345678, 12345678); + } + + private static async Task> GetFirst1000Usernames(long broadcasterId, long moderatorId) + { + List usernames = new(); + HelixResult chatters = await Helix.GetChatters(broadcasterId, moderatorId, first: 1000); + + // Make sure the result is a success and the value contains data + if (!chatters.Success || !chatters.Value.HasContent) return Array.Empty(); + + foreach (var chatter in chatters.Value.Data) + { + usernames.Add(chatter.Username); + } + + return usernames; + } + + private static async Task> GetAllUsernames(long broadcasterId, long moderatorId) + { + List usernames = new(); + HelixResult chatters = await Helix.GetChatters(broadcasterId, moderatorId, first: 1000); + + if (!chatters.Success || !chatters.Value.HasContent) return Array.Empty(); + + foreach (var chatter in chatters.Value.Data) + { + usernames.Add(chatter.Username); + } + + // No more users - return what we got + if (!chatters.CanPaginate) return usernames; + + // Continue paginating if the result is a success and there is content + while (await chatters.Paginate() is { Success: true, Value.HasContent: true } next) + { + foreach (var chatter in next.Value.Data) + { + usernames.Add(chatter.Username); + } + + // Return when pagination is no longer possible + if (!next.CanPaginate) return usernames; + + chatters = next; + } + + return usernames; + } +} +``` \ No newline at end of file diff --git a/MiniTwitch.Helix/Requests/Announcement.cs b/MiniTwitch.Helix/Requests/Announcement.cs new file mode 100644 index 0000000..b4179c2 --- /dev/null +++ b/MiniTwitch.Helix/Requests/Announcement.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct Announcement +{ + public required string Message { get; init; } + [JsonConverter(typeof(EnumToString))] + public AnnouncementColor? Color { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/ConfigurationSegment.cs b/MiniTwitch.Helix/Requests/ConfigurationSegment.cs new file mode 100644 index 0000000..3e81794 --- /dev/null +++ b/MiniTwitch.Helix/Requests/ConfigurationSegment.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct ConfigurationSegment +{ + + public required string ExtensionId { get; init; } + + [JsonConverter(typeof(EnumToString))] + public required ConfigSegmentType Segment { get; init; } + + [JsonConverter(typeof(LongToString))] + public long? BroadcasterId { get; init; } + + public string Content { get; init; } + + public string Version { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/ExtensionChatMessage.cs b/MiniTwitch.Helix/Requests/ExtensionChatMessage.cs new file mode 100644 index 0000000..5ef34ab --- /dev/null +++ b/MiniTwitch.Helix/Requests/ExtensionChatMessage.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct ExtensionChatMessage +{ + public required string Text { get; init; } + public required string ExtensionId { get; init; } + public required string ExtensionVersion { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/ExtensionPubSubMessage.cs b/MiniTwitch.Helix/Requests/ExtensionPubSubMessage.cs new file mode 100644 index 0000000..cf7f6f0 --- /dev/null +++ b/MiniTwitch.Helix/Requests/ExtensionPubSubMessage.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct ExtensionPubSubMessage +{ + public required IEnumerable Target { get; init; } + + [JsonConverter(typeof(LongToString))] + public required long BroadcasterId { get; init; } + + public required string Message { get; init; } + + public bool? IsGlobalBroadcast { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/ExtensionRequiredConfiguration.cs b/MiniTwitch.Helix/Requests/ExtensionRequiredConfiguration.cs new file mode 100644 index 0000000..75078f7 --- /dev/null +++ b/MiniTwitch.Helix/Requests/ExtensionRequiredConfiguration.cs @@ -0,0 +1,8 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct ExtensionRequiredConfiguration +{ + public required string ExtensionId { get; init; } + public required string ExtensionVersion { get; init; } + public required string RequiredConfiguration { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/MessageToCheck.cs b/MiniTwitch.Helix/Requests/MessageToCheck.cs new file mode 100644 index 0000000..eda7f1b --- /dev/null +++ b/MiniTwitch.Helix/Requests/MessageToCheck.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct MessageToCheck +{ + public required IEnumerable Data { get; init; } + + public record Message( + [property: JsonPropertyName("msg_id")] string MessageId, + [property: JsonPropertyName("msg_text")] string MessageText + ); +} diff --git a/MiniTwitch.Helix/Requests/NewAutoModSettings.cs b/MiniTwitch.Helix/Requests/NewAutoModSettings.cs new file mode 100644 index 0000000..dd507ce --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewAutoModSettings.cs @@ -0,0 +1,14 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly record struct NewAutoModSettings +{ + public int? Aggression { get; init; } + public int? Bullying { get; init; } + public int? Disability { get; init; } + public int? Misogyny { get; init; } + public int? OverallLevel { get; init; } + public int? RaceEthnicityOrReligion { get; init; } + public int? SexBasedTerms { get; init; } + public int? SexualitySexOrGender { get; init; } + public int? Swearing { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewChannelInformation.cs b/MiniTwitch.Helix/Requests/NewChannelInformation.cs new file mode 100644 index 0000000..4cf3503 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewChannelInformation.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewChannelInformation +{ + public string GameId { get; init; } + public string BroadcasterLanguage { get; init; } + public string Title { get; init; } + [JsonConverter(typeof(TimeSpanToSeconds))] + public TimeSpan? Delay { get; init; } + public IEnumerable Tags { get; init; } + [JsonPropertyName("content_classification_labels")] + public IEnumerable ClassificationLabels { get; init; } + public bool? IsBrandedContent { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewChatSettings.cs b/MiniTwitch.Helix/Requests/NewChatSettings.cs new file mode 100644 index 0000000..66f0167 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewChatSettings.cs @@ -0,0 +1,14 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewChatSettings +{ + public bool? EmoteMode { get; init; } + public bool? FollowerMode { get; init; } + public bool? NonModeratorChatDelay { get; init; } + public bool? SlowMode { get; init; } + public bool? SubscriberMode { get; init; } + public bool? UniqueChatMode { get; init; } + public int? FollowerModeDuration { get; init; } + public int? NonModeratorChatDelayDuration { get; init; } + public int? SlowModeWaitTime { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewCommercial.cs b/MiniTwitch.Helix/Requests/NewCommercial.cs new file mode 100644 index 0000000..d77083a --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewCommercial.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewCommercial +{ + [JsonConverter(typeof(LongToString))] + public required long BroadcasterId { get; init; } + public required int Length { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewCustomReward.cs b/MiniTwitch.Helix/Requests/NewCustomReward.cs new file mode 100644 index 0000000..e3d6910 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewCustomReward.cs @@ -0,0 +1,18 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewCustomReward +{ + public required string Title { get; init; } + public required long Cost { get; init; } + public string Prompt { get; init; } + public bool? IsEnabled { get; init; } + public string BackgroundColor { get; init; } + public bool? IsUserInputRequired { get; init; } + public bool? IsMaxPerStreamEnabled { get; init; } + public int? MaxPerStream { get; init; } + public bool? IsMaxPerUserPerStreamEnabled { get; init; } + public int? MaxPerUserPerStream { get; init; } + public bool? IsGlobalCooldownEnabled { get; init; } + public int? GlobalCooldownSeconds { get; init; } + public bool? ShouldRedemptionsSkipRequestQueue { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewGuestStarSettings.cs b/MiniTwitch.Helix/Requests/NewGuestStarSettings.cs new file mode 100644 index 0000000..6e95947 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewGuestStarSettings.cs @@ -0,0 +1,10 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewGuestStarSettings +{ + public bool? IsModeratorSendLiveEnabled { get; init; } + public int? SlotCount { get; init; } + public bool? IsBrowserSourceAudioEnabled { get; init; } + public string? GroupLayout { get; init; } + public bool? RegenerateBrowserSources { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewPoll.cs b/MiniTwitch.Helix/Requests/NewPoll.cs new file mode 100644 index 0000000..5073281 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewPoll.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewPoll +{ + [JsonConverter(typeof(LongToString))] + public required long BroadcasterId { get; init; } + public required string Title { get; init; } + public required IEnumerable Choices { get; init; } + [JsonConverter(typeof(TimeSpanToSeconds))] + public required TimeSpan Duration { get; init; } + public bool? ChannelPointsVotingEnabled { get; init; } + public int? ChannelPointsPerVote { get; init; } + + public class Choice + { + public required string Title { get; init; } + } +} diff --git a/MiniTwitch.Helix/Requests/NewPrediction.cs b/MiniTwitch.Helix/Requests/NewPrediction.cs new file mode 100644 index 0000000..34f3308 --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewPrediction.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewPrediction +{ + [JsonConverter(typeof(LongToString))] + public required long BroadcasterId { get; init; } + public required string Title { get; init; } + public required IEnumerable Outcomes { get; init; } + [JsonConverter(typeof(TimeSpanToSeconds))] + public required TimeSpan PredictionWindow { get; init; } + + public class Outcome + { + public required string Title { get; init; } + } +} diff --git a/MiniTwitch.Helix/Requests/NewScheduleSegment.cs b/MiniTwitch.Helix/Requests/NewScheduleSegment.cs new file mode 100644 index 0000000..6f3a53e --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewScheduleSegment.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewScheduleSegment +{ + public required DateTime StartTime { get; init; } + public required string Timezone { get; init; } + [JsonConverter(typeof(IntToString))] + public required int DurationHours { get; init; } + public bool? IsRecurring { get; init; } + public string CategoryId { get; init; } + public string Title { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/NewSubscription.cs b/MiniTwitch.Helix/Requests/NewSubscription.cs new file mode 100644 index 0000000..b19941c --- /dev/null +++ b/MiniTwitch.Helix/Requests/NewSubscription.cs @@ -0,0 +1,16 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct NewSubscription +{ + public required string Type { get; init; } + public required string Version { get; init; } + public required EventsubTransport Transport { get; init; } + + public readonly struct EventsubTransport + { + public required string Method { get; init; } + public string Callback { get; init; } + public string Secret { get; init; } + public string SessionId { get; init; } + } +} diff --git a/MiniTwitch.Helix/Requests/PredictionToEnd.cs b/MiniTwitch.Helix/Requests/PredictionToEnd.cs new file mode 100644 index 0000000..32b0fab --- /dev/null +++ b/MiniTwitch.Helix/Requests/PredictionToEnd.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct PredictionToEnd +{ + [JsonConverter(typeof(LongToString))] + public required long BroadcasterId { get; init; } + public required string Id { get; init; } + public required string Status { get; init; } + public string WinningOutcomeId { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/UpdatedBitsProduct.cs b/MiniTwitch.Helix/Requests/UpdatedBitsProduct.cs new file mode 100644 index 0000000..c9b3ec1 --- /dev/null +++ b/MiniTwitch.Helix/Requests/UpdatedBitsProduct.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct UpdatedBitsProduct +{ + [JsonPropertyName("sku")] + public required string SKU { get; init; } + [JsonIgnore] + public required int CostBits { get; init; } + [JsonInclude] + private object cost => new { amount = this.CostBits, type = "bits" }; + public required string DisplayName { get; init; } + public bool? InDevelopment { get; init; } + public DateTime? Expiration { get; init; } + public bool? IsBroadcast { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/UpdatedCustomReward.cs b/MiniTwitch.Helix/Requests/UpdatedCustomReward.cs new file mode 100644 index 0000000..bc294ac --- /dev/null +++ b/MiniTwitch.Helix/Requests/UpdatedCustomReward.cs @@ -0,0 +1,19 @@ +namespace MiniTwitch.Helix.Requests; + +public readonly struct UpdatedCustomReward +{ + public string Title { get; init; } + public long? Cost { get; init; } + public string Prompt { get; init; } + public bool? IsEnabled { get; init; } + public string BackgroundColor { get; init; } + public bool? IsUserInputRequired { get; init; } + public bool? IsMaxPerStreamEnabled { get; init; } + public int? MaxPerStream { get; init; } + public bool? IsMaxPerUserPerStreamEnabled { get; init; } + public int? MaxPerUserPerStream { get; init; } + public bool? IsGlobalCooldownEnabled { get; init; } + public int? GlobalCooldownSeconds { get; init; } + public bool? ShouldRedemptionsSkipRequestQueue { get; init; } + public bool? IsPaused { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/UpdatedScheduleSegment.cs b/MiniTwitch.Helix/Requests/UpdatedScheduleSegment.cs new file mode 100644 index 0000000..3dd941b --- /dev/null +++ b/MiniTwitch.Helix/Requests/UpdatedScheduleSegment.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct UpdatedScheduleSegment +{ + public DateTime? StartTime { get; init; } + public string Timezone { get; init; } + [JsonConverter(typeof(IntToString))] + public int DurationHours { get; init; } + public bool? IsRecurring { get; init; } + public string CategoryId { get; init; } + public string Title { get; init; } +} diff --git a/MiniTwitch.Helix/Requests/UserToBan.cs b/MiniTwitch.Helix/Requests/UserToBan.cs new file mode 100644 index 0000000..82caede --- /dev/null +++ b/MiniTwitch.Helix/Requests/UserToBan.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Internal.Json; + +namespace MiniTwitch.Helix.Requests; + +public readonly struct UserToBan +{ + public required Info Data { get; init; } + + public readonly struct Info + { + [JsonConverter(typeof(LongToString))] + public required long UserId { get; init; } + [JsonConverter(typeof(TimeSpanToSeconds))] + public TimeSpan? Duration { get; init; } + public string Reason { get; init; } + } +} diff --git a/MiniTwitch.Helix/Responses/ActiveExtensions.cs b/MiniTwitch.Helix/Responses/ActiveExtensions.cs new file mode 100644 index 0000000..bd0a7b4 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ActiveExtensions.cs @@ -0,0 +1,38 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Responses; + +public class ActiveExtensions +{ + [JsonPropertyName("data")] + public ExtensionsData Data { get; init; } + + public record Component( + [property: JsonPropertyName("active")] bool Active, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("x")] int X, + [property: JsonPropertyName("y")] int Y + ); + + public record Panel( + [property: JsonPropertyName("active")] bool Active, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("name")] string Name + ); + + public record Overlay( + [property: JsonPropertyName("active")] bool Active, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("name")] string Name + ); + + public record ExtensionsData( + [property: JsonPropertyName("panel")] Dictionary Panel, + [property: JsonPropertyName("overlay")] Dictionary Overlay, + [property: JsonPropertyName("component")] Dictionary Component + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/AdSchedule.cs b/MiniTwitch.Helix/Responses/AdSchedule.cs new file mode 100644 index 0000000..eb34484 --- /dev/null +++ b/MiniTwitch.Helix/Responses/AdSchedule.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class AdSchedule : BaseResponse +{ + public record Ad( + [property: JsonPropertyName("next_ad_at")] DateTime? NextAdAt, + [property: JsonPropertyName("last_ad_at")] DateTime? LastAdAt, + [property: JsonPropertyName("length_seconds")] int LengthSeconds, + [property: JsonPropertyName("preroll_free_time_seconds")] int PrerollFreeTimeSeconds, + [property: JsonPropertyName("snooze_count")] int SnoozeCount, + [property: JsonPropertyName("snooze_refresh_at")] DateTime? SnoozeRefreshAt + ); +} diff --git a/MiniTwitch.Helix/Responses/AutoModSettings.cs b/MiniTwitch.Helix/Responses/AutoModSettings.cs new file mode 100644 index 0000000..620c0c4 --- /dev/null +++ b/MiniTwitch.Helix/Responses/AutoModSettings.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class AutoModSettings : SingleResponse +{ + public record Settings( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("moderator_id")] long ModeratorId, + [property: JsonPropertyName("overall_level")] int? OverallLevel, + [property: JsonPropertyName("disability")] int Disability, + [property: JsonPropertyName("aggression")] int Aggression, + [property: JsonPropertyName("sexuality_sex_or_gender")] int SexualitySexOrGender, + [property: JsonPropertyName("misogyny")] int Misogyny, + [property: JsonPropertyName("bullying")] int Bullying, + [property: JsonPropertyName("swearing")] int Swearing, + [property: JsonPropertyName("race_ethnicity_or_religion")] int RaceEthnicityOrReligion, + [property: JsonPropertyName("sex_based_terms")] int SexBasedTerms + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/AutoModStatus.cs b/MiniTwitch.Helix/Responses/AutoModStatus.cs new file mode 100644 index 0000000..d1d22ea --- /dev/null +++ b/MiniTwitch.Helix/Responses/AutoModStatus.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class AutoModStatus : BaseResponse +{ + public record Message( + [property: JsonPropertyName("msg_id")] string MessageId, + [property: JsonPropertyName("is_permitted")] bool IsPermitted + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BannedUser.cs b/MiniTwitch.Helix/Responses/BannedUser.cs new file mode 100644 index 0000000..024167c --- /dev/null +++ b/MiniTwitch.Helix/Responses/BannedUser.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BannedUser : BaseResponse +{ + public record User( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("moderator_id")] long ModeratorId, + [property: JsonPropertyName("user_id")] string UserId, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("end_time")] DateTime? EndTime + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BannedUsers.cs b/MiniTwitch.Helix/Responses/BannedUsers.cs new file mode 100644 index 0000000..98c5889 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BannedUsers.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BannedUsers : PaginableResponse +{ + public record User( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("expires_at")] DateTime? ExpiresAt, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("reason")] string Reason, + [property: JsonPropertyName("moderator_id")] long ModeratorId, + [property: JsonPropertyName("moderator_login")] string ModeratorName, + [property: JsonPropertyName("moderator_name")] string ModeratorDisplayName + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BitsLeaderboard.cs b/MiniTwitch.Helix/Responses/BitsLeaderboard.cs new file mode 100644 index 0000000..ef319a0 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BitsLeaderboard.cs @@ -0,0 +1,24 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BitsLeaderboard : BaseResponse +{ + [JsonPropertyName("date_range")] + public StartEndDate DateRange { get; init; } + [JsonPropertyName("total")] + public int Total { get; init; } + + public record User( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("user_name")] string DisplayName, + [property: JsonPropertyName("rank")] int Rank, + [property: JsonPropertyName("score")] int Score + ); + public record StartEndDate( + [property: JsonPropertyName("started_at")] DateTime StartedAt, + [property: JsonPropertyName("ended_at")] DateTime EndedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BlockList.cs b/MiniTwitch.Helix/Responses/BlockList.cs new file mode 100644 index 0000000..9ce68f5 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BlockList.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BlockList : PaginableResponse +{ + public record User( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("display_name")] string UserDisplayName + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BlockedTerm.cs b/MiniTwitch.Helix/Responses/BlockedTerm.cs new file mode 100644 index 0000000..422fe20 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BlockedTerm.cs @@ -0,0 +1,7 @@ +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BlockedTerm : SingleResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BlockedTerms.cs b/MiniTwitch.Helix/Responses/BlockedTerms.cs new file mode 100644 index 0000000..ba0dd60 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BlockedTerms.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BlockedTerms : PaginableResponse +{ + public record Term( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("moderator_id")] long ModeratorId, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("text")] string Text, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("updated_at")] DateTime? UpdatedAt, + [property: JsonPropertyName("expires_at")] DateTime? ExpiresAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/BroadcasterSubscriptions.cs b/MiniTwitch.Helix/Responses/BroadcasterSubscriptions.cs new file mode 100644 index 0000000..e214be1 --- /dev/null +++ b/MiniTwitch.Helix/Responses/BroadcasterSubscriptions.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class BroadcasterSubscriptions : PaginableResponse +{ + [property: JsonPropertyName("total")] + public int Total { get; init; } + [property: JsonPropertyName("points")] + public int Points { get; init; } + + public record Subscription( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("gifter_login")] string GifterName, + [property: JsonPropertyName("gifter_name")] string GifterDisplayName, + [property: JsonPropertyName("is_gift")] bool IsGift, + [property: JsonPropertyName("tier")] string Tier, + [property: JsonPropertyName("plan_name")] string PlanName, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("user_login")] string Username + ) + { + [JsonInclude, JsonPropertyName("gifter_id")] + private readonly string _gifterId = default!; + [JsonIgnore] + public long GifterId => _gifterId is { Length: > 0 } ? long.Parse(_gifterId) : 0; + }; +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Categories.cs b/MiniTwitch.Helix/Responses/Categories.cs new file mode 100644 index 0000000..b356150 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Categories.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Categories : PaginableResponse +{ + public record Category( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("box_art_url")] string BoxArtUrl + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChannelEditors.cs b/MiniTwitch.Helix/Responses/ChannelEditors.cs new file mode 100644 index 0000000..fa623f2 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChannelEditors.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChannelEditors : BaseResponse +{ + public record Editor( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("created_at")] DateTime CreatedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChannelFollowers.cs b/MiniTwitch.Helix/Responses/ChannelFollowers.cs new file mode 100644 index 0000000..74d7260 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChannelFollowers.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChannelFollowers : PaginableResponse +{ + [JsonPropertyName("total")] + public int Total { get; init; } + + public record Follower( + [property: JsonPropertyName("user_id")] long FollowerId, + [property: JsonPropertyName("user_login")] string FollowerName, + [property: JsonPropertyName("user_name")] string FollowerDisplayName, + [property: JsonPropertyName("followed_at")] DateTime FollowedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChannelGuestStarSettings.cs b/MiniTwitch.Helix/Responses/ChannelGuestStarSettings.cs new file mode 100644 index 0000000..0040b9d --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChannelGuestStarSettings.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChannelGuestStarSettings : SingleResponse +{ + public record Settings( + [property: JsonPropertyName("is_moderator_send_live_enabled")] bool IsModeratorSendLiveEnabled, + [property: JsonPropertyName("slot_count")] int SlotCount, + [property: JsonPropertyName("is_browser_source_audio_enabled")] bool IsBrowserSourceAudioEnabled, + [property: JsonPropertyName("layout")] string Layout, + [property: JsonPropertyName("browser_source_token")] string BrowserSourceToken + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChannelTeams.cs b/MiniTwitch.Helix/Responses/ChannelTeams.cs new file mode 100644 index 0000000..8e2ed3f --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChannelTeams.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChannelTeams : BaseResponse +{ + public record Team( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("background_image_url")] string? BackgroundImageUrl, + [property: JsonPropertyName("banner")] string? Banner, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("updated_at")] DateTime? UpdatedAt, + [property: JsonPropertyName("info")] string Info, + [property: JsonPropertyName("thumbnail_url")] string ThumbnailUrl, + [property: JsonPropertyName("team_name")] string TeamName, + [property: JsonPropertyName("team_display_name")] string TeamDisplayName, + [property: JsonPropertyName("id")] string Id + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Channels.cs b/MiniTwitch.Helix/Responses/Channels.cs new file mode 100644 index 0000000..6d01e87 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Channels.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Channels : PaginableResponse +{ + public record Channel( + [property: JsonPropertyName("broadcaster_language")] string BroadcasterLanguage, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("display_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("game_name")] string GameName, + [property: JsonPropertyName("id")] long BroadcasterId, + [property: JsonPropertyName("is_live")] bool IsLive, + [property: JsonPropertyName("tags")] IReadOnlyList Tags, + [property: JsonPropertyName("thumbnail_url")] string ThumbnailUrl, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("started_at")] DateTime? StartedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChannelsInformation.cs b/MiniTwitch.Helix/Responses/ChannelsInformation.cs new file mode 100644 index 0000000..1ce91d3 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChannelsInformation.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChannelsInformation : BaseResponse +{ + public record Information( + [property: JsonPropertyName("broadcaster_id")] long Id, + [property: JsonPropertyName("broadcaster_login")] string Name, + [property: JsonPropertyName("broadcaster_name")] string DisplayName, + [property: JsonPropertyName("broadcaster_language")] string Language, + [property: JsonPropertyName("game_name")] string GameName, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("delay")] int Delay, + [property: JsonPropertyName("tags")] IReadOnlyList Tags + ); +} + +public class ChannelInformation : SingleResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CharityCampaign.cs b/MiniTwitch.Helix/Responses/CharityCampaign.cs new file mode 100644 index 0000000..28be30b --- /dev/null +++ b/MiniTwitch.Helix/Responses/CharityCampaign.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CharityCampaign : BaseResponse +{ + public record Campaign( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("charity_name")] string CharityName, + [property: JsonPropertyName("charity_description")] string CharityDescription, + [property: JsonPropertyName("charity_logo")] string CharityLogo, + [property: JsonPropertyName("charity_website")] string CharityWebsite, + [property: JsonPropertyName("current_amount")] CurrentAmount CurrentAmount, + [property: JsonPropertyName("target_amount")] TargetAmount TargetAmount + ); + + public record CurrentAmount( + [property: JsonPropertyName("value")] int Value, + [property: JsonPropertyName("decimal_places")] int DecimalPlaces, + [property: JsonPropertyName("currency")] string Currency + ); + + public record TargetAmount( + [property: JsonPropertyName("value")] int Value, + [property: JsonPropertyName("decimal_places")] int DecimalPlaces, + [property: JsonPropertyName("currency")] string Currency + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CharityCampaignDonations.cs b/MiniTwitch.Helix/Responses/CharityCampaignDonations.cs new file mode 100644 index 0000000..276af34 --- /dev/null +++ b/MiniTwitch.Helix/Responses/CharityCampaignDonations.cs @@ -0,0 +1,25 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CharityCampaignDonations : PaginableResponse +{ + public record Donation( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("campaign_id")] string CampaignId, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("amount")] DonationAmount Amount + ); + + public record DonationAmount( + [property: JsonPropertyName("value")] int Value, + [property: JsonPropertyName("decimal_places")] int DecimalPlaces, + [property: JsonPropertyName("curency")] string Currency + ) + { + public double GetActualAmount() => this.Value * Math.Pow(10, -this.DecimalPlaces); + }; +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChatBadges.cs b/MiniTwitch.Helix/Responses/ChatBadges.cs new file mode 100644 index 0000000..0c4020d --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChatBadges.cs @@ -0,0 +1,23 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChatBadges : SingleResponse +{ + public record BadgeSet( + [property: JsonPropertyName("set_id")] string SetId, + [property: JsonPropertyName("versions")] IReadOnlyList Versions + ); + + public record Version( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("image_url_1x")] string ImageUrl1x, + [property: JsonPropertyName("image_url_2x")] string ImageUrl2x, + [property: JsonPropertyName("image_url_4x")] string ImageUrl4x, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("click_action")] string ClickAction, + [property: JsonPropertyName("click_url")] string ClickUrl + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ChatSettings.cs b/MiniTwitch.Helix/Responses/ChatSettings.cs new file mode 100644 index 0000000..04ed4c1 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ChatSettings.cs @@ -0,0 +1,20 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ChatSettings : SingleResponse +{ + public record Settings( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("slow_mode")] bool SlowMode, + [property: JsonPropertyName("slow_mode_wait_time")] int SlowModeWaitTime, + [property: JsonPropertyName("follower_mode")] bool FollowerMode, + [property: JsonPropertyName("follower_mode_duration")] int FollowerModeDuration, + [property: JsonPropertyName("subscriber_mode")] bool SubscriberMode, + [property: JsonPropertyName("emote_mode")] bool EmoteMode, + [property: JsonPropertyName("unique_chat_mode")] bool UniqueChatMode, + [property: JsonPropertyName("non_moderator_chat_delay")] bool NonModeratorChatDelay, + [property: JsonPropertyName("non_moderator_chat_delay_duration")] int NonModeratorChatDelayDuration + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Chatters.cs b/MiniTwitch.Helix/Responses/Chatters.cs new file mode 100644 index 0000000..f2d0571 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Chatters.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Chatters : PaginableResponse +{ + [JsonPropertyName("total")] + public int Total { get; init; } + + public record Chatter( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("user_name")] string UserDisplayName + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Cheermotes.cs b/MiniTwitch.Helix/Responses/Cheermotes.cs new file mode 100644 index 0000000..8610e03 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Cheermotes.cs @@ -0,0 +1,32 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Cheermotes : BaseResponse +{ + public record Emote( + [property: JsonPropertyName("prefix")] string Prefix, + [property: JsonPropertyName("tiers")] IReadOnlyList Tiers, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("order")] int Order, + [property: JsonPropertyName("last_updated")] DateTime LastUpdated, + [property: JsonPropertyName("is_charitable")] bool IsCharitable + ); + public record Tier( + [property: JsonPropertyName("min_bits")] int MinBits, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("color")] string Color, + [property: JsonPropertyName("images")] Images Images, + [property: JsonPropertyName("can_cheer")] bool CanCheer, + [property: JsonPropertyName("show_in_bits_card")] bool ShowInBitsCard + ); + public record Images( + [property: JsonPropertyName("dark")] ImageSet Dark, + [property: JsonPropertyName("light")] ImageSet Light + ); + public record ImageSet( + [property: JsonPropertyName("animated")] IDictionary Animated, + [property: JsonPropertyName("static")] IDictionary Static + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Clip.cs b/MiniTwitch.Helix/Responses/Clip.cs new file mode 100644 index 0000000..25f2c92 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Clip.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Clip : SingleResponse +{ + public record Info( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("edit_url")] string EditUrl + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Clips.cs b/MiniTwitch.Helix/Responses/Clips.cs new file mode 100644 index 0000000..43cbe9d --- /dev/null +++ b/MiniTwitch.Helix/Responses/Clips.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Clips : PaginableResponse +{ + public record Clip( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("url")] string Url, + [property: JsonPropertyName("embed_url")] string EmbedUrl, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterName, + [property: JsonPropertyName("creator_id")] long CreatorId, + [property: JsonPropertyName("creator_name")] string CreatorName, + [property: JsonPropertyName("video_id")] string VideoId, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("language")] string Language, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("view_count")] int ViewCount, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("thumbnail_url")] string ThumbnailUrl, + [property: JsonPropertyName("duration")] int Duration, + [property: JsonPropertyName("vod_offset")] int VodOffset, + [property: JsonPropertyName("is_featured")] bool IsFeatured + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Commercial.cs b/MiniTwitch.Helix/Responses/Commercial.cs new file mode 100644 index 0000000..7df0344 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Commercial.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Commercial : SingleResponse +{ + public record Info( + [property: JsonPropertyName("length")] int Length, + [property: JsonPropertyName("message")] string Message, + [property: JsonPropertyName("retry_after")] int RetryAfter + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ContentClassificationLabels.cs b/MiniTwitch.Helix/Responses/ContentClassificationLabels.cs new file mode 100644 index 0000000..e955385 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ContentClassificationLabels.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ContentClassificationLabels : BaseResponse +{ + public record Label( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("name")] string Name + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CreatedSubscription.cs b/MiniTwitch.Helix/Responses/CreatedSubscription.cs new file mode 100644 index 0000000..0c515ac --- /dev/null +++ b/MiniTwitch.Helix/Responses/CreatedSubscription.cs @@ -0,0 +1,34 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CreatedSubscription : SingleResponse +{ + [JsonPropertyName("total")] + public int Total { get; init; } + [JsonPropertyName("total_cost")] + public int TotalCost { get; init; } + [JsonPropertyName("max_total_cost")] + public int MaxTotalCost { get; init; } + + public record Condition( + [property: JsonPropertyName("user_id")] long UserId + ); + + public record Info( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("status")] string Status, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("condition")] Condition Condition, + [property: JsonPropertyName("created_at")] string CreatedAt, + [property: JsonPropertyName("transport")] Transport Transport, + [property: JsonPropertyName("cost")] int Cost + ); + + public record Transport( + [property: JsonPropertyName("method")] string Method, + [property: JsonPropertyName("callback")] string Callback + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CreatorGoals.cs b/MiniTwitch.Helix/Responses/CreatorGoals.cs new file mode 100644 index 0000000..e747dfc --- /dev/null +++ b/MiniTwitch.Helix/Responses/CreatorGoals.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CreatorGoals : BaseResponse +{ + public record Goal( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("current_amount")] int CurrentAmount, + [property: JsonPropertyName("target_amount")] int TargetAmount, + [property: JsonPropertyName("created_at")] DateTime CreatedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CustomReward.cs b/MiniTwitch.Helix/Responses/CustomReward.cs new file mode 100644 index 0000000..58ed0ff --- /dev/null +++ b/MiniTwitch.Helix/Responses/CustomReward.cs @@ -0,0 +1,51 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CustomReward : SingleResponse +{ + public record Reward( + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("id")] string RewardId, + [property: JsonPropertyName("image")] Image? Image, + [property: JsonPropertyName("background_color")] string BackgroundColor, + [property: JsonPropertyName("is_enabled")] bool IsEnabled, + [property: JsonPropertyName("cost")] long Cost, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("prompt")] string Prompt, + [property: JsonPropertyName("is_user_input_required")] bool IsUserInputRequired, + [property: JsonPropertyName("max_per_stream_setting")] MaxPerStreamSetting MaxPerStreamSetting, + [property: JsonPropertyName("max_per_user_per_stream_setting")] MaxPerUserPerStreamSetting MaxPerUserPerStreamSetting, + [property: JsonPropertyName("global_cooldown_setting")] GlobalCooldownSetting GlobalCooldownSetting, + [property: JsonPropertyName("is_paused")] bool IsPaused, + [property: JsonPropertyName("is_in_stock")] bool IsInStock, + [property: JsonPropertyName("default_image")] Image DefaultImage, + [property: JsonPropertyName("should_redemptions_skip_request_queue")] bool ShouldRedemptionsSkipRequestQueue, + [property: JsonPropertyName("redemptions_redeemed_current_stream")] int? RedemptionsRedeemedInCurrentStream, + [property: JsonPropertyName("cooldown_expires_at")] DateTime? CooldownExpiresAt + ); + + public record Image( + [property: JsonPropertyName("url_1x")] string Url1x, + [property: JsonPropertyName("url_2x")] string Url2x, + [property: JsonPropertyName("url_4x")] string Url4x + ); + + public record GlobalCooldownSetting( + [property: JsonPropertyName("is_enabled")] bool IsEnabled, + [property: JsonPropertyName("global_cooldown_seconds")] long GlobalCooldownSeconds + ); + + public record MaxPerStreamSetting( + [property: JsonPropertyName("is_enabled")] bool IsEnabled, + [property: JsonPropertyName("max_per_stream")] long MaxPerStream + ); + + public record MaxPerUserPerStreamSetting( + [property: JsonPropertyName("is_enabled")] bool IsEnabled, + [property: JsonPropertyName("max_per_user_per_stream")] long MaxPerUserPerStream + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/CustomRewardRedemptions.cs b/MiniTwitch.Helix/Responses/CustomRewardRedemptions.cs new file mode 100644 index 0000000..9d02449 --- /dev/null +++ b/MiniTwitch.Helix/Responses/CustomRewardRedemptions.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Enums; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class CustomRewardRedemptions : PaginableResponse +{ + public record Info( + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("user_login")] string UserName, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("user_input")] string UserInput, + [property: JsonPropertyName("redeemed_at")] DateTime RedeemedAt, + [property: JsonPropertyName("reward")] RedemptionReward Reward + ) + { + internal string status = "None"; + public RewardRedemptionStatus Status => Enum.Parse(status); + }; + + public record RedemptionReward( + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("prompt")] string Prompt, + [property: JsonPropertyName("cost")] long Cost + ); +} + +public class CustomRewardRedemption : PaginableResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/DropsEntitlements.cs b/MiniTwitch.Helix/Responses/DropsEntitlements.cs new file mode 100644 index 0000000..4f94a83 --- /dev/null +++ b/MiniTwitch.Helix/Responses/DropsEntitlements.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class DropsEntitlements : PaginableResponse +{ + public record Entitlement( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("benefit_id")] string BenefitId, + [property: JsonPropertyName("timestamp")] DateTime Timestamp, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("fulfillment_status")] string FulfillmentStatus, + [property: JsonPropertyName("last_updated")] DateTime LastUpdated + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/EmoteSets.cs b/MiniTwitch.Helix/Responses/EmoteSets.cs new file mode 100644 index 0000000..3b64a9f --- /dev/null +++ b/MiniTwitch.Helix/Responses/EmoteSets.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class EmoteSets : BaseResponse +{ + [JsonPropertyName("template")] + public string Template { get; init; } + + public record Emote( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("images")] Images Images, + [property: JsonPropertyName("emote_type")] string EmoteType, + [property: JsonPropertyName("emote_set_id")] string EmoteSetId, + [property: JsonPropertyName("owner_id")] long OwnerId, + [property: JsonPropertyName("format")] IReadOnlyList Formats, + [property: JsonPropertyName("scale")] IReadOnlyList Scales, + [property: JsonPropertyName("theme_mode")] IReadOnlyList ThemeModes + ); + + public record Images( + [property: JsonPropertyName("url_1x")] string Url1x, + [property: JsonPropertyName("url_2x")] string Url2x, + [property: JsonPropertyName("url_4x")] string Url4x + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Emotes.cs b/MiniTwitch.Helix/Responses/Emotes.cs new file mode 100644 index 0000000..e17444c --- /dev/null +++ b/MiniTwitch.Helix/Responses/Emotes.cs @@ -0,0 +1,28 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Emotes : BaseResponse +{ + [JsonPropertyName("template")] + public string Template { get; init; } + + public record Emote( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("images")] Images Images, + [property: JsonPropertyName("tier")] string Tier, + [property: JsonPropertyName("emote_type")] string EmoteType, + [property: JsonPropertyName("emote_set_id")] string EmoteSetId, + [property: JsonPropertyName("format")] IReadOnlyList Formats, + [property: JsonPropertyName("scale")] IReadOnlyList Scales, + [property: JsonPropertyName("theme_mode")] IReadOnlyList ThemeModes + ); + + public record Images( + [property: JsonPropertyName("url_1x")] string Url1x, + [property: JsonPropertyName("url_2x")] string Url2x, + [property: JsonPropertyName("url_4x")] string Url4x + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/EventSubSubscriptions.cs b/MiniTwitch.Helix/Responses/EventSubSubscriptions.cs new file mode 100644 index 0000000..232e1f9 --- /dev/null +++ b/MiniTwitch.Helix/Responses/EventSubSubscriptions.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class EventSubSubscriptions : PaginableResponse +{ + [JsonPropertyName("total_cost")] + public int TotalCost { get; init; } + [JsonPropertyName("max_total_cost")] + public int MaxTotalCost { get; init; } + [JsonPropertyName("total")] + public int Total { get; init; } + + public record Condition( + [property: JsonPropertyName("broadcaster_user_id")] long BroadcasterUserId, + [property: JsonPropertyName("user_id")] long UserId + ); + + public record Subscription( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("status")] string Status, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("condition")] Condition Condition, + [property: JsonPropertyName("created_at")] string CreatedAt, + [property: JsonPropertyName("transport")] Transport Transport, + [property: JsonPropertyName("cost")] int Cost + ); + + public record Transport( + [property: JsonPropertyName("method")] string Method, + [property: JsonPropertyName("callback")] string Callback + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionAnalytics.cs b/MiniTwitch.Helix/Responses/ExtensionAnalytics.cs new file mode 100644 index 0000000..e7c4f86 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionAnalytics.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionAnalytics : PaginableResponse +{ + public record Analytics( + [property: JsonPropertyName("extension_id")] string ExtensionId, + [property: JsonPropertyName("URL")] string Url, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("date_range")] DateRange DateRange + ); + public record DateRange( + [property: JsonPropertyName("started_at")] DateTime StartedAt, + [property: JsonPropertyName("ended_at")] DateTime EndedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionBitsProducts.cs b/MiniTwitch.Helix/Responses/ExtensionBitsProducts.cs new file mode 100644 index 0000000..f165d51 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionBitsProducts.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionBitsProducts : BaseResponse +{ + public record Cost( + [property: JsonPropertyName("amount")] int Amount, + [property: JsonPropertyName("type")] string Type + ); + + public record BitsProduct( + [property: JsonPropertyName("sku")] string SKU, + [property: JsonPropertyName("cost")] Cost Cost, + [property: JsonPropertyName("in_development")] bool InDevelopment, + [property: JsonPropertyName("display_name")] string DisplayName, + [property: JsonPropertyName("expiration")] DateTime Expiration, + [property: JsonPropertyName("is_broadcast")] bool IsBroadcast + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionConfigurationSegment.cs b/MiniTwitch.Helix/Responses/ExtensionConfigurationSegment.cs new file mode 100644 index 0000000..666e23f --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionConfigurationSegment.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionConfigurationSegment : SingleResponse +{ + public record ConfigSegment( + [property: JsonPropertyName("segment")] string Segment, + [property: JsonPropertyName("content")] string Content, + [property: JsonPropertyName("version")] string Version + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionLiveChannels.cs b/MiniTwitch.Helix/Responses/ExtensionLiveChannels.cs new file mode 100644 index 0000000..b6b6be5 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionLiveChannels.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionLiveChannels : PaginableResponse +{ + public record Channel( + [property: JsonPropertyName("broadcaster_id")] string BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("game_name")] string GameName, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("title")] string Title + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionSecrets.cs b/MiniTwitch.Helix/Responses/ExtensionSecrets.cs new file mode 100644 index 0000000..851d464 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionSecrets.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionSecrets : BaseResponse +{ + public record Info( + [property: JsonPropertyName("format_version")] int FormatVersion, + [property: JsonPropertyName("secrets")] IReadOnlyList Secrets + ); + + public record Secret( + [property: JsonPropertyName("content")] string Content, + [property: JsonPropertyName("active_at")] DateTime ActiveAt, + [property: JsonPropertyName("expires_at")] DateTime ExpiresAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ExtensionTransactions.cs b/MiniTwitch.Helix/Responses/ExtensionTransactions.cs new file mode 100644 index 0000000..ee1fb35 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ExtensionTransactions.cs @@ -0,0 +1,33 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ExtensionTransactions : PaginableResponse +{ + public record Transaction( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("timestamp")] DateTime Timestamp, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_login")] string UserName, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("product_type")] string ProductType, + [property: JsonPropertyName("product_data")] ProductData ProductData + ); + public record ProductData( + [property: JsonPropertyName("domain")] string Domain, + [property: JsonPropertyName("sku")] string Sku, + [property: JsonPropertyName("cost")] Cost Cost, + [property: JsonPropertyName("inDevelopment")] bool InDevelopment, + [property: JsonPropertyName("displayName")] string DisplayName, + [property: JsonPropertyName("expiration")] string Expiration, + [property: JsonPropertyName("broadcast")] bool Broadcast + ); + public record Cost( + [property: JsonPropertyName("amount")] int Amount, + [property: JsonPropertyName("type")] string Type + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Extensions.cs b/MiniTwitch.Helix/Responses/Extensions.cs new file mode 100644 index 0000000..2336a9f --- /dev/null +++ b/MiniTwitch.Helix/Responses/Extensions.cs @@ -0,0 +1,76 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Extensions : BaseResponse +{ + public record Component( + [property: JsonPropertyName("viewer_url")] string ViewerUrl, + [property: JsonPropertyName("aspect_width")] int AspectWidth, + [property: JsonPropertyName("aspect_height")] int AspectHeight, + [property: JsonPropertyName("aspect_ratio_x")] int AspectRatioX, + [property: JsonPropertyName("aspect_ratio_y")] int AspectRatioY, + [property: JsonPropertyName("autoscale")] bool Autoscale, + [property: JsonPropertyName("scale_pixels")] int ScalePixels, + [property: JsonPropertyName("target_height")] int TargetHeight, + [property: JsonPropertyName("size")] int Size, + [property: JsonPropertyName("zoom")] bool Zoom, + [property: JsonPropertyName("zoom_pixels")] int ZoomPixels, + [property: JsonPropertyName("can_link_external_content")] bool CanLinkExternalContent + ); + + public record Extension( + [property: JsonPropertyName("author_name")] string AuthorName, + [property: JsonPropertyName("bits_enabled")] bool BitsEnabled, + [property: JsonPropertyName("can_install")] bool CanInstall, + [property: JsonPropertyName("configuration_location")] string ConfigurationLocation, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("eula_tos_url")] string EulaTosUrl, + [property: JsonPropertyName("has_chat_support")] bool HasChatSupport, + [property: JsonPropertyName("icon_url")] string IconUrl, + [property: JsonPropertyName("icon_urls")] IconUrls IconUrls, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("privacy_policy_url")] string PrivacyPolicyUrl, + [property: JsonPropertyName("request_identity_link")] bool RequestIdentityLink, + [property: JsonPropertyName("screenshot_urls")] IReadOnlyList ScreenshotUrls, + [property: JsonPropertyName("state")] string State, + [property: JsonPropertyName("subscriptions_support_level")] string SubscriptionsSupportLevel, + [property: JsonPropertyName("summary")] string Summary, + [property: JsonPropertyName("support_email")] string SupportEmail, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("viewer_summary")] string ViewerSummary, + [property: JsonPropertyName("views")] Views Views, + [property: JsonPropertyName("allowlisted_config_urls")] IReadOnlyList AllowlistedConfigUrls, + [property: JsonPropertyName("allowlisted_panel_urls")] IReadOnlyList AllowlistedPanelUrls + ); + + public record IconUrls( + [property: JsonPropertyName("100x100")] string Url100x100, + [property: JsonPropertyName("24x24")] string Url24x24, + [property: JsonPropertyName("300x200")] string Url300x200 + ); + + public record Mobile( + [property: JsonPropertyName("viewer_url")] string ViewerUrl + ); + + public record Panel( + [property: JsonPropertyName("viewer_url")] string ViewerUrl, + [property: JsonPropertyName("height")] int Height, + [property: JsonPropertyName("can_link_external_content")] bool CanLinkExternalContent + ); + + public record VideoOverlay( + [property: JsonPropertyName("viewer_url")] string ViewerUrl, + [property: JsonPropertyName("can_link_external_content")] bool CanLinkExternalContent + ); + + public record Views( + [property: JsonPropertyName("mobile")] Mobile Mobile, + [property: JsonPropertyName("panel")] Panel Panel, + [property: JsonPropertyName("video_overlay")] VideoOverlay VideoOverlay, + [property: JsonPropertyName("component")] Component Component + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/FollowedChannels.cs b/MiniTwitch.Helix/Responses/FollowedChannels.cs new file mode 100644 index 0000000..efaf382 --- /dev/null +++ b/MiniTwitch.Helix/Responses/FollowedChannels.cs @@ -0,0 +1,17 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class FollowedChannels : PaginableResponse +{ + [JsonPropertyName("total")] + public int Total { get; init; } + + public record Channel( + [property: JsonPropertyName("broadcaster_id")] long ChannelId, + [property: JsonPropertyName("broadcaster_login")] string ChannelName, + [property: JsonPropertyName("broadcaster_name")] string ChannelDisplayName, + [property: JsonPropertyName("followed_at")] DateTime FollowedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/FollowedStreams.cs b/MiniTwitch.Helix/Responses/FollowedStreams.cs new file mode 100644 index 0000000..dddfd0d --- /dev/null +++ b/MiniTwitch.Helix/Responses/FollowedStreams.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class FollowedStreams : PaginableResponse +{ + public record Stream( + [property: JsonPropertyName("broadcaster_language")] string BroadcasterLanguage, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("display_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("game_id")] string GameId, + [property: JsonPropertyName("game_name")] string GameName, + [property: JsonPropertyName("id")] long BroadcasterId, + [property: JsonPropertyName("is_live")] bool IsLive, + [property: JsonPropertyName("tags")] IReadOnlyList Tags, + [property: JsonPropertyName("thumbnail_url")] string ThumbnailUrl, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("started_at")] DateTime? StartedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/GameAnalytics.cs b/MiniTwitch.Helix/Responses/GameAnalytics.cs new file mode 100644 index 0000000..4074fb5 --- /dev/null +++ b/MiniTwitch.Helix/Responses/GameAnalytics.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class GameAnalytics : PaginableResponse +{ + public record Analytics( + [property: JsonPropertyName("game_id")] string ExtensionId, + [property: JsonPropertyName("URL")] string Url, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("date_range")] DateRange DateRange + ); + public record DateRange( + [property: JsonPropertyName("started_at")] DateTime StartedAt, + [property: JsonPropertyName("ended_at")] DateTime EndedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Games.cs b/MiniTwitch.Helix/Responses/Games.cs new file mode 100644 index 0000000..415977e --- /dev/null +++ b/MiniTwitch.Helix/Responses/Games.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Games : PaginableResponse +{ + public record Game( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name, + [property: JsonPropertyName("box_art_url")] string BoxArtUrl, + [property: JsonPropertyName("igdb_id")] string IgdbId + ); +} + +public class Game : SingleResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/GuestStarInvites.cs b/MiniTwitch.Helix/Responses/GuestStarInvites.cs new file mode 100644 index 0000000..605c023 --- /dev/null +++ b/MiniTwitch.Helix/Responses/GuestStarInvites.cs @@ -0,0 +1,18 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class GuestStarInvites : BaseResponse +{ + public record Invite( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("invited_at")] DateTime InvitedAt, + [property: JsonPropertyName("status")] string Status, + [property: JsonPropertyName("is_audio_enabled")] bool IsAudioEnabled, + [property: JsonPropertyName("is_video_enabled")] bool IsVideoEnabled, + [property: JsonPropertyName("is_audio_available")] bool IsAudioAvailable, + [property: JsonPropertyName("is_video_available")] bool IsVideoAvailable + ); + +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/GuestStarSession.cs b/MiniTwitch.Helix/Responses/GuestStarSession.cs new file mode 100644 index 0000000..7e90b90 --- /dev/null +++ b/MiniTwitch.Helix/Responses/GuestStarSession.cs @@ -0,0 +1,36 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class GuestStarSession : SingleResponse +{ + public record AudioSettings( + [property: JsonPropertyName("is_available")] bool IsAvailable, + [property: JsonPropertyName("is_host_enabled")] bool IsHostEnabled, + [property: JsonPropertyName("is_guest_enabled")] bool IsGuestEnabled + ); + + public record Info( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("guests")] IReadOnlyList Guests + ); + + public record Guest( + [property: JsonPropertyName("slot_id")] string SlotId, + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_display_name")] string DisplayName, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("is_live")] bool IsLive, + [property: JsonPropertyName("volume")] int Volume, + [property: JsonPropertyName("assigned_at")] DateTime AssignedAt, + [property: JsonPropertyName("audio_settings")] AudioSettings AudioSettings, + [property: JsonPropertyName("video_settings")] VideoSettings VideoSettings + ); + + public record VideoSettings( + [property: JsonPropertyName("is_available")] bool IsAvailable, + [property: JsonPropertyName("is_host_enabled")] bool IsHostEnabled, + [property: JsonPropertyName("is_guest_enabled")] bool IsGuestEnabled + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/HypeTrainEvents.cs b/MiniTwitch.Helix/Responses/HypeTrainEvents.cs new file mode 100644 index 0000000..417bf7d --- /dev/null +++ b/MiniTwitch.Helix/Responses/HypeTrainEvents.cs @@ -0,0 +1,35 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class HypeTrainEvents : PaginableResponse +{ + public record Event( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("event_type")] string EventType, + [property: JsonPropertyName("event_timestamp")] DateTime EventTimestamp, + [property: JsonPropertyName("version")] string Version, + [property: JsonPropertyName("event_data")] EventData EventData + ); + + public record EventData( + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("cooldown_end_time")] string CooldownEndTime, + [property: JsonPropertyName("expires_at")] DateTime ExpiresAt, + [property: JsonPropertyName("goal")] int Goal, + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("last_contribution")] Contribution LastContribution, + [property: JsonPropertyName("level")] int Level, + [property: JsonPropertyName("started_at")] string StartedAt, + [property: JsonPropertyName("top_contributions")] IReadOnlyList TopContributions, + [property: JsonPropertyName("total")] int Total + ); + + public record Contribution( + [property: JsonPropertyName("total")] int Total, + [property: JsonPropertyName("type")] string Type, + [property: JsonPropertyName("user")] long UserId + ); + +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Moderators.cs b/MiniTwitch.Helix/Responses/Moderators.cs new file mode 100644 index 0000000..25964ad --- /dev/null +++ b/MiniTwitch.Helix/Responses/Moderators.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Moderators : PaginableResponse +{ + public record Moderator( + [property: JsonPropertyName("user_id")] long ModeratorId, + [property: JsonPropertyName("user_login")] string ModeratorName, + [property: JsonPropertyName("user_name")] string ModeratorDisplayName + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Poll.cs b/MiniTwitch.Helix/Responses/Poll.cs new file mode 100644 index 0000000..210d7f3 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Poll.cs @@ -0,0 +1,29 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Poll : SingleResponse +{ + public record Choice( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("votes")] int Votes, + [property: JsonPropertyName("channel_points_votes")] int ChannelPointsVotes + ); + + public record Info( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("choices")] IReadOnlyList Choices, + [property: JsonPropertyName("channel_points_voting_enabled")] bool ChannelPointsVotingEnabled, + [property: JsonPropertyName("channel_points_per_vote")] int ChannelPointsPerVote, + [property: JsonPropertyName("status")] string Status, + [property: JsonPropertyName("duration")] int Duration, + [property: JsonPropertyName("started_at")] DateTime StartedAt, + [property: JsonPropertyName("ended_at")] DateTime? EndedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Polls.cs b/MiniTwitch.Helix/Responses/Polls.cs new file mode 100644 index 0000000..f417836 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Polls.cs @@ -0,0 +1,7 @@ +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Polls : PaginableResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Prediction.cs b/MiniTwitch.Helix/Responses/Prediction.cs new file mode 100644 index 0000000..e74fb20 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Prediction.cs @@ -0,0 +1,31 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Prediction : SingleResponse +{ + public record Info( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("winning_outcome_id")] string? WinningOutcomeId, + [property: JsonPropertyName("outcomes")] IReadOnlyList Outcomes, + [property: JsonPropertyName("prediction_window")] int PredictionWindow, + [property: JsonPropertyName("status")] string Status, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("ended_at")] DateTime? EndedAt, + [property: JsonPropertyName("locked_at")] DateTime? LockedAt + ); + + public record Outcome( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("users")] int Users, + [property: JsonPropertyName("channel_points")] int ChannelPoints, + [property: JsonPropertyName("top_predictors")] object TopPredictors, + [property: JsonPropertyName("color")] string Color + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Predictions.cs b/MiniTwitch.Helix/Responses/Predictions.cs new file mode 100644 index 0000000..1e8ad9d --- /dev/null +++ b/MiniTwitch.Helix/Responses/Predictions.cs @@ -0,0 +1,7 @@ +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Predictions : PaginableResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/Raid.cs b/MiniTwitch.Helix/Responses/Raid.cs new file mode 100644 index 0000000..0500fa6 --- /dev/null +++ b/MiniTwitch.Helix/Responses/Raid.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class Raid : SingleResponse +{ + public record Info( + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("is_mature")] bool IsMature + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ReleasedExtensions.cs b/MiniTwitch.Helix/Responses/ReleasedExtensions.cs new file mode 100644 index 0000000..d18951b --- /dev/null +++ b/MiniTwitch.Helix/Responses/ReleasedExtensions.cs @@ -0,0 +1,7 @@ +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ReleasedExtensions : BaseResponse +{ +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ScheduleSegment.cs b/MiniTwitch.Helix/Responses/ScheduleSegment.cs new file mode 100644 index 0000000..f773272 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ScheduleSegment.cs @@ -0,0 +1,37 @@ +using System.Text.Json.Serialization; + +namespace MiniTwitch.Helix.Responses; + +public class ScheduleSegment +{ + [property: JsonPropertyName("data")] + public ScheduleData Data { get; init; } + + public record Category( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("name")] string Name + ); + + public record ScheduleData( + [property: JsonPropertyName("segments")] IReadOnlyList Segments, + [property: JsonPropertyName("broadcaster_id")] long BroadcasterId, + [property: JsonPropertyName("broadcaster_name")] string BroadcasterDisplayName, + [property: JsonPropertyName("broadcaster_login")] string BroadcasterName, + [property: JsonPropertyName("vacation")] Vacation Vacation + ); + + public record Segment( + [property: JsonPropertyName("id")] string Id, + [property: JsonPropertyName("start_time")] DateTime StartTime, + [property: JsonPropertyName("end_time")] DateTime EndTime, + [property: JsonPropertyName("title")] string Title, + [property: JsonPropertyName("canceled_until")] DateTime? CanceledUntil, + [property: JsonPropertyName("category")] Category Category, + [property: JsonPropertyName("is_recurring")] bool IsRecurring + ); + + public record Vacation( + [property: JsonPropertyName("start_time")] DateTime StartTime, + [property: JsonPropertyName("end_time")] DateTime EndTime + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/ShieldModeStatus.cs b/MiniTwitch.Helix/Responses/ShieldModeStatus.cs new file mode 100644 index 0000000..4fa9325 --- /dev/null +++ b/MiniTwitch.Helix/Responses/ShieldModeStatus.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class ShieldModeStatus : SingleResponse +{ + public record Status( + [property: JsonPropertyName("is_active")] bool IsActive, + [property: JsonPropertyName("moderator_id")] long ModeratorId, + [property: JsonPropertyName("moderator_name")] string ModeratorDisplayName, + [property: JsonPropertyName("moderator_login")] string ModeratorName, + [property: JsonPropertyName("last_activated_at")] DateTime LastActivatedAt + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/SnoozedAd.cs b/MiniTwitch.Helix/Responses/SnoozedAd.cs new file mode 100644 index 0000000..243a2cf --- /dev/null +++ b/MiniTwitch.Helix/Responses/SnoozedAd.cs @@ -0,0 +1,13 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class SnoozedAd : SingleResponse +{ + public record Info( + [property: JsonPropertyName("snooze_count")] int SnoozeCount, + [property: JsonPropertyName("snooze_refresh_at")] DateTime SnoozeRefreshAt, + [property: JsonPropertyName("next_ad_at")] DateTime NextAdAt + ); +} diff --git a/MiniTwitch.Helix/Responses/StreamKey.cs b/MiniTwitch.Helix/Responses/StreamKey.cs new file mode 100644 index 0000000..5ac68e5 --- /dev/null +++ b/MiniTwitch.Helix/Responses/StreamKey.cs @@ -0,0 +1,11 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class StreamKey : SingleResponse +{ + public record Info( + [property: JsonPropertyName("stream_key")] string StreamKey + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/StreamMarker.cs b/MiniTwitch.Helix/Responses/StreamMarker.cs new file mode 100644 index 0000000..9578c15 --- /dev/null +++ b/MiniTwitch.Helix/Responses/StreamMarker.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class StreamMarker : SingleResponse +{ + public record Marker( + [property: JsonPropertyName("id")] int Id, + [property: JsonPropertyName("created_at")] DateTime CreatedAt, + [property: JsonPropertyName("description")] string Description, + [property: JsonPropertyName("position_seconds")] int PositionSeconds + ); +} \ No newline at end of file diff --git a/MiniTwitch.Helix/Responses/StreamMarkers.cs b/MiniTwitch.Helix/Responses/StreamMarkers.cs new file mode 100644 index 0000000..bd9dd2e --- /dev/null +++ b/MiniTwitch.Helix/Responses/StreamMarkers.cs @@ -0,0 +1,27 @@ +using System.Text.Json.Serialization; +using MiniTwitch.Helix.Models; + +namespace MiniTwitch.Helix.Responses; + +public class StreamMarkers : PaginableResponse +{ + public record Info( + [property: JsonPropertyName("user_id")] long UserId, + [property: JsonPropertyName("user_name")] string UserDisplayName, + [property: JsonPropertyName("user_login")] string Username, + [property: JsonPropertyName("videos")] IReadOnlyList