サイトアイコン Lonely Mobiler

Ruby on Rails + devise + omniauth + whenever で Twitter bot を作る

なんとなく Twitter の bot を作りたくなったので Rails を使ってやってみた。twitter の bot 動かすだけなら Rails 使う必要もないんだけど、devise とか omniauth とか使ってみたかったのでお試しということで。

多分、以下のような感じに作れるが作業ログに見落としがあるかもしれない。

github にもあげた。

https://github.com/ryomatsu/twitter-bot

Twitter アプリの登録

Twitter Application Management からアプリを以下のような感じに作成する。

https://apps.twitter.com

URL は各自の環境に合わせて設定しよう。

Rails アプリの作成

$ rails new twitter-bot $ cd twitter-bot

Twitter アプリ作成時に取得した Consumer Key と Consumer Secret を config/secrets.yml に記述する。

development: secret_key_base: c889ef... twitter_api_key: CONSUMER_KEY twitter_api_secret: CONSUMER_SECRET

必要な Gem の追加

Gemfile に以下を追加する。

gem 'devise' gem 'omniauth-twitter' gem 'twitter' gem 'whenever'

記述したら bundle install する。

devise の設定

認証を行う為の gem である devise を設定する。

$ rails g devise:intall

config/initializers/devise.rb に以下を記述する。

config.omniauth :twitter, Rails.application.secrets.twitter_api_key, Rails.application.secrets.twitter_api_secret

ユーザの作成

user モデルを作成する。

$ rails g model user provider uid access_token access_token_secret

rails g devise user 使ってもいいけど、どうせ大したことしないので普通にモデル作ってる。

このへんは以下のページを参考にした。

http://qiita.com/soramugi/items/5b2ed46e8c8b6157e7cc

コマンドを実行したら db/migrate/ 以下にある create_users.rb を編集する

class CreateUsers < ActiveRecord::Migration def change create_table :users do |t| t.string :provider t.string :uid t.string :access_token t.string :access_token_secret

t.timestamps end add_index :users, [:provider, :uid], unique: true end end

編集したらデータベースに反映させる。

$ rake db:migrate

app/models/user.rb を編集し、devise で omniauth を利用する際の処理及び Twitter で認証した際に習得できるデータを DB に保存できるようにする。

ついでに Twitter API を扱うための処理も入れておく。

class User < ActiveRecord::Base devise :omniauthable

def self.from_omniauth(auth) where(provider: auth["provider"], uid: auth["uid"]).first_or_create do |user| user.provider = auth["provider"] user.uid = auth["uid"] user.access_token = auth["credentials"]["token"] user.access_token_secret = auth["credentials"]["secret"] end end

def twitter @client ||= Twitter::REST::Client.new do |config| config.consumer_key = Rails.application.secrets.twitter_api_key config.consumer_secret = Rails.application.secrets.twitter_api_secret config.access_token = access_token config.access_token_secret = access_token_secret end end end

こうしておけば user.twitter.update('hogehoge') みたいな感じに Twitter を扱えるようになる。

omniauth での認証

Twitter で認証する際に呼ばれるコールバック関数を作成する。

$ mkdir app/controllers/users/ $ vi app/controllers/users/omniauth_callbacks_controller.rb

class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def twitter @user = User.from_omniauth(request.env["omniauth.auth"])

if @user.persisted? sign_in_and_redirect @user, :event => :authentication set_flash_message(:notice, :success, :kind => "Twitter") if is_navigational_format? else session["devise.twitter_data"] = request.env["omniauth.auth"] redirect_to new_user_registration_url end end end

ログイン画面の作成

app/views/layouts/application.html.erb の <body>直下に以下を記述する。

<% if user_signed_in? %> <%= link_to "Sign out", destroy_user_session_path %> <% else %> <%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %> <% end %> <p class="notice"><%= notice %></p> <p class="alert"><%= alert %></p>

ルーティングの設定

config/routes.rb を以下のように設定する。

Rails.Application.routes.draw do root "home#index" get "home/index" devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" } devise_scope :user do get 'sign_out', :to => 'devise/sessions#destroy', :as => :destroy_user_session end

ここまでやれば rails s でサーバ起動して Sign in with Twitter でログインし、アクセストークンをデータベースに保存できると思う。

tweet task の作成

自動で呟く際に実行するタスクを作成する。

$ rails g task tweet $ vim lib/tasks/tweet.rake

ユーザ認証しているアカウント全部で呟く処理を書く。

namespace :tweet do task :autotweet => :environment do|t, args| User.all.each do |user| user.twitter.update('ひるほー') end end end

$ rake tweet:autotweet

これでツイートできたらOK

whenever の設定

bot なので自動で呟くための仕組みを導入する。rails であれば whenever を使うのが良いらしい。gem 自体は rails new した直後に設定して入れてあるのでそれを利用する。

詳しくは以下の記事を参照してほしい。

whenever を使って rails で crontab を扱う | Lonely Mobiler

$ bundle exec wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized! $ vim config/schedule.rb

every 1.day, :at => '12:00 pm' do rake "tweet:autotweet" end

$ bundle exec whenever --update-cron --set environment=development

crontab -l でちゃんと反映されているのかを確認できる。これで自動で呟かれていたら OK だ。

Sponsored Link
モバイルバージョンを終了