LoginSignup
13
14

More than 5 years have passed since last update.

ruby で Mastodon の Streaming API を受信する

Posted at

Mastodon の bot 等を作るために Streaming API を取得したかったのですが mastodon-api gem には REST API しかなかったのと、具体的なコード例がなかったのとでいくらか調査が必要でした。
その調べた結果を残しておきます。

以下の記事も参考にしました
「PHPでMastodonのStreaming APIを受信する」
http://qiita.com/yyano/items/841f79266faf2dc8b6dc

Streaming API 概要

タイムラインや通知を Websocket で受け取ることができます。
URL は https://(インスタンスのURL)/api/v1/streaming
アプリケーションの API アクセストークンとタイムライン種類をクエリで渡すことができます https://(インスタンスのURL)/api/v1/streaming?access_token=(アクセストークン)&stream=[user|public|hashtag]

アクセストークンの取得については他の Mastodon API 解説記事を参照してください。

faye-websocket gem を使う例

以下の gem を使うのでインストールする。

  • eventmachine
  • faye-websocket
require "eventmachine"
require "faye/websocket"

INSTANCE="(インスタンスのURL)"
TOKEN='(アクセストークン)'
TL='user'

EM.run do
  conn = Faye::WebSocket::Client.new(
    "wss://#{INSTANCE}/api/v1/streaming?access_token=#{TOKEN}&stream=#{TL}",
  )

    conn.on :open do |e|
        puts "connection success."
    end

    conn.on :error do |e|
        puts "error occured."
    end

    conn.on :close do |e|
        puts "connection close."
    end

    conn.on :message do |msg|
        puts "message receive."
        puts msg.data
    end
end

websocket-client-simple gem を使う例

必要なのは client だけだとか、eventmachine でネイティブエクステンションをインストールしたくないとかいった場合 websocket-client-simple を使うのが良いです。

以下の gem を使うのでインストールする。

  • websocket-client-simple
require 'websocket-client-simple'

INSTANCE="(インスタンスのURL)"
TOKEN='(アクセストークン)'
TL='user'

url = "https://#{INSTANCE}/api/v1/streaming?access_token=#{TOKEN}&stream=#{TL}"

# --- streaming receiver
begin
  ws = WebSocket::Client::Simple.connect(url)
rescue => e
  puts "error: #{e}"
else
  ws.on :message do |msg|
    puts "!message"
    p msg
  end

  ws.on :open do
    puts "streaming open"
  end

  ws.on :close do |e|
    puts "close"
    p e
    exit 1
  end

  ws.on :error do |e|
    p e
  end
end

loop do
  sleep 1
end

簡単な bot のサンプル

メンションで「にゃーん」と言われたら、相手に「にゃーん」と返す簡単な応答 bot です。
Streaming API で通知を監視し、該当のメンションを見つけたら REST API で応答しています。

以下の gem を使用しています

  • mastodon-api
  • websocket-client-simple
  • nokogiri
# coding: utf-8
require 'mastodon'
require 'websocket-client-simple'
require 'nokogiri'
require 'json'

# --- debug switch
VERB = true

# --- config
INSTANCE="(インスタンスのURL)"
TOKEN='(アクセストークン)'
TL='user'

BASEURL = "https://#{INSTANCE}" 
STREAMURL = "#{BASEURL}/api/v1/streaming?access_token=#{TOKEN}&stream=#{TL}"


queue = Queue.new
mastodon_client = Mastodon::REST::Client.new(base_url: BASEURL, bearer_token: TOKEN)

# --- action
def answer(request)
  result = {}
  p request if VERB
  contents = Nokogiri::HTML.parse(request["status"]["content"])
  text = ''
  contents.search('p').children.each do |item|
    text += item.text.strip if item.text?
  end
  #
  if text == "にゃーん"
    result[:username] = request["account"]["username"]
    result[:answer] = "にゃーん"
  end
  #
  p result
  return result
end

# --- streaming receiver
begin
  ws = WebSocket::Client::Simple.connect(STREAMURL)
rescue => e
  puts "error: #{e}"
else
  ws.on :message do |msg|
    if msg.data.size > 0
      begin
        toot = JSON.parse(msg.data)
        if toot["event"] == "notification"
          body = JSON.parse(toot["payload"])
          if body["type"] == "mention"
            puts "!message" if VERB
            res = answer(body)
            if res.size > 0
              queue.push(res)
            end
          end
        end
      rescue => e
        puts "content parse error."
        puts e
      end
    end
  end

  ws.on :open do
    puts "streaming open"
  end

  ws.on :close do |e|
    puts "close"
    p e
    exit 1
  end

  ws.on :error do |e|
    p e
  end
end


# --- wait loop and response sender
loop do
  action = queue.pop
  if action.key?(:username) && action.key?(:answer)
    toot = "@#{action[:username]} #{action[:answer]}"
    begin
      result = mastodon_client.create_status(toot)
      p result if VERB
    rescue => e
      p e
      exit 1
    end
  end
  sleep 0.2
end
13
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14