Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
17
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

Rubyで完全自動Mastodon botを作成する

何を作るか

1時間おきに自動トゥートしてくれるマストドン(Mastodon) bot

Mastodon botの作成

Mastodon APIを取得するCLI

bot.rb
#!/usr/bin/env ruby

require 'bundler/setup'
Bundler.require(:default)

require 'mastodon'
require 'highline/import'
require 'oauth2'
require 'dotenv'
require 'pp'

##デフォルト環境の設定
DEFAULT_APP_NAME = "mastodon-cli-sample"
DEFAULT_MASTODON_URL = 'https://mstdn.jp'
FULL_ACCESS_SCOPES = "read write follow"

Dotenv.load

##インスタンスとURLの確認
if !ENV["MASTODON_URL"]
  ENV["MASTODON_URL"] = ask("Instance URL: "){|q| q.default = DEFAULT_MASTODON_URL}
  File.open(".env","a+") do |f|
    f.write "MASTODON_URL = '#{ENV["MASTODON_URL"]}'\n"
  end
end

scopes = ENV["MASTODON_SCOPES"] || FULL_ACCESS_SCOPES
app_name = ENV["MASTODON_APP_NAME"] || DEFAULT_APP_NAME

##クライアントIDの確認
if !ENV["MASTODON_CLIENT_ID"] || !ENV["MASTODON_CLIENT_SECRET"]
  client = Mastodon::REST::Client.new(base_url: ENV["MASTODON_URL"])
  app = client.create_app(app_name, "urn:ietf:wg:oauth:2.0:oob", scopes)
  ENV["MASTODON_CLIENT_ID"] = app.client_id
  ENV["MASTODON_CLIENT_SECRET"] = app.client_secret
  File.open(".env","a+") do |f|
    f.write "MASTODON_CLIENT_ID = '#{ENV["MASTODON_CLIENT_ID"]}'\n"
    f.write "MASTODON_CLIENT_SECRET = '#{ENV["MASTODON_CLIENT_SECRET"]}'\n"
  end
end

##アクセストークンの確認(アカウントとパスワード)
if !ENV["MASTODON_ACCESS_TOKEN"]
  client = OAuth2::Client.new(ENV["MASTODON_CLIENT_ID"],ENV["MASTODON_CLIENT_SECRET"],site: ENV["MASTODON_URL"])
  login_id = ask("Your Account: ")
  password = ask("Your Password: ")
  token = client.password.get_token(login_id,password, scope: scopes)
  ENV["MASTODON_ACCESS_TOKEN"] = token.token
  File.open(".env","a+") do |f|
    f.write "MASTODON_ACCESS_TOKEN = '#{ENV["MASTODON_ACCESS_TOKEN"]}'\n"
  end
end

client = Mastodon::REST::Client.new(base_url: ENV["MASTODON_URL"],
                                    bearer_token: ENV["MASTODON_ACCESS_TOKEN"])


## messageに定期トゥートする文言を設定
message = ("test toot")
response = client.create_status(message)

## 結果の出力
pp response
Gemfile
source "https://rubygems.org"

gem "mastodon-api"
gem "highline"
gem "oauth2"
gem "dotenv"
gem "clockwork"

Mastodon botの使用方法

message変数に定期的にトゥートしたい文言を入れます。
完成したら下記を実行します。

$ ruby bot.rb
Instance URL: |https://mstdn.jp| 
Your Account: email-address@example.co.jp
Your Password: *********************

これで自分のマストドンにトゥートがされます。
また、AccountとPasswordの入力は初回のみで、アクセストークン等は.envに自動で書き込まれます。

Mastodon botの自動化

gem clockworkの利用

ここから手動ではなく、自動でトゥートしてくれるようにします。今回は、clockworkというgemを利用します。
Gemfileには、すでに記述してありますので、設定をするだけで利用できます。

clockwork.rb
require 'clockwork'
include Clockwork

every(1.hour, 'ruby.job') do
 puts `ruby bot.rb`
end
$ clockwork clockwork.rb

これで3分おきに先ほど設定したトゥートをしてくれます。時間の変更をしたい場合は数字の部分を変更したり、単位を変更したりしてください。

clockworkと似たgemにwheneverがありますが、wheneverでrubyコマンドを実行しようとする場合にはbashでシェルを作成し、rubyコマンドを登録しなければならないのでこちらを利用しています。

完全自動化

$ clockwork clockwork.rb

だとPCを閉じた時にトゥートも止まってしまいますので、完全自動のコマンドを実行します。

$ nohup clockwork clockwork.rb &

止めたいときは、

$ ps -x | grep clock
$ kill [プロセスID]

を実行します。

bot.rbとclockwork.rbのディレクトリが違う場合

ここからは、オプション設定になります。
clockworkの実行は、現在いるディレクトリ内で行われます。つまり、bot.rbとclockwork.rbが同ディレクトリ内にないといけません。

もし、ディレクトリが違う場合には、clockwork.rbを下記のように書き換えます。

clockwokr.rb
require 'clockwork'
include Clockwork

every(1.hour, 'ruby.job') do
  Dir.chdir("./test/"){ puts `ruby bot.rb` }
end
Dir.chdir("./test/")

の{}内は、$pwdでディレクトリを確認してから設定するとバグが少なくなります。

参考

このbotは、下記の記事を参考に作成しました。ほとんど下記のエントリーの組み合わせです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
17
Help us understand the problem. What are the problem?