Edited at

【Rails】Twitterでサンタコスbotを作る

More than 1 year has passed since last update.


概要

せっかくのAdvent Calendarなので、クリスマスに関連するアプリを作りたいですね

ちなみに、TECH::CAMP Advent Calenderでは、二日目に以下のような記事がすでに投稿されております!

【Swift】Twitter APIを使ってサンタコス女子を探す

二日目の記事では、サンタコスを探すアプリだったので、今回はサンタコスの画像をTwitterに発信しようかと!

つまり


Twitter bot

ですね!

ちなみに、検索してもらうとわかるのですが、Twitterのbotの作り方の記事ってたくさんあるのですね!もちろん、rubyを使ったものも多いです。。

そこで、この記事では、特に以下のような点を意識して書きます!


1. Railアプリであること

まず、rubyで動かすbotの記事は多いですが、railsまで使う記事はあまりありませんでした。特に、データベースを活用したRailsアプリによるbotがあまりありませんでした。

そのため、この記事では、Railsを使用して、以下のようにツイートを画像URL付きで保存する機能をつけます。

そこから、二段階に分けて、最初は手動でのランダム投稿、その次に自動化するようにします!

a61b6fc981c70bc12f29e1b7c6931130.gif

これが最初につくる手動でのランダム投稿

3f0a513aead578f146e8fd68978226fb.gif

そうすると、、、

35050eb53d29609b26ec1fdef7e3608a.png

この記事では、最初に、基本的な手続きを踏んで、railsアプリを作成するので、是非Railsの基礎だけ学んだような人にも見てもらいたいです


2. wheneverを使用した自動投稿

最初は手動でツイートできるようにしますが、やはりbotなので自動で動かしたいですね!

そこで、wheneverを使用して、一定時間ごとにデータベースに保存したツイートをtwitterに自動投稿する機能を作ってみます。


3. twitterのgemの最新版を使用

twitterのgemは、最新版で少し記述の仕方が変わったようです。そのため、古い記事通りに作るとうまくいかないこともあるようです。ですので、ここでは最新版の書き方に従って書きます。


4. 画像付きツイートのbot

まあこれはそれ用のメソッド使えばできます笑


5. サンタコスbot

季節限定感出します(サンタコス以外のbotでも作り方は全く一緒です! 実際、最初は飯テロアプリのつもりでした笑)


6. おまけ(サンタコスツイートを検索してお気に入り登録(いいね)する)付き

個人的にはおまけの項が一番やりたかったことです笑


環境

・Ruby 2.1.3

・Ruby on Rails 4.2.4


目次

Ⅰ Railsアプリにツイートを保存する機能を作る

Ⅱ RailsアプリとTwitterを連動させる

Ⅲ wheneverを使用して自動投稿できるようにする

Ⅳ 完成コード

Ⅴ おまけ(サンタコスツイートを検索してお気に入り登録(いいね)する)

 


それでは作っていきましょう(゚∀゚)


Ⅰ Railsアプリにツイートを保存する機能を作る

この章では、Railsの基礎的な話なのでさくさくいきます!わかる人は飛ばしてください!


1. アプリを作り始める(慣れているのでmysqlでいきます)

$ rails new santacosbot -d mysql

$ cd santacosbot

最新版(2015年12月6日現在)のmysqlがエラーするので、mysqlの記述を上書き

gem 'mysql2', '0.3.18'

それで

$ bundle install

$ rake db:create

これで最低限の準備は整いました。


2.ツイートの投稿と保存まで

ルーティング


route.rb

Rails.application.routes.draw do

root 'tweets#new'
resources :tweets, only: [:new, :create]
end

コントローラー

$ rails g controller tweets

できたコントローラーファイルを以下のように編集


tweets_controller.rb

class TweetsController < ApplicationController

def new
@tweet = Tweet.new
end

def create
Tweet.create(create_params)
redirect_to :root
end

private
def create_params
params.require(:tweet).permit(:text, :image)
end
end


ビューファイル(自分しか使わないから見栄えは気にしない方針で)

一応twitterなので140文字の制限だけつけておきます!(追記:画像付きツイートしか保存しない方針なら、116文字で大丈夫だそうです。画像へのリンクが付くことによって入力できる文字数が減るからです。)


new.html.erb

<%= form_for @tweet do |f| %>

<%= f.text_area :text, cols: 40, rows: 5 ,maxlength: 140 %>
<%= f.text_field :image %>
<%= f.submit '保存' %>
<% end %>

テーブル・モデル

$ rails g model tweet

で、マイグレーションファイルを以下のように編集


201oooooooooo_create_tweets.rb

class CreateTweets < ActiveRecord::Migration

def change
create_table :tweets do |t|
t.text :text
t.text :image
t.timestamps
end
end
end

そして、実行



$ rake db:migrate

これで、以下のようなフォームからツイートを保存をすることだけはできるようになったはずです!!

cef0d90571bdbf6e8a8e45e043359c2b.png


Ⅱ RailsアプリとTwitterを連動させる


1.Twitterアカウントを作る(電話番号も登録する)

・すでにあるアカウントを使用しない場合は以下から新規アカウントを作成。

Twitterをはじめましょう

8ac66bda93cc1b95873010be5fe0cb54.png

*ちなみに電話番号の登録と認証をしておかないと、下のアプリ登録が出来ないので登録しておきましょう

*一つの電話番号を複数のアカウントに登録できるので、他のアカウントとの兼ね合いの心配は要りません

*電話番号の登録がうまくいかない人は下記を参照

Twitterで携帯電話番号の登録に失敗する


2.Twitterのアカウントにアプリ登録をする

Twitter Applicant Management

「Create New App」ボタンを押して、設定をはじめましょう。

028fc0c5b6a0853237c5c34a4e7fed57.png

a94cfd429de15caabc913d854fc2769a.png

Name(アプリの名前)、Description(アプリの説明、10文字以上必要)、Website(自分のウェブサイト等)は必須なので入力しましょう。

このうち、Nameはアプリの名前なのでちゃんと書きたいのですが、他はあまり重要でないのでとりあえず埋めておきましょう。

WebsiteはもはやTwitterのURLでもいいです(笑)


3.必要なキーを入手しよう

・Consumer Key(API key)

・Consumer Secret(API secret)

・Access token

・Access token secret

この4つが、アプリから連携する上で必要なのでこの4つのキーを取得して、記録しておきます。

登録済みアプリのページの「Keys and Access Tokens」のタブからすべて取得できます。

「Keys and Access Tokens」のタブの一番下の「Create my access token」を押します。

そうすると、下記のように必要なキーが取得できます。

ちなみに、access levelの設定が「Read and Write」以上であることを確認してください。違っていたら、「permission」タブから読み込みと書き込みができるように設定を変更しておいてください。

70429643e89f8ab610f9cec8688489b3.png

手続きに困ったら下記のサイトを参考にしてください。

RubyでTwitter Botをつくる

これでTwitter側の設定は完了となります!


4. RailsアプリにTwitterと連携の設定をする

まず、以下のgemを追加

gem 'twitter'

$ bundle install

これでtwitterのgemが使用可能になりました!

基本的に下記の記述をどこかに書けば、twitterと連携することができます。(古いversionのtwitter gemと記述の仕方が異なります。)

client = Twitter::REST::Client.new do |config|

config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end

今回は下記のように、controller内に書いてbefore_actionで動かそうかと思います。


tweets_controller.rb

class TweetsController < ApplicationController

before_action :twitter_client, except: :new

def twitter_client
@client = Twitter::REST::Client.new do |config|
config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end
end
end


これで、@clientに対してツイートするメソッドを実行することで、実際に投稿できるようになります。

そして、投稿するメソッドも書いてルーティングを設定してあげましょう。


tweets_controller.rb

def post

tweet = Tweet.order('rand()').first
status = tweet.text
media = open(tweet.image)
@client.update_with_media(status, media)
redirect_to :root
end


route.rb

Rails.application.routes.draw do

root 'tweets#new'
resources :tweets, only: [:new, :create] do
collection do
get 'post'
end
end
end

そして、とりあえず手動で動かしたいので、ツイートをデータベースに投稿する画面に「ツイート」ボタンを作りましょう。


new.html.erb

<hr>

<button type="submit" style = "width: 70px; height: 25px;"><%= link_to 'ツイート', post_tweets_path %></button>

これで「ツイートボタンをおすことで、tweetsテーブルに保存されたツイートからランダムでtwitterに投稿されます。


基本機能完成

これでとりあえず、ローカルで自分で叩けば動くようになりました(自分しか使わない前提なので見栄えは気にしないでください笑)。

上部に、ツイートしたい文章と、画像のURLを貼ります!

これで、ツイートが保存されます

a61b6fc981c70bc12f29e1b7c6931130.gif

そして、「ツイート」ボタンを押すと、保存されたツイートからランダムに一件ツイートされます!

3f0a513aead578f146e8fd68978226fb.gif

そうすると、、、


Twitterに投稿できました!!ワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

2c6a845fa3edb1ffca4a75fa383b8bce.png


Ⅲ wheneverを使用して自動投稿できるようにする

ここまでは手動でのツイートでしたが、せっかくのbotなので自動でもできるようにしたいですね。ですので、ここからはwheneverのgemを使用します。

まず、以下のgemを追加

gem 'whenever', require: false

$ bundle install

次に、wheneverで動かしやすいようにrakeタスクを作りましょう

$ rails g task twitter

そうすると、lib/tasks以下に'twitter.rake'という名前のファイルができるので編集していきます。


lib/tasks/twitter.rake

namespace :twitter do

desc "random_tweet"
task :tweet => :environment do
twitter_client
tweet = Tweet.order('rand()').first
status = tweet.text
media = open(tweet.image)
@client.update_with_media(status, media)
end
end

def twitter_client
@client = Twitter::REST::Client.new do |config|
config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end
end


基本的にはコントローラにのpostに書いた内容と同じです。これで

$ rake twitter:tweet

のコマンドでツイートができるか確認してみましょう

そして、wheneverでこれを自動化していきましょう

$ wheneverize .

のコマンドを入力して、configにschedule.rbのファイルを作ります。

それを以下のように編集


config/schedule.rb

require File.expand_path(File.dirname(__FILE__) + "/environment")

set :output, 'log/crontab.log'
set :environment, :development

#2時間ごとに動かす
every 2.hours do
rake 'twitter:tweet'
end


とりあえず二時間ごとに設定するために以下のようにしましたが、時間の指定の仕方はいろいろあるので以下を参考にカスタマイズしてください

Wheneverは導入が超簡単なcrontab管理ライブラリGemです![Rails4.2]

これで、あとは、このファイルを起動させれば自動ツイートされます。

$ whenever --update-cron #起動

$ whenever #起動中に起動内容確認

$ whenever --clear-crontab #終了

ですので、一番上の起動のコマンドを打てば動きます!

以上です!!!

これで完成となりますワーイヽ(゚∀゚)メ(゚∀゚)メ(゚∀゚)ノワーイ

完全に全自動になるようにしたい方は、オンラインサーバーにもあげましょう(Herokuを使用する方は一番下の注意の項を読んでください)


Ⅳ 完成コード


routes.rb

Rails.application.routes.draw do

root 'tweets#new'
resources :tweets, only: [:new, :create] do
collection do
get 'post'
end
end
end



tweets_controller.rb

class TweetsController < ApplicationController

before_action :twitter_client, except: :new
def new
@tweet = Tweet.new
end

def create
Tweet.create(create_params)
redirect_to :root
end

def post
tweet = Tweet.order('rand()').first
status = tweet.text
media = open(tweet.image)
@client.update_with_media(status, media)
redirect_to :root
end

def twitter_client
@client = Twitter::REST::Client.new do |config|
config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end
end

private
def create_params
params.require(:tweet).permit(:text, :image)
end
end



new.html.erb

<%= form_for @tweet do |f| %>

<%= f.text_area :text, cols: 40, rows: 5 ,maxlength: 140 %>
<%= f.text_field :image %>
<%= f.submit '保存' %>
<% end %>
<hr>
<button type="submit" style = "width: 70px; height: 25px;"><%= link_to 'ツイート', post_tweets_path %></button>


gemfile

gem 'mysql2', '0.3.18'

gem 'twitter'
gem 'whenever', require: false


20oooooooo_create_tweets.rb

class CreateTweets < ActiveRecord::Migration

def change
create_table :tweets do |t|
t.text :text
t.string :image
t.timestamps
end
end
end


lib/tasks/twitter.rake

namespace :twitter do

desc "random_tweet"
task :tweet => :environment do
twitter_client
tweet = Tweet.order('rand()').first
status = tweet.text
media = open(tweet.image)
@client.update_with_media(status, media)
end
end

def twitter_client
@client = Twitter::REST::Client.new do |config|
config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end
end



schedule.rb

require File.expand_path(File.dirname(__FILE__) + "/environment")

set :output, 'log/crontab.log'
set :environment, :development

every 2.hours do
rake 'twitter:tweet'
end



Ⅴ おまけ(サンタコスツイートを検索してお気に入り登録(いいね)する)

せっかくなので、railsで旬なサンタコスツイートを検索してお気に入り登録する方法も書いておきますね

個人的にはこれが一番やりたかった

rakeファイルなりコントローラーなりに以下の記述すればできます(ここではrakeファイルに書いた場合)


lib/tasks/twitter_search.rake

namespace :twitter_search do

desc "favorite_santa_tweet"
task :tweet_search => :environment do
twitter_client
query = "#サンタコス"
results = @client.search(query, count: 100, result_type: "recent", exclude: "retweets", filter: "images")
results.take(100).each do |tw|
@client.favorite(tw.id)
end
end
end

def twitter_client
@client = Twitter::REST::Client.new do |config|
config.consumer_key = "自分のConsumer Key(API key)"
config.consumer_secret = "自分のConsumer Secret(API secret)"
config.access_token = "自分のAccess token"
config.access_token_secret = "自分のAccess token secret"
end
end


基本的にコードみればわかると思いますが、searchメソッドで検索して、takeメソッドで件数の指定をした上でお気に入り登録していきます。

ちなみにお気づきの方もいるかと思いますが、このgemのメソッドを使用すれば、ツイートを検索して取得できます。

つまり、そこから画像を取得してデータベースに保存することも、、、いわゆるスクレイピングですね笑

そうすればそこからその画像を再利用してツイートすることもできちゃいますね笑

ただ、それを本当にやっていいのかわからないのと、同じadvent calenderの【Swift】Twitter APIを使ってサンタコス女子を探すとやってることがかなりかぶるのでここでは書きません笑

やりたい方は、上記のリンクを見てみてください(swiftわからなくてもわかります笑)

以上で終了となります。このように、Twitterのgemを使うと遊べることがたくさんありますね笑

(ネットストーカー御用達ですね)

とりあえず、今回はこれで終わりにしますが、またTwitter関連で記事を書こうかなと思います!


注意

・アカウント凍結に注意しましょう。

Twitterでは、一定時間内に投稿できる件数が決まっております。また、一定時間内に同じツイートを連続投稿するのもまずいみたいです。うまく動かなくてツイートボタンを連打してたらアカウント凍結されてたみたいにならないようにしましょう笑

・このままHerokuなどのサーバーにアップする場合は、ビューのツイートボタンにパスワードの入力フォームを入れて、postアクションにパスワード認証をつける

これは上記のアカウント凍結を避けるためです。Herokuなどにあげると、もし第三者がアクセスできてしまった場合に、ツイートボタンを押されないようにするためです。

・Herokuでは、wheneverは機能しない

wheneverによる自動ツイートを残したままオンラインサーバーにあげたいときはさくらVPSあたりを使用しましょう

Herokuでやる場合は、アドオンのschedulerを使用しましょう。

heroku schedulerの使い方(Rails,sinatra)


参考

RubyでTwitter Botをつくる

[Rails4] wheneverを使ってcrontabを管理して、cronを回す

3分でスッキリ! Oauth 1.0図解とRuby Twitter bot開発

rubyでtwitterのbotを実装する(第5世代のやり方)

Wheneverは導入が超簡単なcrontab管理ライブラリGemです![Rails4.2]

Twitter gemでツイート検索する場合の要点、及び:since_id指定を有効にするモンキーパッチ

Twitterで携帯電話番号の登録に失敗する