【OAuth2】フォルダ内の画像をまとめてTumblrに予約投稿する

指定したローカルフォルダ内の画像を全て、Tumblrのキューに追加(予約投稿に一括投稿)する方法を解説します。
OAuth2で認証して、TumblrのAPIを使用します。

Tumblr APIガイドに従って進めます。

アプリケーションの登録

まずはTumblr APIにアプリの登録をします。

Register - Login
Tumblr. Pure effervescent enrichment. Old internet energy. Home of the Reblogs. All the art you never knew you needed. A...

ログインし、”アプリを登録する”をクリックします。

アプリケーションの登録
アプリケーション名

何でも良いですが、ここでは”bulk_post_for_queue”とします。

アプリケーションウェブサイト

今回はWebアプリではないので何でも良いです。機能には影響しません。自分のブログなりSNSがあればそのアドレスでも良いと思います。

アプリケーションの説明

何でも良いですが、ここでは“add multiple images to the queue all at once”とします。

管理用の連絡先メール

自分のメールアドレスを入力します(特に使いません)。

デフォルトのコールバックURL

OAuth1用ですので今回は使いませんが、OAuth2リダイレクトURLと同じにしておきます。

OAuth2リダイレクトURL

下記のステップ2で使用します。

今回はlocalhostに簡易サーバーを立ち上げてhttp://localhost:8000とするのがシンプルだと思います。127.0.0.1は仕様のためか登録できません。
Webアプリを作成するのであればそのアドレスで良いでしょう。
存在するアドレスなら、例えばhttps://www.google.com/でも可能だとは思います。twitter(X)やgoogleのAPIでは存在しないアドレスでも可能なようですが、tumblrの場合は正常に表示される必要があります。

OAuth2リダイレクトURLをhttp://localhost:8000とする場合、60秒(任意)だけサーバーを立ち上げる、pythonコードの例を示します。

from http.server import HTTPServer, BaseHTTPRequestHandler
import threading

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()
        self.wfile.write(b"Hello, world!")

def start_server(duration=60):
    port = 8000
    httpd = HTTPServer(('', port), Handler)
    print(f'HTTPServer started -> http://127.0.0.1:{port}')

    server_thread = threading.Thread(target=httpd.serve_forever)
    server_thread.start()

    shutdown_timer = threading.Timer(duration, httpd.shutdown)
    shutdown_timer.start()

    server_thread.join()

if __name__ == "__main__":
    start_server(60)  # 60秒後に閉じる

このアプリに対して、userがuserのリソースサーバー(今回はTumblrのアカウント)へのアクセス許可を出すと、http://localhost/?code=****のような形で、OAuth2リダイレクトURLにクエリとしてアクセストークン取得用のcodeが付与され、userをリダイレクトします。
つまり、標準ブラウザで{OAuth2リダイレクトURL}?code=***が開きます。

その他の項目はそのままで、登録します。

登録したアプリを確認します。

アプリ一覧

OAuth Consumer Keyと、Secret keyが必要です。Secret keyは、Show secret keyをクリックすると表示されます。

ステップ1 OAuth2認証

The OAuth2 Authorization flow – Step One

userをTumblrのOAuth2認証エンドポイントにリダイレクトします。
つまり、アプリ(Your application)がuserのTumblr API(リソースサーバー)にアクセスすることを、userが許可するよう促します。
方法は次のリンクの通りです。

Authorization Request

具体的には以下のようなアドレスを作成し、userにアクセスさせます。

https://www.tumblr.com/oauth2/authorize?client_id={Your OAuth consumer Key}&response_type=code&scope=basic%20write&state=abcdefghijkl
URI

www.tumblr.com/oauth2/authorize

client_id String

Consumer key

response_type

常にresponse_type=codeです。

scope

APIが許可をする範囲です。今回はscope=basic%20writeです。

state

CSRF攻撃を防ぐためのパラメータです。予測しにくい文字列とします。コードに組み込む場合は

state = hashlib.sha256(os.urandom(32)).hexdigest()

のような形で生成します。

stateの役割について:
一旦下記のステップ2まで読むとわかりやすいと思います。
例えば設定したOAuth2リダイレクトURLのサーバーにおいてYour applicationがリダイレクトを待機した状態(ステップ2を待機した状態)であるとします。Your applicationはステップ1の処理をしたかもしれませんし、まだかもしれません。

ステップ2のリダイレクトURLの代わりに、悪意のある攻撃者が自分のリダイレクトURL(攻撃者のアクセストークン発行用のcodeを含む)をuserにクリックさせた場合、Your applicationは攻撃者のcodeを用いてアクセストークンをリクエストしてしまいます。すると攻撃者のTumblrが認証されたとみなされ、攻撃者のアクセストークンを用いてuserの情報を送ってしまう可能性があります。

これを防ぐため、リダイレクトURLにはcodeとともにstateがクエリとして含まれており、Your applicationがstateの有無および値の確認をすることで、userのcodeではないことに気づくことができます。Your applicationが送ったリクエストであれば、リダイレクトURLにはYour applicationが送ったstateが付与されているはずだからです。

redirect_uri

不要です。もし入れるのであればOAuth2リダイレクトURLと一致させます。

Tumblrにログインしていなければログインするように促されます。
ログインした状態であれば、以下のようなメッセージが表示されますので許可をクリックします。

許可

アプリ登録時に設定したOAuth2リダイレクトURLへリダイレクトされます。

ステップ2 コールバックリクエストの処理

コールバックリクエストを処理します。

リダイレクトURLにはcodeおよびstateのクエリパラメータが含まれます。
設定したOAuth2リダイレクトURLに寄りますが、例えば以下のような感じです。

http://localhost:8000/?code=0123456789&state=abcdefghijkl#=

stateの値を検証します(ステップ1のstate参照)。
codeを取得します。

ステップ3 アクセストークンのリクエスト

アクセストークンをリクエストします。
方法は次のリンクの通りです。

Authorization Code Grant Request

具体的には以下のようなコマンドを作成し、コマンドラインに入力します。

curl -F grant_type=authorization_code -F code={code} -F client_id={Your OAuth consumer key} -F client_secret={Your OAuth secret key} https://api.tumblr.com/v2/oauth2/token
URI

api.tumblr.com/v2/oauth2/token

grant_type

grant_type=authorization_codeです。

code

ステップ2で取得したcode

client_id

Your OAuth consumer key

consumer key
client_secret

Your OAuth consumer secret

redirect_uri

不要です。もし入れるのであればOAuth2リダイレクトURLと一致させます。

以下のような形式でアクセストークンが返ってきます。

{
    "access_token": "{access_token}",
    "expires_in": 2520,
    "id_token": false,
    "refresh_token": "{refresh_token}",
    "scope": "write offline_access",
    "token_type": "bearer"
}

ステップ4 投稿する

APIを使います。

投稿したいので、

Create/Reblog a Post (Neue Post Format)

を使いたいのですが、ローカルファイルを読み込みたい都合上、base64形式を使用したいため、

Create a New Blog Post (Legacy)

こちらを使います。

使いやすい言語で記述します。公式クライアントは以下のとおりです。

  • Javascript
  • Ruby
  • PHP
  • Java
  • Python
  • Objective-C
  • Go

一例として、pythonでの最低限の実装は次のとおりです。

import requests

access_token = {access_token}

posts_url = "https://api.tumblr.com/v2/blog/{blog-identifier}/post"
headers = {
    "Authorization": f"Bearer {access_token}"
}
param = {
            "type": "photo",
            "state": "queue",
            "data64": encoded_string
}

response = requests.post(posts_url , headers=headers, json=param)

{blog-identifier}は、Tumblrのユーザー名です。https://www.tumblr.com/{blog-identifier}の部分です。
encoded_stringは対象のファイルを開き、
encoded_string = base64.b64encode(file.read()).decode(‘utf-8’)
のようにエンコードします。
“data64”: encoded_stringの部分を”source”:{The photo source URL}のように差し替えれば、ウェブ上の画像がキューに投稿できます(その場合はエンコードする必要はありませんし、neue post formatの方を使用できます)。

まとめ

ここまでの一連の処理を一つにまとめたpythonコードをnoteで販売しています。
以下のような簡単な操作で、フォルダ内のすべての画像がキューに予約投稿されます。

  1. デフォルトブラウザでTumblrにログイン
  2. コード実行
  3. フォルダ選択
  4. 許可をクリック

pngファイルで動作を確認しています。

コメント

タイトルとURLをコピーしました