2010年3月9日火曜日

第22回 ダイレクトメッセージを送る

今回はDirectMessageの取得と送信を実装します。
APIはここから。
http://apiwiki.twitter.com/Twitter-API-Documentation

Modelから説明します。

まずこれまで通り、APIを参照してJson形式を受け取るクラスを作る


 [DataContract]
 public class DirectMessage {
  [DataMember(Name = "id")]
  public long Id { get; set; }
・・・略


Json形式のUserのフォーマットはStatusと共通みたいですので使い回します。
あと、プロジェクトのフォルダ構成を変えていますので注意。

次にStatusと場合と同じようにDirectMessageを読み込むクラスを作ります。



 class DirectMessageReader : IItemsReader {
  #region IItemsReader メンバ

  public IEnumerable<ITimelineItem> Read(Stream source) {
   var serializer = new DataContractJsonSerializer(typeof(List<DirectMessage>));
   var result = serializer.ReadObject(source) as List<DirectMessage>;
   foreach (var item in result) {
    yield return new DirectMessageItem(item);
   }
  }

  #endregion
 }



そして、Statusと同じように、APIを叩くクラス。


 static class DirectMessageMethod {
  //APIのURL
  private static readonly string NewUrl = "http://api.twitter.com/1/direct_messages/new.json";

  /// <summary>
  /// New
  /// </summary>
  /// <param name="toUserName">宛先(Id or ScreenName)</param>
  /// <param name="text">投稿内容</param>
  /// <param name="info">認証情報</param>
  /// <returns>投稿した結果、サーバから返ってきたデータ</returns>
  public static DirectMessage New(string toUserName, string text, UserInfo info)  {
   var parameters = new RequestParameter[] {
    new RequestParameter("user", toUserName),
    new RequestParameter("text", text)
   };
   return WebUtility<DirectMessage>.GetDeserializedJsonData(NewUrl, "POST", parameters, info);
  }
 }

将来的にはAPIのDeleteなどもここに来る予定。

request作ってresponse取得してstream取得してJsonでDeserializeというパターンが何回かでてきたので
WebUtilityクラスの下に以下のようなクラスを追加。


 static class WebUtility<T> where T : class {
  /// <summary>
  ///
  /// </summary>
  /// <param name="url">リクエストするURL</param>
  /// <param name="method">"GET" or "POST"</param>
  /// <param name="parameters">リクエストのパラメータ</param>
  /// <param name="info">認証情報</param>
  /// <returns>リクエストした結果(Json形式)をT型にDeserializeしたオブジェクト</returns>
  public static T GetDeserializedJsonData(string url, string method, RequestParameter[] parameters, UserInfo info) {
   var serializer = new DataContractJsonSerializer(typeof(T));
   T result;
   using (var response = WebUtility.GetResponse(url, method, parameters, info))
   using (var stream = response.GetResponseStream()) {
    result = serializer.ReadObject(stream) as T;
   }
   return result;
  }



TwitterTimelineはStatusと共用。
ITimelineItemの実装としてDirectMessageItemクラスを追加。コード略。
※CreatedAtの解釈をDirectMessageではなくてDirectMessageItemにしているのが
Statusと構造が違うけど、JsonフォルダのクラスはJsonの構造を表すだけに後々変更したいので、
Statusの方をDirectMessageにあわせるようにいずれ変更予定。
DirectMessageSettingクラスも作っているけど略。

ここからViewModel。
まずOptionViewModelはDirectMessageのタイムラインを追加するコマンドを追加。(コード略)

SubmitPanelViewModelクラスはDirectMessageCommandを追加。
Submit()でDirectMessageのAPIを叩くように追加。

TimelineItemViewModelクラスは
DirectMessageの時は違うアイコンボタンを表示したいので、
ImageButton[]のプロパティを用意。
コンストラクタで中身を作っています。


public ImageButton[] Commands { get; set; }

以下のswitchのところ。


  public TimelineItemViewModel(ITimelineItem item, UserInfo info)
   : base (""){
   _item = item;
   _userInfo = info;
   var baseUri = System.IO.Directory.GetParent(
    System.Reflection.Assembly.GetExecutingAssembly().Location).FullName;

   switch (item.Type) {
    case ItemType.TwitterStatus:
    case ItemType.SearchTwitter:
     Commands = new ImageButton[] {
      new ImageButton("返信", ReplyCommand, baseUri + @"\icons\16x16\comments.png"),
      new ImageButton("ReTweet", RTCommand, baseUri + @"\icons\16x16\megaphone.png")
     };
     break;
    case ItemType.DirectMessage:
     Commands = new ImageButton[] {
      new ImageButton("DirectMessage返信", ReplyToMailCommand, baseUri + @"\icons\16x16\mail_send.png")
     };
     break;
    case ItemType.Other:
     Commands = new ImageButton[] { };
     break;
    default:
     throw new InvalidOperationException();
   }
   Update();
  }

コマンドも追加しているけど略。

最後にView.

TimelineViewはViewModelでImageButtonを配列に変えたことを受けて、
ItemsControlに変更。

        <ItemsControl ItemsSource="{Binding Path=Commands}">
         <ItemsControl.ItemsPanel>
          <ItemsPanelTemplate>
           <StackPanel Orientation="Horizontal"/>
          </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
        </ItemsControl>


直接指定しなくなったので、アイテムごとに登録されているボタンを表示できます。

あとはSubmitViewにMessage用のボタンも用意したけど略。

追加した箇所は多いけど、目新しい仕組みは少ないので難しくないと思います。
今回のコード
http://wtwitter.codeplex.com/SourceControl/changeset/view/42693



0 件のコメント:

コメントを投稿