指定したローカルフォルダ内の画像を全て、Tumblrのキューに追加(予約投稿に一括投稿)する方法を解説します。
OAuth2で認証して、TumblrのAPIを使用します。
Tumblr APIガイドに従って進めます。
アプリケーションの登録
まずはTumblr APIにアプリの登録をします。
ログインし、”アプリを登録する”をクリックします。
アプリケーション名
何でも良いですが、ここでは”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が許可するよう促します。
方法は次のリンクの通りです。
具体的には以下のようなアドレスを作成し、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
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で販売しています。
以下のような簡単な操作で、フォルダ内のすべての画像がキューに予約投稿されます。
- デフォルトブラウザでTumblrにログイン
- コード実行
- フォルダ選択
- 許可をクリック
pngファイルで動作を確認しています。
コメント