ツイートデータへのアクセス (xyttr Advent Calendar 2日目)

この記事はxyttr Advent Calendar 2011の記事です。

インストール方法や基本操作から始めた方が良いかなーと思いつつ、まあその辺はreadmeで事足りるでしょうという事で拡張用コードの書き方に絞って進めて行きます。
※ xyttr拡張用コードは.xyzzyに書いても良いですが、~/.xyzzy/config.l に書く事をお勧めします。

◆ ツイートデータを覗いてみる

タイムラインバッファ上のツイートについて情報を取り出すには、xyttr::entry-point関数xyttr::w/entryマクロを使います。使い方を見て行きましょう。



xyttr::entry-point関数はカーソル下にあるツイートの開始位置(直前のセパレータの先頭位置)とツイートデータ(連想リスト)を多値で返します。

;;; -*- mode:lisp; package:xyttr -*-

(in-package :xyttr)

(defun test ()
  (interactive)
  (multiple-value-bind (start data) (entry-point)
    (msgbox "~S" data)))

(define-key *xyttr-timeline-keymap* #\t 'test)

;; userパッケージやeditorパッケージからはxyttr::entry-pointのように
;; パッケージ修飾子をつけないと使用できないので、config.lでは冒頭の方で
;; (in-package :xyttr)としておくと面倒がなくて良いです。

上記のコードを~/.xyttr/config.lとして保存してからxyttrを起動します。xyttrが起動済みなら単にM-x eval-bufferすればOKです。
そして適当なツイートにカーソルを乗せてからtキーを押すとツイートのデータがメッセージボックスで表示されると思います。

http://gyazo.com/4869daf9f452d45833559e5f03959b31.png

このリストはTwitter APIより取得したJSON文字列をjson:json-decode関数でパースして得られたリストで、連想リストの形になっています。
ではここから何かデータを抜き出してみましょう。JSONリストより指定したフィールド値を取り出すxyttr::json-valueというマクロが用意されているので、まずはこれを使ってみます。

;; 以下 in-package 等は省略

;; アカウント名・投稿文・投稿日時を取得して整形し、
;; クリップボードにコピーする
(defun test ()
  (interactive)
  (multiple-value-bind (start data) (entry-point)
    (let* ((name (json-value data user.screen_name))
           (text (json-value data text))
           (date (json-value data created_at))
           (tweet (format nil "@~A: ~A [~A]" name text date)))
      (copy-to-clipboard tweet)
      (message "copied: ~A" tweet))))

json-valueマクロはJSONリスト(連想リスト)とフィールド名(シンボル)を引数に取ります。
フィールド名はJavaScriptのようにドットで連結して深い階層のフィールド名を指定する事ができます。

取り出すフィールド値が1つ2つだったらこれで良いですが、多くなるとjson-valueを使うのも面倒になるので、さらに便利なxyttr::w/jsonというマクロが用意されています。(w/〜 は所謂with-系マクロのArc流命名法です)

;; w/jsonを使って同じ処理を書いてみる。

(defun test ()
  (interactive)
  (multiple-value-bind (start data) (entry-point)
    (w/json (user.screen_name text created_at) data
      (let ((tweet (format nil "@~A: ~A [~A]" user.screen_name text created_at)))
        (copy-to-clipboard tweet)
        (message "copied: ~A" tweet))))

w/jsonは第1引数で指定されたフィールドについて第2引数のJSONリストより値を取り出し、その値をそのまま第1引数中のシンボルに束縛してbody部を評価します。
そして、startが不要な場合はもっと楽に書けてもいいよね、ということでentry-point関数とw/jsonを組み合わせたxyttr::w/entryマクロがあります。

(defun test ()
  (interactive)
  (w/entry (user.screen_name text created_at)
    (let ((tweet (format nil "@~A: ~A [~A]" user.screen_name text created_at)))
        (copy-to-clipboard tweet)
        (message "copied: ~A" tweet))))

大分すっきりしました。
もう1つ、w/entryを使って簡単なコマンドを書いてみましょう

◆ クライアントアプリのWEBサイトを表示してみる

タイムラインを見てるとたまに見慣れないアプリの名前が流れてきて気になる事があります。WEB版Twitterなら詳細表示してからアプリ名をクリックするとページに飛べますが、xyttrにはそのような機能がないのでコマンドを作ってみましょう。

クライアントアプリの情報は、

<a href="url"> アプリ名 </a>

というHTMLの形式でsourceフィールドに入っています。このURLを取り出し、WEBブラウザで表示します。

(defun open-client-url ()
  (interactive)
  (w/entry (source)
    (whenlet url (and (string-match "<a href=\"\\([^\\\"]+\\)\"" source)
                      (match-string 1))
      (shell-execute url t))))

(define-key *xyttr-timeline-keymap* '(#\c #\l) 'open-client-url)

xyttr::whenletマクロはArcからパクったユーティリティーマクロです。(参考)

M-x eval-bufferしたら、気になったツイート上でc lと入力してみましょう。
http://gyazo.com/393238295fb43daf55b7cb0a81caaa62.png
このように確認できます。



以上、ツイートデータへのアクセス方法の紹介でした。