背景
HerokuでBot作りたかったので,下記サイトの記述通りやった.
一昨日はじめてRuby触って文法すらわからなかったけど,コピペでなんとかなるだろと思っていた.
記述が丁寧で大変参考になる記事なのだが,執筆時が2011年と古く,ソフトウェアの仕様変更のために結局コピペだけでは動かなかった.Ruby素人(筆者)が動くようにするまでの試行錯誤をまとめる.
ソースコード
Gistに,本記事で指摘する反映点を全て含んだコードをおいておきました.
なお,組んだBotはこいつ.実装時点では,1日1回朝9時につぶやく.事前にハードコードした31日分の文を繰り返しつぶやく.
注意
参考記事では,まず手動でBotの動作を確認してから自動化していますが,Gistにあげたソースコードは最初から自動でツイートすることが前提の設定になっているので注意.
本記事の使い方
この資料はあくまで上記事実装を2014年11月時点で動かすことを目的とした補足です.詳細な手順は上述のサイトを参照してください.
先に本記事の目次に目を通しておき,元記事の通りに進め,本記事で指摘された項目が出てきた時点で本記事を読むという使い方を推奨します.
補足:本ソースコードを利用した際の手順の概要(自動ツイートするBotの作成)
- Twitter側の設定
- Twitterアカウントを作成する
- Twitterのアプリケーション登録を行い,Consumer keyとConsumer secretをメモする.
- Twitter GemでOAuthに必要なトークンを取得する.
- 環境設定
3. Ruby環境を整える(Gemのインストールなど).
3. Heroku Toolbertのインストール.
2. 作業ディレクトリを作って$ git init
する. - コーディング
- 上記の全てのソースコードを入れる.
- "tweet.rb"のトークン部分を自分のトークンに差し替え,つぶやかせたい文を31行分書く.また"Gemfile"のRubyのバージョンを自分の利用しているバージョンに置き換える.
-
$ bundle install
を実行して依存関係のあるパッケージを導入.パッケージの情報が記録されたファイル(Gemfile.lock)を作成.
参考:Gem - Bundler概要 - Qiita - Herokuでの公開
- Herokuにアプリを作成する(
heroku create [app. name]
). - Herokuにローカルで作ったアプリを公開する(
$ git push heroku master
). - Herokuにアドオンを導入して自動ツイートのための設定を行う.
では実際にBotを作っていこう.基本的には上記サイトのとおりに環境を設定していく.2014年11月時点で,ソフトウェアのバージョンの差異によって詰まった点とその解決策を,上記サイトの節に沿って解説します.
「1. プロジェクトの準備」に関する注意点
Ruby環境を導入する際の注意
複数バージョンのRubyを入れたい場合,バージョン管理ソフトrbenv入れておくと便利.RVMという管理ソフトもあるらしいがrbrnvの方が軽量のよう.詳しくは参考サイトを参照されたい.
Homebrewを使ってrbenvを導入する.
$ brew install rbenv
表示される指示に従って.bash_profileや.bashrcの適切な場所に以下を書き込む.僕はzshを使っているので,とりあえず.zshrcに全部ぶち込んだ.
### rbenv
# To use Homebrew's directories rather than ~/.rbenv
export RBENV_ROOT=/usr/local/var/rbenv
# To enable shims and autocompletion
if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi
export RBENV_ROOT=/usr/local/var/rbenv
参考
「必要なgemのインストール」に関する注意点
元記事ではgemをインストールする際一気に入れていて,その中で$ gem install heroku
としてHerokuでのアプリを作成するために必要なツールを入れているが,
ドキュメントを読むとHeroku Toolbeltからインストールせよとあるので従う.
$ gem install sinatra bundler get-twitter-oauth-token --no-rdoc --no-ri
なお,ドキュメントが必要な場合--no-rdoc --no-ri
を外しておく.
「3. プログラミング」に関する注意点
成功した際に利用したソフトウェアのバージョン
- ruby 2.1.4p265 (2014-10-27 revision 48166) [x86_64-darwin14.0]
- RubyGems(2.2.2)
- twitter (5.12.0)
- get-twitter-oauth-token (1.1.0)
- sinatra (1.4.5)
問題1. requireで指定したファイルが見つからない
$ heroku logs | grep Error (git)-[master]
2014-11-06T00:18:39.206506+00:00 app[web.1]: /app/config.ru:1:in `require': cannot load such file -- app.rb (LoadError)
原因:Rubyのバージョンが新しい
Ruby 1.9.2 以降は $LOAD_PATH にカレントディレクトリが含まれない
Rubyのrequireで相対的にパスを指定する方法 - QA@IT
参考にした記事ではrubyのバージョンは1.8.7だったので,カレントディレクトリがちゃんと読み込まれていた.
解決策:require_relativeを使う
自作のコードをrequire
している部分を全てrequire_relative './tweet.rb'
のように書き換える.
参考
- Error with Ruby Twitter API - Stack Overflow
- Ruby 1.9.2p0 で requireとrequire_relativeについて調べてみた - tagomorisのメモ置き場
問題2. Twitter認証ができない
$ heroku logs | grep Error (git)-[master]
2014-11-06T00:43:15.473638+00:00 app[web.1]: NoMethodError - undefined method `configure' for Twitter:Module:
原因:Twitterライブラリの仕様変更
RubyGems ライブラリ Twitter のバージョン 5.0.0 以上(?)ではエラーが発生する。
Ruby - Twitter Gem 不具合! - mk-mode BLOG
$ gem list | grep twitter
twitter (5.12.0)
解決策(不完全)
Twitter(RubyGems)v.5.12.0のドキュメントを見ながら直していこう.
まず,TweetクラスのTwitter認証に関する以下の部分を修正する.
# 修正前
Twitter.configure do |config|
config.consumer_key = 'メモったConsumer keyを挿入する'
config.consumer_secret = 'メモったConsumer secretを挿入する'
config.oauth_token = 'メモったTokenを挿入する'
config.oauth_token_secret = 'メモったSecretを挿入する'
end
修正後のコードは次のようになる.
# 修正後
client = Twitter::REST::Client.new do |config|
config.consumer_key = "YOUR_CONSUMER_KEY"
config.consumer_secret = "YOUR_CONSUMER_SECRET"
config.access_token = "YOUR_ACCESS_TOKEN"
config.access_token_secret = "YOUR_ACCESS_SECRET"
end
update
メソッドのTwitter.update(tweet.chomp)
を以下のように変更.
client.update(tweet.chomp)
この状態で再度git push heroku master
すると,Herokuのページには何も表示されず,混乱する.
何も表示されず真っ白なページなら失敗!
という元のページの文章が頭をよぎる.
とりあえず$ heroku logs | grep Error
するも該当なし.
rubyの文法わからないけどメンバ変数とかの問題と当たりをつけてググる.インスタンス変数の頭には@が付いているらしい.これがないからか!
続・解決策(完全)
インスタンス変数に@をつける.
@client = Twitter::REST::Client.new do |config|
@client.update(tweet.chomp)
再度git push heroku master
してrandom_tweetページに移動すると,無事動作することが確認できる.ただしTwitter gemの仕様変更によりページは白紙のままである.なぜページが白紙のままなのかについての詳細は,コメント欄のriocamposさんによる丁寧な解説を参照ください.
「4. 公開」に関する注意点
Herokuに公開鍵を設定しようとすると怒られる問題
heroku keys:add
するとApplication Errorが出る.
解決策:連続2回トライする
これで通ってしまった.なぜ?
参考
問題3. rubygemsが古い
$ heroku run bundle exec ruby task.rb (git)-[master]
Running `bundle exec ruby task.rb` attached to terminal... up, run.8527
The source :rubygems is deprecated because HTTP requests are insecure.
Please change your source to 'https://rubygems.org' if possible, or 'http://rubygems.org' if not.
解決策
rubygemはセキュアじゃないので廃止予定だから変更しろと言われている.
Gemfileのsource :rubygems
を言われたとおりに変更する.
source 'https://rubygems.org'
これでエラーは出なくなりました.
問題4. 連投できない
二回以上連続でruby task.rb
を実行しても(つまり内容の同じツイートを二回以上つぶやこうとしても)できませんでした.これは内容が重複している場合にTwitter側が投稿を制限するためです.
一定時間内に同じツイートをすることができないようです.直前の発言のみに制限されるわけではありません.例えば内容hogeをつぶやいた後にhogeをつぶやくのはもちろんだめですが,hoge→hage→hogeとワンクッション程度おいても制限されます.
なお,Twitterヘルプセンターには制限の解除されるために必要な時間は書いてありませんでした.
解決策:連続で同一投稿を投稿をしない
問題解決になっていませんが,とりあえず同一投稿をするのを避けましょう.
10ツイート挟むと同じ投稿が可能
という実験をした人がいます(2011年時点).
24時間おけば同一内容でも大丈夫という意見も見つけましたがソースが見つからず.
※コメント欄で「6時間ぐらい空けば同一ツイート連投もOKという印象」という意見も頂いています.要テスト.
参考
問題5. Herokuにcronがない
解決策:Heroku Schedulerを使う
他にもいくつかあったので気になる方はググられたし.
なお,常時データを監視する際にはclockworkというGemを使うのがいいっぽいです.
※コメント欄で教えていただいた情報によると,rufus-schedulerというgemを使うと秒単位まで指定できる.
インストールする.
$ heroku addons:add scheduler:standard
スケジューラーを開いて設定する.
$ heroku addons:open scheduler
GUIが開かれるので,jobを追加して次のコマンドを入れる
bundle exec ruby task.rb
"task.rb"が実行されるたびにツイートされるので,好きな時刻を設定する.
実行時間のタイムゾーンがUTC(世界協定時)固定なので,JST(日本標準時)にするためには時差を足す必要があります. UTC = JST - 9h
です.
例えば日本時間19時にツイートしたければUTCの10時に設定します.
なお,schedulerの実行時間のデフォルトをJSTにしたくて,HerokuのタイムゾーンをJSTにしても変わりませんでした.できた人教えてください.