is Neet

ネトゲしながら暮したい

Twitter Botを、RubyとMongoHQを使って作ってみたのでまとめておく

Bot作ってみました。

f:id:soplana:20120330000208p:plain



知り合いからリクエストがあったので、Rubyで「あまえびたん」というTwitterBotを作ってみました。
仕組はとても単純で、「あまえびたん」へメンションを飛ばすと、リプライを返してくれるだけのBotです。

途中、DB管理が必要な処理があったので、同僚の@rin_muさんにおしえて貰ったmongoHQを使ってみました。

今回書く内容程度のBotであれば、Rubyがある程度書けたら多分1時間くらいあれば作れると思います。
あと、mongoHQのまとまった日本語の記事はあんまり見つからなかったので一応登録からRubyでinsertしたりするまでを書いてみようと思います。


一応作ったモノはgithubに公開しているので思う存分眺めて下さい。
soplana / amaebitann



Botアカウントを作成する

TwitterBot用のアカウントを作成。



アプリケーション登録する

さっき作ったBot用アカウントでここに登録して、アプリケーションの登録を済ませます。
適当に情報を入力して登録が完了したら、まず「Settings」というタブにある「Application Type」という項目を「Read only」から「Read, Write and Access direct messages」とかに変更します。

f:id:soplana:20120329203234p:plain

次に、「OAuth Tool」というタブにある、Consumer key、Consumer secret、Access token、Access token secretをメモしておきます。

f:id:soplana:20120329203700p:plain

あまえびたんのアカウント情報が漏れまくってますがおかまいなしで続けます。



アプリにTwitterアカウントから許可を出しておく

これはやり方他にあるのかもしれませんが、僕はirbからauthorize_urlを取得して許可しました。
ってことでirbを起動します。

irb(main):001:0> require "oauth"
irb(main):001:0> c_key = "xxxxx"
irb(main):001:0> c_secret = "xxxxx"
irb(main):001:0> consumer = OAuth::Consumer.new(c_key, c_secret, :site => "https://api.twitter.com")
irb(main):001:0> r_token = consumer.get_request_token
irb(main):001:0> r_token.authorize_url
 # => "https://twitter.com/oauth/authorize?oauth_token=xxxxx"

これで取得できるURLをブラウザで開き、アプリを許可します。
次にブラウザに7桁のpinコードが表示されると思うのでその入力を行います。

irb(main):001:0> access_token = r_token.get_access_token(:oauth_verifier => 'メモったPINコード')
irb(main):001:0> access_token.token
 => "xxxx...."
irb(main):001:0> access_token.secret 
 => "xxxx...."

ここまでで下準備は大体完了でしょうか。



Botプログラムを書く

まずBot用のディレクトリを作ります。

$ mkdir amaebitann

こういう単発モノで入れるgemはそれぞれで管理したいのでGemfileを作ってbundleで必要なgemを入れます。
mongoDBとか使わないよ!!って方はtwitterだけ入れておけばいいと思います。

$ vim Gemfile

# Gemfileの中身
source 'http://rubygems.org'
gem 'twitter'
gem 'mongo'
gem 'bson_ext'
gem 'json'

$ bundle install --path bundle

これでamaebitannディレクトリ以下にbundleというディレクトリが出来てgemがそこに入ります。
gemを使用するrbファイルの先頭で、require 'bundler/setup'をすることでbundle以下のgemを見てくれるようになるそうです。
ここまで来たらいよいよBotプログラムが書けます。
amaebitann.rbを作成ます。適当にツイートしてみます。
consumer_key、consumer_secret、oauth_token、oauth_token_secretには最初のほうでメモった値を入れて下さい。

# -*- encoding: UTF-8 -*-
require 'bundler/setup'
require 'twitter'

Twitter.configure do |config|
  config.consumer_key       = 'xxxxx'
  config.consumer_secret    = 'xxxxx'
  config.oauth_token        = 'xxxxx'
  config.oauth_token_secret = 'xxxxx'
end

Twitter.update("test")

これで作ったBot用アカウントが「test」とツイートしてると思います!簡単!!
あとはタイムライン拾ってきたり、メンション拾ってきたりとかやりたい放題なので、

Ruby Twitter Gem簡易リファレンス
The Twitter Ruby Gem

この辺見ながらやれば大体やりたい事は出来るかと思います。




で、とりあえず「あまえびたん」に話を戻すと、あまえびたんは「メンションに反応してリプライを返すBot」なので、それっぽい動作をさせるためにはTwitter.mentionsで取得できるmention一覧に対してeachとかで処理すればいいのですが、これだと過去にリプライを返したツイートにも反応してしまいます。
なので一度反応したツイートはスルーするという処理が必要で、その為にDBにツイートIDを保存しておきたかったのです。
そこでmongoHQを使ってmongoDBにツイートIDを保存する仕組を作りました。
もっと良いやり方があるなら教えてください…。



mongoHQに登録する

mongoHQは名前の通りユーザ登録しておけば、mongoDBを使えるよになるクラウドサービスです。多分。
Freeプランだと16MBしか容量はありませんが、手軽さが魅力的なので、今回のようなケースにはもってこいです。
まずはここから新規登録します。
会員登録が終わると、会員画面にある「My Databases」ページにある「Add a Database」をクリックしてDBを追加します。
色々プランはありますが、Freeだと16MBのDBしか選べません。ザンネン。
僕はDB名は「amaebitann」で作成します。

f:id:soplana:20120329213952p:plain


f:id:soplana:20120329214144p:plain


f:id:soplana:20120329214516p:plain


DBの作成が出来たら、今度はそのDBにユーザを追加します。
「Database Users」タブからAdd a userをクリックしてユーザを追加します。
この際Read Only?にチェックを入れると、mongoDBへのinsertが出来なくなります。
僕は間違ってここにチェックを入れて作成してしまい、しばらくハマりました。

f:id:soplana:20120329233840p:plain


次に、「Database Info」タブを開きMongo URI をメモっときます。
後々Rubyから接続する時に必要になるからです。

f:id:soplana:20120329234224p:plain



まぁ…、amaebitannの漏れてはいけない情報が漏れまくってますがきにしません。


そしたらこれでDBが出来上がるので次はcollectionを作成します。
collectonはRDBで言うところの、tableみたいなものです。
先程作成したamaebitannをクリックして、「Add a Collection」をクリックし、適当な名前でcollectionを作成します。

f:id:soplana:20120329214918p:plain

f:id:soplana:20120329215114p:plain

これでDBとcollectionの準備が整いました。



RubyからmongoHQに接続する

はい。やっとここまで来ました。
どうやらRubyからmongoHQをいじるに当たってmongohq-rubyという便利なgemがあるようですが、今回は簡単な処理にとどまるので使用しません。
使うgemはmongo、urijsonの三つです。
では接続からデータのinsertとfindまでをやってみます。

# -*- coding: utf-8 -*-
require 'bundler/setup'
require 'mongo'
require 'uri'
require 'json'

# Database Infoでメモったmongo uriに、DB作成時に作ったuser:passwordを付けて
MONGOHQ_URL="mongodb://user:password@staff.mongohq.com:10037/amaebitann"

# ほとんど公式のサンプルのまま
def get_connection
  return @db if @db
  db      = URI.parse(MONGOHQ_URL)
  db_name = db.path.gsub(/^\//, '')
  @db     = Mongo::Connection.new(db.host, db.port).db(db_name)
  @db.authenticate(db.user, db.password) unless (db.user.nil? || db.user.nil?)
  return @db
end

# collection_nameの所に自分で作ったcollection名をいれてcollectionを取得
collection = get_connection.collection("collection_name")

# データをinsertしてみる
collection.insert(tweet_id: 1)

#データを取得してみる
collection.find(tweet_id: 1).first


RDBと違ってカラムの定義とかしなくていいからもうこれだけで動きます。
簡単なアプリならこれで、後はゴリゴリ書いていけるはずです。


で、後はcronで定期的に実行させて取り敢えずは完了です。


あまえびたんはgithubで公開していますので、自由に眺めたりして下さい。

soplana / amaebitann