Ruby + Heroku の無料枠で Twitter bot をお手軽に作成(使い捨て編) #heroku #twitter #ruby #bot

# Ruby + Heroku の無料枠で Twitter bot をお手軽に作成(使い捨て編) #heroku #twitter #ruby #bot
## <i class="fa fa-cubes" style="font-size:1em;"></i> 概要
Ruby で Twitter bot を作成(使い捨て編)

## <i class="fa fa-history" style="font-size:1em;"></i> 経緯
Ruby のボットフレームワークの Ruboty で Twitter bot を作成しようと思ったところ、
twitter-adapter を修正する必要があるということが分かりました。
時間ができてから、 twitter-adapter を修正してプルリクしようと思いますが、
ボット用のアカウントを作成してしまったし、もったいないので先に簡易 bot を作成しようと思いました。

twitter-adapter が直ったら今エントリのプログラムは破棄して ruboty に移行する予定です。
どうせ捨てる予定なので、メンテナンス面などはあまり気にかけず最低限動く内容に留めます。

=> 2014/12/10追記。 ruboty twitter-adapter の動作確認とれました。私の勘違いで、利用法が間違っていただけでした。
ボット用のアカウント名にメンションを送る形でコマンドを叩くのかと思っていましたが、
アカウント名とは関係なく ruboty + コマンド内容 を叩けばいいことが分かりました。

## <i class="fa fa-cube" style="font-size:1em;"></i> 構成
* デプロイ先は Heroku
    * Heroku の登録, 利用方法に関しては詳しく書かないのでグーグル先生参照
* 環境変数の設定に dotenv gem を利用

## <i class="fa fa-files-o" style="font-size:1em;"></i> 手順
### <i class="fa fa-tree" style="font-size:1em;"></i> ファイル構成

~~~bash
$tree
.
┠ .env
┠ bot.rb
┠ Gemfile
┠ Gemfile.lock
┠ LICENSE.txt # GitHub 公開用
┠ Procfile
┗ README.md # GitHub 公開用
~~~

### <i class="fa fa-gear" style="font-size:1em;"></i> Gemfile の作成
bot に関わる依存ライブラリは bundler で管理します。
今回は twitter のライブラリ2つ（ twitter, tweetstream ）。
環境変数の設定用に dotenv。
十干十二支・干支を扱う自作 gem の eto を設定します。

~~~ruby
source "https://rubygems.org"

gem "dotenv"
gem "twitter"
gem "tweetstream"
gem 'eto'
~~~

### <i class="fa fa-gear" style="font-size:1em;"></i> Dotenv の設定
環境変数の設定のため .env ファイルを作成します。
ここに、 Twitter の認証情報を設定します。
トークンの取得方法はあちこちに情報があるので割愛。

~~~ruby
TWITTER_CONSUMER_KEY=your_consumer_key
TWITTER_CONSUMER_SECRET=your_cunsumer_secret
TWITTER_ACCESS_TOKEN=your_assecc_token
TWITTER_ACCESS_TOKEN_SECRET=your_token_secret
~~~

### <i class="fa fa-code" style="font-size:1em;"></i> bot.rb にソースコードを記述
tweeter gem については <i class="fa fa-github-square" style="font-size:1em;"></i> [tweeter](https://github.com/sferik/twitter)  
tweeterstream gem については <i class="fa fa-github-square" style="font-size:1em;"></i> [tweeterstream](https://github.com/tweetstream/tweetstream)  
eto gem については <i class="fa fa-github-square" style="font-size:1em;"></i> [eto](https://github.com/tbpgr/eto)  
をそれぞれ参照

~~~ruby
# coding:utf-8
 
require 'dotenv'
require 'twitter'
require 'tweetstream'
require 'eto'
require 'date'

class RobertGarcia
  attr_accessor :client, :stream_client

  def initialize
    Dotenv.load
    @client = new_tweet_client_instance
    @stream_client = new_teetstreem_client_instance
  end

  def tweet(text)
    @client.update(text)
  end

  def reply(text, target_id, tweet_id)
    rep_text = "@#{target_id} #{text}"
    @client.update("@#{target_id} #{text}" ,{ in_reply_to_status_id: tweet_id } )
  end

  def favorite(tweet_id)
    @client.favorite(tweet_id)
  end
 
  def retweet(tweet_id)
    @client.retweet(tweet_id)
  end

  private

  def new_tweet_client_instance
    Twitter::REST::Client.new { |config|auth(config) }
  end

  def new_teetstreem_client_instance
    TweetStream.configure do |config|
      config.consumer_key        = ENV["TWITTER_CONSUMER_KEY"]
      config.consumer_secret     = ENV["TWITTER_CONSUMER_SECRET"]
      config.oauth_token         = ENV["TWITTER_ACCESS_TOKEN"]
      config.oauth_token_secret  = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
      config.auth_method         = :oauth
    end
    TweetStream::Client.new
  end

  def auth(config)
    config.consumer_key         = ENV["TWITTER_CONSUMER_KEY"]
    config.consumer_secret      = ENV["TWITTER_CONSUMER_SECRET"]
    config.access_token         = ENV["TWITTER_ACCESS_TOKEN"]
    config.access_token_secret  = ENV["TWITTER_ACCESS_TOKEN_SECRET"]
    config
  end
end

def current_time
  DateTime.now.strftime('%Y/%m/%d %H:%M:%S')
end

robert_garcia = RobertGarcia.new
robert_garcia.stream_client.on_timeline_status do |status|
  begin
    twitter_id = status.user.screen_name
    # 私のメインアカウント以外からのツイートは無視します
    next unless twitter_id == 'tbpgr'
    tweet = status.text
    tweet = tweet.gsub("@tbpgr_bot", '')
    if /^\s*十二支 (?<year>\d{4})\z/ =~ tweet
      year = Regexp.last_match[:year]
      eto = Eto.name(year.to_i)
      robert_garcia.tweet "西暦#{year}年 の十二支は #{eto} 年"
    elsif /^\s*十干十二支 (?<year>\d{4})\z/ =~ tweet
      year = Regexp.last_match[:year]
      eto = Eto.name(year.to_i, false )
      robert_garcia.tweet "西暦#{year}年 の十干十二支は #{eto} 年"
    end
  rescue
    robert_garcia.tweet "bad request #{current_time}"
  end
end

robert_garcia.stream_client.userstream  do |tweet|
end
~~~

## <i class="fa fa-gear" style="font-size:1em;"></i> Procfile に heroku の起動設定を記述します

~~~ruby
bot: bundle exec ruby bot.rb
~~~

### <i class="fa fa-cube" style="font-size:1em;"></i> git にコミットします

~~~bash
$ git init
$ git add -A
$ git commit -m "first commit"
~~~

### <i class="fa fa-cloud-upload" style="font-size:1em;"></i> Heroku にデプロイします
※ heroku toolbelt のインストールについては Heroku の Getting Started with Ruby on Heroku を参照 

~~~bash
$ heroku login
# remote の設定に heroku を追加します
$ heroku create tbpgrbot
# プロジェクトを heroku に push します
$ git push heroku master
# 環境変数の設定
$ heroku config:add TWITTER_CONSUMER_KEY=your_consumer_key
$ heroku config:add TWITTER_CONSUMER_SECRET=your_consumer_secret
$ heroku config:add TWITTER_ACCESS_TOKEN=your_access_token
$ heroku config:add TWITTER_ACCESS_TOKEN_SECRET=your_access_token_secret
$ heroku ps:scale bot=1
~~~

### <i class="fa fa-image" style="font-size:1em;"></i> 試行
![reply.png](https://qiita-image-store.s3.amazonaws.com/0/43480/1e5a1e09-c0b2-80b4-9ac9-da8f9f92a335.png)

## <i class="fa fa-plus" style="font-size:1em;"></i> 補足
* bot の利用（ hubot / rubot を除く ）は初めてなので色々と作法的に間違っていることはあるかも

## <i class="fa fa-arrow-circle-right" style="font-size:1em;"></i> 参照
<i class="fa fa-github-square" style="font-size:1em;"></i> [TbpgrBot GitHub](https://github.com/tbpgr/ruby_twibot)