ConoHa VPS +Docker で Twitter bot 的なものを作成する
某毒舌な bot を作成してみようと思い、 ConoHa VPS で作業をしました。
Docker のコンテナに Ruby で書いたスクリプトから PostgreSQL に入れた文章をツイートさせます。
使ったのは gem くらいでフレームワーク的なものは使ってないです。
ツイートさせたい文章を1ツイート1行になるような import.csv
を UTF-8 で用意しておくのも必要です。
今回は CentOS 6.5 な仮想マシンを作成して、 ConoHa の薄い本 Vol.3 ConoHa + Docker でサーバーをドカドカ立てよう!を参考に Docker を導入します。
導入して PDF の内容を一通りこなしてみてから一般ユーザーでも docker コマンドを使えるように、ユーザーを docker グループに追加します。
# gpasswd docker -a k-zoar
使い慣れた debian を pull して作業を行います。
$ docker pull debian $ docker run -i -t debian /bin/bash
とりあえず Exit して一度 Commit しました。
docker # Exit $ docker commit `dl` zoar/bot
今度はbot 用のコンテナを指定して起動します。
$ docker run -i -t zoar/bot /bin/bash
以下はコンテナ内での作業です。
とりあえず一般ユーザーを作成しておきます。
# useradd zoar # mkdir -p /home/zoar # chown zoar:zoar /home/zoar # passwd zoar # su zoar $ chsh -s /bin/bash $ exit
一般ユーザーのホームディレクトリに適当な方法で Import.csv
をコピーしておきます。
scp でどっかから取ってくるのが楽かもしれません。
Ruby と PostgreSQL をインストールします。
設定は PostgreSQL からしていきました。
# apt-get update # apt-get install ruby ruby1.9.1-dev postgresql-9.1 postgresql-server-dev-9.1 vim # service postgresql start
サービスを起動させてから postgres ユーザーになり、データベースアクセス用のユーザーを作成します。
# su postgres $ createuser -s zoar $ psql psql > alter user zoar password '%Password%'; psql > \q $ exit
一般ユーザーになってデータベース、テーブルを作成してツイートの内容をデータベースに取り込みます。
テーブルは id カラムを自動採番にして、 body カラムにツイートの内容を入れるようにしています。
# su zoar $ createdb -h localhost -U zoar tweet $ psql -h localhost -U zoar tweet psql > CREATE TABLE tweet ( id SERIAL UNIQUE, body TEXT ); psql > COPY tweet (body) from '/home/zoar/import.csv' with CSV; psql > exit $ exit
Ruby gems から PostgreSQL アクセス用の gem と Twitter 操作用の gem をインストールします。
# gem install pg twitter
一般ユーザーのホームディレクトリに PostgreSQL アクセスアカウントの情報と Twitter 投稿に必要な情報を記録しておきます。
# su zoar $ touch ./.pgaccount $ chmod 600 ./.pgaccount $ vi ./.pgaccount
ベタのテキストで1行目にデータベース接続用アカウントのアカウント名、2行目にパスワードを入力しておきます。
zoar %Password%
Twitter の情報は Twitter Application Management のサイトで適当にアプリケーションを作成して、アプリケーションとアクセストークンの Access Level を Read and write
に変更しておきます。
$ touch ./.twaccount $ chmod 600 ./.twaccount $ vi ./.twaccount
./.twaccount
も ./.pgaccount
と同じ様にベタのテキストでそれぞれ1行ずつ記録しておきます。
%Consumer Key% %Consumer Secret% %Access Token% %Access Token Secret%
ツイート用のスクリプトを適当なディレクトリに書き込みます。
$ mkdir bot $ cd bot $ touch ./sendtweet.rb $ chmod +x ./sendtweer.rb $ vi ./sendtweet.rb
スクリプトは次のような感じ
#!/usr/bin/ruby -Ku require 'pg' require 'twitter' pgacdata = [] open("/home/zoar/.pgaccount") do |pgaccount| pgaccount.each_line do |pgaccountline| pgacdata << pgaccountline.chomp end end def sendtweet(body) twacdata = [] open("/home/zoar/.twaccount") do |twaccount| twaccount.each_line do |twaccountline| twacdata << twaccountline.chomp end end client = Twitter::REST::Client.new do |config| config.consumer_key = twacdata[0] config.consumer_secret = twacdata[1] config.access_token = twacdata[2] config.access_token_secret = twacdata[3] end client.update(body) end connection = PG::connect( :host => "localhost", :user => pgacdata[0], :password => pgacdata[1], :dbname => "tweet", :port => "5432") begin result = connection.exec("Select * from tweet") $datacount = result.ntuples $getnumber = rand(1..$datacount) result = connection.exec("Select body from tweet where id=#{$getnumber}") result.each do |value| sendtweet(value['body']) end ensure connection.finish end
PostgreSQL のレコード数を確認して、乱数から適当なツイートをとってきて Twitter に投稿しています。
なんでグローバル関数のところがあるんだろうか…。その辺は適当に変えてくだし。
Ruby スクリプトを書いたら Cron から Ruby スクリプトを呼び出せるようにします。
一度一般ユーザーから exit して root で作業
# apt-get install anacron sudo # gpasswd crontab -a zoar # gpasswd sudo -a zoar
グループに追加したら cron の設定をします。
# su zoar $ crontab -e
好きなタイミングで sendtweet.rb を呼び出す内容を書き込めば OK です。
ところで、コンテナ起動時には PostgreSQL も cron も起動してくれないので次のようなスクリプトを書いておきました。
# touch /etc/start # chmod +x /etc/start # vi /etc/start
#!/bin/sh service postgresql start service cron start /bin/bash
スクリプトを書き終えたら Exit してホスト OS に戻って Commit します。
docker # exit $ docker commit `dl` zoar/bot
コンテナを動かす時には次のように起動させるとサービスも動かせます。
$ docker run -i -t zoar/bot /etc/start
docker から C-p
C-q
で抜けて設定した時間にツイートが流れれば OK です。
ホスト OS 側から操作するためにコンテナで SSH 動かしても良いかもしれません。
長々と書いたけど、もっと簡単な方法があるんだろうなぁと思ってるところです。