C# check if Twitch steam is online or not


#1

Hello,
I am developing a C# application which is supposed to check whether a stream is online or not. Though, I am having difficulties in doing so. I know I have to use Twitch API to do it but can’t figure out how exactly.

https://api.twitch.tv/kraken/streams/camoduck?client_id=xskte44y2wfqin464ayecyc09nikcj

Before, you could use kraken but this doesn’t to seem to work anymore. Instead, I have to use helix and for that I believe the “client-id” needs to be passed as header in the url. But i don’t know how to do that exactly. Could someone help me with coming up with proper url. Thanks in advance


#2

You should use HttpClient, for example:

class SomeClass {
        static HttpClientHandler hcHandle = new HttpClientHandler();

        static async Task<bool> IsOnline(string channel)
        {
            using (var hc = new HttpClient(hcHandle, false))
                    // false here prevents disposing the handler, which should live for the duration of the program and be shared by all requests that use the same handler properties
            {
                hc.DefaultRequestHeaders.Add("Client-ID", "your client id");
                hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your oauth token, should you have one (you should, but not required)");
                hc.DefaultRequestHeaders.UserAgent.ParseAdd("this would be good practice to set to your own");
                hc.Timeout = TimeSpan.FromSeconds(5); // good idea to set to something reasonable

                using (var response = await hc.GetAsync($"https://api.twitch.tv/helix/streams?user_login={channel}"))
                {
                    response.EnsureSuccessStatusCode(); // throws, if fails, can check response.StatusCode yourself if you prefer
                    string jsonString = await response.Content.ReadAsStringAsync();
                    // TODO: parse json and return true, if the returned array contains the stream
                }
            }
        }
}

#3

Hello, Thanks for your response. would you be able to tell me if this is the correct way to finish it.

var r = JsonConvert.DeserializeObject<RootObject>(jsonString);
                    if (r.data[0] == null)
                    {
                        
                    }
                    else
                    {
                        return true;
                    }

After your code, this is what i added. I used json2csharp.com and got this:

public class Datum
{
    public string id { get; set; }
    public string user_id { get; set; }
    public string user_name { get; set; }
    public string game_id { get; set; }
    public string type { get; set; }
    public string title { get; set; }
    public int viewer_count { get; set; }
    public DateTime started_at { get; set; }
    public string language { get; set; }
    public string thumbnail_url { get; set; }
    public List<string> tag_ids { get; set; }
}

public class Pagination
{
    public string cursor { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
    public Pagination pagination { get; set; }
}

Please let me know, appreciate your help


#4

r.data[0] will throw index out of bounds. Instead: return !(r == default(RootObject) || r.data.Length == 0);

json2csharp gives a good base, but I’d recommend using tags and C#-style naming for the objects instead.

E.G.

public class Datum
{
    [JsonProperty("id")] public string ID { get; set; }
    [JsonProperty("user_id")] public string UserID { get; set; }
}

I’d also call RootObject something else like HelixStreamsResponse, so it’s immediately clear, and you don’t end up with multiple RootObjects for different requests.


#5

Im a bit confused now. Firstly, do you mean to do this?

if (!(r == default(RootObject)))
                {
                    
                }
                else
                {
                    return true;
                }

im not sure why but using r.data.Length == 0) gives an error on Legnth:

|Error|CS1061|‘List’ does not contain a definition for ‘Length’ and no accessible extension method ‘Length’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)

I can’t even seem to get the data such r.data.type or anything else:

|Error|CS1061|‘List’ does not contain a definition for ‘id’ and no accessible extension method ‘id’ accepting a first argument of type ‘List’ could be found (are you missing a using directive or an assembly reference?)

I have done what you told me to do:

 [JsonProperty("id")] public string ID { get; set; }
    [JsonProperty("userId")] public string user_id { get; set; }
    [JsonProperty("user_name")] public string user_name { get; set; }
    [JsonProperty("game_id")] public string game_id { get; set; }
    [JsonProperty("type")] public string type { get; set; }
    [JsonProperty("title")] public string title { get; set; }
    [JsonProperty("viewer_count")] public int viewer_count { get; set; }
    [JsonProperty("datetime")] public DateTime started_at { get; set; }
    [JsonProperty("language")] public string language { get; set; }
    [JsonProperty("thumb_url")] public string thumbnail_url { get; set; }
    [JsonProperty("tag_ids")] public List<string> tag_ids { get; set; }
}

public class Pagination
{
    public string cursor { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
    public Pagination pagination { get; set; }
}

Doesn’t seem to work.

Here is rest of the code as well if you want to see.

static HttpClientHandler hcHandle = new HttpClientHandler();

    static async Task<bool> IsOnline(string channel)
    {
        using (var hc = new HttpClient(hcHandle, false))
        // false here prevents disposing the handler, which should live for the duration of the program and be shared by all requests that use the same handler properties
        {
            hc.DefaultRequestHeaders.Add("Client-ID", "51dn565kyrjdvphqwhxvi1agfgq3mn");
            //hc.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", "your oauth token, should you have one (you should, but not required)");
            //hc.DefaultRequestHeaders.UserAgent.ParseAdd("this would be good practice to set to your own");
            hc.Timeout = TimeSpan.FromSeconds(15); // good idea to set to something reasonable

            using (var response = await hc.GetAsync($"https://api.twitch.tv/helix/streams?user_login={channel}"))
            {
                response.EnsureSuccessStatusCode(); // throws, if fails, can check response.StatusCode yourself if you prefer
                string jsonString = await response.Content.ReadAsStringAsync();
                // TODO: parse json and return true, if the returned array contains the stream
                var r = JsonConvert.DeserializeObject<RootObject>(jsonString);

                if (!(r == default(RootObject)))
                {
                    
                }
                else
                {
                    return true;
                }

            }
        }
        return false;
    }
    

    public async void button1_Click(object sender, EventArgs e)
    {
        bool is_valid = await IsOnline("Tumblurr");
        if(is_valid == false)
        {
            MessageBox.Show("stream is offline");
        }
        else
        {
            MessageBox.Show("stream is online");
        }
       
    }

Really appreiciate your help. I’m pretty new to API and JSON things. So Thanks alot.


#6
if (something)
{
  return false;
}
else
{
  return true;
}

can always be simplified as

return !something;

I meant .Count instead of .Length. Didn’t realize it was a list and not an array.

r == default(RootObject) // checks that r has something
r.data.Count == 0 // checks that there is a stream object in the response
r == default(RootObject) || r.data.Count == 0 // no response or response had no stream
!(r == default(RootObject) || r.data.Count == 0) // there is a response and that response contains a live stream
// so you want this for "the requested stream is live: true/false":
return !(r == default(RootObject) || r.data.Count == 0);

#7

Thank you so much for all your help. That should clear everything. Really appreciate all of your help and your detailed answers!


closed #8

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.