Git Product home page Git Product logo

twitchlib.api's Introduction

Platform: iOS

PLEASE check the "Dev" build before doing a PR if master does not have a feature your looking for.

About

TwitchLib is a powerful C# library that allows for interaction with various Twitch services. Currently supported services are: chat and whisper, API's (v5(deprecated), helix, undocumented, and third party), PubSub event system, and Twitch Extensions. Below are the descriptions of the core components that make up TwitchLib.

Talk directly with us on Discord. https://discord.gg/8NXaEyV

  • TwitchLib.Client: Handles chat and whisper Twitch services. Complete with a suite of events that fire for virtually every piece of data received from Twitch. Helper methods also exist for replying to whispers or fetching moderator lists.
  • TwitchLib.Api: Complete coverage of v5(deprecated), and Helix endpoints. The API is now a singleton class. This class allows fetching all publicly accessible data as well as modify Twitch services like profiles and streams.
  • TwitchLib.PubSub: Supports all documented Twitch PubSub topics as well as a few undocumented ones.
  • TwitchLib.Extension: EBS implementation for validating requests, interacting with extension via PubSub and calling Extension endpoints.
  • TwitchLib.Unity: Unity wrapper system for TwitchLib to allow easy usage of TwitchLib in Unity projects!
  • TwitchLib.Webhook: Implements ASP.NET Core Webhook Receiver with TwitchLib. [Requires DotNet Core 2.1+]

Features

  • TwitchLib.Client:
    • Send formatted or raw messages to Twitch
    • Chat and Whisper command detection and parsing
    • Helper methods
      • Timeout, ban, unban users
      • Change chat color and clear chat
      • Invoke stream commercials and hosts
      • Emote only, follower only, subscriber only, and slow mode
      • Reply-to whisper support
    • Handles chat and whisper events:
      • Connected and Joined channel
      • Channel and User state changed
      • Message received/sent
      • Whisper received/sent (Sending requires a known/verified bot)
      • User joined/left
      • Moderator joined/left
      • New subscriptions and resubscriptions
      • Hosting and raid detection
      • Chat clear, user timeouts, user bans
  • TwitchLib.APi:
    • Supported Twitch API endpoints:v5(deprecated), Helix
    • Supported API sections:
      • Badges, Bits, Blocks
      • ChannelFeeds, Channels, Chat, Clips, Collections, Communities,
      • Follows
      • Games
      • HypeTrain
      • Ingests
      • Root
      • Search, Streams, Subscriptions
      • Teams
      • ThirdParty
      • Undocumented
        • ClipChat
        • TwitchPrimeOffers
        • ChannelHosts
        • ChatProperties
        • ChannelPanels
        • CSMaps
        • CSStreams
        • RecentMessages
        • Chatters
        • RecentChannelEvents
        • ChatUser
        • UsernameAvailable
      • User
      • Videos
    • Services
      • FollowerService: Service for detection of new followers in somewhat real time.
      • LiveStreamMonitor: Service for detecting when a channel goes online/offline in somewhat real time.
      • MessageThrottler: Service to throttle chat messages to abide by Twitch use requirements.
  • TwitchLib.PubSub:
    • Supported topics:
      • ChatModeratorActions
      • BitsEvents
      • VideoPlayback
      • Whispers
      • Subscriptions
      • (Dev) Channel Points
  • TwitchLib.Extension:
    • Developed to be used as part of an EBS (extension back-end service) for a Twitch Extension.
    • Perform API calls related to Extensions (create secret, revoke, channels using extension, etc.)
    • Validation of requests to EBS using extension secret and JWT.
    • Interact with extension via PubSub.

Documentation

Doxygen

For complete library documentation, view the doxygen docs here.

Implementing

Below are basic examples of how to utilize each of the core components of TwitchLib. These are C# examples. NOTE: Twitchlib.API currently does not support Visual Basic. UPDATE: PR'd Visual Basic fix but requires testing by someone that uses it.

Twitchlib.Client - CSharp

using System;
using TwitchLib.Client;
using TwitchLib.Client.Enums;
using TwitchLib.Client.Events;
using TwitchLib.Client.Extensions;
using TwitchLib.Client.Models;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Models;

namespace TestConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Bot bot = new Bot();
            Console.ReadLine();
        }
    }

    class Bot
    {
        TwitchClient client;
	
        public Bot()
        {
            ConnectionCredentials credentials = new ConnectionCredentials("twitch_username", "access_token");
	    var clientOptions = new ClientOptions
                {
                    MessagesAllowedInPeriod = 750,
                    ThrottlingPeriod = TimeSpan.FromSeconds(30)
                };
            WebSocketClient customClient = new WebSocketClient(clientOptions);
            client = new TwitchClient(customClient);
            client.Initialize(credentials, "channel");

            client.OnLog += Client_OnLog;
            client.OnJoinedChannel += Client_OnJoinedChannel;
            client.OnMessageReceived += Client_OnMessageReceived;
            client.OnWhisperReceived += Client_OnWhisperReceived;
            client.OnNewSubscriber += Client_OnNewSubscriber;
            client.OnConnected += Client_OnConnected;

            client.Connect();
        }
  
        private void Client_OnLog(object sender, OnLogArgs e)
        {
            Console.WriteLine($"{e.DateTime.ToString()}: {e.BotUsername} - {e.Data}");
        }
  
        private void Client_OnConnected(object sender, OnConnectedArgs e)
        {
            Console.WriteLine($"Connected to {e.AutoJoinChannel}");
        }
  
        private void Client_OnJoinedChannel(object sender, OnJoinedChannelArgs e)
        {
            Console.WriteLine("Hey guys! I am a bot connected via TwitchLib!");
            client.SendMessage(e.Channel, "Hey guys! I am a bot connected via TwitchLib!");
        }

        private void Client_OnMessageReceived(object sender, OnMessageReceivedArgs e)
        {
            if (e.ChatMessage.Message.Contains("badword"))
                client.TimeoutUser(e.ChatMessage.Channel, e.ChatMessage.Username, TimeSpan.FromMinutes(30), "Bad word! 30 minute timeout!");
        }
        
        private void Client_OnWhisperReceived(object sender, OnWhisperReceivedArgs e)
        {
            if (e.WhisperMessage.Username == "my_friend")
                client.SendWhisper(e.WhisperMessage.Username, "Hey! Whispers are so cool!!");
        }
        
        private void Client_OnNewSubscriber(object sender, OnNewSubscriberArgs e)
        {
            if (e.Subscriber.SubscriptionPlan == SubscriptionPlan.Prime)
                client.SendMessage(e.Channel, $"Welcome {e.Subscriber.DisplayName} to the substers! You just earned 500 points! So kind of you to use your Twitch Prime on this channel!");
            else
                client.SendMessage(e.Channel, $"Welcome {e.Subscriber.DisplayName} to the substers! You just earned 500 points!");
        }
    }
}

Twitchlib.Client - Visual Basic

Imports System
Imports TwitchLib.Client
Imports TwitchLib.Client.Enums
Imports TwitchLib.Client.Events
Imports TwitchLib.Client.Extensions
Imports TwitchLib.Client.Models

Module Module1

    Sub Main()
        Dim bot As New Bot()
        Console.ReadLine()
    End Sub

    Friend Class Bot
        Private client As TwitchClient

        Public Sub New()
            Dim credentials As New ConnectionCredentials("twitch_username", "Token")

            client = New TwitchClient()
            client.Initialize(credentials, "Channel")

            AddHandler client.OnJoinedChannel, AddressOf onJoinedChannel
            AddHandler client.OnMessageReceived, AddressOf onMessageReceived
            AddHandler client.OnWhisperReceived, AddressOf onWhisperReceived
            AddHandler client.OnNewSubscriber, AddressOf onNewSubscriber
            AddHandler client.OnConnected, AddressOf Client_OnConnected

            client.Connect()
        End Sub
        Private Sub Client_OnConnected(ByVal sender As Object, ByVal e As OnConnectedArgs)
            Console.WriteLine($"Connected to {e.AutoJoinChannel}")
        End Sub
        Private Sub onJoinedChannel(ByVal sender As Object, ByVal e As OnJoinedChannelArgs)
            Console.WriteLine("Hey guys! I am a bot connected via TwitchLib!")
            client.SendMessage(e.Channel, "Hey guys! I am a bot connected via TwitchLib!")
        End Sub

        Private Sub onMessageReceived(ByVal sender As Object, ByVal e As OnMessageReceivedArgs)
            If e.ChatMessage.Message.Contains("badword") Then
                client.TimeoutUser(e.ChatMessage.Channel, e.ChatMessage.Username, TimeSpan.FromMinutes(30), "Bad word! 30 minute timeout!")
            End If
        End Sub
        Private Sub onWhisperReceived(ByVal sender As Object, ByVal e As OnWhisperReceivedArgs)
            If e.WhisperMessage.Username = "my_friend" Then
                client.SendWhisper(e.WhisperMessage.Username, "Hey! Whispers are so cool!!")
            End If
        End Sub
        Private Sub onNewSubscriber(ByVal sender As Object, ByVal e As OnNewSubscriberArgs)
            If e.Subscriber.SubscriptionPlan = SubscriptionPlan.Prime Then
                client.SendMessage(e.Channel, $"Welcome {e.Subscriber.DisplayName} to the substers! You just earned 500 points! So kind of you to use your Twitch Prime on this channel!")
            Else
                client.SendMessage(e.Channel, $"Welcome {e.Subscriber.DisplayName} to the substers! You just earned 500 points!")
            End If
        End Sub
    End Class


End Module

For a complete list of TwitchClient events and calls, click here

Twitchlib.API - CSharp

Note: TwitchAPI is now a singleton class that needs to be instantiated with optional clientid and auth token. Please know that failure to provide at least a client id, and sometimes an access token will result in exceptions. v5(Deprecated) and Helix operate almost entirely on Twitch user id's. There are methods in all Twitch api versions to get corresponding usernames/userids.

using System.Collections.Generic;
using System.Threading.Tasks;

using TwitchLib.Api;
using TwitchLib.Api.Helix.Models.Users;
using TwitchLib.Api.V5.Models.Subscriptions; //v5 Deprecated

namespace Example
{
    class Program
    {
        private static TwitchAPI api;

        private void Main()
        {
            api = new TwitchAPI();
            api.Settings.ClientId = "client_id";
            api.Settings.AccessToken = "access_token"; // App Secret is not an Accesstoken
        }

        private async Task ExampleCallsAsync()
        {
            //Gets a list of all the subscritions of the specified channel.
	    var allSubscriptions = await api.Helix.Subscriptions.GetBroadcasterSubscriptionsAsync("broadcasterID",null ,100 ,"accesstoken")

            //Get channels a specified user follows.
            var userFollows = await api.Helix.Users.GetUsersFollowsAsync("user_id");

            //Get Specified Channel Follows
            var channelFollowers = await api.Helix.Users.GetUsersFollowsAsync(fromId: "channel_id");

            //Returns a stream object if online, if channel is offline it will be null/empty.
            var streams = await api.Helix.Streams.GetStreamsAsync(userIds: userIdsList); // Alternative: userLogins: userLoginsList

            //Update Channel Title/Game/Language/Delay - Only require 1 option here.
	    var request = new ModifyChannelInformationRequest(){GameId = "New_Game_Id", Title = "New stream title", BroadcasterLanguage = "New_Language", Delay = New_Delay};
            await api.Helix.Channels.ModifyChannelInformationAsync("broadcaster_Id", request, "AccessToken");
        }
    }
}

Twitchlib.API - Visual Basic

Imports System.Collections.Generic
Imports System.Threading.Tasks

Imports TwitchLib.Api
Imports TwitchLib.Api.Models.Helix.Users.GetUsersFollows
Imports TwitchLib.Api.Models.Helix.Users.GetUsers
Imports TwitchLib.Api.Models.v5.Subscriptions // V5 deprecated

Module Module1

    Public api As TwitchAPI

    Sub Main()
        api = New TwitchAPI()
        api.Settings.ClientId = "Client_id"
        api.Settings.AccessToken = "access_token" // App Secret is not an Accesstoken
        streaming().Wait()
        getchanfollows().Wait()
        getusersubs().Wait()
        getnumberofsubs().Wait()
        getsubstochannel().Wait()
        Console.ReadLine()
    End Sub

    Private Async Function getusersubs() As Task
        'Checks subscription for a specific user and the channel specified.
        Dim subscription As Subscription = Await api.Channels.v5.CheckChannelSubscriptionByUserAsync("channel_id", "user_id")
        Console.WriteLine("User subed: " + subscription.User.Name.ToString)
    End Function

    Private Async Function streaming() As Task
        'shows if the channel is streaming or not (true/false)
        Dim isStreaming As Boolean = Await api.Streams.v5.BroadcasterOnlineAsync("channel_id")
        If isStreaming = True Then
            Console.WriteLine("Streaming")
        Else
            Console.WriteLine("Not Streaming")
        End If
    End Function

    Private Async Function chanupdate() As Task
        'Update Channel Title/Game
        'not used this yet
        Await api.Channels.v5.UpdateChannelAsync("channel_id", "New stream title", "Stronghold Crusader")
    End Function

    Private Async Function getchanfollows() As Task
        'Get Specified Channel Follows
        Dim channelFollowers = Await api.Channels.v5.GetChannelFollowersAsync("channel_id")
        Console.WriteLine(channelFollowers.Total.ToString)
    End Function

    Private Async Function getchanuserfollow() As Task
        'Get channels a specified user follows.
        Dim userFollows As GetUsersFollowsResponse = Await api.Users.helix.GetUsersFollowsAsync("user_id")
        Console.WriteLine(userFollows.TotalFollows.ToString)
    End Function

    Private Async Function getnumberofsubs() As Task
        'Get the number of subs to your channel
        Dim numberofsubs = Await api.Channels.v5.GetChannelSubscribersAsync("channel_id")
        Console.WriteLine(numberofsubs.Total.ToString)
    End Function

    Private Async Function getsubstochannel() As Task
        'Gets a list of all the subscritions of the specified channel.
        Dim allSubscriptions As List(Of Subscription) = Await api.Channels.v5.GetAllSubscribersAsync("channel_id")
        Dim num As Integer
        For num = 0 To allSubscriptions.Count - 1
            Console.WriteLine(allSubscriptions.Item(num).User.Name.ToString)
        Next num
    End Function

End Module

For a complete list of TwitchAPI calls, click here

Twitchlib.PubSub

using System;
using TwitchLib.PubSub;
using TwitchLib.PubSub.Events;

namespace TwitchLibPubSubExample
{
    class Program
    {
        private TwitchPubSub client;
        
        static void Main(string[] args)
        {
            new Program().Run();
        }
        
        private void Run()
        {
            client = new TwitchPubSub();

            client.OnPubSubServiceConnected += onPubSubServiceConnected;
            client.OnListenResponse += onListenResponse;
            client.OnStreamUp += onStreamUp;
            client.OnStreamDown += onStreamDown;

            client.ListenToVideoPlayback("channelUsername");
            client.ListenToBitsEvents("channelTwitchID");
            
            client.Connect();
	    
	    Console.ReadLine(); // Quick fix to keep program from closing right away. ReadKey could also be used.
        }
        

        private void onPubSubServiceConnected(object sender, EventArgs e)
        {
            // SendTopics accepts an oauth optionally, which is necessary for some topics
            client.SendTopics();
        }
        
        private void onListenResponse(object sender, OnListenResponseArgs e)
        {
            if (!e.Successful)
                throw new Exception($"Failed to listen! Response: {e.Response}");
        }

        private void onStreamUp(object sender, OnStreamUpArgs e)
        {
            Console.WriteLine($"Stream just went up! Play delay: {e.PlayDelay}, server time: {e.ServerTime}");
        }

        private void onStreamDown(object sender, OnStreamDownArgs e)
        {
            Console.WriteLine($"Stream just went down! Server time: {e.ServerTime}");
        }
    }
}

For a complete list of TwitchPubSub functionality, click here

TwitchLib.Extension

See the Extension README here.

Examples, Applications, Community Work, and Projects

NOTE: Use these projects as a reference, they are NOT guaranteed to be up-to-date.

If you have any issues using these examples, please indicate what example you are referencing in the Issue or in Discord.

Installation

To install this library via NuGet via NuGet console, use:

Install-Package TwitchLib

and via Package Manager, simply search:

TwitchLib

You are also more than welcome to clone/fork this repo and build the library yourself!

Dependencies

Contributors

Credits and Other Project Licenses

License

This project is available under the MIT license. See the LICENSE file for more info.

:)

twitchlib.api's People

Contributors

hampo avatar hantick avatar honestdan avatar iprodigy avatar itssimple avatar jaybyrrd avatar jbowmanp1107 avatar joakimwehype avatar johngames avatar kamparr avatar kamyker avatar luckynos7evin avatar mahsaap avatar moritzuehling avatar mtleliever avatar myroot avatar nickcraver avatar pietrodicaprio avatar pixlcrashr avatar prom3theu5 avatar ritzmo avatar rrickkert avatar sollaholla avatar swiftyspiffy avatar syzuna avatar terasol avatar teravus avatar urantij avatar wreckedarrow avatar yartch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twitchlib.api's Issues

OnStreamOffline Long Delay

I set the polling Interval to 30 seconds and it works perfectly for OnStreamOnline but it takes 5-10 minutes after the stream has ended for OnStreamOffline to be triggered.

HandleWebException in TwitchHttpClient should throw a more useful error message on HTTP 429

When this class encounters HTTP 429 (rate limited on Helix API), it just throws a generic error:

Something went wrong during the request! Please try again later

Instead, it should throw an error message indicating that the user probably needs to set up rate limiting in the API client (I assumed that not providing a rate limited meant that it just defaulted to an implementation that uses the API headers, rather than no rate limiting at all).

GetExtensionTransactionsResponse Does Not Include Pagination Cursor

The TwitchLib.Api.Helix.Models.Extensions.Transactions.GetExtensionTransactionsResponse model does not include the pagination object that contains the cursor. This makes it impossible to paginate records.

Also consider renaming CreatedClips to Data to be consistent with the response content.

LiveStreamMonitor exception (unhandled internally)

Hello, the following happened after running the LiveStreamMonitor service for possibly a few days, im not entirely sure on the time. Surprisingly that somehow crashed my application.

Some usage context if that helps: I have a timer that runs every minute and calls "SetChannelsById"; I am only calling UpdateLiveStreamersAsync once, at the application start-up; there has been only 1 twitch channel in the list all along.

2020-10-22T00:21:55.639802057Z Unhandled exception. System.Net.Http.HttpRequestException: An error occurred while sending the request.
2020-10-22T00:21:55.639865762Z ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer.
2020-10-22T00:21:55.639922366Z ---> System.Net.Sockets.SocketException (104): Connection reset by peer
2020-10-22T00:21:55.639947168Z --- End of inner exception stack trace ---
2020-10-22T00:21:55.639983171Z at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
2020-10-22T00:21:55.639997172Z at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.GetResult(Int16 token)
2020-10-22T00:21:55.640040775Z at System.Net.Security.SslStream.g__InternalFillBufferAsync|215_0[TReadAdapter](TReadAdapter adap, ValueTask1 task, Int32 min, Int32 initial) 2020-10-22T00:21:55.640055377Z at System.Net.Security.SslStream.ReadAsyncInternal[TReadAdapter](TReadAdapter adapter, Memory1 buffer)
2020-10-22T00:21:55.640088879Z at System.Net.Http.HttpConnection.FillAsync()
2020-10-22T00:21:55.640102580Z at System.Net.Http.HttpConnection.ReadNextResponseHeaderLineAsync(Boolean foldedHeadersAllowed)
2020-10-22T00:21:55.640144684Z at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
2020-10-22T00:21:55.640159085Z --- End of inner exception stack trace ---
2020-10-22T00:21:55.640190987Z at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, CancellationToken cancellationToken)
2020-10-22T00:21:55.640204588Z at System.Net.Http.HttpConnectionPool.SendWithNtConnectionAuthAsync(HttpConnection connection, HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
2020-10-22T00:21:55.656753594Z at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
2020-10-22T00:21:55.656772195Z at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
2020-10-22T00:21:55.656777496Z at TwitchLib.Api.Core.Internal.TwitchHttpClientHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
2020-10-22T00:21:55.656781596Z at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts) 2020-10-22T00:21:55.656787597Z at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.GeneralRequest(String url, String method, String payload, ApiVersion api, String clientId, String accessToken) 2020-10-22T00:21:55.656791797Z at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass14_01.b__1()
2020-10-22T00:21:55.656796097Z at System.Threading.Tasks.Task1.InnerInvoke() 2020-10-22T00:21:55.656800098Z at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(Thread threadPoolThread, ExecutionContext executionContext, ContextCallback callback, Object state) 2020-10-22T00:21:55.656812198Z --- End of stack trace from previous location where exception was thrown --- 2020-10-22T00:21:55.656815699Z at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread) 2020-10-22T00:21:55.656830000Z --- End of stack trace from previous location where exception was thrown --- 2020-10-22T00:21:55.656833700Z at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass14_01.<b__0>d.MoveNext()
2020-10-22T00:21:55.656837801Z --- End of stack trace from previous location where exception was thrown ---
2020-10-22T00:21:55.656841101Z at TwitchLib.Api.Services.LiveStreamMonitorService.GetLiveStreamersAsync()
2020-10-22T00:21:55.656844601Z at TwitchLib.Api.Services.LiveStreamMonitorService.UpdateLiveStreamersAsync(Boolean callEvents)
2020-10-22T00:21:55.656848001Z at TwitchLib.Api.Services.LiveStreamMonitorService.OnServiceTimerTick()
2020-10-22T00:21:55.656851402Z at TwitchLib.Api.Services.Core.ServiceTimer.TimerElapsedAsync(Object sender, ElapsedEventArgs e)
2020-10-22T00:21:55.656854802Z at System.Threading.Tasks.Task.<>c.b__139_1(Object state)
2020-10-22T00:21:55.656858502Z at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
2020-10-22T00:21:55.656862202Z at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
2020-10-22T00:21:55.656866003Z at System.Threading.QueueUserWorkItemCallback.Execute()
2020-10-22T00:21:55.656869503Z at System.Threading.ThreadPoolWorkQueue.Dispatch()

Some of the data in the response was lost.

I make a request through "api.V5.Games.GetTopGamesAsync(...)", part of the data in the class "TwitchLib.Api.V5.Models.Games.Game" disappears (I get "id == 0" and "viewers == 0").

I checked the response format on the website using the link below and in the TwitchLib.Api code. The response format may have changed (the id was renamed _id, and the viewers were completely removed).

https://dev.twitch.tv/docs/v5/reference/games/

Can you confirm the problem?

Add Get Id Examples

Many seem to ask, so good to have.

//V5
var user = await api.V5.Users.GetUserByNameAsync("ChannelName");

V5.Users.CheckUserSubscriptionByChannelAsync and V5.Channels.CheckChannelSubscriptionByUserAsync throw BadResourceException when user is not subscribed

Both the V5.Users.CheckUserSubscriptionByChannelAsync and V5.Channels.CheckChannelSubscriptionByUserAsync throw a BadResourceException when the provided user is not subscribed to the target channel.

The reason: Twitch returns a 404 with a message "[channel/user name] has no subscriptions to [channel/user name]" when the subscription cannot be found in both cases.

See the example responses if the User is Not Subscribed to the Channel:

The fact that TwitchLib throws a BadResourceException is unwanted, since the "twitch api resource can be found". It's just that there is no subscription.

This is very unclear, and there is no way of knowing what the actual problem is, since the message in the response cannot be obtained from the BadResourceException.

Missing AuthScopes at PingResponse

Working with this library I've found I can't use the Third Party AuthorizationFlow with Channel_Editor scope. Maybe it's due to the missing of this scope at TwitchLib.Api/TwitchLib.Api/ThirdParty/AuthorizationFlow/PingResponse.cs - StringToScope method.

private AuthScopes StringToScope(string scope)
        {
            switch (scope)
            {
                case "user_read":
                    return AuthScopes.User_Read;
                case "user_blocks_edit":
                    return AuthScopes.User_Blocks_Edit;
                case "user_blocks_read":
                    return AuthScopes.User_Blocks_Read;
                case "user_follows_edit":
                    return AuthScopes.User_Follows_Edit;
                case "channel_read":
                    return AuthScopes.Channel_Read;
                case "channel_commercial":
                    return AuthScopes.Channel_Commercial;
                case "channel_stream":
                    return AuthScopes.Channel_Subscriptions;
                case "channel_subscriptions":
                    return AuthScopes.Channel_Subscriptions;
                case "user_subscriptions":
                    return AuthScopes.User_Subscriptions;
                case "channel_check_subscription":
                    return AuthScopes.Channel_Check_Subscription;
                case "chat_login":
                    return AuthScopes.Chat_Login;
                case "channel_feed_read":
                    return AuthScopes.Channel_Feed_Read;
                case "channel_feed_edit":
                    return AuthScopes.Channel_Feed_Edit;
                case "collections_edit":
                    return AuthScopes.Collections_Edit;
                case "communities_edit":
                    return AuthScopes.Communities_Edit;
                case "communities_moderate":
                    return AuthScopes.Communities_Moderate;
                case "viewing_activity_read":
                    return AuthScopes.Viewing_Activity_Read;
                case "user:edit":
                    return AuthScopes.Helix_User_Edit;
                case "user:read:email":
                    return AuthScopes.Helix_User_Read_Email;
                case "clips:edit":
                    return AuthScopes.Helix_Clips_Edit;
                case "analytics:read:games":
                    return AuthScopes.Helix_Analytics_Read_Games;
                case "bits:read":
                    return AuthScopes.Helix_Bits_Read;
                default:
                    throw new Exception("Unknown scope");
            }
}

NotPartneredException on Follower Service (v1.1.0)

I'm getting a "The resource you requested is only available to channels that have been partnered by Twitch." if I try to get a Followers Name on Follower Service.

My Code:

foreach (var follower in e.NewFollowers)
{
     if (follower == null)
     {
         continue;
     }

     // Getting User by ID
     var getFollowerName = await TwitchService.TwitchAPIClient.V5.Users.GetUserByIDAsync(follower.FromUserId); 
     // Crashes on this one with the TwitchLib.Api.Core.Exceptions.NotPartneredException

}

Making the Api library testable

So the Api is not really testable at the moment due to its dependency on HttpClient (>2.0) and WebRequest (<2.0)

Therefore I propose the following:-

  1. Break out the actual calls made into a different class
  2. create an interface
  3. profit

With the aim of making the Api more DI friendly this would mean a new constructor value in which a "HttpCallHandler" can be injected

Follower Service Always Reporting New Followers

When I start a FollowerService and watch the OnNewFollowerDetected event, it always starts off by reporting 100 new followers. They're not new followers. I don't think it's setting its cache when the service starts. This means it always considers everyone to be "new" for the first trigger of the event.

This is the version of TwitchLib I am referencing.

    <PackageReference Include="TwitchLib" Version="3.0.1" />

RefreshResponse ExpiresIn is always 0

Hey, I am using the following code on the latest lib version (2.1.4)

var authToken = TwitchApi.Auth.v5.RefreshAuthTokenAsync(refreshToken, clientSecret).GetAwaiter().GetResult();

And the response it gives always have the ExpiresIn field set to 0.

Unhandled exception in LiveStreamMonitorService

CoreCLR Version: 4.6.27129.4
Description: The process was terminated due to an unhandled exception.
Exception Info: TwitchLib.Api.Core.Exceptions.InternalServerErrorException: The API answered with a 500 Internal Server Error. Please retry your request
at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.HandleWebException(HttpResponseMessage errorResp)
at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.GeneralRequest(String url, String method, String payload, ApiVersion api, String clientId, String accessToken)
at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass13_01.<TwitchGetGenericAsync>b__1() at System.Threading.Tasks.Task1.InnerInvoke()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot)
--- End of stack trace from previous location where exception was thrown ---
at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass13_0`1.<b__0>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at TwitchLib.Api.Services.LiveStreamMonitorService.GetLiveStreamersAsync()
at TwitchLib.Api.Services.LiveStreamMonitorService.UpdateLiveStreamersAsync(Boolean callEvents)
at TwitchLib.Api.Services.LiveStreamMonitorService.OnServiceTimerTick()
at TwitchLib.Api.Services.Core.ServiceTimer.TimerElapsedAsync(Object sender, ElapsedEventArgs e)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
at System.Threading.ThreadPoolWorkQueue.Dispatch()

I believe exception escapes here

await _serviceTimerTickAsyncCallback();

From MSDN

The Timer component catches and suppresses all exceptions thrown by event handlers for the Elapsed event. This behavior is subject to change in future releases of the .NET Framework. Note, however, that this is not true of event handlers that execute asynchronously and include the await operator (in C#) or the Await operator (in Visual Basic). Exceptions thrown in these event handlers are propagated back to the calling thread, as the following example illustrates.

TwitchApi.V5.Chat.GetAllChatEmoticonsAsync throws BadRequestException

Got an BadRequestException using method TwitchApi.V5.Chat.GetAllChatEmoticonsAsync()

Update: if dont push AccessToken (comment line in code), i get result from API. But this result was unable to deserialize:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'TwitchLib.Api.V5.Models.Chat.EmoticonImage[]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'emoticons[0].images.emoticon_set', line 1, position 129.

Update2: If save response json to file it took ~120Mbytes

GetUserActiveExtensions - missing parameter

Hi there!

According to the docs, I can ask the extensions for a specific user by supplying the user_id:

image

Unfortunately, TwitchLib doesn't seem to support this, the relevant code seems to be here

        public Task<GetUserActiveExtensionsResponse> GetUserActiveExtensionsAsync(string authToken = null)
        {
            return TwitchGetGenericAsync<GetUserActiveExtensionsResponse>("/users/extensions", ApiVersion.Helix, accessToken: authToken);
        }

I think I'll try a PR, as I need that endpoint, but still creating this issue just in case.

Bits.helix.GetBitsLeaderboardAsync throws NullReferenceException

I've initialized the client and set the accesstoken and clientid but when using the command TwitchAPI.Bits.helix.GetBitsLeaderboardAsync(1, TwitchLib.Api.Enums.BitsLeaderboardPeriodEnum.Week); I get a System.NullReferenceException from TwitchLib.Api.ApiSettings,DynamicScopeValidation.

EDIT: To make it clear, I don't call it like a static function in the actual code

Better way of setting Creds for Api

At the moment we have an Initialise Method which sets creds and checks them against the Api

I would like to remove this and instead enable setting of the creds through Api.Settings.ClientId and Api.Settings.AccessToken however include a "CheckCredentials" method which does just that. Returning a KeyValuePair<bool, string>

V5.Users.CheckUserSubscriptionByChannelAsync response User property null

When getting a successful response from V5.Users.CheckUserSubscriptionByChannelAsync, the .User property from the "Subscription" response is null.

The reason: This endpoint has a Channel object instead of a User object in the response instead.
See the difference between:

The same response class is used, hence the .User property is null.

Proxy in API

Hello!

Is there any option to set proxy in API object? If it is, can you give me example how I can set it. If not please add this feature. Maybe like param in API object constructor, or in Settings param.

Twitch OAuth2 code flow

Note: I'm not sure if the API repo is the right place for this, but I see you have other v5 auth methods so I'll add it here.

Any plan on adding the OAuth Code Flow endpoints to the library? This would be very helpful. You seem to have something similar in v5.Auth for refreshing tokens; it would be nice to see "GetAuthorizationUrl" and "AuthorizeCode" methods in there too.

Here's what I'm having to do now:

public static async Task<string> AuthorizeCode(string code, string clientId, string secret, string redirectUrl, HttpClient client, CancellationToken? cancellationToken = null)
{
	var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post,
		"https://id.twitch.tv/oauth2/token?" +
		$"client_id={clientId}&" +
		$"client_secret={HttpUtility.UrlEncode(secret)}&" +
		$"code={code}&" +
		"grant_type=authorization_code&" +
		$"redirect_uri={HttpUtility.UrlEncode(redirectUrl)}");

	var twitchTokenResponse = cancellationToken != null
		? await client.SendAsync(httpRequestMessage, cancellationToken.Value)
		: await client.SendAsync(httpRequestMessage);

	var responseString = await twitchTokenResponse.Content.ReadAsStringAsync();
	return
		twitchTokenResponse.IsSuccessStatusCode
			? JObject.Parse(responseString).GetValue("access_token").Value<string>()
			: null;
}

Hope you'll consider it!

[Broke]{Dev Branch} Helix change for the monitor broken

Not sure how I missed this but its not triggering event on detecting a channel online. It does however detect the online channels correctly in the library code. GetLiveStreamersAsync works. Its CheckForOnlineStreamChangesAsync not working atm.

I'm still investigating, but to ensure the lib is not pushed to nuget or to master till this is fixed, I'm adding this issue.

Error Capturing Question

Is there a "preferred way" to capture and/or ignore errors thrown by the Library? I am getting a 502 error from Twitch every now and then, but would like it to try again at the specified interval.

An unhandled exception of type 'TwitchLib.Api.Core.Exceptions.BadGatewayException' occurred in System.Private.CoreLib.dll: 'The API answered with a 502 Bad Gateway. Please retry your request'
Stack trace:
 >   at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.HandleWebException(HttpResponseMessage errorResp)
 >   at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.GeneralRequest(String url, String method, String payload, ApiVersion api, String clientId, String accessToken)
 >   at TwitchLib.Api.Core.ApiBase.GenerateServerBasedAccessToken()
 >   at TwitchLib.Api.Core.ApiBase.GetAccessToken(String accessToken)
 >   at TwitchLib.Api.Core.ApiBase.TwitchGetGenericAsync[T](String resource, ApiVersion api, List`1 getParams, String accessToken, String clientId, String customBase)
 >   at TwitchLib.Api.Helix.Streams.GetStreamsAsync(String after, List`1 communityIds, Int32 first, List`1 gameIds, List`1 languages, String type, List`1 userIds, List`1 userLogins)
 >   at TwitchLib.Api.Services.Core.LiveStreamMonitor.IdBasedMonitor.GetStreamsAsync(List`1 channels)
 >   at TwitchLib.Api.Services.LiveStreamMonitorService.<GetLiveStreamersAsync>d__30.MoveNext()
 >   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 >   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 >   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 >   at TwitchLib.Api.Services.LiveStreamMonitorService.<UpdateLiveStreamersAsync>d__26.MoveNext()
 >   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 >   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 >   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 >   at TwitchLib.Api.Services.LiveStreamMonitorService.<OnServiceTimerTick>d__27.MoveNext()
 >   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 >   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
 >   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
 >   at TwitchLib.Api.Services.Core.ServiceTimer.<TimerElapsedAsync>d__6.MoveNext()
 >   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
 >   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__139_1(Object state)
 >   at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
 >   at System.Threading.ThreadPoolWorkQueue.Dispatch()

Custom Room Message

Hello.
I can not get the bot to send a message to custom rooms. After Connect to Room (client.JoinRoom(channelName, "market"), messages are still sent to stream chat. Thx for help

[Suggestion] Add a summary to all endpoints

Sometimes it can be quite unclear what an endpoint in the API does exactly.
Along with that, it can throw unexpected exceptions which aren't documented anywhere.
Next to that, even the parameter names aren't quite clear from time to time.

So my suggestion is to start adding summaries to at least all future added endpoints (Helix) and try to add a summary to all current Helix endpoints which are already created.
For V5 endpoints, it would be nice, but since it's a bit depreciated and it should be removed at the end of the year), it might not be worth adding them to those endpoints.

An example of a summary would be:

/// <summary>
/// <see href="https://dev.twitch.tv/docs/api/reference/#replace-stream-tags">Replace Stream Tags</see>
/// </summary>
/// <exception cref="ArgumentNullException">When the <paramref name="broadcasterId"/> is null.</exception>
/// <exception cref="ArgumentException">When the amount of tags in <paramref name="tagIds"/> is more than 5.</exception>
/// <param name="broadcasterId">ID of the stream for which tags are to be replaced.</param>
/// <param name="tagIds">IDs of tags to be applied to the stream.</param>
/// <param name="accessToken">An accessToken to use for this specific request.</param>

Preferably it would also have the methods which can be thrown internally, such as BadScopeException, BadGatewayException, InternalServerErrorException, etc. Since it's possible that this method throws those errors and a user should know that he/she needs to handle them if such a thing happens for whatever reason.

Please consider adding a CancellationToken as parameter for async methods

From @niklr on April 12, 2018 10:1

Is it currently possible to cancel a pending async method? What happens if Twitch is down: will the sync/async methods run forever or cancel/timeout after a specific time?

Please consider adding a CancellationToken as parameter for async methods. Additionally, consider the possibility to specify a number of milliseconds to wait before requests time out.

Copied from original issue: TwitchLib/TwitchLib#389

WebException: The remote name could not be resolved: 'api.twitch.tv'

Lately I have been leaving my bot running in debug mode because it tends to crash randomly, and this error has showed up twice now:

System.Net.Http.HttpRequestException
HResult=0x80131509
Message=An error occurred while sending the request.
Source=mscorlib
StackTrace:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Core.Internal.TwitchHttpClientHandler.d__2.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.Http.HttpClient.d__58.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Core.HttpCallHandlers.TwitchHttpClient.GeneralRequest(String url, String method, String payload, ApiVersion api, String clientId, String accessToken)
at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass13_01.<TwitchGetGenericAsync>b__1() at System.Threading.Tasks.Task1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Core.ApiBase.<>c__DisplayClass13_0`1.<b__0>d.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Services.LiveStreamMonitorService.d__30.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Services.LiveStreamMonitorService.d__26.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Services.LiveStreamMonitorService.d__27.MoveNext()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at TwitchLib.Api.Services.Core.ServiceTimer.d__6.MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<>c.b__6_1(Object state)
at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Inner Exception 1:
WebException: The remote name could not be resolved: 'api.twitch.tv'

Let me know if you need any more information.

Not Compatible with Visual Basic

From @mbfan on April 27, 2018 17:22

Hello,
please consider rewriting the Code to remove all duplication of Members. Visual Basic ignores upper and lower case, and i can't use any method cause there is (for example) a "v5" and a "V5", which are the same to VB.
With kind regards,
Nico

Copied from original issue: TwitchLib/TwitchLib#394

ITwitchAPI is not mockable

I am looking forward to using TwitchLib.Api for a project I am currently working on, but it does look like ITwitchAPI can't correctly be mocked and used in unit tests.

Having ITwitchAPI define concrete type as properties makes it impossible to mock the underlying implementation.

Am I missing something here? Are there plans to make it more unit-test friendly?

V5.Users.CheckUserSubscriptionByChannelAsync throws HttpRequestException when token is not from user

When calling the V5.Users.CheckUserSubscriptionByChannelAsync endpoint, and the token is not from the user, but instead from the channel owner, a HttpRequestException is thrown.

The cause of this is that this specific endpoint is meant for the User to get information about a subscription to a channel, not the other way around.

The response from the API on Twitch's side is a 403 (Forbidden) with the message: "Cannot view user subscription's channel of another user."

Since the HandleWebException in the TwitchHttpClient does not handle 403 return codes, a generic HttpRequestException is thrown instead.
The user gets this error message without any other information on what's going wrong and has no access to the message provided by Twitch.

Undocumented.GetChatUserAsync returns null Badges

The Undocumented.GetChatUserAsync method returns ChatUserResponse, which has a Badges property of type KeyValuePair<string,string>, but that's not the structure returned from the API Call. An array of models in this structure could handle the badge data that is returned.

public class Badge
{
    public string id { get; set; }
    public string version { get; set; }
}

Server based access token are generated on every request

Currently when using server based access tokens (client_credentials flow) a new access token is created for every api call.
This creates a lot of unneccessary requests and delay.

Instead the expiration time should be stored and a new access token only requested when it is near that expiration time.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.