├── .gitattributes ├── .gitignore ├── LICENSE.md ├── README.md ├── TwitchDotNet.Tests ├── Assets │ ├── LockScreenLogo.scale-200.png │ ├── SplashScreen.scale-200.png │ ├── Square150x150Logo.scale-200.png │ ├── Square44x44Logo.scale-200.png │ ├── Square44x44Logo.targetsize-24_altform-unplated.png │ ├── StoreLogo.png │ └── Wide310x150Logo.scale-200.png ├── Clients │ ├── TwitchClientAuthenticatedTests.cs │ └── TwitchClientTests.cs ├── Helpers │ ├── HttpHelperTests.cs │ └── PaginationTests.cs ├── Package.appxmanifest ├── Properties │ ├── AssemblyInfo.cs │ └── UnitTestApp.rd.xml ├── TwitchDotNet.Tests.csproj ├── UnitTestApp.xaml ├── UnitTestApp.xaml.cs └── project.json ├── TwitchDotNet.sln └── TwitchDotNet ├── Clients ├── TwitchClient.cs └── TwitchClientAuthenticated.cs ├── Enums ├── BroadcastType.cs ├── Period.cs ├── SortBy.cs ├── SortDirection.cs ├── SortKey.cs └── StreamType.cs ├── Helpers ├── CursorPagination.cs ├── HttpHelper.cs ├── OAuth2Broker.cs └── Pagination.cs ├── Interfaces ├── ITwitchClient.cs └── ITwitchClientAuthenticated.cs ├── Properties ├── AssemblyInfo.cs └── TwitchDotNet.rd.xml ├── TwitchDotNet.csproj ├── TwitchDotNet.nuspec └── project.json /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | 263 | # Custom 264 | # Resources files 265 | *.resw -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Travis Liew 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 | # TwitchDotNet 2 | A .NETCore (UWP) C# Library for Twitch API v5. 3 | 4 | ## Getting Started 5 | 6 | Follow these instructions to get started with TwitchDotNet 7 | 8 | ### Prerequisites 9 | 10 | - Visual Studio (2015 or 2017 RC) 11 | - SDKs and libraries: .NET Native, Windows 10 SDK 10.0.14393.0 or later. Easiest way is to install VS2017 RC and select "Universal Windows Platform development" option when installing 12 | - A Twitch Client-Id, see: https://blog.twitch.tv/client-id-required-for-kraken-api-calls-afbb8e95f843 13 | - Clone this repo to local 14 | - External Nuget dependencies: Newtonsoft.Json 15 | 16 | #### Add a reference to project 17 | 18 | Build the project and add a reference to the `TwitchDotNet.dll` (located in `../bin///dll`, or add the project to your existing solution (via right-clicking your solution in Visual Studio and selecting Add -> Existing Project -> `/path/to/local/repo/TwitchDotNet.csproj`) 19 | 20 | ### Usage 21 | 22 | Clone the repository and open the solution in Visual Studio. 23 | 24 | For unauthenticated Twitch requests: 25 | 26 | ``` 27 | string baseUrl = "https://api.twitch.tv"; 28 | string clientId = ""; 29 | 30 | // Init an unauthenticated client with base url and client id 31 | var client = new TwitchClient(baseUrl, clientId); 32 | 33 | // Search for games 34 | var result = await client.SearchGames("Dota"); 35 | JObject response_object = JObject.Parse(result?.ToString()); // Parse to JObject 36 | var found_game_list = JsonConvert.DeserializeObject>(response_object["games"]?.ToString(); // Parse to list of game objects (refer to Twitch docs for returned JSON) 37 | 38 | // Get streams summary 39 | result = await client.GetStreamsSummary(); 40 | response_object = JObject.Parse(result?.ToString()); // Parse to JObject 41 | ``` 42 | 43 | For authenticated Twitch requests: 44 | 45 | ``` 46 | string baseUrl = "https://api.twitch.tv"; 47 | string clientId = ""; 48 | string redirectUri = ""; 49 | string scopes = ""; 50 | 51 | // First get an oauth_token for Twitch authentication 52 | string oauth_token = await Oauth2Broker.Authenticate(baseUrl, clientId, redirectUri, scopes); 53 | 54 | // Init an authenticated client with base url, client id and an oauth_token 55 | var client = new TwitchClientAuthenticated(baseUrl, clientId, oauth_token); 56 | 57 | // Do stuff with Twitch authenticated APIs: 58 | 59 | // Get my channel info 60 | var result = await client.GetChannel(); // Uses oauth_token to know my user 61 | JObject response_object = JObject.Parse(result?.ToString()); // Parse to JObject 62 | string displayName = response_object["display_name"]?.ToString(); // Get object by key (display_name) (refer to Twitch docs for returned JSON) 63 | 64 | // Follow a channel 65 | // Convert twitch user ids to twitch ids 66 | string myId = client.GetIdByName("my username"); 67 | string targetId = client.GetIdByName("target username"); 68 | result = await client.FollowChannel(myId, targetId); 69 | 70 | // Start my channel commercial 71 | result = await client.StartChannelCommercial(channelId); 72 | ``` 73 | 74 | For more information, please refer to links below: 75 | - [Twitch API v5 Documentation](https://dev.twitch.tv/docs/) 76 | - Authentication: [OAuth2Broker class](TwitchDotNet/Helpers/OAuth2Broker.cs) and [Twitch Authentication docs](https://dev.twitch.tv/docs/v5/guides/authentication/). 77 | 78 | ## Running the tests 79 | 80 | To run tests locaed in test project `TwitchDotNet.Tests`, simply add a Resource file called `Resources.resw` to the root folder of `TwitchDotNet.Tests` with the following values: 81 | 82 | `Resources.resw`: 83 | 84 | Name | Value | Comment 85 | --- | --- | --- 86 | AUTH_REDIRECT_URI | `` | Twitch Authentication Redirect Uri 87 | AUTH_SCOPES | `` | Twitch Authentication Scopes 88 | CLIENT_ID | `` | Client Id 89 | OAUTH_TOKEN | `` | Twitch OAuthToken 90 | TWITCH_API_BASE_URL | https://api.twitch.tv | Base Twitch API Url 91 | 92 | The test project will use these values to initialise the `TwitchClient(s)` and perform the tests. 93 | 94 | Note: OAuth token is manually specified at this stage -- get it from `Fiddler`, `Wireshark` when using `OAuth2Broker` or directly from browser using the `Inspector` and passing in the auth url manually. 95 | 96 | ## Nuget 97 | 98 | Coming soon 99 | 100 | ## Authors 101 | 102 | - **Travis Liew** - [travisliew](https://github.com/travisliew) 103 | 104 | See also the list of [contributors](https://github.com/your/project/contributors) who participated in this project. 105 | 106 | ## License 107 | 108 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details 109 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/LockScreenLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/LockScreenLogo.scale-200.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/Square150x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/Square150x150Logo.scale-200.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/Square44x44Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/Square44x44Logo.scale-200.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/Square44x44Logo.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/Square44x44Logo.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/StoreLogo.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Assets/Wide310x150Logo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travisliew/TwitchDotNet/289214cc3c377bc4bf90b0d544d741ad81307e0d/TwitchDotNet.Tests/Assets/Wide310x150Logo.scale-200.png -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Clients/TwitchClientAuthenticatedTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using TwitchDotNet.Helpers; 5 | using TwitchDotNet.Enums; 6 | using Windows.ApplicationModel.Resources; 7 | using TwitchDotNet.Clients; 8 | using System.Net.Http; 9 | using Newtonsoft.Json.Linq; 10 | using Newtonsoft.Json; 11 | 12 | namespace TwitchDotNet.Tests { 13 | [TestClass] 14 | public class TwitchClientAuthenticatedTests { 15 | 16 | private static ResourceLoader resourceLoader = new ResourceLoader(); 17 | private static TwitchClientAuthenticated twitchClientAuthenticated; 18 | 19 | // Initialise base variables 20 | [ClassInitialize] 21 | public static void Initialise(TestContext context) { 22 | // Retrieve config from Resources.resw 23 | string baseUrl = resourceLoader.GetString("TWITCH_API_BASE_URL"); 24 | string clientId = resourceLoader.GetString("CLIENT_ID"); 25 | string redirectUri = resourceLoader.GetString("AUTH_REDIRECT_URI"); 26 | string scopes = resourceLoader.GetString("AUTH_SCOPES"); 27 | string oauthToken = resourceLoader.GetString("OAUTH_TOKEN"); 28 | 29 | // Init client 30 | // Manual OAuth Token as WebAuthenticationBroker for UWP doesn't work in a UnitTest 31 | twitchClientAuthenticated = new TwitchClientAuthenticated(baseUrl, clientId, oauthToken); 32 | } 33 | 34 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api 35 | 36 | [TestMethod] 37 | public void Test_GetRoot() { 38 | Assert.IsNotNull(twitchClientAuthenticated.GetRoot().Result); 39 | } 40 | 41 | #endregion 42 | 43 | #region ChannelFeed - Https://dev.twitch.tv/docs/v5/reference/channel-feed/ 44 | 45 | [TestMethod] 46 | public void Test_GetChannelFeedPosts() { 47 | string channelId = "32220409"; // travy92 48 | Assert.IsNotNull(twitchClientAuthenticated.GetChannelFeedPosts(channelId, new CursorPagination()).Result); 49 | } 50 | 51 | [TestMethod] 52 | public void Test_GetChannelFeedPost() { 53 | string channelId = "32220409"; // travy92 54 | string postId = "322204091482884560"; 55 | Assert.IsNotNull(twitchClientAuthenticated.GetChannelFeedPost(channelId, postId).Result); 56 | } 57 | 58 | // Test_CreateChannelFeedPost 59 | // Test_DeleteChannelFeedPost 60 | [TestMethod] 61 | public void Test_CreateAndDeleteChannelFeedPost() { 62 | string channelId = "32220409"; // travy92 63 | string content = "Test Post from TwitchDotNet Unit Test"; 64 | 65 | // Create post 66 | var response = twitchClientAuthenticated.CreateChannelFeedPost(channelId, content).Result; 67 | Assert.IsNotNull(response); 68 | 69 | // Delete post 70 | Assert.IsNotNull(twitchClientAuthenticated.DeleteChannelFeedPost(channelId, response.post.id.ToString()).Result); 71 | } 72 | 73 | // Test_CreateReactionToChannelFeedPost 74 | // Test_DeleteReactionToChannelFeedPost 75 | [TestMethod] 76 | public void Test_CreateAndDeleteReactionToChannelFeedPost() { 77 | string channelId = "32220409"; // travy92 78 | string postId = "322204091482884560"; 79 | string emoteId = "endorse"; 80 | 81 | // Create reaction to post 82 | Assert.IsNotNull(twitchClientAuthenticated.CreateReactionToChannelFeedPost(channelId, postId, emoteId).Result); 83 | 84 | // Delete reaction to post 85 | Assert.IsNotNull(twitchClientAuthenticated.DeleteReactionToChannelFeedPost(channelId, postId, emoteId).Result); 86 | } 87 | 88 | [TestMethod] 89 | public void Test_GetChannelFeedPostComments() { 90 | string channelId = "32220409"; // travy92 91 | string postId = "322204091482884560"; 92 | Assert.IsNotNull(twitchClientAuthenticated.GetChannelFeedPostComments(channelId, postId, new CursorPagination()).Result); 93 | } 94 | 95 | // Test_CreateChannelFeedPostComment 96 | // Test_DeleteChannelFeedPostComment 97 | [TestMethod] 98 | public void Test_CreateAndDeleteChannelFeedPostComment() { 99 | string channelId = "32220409"; // travy92 100 | string postId = "322204091482884560"; 101 | string content = "Test Comment from TwitchDotNet Unit Test"; 102 | 103 | // Create post comment 104 | var response = twitchClientAuthenticated.CreateChannelFeedPostComment(channelId, postId, content).Result; 105 | Assert.IsNotNull(response); 106 | 107 | // Delete post comment 108 | Assert.IsNotNull(twitchClientAuthenticated.DeleteChannelFeedPostComment(channelId, postId, response.id.ToString()).Result); 109 | } 110 | 111 | // Test_CreateReactionToChannelFeedPostComment 112 | // Test_DeleteReactionToChannelFeedPostComment 113 | [TestMethod] 114 | public void Test_CreateAndDeleteReactionToChannelFeedPostComment() { 115 | string channelId = "32220409"; // travy92 116 | string postId = "322204091482884560"; 117 | string commentId = "157121"; 118 | string emoteId = "endorse"; 119 | 120 | // Create reaction to post comment 121 | Assert.IsNotNull(twitchClientAuthenticated.CreateReactionToChannelFeedPostComment(channelId, postId, commentId, emoteId).Result); 122 | 123 | // Delete reaction to post comment 124 | Assert.IsNotNull(twitchClientAuthenticated.DeleteReactionToChannelFeedPostComment(channelId, postId, commentId, emoteId).Result); 125 | } 126 | 127 | #endregion 128 | 129 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 130 | 131 | [TestMethod] 132 | public void Test_GetChannel() { 133 | Assert.IsNotNull(twitchClientAuthenticated.GetChannel().Result); 134 | } 135 | 136 | [TestMethod] 137 | public void Test_UpdateChannel() { 138 | string channelId = "32220409"; // travy92 139 | string status = "test"; 140 | string game = "League of Legends"; 141 | string delay = "0"; 142 | bool channelFeedEnabled = false; 143 | Assert.IsNotNull(twitchClientAuthenticated.UpdateChannel(channelId, status, game, delay, channelFeedEnabled).Result); 144 | } 145 | 146 | [TestMethod] 147 | public void Test_GetChannelEditors() { 148 | string channelId = "32220409"; // travy92 149 | Assert.IsNotNull(twitchClientAuthenticated.GetChannelEditors(channelId).Result); 150 | } 151 | 152 | [TestMethod] 153 | public void Test_GetChannelSubscribers() { 154 | // Expecting null as I don't have any subscribers 155 | string channelId = "28036688"; // travy92 156 | Assert.IsNull(twitchClientAuthenticated.GetChannelSubscribers(channelId, new Pagination()).Result); 157 | } 158 | 159 | [TestMethod] 160 | public void Test_CheckChannelSubscriptionByUser() { 161 | string channelId = "32220409"; // travy92 162 | string targetUserId = "28036688"; // trick2g 163 | Assert.IsNotNull(twitchClientAuthenticated.CheckChannelSubscriptionByUser(channelId, targetUserId).Result); 164 | } 165 | 166 | [TestMethod] 167 | public void Test_StartChannelCommercial() { 168 | string channelId = "32220409"; // travy92 169 | Assert.IsNotNull(twitchClientAuthenticated.ResetChannelStreamKey(channelId).Result); 170 | } 171 | 172 | [TestMethod] 173 | public void Test_ResetChannelStreamKey() { 174 | string channelId = "32220409"; // travy92 175 | Assert.IsNotNull(twitchClientAuthenticated.ResetChannelStreamKey(channelId).Result); 176 | } 177 | 178 | #endregion 179 | 180 | #region Game - Unofficial https://discuss.dev.twitch.tv/t/game-following-requests/2186 181 | 182 | // Test_FollowGame 183 | // Test_UnfollowGame 184 | [TestMethod] 185 | public void Test_FollowAndUnfollowGame() { 186 | string username = "travy92"; 187 | string game = "Poker"; 188 | 189 | // Follow game 190 | Assert.IsNotNull(twitchClientAuthenticated.FollowGame(username, game).Result); 191 | 192 | // Unfollow game 193 | Assert.IsNotNull(twitchClientAuthenticated.UnfollowGame(username, game).Result); 194 | } 195 | 196 | #endregion 197 | 198 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 199 | 200 | [TestMethod] 201 | public void Test_GetFollowedStreams() { 202 | Assert.IsNotNull(twitchClientAuthenticated.GetFollowedStreams(new Pagination()).Result); 203 | } 204 | 205 | #endregion 206 | 207 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 208 | 209 | [TestMethod] 210 | public void Test_GetUser() { 211 | Assert.IsNotNull(twitchClientAuthenticated.GetUser().Result); 212 | } 213 | 214 | [TestMethod] 215 | public void Test_GetUserEmotes() { 216 | string userId = "32220409"; // travy92 217 | Assert.IsNotNull(twitchClientAuthenticated.GetUserEmotes(userId).Result); 218 | } 219 | 220 | [TestMethod] 221 | public void Test_CheckUserSubscriptionByChannel() { 222 | string userId = "32220409"; // travy92 223 | string channelId = "28036688"; // trick2g 224 | Assert.IsNotNull(twitchClientAuthenticated.CheckUserSubscriptionByChannel(userId, channelId).Result); 225 | } 226 | 227 | // Test_FollowChannel 228 | // Test_UnfollowChannel 229 | [TestMethod] 230 | public void Test_FollowAndUnfollowChannel() { 231 | string userId = "32220409"; // travy92 232 | string targetChannelId = "44322889"; // dallas 233 | 234 | // Follow channel 235 | Assert.IsNotNull(twitchClientAuthenticated.FollowChannel(userId, targetChannelId).Result); 236 | 237 | // Unfollow Channel 238 | Assert.IsNotNull(twitchClientAuthenticated.UnfollowChannel(userId, targetChannelId).Result); 239 | } 240 | 241 | [TestMethod] 242 | public void Test_GetUserBlockList() { 243 | string userId = "32220409"; // travy92 244 | Assert.IsNotNull(twitchClientAuthenticated.GetUserBlockList(userId, new Pagination()).Result); 245 | } 246 | 247 | // Test_BlockUser 248 | // Test_UnblockUser 249 | [TestMethod] 250 | public void Test_BlockAndUnblockUser() { 251 | string userId = "32220409"; // travy92 252 | string targetUserId = "28036688"; // trick2g 253 | 254 | // Block user 255 | Assert.IsNotNull(twitchClientAuthenticated.BlockUser(userId, targetUserId).Result); 256 | 257 | // Unblock user 258 | Assert.IsNotNull(twitchClientAuthenticated.UnblockUser(userId, targetUserId).Result); 259 | } 260 | 261 | #endregion 262 | 263 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 264 | 265 | [TestMethod] 266 | public void Test_GetFollowedVideos() { 267 | Assert.IsNotNull(twitchClientAuthenticated.GetFollowedVideos(new Pagination()).Result); 268 | } 269 | 270 | #endregion 271 | } 272 | } -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Clients/TwitchClientTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using TwitchDotNet.Helpers; 5 | using System.Net.Http; 6 | using System.Collections.Generic; 7 | using TwitchDotNet.Enums; 8 | using TwitchDotNet.Clients; 9 | using Windows.ApplicationModel.Resources; 10 | using Newtonsoft.Json.Linq; 11 | using Newtonsoft.Json; 12 | 13 | namespace TwitchDotNet.Tests 14 | { 15 | [TestClass] 16 | public class TwitchClientTests { 17 | 18 | private static ResourceLoader resourceLoader = new ResourceLoader(); 19 | private static TwitchClient twitchClient; 20 | 21 | [ClassInitialize] 22 | public static void Initialise(TestContext context) { 23 | // Retrieve config from Resources.resw 24 | string baseUrl = resourceLoader.GetString("TWITCH_API_BASE_URL"); 25 | string clientId = resourceLoader.GetString("CLIENT_ID"); 26 | 27 | // Init client 28 | twitchClient = new TwitchClient(baseUrl, clientId); 29 | } 30 | 31 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api 32 | 33 | [TestMethod] 34 | public void Test_GetIdByName() { 35 | string name = "trick2g"; 36 | Assert.IsNotNull(twitchClient.GetIdByName(name).Result); 37 | } 38 | 39 | #endregion 40 | 41 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 42 | 43 | [TestMethod] 44 | public void Test_GetChannel() { 45 | string channelId = "28036688"; // trick2g 46 | Assert.IsNotNull(twitchClient.GetChannel(channelId).Result); 47 | } 48 | 49 | [TestMethod] 50 | public void Test_GetChannelFollowers() { 51 | string channelId = "28036688"; // trick2g 52 | Assert.IsNotNull(twitchClient.GetChannelFollowers(channelId, new Pagination()).Result); 53 | } 54 | 55 | [TestMethod] 56 | public void Test_GetChannelTeams() { 57 | string channelId = "28036688"; // trick2g 58 | Assert.IsNotNull(twitchClient.GetChannelTeams(channelId).Result); 59 | } 60 | 61 | [TestMethod] 62 | public void Test_GetChannelVideos() { 63 | string channelId = "28036688"; // trick2g 64 | Assert.IsNotNull(twitchClient.GetChannelVideos(channelId, new Pagination()).Result); 65 | } 66 | 67 | #endregion 68 | 69 | #region Chat - Https://dev.twitch.tv/docs/v5/reference/chat/ 70 | 71 | [TestMethod] 72 | public void Test_GetChatBadgesByChannel() { 73 | string channelId = "28036688"; // trick2g 74 | Assert.IsNotNull(twitchClient.GetChatBadgesByChannel(channelId).Result); 75 | } 76 | 77 | [TestMethod] 78 | public void Test_GetChatEmoticonsBySet() { 79 | Assert.IsNotNull(twitchClient.GetChatEmoticonsBySet().Result); 80 | } 81 | 82 | [TestMethod] 83 | public void Test_GetEmoticons() { 84 | Assert.IsNotNull(twitchClient.GetEmoticons().Result); 85 | } 86 | 87 | #endregion 88 | 89 | #region Games - Https://dev.twitch.tv/docs/v5/reference/games/ 90 | 91 | [TestMethod] 92 | public void Test_GetTopGames() { 93 | Assert.IsNotNull(twitchClient.GetTopGames(new Pagination()).Result); 94 | } 95 | 96 | [TestMethod] 97 | public void Test_GetFollowedGames() { 98 | string username = "trick2g"; 99 | Assert.IsNotNull(twitchClient.GetFollowedGames(username, new Pagination()).Result); 100 | } 101 | 102 | #endregion 103 | 104 | #region Ingests - Https://dev.twitch.tv/docs/v5/reference/ingests/ 105 | 106 | [TestMethod] 107 | public void Test_GetIngests() { 108 | Assert.IsNotNull(twitchClient.GetIngests().Result); 109 | } 110 | 111 | #endregion 112 | 113 | #region Search - Https://dev.twitch.tv/docs/v5/reference/search/ 114 | 115 | [TestMethod] 116 | public void Test_SearchChannels() { 117 | string query = "star"; 118 | Assert.IsNotNull(twitchClient.SearchChannels(query, new Pagination()).Result); 119 | } 120 | 121 | [TestMethod] 122 | public void Test_SearchStreams() { 123 | string query = "star"; 124 | Assert.IsNotNull(twitchClient.SearchStreams(query, new Pagination()).Result); 125 | } 126 | 127 | [TestMethod] 128 | public void Test_SearchGames() { 129 | string query = "star"; 130 | Assert.IsNotNull(twitchClient.SearchGames(query).Result); 131 | } 132 | 133 | #endregion 134 | 135 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 136 | 137 | [TestMethod] 138 | public void Test_GetStreams() { 139 | Assert.IsNotNull(twitchClient.GetStreams(new Pagination()).Result); 140 | Assert.IsNotNull(twitchClient.GetStreams(new Pagination(), "Dungeons & Dragons").Result); 141 | } 142 | 143 | [TestMethod] 144 | public void Test_GetStream() { 145 | string channelId = "28036688"; // trick2g 146 | Assert.IsNotNull(twitchClient.GetStream(channelId).Result); 147 | } 148 | 149 | [TestMethod] 150 | public void Test_GetFeaturedStreams() { 151 | Assert.IsNotNull(twitchClient.GetFeaturedStreams(new Pagination()).Result); 152 | } 153 | 154 | [TestMethod] 155 | public void Test_GetStreamsSummary() { 156 | Assert.IsNotNull(twitchClient.GetStreamsSummary().Result); 157 | } 158 | 159 | #endregion 160 | 161 | #region Teams - Https://dev.twitch.tv/docs/v5/reference/teams/ 162 | 163 | [TestMethod] 164 | public void Test_GetTeams() { 165 | Assert.IsNotNull(twitchClient.GetTeams(new Pagination()).Result); 166 | } 167 | 168 | [TestMethod] 169 | public void Test_GetTeam() { 170 | string teamName = "staff"; 171 | Assert.IsNotNull(twitchClient.GetTeam(teamName).Result); 172 | } 173 | 174 | #endregion 175 | 176 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 177 | 178 | [TestMethod] 179 | public void Test_GetUser() { 180 | string userId = "28036688"; // trick2g 181 | Assert.IsNotNull(twitchClient.GetUser(userId).Result); 182 | } 183 | 184 | [TestMethod] 185 | public void Test_GetUserFollowedChannels() { 186 | string userId = "28036688"; // trick2g 187 | Assert.IsNotNull(twitchClient.GetUserFollowedChannels(userId, new Pagination()).Result); 188 | } 189 | 190 | 191 | [TestMethod] 192 | public void Test_CheckUserFollowsByChannel() { 193 | // Am following, expecting result 194 | string userId = "32220409"; // travy92 195 | string channelId = "28036688"; // trick2g 196 | Assert.IsNotNull(twitchClient.CheckUserFollowsByChannel(userId, channelId).Result); 197 | 198 | // Not following, still expecting result (but 404 http code with message of "X is not following Y") 199 | channelId = "129454141"; 200 | Assert.IsNotNull(twitchClient.CheckUserFollowsByChannel(userId, channelId).Result); 201 | } 202 | 203 | [TestMethod] 204 | public void Test_CheckUserFollowsByGame() { 205 | // Am following, expecting result 206 | string username = "travy92"; 207 | string game = "League of Legends"; 208 | Assert.IsNotNull(twitchClient.CheckUserFollowsByGame(username, game).Result); 209 | 210 | // Not following, still expecting result (but 404 http code with message of "X is not following Y") 211 | game = "Poker"; 212 | Assert.IsNotNull(twitchClient.CheckUserFollowsByGame(username, game).Result); 213 | } 214 | 215 | #endregion 216 | 217 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 218 | 219 | [TestMethod] 220 | public void Test_GetVideo() { 221 | // https://www.twitch.tv/twitch/v/106400740 222 | string videoId = "106400740"; 223 | Assert.IsNotNull(twitchClient.GetVideo(videoId).Result); 224 | } 225 | 226 | [TestMethod] 227 | public void Test_GetTopVideos() { 228 | Assert.IsNotNull(twitchClient.GetTopVideos(new Pagination()).Result); 229 | 230 | // With game 231 | string game = "Overwatch"; 232 | Assert.IsNotNull(twitchClient.GetTopVideos(new Pagination(), game).Result); 233 | } 234 | 235 | #endregion 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Helpers/HttpHelperTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using TwitchDotNet.Helpers; 5 | using System.Net.Http; 6 | using Windows.ApplicationModel.Resources; 7 | 8 | namespace TwitchDotNet.Tests 9 | { 10 | [TestClass] 11 | public class HttpHelperTests { 12 | 13 | [TestMethod] 14 | public void ValidQueryString() 15 | { 16 | var httpHelper = new HttpHelper("http://www.travisliew.com", ""); 17 | var request = httpHelper.CreateHttpRequest("users/travis", HttpMethod.Get); 18 | 19 | // Add some dummy query string data 20 | httpHelper.AddQueryString(request, "game", "123"); 21 | httpHelper.AddQueryString(request, "id", "1"); 22 | var pagination = new Pagination(); 23 | httpHelper.AddQueryString(request, pagination); 24 | 25 | // Assert that AddQueryString creates a valid query string 26 | string query = $"?game=123&id=1&limit={pagination.Limit}&offset={pagination.Offset}"; 27 | Assert.IsTrue(request.RequestUri.Query.Equals(query)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Helpers/PaginationTests.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using TwitchDotNet.Helpers; 5 | using Windows.Web.Http; 6 | 7 | namespace TwitchDotNet.Tests 8 | { 9 | [TestClass] 10 | public class PaginationTests { 11 | 12 | [TestMethod] 13 | public void ValidPagination() 14 | { 15 | // Initialise (limit = 25, offset = 0) 16 | var pagination = new Pagination(); 17 | var oldLimit = pagination.Limit; 18 | var oldOffset = pagination.Offset; 19 | 20 | pagination.NextPage(); // Increment page (limit = 25, offset = 25) 21 | 22 | // Assert that NextPage increments offset by limit, leaving limit as-is 23 | Assert.IsTrue(pagination.Limit == oldLimit && pagination.Offset == oldOffset + oldLimit); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Package.appxmanifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | TwitchDotNet.Tests 7 | Travis Liew 8 | Assets\StoreLogo.png 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TwitchDotNet.Tests")] 9 | [assembly: AssemblyDescription("Testing class for .NETCore (UWP) C# Library for Twitch API v5")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TwitchDotNet.Tests")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | [assembly: AssemblyMetadata("TargetPlatform","UAP")] 17 | 18 | // Version information for an assembly consists of the following four values: 19 | // 20 | // Major Version 21 | // Minor Version 22 | // Build Number 23 | // Revision 24 | // 25 | // You can specify all the values or you can default the Build and Revision Numbers 26 | // by using the '*' as shown below: 27 | // [assembly: AssemblyVersion("1.0.*")] 28 | [assembly: AssemblyVersion("1.0.0.0")] 29 | [assembly: AssemblyFileVersion("1.0.0.0")] 30 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /TwitchDotNet.Tests/Properties/UnitTestApp.rd.xml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/TwitchDotNet.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x86 7 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF} 8 | AppContainerExe 9 | Properties 10 | TwitchDotNet.Tests 11 | TwitchDotNet.Tests 12 | en-US 13 | UAP 14 | 10.0.14393.0 15 | 10.0.14393.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | TwitchDotNet.Tests_TemporaryKey.pfx 20 | 15.0 21 | 22 | 23 | true 24 | bin\x86\Debug\ 25 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 26 | ;2008 27 | full 28 | x86 29 | false 30 | prompt 31 | true 32 | 33 | 34 | bin\x86\Release\ 35 | TRACE;NETFX_CORE;WINDOWS_UWP 36 | true 37 | ;2008 38 | pdbonly 39 | x86 40 | false 41 | prompt 42 | true 43 | true 44 | 45 | 46 | true 47 | bin\ARM\Debug\ 48 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 49 | ;2008 50 | full 51 | ARM 52 | false 53 | prompt 54 | true 55 | 56 | 57 | bin\ARM\Release\ 58 | TRACE;NETFX_CORE;WINDOWS_UWP 59 | true 60 | ;2008 61 | pdbonly 62 | ARM 63 | false 64 | prompt 65 | true 66 | true 67 | 68 | 69 | true 70 | bin\x64\Debug\ 71 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 72 | ;2008 73 | full 74 | x64 75 | false 76 | prompt 77 | true 78 | 79 | 80 | bin\x64\Release\ 81 | TRACE;NETFX_CORE;WINDOWS_UWP 82 | true 83 | ;2008 84 | pdbonly 85 | x64 86 | false 87 | prompt 88 | true 89 | true 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | UnitTestApp.xaml 104 | 105 | 106 | 107 | 108 | 109 | MSBuild:Compile 110 | Designer 111 | 112 | 113 | 114 | 115 | Designer 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | {032c681c-c251-47d1-a6bf-ebc3751efdaa} 132 | TwitchDotNet 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 15.0 141 | 142 | 143 | 150 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/UnitTestApp.xaml: -------------------------------------------------------------------------------- 1 |  7 | 8 | 9 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/UnitTestApp.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Runtime.InteropServices.WindowsRuntime; 6 | using Windows.ApplicationModel; 7 | using Windows.ApplicationModel.Activation; 8 | using Windows.Foundation; 9 | using Windows.Foundation.Collections; 10 | using Windows.UI.Xaml; 11 | using Windows.UI.Xaml.Controls; 12 | using Windows.UI.Xaml.Controls.Primitives; 13 | using Windows.UI.Xaml.Data; 14 | using Windows.UI.Xaml.Input; 15 | using Windows.UI.Xaml.Media; 16 | using Windows.UI.Xaml.Navigation; 17 | 18 | namespace TwitchDotNet.Tests 19 | { 20 | /// 21 | /// Provides application-specific behavior to supplement the default Application class. 22 | /// 23 | sealed partial class App : Application 24 | { 25 | /// 26 | /// Initializes the singleton application object. This is the first line of authored code 27 | /// executed, and as such is the logical equivalent of main() or WinMain(). 28 | /// 29 | public App() 30 | { 31 | this.InitializeComponent(); 32 | this.Suspending += OnSuspending; 33 | } 34 | 35 | /// 36 | /// Invoked when the application is launched normally by the end user. Other entry points 37 | /// will be used such as when the application is launched to open a specific file. 38 | /// 39 | /// Details about the launch request and process. 40 | protected override void OnLaunched(LaunchActivatedEventArgs e) 41 | { 42 | 43 | #if DEBUG 44 | if (System.Diagnostics.Debugger.IsAttached) 45 | { 46 | this.DebugSettings.EnableFrameRateCounter = true; 47 | } 48 | #endif 49 | 50 | Frame rootFrame = Window.Current.Content as Frame; 51 | 52 | // Do not repeat app initialization when the Window already has content, 53 | // just ensure that the window is active 54 | if (rootFrame == null) 55 | { 56 | // Create a Frame to act as the navigation context and navigate to the first page 57 | rootFrame = new Frame(); 58 | 59 | rootFrame.NavigationFailed += OnNavigationFailed; 60 | 61 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated) 62 | { 63 | //TODO: Load state from previously suspended application 64 | } 65 | 66 | // Place the frame in the current Window 67 | Window.Current.Content = rootFrame; 68 | } 69 | 70 | Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.CreateDefaultUI(); 71 | 72 | // Ensure the current window is active 73 | Window.Current.Activate(); 74 | 75 | Microsoft.VisualStudio.TestPlatform.TestExecutor.UnitTestClient.Run(e.Arguments); 76 | } 77 | 78 | /// 79 | /// Invoked when Navigation to a certain page fails 80 | /// 81 | /// The Frame which failed navigation 82 | /// Details about the navigation failure 83 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e) 84 | { 85 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName); 86 | } 87 | 88 | /// 89 | /// Invoked when application execution is being suspended. Application state is saved 90 | /// without knowing whether the application will be terminated or resumed with the contents 91 | /// of memory still intact. 92 | /// 93 | /// The source of the suspend request. 94 | /// Details about the suspend request. 95 | private void OnSuspending(object sender, SuspendingEventArgs e) 96 | { 97 | var deferral = e.SuspendingOperation.GetDeferral(); 98 | //TODO: Save application state and stop any background activity 99 | deferral.Complete(); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /TwitchDotNet.Tests/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", 4 | "MSTest.TestAdapter": "1.1.4-preview", 5 | "MSTest.TestFramework": "1.0.5-preview" 6 | }, 7 | "frameworks": { 8 | "uap10.0": {} 9 | }, 10 | "runtimes": { 11 | "win10-arm": {}, 12 | "win10-arm-aot": {}, 13 | "win10-x86": {}, 14 | "win10-x86-aot": {}, 15 | "win10-x64": {}, 16 | "win10-x64-aot": {} 17 | } 18 | } -------------------------------------------------------------------------------- /TwitchDotNet.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.15 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitchDotNet", "TwitchDotNet\TwitchDotNet.csproj", "{032C681C-C251-47D1-A6BF-EBC3751EFDAA}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitchDotNet.Tests", "TwitchDotNet.Tests\TwitchDotNet.Tests.csproj", "{0BD40987-8086-4EEB-BB5F-1289864BBCCF}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|ARM = Debug|ARM 14 | Debug|x64 = Debug|x64 15 | Debug|x86 = Debug|x86 16 | Release|Any CPU = Release|Any CPU 17 | Release|ARM = Release|ARM 18 | Release|x64 = Release|x64 19 | Release|x86 = Release|x86 20 | EndGlobalSection 21 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 22 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|ARM.ActiveCfg = Debug|ARM 25 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|ARM.Build.0 = Debug|ARM 26 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|x64.ActiveCfg = Debug|x64 27 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|x64.Build.0 = Debug|x64 28 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|x86.ActiveCfg = Debug|x86 29 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Debug|x86.Build.0 = Debug|x86 30 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|Any CPU.Deploy.0 = Release|Any CPU 33 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|ARM.ActiveCfg = Release|ARM 34 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|ARM.Build.0 = Release|ARM 35 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|x64.ActiveCfg = Release|x64 36 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|x64.Build.0 = Release|x64 37 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|x86.ActiveCfg = Release|x86 38 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA}.Release|x86.Build.0 = Release|x86 39 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|Any CPU.ActiveCfg = Debug|x86 40 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|ARM.ActiveCfg = Debug|ARM 41 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|ARM.Build.0 = Debug|ARM 42 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|ARM.Deploy.0 = Debug|ARM 43 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x64.ActiveCfg = Debug|x64 44 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x64.Build.0 = Debug|x64 45 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x64.Deploy.0 = Debug|x64 46 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x86.ActiveCfg = Debug|x86 47 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x86.Build.0 = Debug|x86 48 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Debug|x86.Deploy.0 = Debug|x86 49 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|Any CPU.ActiveCfg = Release|x86 50 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|ARM.ActiveCfg = Release|ARM 51 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|ARM.Build.0 = Release|ARM 52 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|ARM.Deploy.0 = Release|ARM 53 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x64.ActiveCfg = Release|x64 54 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x64.Build.0 = Release|x64 55 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x64.Deploy.0 = Release|x64 56 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x86.ActiveCfg = Release|x86 57 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x86.Build.0 = Release|x86 58 | {0BD40987-8086-4EEB-BB5F-1289864BBCCF}.Release|x86.Deploy.0 = Release|x86 59 | EndGlobalSection 60 | GlobalSection(SolutionProperties) = preSolution 61 | HideSolutionNode = FALSE 62 | EndGlobalSection 63 | EndGlobal 64 | -------------------------------------------------------------------------------- /TwitchDotNet/Clients/TwitchClient.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using TwitchDotNet.Enums; 3 | using TwitchDotNet.Helpers; 4 | using TwitchDotNet.Interfaces; 5 | using System.Net.Http; 6 | using Newtonsoft.Json; 7 | using System.Threading.Tasks; 8 | using System.Net; 9 | 10 | namespace TwitchDotNet.Clients { 11 | 12 | /// 13 | /// TwitchClient 14 | /// Provides an interface for an session to retrieve data from Twitch API's (where authentication is not required) 15 | /// 16 | public class TwitchClient : ITwitchClient { 17 | 18 | protected readonly HttpHelper httpHelperClient; 19 | 20 | /// 21 | /// Initialise HttpClient for requests 22 | /// 23 | /// Base Twitch API url 24 | /// Client Id header 25 | public TwitchClient(string _baseUrl, string _clientId) { 26 | httpHelperClient = new HttpHelper(_baseUrl, _clientId); 27 | } 28 | 29 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ 30 | 31 | /// 32 | /// Get Twitch Id by Twitch Username. 33 | /// https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api#translating-from-user-names-to-user-ids 34 | /// 35 | /// Twitch username 36 | /// 37 | public async Task GetIdByName(string _username) { 38 | var request = httpHelperClient.CreateHttpRequest($"kraken/users", HttpMethod.Get); 39 | httpHelperClient.AddQueryString(request, "login", _username); 40 | return await httpHelperClient.ExecuteRequest(request); 41 | } 42 | 43 | #endregion 44 | 45 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 46 | 47 | /// 48 | /// Gets a specified channel object. 49 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-by-id 50 | /// 51 | /// Channel Id 52 | /// 53 | public async Task GetChannel(string _channelId) { 54 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}", HttpMethod.Get); 55 | return await httpHelperClient.ExecuteRequest(request); 56 | } 57 | 58 | /// 59 | /// Gets a list of users who follow a specified channel, sorted by the date when they started following the channel (newest first, unless specified otherwise). 60 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-followers 61 | /// 62 | /// Channel Id 63 | /// Pagination info 64 | /// Sort direction 65 | /// 66 | public async Task GetChannelFollowers(string _channelId, Pagination _pagination, SortDirection _direction = SortDirection.desc) { 67 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/follows", HttpMethod.Get); 68 | httpHelperClient.AddQueryString(request, _pagination); 69 | httpHelperClient.AddQueryString(request, "direction", _direction.ToString()); 70 | return await httpHelperClient.ExecuteRequest(request); 71 | } 72 | 73 | /// 74 | /// Gets a list of teams to which a specified channel belongs. 75 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-teams 76 | /// 77 | /// Channel Id 78 | /// 79 | public async Task GetChannelTeams(string _channelId) { 80 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/teams", HttpMethod.Get); 81 | return await httpHelperClient.ExecuteRequest(request); 82 | } 83 | 84 | /// 85 | /// Gets a list of VODs (Video on Demand) from a specified channel. 86 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-videos 87 | /// 88 | /// Channel Id 89 | /// Pagination info 90 | /// Broadcast type 91 | /// Restrict VODs to specific language(s) 92 | /// Sort by 93 | /// 94 | public async Task GetChannelVideos(string _channelId, Pagination _pagination, BroadcastType _broadcastType = BroadcastType.highlight, List _languages = default(List), SortBy _sort = SortBy.time) { 95 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/videos", HttpMethod.Get); 96 | httpHelperClient.AddQueryString(request, _pagination); 97 | httpHelperClient.AddQueryString(request, "broadcast_type", _broadcastType.ToString()); 98 | if (_languages != default(List) && _languages.Count > 0) { httpHelperClient.AddQueryString(request, "language", string.Join(",", _languages)); } 99 | httpHelperClient.AddQueryString(request, "sort", _sort.ToString()); 100 | return await httpHelperClient.ExecuteRequest(request); 101 | } 102 | 103 | #endregion 104 | 105 | #region Chat - Https://dev.twitch.tv/docs/v5/reference/chat/ 106 | 107 | /// 108 | /// Gets a list of badges that can be used in chat for a specified channel. 109 | /// Https://dev.twitch.tv/docs/v5/reference/chat/#get-chat-badges-by-channel 110 | /// 111 | /// Channel Id 112 | /// 113 | public async Task GetChatBadgesByChannel(string _channelId) { 114 | var request = httpHelperClient.CreateHttpRequest($"kraken/chat/{_channelId}/badges", HttpMethod.Get); 115 | return await httpHelperClient.ExecuteRequest(request); 116 | } 117 | 118 | /// 119 | /// Gets all chat emoticons (not including their images) in a specified set. 120 | /// Https://dev.twitch.tv/docs/v5/reference/chat/#get-chat-emoticons-by-set 121 | /// 122 | /// Emote set 123 | /// 124 | public async Task GetChatEmoticonsBySet(List _emoteSets = default(List)) { 125 | var request = httpHelperClient.CreateHttpRequest($"kraken/chat/emoticon_images", HttpMethod.Get); 126 | if (_emoteSets != default(List) && _emoteSets.Count > 0) { httpHelperClient.AddQueryString(request, "emotesets", string.Join(",", _emoteSets)); } 127 | return await httpHelperClient.ExecuteRequest(request); 128 | } 129 | 130 | /// 131 | /// Gets all chat emoticons (including their images). 132 | /// Https://dev.twitch.tv/docs/v5/reference/chat/#get-all-chat-emoticons 133 | /// 134 | /// 135 | public async Task GetEmoticons() { 136 | var request = httpHelperClient.CreateHttpRequest($"kraken/chat/emoticons", HttpMethod.Get); 137 | return await httpHelperClient.ExecuteRequest(request); 138 | } 139 | 140 | #endregion 141 | 142 | #region Games - Https://dev.twitch.tv/docs/v5/reference/games/ 143 | 144 | /// 145 | /// Get games by number of current viewers. 146 | /// Https://dev.twitch.tv/docs/v5/reference/games/#get-top-games 147 | /// 148 | /// Pagination info 149 | /// 150 | public async Task GetTopGames(Pagination _pagination) { 151 | var request = httpHelperClient.CreateHttpRequest($"kraken/games/top", HttpMethod.Get); 152 | httpHelperClient.AddQueryString(request, _pagination); 153 | return await httpHelperClient.ExecuteRequest(request); 154 | } 155 | 156 | /// 157 | /// **UNOFFOCIAL API** https://discuss.dev.twitch.tv/t/game-following-requests/2186 158 | /// Get followed games by user. 159 | /// 160 | /// Username to retrieve followed games for 161 | /// Pagination info 162 | /// 163 | public async Task GetFollowedGames(string _username, Pagination _pagination) { 164 | var request = httpHelperClient.CreateHttpRequest($"api/users/{_username}/follows/games", HttpMethod.Get); 165 | httpHelperClient.AddQueryString(request, _pagination); 166 | return await httpHelperClient.ExecuteRequest(request); 167 | } 168 | 169 | #endregion 170 | 171 | #region Ingests - Https://dev.twitch.tv/docs/v5/reference/ingests/ 172 | 173 | /// 174 | /// Gets a list of ingest servers. 175 | /// Https://dev.twitch.tv/docs/v5/reference/ingests/#get-ingest-server-list 176 | /// 177 | /// 178 | public async Task GetIngests() { 179 | var request = httpHelperClient.CreateHttpRequest($"kraken/ingests", HttpMethod.Get); 180 | return await httpHelperClient.ExecuteRequest(request); 181 | } 182 | 183 | #endregion 184 | 185 | #region Search - Https://dev.twitch.tv/docs/v5/reference/search/ 186 | 187 | /// 188 | /// Search for channels based on the query parameter. 189 | /// Https://dev.twitch.tv/docs/v5/reference/search/#search-channels 190 | /// 191 | /// Search query 192 | /// Pagination info 193 | /// 194 | public async Task SearchChannels(string _query, Pagination _pagination) { 195 | var request = httpHelperClient.CreateHttpRequest($"kraken/search/channels", HttpMethod.Get); 196 | httpHelperClient.AddQueryString(request, "query", _query); 197 | httpHelperClient.AddQueryString(request, _pagination); 198 | return await httpHelperClient.ExecuteRequest(request); 199 | } 200 | 201 | /// 202 | /// Search for streams based on the query parameter. 203 | /// Https://dev.twitch.tv/docs/v5/reference/search/#search-streams 204 | /// 205 | /// Search query 206 | /// Pagination info 207 | /// If true, return only HLS streams, false, only non-HLS streams 208 | /// 209 | public async Task SearchStreams(string _query, Pagination _pagination, bool _hls = true) { 210 | var request = httpHelperClient.CreateHttpRequest($"kraken/search/streams", HttpMethod.Get); 211 | httpHelperClient.AddQueryString(request, "query", _query); 212 | httpHelperClient.AddQueryString(request, _pagination); 213 | httpHelperClient.AddQueryString(request, "hls", _hls.ToString()); 214 | return await httpHelperClient.ExecuteRequest(request); 215 | } 216 | 217 | /// 218 | /// Search for games based on the query parameter. 219 | /// Https://dev.twitch.tv/docs/v5/reference/search/#search-games 220 | /// 221 | /// Search query 222 | /// If true, return only games that are live on at least one channel, false, return all 223 | /// 224 | public async Task SearchGames(string _query, bool _live = false) { 225 | var request = httpHelperClient.CreateHttpRequest($"kraken/search/games", HttpMethod.Get); 226 | httpHelperClient.AddQueryString(request, "query", _query); 227 | httpHelperClient.AddQueryString(request, "live", _live.ToString()); 228 | return await httpHelperClient.ExecuteRequest(request); 229 | } 230 | 231 | #endregion 232 | 233 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 234 | 235 | /// 236 | /// Gets a list of all live streams. 237 | /// Https://dev.twitch.tv/docs/v5/reference/streams/#get-all-streams 238 | /// 239 | /// Pagination info 240 | /// Restrict streams to specific game 241 | /// Restrict streams to specific channel(s) (by Id) 242 | /// Stream type 243 | /// Restrict VODs to specific language(s) 244 | /// 245 | public async Task GetStreams(Pagination _pagination, string _game = default(string), List _channels = default(List), StreamType _streamType = StreamType.live, List _languages = default(List)) { 246 | var request = httpHelperClient.CreateHttpRequest($"kraken/streams", HttpMethod.Get); 247 | httpHelperClient.AddQueryString(request, _pagination); 248 | if (!string.IsNullOrEmpty(_game)) { httpHelperClient.AddQueryString(request, "game", _game); } 249 | if (_channels != default(List) && _channels.Count > 0) { httpHelperClient.AddQueryString(request, "channel", string.Join(",", _channels)); } 250 | httpHelperClient.AddQueryString(request, "stream_type", _streamType.ToString()); 251 | if (_languages != default(List) && _languages.Count > 0) { httpHelperClient.AddQueryString(request, "language", string.Join(",", _languages)); } 252 | return await httpHelperClient.ExecuteRequest(request); 253 | } 254 | 255 | /// 256 | /// Gets stream information (the stream object) for a specified channel. 257 | /// Https://dev.twitch.tv/docs/v5/reference/streams/#get-stream-by-channel 258 | /// 259 | /// Channel Id 260 | /// Stream type 261 | /// 262 | public async Task GetStream(string _channelId, StreamType _streamType = StreamType.live) { 263 | var request = httpHelperClient.CreateHttpRequest($"kraken/streams/{_channelId}", HttpMethod.Get); 264 | httpHelperClient.AddQueryString(request, "stream_type", _streamType.ToString()); 265 | return await httpHelperClient.ExecuteRequest(request); 266 | } 267 | 268 | /// 269 | /// Gets a list of all featured live streams. 270 | /// Https://dev.twitch.tv/docs/v5/reference/streams/#get-featured-streams 271 | /// 272 | /// Pagination info 273 | /// 274 | public async Task GetFeaturedStreams(Pagination _pagination) { 275 | var request = httpHelperClient.CreateHttpRequest($"kraken/streams/featured", HttpMethod.Get); 276 | httpHelperClient.AddQueryString(request, _pagination); 277 | return await httpHelperClient.ExecuteRequest(request); 278 | } 279 | 280 | /// 281 | /// Gets a summary of all live streams. 282 | /// Https://dev.twitch.tv/docs/v5/reference/streams/#get-streams-summary 283 | /// 284 | /// Restrict summary to specific game 285 | /// 286 | public async Task GetStreamsSummary(string _game = default(string)) { 287 | var request = httpHelperClient.CreateHttpRequest($"kraken/streams/summary", HttpMethod.Get); 288 | if (!string.IsNullOrEmpty(_game)) { httpHelperClient.AddQueryString(request, "game", _game); } 289 | return await httpHelperClient.ExecuteRequest(request); 290 | } 291 | 292 | #endregion 293 | 294 | #region Teams - Https://dev.twitch.tv/docs/v5/reference/teams/ 295 | 296 | /// 297 | /// Gets all of the active teams. 298 | /// Https://dev.twitch.tv/docs/v5/reference/teams/#get-all-teams 299 | /// 300 | /// Pagination info 301 | /// 302 | public async Task GetTeams(Pagination _pagination) { 303 | var request = httpHelperClient.CreateHttpRequest($"kraken/teams", HttpMethod.Get); 304 | httpHelperClient.AddQueryString(request, _pagination); 305 | return await httpHelperClient.ExecuteRequest(request); 306 | } 307 | 308 | /// 309 | /// Gets a single team object. 310 | /// Https://dev.twitch.tv/docs/v5/reference/teams/#get-team 311 | /// 312 | /// Team name 313 | /// 314 | public async Task GetTeam(string _teamName) { 315 | var request = httpHelperClient.CreateHttpRequest($"kraken/teams/{_teamName}", HttpMethod.Get); 316 | return await httpHelperClient.ExecuteRequest(request); 317 | } 318 | 319 | #endregion 320 | 321 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 322 | 323 | /// 324 | /// Gets a specified user object. 325 | /// Https://dev.twitch.tv/docs/v5/reference/users/#get-user-by-id 326 | /// 327 | /// User Id 328 | /// 329 | public async Task GetUser(string _userId) { 330 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}", HttpMethod.Get); 331 | return await httpHelperClient.ExecuteRequest(request); 332 | } 333 | 334 | /// 335 | /// Gets a list of all channels followed by a specified user, sorted by the date when they started following each channel. 336 | /// Https://dev.twitch.tv/docs/v5/reference/users/#get-user-follows 337 | /// 338 | /// User Id 339 | /// Pagination info 340 | /// Sort direction 341 | /// Sort key 342 | /// 343 | public async Task GetUserFollowedChannels(string _userId, Pagination _pagination, SortDirection _direction = SortDirection.desc, SortKey _sortKey = SortKey.created_at) { 344 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/follows/channels", HttpMethod.Get); 345 | httpHelperClient.AddQueryString(request, _pagination); 346 | httpHelperClient.AddQueryString(request, "direction", _direction.ToString()); 347 | httpHelperClient.AddQueryString(request, "sortby", _sortKey.ToString()); 348 | return await httpHelperClient.ExecuteRequest(request); 349 | } 350 | 351 | /// 352 | /// Checks if a specified user follows a specified channel. 353 | /// Https://dev.twitch.tv/docs/v5/reference/users/#check-user-follows-by-channel 354 | /// 355 | /// User Id 356 | /// Channel Id to check 357 | /// 358 | public async Task CheckUserFollowsByChannel(string _userId, string _channelId) { 359 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/follows/channels/{_channelId}", HttpMethod.Get); 360 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.OK | HttpStatusCode.NotFound); 361 | } 362 | 363 | /// 364 | /// ** Unofficial API ** 365 | /// Checks if a specified user follows a specified game. 366 | /// 367 | /// Username 368 | /// Game to check 369 | /// 370 | public async Task CheckUserFollowsByGame(string _username, string _game) { 371 | var request = httpHelperClient.CreateHttpRequest($"api/users/{_username}/follows/games/{_game}", HttpMethod.Get); 372 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.OK | HttpStatusCode.NotFound); 373 | } 374 | 375 | #endregion 376 | 377 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 378 | 379 | /// 380 | /// Gets a specified video object. 381 | /// Https://dev.twitch.tv/docs/v5/reference/videos/#get-video 382 | /// 383 | /// Video Id 384 | /// 385 | public async Task GetVideo(string _videoId) { 386 | var request = httpHelperClient.CreateHttpRequest($"kraken/videos/{_videoId}", HttpMethod.Get); 387 | return await httpHelperClient.ExecuteRequest(request); 388 | } 389 | 390 | /// 391 | /// Gets the top videos based on viewcount. 392 | /// Https://dev.twitch.tv/docs/v5/reference/videos/#get-top-videos 393 | /// 394 | /// Pagination info 395 | /// Game name 396 | /// Period range 397 | /// Broadcast type 398 | /// 399 | public async Task GetTopVideos(Pagination _pagination, string _game = default(string), Period _period = Period.week, BroadcastType _broadcastType = BroadcastType.highlight) { 400 | var request = httpHelperClient.CreateHttpRequest($"kraken/videos/top", HttpMethod.Get); 401 | httpHelperClient.AddQueryString(request, _pagination); 402 | if (!string.IsNullOrEmpty(_game)) { httpHelperClient.AddQueryString(request, "game", _game); } 403 | httpHelperClient.AddQueryString(request, "period", _period.ToString()); 404 | httpHelperClient.AddQueryString(request, "broadcast_type", _broadcastType.ToString()); 405 | return await httpHelperClient.ExecuteRequest(request); 406 | } 407 | 408 | #endregion 409 | } 410 | } 411 | -------------------------------------------------------------------------------- /TwitchDotNet/Clients/TwitchClientAuthenticated.cs: -------------------------------------------------------------------------------- 1 | using TwitchDotNet.Enums; 2 | using TwitchDotNet.Helpers; 3 | using TwitchDotNet.Interfaces; 4 | using System.Net.Http; 5 | using System; 6 | using Newtonsoft.Json.Linq; 7 | using System.Collections.Generic; 8 | using Newtonsoft.Json; 9 | using System.Text; 10 | using System.Net; 11 | using System.Threading.Tasks; 12 | 13 | namespace TwitchDotNet.Clients { 14 | 15 | /// 16 | /// Authenticated TwitchClient 17 | /// Provides an interface for an authenticated session to retrieve data from Twitch API's (where authentication is required) 18 | /// 19 | public class TwitchClientAuthenticated : TwitchClient, ITwitchClientAuthenticated, ITwitchClient { 20 | 21 | /// 22 | /// Initialise HttpClient for authenticated requests 23 | /// 24 | /// Base Twitch API url 25 | /// Client Id header 26 | /// OAuth Token header 27 | public TwitchClientAuthenticated(string _baseUrl, string _clientId, string _oauthToken) : base(_baseUrl, _clientId) { 28 | // Add authentication header to HttpHelper client 29 | httpHelperClient.AddHttpClientHeader("Authorization", $"OAuth {_oauthToken}"); 30 | } 31 | 32 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ 33 | 34 | /// 35 | /// Check token status using Root Url. 36 | /// https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api#root-url 37 | /// 38 | /// Token status 39 | public async Task GetRoot() { 40 | var request = httpHelperClient.CreateHttpRequest($"kraken", HttpMethod.Get); 41 | return await httpHelperClient.ExecuteRequest(request); 42 | } 43 | 44 | #endregion 45 | 46 | #region ChannelFeed - Https://dev.twitch.tv/docs/v5/reference/channel-feed/ 47 | 48 | /// 49 | /// Gets posts from a specified channel feed. 50 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#get-multiple-feed-posts 51 | /// 52 | /// Channel Id 53 | /// Cursor Pagination info 54 | /// Number of comments to retrieve 55 | /// 56 | public async Task GetChannelFeedPosts(string _channelId, CursorPagination _pagination, long _comments = 5) { 57 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts", HttpMethod.Get); 58 | httpHelperClient.AddQueryString(request, _pagination); 59 | httpHelperClient.AddQueryString(request, "comments", _comments.ToString()); 60 | return await httpHelperClient.ExecuteRequest(request); 61 | } 62 | 63 | /// 64 | /// Gets a specified post from a specified channel feed. 65 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#get-feed-post 66 | /// 67 | /// Channel Id 68 | /// Post Id 69 | /// Number of comments to retrieve 70 | /// 71 | public async Task GetChannelFeedPost(string _channelId, string _postId, long _comments = 5) { 72 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}", HttpMethod.Get); 73 | httpHelperClient.AddQueryString(request, "comments", _comments.ToString()); 74 | return await httpHelperClient.ExecuteRequest(request); 75 | } 76 | 77 | /// 78 | /// Creates a post in a specified channel feed. 79 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#create-feed-post 80 | /// 81 | /// Channel Id 82 | /// Content of the post 83 | /// If true, share a link to the post on the channel's Twitter feed (if connected) 84 | /// 85 | public async Task CreateChannelFeedPost(string _channelId, string _content, bool _share = false) { 86 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts", HttpMethod.Post); 87 | httpHelperClient.AddQueryString(request, "content", _content); 88 | httpHelperClient.AddQueryString(request, "share", _share.ToString()); 89 | return await httpHelperClient.ExecuteRequest(request); 90 | } 91 | 92 | /// 93 | /// Deletes a specified post in a specified channel feed. 94 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#delete-feed-post 95 | /// 96 | /// Channel Id 97 | /// Post Id to delete 98 | /// 99 | public async Task DeleteChannelFeedPost(string _channelId, string _postId) { 100 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}", HttpMethod.Delete); 101 | return await httpHelperClient.ExecuteRequest(request); ; } 102 | 103 | /// 104 | /// reates a reaction to a specified post in a specified channel feed. 105 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#create-reaction-to-a-feed-post 106 | /// 107 | /// Channel Id 108 | /// Post Id 109 | /// Reaction emote to create 110 | /// 111 | public async Task CreateReactionToChannelFeedPost(string _channelId, string _postId, string _emoteId) { 112 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/reactions", HttpMethod.Post); 113 | httpHelperClient.AddQueryString(request, "emote_id", _emoteId); 114 | return await httpHelperClient.ExecuteRequest(request); 115 | } 116 | 117 | /// 118 | /// Deletes a specified reaction to a specified post in a specified channel feed. 119 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#delete-reaction-to-a-feed-post 120 | /// 121 | /// Channel Id 122 | /// Post Id 123 | /// Reaction emote to delete 124 | /// 125 | public async Task DeleteReactionToChannelFeedPost(string _channelId, string _postId, string _emoteId) { 126 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/reactions", HttpMethod.Delete); 127 | httpHelperClient.AddQueryString(request, "emote_id", _emoteId); 128 | return await httpHelperClient.ExecuteRequest(request); 129 | } 130 | 131 | /// 132 | /// Gets all comments on a specified post in a specified channel feed. 133 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#get-feed-comments 134 | /// 135 | /// Channel Id 136 | /// Post Id 137 | /// Pagination info 138 | /// 139 | public async Task GetChannelFeedPostComments(string _channelId, string _postId, CursorPagination _pagination) { 140 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/comments", HttpMethod.Get); 141 | httpHelperClient.AddQueryString(request, _pagination); 142 | return await httpHelperClient.ExecuteRequest(request); 143 | } 144 | 145 | /// 146 | /// Creates a comment to a specified post in a specified channel feed. 147 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#create-feed-comment 148 | /// 149 | /// Channel Id 150 | /// Post Id 151 | /// Content of the comment 152 | /// 153 | public async Task CreateChannelFeedPostComment(string _channelId, string _postId, string _content) { 154 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/comments", HttpMethod.Post); 155 | httpHelperClient.AddQueryString(request, "content", _content); 156 | return await httpHelperClient.ExecuteRequest(request); 157 | } 158 | 159 | /// 160 | /// Deletes a specified comment on a specified post in a specified channel feed. 161 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#delete-feed-comment 162 | /// 163 | /// Channel Id 164 | /// Post Id 165 | /// Comment Id to delete 166 | /// 167 | public async Task DeleteChannelFeedPostComment(string _channelId, string _postId, string _commentId) { 168 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/comments/{_commentId}", HttpMethod.Delete); 169 | return await httpHelperClient.ExecuteRequest(request); 170 | } 171 | 172 | /// 173 | /// Creates a reaction to a specified comment on a specified post in a specified channel feed. 174 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#create-reaction-to-a-feed-comment 175 | /// 176 | /// Channel Id 177 | /// Post Id 178 | /// Comment Id 179 | /// Reaction emote to create 180 | /// 181 | public async Task CreateReactionToChannelFeedPostComment(string _channelId, string _postId, string _commentId, string _emoteId) { 182 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/comments/{_commentId}/reactions", HttpMethod.Post); 183 | httpHelperClient.AddQueryString(request, "emote_id", _emoteId); 184 | return await httpHelperClient.ExecuteRequest(request); 185 | } 186 | 187 | /// 188 | /// Deletes a reaction to a specified comment on a specified post in a specified channel feed. 189 | /// Https://dev.twitch.tv/docs/v5/reference/channel-feed/#delete-reaction-to-a-feed-comment 190 | /// 191 | /// Channel Id 192 | /// Post Id 193 | /// Comment Id 194 | /// Reaction emote to delete 195 | /// 196 | public async Task DeleteReactionToChannelFeedPostComment(string _channelId, string _postId, string _commentId, string _emoteId) { 197 | var request = httpHelperClient.CreateHttpRequest($"kraken/feed/{_channelId}/posts/{_postId}/comments/{_commentId}/reactions", HttpMethod.Delete); 198 | httpHelperClient.AddQueryString(request, "emote_id", _emoteId); 199 | return await httpHelperClient.ExecuteRequest(request); 200 | } 201 | 202 | #endregion 203 | 204 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 205 | 206 | /// 207 | /// Gets a channel object based on the OAuth token provided. 208 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel 209 | /// 210 | /// 211 | public async Task GetChannel() { 212 | var request = httpHelperClient.CreateHttpRequest($"kraken/channel", HttpMethod.Get); 213 | return await httpHelperClient.ExecuteRequest(request); 214 | } 215 | 216 | /// 217 | /// Updates specified properties of a specified channel. 218 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#update-channel 219 | /// 220 | /// Channel Id 221 | /// Broadcast status 222 | /// Game name 223 | /// Channel delay in seconds 224 | /// If true, the channel's feed is turned on, false otherwise 225 | /// 226 | public async Task UpdateChannel(string _channelId, string _status, string _game, string _delay, bool _channelFeedEnabled) { 227 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}", HttpMethod.Put); 228 | 229 | // Only add as property if it is explicitly set, otherwise we will be overriding when not intending to 230 | var properties = new JObject(); 231 | properties["channel"] = new JObject(); 232 | if (_status != null) { properties["channel"]["status"] = _status; } 233 | if (_game != null) { properties["channel"]["game"] = _game; } 234 | if (_delay != null) { properties["channel"]["delay"] = _delay; } 235 | if (_channelFeedEnabled) { properties["channel"]["channel_feed_enabled"] = _channelFeedEnabled.ToString(); } 236 | 237 | request.Content = new StringContent(properties.ToString(), Encoding.UTF8,"application/json"); 238 | return await httpHelperClient.ExecuteRequest(request); 239 | } 240 | 241 | /// 242 | /// Gets a list of users who are editors for a specified channel. 243 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-editors 244 | /// 245 | /// Channel Id 246 | /// 247 | public async Task GetChannelEditors(string _channelId) { 248 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/editors", HttpMethod.Get); 249 | return await httpHelperClient.ExecuteRequest(request); 250 | } 251 | 252 | /// 253 | /// Gets a list of users subscribed to a specified channel, sorted by the date when they subscribed. 254 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#get-channel-subscribers 255 | /// 256 | /// Channel Id 257 | /// Pagination info 258 | /// Sort direction 259 | /// 260 | public async Task GetChannelSubscribers(string _channelId, Pagination _pagination, SortDirection _direction = SortDirection.asc) { 261 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/subscriptions", HttpMethod.Get); 262 | httpHelperClient.AddQueryString(request, _pagination); 263 | httpHelperClient.AddQueryString(request, "direction", _direction.ToString()); 264 | return await httpHelperClient.ExecuteRequest(request); 265 | } 266 | 267 | /// 268 | /// Checks if a specified channel has a specified user subscribed to it. 269 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#check-channel-subscription-by-user 270 | /// 271 | /// Channel Id 272 | /// Target User Id to check 273 | /// 274 | public async Task CheckChannelSubscriptionByUser(string _channelId, string _targetUserId) { 275 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/subscriptions/{_targetUserId}", HttpMethod.Get); 276 | // 422 Unprocessable Entity (no subscription program), 404 Not Found when user is not a subscriber of the channel 277 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.OK | (HttpStatusCode)422 | HttpStatusCode.NotFound); 278 | } 279 | 280 | /// 281 | /// Starts a commercial (advertisement) on a specified channel. 282 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#start-channel-commercial 283 | /// 284 | /// Channel Id 285 | /// 286 | public async Task StartChannelCommercial(string _channelId) { 287 | var request = httpHelperClient.CreateHttpRequest($"kraken/channel/{_channelId}/commercial", HttpMethod.Post); 288 | return await httpHelperClient.ExecuteRequest(request); 289 | } 290 | 291 | /// 292 | /// Deletes the stream key for a specified channel. 293 | /// Https://dev.twitch.tv/docs/v5/reference/channels/#reset-channel-stream-key 294 | /// 295 | /// Channel Id 296 | /// 297 | public async Task ResetChannelStreamKey(string _channelId) { 298 | var request = httpHelperClient.CreateHttpRequest($"kraken/channels/{_channelId}/stream_key", HttpMethod.Delete); 299 | return await httpHelperClient.ExecuteRequest(request); 300 | } 301 | 302 | #endregion 303 | 304 | #region Game - Unofficial https://discuss.dev.twitch.tv/t/game-following-requests/2186 305 | 306 | /// 307 | /// Adds a specified user to the followers of a specified game. 308 | /// 309 | /// 310 | /// 311 | /// 312 | public async Task FollowGame(string _username, string _game) { 313 | var request = httpHelperClient.CreateHttpRequest($"api/users/{_username}/follows/games/{_game}", HttpMethod.Put); 314 | return await httpHelperClient.ExecuteRequest(request); 315 | } 316 | 317 | /// 318 | /// Deletes a specified user from the followers of a specified game. 319 | /// 320 | /// 321 | /// 322 | /// 323 | public async Task UnfollowGame(string _username, string _game) { 324 | var request = httpHelperClient.CreateHttpRequest($"api/users/{_username}/follows/games/{_game}", HttpMethod.Delete); 325 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.NoContent); 326 | } 327 | 328 | #endregion 329 | 330 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 331 | 332 | /// 333 | /// Gets the list of live streams a user follows based on the OAuth token provided. 334 | /// Https://dev.twitch.tv/docs/v5/reference/streams/#get-followed-streams 335 | /// 336 | /// Pagination info 337 | /// Stream type 338 | /// 339 | public async Task GetFollowedStreams(Pagination _pagination, StreamType _streamType = StreamType.live) { 340 | var request = httpHelperClient.CreateHttpRequest($"kraken/streams/followed", HttpMethod.Get); 341 | httpHelperClient.AddQueryString(request, _pagination); 342 | httpHelperClient.AddQueryString(request, "stream_type", _streamType.ToString()); 343 | return await httpHelperClient.ExecuteRequest(request); 344 | } 345 | 346 | #endregion 347 | 348 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 349 | 350 | /// 351 | /// Gets a user object based on the OAuth token provided. 352 | /// Https://dev.twitch.tv/docs/v5/reference/users/#get-user 353 | /// 354 | /// 355 | public async Task GetUser() { 356 | var request = httpHelperClient.CreateHttpRequest($"kraken/user", HttpMethod.Get); 357 | return await httpHelperClient.ExecuteRequest(request); 358 | } 359 | 360 | /// 361 | /// Gets a list of the emojis and emoticons that the specified user can use in chat. 362 | /// Https://dev.twitch.tv/docs/v5/reference/users/#get-user-emotes 363 | /// 364 | /// User Id 365 | /// 366 | public async Task GetUserEmotes(string _userId) { 367 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/emotes", HttpMethod.Get); 368 | return await httpHelperClient.ExecuteRequest(request); 369 | } 370 | 371 | /// 372 | /// Checks if a specified user is subscribed to a specified channel. 373 | /// Https://dev.twitch.tv/docs/v5/reference/users/#check-user-subscription-by-channel 374 | /// 375 | /// User Id 376 | /// Channel Id to check 377 | /// 378 | public async Task CheckUserSubscriptionByChannel(string _userId, string _channelId) { 379 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/subscriptions/{_channelId}", HttpMethod.Get); 380 | // 422 Unprocessable Entity (no subscription program), 404 Not Found when user is not a subscriber of the channel 381 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.OK | (HttpStatusCode)422 | HttpStatusCode.NotFound); 382 | } 383 | 384 | /// 385 | /// Adds a specified user to the followers of a specified channel. 386 | /// Https://dev.twitch.tv/docs/v5/reference/users/#follow-channel 387 | /// 388 | /// User Id 389 | /// Target Channel to follow 390 | /// If true, the user gets email or push notifications (depending on his notification settings) when the channel goes live, false otherwise 391 | /// 392 | public async Task FollowChannel(string _userId, string _targetChannelId, bool _enableNotifications = false) { 393 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/follows/channels/{_targetChannelId}", HttpMethod.Put); 394 | return await httpHelperClient.ExecuteRequest(request); 395 | } 396 | 397 | /// 398 | /// Deletes a specified user from the followers of a specified channel. 399 | /// Https://dev.twitch.tv/docs/v5/reference/users/#unfollow-channel 400 | /// 401 | /// User Id 402 | /// Target Channel to unfollow 403 | /// 404 | public async Task UnfollowChannel(string _userId, string _targetChannelId) { 405 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/follows/channels/{_targetChannelId}", HttpMethod.Delete); 406 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.NoContent); 407 | } 408 | 409 | /// 410 | /// Gets a user’s block list. 411 | /// Https://dev.twitch.tv/docs/v5/reference/users/#get-user-block-list 412 | /// 413 | /// User Id 414 | /// Pagination info 415 | /// 416 | public async Task GetUserBlockList(string _userId, Pagination _pagination) { 417 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/blocks", HttpMethod.Get); 418 | httpHelperClient.AddQueryString(request, _pagination); 419 | return await httpHelperClient.ExecuteRequest(request); 420 | } 421 | 422 | /// 423 | /// Blocks the target user. 424 | /// Https://dev.twitch.tv/docs/v5/reference/users/#block-user 425 | /// 426 | /// User Id 427 | /// Target User Id to block 428 | /// 429 | public async Task BlockUser(string _userId, string _targetUserId) { 430 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/blocks/{_targetUserId}", HttpMethod.Put); 431 | return await httpHelperClient.ExecuteRequest(request); 432 | } 433 | 434 | /// 435 | /// Unblocks the target user. 436 | /// Https://dev.twitch.tv/docs/v5/reference/users/#unblock-user 437 | /// 438 | /// User Id 439 | /// Target User Id to unblock 440 | /// 441 | public async Task UnblockUser(string _userId, string _targetUserId) { 442 | var request = httpHelperClient.CreateHttpRequest($"kraken/users/{_userId}/blocks/{_targetUserId}", HttpMethod.Delete); 443 | return await httpHelperClient.ExecuteRequest(request, HttpStatusCode.NoContent); 444 | } 445 | 446 | #endregion 447 | 448 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 449 | 450 | /// 451 | /// Gets the videos from channels the user is following based on the OAuth token provided. 452 | /// Https://dev.twitch.tv/docs/v5/reference/videos/#get-followed-videos 453 | /// 454 | /// Pagination info 455 | /// Broadcast type 456 | /// 457 | public async Task GetFollowedVideos(Pagination _pagination, BroadcastType _broadcastType = BroadcastType.highlight) { 458 | var request = httpHelperClient.CreateHttpRequest($"kraken/videos/followed", HttpMethod.Get); 459 | httpHelperClient.AddQueryString(request, _pagination); 460 | httpHelperClient.AddQueryString(request, "broadcast_type", _broadcastType.ToString()); 461 | return await httpHelperClient.ExecuteRequest(request); 462 | } 463 | 464 | #endregion 465 | } 466 | } 467 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/BroadcastType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for Broadcast Type 11 | /// 12 | public enum BroadcastType { 13 | archive, 14 | highlight, 15 | upload 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/Period.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for valid period ranges 11 | /// 12 | public enum Period { 13 | day, 14 | week, 15 | month, 16 | all 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/SortBy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for Sorting By 11 | /// 12 | public enum SortBy { 13 | views, 14 | time 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/SortDirection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for Sorting Direction 11 | /// 12 | public enum SortDirection { 13 | asc, 14 | desc 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/SortKey.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for Sorting Key 11 | /// 12 | public enum SortKey { 13 | created_at, 14 | last_broadcast, 15 | login 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TwitchDotNet/Enums/StreamType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Enums { 8 | 9 | /// 10 | /// Enum for Stream Type 11 | /// 12 | public enum StreamType { 13 | live, 14 | playlist, // VODs 15 | all 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TwitchDotNet/Helpers/CursorPagination.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Helpers { 8 | 9 | /// 10 | /// Helper class to perform Cursor Pagination with API requests 11 | /// 12 | public class CursorPagination { 13 | 14 | private long _limit = 25; 15 | private string _cursor = default(string); 16 | 17 | /// 18 | /// Limit 19 | /// 20 | public long Limit { 21 | get { return _limit; } 22 | } 23 | /// 24 | /// Cursor 25 | /// 26 | public string Cursor { 27 | get { return _cursor; } 28 | set { _cursor = value; } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TwitchDotNet/Helpers/HttpHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Net.Http; 7 | using System.Net; 8 | using System.Diagnostics; 9 | using Newtonsoft.Json; 10 | 11 | namespace TwitchDotNet.Helpers { 12 | 13 | /// 14 | /// Helper class to perform Http REST Requests 15 | /// 26/12/2016 - RestSharp doesn't support UWP, hence creating my own (basic) helper class 16 | /// 17 | public class HttpHelper { 18 | 19 | private readonly string baseUrl; 20 | private readonly HttpClient httpClient = new HttpClient(); 21 | 22 | /// 23 | /// Initialise httpClient 24 | /// 25 | /// Base Url for all Http requests 26 | /// Client Id Header 27 | public HttpHelper(string _baseUrl, string _clientId) { 28 | this.baseUrl = _baseUrl; 29 | 30 | // Attach default headers to Request 31 | httpClient.DefaultRequestHeaders.Add("Accept", "application/vnd.twitchtv.v5+json"); 32 | httpClient.DefaultRequestHeaders.Add("Client-ID", _clientId); 33 | } 34 | 35 | /// 36 | /// Create a HttpRequest 37 | /// 38 | /// HttpRequest url (+baseUrl) 39 | /// HttpRequest type 40 | /// A HttpRequest 41 | public HttpRequestMessage CreateHttpRequest(string _url, HttpMethod _requestType) { 42 | return new HttpRequestMessage(_requestType, new Uri($"{this.baseUrl}/{_url}")); 43 | } 44 | 45 | /// 46 | /// Send a HttpRequestMessage 47 | /// 48 | /// HttpRequestMessage to send 49 | /// HttpStatusCodes that indicate success 50 | /// Object representing returned content 51 | public async Task ExecuteRequest(HttpRequestMessage _request, HttpStatusCode _successCodes = HttpStatusCode.OK) { 52 | var response = await httpClient.SendAsync(_request).ConfigureAwait(false); 53 | try { 54 | // Ensure successful response (indicated by _successCodes) 55 | if ((_successCodes & response.StatusCode) == response.StatusCode) { 56 | // Read response content as byte array and decode as UTF-8 57 | var response_buffer = await response.Content.ReadAsByteArrayAsync(); 58 | var response_string = Encoding.UTF8.GetString(response_buffer, 0, response_buffer.Length); 59 | return JsonConvert.DeserializeObject(response_string) ?? string.Empty; // Return empty string if get here, as it was expected (see: _successCodes) 60 | } else { 61 | throw new Exception($"HttpRequest did not indicate success. Error Code: {response.StatusCode}"); 62 | } 63 | } catch (Exception ex) { 64 | Debug.WriteLine($"An error occurred while sending off a HttpRequest.\n\n{ex.ToString()}"); 65 | } 66 | return null; 67 | } 68 | 69 | /// 70 | /// Add header to HttpClient 71 | /// 72 | /// Header Key 73 | /// Header Value 74 | public void AddHttpClientHeader(string _key, string _value) { 75 | // Only add header if _value is not empty 76 | if (!string.IsNullOrEmpty(_value)) { 77 | httpClient.DefaultRequestHeaders.Add(_key, _value); 78 | } 79 | } 80 | 81 | /// 82 | /// Add Query String to a Http Request. 83 | /// 84 | /// The HttpRequest 85 | /// Query String Key 86 | /// Query String Value 87 | public void AddQueryString(HttpRequestMessage _request, string _key, string _value) { 88 | 89 | // Only add query string if _value is not empty 90 | if (!string.IsNullOrEmpty(_value)) { 91 | UriBuilder uriBuilder = new UriBuilder(_request.RequestUri); 92 | 93 | // URI Escape _value 94 | string _escapedValue = Uri.EscapeDataString(_value); 95 | 96 | // Build query string 97 | if (uriBuilder.Query != null && uriBuilder.Query.Length > 1) { // Append to existing query string 98 | uriBuilder.Query = $"{uriBuilder.Query.Substring(1)}&{_key}={_escapedValue}"; // ..?..&key=value 99 | } else { // New query string 100 | uriBuilder.Query = $"{_key}={_escapedValue}"; 101 | } 102 | 103 | // Assign Uri to original request 104 | _request.RequestUri = uriBuilder.Uri; 105 | } 106 | } 107 | 108 | /// 109 | /// Adds pagination info as query string to a Http Request 110 | /// 111 | /// The HttpRequest 112 | /// Pagination info 113 | public void AddQueryString(HttpRequestMessage _request, Pagination _pagination) { 114 | this.AddQueryString(_request, "limit", _pagination.Limit.ToString()); 115 | this.AddQueryString(_request, "offset", _pagination.Offset.ToString()); 116 | } 117 | 118 | /// 119 | /// Adds cursor pagination info as query string to a Http Request 120 | /// 121 | /// The HttpRequest 122 | /// Pagination info 123 | public void AddQueryString(HttpRequestMessage _request, CursorPagination _pagination) { 124 | this.AddQueryString(_request, "limit", _pagination.Limit.ToString()); 125 | this.AddQueryString(_request, "cursor", _pagination.Cursor); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /TwitchDotNet/Helpers/OAuth2Broker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.Linq; 5 | using System.Net.Http; 6 | using System.Text; 7 | using System.Text.RegularExpressions; 8 | using System.Threading.Tasks; 9 | using Windows.ApplicationModel.Resources; 10 | using Windows.Security.Authentication.Web; 11 | using Windows.UI.Core; 12 | 13 | namespace TwitchDotNet.Helpers { 14 | 15 | /// 16 | /// Broker for OAuth2 authentication 17 | /// 18 | public static class OAuth2Broker { 19 | 20 | /// 21 | /// Authenticate against OAuth2 using WebAuthenticationBroker for a valid access token 22 | /// 23 | /// Base Twitch API Url 24 | /// Client Id 25 | /// Authentication Redirect Uri 26 | /// Authentication Scopes 27 | /// An access token to use with API requests 28 | public static async Task Authenticate(string _baseUrl, string _clientId, string _redirectUri, string _scopes) { 29 | // Create request (use httpHelper to build query string) 30 | var httpHelper = new HttpHelper(_baseUrl, _clientId); 31 | var request = httpHelper.CreateHttpRequest("kraken/oauth2/authenticate", HttpMethod.Get); 32 | httpHelper.AddQueryString(request, "client_id", _clientId); // Add client_id manually so it is part of the query string (required for WAB startUri below) 33 | httpHelper.AddQueryString(request, "action", "authorize"); 34 | httpHelper.AddQueryString(request, "response_type", "token"); 35 | httpHelper.AddQueryString(request, "redirect_uri", _redirectUri); 36 | httpHelper.AddQueryString(request, "scope", _scopes); 37 | //httpHelper.AddQueryString(request, "state", ""); // TODO? 38 | 39 | // Now use request.Uri to authenticate with WebAuthenticationBroker (OAuth2 for UWP applications) 40 | try { 41 | // Define where the WebAuthenticationBroker should start and end 42 | var startUri = request.RequestUri; 43 | var endUri = new Uri(_redirectUri); 44 | 45 | // Begin authorization process 46 | WebAuthenticationResult WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None, startUri, endUri); 47 | if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success) { 48 | // Success, so extract access token from result 49 | string fragment = WebAuthenticationResult.ResponseData; 50 | 51 | // Exit if user denies access (response was a twitch-cancel button (i.e. html user cancel)) 52 | // ?error=&error_description= 53 | Match match = Regex.Match(fragment, "error=(?.*)&error_description"); 54 | string errorString = match.Groups["reason"].Value; 55 | if (errorString.Equals("access_denied")) { 56 | throw new Exception("Access denied"); 57 | } 58 | 59 | // Attempt to retrieve access token (successfully logged in) 60 | // #access_token= 61 | match = Regex.Match(fragment, "#access_token=(?.*)&scope="); 62 | string oauth_token = match.Groups["token"].Value; 63 | 64 | // Return oauth_token 65 | if (!string.IsNullOrEmpty(oauth_token)) { 66 | return oauth_token; 67 | } else { 68 | throw new Exception("Returned OAuth Token was empty. Are you passing in the correct Client_Id?"); 69 | } 70 | } else if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.ErrorHttp) { 71 | throw new Exception(WebAuthenticationResult.ResponseErrorDetail.ToString()); 72 | } else if (WebAuthenticationResult.ResponseStatus != WebAuthenticationStatus.UserCancel) { 73 | // Show error if not user cancel 74 | throw new Exception(WebAuthenticationResult.ResponseStatus.ToString()); 75 | } 76 | } catch (Exception ex) { 77 | Debug.WriteLine($"An error occurred while authenticating.\n\n{ex.ToString()}"); 78 | } 79 | return string.Empty; 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /TwitchDotNet/Helpers/Pagination.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace TwitchDotNet.Helpers { 8 | 9 | /// 10 | /// Helper class to perform Pagination with API requests 11 | /// 12 | public class Pagination { 13 | 14 | private long _limit = 25; 15 | private long _offset = 0; 16 | 17 | /// 18 | /// Limit 19 | /// 20 | public long Limit { 21 | get { return _limit; } 22 | } 23 | 24 | /// 25 | /// Offset 26 | /// 27 | public long Offset { 28 | get { return _offset; } 29 | set { _offset = value; } 30 | } 31 | 32 | /// 33 | /// Increments the offset by limit value to provide next page Pagination info 34 | /// 35 | public void NextPage() { 36 | this.Offset += this.Limit; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TwitchDotNet/Interfaces/ITwitchClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using TwitchDotNet.Enums; 7 | using TwitchDotNet.Helpers; 8 | 9 | namespace TwitchDotNet.Interfaces { 10 | 11 | /// 12 | /// TwitchClient Interface for requests to Twitch API 13 | /// 14 | public interface ITwitchClient { 15 | 16 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api/ 17 | 18 | Task GetIdByName(string _username); 19 | 20 | #endregion 21 | 22 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 23 | 24 | Task GetChannel(string _channelId); 25 | Task GetChannelFollowers(string _channelId, Pagination _pagination, SortDirection _direction = SortDirection.desc); 26 | Task GetChannelTeams(string _channelId); 27 | Task GetChannelVideos(string _channelId, Pagination _pagination, BroadcastType _broadcastType = BroadcastType.highlight, List _language = default(List), SortBy _sort = SortBy.time); 28 | 29 | #endregion 30 | 31 | #region Chat - Https://dev.twitch.tv/docs/v5/reference/chat/ 32 | 33 | Task GetChatBadgesByChannel(string _channelId); 34 | Task GetChatEmoticonsBySet(List _emoteSets = default(List)); 35 | Task GetEmoticons(); 36 | 37 | #endregion 38 | 39 | #region Games - Https://dev.twitch.tv/docs/v5/reference/games/ 40 | 41 | Task GetTopGames(Pagination _pagination); 42 | Task GetFollowedGames(string _username, Pagination _pagination); 43 | 44 | #endregion 45 | 46 | #region Ingests - Https://dev.twitch.tv/docs/v5/reference/ingests/ 47 | 48 | Task GetIngests(); 49 | 50 | #endregion 51 | 52 | #region Search - Https://dev.twitch.tv/docs/v5/reference/search/ 53 | 54 | Task SearchChannels(string _query, Pagination _pagination); 55 | Task SearchStreams(string _query, Pagination _pagination, bool _hls = true); 56 | Task SearchGames(string _query, bool _live = false); 57 | 58 | #endregion 59 | 60 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 61 | 62 | Task GetStreams(Pagination _pagination, string _game = default(string), List _channels = default(List), StreamType _streamType = StreamType.live, List _languages = default(List)); 63 | Task GetStream(string _channelId, StreamType _streamType = StreamType.live); 64 | Task GetFeaturedStreams(Pagination _pagination); 65 | Task GetStreamsSummary(string _game = default(string)); 66 | 67 | #endregion 68 | 69 | #region Teams - Https://dev.twitch.tv/docs/v5/reference/teams/ 70 | 71 | Task GetTeams(Pagination _pagination); 72 | Task GetTeam(string _teamName); 73 | 74 | #endregion 75 | 76 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 77 | 78 | Task GetUser(string _userId); 79 | Task GetUserFollowedChannels(string _userId, Pagination _pagination, SortDirection _direction = SortDirection.desc, SortKey _sortBy = SortKey.created_at); 80 | Task CheckUserFollowsByChannel(string _userId, string _channelId); 81 | // Unofficial 82 | Task CheckUserFollowsByGame(string _username, string _game); 83 | 84 | #endregion 85 | 86 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 87 | 88 | Task GetVideo(string _videoId); 89 | Task GetTopVideos(Pagination _pagination, string _game = default(string), Period _period = Period.week, BroadcastType _broadcastType = BroadcastType.highlight); 90 | 91 | #endregion 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TwitchDotNet/Interfaces/ITwitchClientAuthenticated.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using TwitchDotNet.Enums; 7 | using TwitchDotNet.Helpers; 8 | 9 | namespace TwitchDotNet.Interfaces { 10 | 11 | /// 12 | /// TwitchClient Interface for Authenticated requests to Twitch API 13 | /// 14 | public interface ITwitchClientAuthenticated { 15 | 16 | #region General - https://dev.twitch.tv/docs/v5/guides/using-the-twitch-api 17 | 18 | Task GetRoot(); 19 | 20 | #endregion 21 | 22 | #region ChannelFeed - Https://dev.twitch.tv/docs/v5/reference/channel-feed/ 23 | 24 | Task GetChannelFeedPosts(string _channelId, CursorPagination _pagination, long _comments = 5); 25 | Task GetChannelFeedPost(string _channelId, string _postId, long _comments = 5); 26 | Task CreateChannelFeedPost(string _channelId, string _content, bool _share = false); 27 | Task DeleteChannelFeedPost(string _channelId, string _postId); 28 | Task CreateReactionToChannelFeedPost(string _channelId, string _postId, string _emoteId); 29 | Task DeleteReactionToChannelFeedPost(string _channelId, string _postId, string _emoteId); 30 | Task GetChannelFeedPostComments(string _channelId, string _postId, CursorPagination _pagination); 31 | Task CreateChannelFeedPostComment(string _channelId, string _postId, string _content); 32 | Task DeleteChannelFeedPostComment(string _channelId, string _postId, string _commentId); 33 | Task CreateReactionToChannelFeedPostComment(string _channelId, string _postId, string _commentId, string _emoteId); 34 | Task DeleteReactionToChannelFeedPostComment(string _channelId, string _postId, string _commentId, string _emoteId); 35 | 36 | #endregion 37 | 38 | #region Channels - Https://dev.twitch.tv/docs/v5/reference/channels/ 39 | 40 | Task GetChannel(); 41 | Task UpdateChannel(string _channelId, string _status, string _game, string _delay, bool _channelFeedEnabled); 42 | Task GetChannelEditors(string _channelId); 43 | Task GetChannelSubscribers(string _channelId, Pagination _pagination, SortDirection _direction = SortDirection.asc); 44 | Task CheckChannelSubscriptionByUser(string _channelId, string _targetUserId); 45 | Task StartChannelCommercial(string _channelId); 46 | Task ResetChannelStreamKey(string _channelId); 47 | 48 | #endregion 49 | 50 | #region Game - Unsupported https://discuss.dev.twitch.tv/t/game-following-requests/2186 51 | 52 | Task FollowGame(string _username, string _game); 53 | Task UnfollowGame(string _username, string _game); 54 | 55 | #endregion 56 | 57 | #region Streams - Https://dev.twitch.tv/docs/v5/reference/streams/ 58 | 59 | Task GetFollowedStreams(Pagination _pagination, StreamType _streamType = StreamType.live); 60 | 61 | #endregion 62 | 63 | #region Users - Https://dev.twitch.tv/docs/v5/reference/users/ 64 | 65 | Task GetUser(); 66 | Task GetUserEmotes(string _userId); 67 | Task CheckUserSubscriptionByChannel(string _userId, string _channelId); 68 | Task FollowChannel(string _userId, string _targetChannelId, bool _enableNotifications = false); 69 | Task UnfollowChannel(string _userId, string _targetChannelId); 70 | Task GetUserBlockList(string _userId, Pagination _pagination); 71 | Task BlockUser(string _userId, string _targetUserId); 72 | Task UnblockUser(string _userId, string _targetUserId); 73 | 74 | #endregion 75 | 76 | #region Videos - Https://dev.twitch.tv/docs/v5/reference/videos/ 77 | 78 | Task GetFollowedVideos(Pagination _pagination, BroadcastType _broadcastType = BroadcastType.highlight); 79 | 80 | #endregion 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /TwitchDotNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TwitchDotNet")] 9 | [assembly: AssemblyDescription("A .NETCore (UWP) C# Library for Twitch API v5")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("TwitchDotNet")] 13 | [assembly: AssemblyCopyright("Copyright © 2016")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /TwitchDotNet/Properties/TwitchDotNet.rd.xml: -------------------------------------------------------------------------------- 1 | 2 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /TwitchDotNet/TwitchDotNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {032C681C-C251-47D1-A6BF-EBC3751EFDAA} 8 | Library 9 | Properties 10 | TwitchDotNet 11 | TwitchDotNet 12 | en-US 13 | UAP 14 | 10.0.14393.0 15 | 10.0.14393.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | SAK 20 | SAK 21 | SAK 22 | SAK 23 | 24 | 25 | AnyCPU 26 | true 27 | full 28 | false 29 | bin\Debug\ 30 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 31 | prompt 32 | 4 33 | 34 | 35 | AnyCPU 36 | pdbonly 37 | true 38 | bin\Release\ 39 | TRACE;NETFX_CORE;WINDOWS_UWP 40 | prompt 41 | 4 42 | 43 | 44 | x86 45 | true 46 | bin\x86\Debug\ 47 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 48 | ;2008 49 | full 50 | x86 51 | false 52 | prompt 53 | 54 | 55 | x86 56 | bin\x86\Release\ 57 | TRACE;NETFX_CORE;WINDOWS_UWP 58 | true 59 | ;2008 60 | pdbonly 61 | x86 62 | false 63 | prompt 64 | 65 | 66 | ARM 67 | true 68 | bin\ARM\Debug\ 69 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 70 | ;2008 71 | full 72 | ARM 73 | false 74 | prompt 75 | 76 | 77 | ARM 78 | bin\ARM\Release\ 79 | TRACE;NETFX_CORE;WINDOWS_UWP 80 | true 81 | ;2008 82 | pdbonly 83 | ARM 84 | false 85 | prompt 86 | 87 | 88 | x64 89 | true 90 | bin\x64\Debug\ 91 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 92 | ;2008 93 | full 94 | x64 95 | false 96 | prompt 97 | 98 | 99 | x64 100 | bin\x64\Release\ 101 | TRACE;NETFX_CORE;WINDOWS_UWP 102 | true 103 | ;2008 104 | pdbonly 105 | x64 106 | false 107 | prompt 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 14.0 136 | 137 | 138 | 145 | -------------------------------------------------------------------------------- /TwitchDotNet/TwitchDotNet.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/travisliew/TwitchDotNet/blob/master/LICENSE.md 10 | https://github.com/travisliew/TwitchDotNet 11 | false 12 | $description$ 13 | Initial release 14 | Copyright 2016 15 | twitch 16 | 17 | -------------------------------------------------------------------------------- /TwitchDotNet/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", 4 | "Newtonsoft.Json": "9.0.1" 5 | }, 6 | "frameworks": { 7 | "uap10.0": {} 8 | }, 9 | "runtimes": { 10 | "win10-arm": {}, 11 | "win10-arm-aot": {}, 12 | "win10-x86": {}, 13 | "win10-x86-aot": {}, 14 | "win10-x64": {}, 15 | "win10-x64-aot": {} 16 | } 17 | } --------------------------------------------------------------------------------