├── .gitattributes ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── LICENSE ├── NTwitch.sln ├── README.md ├── deploy.sh ├── examples ├── Pubsub │ ├── Advanced │ │ ├── Advanced.csproj │ │ └── Program.cs │ └── Basic │ │ ├── Basic.csproj │ │ └── Program.cs └── Rest │ ├── Advanced │ ├── Advanced.csproj │ └── Program.cs │ ├── Basic │ ├── Basic.csproj │ └── Program.cs │ └── README.md ├── src ├── NTwitch.Chat │ ├── API │ │ ├── DefaultSocketProvider.cs │ │ ├── DefaultTcpSocketClient.cs │ │ ├── Models │ │ │ ├── MessageReceivedEvent.cs │ │ │ └── UserStateEvent.cs │ │ ├── Queue │ │ │ ├── ChatRequest.cs │ │ │ ├── ChatRequestBuilder.cs │ │ │ └── ChatResponse.cs │ │ └── Requests │ │ │ ├── ClearChatRequest.cs │ │ │ └── SetUserModeRequest.cs │ ├── Entities │ │ ├── Channels │ │ │ └── ChatSimpleChannel.cs │ │ ├── ChatEntity.cs │ │ ├── Messages │ │ │ └── ChatMessage.cs │ │ └── Users │ │ │ ├── ChatSelfUser.cs │ │ │ ├── ChatSimpleUser.cs │ │ │ └── ChatUser.cs │ ├── Extensions │ │ └── ChannelExtensions.cs │ ├── NTwitch.Chat.csproj │ ├── TwitchChatApiClient.cs │ ├── TwitchChatClient.Events.cs │ ├── TwitchChatClient.cs │ └── TwitchChatConfig.cs ├── NTwitch.Core │ ├── API │ │ ├── Rest │ │ │ ├── IRestClient.cs │ │ │ ├── RestClientProvider.cs │ │ │ └── RestResponse.cs │ │ └── Sockets │ │ │ ├── ISocketClient.cs │ │ │ ├── IWebSocketClient.cs │ │ │ └── SocketClientProvider.cs │ ├── AssemblyInfo.cs │ ├── Common │ │ ├── BroadcastType.cs │ │ ├── Exceptions │ │ │ ├── HttpException.cs │ │ │ ├── MissingScopeException.cs │ │ │ └── WebSocketClosedException.cs │ │ ├── Parameters │ │ │ ├── CreateVideoParams.cs │ │ │ ├── GetStreamsParams.cs │ │ │ ├── ModifyChannelParams.cs │ │ │ ├── ModifyCommunityParams.cs │ │ │ ├── ModifyVideoParams.cs │ │ │ └── TopClipsParams.cs │ │ ├── PreviewImage.cs │ │ ├── SortMode.cs │ │ ├── StreamType.cs │ │ ├── UserNotifications.cs │ │ ├── VideoSegment.cs │ │ ├── VideoThumbnail.cs │ │ └── VideoThumbnailImage.cs │ ├── ConnectionState.cs │ ├── Entities │ │ ├── Channels │ │ │ ├── IChannel.cs │ │ │ ├── ISelfChannel.cs │ │ │ └── ISimpleChannel.cs │ │ ├── Chat │ │ │ ├── IChatBadges.cs │ │ │ ├── ICheer.cs │ │ │ ├── ICheerImage.cs │ │ │ ├── ICheerInfo.cs │ │ │ ├── ICheerScale.cs │ │ │ └── IEmote.cs │ │ ├── Communities │ │ │ ├── ICommunity.cs │ │ │ ├── ICommunityPermissions.cs │ │ │ ├── ISimpleCommunity.cs │ │ │ ├── ITopCommunity.cs │ │ │ └── IUserCommunity.cs │ │ ├── Follows │ │ │ ├── IChannelFollow.cs │ │ │ ├── IFollow.cs │ │ │ └── IUserFollow.cs │ │ ├── Games │ │ │ ├── IGame.cs │ │ │ └── IGameSummary.cs │ │ ├── IEntity.cs │ │ ├── IUpdateable.cs │ │ ├── Ingests │ │ │ └── IIngest.cs │ │ ├── Messages │ │ │ └── IMessage.cs │ │ ├── Streams │ │ │ ├── IFeaturedStream.cs │ │ │ └── IStream.cs │ │ ├── Subscriptions │ │ │ ├── IChannelSubscription.cs │ │ │ ├── ISubscription.cs │ │ │ └── IUserSubscription.cs │ │ ├── Teams │ │ │ ├── ISimpleTeam.cs │ │ │ └── ITeam.cs │ │ ├── Tokens │ │ │ ├── IAuthorization.cs │ │ │ └── ITokenInfo.cs │ │ ├── Users │ │ │ ├── IBannedUser.cs │ │ │ ├── IBlockedUser.cs │ │ │ ├── ISelfUser.cs │ │ │ ├── ISimpleUser.cs │ │ │ ├── IUser.cs │ │ │ └── IUserNotifications.cs │ │ └── Videos │ │ │ ├── IClip.cs │ │ │ ├── ISimpleVideo.cs │ │ │ └── IVideo.cs │ ├── ITwitchClient.cs │ ├── LoginState.cs │ ├── NTwitch.Core.csproj │ ├── PageOptions.cs │ ├── RequestOptions.cs │ ├── RetryMode.cs │ ├── TwitchConfig.cs │ └── Utility │ │ ├── Cache │ │ ├── CacheClientProvider.cs │ │ ├── DefaultCacheClient.cs │ │ ├── DefaultCacheClientProvider.cs │ │ └── ICacheClient.cs │ │ ├── DateTimeHelper.cs │ │ ├── Events │ │ ├── AsyncEvent.cs │ │ └── AsyncEventExtensions.cs │ │ ├── FileHelper.cs │ │ ├── Logs │ │ ├── LogManager.cs │ │ ├── LogMessage.cs │ │ ├── LogSeverity.cs │ │ └── Logger.cs │ │ └── Optional.cs ├── NTwitch.Pubsub │ ├── API │ │ ├── DefaultWebSocketClient.cs │ │ ├── DefaultWebSocketProvider.cs │ │ ├── Models │ │ │ ├── Emote.cs │ │ │ ├── Message.cs │ │ │ ├── Requests │ │ │ │ ├── PubsubFrame.cs │ │ │ │ ├── PubsubInData.cs │ │ │ │ └── PubsubOutData.cs │ │ │ └── Subscription.cs │ │ ├── Queue │ │ │ ├── PubsubRequest.cs │ │ │ └── PubsubRequestBuilder.cs │ │ └── Requests │ │ │ ├── ListenBitsRequest.cs │ │ │ ├── ListenSubscriptionsRequest.cs │ │ │ ├── ListenVideoPlaybackRequest.cs │ │ │ └── ListenWhispersRequest.cs │ ├── Entities │ │ ├── Channels │ │ │ └── PubsubSimpleChannel.cs │ │ ├── Emotes │ │ │ └── PubsubEmote.cs │ │ ├── PubsubEntity.cs │ │ ├── Subscriptions │ │ │ └── PubsubSubscription.cs │ │ └── Users │ │ │ └── PubsubSimpleUser.cs │ ├── NTwitch.Pubsub.csproj │ ├── TwitchPubsubApiClient.cs │ ├── TwitchPubsubClient.Events.cs │ ├── TwitchPubsubClient.cs │ └── TwitchPubsubConfig.cs ├── NTwitch.Rest │ ├── API │ │ ├── DefaultRestClient.cs │ │ ├── DefaultRestClientProvider.cs │ │ ├── Models │ │ │ ├── Badge.cs │ │ │ ├── BlockedUser.cs │ │ │ ├── Collections │ │ │ │ ├── BlockCollection.cs │ │ │ │ ├── ChannelCollection.cs │ │ │ │ ├── CheerCollection.cs │ │ │ │ ├── ClipCollection.cs │ │ │ │ ├── CommunityCollection.cs │ │ │ │ ├── FollowCollection.cs │ │ │ │ ├── GameCollection.cs │ │ │ │ ├── IngestCollection.cs │ │ │ │ ├── StreamCollection.cs │ │ │ │ ├── SubscriptionCollection.cs │ │ │ │ ├── TeamCollection.cs │ │ │ │ ├── TokenCollection.cs │ │ │ │ ├── UserCollection.cs │ │ │ │ └── VideoCollection.cs │ │ │ ├── Errors │ │ │ │ ├── Error.cs │ │ │ │ └── ErrorMessage.cs │ │ │ ├── Heartbeat.cs │ │ │ ├── Old │ │ │ │ ├── Authorization.cs │ │ │ │ ├── Channel.cs │ │ │ │ ├── ChatBadges.cs │ │ │ │ ├── ChatProperties.cs │ │ │ │ ├── Cheer.cs │ │ │ │ ├── CheerImage.cs │ │ │ │ ├── CheerInfo.cs │ │ │ │ ├── CheerScale.cs │ │ │ │ ├── Clip.cs │ │ │ │ ├── Community.cs │ │ │ │ ├── CommunityPermissions.cs │ │ │ │ ├── Emote.cs │ │ │ │ ├── EmoteSet.cs │ │ │ │ ├── FeaturedStream.cs │ │ │ │ ├── Follow.cs │ │ │ │ ├── Game.cs │ │ │ │ ├── Ingest.cs │ │ │ │ ├── Stream.cs │ │ │ │ ├── Subscription.cs │ │ │ │ ├── Team.cs │ │ │ │ └── Token.cs │ │ │ ├── User.cs │ │ │ └── Video.cs │ │ ├── Queue │ │ │ ├── JsonRestRequest.cs │ │ │ ├── JsonRestRequestBuilder.cs │ │ │ ├── RestRequest.cs │ │ │ └── RestRequestBuilder.cs │ │ └── Requests │ │ │ ├── FindChannelsRequest.cs │ │ │ ├── FindGamesRequest.cs │ │ │ ├── FindStreamsRequest.cs │ │ │ ├── GetChannelFollowersRequest.cs │ │ │ ├── GetChannelVideosRequest.cs │ │ │ ├── GetCheersRequest.cs │ │ │ ├── GetCommunityRequest.cs │ │ │ ├── GetFeaturedStreamsRequest.cs │ │ │ ├── GetFollowedClipsRequest.cs │ │ │ ├── GetFollowedStreamsRequest.cs │ │ │ ├── GetFollowedVideosRequest.cs │ │ │ ├── GetFollowsRequest.cs │ │ │ ├── GetStreamRequest.cs │ │ │ ├── GetStreamSummaryRequest.cs │ │ │ ├── GetStreamsRequest.cs │ │ │ ├── GetSubscribersRequest.cs │ │ │ ├── GetTeamsRequest.cs │ │ │ ├── GetTopClipsRequest.cs │ │ │ ├── GetTopVideosRequest.cs │ │ │ ├── GetUsersRequest.cs │ │ │ ├── ModifyChannelRequest.cs │ │ │ ├── SendCommunityReportRequest.cs │ │ │ ├── SetCommunityAvatarRequest.cs │ │ │ └── SetCommunityCoverRequest.cs │ ├── AssemblyInfo.cs │ ├── BaseTwitchClient.cs │ ├── ClientHelper.cs │ ├── Entities │ │ ├── Channels │ │ │ ├── ChannelHelper.cs │ │ │ ├── RestChannel.cs │ │ │ ├── RestSelfChannel.cs │ │ │ └── RestSimpleChannel.cs │ │ ├── Chat │ │ │ ├── RestChatBadges.cs │ │ │ ├── RestCheer.cs │ │ │ ├── RestCheerImage.cs │ │ │ ├── RestCheerInfo.cs │ │ │ ├── RestCheerScale.cs │ │ │ └── RestEmote.cs │ │ ├── Communities │ │ │ ├── CommunityHelper.cs │ │ │ ├── RestCommunity.cs │ │ │ ├── RestCommunityPermissions.cs │ │ │ ├── RestSimpleCommunity.cs │ │ │ ├── RestTopCommunity.cs │ │ │ └── RestUserCommunity.cs │ │ ├── Follows │ │ │ ├── RestChannelFollow.cs │ │ │ ├── RestFollow.cs │ │ │ └── RestUserFollow.cs │ │ ├── Games │ │ │ ├── RestGame.cs │ │ │ └── RestGameSummary.cs │ │ ├── Ingests │ │ │ └── RestIngest.cs │ │ ├── RestEntity.cs │ │ ├── Streams │ │ │ ├── RestFeaturedStream.cs │ │ │ └── RestStream.cs │ │ ├── Subscriptions │ │ │ ├── RestChannelSubscription.cs │ │ │ ├── RestSubscription.cs │ │ │ └── RestUserSubscription.cs │ │ ├── Teams │ │ │ ├── RestSimpleTeam.cs │ │ │ └── RestTeam.cs │ │ ├── Tokens │ │ │ ├── RestAuthorization.cs │ │ │ └── RestTokenInfo.cs │ │ ├── Users │ │ │ ├── RestBannedUser.cs │ │ │ ├── RestBlockedUser.cs │ │ │ ├── RestSelfUser.cs │ │ │ ├── RestSimpleUser.cs │ │ │ ├── RestUser.cs │ │ │ ├── RestUserNotifications.cs │ │ │ └── UserHelper.cs │ │ └── Videos │ │ │ ├── RestClip.cs │ │ │ ├── RestSimpleVideo.cs │ │ │ ├── RestVideo.cs │ │ │ └── VideoHelper.cs │ ├── NTwitch.Rest.csproj │ ├── TwitchRestApiClient.cs │ ├── TwitchRestClient.cs │ └── TwitchRestConfig.cs └── NTwitch │ └── NTwitch.csproj └── tests └── NTwitch.Tests ├── NTwitch.Tests.csproj └── Program.cs /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### Contributing 2 | When contributing to this repository, please first discuss the changes you wish to make with the contributors and users in the [NTwitch Discord Guild](https://discord.gg/yd8x2wM) before submitting a PR. 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### What is affected by this bug? 4 | 5 | 6 | #### When does the bug occur? 7 | 8 | 9 | #### How can this issue be replicated? 10 | 11 | 12 | #### Other Comments -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | #### Description 4 | 5 | 6 | #### Motivation and Context 7 | 8 | 9 | 10 | #### How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | #### Types of changes 16 | 17 | - [ ] Bug fix (non-breaking change which fixes an issue) 18 | - [ ] New feature (non-breaking change which adds functionality) 19 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 20 | 21 | #### Checklist: 22 | 23 | 24 | - [ ] My code follows the code style of this project. 25 | - [ ] My change requires a change to the documentation. 26 | - [ ] I have updated the documentation accordingly. -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: csharp 2 | solution: NTwitch.sln 3 | git: 4 | depth: 1 5 | matrix: 6 | include: 7 | - os: linux 8 | dist: trusty 9 | sudo: required 10 | mono: none 11 | dotnet: 1.0.0-preview2-003131 12 | env: DOTNETCORE=1 13 | 14 | script: 15 | - sudo apt-get install dotnet-dev-1.0.1 16 | - dotnet restore 17 | - dotnet build --configuration Release --version-suffix beta-$TRAVIS_BUILDNUMBER 18 | 19 | deploy: 20 | skip_cleanup: true 21 | provider: script 22 | script: 23 | - chmod +x deploy.sh 24 | - sudo deploy.sh 25 | on: 26 | branch: master -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository is now depreciated, for an updated library see https://github.com/Akitaux/Twitch 2 | 3 | # NTwitch 4 | [![NuGet](https://img.shields.io/nuget/v/NTwitch.svg)](https://www.nuget.org/packages/NTwitch) [![NuGet Pre Release](https://img.shields.io/nuget/vpre/NTwitch.svg)](https://www.nuget.org/packages/NTwitch) [![MyGet Pre Release](https://img.shields.io/myget/aux/vpre/NTwitch.svg)](https://www.myget.org/feed/Packages/aux) [![Discord](https://discordapp.com/api/guilds/257698577894080512/widget.png)](https://discord.gg/yd8x2wM) 5 | 6 | A .net core implementation of the https://twitch.tv/ version 5 api, strongly based on [Discord.Net](https://github.com/RogueException/Discord.Net). 7 | 8 | ## Builds 9 | Release and pre-release builds can be found on Nuget under [NTwitch](https://www.nuget.org/packages/NTwitch/). 10 | 11 | #### Releases 12 | Stable builds can be found on NTwitch. The contents of these packages reflect what is shown in the [master](https://github.com/Aux/NTwitch/tree/master) branch. 13 | - [NTwitch](https://www.nuget.org/packages/NTwitch/) 14 | - [NTwitch.Rest](https://www.nuget.org/packages/NTwitch.Rest/) 15 | - [NTwitch.Chat](https://www.nuget.org/packages/NTwitch.Chat/) 16 | - [NTwitch.Pubsub](https://www.nuget.org/packages/NTwitch.Pubsub/) 17 | #### Pre-Release 18 | Unstable builds of NTwitch can also be found on Nuget with the pre-release option checked. The contents of these packages reflect what is shown in the [nightly](https://github.com/Aux/NTwitch/tree/nightly) branch, and are updated from the dev branch once a week. 19 | #### Indev 20 | You can access the latest builds of NTwitch via the myget feed listed below. The contents of these packages are built automatically as new code is committed to the [dev](https://github.com/Aux/NTwitch/tree/dev) branch. 21 | - `https://www.myget.org/F/aux/api/v3/index.json` 22 | 23 | ## Documentation 24 | Currently, no documentation for NTwitch exists. If you have any questions or want status updates about the library, please join the [NTwitch Discord Guild](https://discord.gg/yd8x2wM). 25 | 26 | ## Compiling 27 | To compile NTwitch yourself, you will need either of the following: 28 | 29 | ##### Visual Studio 30 | - [Visual Studio 2017](https://www.microsoft.com/net/core#windowsvs2017) 31 | 32 | ##### Command Line Tools 33 | - [.Net Core 1.1 SDK](https://www.microsoft.com/net/download/core) 34 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!bin/sh 2 | 3 | if [ "$TRAVIS_BRANCH" = "master" ] 4 | then 5 | dotnet pack "./src/NTwitch/NTwitch.csproj" -c "Release" -o "../../pkgs" --no-build 6 | dotnet pack "./src/NTwitch.Core/NTwitch.Core.csproj" -c "Release" -o "../../pkgs" --no-build 7 | dotnet pack "./src/NTwitch.Rest/NTwitch.Rest.csproj" -c "Release" -o "../../pkgs" --no-build 8 | dotnet nuget push "./pkgs/*.nupkg" "$NUGET_API_KEY" -verbosity detailed 9 | else 10 | echo "Skipping deploy" 11 | echo "This branch is not master: "$TRAVIS_BRANCH 12 | fi 13 | -------------------------------------------------------------------------------- /examples/Pubsub/Advanced/Advanced.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/Pubsub/Advanced/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Advanced 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | Console.WriteLine("Hello World!"); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /examples/Pubsub/Basic/Basic.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/Pubsub/Basic/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // This example shows how to subscribe to whispers for the current user. 3 | // 4 | 5 | using NTwitch; 6 | using NTwitch.Pubsub; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace Basic 11 | { 12 | class Program 13 | { 14 | public static void Main(string[] args) 15 | => new Program().StartAsync().GetAwaiter().GetResult(); 16 | 17 | private TwitchPubsubClient _client; 18 | 19 | public async Task StartAsync() 20 | { 21 | _client = new TwitchPubsubClient(new TwitchPubsubConfig() 22 | { 23 | LogLevel = LogSeverity.Info 24 | }); 25 | 26 | _client.Log += OnLogAsync; 27 | _client.WhisperReceived += OnWhisperReceivedAsync; 28 | 29 | Console.Write("Please enter your oauth token: "); 30 | string token = Console.ReadLine(); 31 | 32 | await _client.LoginAsync(token); 33 | await _client.ListenWhispersAsync(_client.TokenInfo.UserId); 34 | 35 | await Task.Delay(-1); 36 | } 37 | 38 | private Task OnLogAsync(LogMessage msg) 39 | => Console.Out.WriteLineAsync(msg.ToString()); 40 | 41 | private Task OnWhisperReceivedAsync(string arg) 42 | { 43 | return Console.Out.WriteLineAsync(arg); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /examples/Rest/Advanced/Advanced.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/Rest/Advanced/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // This examples shows how to get a user's channel from an oauth token and edit their status. 3 | // 4 | 5 | using NTwitch; 6 | using NTwitch.Rest; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace Advanced 11 | { 12 | class Program 13 | { 14 | public static void Main(string[] args) 15 | => new Program().StartAsync().GetAwaiter().GetResult(); 16 | 17 | private TwitchRestClient _client; 18 | 19 | public async Task StartAsync() 20 | { 21 | _client = new TwitchRestClient(new TwitchRestConfig() 22 | { 23 | LogLevel = LogSeverity.Info 24 | }); 25 | 26 | _client.Log += OnLogAsync; 27 | 28 | Console.Write("Please enter your oauth token: "); 29 | string token = Console.ReadLine(); 30 | 31 | await _client.LoginAsync(token); 32 | var channel = await _client.GetChannelAsync(_client.TokenInfo.UserId); 33 | 34 | string previous = channel.Status; 35 | while (true) 36 | { 37 | Console.WriteLine(); 38 | Console.Write("Please enter a new value for the stream title: "); 39 | string title = Console.ReadLine(); 40 | 41 | await channel.ModifyAsync(x => 42 | { 43 | x.Status = title; 44 | }); 45 | 46 | Console.WriteLine($"I changed {channel.DisplayName}'s status from `{previous}` to `{channel.Status}`"); 47 | previous = channel.Status; 48 | } 49 | } 50 | 51 | private Task OnLogAsync(LogMessage msg) 52 | => Console.Out.WriteLineAsync(msg.ToString()); 53 | } 54 | } -------------------------------------------------------------------------------- /examples/Rest/Basic/Basic.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp1.1 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /examples/Rest/Basic/Program.cs: -------------------------------------------------------------------------------- 1 | // 2 | // This example shows how to check if a stream is online or offline. 3 | // 4 | 5 | using NTwitch; 6 | using NTwitch.Rest; 7 | using System; 8 | using System.Linq; 9 | using System.Threading.Tasks; 10 | 11 | namespace Basic 12 | { 13 | class Program 14 | { 15 | public static void Main(string[] args) 16 | => new Program().StartAsync().GetAwaiter().GetResult(); 17 | 18 | private TwitchRestClient _client; 19 | 20 | public async Task StartAsync() 21 | { 22 | Console.Write("Please enter your client id: "); 23 | string clientid = Console.ReadLine(); 24 | 25 | _client = new TwitchRestClient(new TwitchRestConfig() 26 | { 27 | ClientId = clientid, 28 | LogLevel = LogSeverity.Info 29 | }); 30 | 31 | _client.Log += OnLogAsync; 32 | 33 | while (true) 34 | { 35 | Console.WriteLine(); 36 | Console.Write("Enter the name of a stream: "); 37 | string name = Console.ReadLine(); 38 | 39 | var user = (await _client.GetUsersAsync(name)).FirstOrDefault(); 40 | if (user == null) 41 | { 42 | Console.WriteLine($"The user `{name}` does not exist!"); 43 | continue; 44 | } 45 | 46 | var stream = await _client.GetStreamAsync(user.Id); 47 | if (stream == null) 48 | Console.WriteLine($"{user.DisplayName} is not currently streaming."); 49 | else 50 | Console.WriteLine($"{user.DisplayName} is streaming {stream.Game} at {stream.Channel.Url}!"); 51 | } 52 | } 53 | 54 | private Task OnLogAsync(LogMessage msg) 55 | => Console.Out.WriteLineAsync(msg.ToString()); 56 | } 57 | } -------------------------------------------------------------------------------- /examples/Rest/README.md: -------------------------------------------------------------------------------- 1 | ### Rest 2 | 3 | This is where some basic information about the rest package and links to documentation and other examples will be provided :) -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/DefaultSocketProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch.Chat 4 | { 5 | public static class DefaultSocketProvider 6 | { 7 | public static readonly SocketClientProvider Instance = () => 8 | { 9 | try 10 | { 11 | return new DefaultTcpSocketClient(); 12 | } 13 | catch (PlatformNotSupportedException ex) 14 | { 15 | throw new PlatformNotSupportedException("The default SocketClientProvider is not supported on this platform.", ex); 16 | } 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Models/MessageReceivedEvent.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Chat.Queue; 2 | using System; 3 | using System.Linq; 4 | 5 | namespace NTwitch.Chat.API 6 | { 7 | internal class MessageReceivedEvent 8 | { 9 | // Prefix 10 | public string UserName { get; set; } 11 | 12 | // Tags 13 | // Message 14 | public string Id { get; set; } 15 | public DateTime SentTimestamp { get; set; } 16 | public DateTime TmiSentTimestamp { get; set; } 17 | public string Badges { get; set; } // Parse this 18 | public string Emotes { get; set; } // Parse this 19 | 20 | // Channel 21 | public ulong ChannelId { get; set; } 22 | 23 | // User 24 | public ulong UserId { get; set; } 25 | public string Color { get; set; } 26 | public string DisplayName { get; set; } 27 | public string UserType { get; set; } 28 | public bool IsMod { get; set; } 29 | public bool IsSubscriber { get; set; } 30 | public bool IsTurbo { get; set; } 31 | 32 | // Parameters 33 | public string ChannelName { get; set; } // First 34 | public string Content { get; set; } // Last 35 | 36 | internal static MessageReceivedEvent Create(ChatResponse msg) 37 | { 38 | var entity = new MessageReceivedEvent(); 39 | entity.Update(msg); 40 | return entity; 41 | } 42 | 43 | internal void Update(ChatResponse msg) 44 | { 45 | int nameEndIndex = msg.Prefix.IndexOf('!'); 46 | UserName = msg.Prefix.Substring(0, nameEndIndex); 47 | 48 | Id = msg.Tags["id"]; 49 | 50 | if (msg.Tags.TryGetValue("sent-ts", out string sentTs)) 51 | SentTimestamp = DateTimeHelper.GetDateTime(sentTs); 52 | 53 | TmiSentTimestamp = DateTimeHelper.GetDateTime(msg.Tags["tmi-sent-ts"]); 54 | Badges = msg.Tags["badges"]; 55 | Emotes = msg.Tags["emotes"]; 56 | 57 | ChannelId = ulong.Parse(msg.Tags["room-id"]); 58 | 59 | UserId = ulong.Parse(msg.Tags["user-id"]); 60 | Color = msg.Tags["color"]; 61 | DisplayName = msg.Tags["display-name"]; 62 | UserType = msg.Tags["user-type"]; 63 | IsMod = msg.Tags["mod"] == "1"; 64 | IsSubscriber = msg.Tags["subscriber"] == "1"; 65 | IsTurbo = msg.Tags["turbo"] == "1"; 66 | 67 | ChannelName = msg.Parameters.First().Substring(1); 68 | Content = msg.Parameters.Last().Trim(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Models/UserStateEvent.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Chat.Queue; 2 | using System.Linq; 3 | 4 | namespace NTwitch.Chat.API 5 | { 6 | internal class UserStateEvent 7 | { 8 | // Tags 9 | public string Badges { get; set; } 10 | public string Color { get; set; } 11 | public string DisplayName { get; set; } 12 | public string EmoteSets { get; set; } // Probably goes in selfuser 13 | public bool IsMod { get; set; } 14 | public bool IsSubscriber { get; set; } 15 | public string UserType { get; set; } 16 | 17 | // Parameters 18 | public string ChannelName { get; set; } // First 19 | 20 | internal static UserStateEvent Create(ChatResponse msg) 21 | { 22 | var entity = new UserStateEvent(); 23 | entity.Update(msg); 24 | return entity; 25 | } 26 | 27 | internal void Update(ChatResponse msg) 28 | { 29 | Badges = msg.Tags["badges"]; 30 | Color = msg.Tags["color"]; 31 | DisplayName = msg.Tags["display-name"]; 32 | EmoteSets = msg.Tags["emote-sets"]; 33 | IsMod = msg.Tags["mod"] == "1"; 34 | IsSubscriber = msg.Tags["subscriber"] == "1"; 35 | UserType = msg.Tags["user-type"]; 36 | 37 | ChannelName = msg.Parameters.First().Substring(1).Trim(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Queue/ChatRequest.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NTwitch.Chat.Queue 4 | { 5 | public class ChatRequest 6 | { 7 | public ISocketClient Client { get; } 8 | public string Message { get; } 9 | public RequestOptions Options { get; } 10 | 11 | public ChatRequest(ISocketClient client, string message, RequestOptions options) 12 | { 13 | Client = client; 14 | Message = message; 15 | Options = options; 16 | } 17 | 18 | public virtual async Task SendAsync() 19 | { 20 | await Client.SendAsync(Message).ConfigureAwait(false); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Queue/ChatRequestBuilder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch.Chat.Queue 4 | { 5 | public class ChatRequestBuilder 6 | { 7 | public string Command => _defaultCommand; 8 | public string Parameters => _defaultParameters; 9 | public string Message => ToString(); 10 | 11 | public Dictionary Tags { get; protected set; } 12 | 13 | internal string _defaultCommand; 14 | internal string _defaultParameters; 15 | 16 | public ChatRequestBuilder(string command, string parameters) 17 | { 18 | _defaultCommand = command; 19 | _defaultParameters = parameters; 20 | Tags = new Dictionary(); 21 | } 22 | 23 | public string GetTagString() 24 | { 25 | if (Tags.Count == 0) 26 | return ""; 27 | 28 | List paramList = new List(); 29 | foreach (var p in Tags) 30 | if (p.Value != null) paramList.Add($"{p.Key}={p.Value}"); 31 | return $"@{string.Join(";", paramList.ToArray())} "; 32 | } 33 | 34 | public override string ToString() 35 | => GetTagString() + _defaultCommand + _defaultParameters; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Requests/ClearChatRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Chat.Queue; 2 | 3 | namespace NTwitch.Chat.API 4 | { 5 | public class ClearChatRequest : ChatRequestBuilder 6 | { 7 | public ClearChatRequest(string channelName, string userName, string reason = null, uint? duration = null) 8 | : base("CLEARCHAT", $"#{channelName} :{userName}") 9 | { 10 | if (reason != null) 11 | Tags.Add("ban-reason", reason); 12 | if (duration != null) 13 | Tags.Add("ban-duration", duration); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/API/Requests/SetUserModeRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Chat.Queue; 2 | 3 | namespace NTwitch.Chat.API 4 | { 5 | public class SetUserModeRequest : ChatRequestBuilder 6 | { 7 | public SetUserModeRequest(string channelName, string userName, bool isOp) 8 | : base("MODE", null) 9 | { 10 | string status = isOp ? "+o" : "-o"; 11 | _defaultCommand = $"#{channelName} {status} {userName}"; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/Entities/ChatEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch.Chat 4 | { 5 | public class ChatEntity : IEntity 6 | { 7 | /// An instance of the client that created this entity 8 | public TwitchChatClient Client { get; } 9 | /// The unique identifier for this entity 10 | public T Id { get; } 11 | 12 | public ChatEntity(TwitchChatClient client, T id) 13 | { 14 | Client = client; 15 | Id = id; 16 | } 17 | 18 | ITwitchClient IEntity.Client 19 | => throw new NotImplementedException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/Entities/Messages/ChatMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Model = NTwitch.Chat.API.MessageReceivedEvent; 3 | 4 | namespace NTwitch.Chat 5 | { 6 | public class ChatMessage : ChatEntity, IMessage 7 | { 8 | /// 9 | public DateTime CreatedAt { get; private set; } 10 | /// 11 | public DateTime TmiCreatedAt { get; private set; } 12 | /// 13 | public string Badges { get; private set; } 14 | /// 15 | public string Emotes { get; private set; } 16 | /// 17 | public string Content { get; private set; } 18 | /// 19 | public ChatSimpleChannel Channel { get; private set; } 20 | /// 21 | public ChatUser User { get; private set; } 22 | 23 | internal ChatMessage(TwitchChatClient client, string id) 24 | : base(client, id) { } 25 | 26 | public bool Equals(IMessage other) 27 | => Id == other.Id; 28 | 29 | internal static ChatMessage Create(TwitchChatClient client, Model model) 30 | { 31 | var entity = new ChatMessage(client, model.Id); 32 | entity.Update(model); 33 | return entity; 34 | } 35 | 36 | internal virtual void Update(Model model) 37 | { 38 | CreatedAt = model.SentTimestamp; 39 | TmiCreatedAt = model.TmiSentTimestamp; 40 | Badges = model.Badges; 41 | Emotes = model.Emotes; 42 | Content = model.Content; 43 | 44 | Channel = ChatSimpleChannel.Create(Client, model); 45 | User = ChatUser.Create(Client, model); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/Entities/Users/ChatSelfUser.cs: -------------------------------------------------------------------------------- 1 | using UserStateModel = NTwitch.Chat.API.UserStateEvent; 2 | 3 | namespace NTwitch.Chat 4 | { 5 | public class ChatSelfUser : ChatUser, ISelfUser 6 | { 7 | /// 8 | public string EmoteSets { get; private set; } 9 | 10 | public ChatSelfUser(TwitchChatClient client, ulong id) 11 | : base(client, id) { } 12 | 13 | internal new static ChatUser Create(TwitchChatClient client, UserStateModel model) 14 | { 15 | var entity = new ChatUser(client, client.TokenInfo.UserId); 16 | entity.Update(model); 17 | return entity; 18 | } 19 | 20 | internal override void Update(UserStateModel model) 21 | { 22 | base.Update(model); 23 | EmoteSets = model.EmoteSets; 24 | } 25 | 26 | // ISelfUser 27 | string ISelfUser.Email => null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/Entities/Users/ChatUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using MsgEventModel = NTwitch.Chat.API.MessageReceivedEvent; 4 | using UserStateModel = NTwitch.Chat.API.UserStateEvent; 5 | 6 | namespace NTwitch.Chat 7 | { 8 | public class ChatUser : ChatSimpleUser, IUser 9 | { 10 | /// 11 | public string Color { get; private set; } 12 | /// 13 | public string UserType { get; private set; } 14 | /// 15 | public bool IsMod { get; private set; } 16 | /// 17 | public bool IsSubscriber { get; private set; } 18 | /// 19 | public bool IsTurbo { get; private set; } 20 | 21 | internal ChatUser(TwitchChatClient client, ulong id) 22 | : base(client, id) { } 23 | 24 | internal new static ChatUser Create(TwitchChatClient client, MsgEventModel model) 25 | { 26 | var entity = new ChatUser(client, model.UserId); 27 | entity.Update(model); 28 | return entity; 29 | } 30 | 31 | internal new static ChatUser Create(TwitchChatClient client, UserStateModel model) 32 | { 33 | var entity = new ChatUser(client, client.TokenInfo.UserId); 34 | entity.Update(model); 35 | return entity; 36 | } 37 | 38 | internal override void Update(MsgEventModel model) 39 | { 40 | base.Update(model); 41 | Color = model.Color; 42 | UserType = model.UserType; 43 | IsMod = model.IsMod; 44 | IsSubscriber = model.IsSubscriber; 45 | IsTurbo = model.IsTurbo; 46 | } 47 | 48 | internal override void Update(UserStateModel model) 49 | { 50 | base.Update(model); 51 | Color = model.Color; 52 | UserType = model.UserType; 53 | IsMod = model.IsMod; 54 | IsSubscriber = model.IsSubscriber; 55 | IsTurbo = false; // Turbo is found in badges for this model 56 | } 57 | 58 | /// 59 | public Task UpdateAsync() 60 | { 61 | throw new NotImplementedException(); 62 | } 63 | 64 | // IUser 65 | string ISimpleUser.AvatarUrl => null; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/Extensions/ChannelExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch.Chat 5 | { 6 | public static class ChannelExtensions 7 | { 8 | // Channels 9 | public static async Task JoinAsync(this ISimpleChannel channel, RequestOptions options = null) 10 | { 11 | var client = channel.Client as TwitchChatClient; 12 | if (client == null) 13 | return; 14 | 15 | await client.ApiClient.JoinChannelAsync(channel.Name, options).ConfigureAwait(false); 16 | } 17 | 18 | public static async Task LeaveAsync(this ISimpleChannel channel, RequestOptions options = null) 19 | { 20 | var client = channel.Client as TwitchChatClient; 21 | if (client == null) 22 | return; 23 | 24 | await client.ApiClient.LeaveChannelAsync(channel.Name, options).ConfigureAwait(false); 25 | } 26 | 27 | // Messages 28 | public static async Task SendMessageAsync(this ISimpleChannel channel, string content, RequestOptions options = null) 29 | { 30 | var client = channel.Client as TwitchChatClient; 31 | if (client == null) 32 | return; 33 | 34 | await client.ApiClient.SendChannelMessageAsync(channel.Name, content, options).ConfigureAwait(false); 35 | } 36 | 37 | public static IReadOnlyCollection GetMessages(this ISimpleChannel channel, int count = -1, RequestOptions options = null) 38 | { 39 | var client = channel.Client as TwitchChatClient; 40 | if (client == null) 41 | return null; 42 | 43 | return client.ApiClient.GetMessages(channel.Id, count); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/NTwitch.Chat.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4 5 | An async compatible implementation of Twitch's version 5 api. 6 | 0.1.0.0 7 | 0.1.0.0 8 | 0.1.0.0 9 | Auxesis,Aux 10 | twitch,tv,dot,net,core,rest,api,lib,library,socket,websocket,chat,irc,tcp 11 | https://github.com/Aux/NTwitch/blob/master/LICENSE 12 | https://github.com/Aux/NTwitch 13 | http://i.imgur.com/kcL6nG0.png 14 | https://github.com/Aux/NTwitch 15 | git 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/TwitchChatClient.Events.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch.Chat 5 | { 6 | public partial class TwitchChatClient 7 | { 8 | //General 9 | public event Func Connected { add { _connectedEvent.Add(value); } remove { _connectedEvent.Remove(value); } } 10 | private readonly AsyncEvent> _connectedEvent = new AsyncEvent>(); 11 | 12 | public event Func Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } } 13 | private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>(); 14 | 15 | public event Func LatencyUpdated { add { _latencyUpdatedEvent.Add(value); } remove { _latencyUpdatedEvent.Remove(value); } } 16 | private readonly AsyncEvent> _latencyUpdatedEvent = new AsyncEvent>(); 17 | 18 | // Channels 19 | public event Func MessageReceived { add { _messageReceivedEvent.Add(value); } remove { _messageReceivedEvent.Remove(value); } } 20 | private readonly AsyncEvent> _messageReceivedEvent = new AsyncEvent>(); 21 | 22 | public event Func JoinedChannel { add { _joinedChannelEvent.Add(value); } remove { _joinedChannelEvent.Remove(value); } } 23 | private readonly AsyncEvent> _joinedChannelEvent = new AsyncEvent>(); 24 | 25 | public event Func LeftChannel { add { _leftChannelEvent.Add(value); } remove { _leftChannelEvent.Remove(value); } } 26 | private readonly AsyncEvent> _leftChannelEvent = new AsyncEvent>(); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/NTwitch.Chat/TwitchChatConfig.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Rest; 2 | 3 | namespace NTwitch.Chat 4 | { 5 | public class TwitchChatConfig : TwitchRestConfig 6 | { 7 | /// Gets or sets the provider used to generate new chat connections. 8 | public SocketClientProvider SocketClientProvider { get; set; } = DefaultSocketProvider.Instance; 9 | /// The host to connect to when making chat requests 10 | public string SocketHost { get; set; } = "irc.chat.twitch.tv"; 11 | 12 | ///// Allow the authenticated user to speak in channels without the moderator permission. 13 | //public bool CanSpeakWithoutMod { get; set; } = false; 14 | 15 | /// Include message tags to several commands 16 | public bool RequestTags { get; } = true; 17 | /// Enables several Twitch-specific commands 18 | public bool RequestCommands { get; } = true; 19 | /// Include membership state event data 20 | public bool RequestMembership { get; } = true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Rest/IRestClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch.Rest 5 | { 6 | public interface IRestClient 7 | { 8 | void SetHeader(string key, string value); 9 | void SetCancelToken(CancellationToken cancelToken); 10 | 11 | Task SendAsync(string method, string endpoint, CancellationToken cancelToken, bool headerOnly = false); 12 | Task SendAsync(string method, string endpoint, string json, CancellationToken cancelToken, bool headerOnly = false); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Rest/RestClientProvider.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch.Rest 2 | { 3 | public delegate IRestClient RestClientProvider(string baseUrl); 4 | } 5 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Rest/RestResponse.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | using System.Net; 4 | 5 | namespace NTwitch.Rest 6 | { 7 | public class RestResponse 8 | { 9 | public HttpStatusCode StatusCode { get; } 10 | public Dictionary Headers { get; } 11 | public Stream Body { get; } 12 | 13 | public RestResponse(HttpStatusCode code, Dictionary headers, Stream body) 14 | { 15 | StatusCode = code; 16 | Headers = headers; 17 | Body = body; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Sockets/ISocketClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace NTwitch 6 | { 7 | public interface ISocketClient 8 | { 9 | event Func TextMessage; 10 | event Func Closed; 11 | 12 | void SetCancelToken(CancellationToken cancelToken); 13 | 14 | Task ConnectAsync(string host); 15 | Task DisconnectAsync(bool disposing = false); 16 | 17 | Task SendAsync(string message); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Sockets/IWebSocketClient.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NTwitch.Pubsub 4 | { 5 | public interface IWebSocketClient : ISocketClient 6 | { 7 | Task SendAsync(byte[] data, int index, int count, bool isText); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/NTwitch.Core/API/Sockets/SocketClientProvider.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public delegate ISocketClient SocketClientProvider(); 4 | } 5 | -------------------------------------------------------------------------------- /src/NTwitch.Core/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("NTwitch.Rest")] 4 | [assembly: InternalsVisibleTo("NTwitch.Pubsub")] 5 | [assembly: InternalsVisibleTo("NTwitch.Chat")] -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/BroadcastType.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum BroadcastType 4 | { 5 | All, 6 | Archive, 7 | Highlight, 8 | Upload 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Exceptions/HttpException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace NTwitch 5 | { 6 | public class HttpException : Exception 7 | { 8 | public HttpStatusCode StatusCode { get; } 9 | public string Reason { get; } 10 | 11 | public HttpException(HttpStatusCode code, string reason = null) 12 | : base($"{code} {reason}") 13 | { 14 | StatusCode = code; 15 | Reason = reason; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Exceptions/MissingScopeException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public class MissingScopeException : ArgumentException 6 | { 7 | public MissingScopeException(params string[] scopes) 8 | : base($"Missing required scopes: {string.Join(", ", scopes)}") { } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Exceptions/WebSocketClosedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public class WebSocketClosedException : Exception 6 | { 7 | public int CloseCode { get; } 8 | public string Reason { get; } 9 | 10 | public WebSocketClosedException(int closeCode, string reason = null) 11 | : base($"The server sent close {closeCode}{(reason != null ? $": \"{reason}\"" : "")}") 12 | { 13 | CloseCode = closeCode; 14 | Reason = reason; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/CreateVideoParams.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace NTwitch 5 | { 6 | public class CreateVideoParams 7 | { 8 | [JsonProperty("description", DefaultValueHandling = DefaultValueHandling.Ignore)] 9 | public string Description { get; set; } 10 | [JsonProperty("game", DefaultValueHandling = DefaultValueHandling.Ignore)] 11 | public string Game { get; set; } 12 | [JsonProperty("language", DefaultValueHandling = DefaultValueHandling.Ignore)] 13 | public string Language { get; set; } 14 | [JsonProperty("tag_list", DefaultValueHandling = DefaultValueHandling.Ignore)] 15 | public string Tags { get; set; } 16 | [JsonProperty("viewable", DefaultValueHandling = DefaultValueHandling.Ignore)] 17 | public string Viewable { get; set; } 18 | [JsonProperty("viewable_at", DefaultValueHandling = DefaultValueHandling.Ignore)] 19 | public DateTime ViewableAt { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/GetStreamsParams.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public class GetStreamsParams 4 | { 5 | public ulong[] ChannelIds { get; set; } = null; 6 | public string Game { get; set; } = null; 7 | public string Language { get; set; } = null; 8 | public StreamType Type { get; set; } = StreamType.Live; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/ModifyChannelParams.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class ModifyChannelParams 6 | { 7 | [JsonProperty("status", DefaultValueHandling = DefaultValueHandling.Ignore)] 8 | public string Status { get; set; } = null; 9 | [JsonProperty("game", DefaultValueHandling = DefaultValueHandling.Ignore)] 10 | public string Game { get; set; } = null; 11 | [JsonProperty("delay", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Delay { get; set; } = null; 13 | [JsonProperty("channel_feed_enabled", DefaultValueHandling = DefaultValueHandling.Ignore)] 14 | public bool? IsFeedEnabled { get; set; } = null; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/ModifyCommunityParams.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class ModifyCommunityParams 6 | { 7 | [JsonProperty("summary", DefaultValueHandling = DefaultValueHandling.Ignore)] 8 | public string Summary { get; set; } 9 | [JsonProperty("description", DefaultValueHandling = DefaultValueHandling.Ignore)] 10 | public string Description { get; set; } 11 | [JsonProperty("rules", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Rules { get; set; } 13 | [JsonProperty("email", DefaultValueHandling = DefaultValueHandling.Ignore)] 14 | public string Email { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/ModifyVideoParams.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class ModifyVideoParams 6 | { 7 | [JsonProperty("title", DefaultValueHandling = DefaultValueHandling.Ignore)] 8 | public string Title { get; set; } 9 | [JsonProperty("description", DefaultValueHandling = DefaultValueHandling.Ignore)] 10 | public string Description { get; set; } 11 | [JsonProperty("game", DefaultValueHandling = DefaultValueHandling.Ignore)] 12 | public string Game { get; set; } 13 | [JsonProperty("language", DefaultValueHandling = DefaultValueHandling.Ignore)] 14 | public string Language { get; set; } 15 | [JsonProperty("tag_list", DefaultValueHandling = DefaultValueHandling.Ignore)] 16 | public string Tags { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/Parameters/TopClipsParams.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public class TopClipsParams 6 | { 7 | public HashSet Channels { get; set; } 8 | public HashSet Games { get; set; } 9 | public uint Limit { get; set; } = 10; 10 | public string Period { get; set; } = "week"; 11 | public bool IsTrending { get; set; } = false; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/PreviewImage.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | internal class PreviewImage 6 | { 7 | [JsonProperty("small")] 8 | public string Small { get; internal set; } 9 | [JsonProperty("medium")] 10 | public string Medium { get; internal set; } 11 | [JsonProperty("large")] 12 | public string Large { get; internal set; } 13 | [JsonProperty("template")] 14 | public string Template { get; internal set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/SortMode.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum SortMode 4 | { 5 | CreatedAt, 6 | LastBroadcast, 7 | Username 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/StreamType.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum StreamType 4 | { 5 | All, 6 | Live, 7 | Playlist 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/UserNotifications.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class UserNotifications 6 | { 7 | [JsonProperty("push")] 8 | public bool IsPushEnabled { get; internal set; } 9 | [JsonProperty("email")] 10 | public bool IsEmailEnabled { get; internal set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/VideoSegment.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class VideoSegment 6 | { 7 | [JsonProperty("duration")] 8 | public uint Duration { get; internal set; } 9 | [JsonProperty("offset")] 10 | public uint Offset { get; internal set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/VideoThumbnail.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch 5 | { 6 | public class VideoThumbnail 7 | { 8 | [JsonProperty("small")] 9 | public IEnumerable Small { get; internal set; } 10 | [JsonProperty("medium")] 11 | public IEnumerable Medium { get; internal set; } 12 | [JsonProperty("large")] 13 | public IEnumerable Large { get; internal set; } 14 | [JsonProperty("template")] 15 | public IEnumerable Template { get; internal set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Common/VideoThumbnailImage.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch 4 | { 5 | public class VideoThumbnailImage 6 | { 7 | [JsonProperty("type")] 8 | public string Type { get; internal set; } 9 | [JsonProperty("url")] 10 | public string Url { get; internal set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/ConnectionState.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum ConnectionState : byte 4 | { 5 | Disconnected, 6 | Connecting, 7 | Connected, 8 | Disconnecting 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Channels/IChannel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public interface IChannel : IEntity, IUpdateable 6 | { 7 | DateTime CreatedAt { get; } 8 | DateTime UpdatedAt { get; } 9 | string Status { get; } 10 | string BroadcasterLanguage { get; } 11 | string Game { get; } 12 | string Language { get; } 13 | string LogoUrl { get; } 14 | string VideoBannerUrl { get; } 15 | string ProfileBannerUrl { get; } 16 | string ProfileBannerBackgroundColor { get; } 17 | string Url { get; } 18 | bool IsMature { get; } 19 | bool IsPartner { get; } 20 | uint Views { get; } 21 | uint Followers { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Channels/ISelfChannel.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ISelfChannel : IChannel, IUpdateable 4 | { 5 | string Email { get; } 6 | string StreamKey { get; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Channels/ISimpleChannel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace NTwitch 6 | { 7 | public interface ISimpleChannel : IEntity, IEquatable 8 | { 9 | string Name { get; } 10 | string DisplayName { get; } 11 | 12 | // Channels 13 | Task ModifyAsync(Action changes, RequestOptions options = null); 14 | 15 | // Chat 16 | Task> GetCheersAsync(RequestOptions options = null); 17 | Task GetChatBadgesAsync(RequestOptions options = null); 18 | 19 | // Streams 20 | Task GetStreamAsync(StreamType type = StreamType.Live, RequestOptions options = null); 21 | 22 | // Teams 23 | Task> GetTeamsAsync(RequestOptions options = null); 24 | 25 | // Users 26 | Task GetUserAsync(RequestOptions options = null); 27 | Task GetSelfUserAsync(RequestOptions options = null); 28 | Task> GetEditorsAsync(RequestOptions options = null); 29 | Task GetSubscriberAsync(ulong userId, RequestOptions options = null); 30 | Task> GetFollowersAsync(bool ascending = false, uint limit = 25, uint offset = 0, RequestOptions options = null); 31 | Task> GetSubscribersAsync(bool ascending = false, uint limit = 25, uint offset = 0, RequestOptions options = null); 32 | 33 | // Videos 34 | Task> GetVideosAsync(uint limit = 25, uint offset = 0, RequestOptions options = null); 35 | Task> GetClipsAsync(bool istrending = false, uint limit = 10, RequestOptions options = null); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/IChatBadges.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IChatBadges 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/ICheer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public interface ICheer : IEntity, IEqualityComparer 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/ICheerImage.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ICheerImage 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/ICheerInfo.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ICheerInfo 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/ICheerScale.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ICheerScale 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Chat/IEmote.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public interface IEmote : IEntity, IEqualityComparer 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Communities/ICommunity.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ICommunity : ISimpleCommunity, IUpdateable 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Communities/ICommunityPermissions.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ICommunityPermissions 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Communities/ISimpleCommunity.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public interface ISimpleCommunity : IEntity, IEqualityComparer 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Communities/ITopCommunity.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ITopCommunity : ISimpleCommunity 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Communities/IUserCommunity.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IUserCommunity : ICommunity 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Follows/IChannelFollow.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IChannelFollow : IFollow 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Follows/IFollow.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IFollow 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Follows/IUserFollow.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IUserFollow : IFollow 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Games/IGame.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IGame 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Games/IGameSummary.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IGameSummary 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/IEntity.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IEntity 4 | { 5 | ITwitchClient Client { get; } 6 | T Id { get; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/IUpdateable.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NTwitch 4 | { 5 | public interface IUpdateable 6 | { 7 | Task UpdateAsync(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Ingests/IIngest.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IIngest 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Messages/IMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace NTwitch 6 | { 7 | public interface IMessage : IEntity, IEquatable 8 | { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Streams/IFeaturedStream.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IFeaturedStream 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Streams/IStream.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IStream 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Subscriptions/IChannelSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IChannelSubscription : ISubscription 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Subscriptions/ISubscription.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ISubscription 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Subscriptions/IUserSubscription.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IUserSubscription : ISubscription 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Teams/ISimpleTeam.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ISimpleTeam 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Teams/ITeam.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ITeam : ISimpleTeam 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Tokens/IAuthorization.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch 5 | { 6 | public interface IAuthorization 7 | { 8 | IReadOnlyCollection Scopes { get; } 9 | DateTime CreatedAt { get; } 10 | DateTime UpdatedAt { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Tokens/ITokenInfo.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface ITokenInfo 4 | { 5 | bool IsValid { get; } 6 | string Token { get; } 7 | string Username { get; } 8 | string ClientId { get; } 9 | ulong UserId { get; } 10 | IAuthorization Authorization { get; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/IBannedUser.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IBannedUser : ISimpleUser 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/IBlockedUser.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IBlockedUser : ISimpleUser 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/ISelfUser.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace NTwitch 4 | { 5 | public interface ISelfUser : IUser, IUpdateable 6 | { 7 | string Email { get; } 8 | //IUserNotifications Notifications { get; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/ISimpleUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public interface ISimpleUser : IEntity, IEquatable 6 | { 7 | string AvatarUrl { get; } 8 | string Name { get; } 9 | string DisplayName { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/IUser.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch 5 | { 6 | public interface IUser : ISimpleUser, IUpdateable 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Users/IUserNotifications.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IUserNotifications 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Videos/IClip.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public interface IClip : IEntity, IUpdateable, IEqualityComparer 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Videos/ISimpleVideo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace NTwitch 4 | { 5 | public interface ISimpleVideo : IEntity, IEqualityComparer 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Entities/Videos/IVideo.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public interface IVideo : ISimpleVideo, IUpdateable 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /src/NTwitch.Core/ITwitchClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace NTwitch 6 | { 7 | public interface ITwitchClient : IDisposable 8 | { 9 | ITokenInfo TokenInfo { get; } 10 | ConnectionState ConnectionState { get; } 11 | 12 | Task ConnectAsync(); 13 | Task DisconnectAsync(); 14 | 15 | // Tokens 16 | Task GetTokenInfo(RequestOptions options = null); 17 | 18 | // Clips 19 | Task GetClipAsync(string clipId); 20 | Task> GetTopClipsAsync(Action options); 21 | 22 | // Communities 23 | Task GetCommunityAsync(string communityId, bool isname = false); 24 | Task> GetTopCommunitiesAsync(uint limit = 10); 25 | 26 | // Channels 27 | Task GetCurrentChannelAsync(); 28 | Task GetChannelAsync(ulong channelId); 29 | Task> FindChannelAsync(string query, uint limit = 25, uint offset = 0); 30 | 31 | // Ingests 32 | Task> GetIngestsAsync(); 33 | 34 | // Streams 35 | Task GetStreamAsync(ulong channelId, StreamType type = StreamType.Live); 36 | Task> GetStreamsAsync(params ulong[] channelIds); 37 | Task> GetStreamsAsync(Action options); 38 | Task GetGameSummaryAsync(string game); 39 | Task> GetFeaturedStreamsAsync(uint limit = 25, uint offset = 0); 40 | Task> FindGamesAsync(string query, bool islive = false); 41 | Task> FindStreamsAsync(string query, bool? hls = null, uint limit = 25, uint offset = 0); 42 | 43 | // Teams 44 | Task> GetTeamsAsync(uint limit = 25, uint offset = 0); 45 | Task GetTeamAsync(string name); 46 | 47 | // Users 48 | Task GetCurrentUserAsync(); 49 | Task GetUserAsync(ulong userId); 50 | Task> GetUsersAsync(params string[] usernames); 51 | 52 | // Videos 53 | Task GetVideoAsync(string videoId); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/NTwitch.Core/LoginState.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum LoginState : byte 4 | { 5 | LoggedOut, 6 | LoggingIn, 7 | LoggedIn, 8 | LoggingOut 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Core/NTwitch.Core.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4 5 | NTwitch's shared source package. 6 | 0.1.0.0 7 | 0.1.0.0 8 | 0.1.0.0 9 | Auxesis,Aux 10 | twitch,tv,dot,net,core,rest,api,lib,library,socket,websocket,chat,irc,tcp 11 | https://github.com/Aux/NTwitch/blob/master/LICENSE 12 | https://github.com/Aux/NTwitch 13 | http://i.imgur.com/kcL6nG0.png 14 | https://github.com/Aux/NTwitch 15 | git 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/NTwitch.Core/PageOptions.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public class PageOptions 4 | { 5 | public static PageOptions Default => new PageOptions(); 6 | 7 | public uint Limit { get; set; } = 20; 8 | public uint Offset { get; set; } = 0; 9 | 10 | internal static PageOptions CreateOrClone(PageOptions options) 11 | { 12 | if (options == null) 13 | return new PageOptions(); 14 | else 15 | return options.Clone(); 16 | } 17 | 18 | public PageOptions Clone() => MemberwiseClone() as PageOptions; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/NTwitch.Core/RequestOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Threading; 2 | 3 | namespace NTwitch 4 | { 5 | public class RequestOptions 6 | { 7 | public static RequestOptions Default => new RequestOptions(); 8 | 9 | public int? Timeout { get; set; } 10 | public CancellationToken CancelToken { get; set; } = CancellationToken.None; 11 | public RetryMode? RetryMode { get; set; } 12 | public bool HeaderOnly { get; internal set; } 13 | 14 | internal bool IgnoreState { get; set; } 15 | 16 | internal static RequestOptions CreateOrClone(RequestOptions options) 17 | { 18 | if (options == null) 19 | return new RequestOptions(); 20 | else 21 | return options.Clone(); 22 | } 23 | 24 | public RequestOptions Clone() => MemberwiseClone() as RequestOptions; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NTwitch.Core/RetryMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | /// Specifies how a request should act in the case of an error. 6 | [Flags] 7 | public enum RetryMode 8 | { 9 | /// If a request fails, an exception is thrown immediately. 10 | AlwaysFail = 0x0, 11 | /// Retry if a request timed out. 12 | RetryTimeouts = 0x1, 13 | // /// Retry if a request failed due to a network error. 14 | //RetryErrors = 0x2, 15 | /// Retry if a request failed due to a ratelimit. 16 | RetryRatelimit = 0x4, 17 | /// Retry if a request failed due to an HTTP error 502. 18 | Retry502 = 0x8, 19 | /// Continuously retry a request until it times out, its cancel token is triggered, or the server responds with a non-502 error. 20 | AlwaysRetry = RetryTimeouts | /*RetryErrors |*/ RetryRatelimit | Retry502, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/NTwitch.Core/TwitchConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace NTwitch 4 | { 5 | public class TwitchConfig 6 | { 7 | public static string Version { get; } = 8 | typeof(TwitchConfig).GetTypeInfo().Assembly.GetCustomAttribute()?.InformationalVersion ?? 9 | typeof(TwitchConfig).GetTypeInfo().Assembly.GetName().Version.ToString(3) ?? 10 | "Unknown"; 11 | 12 | public static string UserAgent { get; } = $"NTwitchApp (https://github.com/Aux/NTwitch, v{Version})"; 13 | public static readonly string DefaultApiUrl = "https://api.twitch.tv/kraken/"; 14 | public static readonly string DefaultChatUrl = "irc.chat.twitch.tv"; 15 | public static readonly string EmoteCdnUrl = "static-cdn.jtvnw.net"; 16 | 17 | public const int APIVersion = 5; 18 | public const int DefaultRequestTimeout = 15000; 19 | 20 | /// Gets or sets the provider used to cache entities. 21 | public CacheClientProvider CacheClientProvider { get; set; } = DefaultCacheClientProvider.Instance; 22 | /// Gets or sets the minimum log level severity that will be sent to the Log event. 23 | public LogSeverity LogLevel { get; set; } = LogSeverity.Info; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Cache/CacheClientProvider.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public delegate ICacheClient CacheClientProvider(int msgCacheSize); 4 | } 5 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Cache/DefaultCacheClientProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public static class DefaultCacheClientProvider 6 | { 7 | public static readonly CacheClientProvider Instance = (int msgCacheSize) => 8 | { 9 | try 10 | { 11 | return new DefaultCacheClient(msgCacheSize); 12 | } 13 | catch (PlatformNotSupportedException ex) 14 | { 15 | throw new PlatformNotSupportedException("The default CacheProvider is not supported on this platform.", ex); 16 | } 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Cache/ICacheClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch 5 | { 6 | public interface ICacheClient 7 | { 8 | IReadOnlyCollection Users { get; } 9 | IReadOnlyCollection Channels { get; } 10 | IReadOnlyCollection Messages { get; } 11 | 12 | void AddUser(IUser user); 13 | void AddChannel(IChannel channel); 14 | void AddMessage(IMessage message); 15 | 16 | IUser RemoveUser(ulong userId); 17 | IChannel RemoveChannel(ulong channelId); 18 | IMessage RemoveMessage(string messageId); 19 | 20 | IUser GetUser(ulong userId); 21 | IChannel GetChannel(ulong channelId); 22 | IMessage GetMessage(string messageId); 23 | 24 | IUser GetOrAddUser(ulong userId, Func userFactory); 25 | IChannel GetOrAddChannel(ulong channelId, Func channelFactory); 26 | IMessage GetOrAddMessage(string messageId, Func messageFactory); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/DateTimeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | internal static class DateTimeHelper 6 | { 7 | public static DateTime GetDateTime(string value) 8 | => GetDateTime(long.Parse(value)); 9 | 10 | public static DateTime GetDateTime(long value) 11 | { 12 | var reference = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); 13 | var actual = reference.AddMilliseconds(value).ToLocalTime(); 14 | return actual; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Events/AsyncEvent.cs: -------------------------------------------------------------------------------- 1 | // Unabashedly copied from https://github.com/RogueException/Discord.Net async event impl 2 | 3 | using System.Collections.Generic; 4 | using System.Collections.Immutable; 5 | 6 | namespace NTwitch 7 | { 8 | public class AsyncEvent where T : class 9 | { 10 | private readonly object _subLock = new object(); 11 | internal ImmutableArray _subscriptions; 12 | 13 | public IReadOnlyList Subscriptions => _subscriptions; 14 | 15 | public AsyncEvent() 16 | { 17 | _subscriptions = ImmutableArray.Create(); 18 | } 19 | 20 | public void Add(T subscriber) 21 | { 22 | lock (_subLock) 23 | _subscriptions = _subscriptions.Add(subscriber); 24 | } 25 | public void Remove(T subscriber) 26 | { 27 | lock (_subLock) 28 | _subscriptions = _subscriptions.Remove(subscriber); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Events/AsyncEventExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch 5 | { 6 | public static class AsyncEventExtensions 7 | { 8 | public static async Task InvokeAsync(this AsyncEvent> eventHandler) 9 | { 10 | var subscribers = eventHandler.Subscriptions; 11 | if (subscribers.Count > 0) 12 | { 13 | for (int i = 0; i < subscribers.Count; i++) 14 | await subscribers[i].Invoke().ConfigureAwait(false); 15 | } 16 | } 17 | public static async Task InvokeAsync(this AsyncEvent> eventHandler, T arg) 18 | { 19 | var subscribers = eventHandler.Subscriptions; 20 | for (int i = 0; i < subscribers.Count; i++) 21 | await subscribers[i].Invoke(arg).ConfigureAwait(false); 22 | } 23 | public static async Task InvokeAsync(this AsyncEvent> eventHandler, T1 arg1, T2 arg2) 24 | { 25 | var subscribers = eventHandler.Subscriptions; 26 | for (int i = 0; i < subscribers.Count; i++) 27 | await subscribers[i].Invoke(arg1, arg2).ConfigureAwait(false); 28 | } 29 | public static async Task InvokeAsync(this AsyncEvent> eventHandler, T1 arg1, T2 arg2, T3 arg3) 30 | { 31 | var subscribers = eventHandler.Subscriptions; 32 | for (int i = 0; i < subscribers.Count; i++) 33 | await subscribers[i].Invoke(arg1, arg2, arg3).ConfigureAwait(false); 34 | } 35 | public static async Task InvokeAsync(this AsyncEvent> eventHandler, T1 arg1, T2 arg2, T3 arg3, T4 arg4) 36 | { 37 | var subscribers = eventHandler.Subscriptions; 38 | for (int i = 0; i < subscribers.Count; i++) 39 | await subscribers[i].Invoke(arg1, arg2, arg3, arg4).ConfigureAwait(false); 40 | } 41 | public static async Task InvokeAsync(this AsyncEvent> eventHandler, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) 42 | { 43 | var subscribers = eventHandler.Subscriptions; 44 | for (int i = 0; i < subscribers.Count; i++) 45 | await subscribers[i].Invoke(arg1, arg2, arg3, arg4, arg5).ConfigureAwait(false); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/FileHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace NTwitch 5 | { 6 | internal static class FileHelper 7 | { 8 | public static string GetBase64String(Stream stream) 9 | { 10 | byte[] bytes; 11 | byte[] buffer = new byte[16 * 1024]; 12 | using (var memory = new MemoryStream()) 13 | { 14 | int read; 15 | while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) 16 | memory.Write(buffer, 0, read); 17 | bytes = memory.ToArray(); 18 | } 19 | 20 | return Convert.ToBase64String(bytes); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Logs/LogManager.cs: -------------------------------------------------------------------------------- 1 | // Unabashedly copied from https://github.com/RogueException/Discord.Net log manager impl 2 | 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | namespace NTwitch 7 | { 8 | internal class LogManager 9 | { 10 | public LogSeverity Level { get; } 11 | private Logger ClientLogger { get; } 12 | 13 | public event Func Message { add { _messageEvent.Add(value); } remove { _messageEvent.Remove(value); } } 14 | private readonly AsyncEvent> _messageEvent = new AsyncEvent>(); 15 | 16 | public LogManager(LogSeverity minSeverity) 17 | { 18 | Level = minSeverity; 19 | ClientLogger = new Logger(this, "Discord"); 20 | } 21 | 22 | public async Task LogAsync(LogSeverity severity, string source, Exception ex) 23 | { 24 | try 25 | { 26 | if (severity <= Level) 27 | await _messageEvent.InvokeAsync(new LogMessage(severity, source, null, ex)).ConfigureAwait(false); 28 | } 29 | catch { } 30 | } 31 | 32 | public async Task LogAsync(LogSeverity severity, string source, string message, Exception ex = null) 33 | { 34 | try 35 | { 36 | if (severity <= Level) 37 | await _messageEvent.InvokeAsync(new LogMessage(severity, source, message, ex)).ConfigureAwait(false); 38 | } 39 | catch { } 40 | } 41 | 42 | public Task ErrorAsync(string source, Exception ex) 43 | => LogAsync(LogSeverity.Error, source, ex); 44 | public Task ErrorAsync(string source, string message, Exception ex = null) 45 | => LogAsync(LogSeverity.Error, source, message, ex); 46 | 47 | public Task WarningAsync(string source, Exception ex) 48 | => LogAsync(LogSeverity.Warning, source, ex); 49 | public Task WarningAsync(string source, string message, Exception ex = null) 50 | => LogAsync(LogSeverity.Warning, source, message, ex); 51 | 52 | public Task InfoAsync(string source, Exception ex) 53 | => LogAsync(LogSeverity.Info, source, ex); 54 | public Task InfoAsync(string source, string message, Exception ex = null) 55 | => LogAsync(LogSeverity.Info, source, message, ex); 56 | 57 | public Task VerboseAsync(string source, Exception ex) 58 | => LogAsync(LogSeverity.Verbose, source, ex); 59 | public Task VerboseAsync(string source, string message, Exception ex = null) 60 | => LogAsync(LogSeverity.Verbose, source, message, ex); 61 | 62 | public Task DebugAsync(string source, Exception ex) 63 | => LogAsync(LogSeverity.Debug, source, ex); 64 | public Task DebugAsync(string source, string message, Exception ex = null) 65 | => LogAsync(LogSeverity.Debug, source, message, ex); 66 | 67 | public Logger CreateLogger(string name) => new Logger(this, name); 68 | 69 | public async Task WriteInitialLog() 70 | { 71 | await ClientLogger.InfoAsync($"NTwitch v{TwitchConfig.Version} (API v{TwitchConfig.APIVersion})").ConfigureAwait(false); 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Logs/LogMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public struct LogMessage 6 | { 7 | public LogSeverity Level { get; } 8 | public string Source { get; } 9 | public string Message { get; } 10 | public Exception Exception { get; } 11 | 12 | public LogMessage(LogSeverity level, string source, string message, Exception ex = null) 13 | { 14 | Level = level; 15 | Source = source; 16 | Message = message; 17 | Exception = ex; 18 | } 19 | 20 | public override string ToString() 21 | => $"[{Level}] {Source}: {(Exception?.ToString() ?? Message)}"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Logs/LogSeverity.cs: -------------------------------------------------------------------------------- 1 | namespace NTwitch 2 | { 3 | public enum LogSeverity 4 | { 5 | Critical = 0, 6 | Error = 1, 7 | Warning = 2, 8 | Info = 3, 9 | Verbose = 4, 10 | Debug = 5 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Logs/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch 5 | { 6 | internal class Logger 7 | { 8 | private readonly LogManager _manager; 9 | 10 | public string Name { get; } 11 | public LogSeverity Level => _manager.Level; 12 | 13 | public Logger(LogManager manager, string name) 14 | { 15 | _manager = manager; 16 | Name = name; 17 | } 18 | 19 | public Task LogAsync(LogSeverity severity, Exception exception = null) 20 | => _manager.LogAsync(severity, Name, exception); 21 | public Task LogAsync(LogSeverity severity, string message, Exception exception = null) 22 | => _manager.LogAsync(severity, Name, message, exception); 23 | 24 | public Task ErrorAsync(Exception exception) 25 | => _manager.ErrorAsync(Name, exception); 26 | public Task ErrorAsync(string message, Exception exception = null) 27 | => _manager.ErrorAsync(Name, message, exception); 28 | 29 | public Task WarningAsync(Exception exception) 30 | => _manager.WarningAsync(Name, exception); 31 | public Task WarningAsync(string message, Exception exception = null) 32 | => _manager.WarningAsync(Name, message, exception); 33 | 34 | public Task InfoAsync(Exception exception) 35 | => _manager.InfoAsync(Name, exception); 36 | public Task InfoAsync(string message, Exception exception = null) 37 | => _manager.InfoAsync(Name, message, exception); 38 | 39 | public Task VerboseAsync(Exception exception) 40 | => _manager.VerboseAsync(Name, exception); 41 | public Task VerboseAsync(string message, Exception exception = null) 42 | => _manager.VerboseAsync(Name, message, exception); 43 | 44 | public Task DebugAsync(Exception exception) 45 | => _manager.DebugAsync(Name, exception); 46 | public Task DebugAsync(string message, Exception exception = null) 47 | => _manager.DebugAsync(Name, message, exception); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/NTwitch.Core/Utility/Optional.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch 4 | { 5 | public struct Optional 6 | { 7 | public static Optional Unspecified => default(Optional); 8 | private readonly T _value; 9 | 10 | /// Gets the value for this paramter. 11 | public T Value 12 | { 13 | get 14 | { 15 | if (!IsSpecified) 16 | throw new InvalidOperationException("This property has no value set."); 17 | return _value; 18 | } 19 | } 20 | /// Returns true if this value has been specified. 21 | public bool IsSpecified { get; } 22 | 23 | /// Creates a new Parameter with the provided value. 24 | public Optional(T value) 25 | { 26 | _value = value; 27 | IsSpecified = true; 28 | } 29 | 30 | public T GetValueOrDefault() => _value; 31 | public T GetValueOrDefault(T defaultValue) => IsSpecified ? _value : defaultValue; 32 | 33 | public override bool Equals(object other) 34 | { 35 | if (!IsSpecified) return other == null; 36 | if (other == null) return false; 37 | return _value.Equals(other); 38 | } 39 | public override int GetHashCode() => IsSpecified ? _value.GetHashCode() : 0; 40 | 41 | public override string ToString() => IsSpecified ? _value?.ToString() : null; 42 | private string DebuggerDisplay => IsSpecified ? (_value?.ToString() ?? "") : ""; 43 | 44 | public static implicit operator Optional(T value) => new Optional(value); 45 | public static explicit operator T(Optional value) => value.Value; 46 | } 47 | 48 | public static class Optional 49 | { 50 | public static Optional Create() => Optional.Unspecified; 51 | public static Optional Create(T value) => new Optional(value); 52 | 53 | public static T? ToNullable(this Optional val) 54 | where T : struct 55 | => val.IsSpecified ? val.Value : (T?)null; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/DefaultWebSocketProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch.Pubsub 4 | { 5 | public static class DefaultWebSocketProvider 6 | { 7 | public static readonly SocketClientProvider Instance = () => 8 | { 9 | try 10 | { 11 | return new DefaultWebSocketClient(); 12 | } 13 | catch (PlatformNotSupportedException ex) 14 | { 15 | throw new PlatformNotSupportedException("The default WebSocketProvider is not supported on this platform.", ex); 16 | } 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Emote.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | internal class Emote 6 | { 7 | [JsonProperty("id")] 8 | public ulong Id { get; set; } 9 | [JsonProperty("start")] 10 | public int StartIndex { get; set; } 11 | [JsonProperty("end")] 12 | public int EndIndex { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Message.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Pubsub.API 5 | { 6 | internal class Message 7 | { 8 | 9 | 10 | 11 | // Subscription 12 | [JsonProperty("message")] 13 | public string Content { get; set; } 14 | [JsonProperty("emotes")] 15 | public IEnumerable Emotes { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Requests/PubsubFrame.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | internal class PubsubFrame 6 | { 7 | [JsonProperty("type")] 8 | public string Type { get; set; } 9 | [JsonProperty("nonce", NullValueHandling = NullValueHandling.Ignore)] 10 | public string Nonce { get; set; } 11 | [JsonProperty("error", NullValueHandling = NullValueHandling.Ignore)] 12 | public string Error { get; set; } 13 | [JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)] 14 | public T Data { get; set; } 15 | 16 | public TMessage GetData() 17 | => JsonConvert.DeserializeObject(Data.ToString()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Requests/PubsubInData.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | internal class PubsubInData 6 | { 7 | [JsonProperty("topic")] 8 | public string Topic { get; set; } 9 | [JsonProperty("message")] 10 | public string Message { get; set; } 11 | 12 | public T GetMessage() 13 | => JsonConvert.DeserializeObject(Message); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Requests/PubsubOutData.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Pubsub.API 5 | { 6 | internal class PubsubOutData 7 | { 8 | [JsonProperty("topics")] 9 | public List Topics { get; set; } 10 | [JsonProperty("auth_token")] 11 | public string AuthToken { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Models/Subscription.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace NTwitch.Pubsub.API 5 | { 6 | internal class Subscription 7 | { 8 | [JsonProperty("user_name")] 9 | public string Username { get; set; } 10 | [JsonProperty("display_name")] 11 | public string DisplayName { get; set; } 12 | [JsonProperty("channel_name")] 13 | public string ChannelName { get; set; } 14 | [JsonProperty("user_id")] 15 | public ulong UserId { get; set; } 16 | [JsonProperty("channel_id")] 17 | public ulong ChannelId { get; set; } 18 | [JsonProperty("time")] 19 | public DateTime Timestamp { get; set; } 20 | [JsonProperty("sub_plan")] 21 | public string SubPlan { get; set; } 22 | [JsonProperty("sub_plan_name")] 23 | public string SubPlanName { get; set; } 24 | [JsonProperty("months")] 25 | public int Months { get; set; } 26 | [JsonProperty("context")] 27 | public string Context { get; set; } 28 | [JsonProperty("sub_message")] 29 | public Message Message { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Queue/PubsubRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.API; 2 | using System.Threading; 3 | using System.Threading.Tasks; 4 | 5 | namespace NTwitch.Pubsub.Queue 6 | { 7 | public class PubsubRequest 8 | { 9 | public IWebSocketClient Client { get; } 10 | public byte[] Data { get; } 11 | public bool IsText { get; } 12 | public RequestOptions Options { get; } 13 | public CancellationToken CancelToken { get; internal set; } 14 | 15 | public PubsubRequest(IWebSocketClient client, string bucketId, byte[] data, bool isText, RequestOptions options) 16 | { 17 | Client = client; 18 | Data = data; 19 | IsText = isText; 20 | Options = options; 21 | } 22 | 23 | public async Task SendAsync() 24 | { 25 | await Client.SendAsync(Data, 0, Data.Length, IsText).ConfigureAwait(false); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Queue/PubsubRequestBuilder.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.API; 2 | using System; 3 | using System.Collections.Generic; 4 | 5 | namespace NTwitch.Pubsub.Queue 6 | { 7 | public class PubsubRequestBuilder 8 | { 9 | public string Type => _defaultType; 10 | public List Topics { get; } 11 | 12 | private readonly string _nonce; 13 | private readonly string _authToken; 14 | private string _defaultType; 15 | 16 | public PubsubRequestBuilder(string type, string authToken = null) 17 | { 18 | Topics = new List(); 19 | _nonce = Guid.NewGuid().ToString(); 20 | _authToken = authToken; 21 | _defaultType = type; 22 | } 23 | 24 | public object GetPayload(bool includeNonce = false) 25 | { 26 | var payload = new PubsubFrame 27 | { 28 | Type = _defaultType, 29 | Data = new PubsubOutData 30 | { 31 | Topics = Topics 32 | } 33 | }; 34 | 35 | if (_authToken != null) 36 | payload.Data.AuthToken = _authToken; 37 | if (includeNonce) 38 | payload.Nonce = _nonce; 39 | return payload; 40 | } 41 | 42 | public string GetNonce() 43 | => _nonce; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Requests/ListenBitsRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.Queue; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | public class ListenBitsRequest : PubsubRequestBuilder 6 | { 7 | public ListenBitsRequest(ulong[] channelIds, string authtoken) 8 | : base("LISTEN", authtoken) 9 | { 10 | foreach (var channelId in channelIds) 11 | Topics.Add($"channel-bits-events-v1.{channelId}"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Requests/ListenSubscriptionsRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.Queue; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | public class ListenSubscriptionsRequest : PubsubRequestBuilder 6 | { 7 | public ListenSubscriptionsRequest(ulong[] channelIds, string authtoken) 8 | : base("LISTEN", authtoken) 9 | { 10 | foreach (var channelId in channelIds) 11 | Topics.Add($"channel-subscribe-events-v1.{channelId}"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Requests/ListenVideoPlaybackRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.Queue; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | public class ListenVideoPlaybackRequest : PubsubRequestBuilder 6 | { 7 | public ListenVideoPlaybackRequest(ulong[] channelIds, string authToken = null) 8 | : base("LISTEN", authToken) 9 | { 10 | foreach (var channelId in channelIds) 11 | Topics.Add($"video-playback.{channelId}"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/API/Requests/ListenWhispersRequest.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Pubsub.Queue; 2 | 3 | namespace NTwitch.Pubsub.API 4 | { 5 | public class ListenWhispersRequest : PubsubRequestBuilder 6 | { 7 | public ListenWhispersRequest(ulong[] userIds, string authtoken) 8 | : base("LISTEN", authtoken) 9 | { 10 | foreach (var userId in userIds) 11 | Topics.Add($"whispers.{userId}"); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/Entities/Emotes/PubsubEmote.cs: -------------------------------------------------------------------------------- 1 | using Model = NTwitch.Pubsub.API.Emote; 2 | 3 | namespace NTwitch.Pubsub 4 | { 5 | public class PubsubEmote : PubsubEntity 6 | { 7 | public int StartIndex { get; private set; } 8 | public int EndIndex { get; private set; } 9 | 10 | internal PubsubEmote(TwitchPubsubClient client, ulong id) 11 | : base(client, id) { } 12 | 13 | internal static PubsubEmote Create(TwitchPubsubClient client, Model model) 14 | { 15 | var entity = new PubsubEmote(client, model.Id); 16 | entity.Update(model); 17 | return entity; 18 | } 19 | 20 | internal virtual void Update(Model model) 21 | { 22 | StartIndex = model.StartIndex; 23 | EndIndex = model.EndIndex; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/Entities/PubsubEntity.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch.Pubsub 4 | { 5 | public class PubsubEntity : IEntity 6 | { 7 | /// An instance of the client that created this entity 8 | public TwitchPubsubClient Client { get; } 9 | /// The unique identifier for this entity 10 | public T Id { get; } 11 | 12 | public PubsubEntity(TwitchPubsubClient client, T id) 13 | { 14 | Client = client; 15 | Id = id; 16 | } 17 | 18 | ITwitchClient IEntity.Client 19 | => throw new NotImplementedException(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/Entities/Subscriptions/PubsubSubscription.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using Model = NTwitch.Pubsub.API.Subscription; 5 | 6 | namespace NTwitch.Pubsub 7 | { 8 | public class PubsubSubscription 9 | { 10 | /// An instance of the client that created this entity 11 | public TwitchPubsubClient Client { get; } 12 | /// The channel being subscribed to 13 | public PubsubSimpleChannel Channel { get; private set; } 14 | /// The user who purchased the subscription 15 | public PubsubSimpleUser User { get; private set; } 16 | /// The date and time this subscription occurred 17 | public DateTime Timestamp { get; private set; } 18 | /// The type of subscription 19 | public string Plan { get; private set; } 20 | /// The text associated with this sub plan 21 | public string PlanText { get; private set; } 22 | /// The number of months this user has subscribed 23 | public int Months { get; private set; } 24 | /// True if this is not this user's first subscription 25 | public bool IsResub { get; private set; } 26 | /// The message associated with this subscription 27 | public string Message { get; private set; } 28 | /// A collection of emotes found in the sub message 29 | public IReadOnlyCollection Emotes { get; private set; } 30 | 31 | internal PubsubSubscription(TwitchPubsubClient client) 32 | { 33 | Client = client; 34 | } 35 | 36 | internal static PubsubSubscription Create(TwitchPubsubClient client, Model model) 37 | { 38 | var entity = new PubsubSubscription(client); 39 | entity.Update(model); 40 | return entity; 41 | } 42 | 43 | internal virtual void Update(Model model) 44 | { 45 | Channel = PubsubSimpleChannel.Create(Client, model); 46 | User = PubsubSimpleUser.Create(Client, model); 47 | 48 | Timestamp = model.Timestamp; 49 | Plan = model.SubPlan; 50 | PlanText = model.SubPlanName; 51 | Months = model.Months; 52 | IsResub = model.Context == "resub"; 53 | 54 | Message = model.Message.Content; 55 | Emotes = model.Message.Emotes.Select(x => PubsubEmote.Create(Client, x)).ToArray(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/NTwitch.Pubsub.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard1.4 5 | An async compatible implementation of Twitch's version 5 api. 6 | 0.1.0.0 7 | 0.1.0.0 8 | 0.1.0.0 9 | Auxesis,Aux 10 | twitch,tv,dot,net,core,rest,api,lib,library,socket,websocket,chat,irc,tcp 11 | https://github.com/Aux/NTwitch/blob/master/LICENSE 12 | https://github.com/Aux/NTwitch 13 | http://i.imgur.com/kcL6nG0.png 14 | https://github.com/Aux/NTwitch 15 | git 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/TwitchPubsubClient.Events.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | 4 | namespace NTwitch.Pubsub 5 | { 6 | public partial class TwitchPubsubClient 7 | { 8 | //General 9 | public event Func Connected { add { _connectedEvent.Add(value); } remove { _connectedEvent.Remove(value); } } 10 | private readonly AsyncEvent> _connectedEvent = new AsyncEvent>(); 11 | 12 | public event Func Disconnected { add { _disconnectedEvent.Add(value); } remove { _disconnectedEvent.Remove(value); } } 13 | private readonly AsyncEvent> _disconnectedEvent = new AsyncEvent>(); 14 | 15 | public event Func LatencyUpdated { add { _latencyUpdatedEvent.Add(value); } remove { _latencyUpdatedEvent.Remove(value); } } 16 | private readonly AsyncEvent> _latencyUpdatedEvent = new AsyncEvent>(); 17 | 18 | // Anonymous 19 | public event Func AnonymousReceived { add { _anonymousReceivedEvent.Add(value); } remove { _anonymousReceivedEvent.Remove(value); } } 20 | private readonly AsyncEvent> _anonymousReceivedEvent = new AsyncEvent>(); 21 | 22 | // Channels 23 | public event Func SubscriptionReceived { add { _subscriptionReceived.Add(value); } remove { _subscriptionReceived.Remove(value); } } 24 | private readonly AsyncEvent> _subscriptionReceived = new AsyncEvent>(); 25 | 26 | public event Func BitsReceived { add { _bitsReceivedEvent.Add(value); } remove { _bitsReceivedEvent.Remove(value); } } 27 | private readonly AsyncEvent> _bitsReceivedEvent = new AsyncEvent>(); 28 | 29 | // Messages 30 | public event Func WhisperReceived { add { _whisperReceivedEvent.Add(value); } remove { _whisperReceivedEvent.Remove(value); } } 31 | private readonly AsyncEvent> _whisperReceivedEvent = new AsyncEvent>(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/NTwitch.Pubsub/TwitchPubsubConfig.cs: -------------------------------------------------------------------------------- 1 | using NTwitch.Rest; 2 | 3 | namespace NTwitch.Pubsub 4 | { 5 | public class TwitchPubsubConfig : TwitchRestConfig 6 | { 7 | /// Gets or sets the provider used to generate new websocket connections. 8 | public SocketClientProvider WebSocketProvider { get; set; } = DefaultWebSocketProvider.Instance; 9 | /// The host to connect to when making pubsub requests 10 | public string WebSocketHost { get; set; } = "wss://pubsub-edge.twitch.tv"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/DefaultRestClientProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace NTwitch.Rest.API 4 | { 5 | public static class DefaultRestClientProvider 6 | { 7 | public static readonly RestClientProvider Instance = url => 8 | { 9 | try 10 | { 11 | return new DefaultRestClient(url); 12 | } 13 | catch (PlatformNotSupportedException ex) 14 | { 15 | throw new PlatformNotSupportedException("The default RestClientProvider is not supported on this platform.", ex); 16 | } 17 | }; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Badge.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch.Rest.API 4 | { 5 | internal class Badge 6 | { 7 | [JsonProperty("id")] 8 | public string Id { get; set; } 9 | [JsonProperty("version")] 10 | public int Version { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/BlockedUser.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class BlockedUser 7 | { 8 | [JsonProperty("_id")] 9 | public ulong Id { get; set; } 10 | [JsonProperty("updated_at")] 11 | public DateTime UpdatedAt { get; set; } 12 | [JsonProperty("user")] 13 | public User User { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/BlockCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class BlockCollection 7 | { 8 | [JsonProperty("_total")] 9 | public uint Total { get; set; } 10 | [JsonProperty("blocks")] 11 | public IEnumerable Blocks { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/ChannelCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class ChannelCollection 7 | { 8 | [JsonProperty("_total")] 9 | public uint Total { get; set; } 10 | [JsonProperty("channels")] 11 | public IEnumerable Channels { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/CheerCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class CheerCollection 7 | { 8 | [JsonProperty("actions")] 9 | public IEnumerable Actions { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/ClipCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class ClipCollection 7 | { 8 | [JsonProperty("cursor")] 9 | public string Cursor { get; set; } 10 | [JsonProperty("clips")] 11 | public IEnumerable Clips { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/CommunityCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class CommunityCollection 7 | { 8 | [JsonProperty("_cursor")] 9 | public string Cursor { get; set; } 10 | [JsonProperty("_total")] 11 | public int Total { get; set; } 12 | [JsonProperty("communities")] 13 | public IEnumerable Communities { get; set; } 14 | [JsonProperty("moderators")] 15 | public IEnumerable Moderators { get; set; } 16 | [JsonProperty("timed_out_users")] 17 | public IEnumerable Timeouts { get; set; } 18 | [JsonProperty("banned_users")] 19 | public IEnumerable Bans { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/FollowCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class FollowCollection 7 | { 8 | [JsonProperty("_cursor")] 9 | public string Cursor { get; set; } 10 | [JsonProperty("_total")] 11 | public uint Total { get; set; } 12 | [JsonProperty("follows")] 13 | public IEnumerable Follows { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/GameCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class GameCollection 7 | { 8 | [JsonProperty("games")] 9 | public IEnumerable Games { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/IngestCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class IngestCollection 7 | { 8 | [JsonProperty("ingests")] 9 | public IEnumerable Ingests { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/StreamCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class StreamCollection 7 | { 8 | [JsonProperty("_total")] 9 | public uint Total { get; set; } 10 | [JsonProperty("stream")] 11 | public Stream Stream { get; set; } 12 | [JsonProperty("streams")] 13 | public IEnumerable Streams { get; set; } 14 | [JsonProperty("featured")] 15 | public IEnumerable Featured { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/SubscriptionCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class SubscriptionCollection 7 | { 8 | [JsonProperty("_total")] 9 | public uint Total { get; set; } 10 | [JsonProperty("subscriptions")] 11 | public IEnumerable Subscriptions { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/TeamCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class TeamCollection 7 | { 8 | [JsonProperty("teams")] 9 | public IEnumerable Teams { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/TokenCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | 3 | namespace NTwitch.Rest.API 4 | { 5 | internal class TokenCollection 6 | { 7 | [JsonProperty("token")] 8 | public Token Token { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/UserCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class UserCollection 7 | { 8 | [JsonProperty("_total")] 9 | public uint Total { get; set; } 10 | [JsonProperty("users")] 11 | public IEnumerable Users { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/NTwitch.Rest/API/Models/Collections/VideoCollection.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Collections.Generic; 3 | 4 | namespace NTwitch.Rest.API 5 | { 6 | internal class VideoCollection 7 | { 8 | [JsonProperty("vods")] 9 | public IEnumerable