LoginSignup
8
8

More than 5 years have passed since last update.

C言語でTwitter UserStreamを受信しよう

Last updated at Posted at 2016-06-10

拙作のC言語向けTwitterライブラリT4CはREST APIに加えてStreaming APIもサポートしています。
今回はC言語でどのようにしてStreaming APIをサポートするのか、について書こうと思います。

Streaming APIとは

Streaming APIとは簡単に言うと、リアルタイムに(何らからのEventが発生した場合に)TwitterからレスポンスがかえってくるAPIです。
で、リアルタイムに帰ってくる事に加え、無限にレスポンスが帰ってきます。
よって、通常のGETリクエストとして処理することはできません。したがって、異なるアプローチをとることにします。

異なるアプローチといっても単純で、タイムアウトを無くして、レスポンスがかえってくるたびにcallbackが呼ばれるようにすればよいのです。

libcurlでタイムアウトをなくすには

curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0);

とすればよいのです。

また、コールバックには次のようなものを指定すればそれが、レスポンスがかえってくるたびに呼ばれます。

static size_t streaming_callback_sample(void* ptr, size_t size, size_t nmemb, void* data) {
  if (size * nmemb == 0)
    return 0;

  size_t realsize = size * nmemb;
  string* str = (string*)data;
  str->length = realsize + 1;
  str->value  = MALLOC_TN(char, str->length);

  if (str->value != NULL) {
    memcpy(str->value, ptr, realsize);
    strcat(str->value, "\0");

    fprintf(stderr, "RECIEVED: %ld bytes\n", realsize);
    fprintf(stderr, "[STREAMING API] received -> %s\n", str->value);
  }

  return realsize;
}

コード

あとは、以前に書いた記事(C言語でTwitter APIをつかって、ツイートしよう! (自前でOAuthを実装する話))のrequestとほぼ同じような感じで一部、上で書いたことを反映させれば実現できます(重複になるのでstream関数内で用いてる関数などについての説明は行いませんので、詳しくは以前書いた記事を参照してください。)

void stream(T4C* t4c, string url, Parameters* paramsArgument, size_t (*callback)(void*, size_t, size_t, void*)) {

  bool paramsArgumentWasNULL = false;
  if (paramsArgument == NULL) {
    paramsArgument = new_parameters();
    paramsArgumentWasNULL = true;
  }

  Parameters* oauthParams = new_parameters();
  genOAuthParams(t4c, oauthParams);
  Parameters* params = new_parameters();
  buildParams(params, oauthParams, paramsArgument);

  string oauthSignature = signature(t4c->consumerSecret, t4c->accessTokenSecret, GET, url, params);
  string encodedSignature = url_encode(oauthSignature);

  add_parameter(oauthParams, make_string("oauth_signature"), encodedSignature);
  add_parameter(params, make_string("oauth_signature"), encodedSignature);

  string authorize      = new_string();
  string authorizeChild = join_parameters(oauthParams, ",");
  authorize.length      = 21 + authorizeChild.length;
  authorize.value       = MALLOC_TN(char, authorize.length);
  sprintf(authorize.value, "Authorization: OAuth %s", string_get_value(authorizeChild));

  string path = join_parameters(params, "&");

  if (DEBUG) {
    printf("----------------------------\n");
    printf("STREAMING API");
    printf("URL: %s\n", string_get_value(url));
    printf("path: %s\n", string_get_value(path));
    printf("authorize: %s\n", string_get_value(authorize));
    printf("----------------------------\n");
  }

  CURL* curl;
  curl = curl_easy_init();

  string reqURL = new_string();

  reqURL.length = url.length + 1 + path.length;
  reqURL.value  = MALLOC_TN(char, reqURL.length);
  sprintf(reqURL.value, "%s?%s", url.value, path.value);

  curl_easy_setopt(curl, CURLOPT_URL, reqURL.value);

  struct curl_slist *headers = NULL;
  headers = curl_slist_append(headers, string_get_value(authorize));
  curl_easy_setopt(curl, CURLOPT_HEADER, headers);

  curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
  curl_easy_setopt(curl, CURLOPT_TIMEOUT, 0);

  curl_easy_perform(curl);
  curl_easy_cleanup(curl);

  free_string(url);
  free_string(path);
  free_string(authorize);
  free_parameters(oauthParams);
  free_parameters(params);
  if (paramsArgumentWasNULL) {
    free_parameters(paramsArgument);
  }
}

このようにすればC言語でTwitter UserStreamが受信できます。
以下にT4Cを用いてC言語でUserStreamを受信するコードを書きます

#include <t4c/parameters.h>
#include <t4c/string.h>
#include <t4c/t4c.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>

//上に載せたコールバックをここに書く(スペースの関係上省略)
static size_t streaming_callback_sample(void* ptr, size_t size, size_t nmemb, void* data);

int main() {
  T4C t4c = {
    .consumerKey       = make_string("Your Consumer Key"),
    .consumerSecret    = make_string("Your Consumer Secret"),
    .accessToken       = make_string("Your AccessToken"),
    .accessTokenSecret = make_string("Your AccessTokenSecret")
  };

  stream(&t4c, make_string("https://userstream.twitter.com/1.1/user.json"), NULL, streaming_callback_sample);
}

また、T4CのREADMEにも書きましたが、/statuses/filter.jsonのような引数をとるAPIも使うことができます。そちらはT4CのREADMEを参照してください。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8