備忘録

備忘録

C#でTwitchAPIを利用してチャンネルを検索する方法

Ⅰ. はじめに

タイトルの通り「C#でTwitchAPIを利用してチャンネルを検索する方法」です。

Ⅱ. 手順

1. 以下URLにアクセスして新規アプリケーションを作成する

https://dev.twitch.tv/console/apps/create

2. (1)で作成したアプリケーションのClientID, ClientSecretをメモする
3. サンプルプログラムを書く

Program.cs

using Twitch;

const string ClientId = "YOUR_CLIENT_ID";
const string SecretKey = "YOUR_SECRET_KEY";
const uint GameId = 515025; // Overwatch 2

var client = new TwitchClient(ClientId, SecretKey);
await client.GetAccessTokenAsync();
var response = await client.GetStreamsAsync(new uint[] { GameId });
foreach (var stream in response.Streams)
{
  Console.WriteLine(stream.Title);
}

TwitchClient.cs

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net;
using System.Web;
using Twitch;

namespace Twitch;

public class TwitchClient
{
  private string _clientId { get; set; }
  private string _secretKey { get; set; }
  private HttpClient _httpClient { get; set; }

  public string? AccessToken { get; set; }

  public TwitchClient(string clientId, string secretKey, string? accessToken = null, IWebProxy? proxy = null)
  {
    _clientId = clientId;
    _secretKey = secretKey;
    AccessToken = accessToken;

    var handler = new HttpClientHandler();
    if (proxy != null)
    {
      handler.Proxy = proxy;
    }
    _httpClient = new HttpClient(handler);

    SetHttpHeader("Client-Id", _clientId);

    if (!string.IsNullOrEmpty(AccessToken))
    {
      SetHttpHeader("Authorization", $"Bearer {AccessToken}");
    }
  }

  private void SetHttpHeader(string key, string value)
  {
    if (_httpClient.DefaultRequestHeaders.Contains(key))
    {
      _httpClient.DefaultRequestHeaders.Remove(key);
    }

    _httpClient.DefaultRequestHeaders.TryAddWithoutValidation(key, value);
  }

  public async Task<string?> GetAccessTokenAsync()
  {
    // https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/#client-credentials-grant-flow
    var query = HttpUtility.ParseQueryString("");
    query.Add("client_id", _clientId);
    query.Add("client_secret", _secretKey);
    query.Add("grant_type", "client_credentials");
    var url = new UriBuilder("https://id.twitch.tv/oauth2/token") { Query = query.ToString() }.Uri;
    var response = await _httpClient.PostAsync(url, null).ConfigureAwait(false);
    var str = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
    var obj = JObject.Parse(str);
    var accessToken = obj["access_token"]?.Value<string>();
    AccessToken = accessToken;
    SetHttpHeader("Authorization", $"Bearer {AccessToken}");
    return AccessToken;
  }

  public async Task<StreamsResponse> GetStreamsAsync(uint[] gameIds, string? cursor = null)
  {
    // https://dev.twitch.tv/docs/api/reference/#get-streams
    var query = HttpUtility.ParseQueryString("");
    foreach (var gameId in gameIds)
    {
      query.Add("game_id", gameId.ToString());
    }
    query.Add("type", "live");
    query.Add("grant_type", "client_credentials");
    query.Add("language", "ja");
    query.Add("first", "100");

    if (!string.IsNullOrEmpty(cursor))
    {
      query.Add("after", cursor);
    }

    var url = new UriBuilder("https://api.twitch.tv/helix/streams") { Query = query.ToString() }.Uri;
    var str = await _httpClient.GetStringAsync(url).ConfigureAwait(false);
    var streamsResponse = JsonConvert.DeserializeObject<StreamsResponse>(str);
    if (streamsResponse == null)
    {
      throw new NullReferenceException();
    }
    return streamsResponse;
  }
}

StreamsResponse.cs

using Newtonsoft.Json;

namespace Twitch;

public class Stream
{
  [JsonProperty("id")]
  public ulong Id { get; set; } = default!;

  [JsonProperty("user_id")]
  public ulong UserId { get; set; } = default!;

  [JsonProperty("user_login")]
  public string UserLogin { get; set; } = default!;

  [JsonProperty("user_name")]
  public string UserName { get; set; } = default!;

  [JsonProperty("game_id")]
  public string GameId { get; set; } = default!;

  [JsonProperty("game_name")]
  public string GameName { get; set; } = default!;

  [JsonProperty("type")]
  public string Type { get; set; } = default!;

  [JsonProperty("title")]
  public string Title { get; set; } = default!;

  [JsonProperty("viewer_count")]
  public uint ViewerCount { get; set; } = default!;

  [JsonProperty("started_at")]
  public DateTime StartedAt { get; set; } = default!;

  [JsonProperty("language")]
  public string Language { get; set; } = default!;

  [JsonProperty("thumbnail_url")]
  public string ThumbnailUrl { get; set; } = default!;

  [JsonProperty("tag_ids")]
  public string[] TagIds { get; set; } = default!;

  [JsonProperty("tags")]
  public string[] Tags { get; set; } = default!;
}

public class Pagination
{
  [JsonProperty("cursor")]
  public string Cursor { get; set; } = default!;
}

public class StreamsResponse
{
  [JsonProperty("data")]
  public Twitch.Stream[] Streams { get; set; } = default!;

  [JsonProperty("pagination")]
  public Pagination Pagination { get; set; } = default!;
}

実行結果

OW星人に褒められたので今日は最強だ。
ランク 勝ちたい勝たせてお願い
TOP10トールビョーンワントリック??
久しぶり配信OW2!
プラチナあるある?OTP引きがち、ゲンジが異常に多い