Twitter のいいねを解除するアプリを作る

だいぶ間が空いてしまいましたが、Twitter APIの申請(2020/2/11現在)の続きです。

申請した内容の通り、自分用の簡単な「いいね」管理のアプリを作成したのでメモしておきます。

……約半年かかってしまいました……。

簡易仕様

アプリの簡単な仕様は以下の通りになります。

  • 自分のTwitterアカウントの「いいね」の一覧を取得し、表示する
    • Twitter上のツイートへのリンクも付ける
  • 各ツイートごと、または一覧表示されている全ての「いいね」に一括でチェックを付けて、「「いいね」を解除する」ボタンで選択したツイートの「いいね」を外す
  • 処理完了後の画面で「いいね」を外したツイートの一覧を念のため再表示、ついでに<textarea>にMarkdownの箇条書き形式でツイートへのリンク一覧をダンプする

自分用なのでシンプルに。

動作サンプル

簡単な動作を図で示します。

1. ログイン

Twitter「いいね」解除アプリ・ログイン画面
Twitter「いいね」解除アプリ・ログイン画面

ログイン画面はログインボタンを付けたものを用意。

2. OAuthで認証

Twitter「いいね」解除アプリ・OAuthで認証
Twitter「いいね」解除アプリ・OAuthで認証

Twitterの認証画面に飛んで認証させます。

図は既にTwitterにログインしている状態でアクセスしたので「認証」ボタンだけですが、Twitterにログインしていない場合はアカウントIDとパスワードを求めるテキストボックスも付いてきますね。

3. トップページ

Twitter「いいね」解除アプリ・トップページ
Twitter「いいね」解除アプリ・トップページ

トップページは認証したユーザの「いいね」の一覧が表示されます。

図はサンプルとして猫の写真を適当に「いいね」しておいたものです。

4. 「いいね」解除

Twitter「いいね」解除アプリ・「いいね」解除
Twitter「いいね」解除アプリ・「いいね」解除

各ツイートの表示の下の方に「解除する」のチェックボックスがあります。これに1つずつチェックを付けて行くか、画面下端の「全ての「いいね」を解除リストに追加する」で一括でチェックを付けることで選択されます。

後は「選択した「いいね」を解除する」ボタンをクリックすれば、解除完了です。

5. 「いいね」解除完了

Twitter「いいね」解除アプリ・「いいね」解除完了
Twitter「いいね」解除アプリ・「いいね」解除完了

「いいね」解除完了すると上述の通り再表示とMarkdownの箇条書きでリンクがダンプされます。

実装上のポイント

実装上での躓いたポイントを記します。

1. 「いいね」解除はユーザ認証のみ( user context only )

冒頭の通り「いいね」の解除を最終目標に据えていたのですが、該当ドキュメントでは

Requires authentication? Yes (user context only)

とありました。

この辺りに詳しく書かれていますが、

All write actions on the Twitter API require the user context.

Authenticating users — Twitter Developers

とのことで、書き込みアクションは user context 、つまりユーザ認証が必要になるようです。アプリ単独認証だと読み取り専用までしかできないわけですね。

アプリ単独認証であれば、 Twitter API の利用申請の手順で発行した

  • API key
  • API secret key

それから、

  • Access Token
  • Access Secret

の4つで行けるのですが、ユーザ認証だと異なる手段が必要になります。

具体的には

  • 登録した Twitter アプリで Callback URL を指定
  • 実際に作成したアプリに以下のプログラムを用意する
    1. login.php: ログイン画面
    2. auth.php: Twitter 認証画面へ
    3. callback.php: コールバックを処理するプログラム( Callback URL でアクセスされる)
    4. index.php: アプリ画面(認証完了した実際の画面)

辺りが必要になるかと(1., 2.辺りは実装にも依りますが)。

以下、実際のコードから要点のみを抽出したサンプルプログラムを記します。

1.0. session.php, config.php: 共通処理(セッション周り、設定)

<?php

function requireLoginedSession()
{
    // セッション開始
    @session_start();
    // ログインしていれば true を還す
    if (isset($_SESSION['access_token'])) {
        return true;
    }
    else {
        return false;
    }
}
function sessionDestroy()
{
    setcookie(session_name(), '', 1);
    session_destroy();
}

まず共通部分としてセッション管理をする部分を先に作っておきます。

<?php

define('CUSTOMER_KEY', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('CUSTOMER_SECRET', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('ACCESS_TOKEN', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('ACCESS_SECRET', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
define('CALLBACK', 'https://app.example.com/callback.php');

また、定数として諸々記述しておきます。

1.1. login.php: ログイン画面

<?php

require_once './config.php';
require_once './session.php';
?>

<form method="post" action="./auth.php">
    <button type="submit" class="btn btn-primary"><i class="fas fa-fw fa-sign-in-alt" aria-hidden="true"></i>ログイン</button>
</form>

ログイン画面はシンプルに2.の Twitter 認証画面へリクエストを投げるプログラムへPOSTするだけです。

1.2. auth.php: Twitter 認証画面へ

<?php

require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';

use Abraham\TwitterOAuth\TwitterOAuth;

requireLoginedSession();
//TwitterOAuth のインスタンス化
$connection = new TwitterOAuth(
    CUSTOMER_KEY,
    CUSTOMER_SECRET
);

//コールバックをセット
$requestToken = $connection->oauth(
    'oauth/request_token',
    [
        'oauth_callback' => CALLBACK
    ]
);

//コールバック用に $_SESSION に入れる
$_SESSION['oauth_token']        = $requestToken['oauth_token'];
$_SESSION['oauth_token_secret'] = $requestToken['oauth_token_secret'];

//Twitter 上の認証画面のURLを取得
$url = $connection->url(
    'oauth/authenticate',
    [
        'oauth_token' => $requestToken['oauth_token']
    ]
);

//リダイレクト
header('Location: ' . $url);

続いて認証部分。 API key ( CUSTOMER_KEY )と API secret key ( CUSTOMER_SECRET )で TwitterOAuth インスタンスを生成し、それを通じてアクセストークンを取得します。

1.3. callback.php: コールバックを処理するプログラム( Callback URL でアクセスされる)

<?php

require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';

use Abraham\TwitterOAuth\TwitterOAuth;

requireLoginedSession();
$requestToken = [
    'oauth_token'        => $_SESSION['oauth_token'],
    'oauth_token_secret' => $_SESSION['oauth_token_secret']
];

if (
    isset($_REQUEST['oauth_token'])
    && $requestToken['oauth_token'] === $_REQUEST['oauth_token']
    && isset($_REQUEST['oauth_verifier'])
) {
    //成功時の処理
    //Twitter からアクセストークンを取得する
    $connection = new TwitterOAuth(
        CUSTOMER_KEY,
        CUSTOMER_SECRET,
        $requestToken['oauth_token'],
        $requestToken['oauth_token_secret']
    );

    $_SESSION['access_token'] = $connection->oauth(
        'oauth/access_token',
        [
            'oauth_verifier' => $_REQUEST[self::OAUTH_VERIFIER_NAME]
        ]
    );

    //セッションIDをリジェネレート
    session_regenerate_id();

    //リダイレクト
    header('Location: index.php');
}
else {
    die('Error!');
}

続いて Twitter の認証画面から戻ってくるコールバック部分。

ちなみに、 Twitter の認証画面から戻ってくるとき、以下のようにGETパラメータが伴ってきます。

https://app.example.com/callback.php?oauth_token=AAAAAAAAAAAAAAAAAAAAAAAAAAA&oauth_verifier=BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB

この oauth_tokenoauth_verifier を拾って処理をしています。

1.4. index.php: アプリ画面(認証完了した実際の画面)

<?php

require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';

use Abraham\TwitterOAuth\TwitterOAuth;

if (requireLoginedSession()) {
    $connection = new TwitterOAuth(
        CUSTOMER_KEY,
        CUSTOMER_SECRET,
        $_SESSION['access_token']['oauth_token'],
        $_SESSION['access_token']['oauth_token_secret']
    );

    try {
        $statuses = $connection->get(
            'favorites/list',
            [
                'screen_name'      => $_SESSION['access_token']['screen_name'],
                'count'            => '20',
                'include_entities' => 'true'
            ]
        );
    } catch (Exception $e) {
        echo $e->getMessage();
        die('Error!');
    }
}
else {
    //リダイレクト
    header('Location: login.php');
    exit();
}

//この後 $statuses から必要な「いいね」の情報を表示させる処理

アプリの認証が終わったら本来やりたかったことの手始めとして、「いいね」の一覧を表示させます。

1.5. finished.php: 処理完了画面

<?php

require_once './vendor/autoload.php';
require_once './config.php';
require_once './session.php';

use Abraham\TwitterOAuth\TwitterOAuth;

if (requireLoginedSession()) {
    $connection = new TwitterOAuth(
        CUSTOMER_KEY,
        CUSTOMER_SECRET,
        $_SESSION['access_token']['oauth_token'],
        $_SESSION['access_token']['oauth_token_secret']
    );

    //post されたパラメータを受け取る
    $checkedArray = $_POST['checked'];

    //チェックした「いいね」を解除する
    foreach ( $checkedArray as $val ) {
        //$checkedArray は ツイート のIDの array
        try {
            $statuses = $connection->post(
                'favorites/destroy',
                [
                    'id' => $val
                ]
            );
            return $statuses;
        } catch (Exception $e) {
            echo $e->getMessage();
            exit();
        }
    }
}
else {
    //リダイレクト
    header('Location: login.php');
    exit();
}

続いて画面上でチェックし、チェックの付いたツイートのIDの array を $_POST で受け取った後( $_POST['checked'] というパラメータとします)の処理です。

ここでは単純に foreach でIDをループさせながらリクエストを投げることにしました。

ここの処理が、冒頭で書いた通り user context が必要になるわけです。

1.6. logout.php: ログアウト画面

<?php

require_once './config.php';
require_once './session.php';

if (requireLoginedSession()) {
    //セッション破棄
    sessionDestroy();
?>

echo 'ログアウト完了';

<?php
}
else {
    //リダイレクト
    header('Location: login.php');
    exit();
}
?>

ログアウト時はセッション破棄。


実際はこの他に細かいことがあれやこれやありますが、要点は以上の通りです。

参考

Twitter API, OAuth

PHP

filter_input

バリデーション (Valitron)

この記事を書いた人

アルム=バンド

フロントエンド・バックエンド・サーバエンジニア。LAMPやNodeからWP、Gulpを使ってejs,Scss,JSのコーディングまで一通り。たまにRasPiで遊んだり、趣味で開発したり。