第19回 DevDo に参加した - twitter の最近の投稿の単語をバラしてカウントしてくれるサービス(仮)を作った

twitter の最近の投稿の単語をバラしてカウントしてくれるようなサーバーを作りました.これと config.ru で動きます.

# -*- coding: utf-8 -*-
require 'uri'
require 'rexml/document'
require 'net/http'
require 'sinatra'
require 'oauth'
require 'twitter'

CONSUMER_KEY = '' # twitter アプリケーションの API の KEY を入れる
CONSUMER_SECRET = '' # twitter アプリケーションの API の SECRET を入れる
HOST_AND_PORT = 'localhost:9292'

class YMA
  BASE_URI = URI.parse('http://jlp.yahooapis.jp/MAService/V1/parse')
  def initialize appid='' # yahoo 形態素解析サービス利用 id を入れる
    @appid = appid
  end
  def parse sentence, option={}
    result = Net::HTTP.post_form(BASE_URI, { 'appid' => @appid, 'sentence' => sentence }).body
    REXML::Document.new(result)
  end
end

set :sessions, true

def consumer
  OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, :site => "https://api.twitter.com")
end

get '/' do
  @request_token = consumer.get_request_token(:oauth_callback => "http://#{HOST_AND_PORT}/auth")
  session[:request_token] = @request_token.token
  session[:request_token_secret] = @request_token.secret
  %Q{<p>OAuth認証してください</p><a href="#{@request_token.authorize_url}">認証する!</a>}
end

get '/auth' do
  @request_token = OAuth::RequestToken.new(consumer,
                                           session[:request_token],
                                           session[:request_token_secret])
  @access_token = @request_token.get_access_token({},
                                                  :oauth_token => params[:oauth_token],
                                                  :oauth_verifier => params[:oauth_verifier])
  session[:access_token] = @access_token.token
  session[:access_token_secret] = @access_token.secret
  %Q{<p>認証成功</p><p><a href="/tagging">タグ付けしてみる</a></p>}
end

get '/tagging' do
  oauth = Twitter::OAuth.new(CONSUMER_KEY, CONSUMER_SECRET)
  oauth.authorize_from_access(session[:access_token], session[:access_token_secret])
  @twit = Twitter::Base.new(oauth)
  result =  @twit.user_timeline.map(&:text).inject(Hash.new(0)){ |base,element|
    words = YMA.new.parse(element).elements['ResultSet/ma_result/word_list'].map{|e| e.elements['surface'].text }
    words.each{ |e| base[e] += 1 }
    base
  }.sort{ |a,b| b[1].to_i <=> a[1].to_i }
  %Q!<DL>#{result.map{ |e| "<DT>#{e[0]}</DT><DD>#{e[1]}</DD>"}.join}<DL>!
end