WCFでTwitter APIをたたいてみる

昨日WCFはてなスターの総数を取得してみたけど、次はTwitter APIをたたいてみる。

[観] Twitter API 仕様書 (勝手に日本語訳シリーズ)を参考にしつつ、つくってみた。

ソースは以下の通り。とりあえず、friendタイムラインとpublicタイムラインの取得、ステータスの更新機能だけ。

using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;

class TwitterTest
{
    static void Main(string[] args)
    {
        string url = "http://twitter.com";

        WebHttpBinding binding = new WebHttpBinding();
        binding.Security.Mode = WebHttpSecurityMode.TransportCredentialOnly;
        binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

        using (var factory = new WebChannelFactory<ITwitterService>(binding, new Uri(url)))
        {
            factory.Credentials.UserName.UserName = "あなたのユーザーID";
            factory.Credentials.UserName.Password = "あなたのパスワード";

            ITwitterService s = factory.CreateChannel();

            Statuses results = s.GetFriendTimeline();
            foreach (var result in results)
            {
                Console.WriteLine("{0}:{1}", result.User.Name, result.Text);
            }
        }
    }
}


[ServiceContract]
public interface ITwitterService
{
    [OperationContract]
    [WebInvoke(UriTemplate = "/statuses/update.xml?status={text}")]
    Status UpdateStatus(string text);

    [OperationContract]
    [WebGet(UriTemplate = "/statuses/public_timeline.xml")]
    Statuses GetPublicTimeline();

    [OperationContract]
    [WebInvoke(UriTemplate = "/statuses/friends_timeline.xml")]
    Statuses GetFriendTimeline();
}
[CollectionDataContract(Name = "statuses", ItemName = "status", Namespace = "")]
public class Statuses : List<Status>
{
}

[DataContract(Name = "status", Namespace = "")]
public sealed class Status
{
    [DataMember(Name = "created_at", Order = 0)]
    public string CreatedAt { get; set; }

    [DataMember(Name = "id", Order = 1)]
    public string ID { get; set; }

    [DataMember(Name = "text", Order = 2)]
    public string Text { get; set; }

    [DataMember(Name = "source", Order = 3)]
    public string Source { get; set; }

    [DataMember(Name = "truncated", Order = 4)]
    public bool Truncated { get; set; }

    [DataMember(Name = "in_reply_to_status_id", Order = 5)]
    public string InReplyToStatusId { get; set; }

    [DataMember(Name = "in_reply_to_user_id", Order = 6)]
    public string InReplyToUserId { get; set; }

    [DataMember(Name = "favorited", Order = 7)]
    public bool Favorited { get; set; }

    [DataMember(Name = "user", Order = 8)]
    public User User { get; set; }
}

[DataContract(Name = "user", Namespace = "")]
public sealed class User
{
    [DataMember(Name = "id", Order = 0)]
    public string ID { get; set; }

    [DataMember(Name = "name", Order = 1)]
    public string Name { get; set; }

    [DataMember(Name = "screen_name", Order = 2)]
    public string ScreenName { get; set; }

    [DataMember(Name = "description", Order = 3)]
    public string Description { get; set; }

    [DataMember(Name = "location", Order = 4)]
    public string Location { get; set; }

    [DataMember(Name = "profile_image_url", Order = 5)]
    public string ProfileImageUrl { get; set; }

    [DataMember(Name = "url", Order = 6)]
    public string Url { get; set; }

    [DataMember(Name = "protected", Order = 7)]
    public bool Protected { get; set; }

    [DataMember(Name = "followers_count", Order = 8)]
    public int FollowersCount { get; set; }
}

CollectionDataContractとか、Namespaceの指定が分からずにちょっと苦労したけど、全体的にすごくスッキリ。

これを使ってSilverlightTwitterクライアントでも作ってみようかなと思ったけど、SilverlightではまだWebHttpBindingは使えないのね。残念。


Silverlightと言えば、id:coma2nさんのところで口コミで評判の「トゥルースリーパー」でプレミアムな睡眠タイムを満喫!というサイトが紹介されていた。バナーがかわいい。



(2008/09/11追記)
DataMemberAttributeにOrderを指定しておかないと、一部の要素が正しく取得できないことが分かったので、少し修正しました。