Mastodon API を Ruby(Faraday) / Python(Pycurl) / PHP(Curl) で叩いてみた

  • 4
    Like
  • 0
    Comment

マストドンをとりあえず叩いてみました。
表題の通り、Ruby は Faraday、Python は Pycurl、PHP は Curl を使っています。
app.xx でアプリ登録を行い、test.xx で認証〜投稿の流れとしました。

Ruby

app.rb
#!/usr/local/bin/ruby
# -*- coding: utf-8 -*-

require 'faraday'
require 'uri'

CALLBACK_URL = 'アプリの URL'
MASTODON_URL = '対象とするインスタンスの URL(例: https://mstdn.high-low.ml)'
SCOPE = '欲しい権限(例: read write)'

options = {
  client_name: 'アプリの名前',
  redirect_uris: CALLBACK_URL,
  scopes: SCOPE
}

conn = Faraday.new(:url => MASTODON_URL) do |faraday|
  faraday.request :url_encoded
  faraday.response :logger
  faraday.adapter Faraday.default_adapter
end
response = conn.post do |request|
  request.url '/api/v1/apps'
  request.body = URI.encode_www_form(options)
end
print "Content-Type: application/json; charset=UTF-8\n\n"
print response.body

出力結果に表示された「client_id」と「client_secret」を保存します。

test.rb
#!/usr/local/bin/ruby
# -*- coding: utf-8 -*-

require 'cgi'
require 'uri'

cgi = CGI.new()

CALLBACK_URL = 'アプリの URL'
MASTODON_URL = '対象とするインスタンスの URL'
CLIENT_ID = 'app.rb で取得した CLIENT_ID'
CLIENT_SECRET = 'app.rb で取得した CLIENT_SECRET'
SCOPE = '指定した権限'

if cgi['code'].empty?
  # 認証を取りに行きます
  options = {
    client_id: CLIENT_ID,
    response_type: 'code',
    scope: SCOPE,
    redirect_uri: CALLBACK_URL
  }
  print cgi.header({
    'status' => 'REDIRECT',
    'Location' => "#{MASTODON_URL}/oauth/authorize?#{URI.encode_www_form(options)}"
  })
else
  # 認証されたので access_token を取りにいきます
  require 'faraday'
  require 'json'

  options = {
    client_id: CLIENT_ID,
    client_secret: CLIENT_SECRET,
    grant_type: 'authorization_code',
    redirect_uri: CALLBACK_URL,
    scope: SCOPE,
    code: cgi['code']
  }

  conn = Faraday.new(:url => MASTODON_URL) do |faraday|
    faraday.request :url_encoded
    faraday.response :logger
    faraday.adapter Faraday.default_adapter
  end
  response = conn.post do |request|
    request.url '/oauth/token'
    request.body = URI.encode_www_form(options)
  end
  access_token = JSON.parse(response.body)['access_token']

  # access_token を取れたついでに、世間の中心でぱおーんと叫びます
  options = {
    mastodon_host: MASTODON_URL,
    status: 'ぱおーん'
  }
  response = conn.post do |request|
    request.url '/api/v1/statuses'
    request.headers = {
      'Authorization' => "Bearer #{access_token}"
    }
    request.body = URI.encode_www_form(options)
  end
  print "Content-Type: application/json; charset=UTF-8\n\n"
  print response.body
end

認証画面はこんな感じです。
スクリーンショット 2017-04-19 17.37.07.png

Python

app.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import pycurl, urllib
from StringIO import StringIO

CALLBACK_URL = 'アプリの URL'
MASTODON_URL = '対象とするインスタンスの URL'
SCOPE = '欲しい権限(例: read write)'

options = {
    'client_name': 'アプリの名前',
    'redirect_uris': CALLBACK_URL,
    'scopes': SCOPE
}

response = StringIO()
curl = pycurl.Curl()
curl.setopt(pycurl.URL, '%s/api/v1/apps' %(MASTODON_URL))
curl.setopt(pycurl.WRITEFUNCTION, response.write)
curl.setopt(pycurl.POST, 1)
curl.setopt(pycurl.POSTFIELDS, urllib.urlencode(options))
curl.perform()
print "Content-Type: application/json; charset=UTF-8\n\n"
print response.getvalue()
test.py
#!/usr/bin/python
# -*- coding: utf-8 -*-

import urllib, cgi
from StringIO import StringIO

form = cgi.FieldStorage()

CALLBACK_URL = 'アプリの URL'
MASTODON_URL = '対象とするインスタンスの URL'
CLIENT_ID = 'app.py で取得した CLIENT_ID'
CLIENT_SECRET = 'app.py で取得した CLIENT_SECRET'
SCOPE = '指定した権限'

if not form.has_key('code'):
    # 認証を取りにいきます
    options = {
        'client_id': CLIENT_ID,
        'response_type': 'code',
        'scope': SCOPE,
        'redirect_uri': CALLBACK_URL
    }
    print "Content-Type: text/html\n\n"
    print '<meta http-equiv=\"refresh\" content=\"0; URL=%s/oauth/authorize?%s\">' %(MASTODON_URL, urllib.urlencode(options))
else:
    # access_token を取りにいきます
    import pycurl, json

    options = {
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET,
        'grant_type': 'authorization_code',
        'redirect_uri': CALLBACK_URL,
        'scope': SCOPE,
        'code': form['code'].value
    }

    response = StringIO()
    curl = pycurl.Curl()
    curl.setopt(pycurl.URL, '%s/oauth/token' %(MASTODON_URL))
    curl.setopt(pycurl.WRITEFUNCTION, response.write)
    curl.setopt(pycurl.POST, 1)
    curl.setopt(pycurl.POSTFIELDS, urllib.urlencode(options))
    curl.perform()
    access_token = str(json.loads(response.getvalue())['access_token'])

    # ぱおーんと叫びます
    options = {
        'mastodon_host': MASTODON_URL,
        'status': 'ぱおーん'
    }

    curl.setopt(pycurl.URL, '%s/api/v1/statuses' %(MASTODON_URL))
    curl.setopt(pycurl.HTTPHEADER, ['Authorization: Bearer %s' %(access_token)])
    curl.setopt(pycurl.POSTFIELDS, urllib.urlencode(options))
    curl.perform()

    print "Content-Type: application/json; charset=UTF-8\n\n"
    print response.getvalue()

PHP

app.php
<?php
define('CALLBACK_URL', 'アプリの URL');
define('MASTODON_URL', '対象とするインスタンスの URL(例: https://mstdn.high-low.ml)');
define('SCOPE', '欲しい権限(例: read write)');

$options = array(
    'client_name' => 'アプリの名前',
    'redirect_uris' => CALLBACK_URL,
    'scopes' => SCOPE
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, MASTODON_URL. '/api/v1/apps');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $options);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
curl_close($ch);

header('Content-type: application/json; charset=utf-8');
echo $response;
test.php
<?php
define('CALLBACK_URL', 'アプリの URL');
define('MASTODON_URL', '対象とするインスタンスの URL');
define('CLIENT_ID', 'app.php で取得した CLIENT_ID');
define('CLIENT_SECRET', 'app.php で取得した CLIENT_SECRET');
define('SCOPE', '指定した権限');

if (!isset($_GET['code'])) {
    # 認証
    $options = array(
        'client_id' => CLIENT_ID,
        'response_type' => 'code',
        'scope' => SCOPE,
        'redirect_uri' => CALLBACK_URL
    );
    header('Location: '. MASTODON_URL. '/oauth/authorize?'. http_build_query($options, '', '&'));
} else {
    # access_token 取得
    $options = array(
        'client_id' => CLIENT_ID,
        'client_secret' => CLIENT_SECRET,
        'grant_type' => 'authorization_code',
        'redirect_uri' => CALLBACK_URL,
        'scope' => SCOPE,
        'code' => $_GET['code']
    );

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, MASTODON_URL. '/oauth/token');
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $options);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $response = curl_exec($ch);
    $data = json_decode($response);
    $access_token = $data->access_token;

    # ぱおーん
    $options = array(
        'mastodon_host' => MASTODON_URL,
        'status' => 'ぱおーん'
    );

    curl_setopt($ch, CURLOPT_URL, MASTODON_URL. '/api/v1/statuses');
    curl_setopt($ch, CURLOPT_HTTPHEADER, array("Authorization: Bearer {$access_token}"));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $options);
    $response = curl_exec($ch);
    curl_close($ch);
    header('Content-type: application/json; charset=utf-8');
    echo $response;
}

参考

tootsuite/mastodon-api: A ruby interface for the Mastodon API
MastodonのAPIをcurlで叩いてみるサンプル - Qiita
Mastodon API の叩き方