RubyでiTunesとTwitter

この間作ったスクリプトiTunesTwitterクラスに分離して機能を増やしてみた。
gemなどにはすでに便利なクラスもあるみたいだけど、勉強用なので自前で実装。
Twitterクラスはまだ update と friends_timeline のみなので、徐々に増やそう。
今回は XML 使ったけど、今っぽく JSON に直そうかな?(JSON使ったことないので)
そのうち github に移す予定。

itunes.rb

# -*- coding: utf-8 -*-
#
# itunes.rb
#
# iTunesを制御するITunesクラス (Mac用)
#  内部でAppleScriptを使用している
#
class ITunes
  def initialize
    str = `osascript -e 'tell application "iTunes" to launch'`
  end

  # 再生
  def play
    str = `osascript -e 'tell application "iTunes"' -e 'play' -e 'end tell'`
  end

  # 停止
  def stop
    str = `osascript -e 'tell application "iTunes"' -e 'stop' -e 'end tell'`
  end

  # 一時停止/再生
  def playpause
    str = `osascript -e 'tell application "iTunes"' -e 'playpause' -e 'end tell'`
  end

  # 次の曲へ
  def next
    str = `osascript -e 'tell application "iTunes"' -e 'next track' -e 'end tell'`
  end

  # 前の曲へ
  def previous
    str = `osascript -e 'tell application "iTunes"' -e 'previous track' -e 'end tell'`
  end

  # 曲名を取得
  def name
    str = `osascript -e 'tell application "iTunes"' -e 'set trackName to name of current track' -e 'return trackName' -e 'end tell'`
    (str != "") ? str.chop : nil
  end

  # アーティスト名を取得
  def artist
    str = `osascript -e 'tell application "iTunes"' -e 'set trackArtist to artist of current track' -e 'return trackArtist' -e 'end tell'`
    (str != "") ? str.chop : nil
  end

  # アルバム名を取得
  def album
    str = `osascript -e 'tell application "iTunes"' -e 'set trackAlbum to album of current track' -e 'return trackAlbum' -e 'end tell'`
    (str != "") ? str.chop : nil
  end
end

twitter.rb

# -*- coding: utf-8 -*-
#
# twitter.rb
#
# Twitterクライアントクラス
#
require 'net/http'
require 'rexml/document'

class Twitter
  attr_reader :users, :res

  def initialize(user, pass)
    @user = user
    @pass = pass

    @users = Hash.new
  end

  # つぶやく
  def update(msg)
    url = "http://twitter.com/statuses/update.xml"
    param = "status="

    uri = URI.parse(url)
    req = Net::HTTP::Post.new(uri.path)
    req.basic_auth(@user, @pass)
    req.body = param + msg

    res = Net::HTTP.start(uri.host) { |http|
      http.request(req)
    }
  end

  # friends timeline
  def friends_timeline(page = nil)
    url = "http://twitter.com/statuses/friends_timeline.xml"
    param = "?page="

    url += param + page.to_s if page != nil && page > 0

    uri = URI.parse(url)
    req = Net::HTTP::Get.new(uri.path)
    req.basic_auth(@user, @pass)

    res = Net::HTTP.start(uri.host) { |http|
      http.request(req)
    }

    if res.class != Net::HTTPOK
      @res = res
      return nil
    end

    statuses = []
    doc = REXML::Document.new(res.body)
    doc.elements.each('statuses/status') { |s|
      uid = s.elements['user/id'].text
      name = s.elements['user/name'].text
      sname = s.elements['user/screen_name'].text
      loc = s.elements['user/location'].text
      desc = s.elements['user/description'].text
      image = s.elements['user/profile_image_url'].text
      url = s.elements['user/url'].text

      sid = s.elements['id'].text
      create = s.elements['created_at'].text
      text = s.elements['text'].text

      @users[uid] = User.new(uid, name, sname, loc, desc, image, url) if @users[uid] == nil
      statuses.push(Status.new(sid, create, text, uid))
    }
 
    return statuses
  end

  class Status
    attr_reader :created_at, :status_id, :text, :user_id

    def initialize(sid, create, text, uid)
      @created_at = create
      @status_id = sid
      @text = text
      @user_id = uid
    end
  end

  class User
    attr_reader :user_id, :name, :screen_name, :location, :description, :image_url, :url
 
    def initialize(uid, name, sname, loc, desc, image, url)
      @user_id = uid
      @name = name
      @screen_name = sname
      @location = loc
      @description = desc
      @image_url = image
      @url = url
    end
  end
end

使い方

require 'itunes'
require 'twitter'

itunes = ITunes.new()
message = "Now playing: " + itunes.name() + " / " + itunes.artist()

twitter = Twitter.new("USERNAME", "PASSWORD") # 自分のアカウントに直す
twitter.update(message)
statuses = twitter.friends_timeline()
statuses.each { |s|
  puts twitter.users[s.user_id].screen_name, s.text, s.created_at, ""
}