Laravel で X(Twitter)の見守り機能をつくる

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、マーケティングとしても重要な位置づけになっているSNSの勉強を続けています。

なぜならSNSは、

  • 広告を出さずに商品へ誘導できたり、
  • 価値観を同じにできるので採用をしやすかったり、
  • 口コミが出ればさらに集客できる

などメリットが多数あります。

でも、逆に一番のデメリットと言えば・・・
そう、

炎上する🔥

可能性があるってことですね。

しかもXTwitter)の場合は拡散性がとても高いので一度火がつくと延焼しやすいと言われてます。

そこで❗

今回はLaravelを使って「ツイートを承認式にして、事前に誰かのチェックを入れられる」機能をつくってみることにしました。

ぜひ何かの参考になりましたら嬉しいです。😊✨

「ビックリマンチョコ、
美味しかったなぁ。
手の感覚が当時と一緒だし😊✨」

開発環境: Laravel 11.x

実装する機能の概要

今回は、例えば「アイドルとマネージャーさん」のような関係を考えてます。
つまり、

  • アイドルさんが今回のシステムでツイートを登録する
  • マネージャーさんにメールで文章が届く
  • チェックして問題なければ、ツイートを許可し実際に X へ反映する

という流れです。

※ なので、もしかすると「新人さんにツイートを任せるけどちょっと心配…」といったケースにも使えるかもしれませんね👍

前提として

すでにTwitter APIにアクセスするための以下4つのキーを取得していることが前提です。

  • CONSUMER KEY(API Key)
  • CONSUMER SECRET (API Secret)
  • ACCESS TOKEN(Access Token)
  • ACCESS SECRET(Access Secret)

なお、APIの登録やキーの取得は以下のページがわかりやすいです。

📝 【2023年度最新版】Twitter API 取得方法

そして、4つのキーを取得したら、.envにセットしておいてください。

.env

TWITTER_CONSUMER_KEY="(ここにAPI Key)"
TWITTER_CONSUMER_SECRET="(ここにAPI Key Secret)"
TWITTER_ACCESS_TOKEN="(ここにAccess Token)"
TWITTER_ACCESS_TOKEN_SECRET="(ここにAccess Token Secret)"

※ また、今回は「ツイートの承認部分」がメインなのでツイートの保存などは省略します。

パッケージをインストールする

次にツイートするために必要なパッケージをインストールします。
以下のコマンドを実行して下さい。

composer require abraham/twitteroauth

これで準備は完了です。
では実際につくっていきましょう❗

DBまわりをつくる

まずはデータベース周りです。
以下のコマンドで一気につくってしまいましょう!

php artisan make:model Tweet -m

すると、モデルとマイグレーションが作成されるので中身を以下のようにします。

app/Models/Tweet.php

<?php

namespace App\Models;

use App\Events\TweetSaved;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Tweet extends Model
{
    use HasFactory;

    protected $dispatchesEvents = [
        'saved' => TweetSaved::class,
    ];
}

なお、この中のTweetSavedイベントは次でつくります。

database/migrations/****_**_**_******_create_tweets_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('tweets', function (Blueprint $table) {
            $table->id();
            $table->string('body')->comment('ツイート本文');
            $table->dateTime('tweeted_at')->nullable()->comment('ツイート日時');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('tweets');
    }
};

では、この状態でマイグレーションを実行してみましょう。
以下のコマンドを実行して下さい。

php artisan migrate

すると、実際のテーブルはこうなりました。

イベントをつくる

では、モデルの中でセットしたTweetSavedをつくって、「Tweetモデルでデータが保存されたら自動で実行される」コードをつくっていきましょう❗

以下のコマンドを実行して下さい。

php artisan make:event TweetSaved

※なお、変更したときも通知できるようにsavedイベントを選択しました。

すると、ファイルが作成されるので中身を以下のようにします。

app/Events/TweetSaved.php

<?php

namespace App\Events;

use App\Mail\TweetPosted;
use App\Models\Tweet;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;

class TweetSaved
{
    use Dispatchable, InteractsWithSockets, SerializesModels;

    /**
     * Create a new event instance.
     */
    public function __construct(Tweet $tweet)
    {
        $to = 'manager@example.com'; // マネージャーのメールアドレス

        Mail::to($to)->send(new TweetPosted($tweet)); // メール送信
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn(): array
    {
        return [
            new PrivateChannel('channel-name'),
        ];
    }
}

Mailable をつくる

では、ツイートが登録されたときに(マネージャーさんに)送信されるメール送信の部分をつくっていきましょう。

以下のコマンドを実行して下さい。

php artisan make:mail TweetPosted

※イベントのTweetSavedと名前がかぶると面倒なのでTweetPostedにしました😊

すると、Mailableファイルが作成されるので中身を変更します。

app/Mail/TweetPosted.php

<?php

namespace App\Mail;

use App\Models\Tweet;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;

class TweetPosted extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     */
    public function __construct(private Tweet $tweet)
    {}

    /**
     * Get the message envelope.
     */
    public function envelope(): Envelope
    {
        return new Envelope(
            subject: 'ツイートが投稿されました',
        );
    }

    /**
     * Get the message content definition.
     */
    public function content(): Content
    {
        $tweet_approval_url = route('tweet.approve', ['tweet' => $this->tweet->id]);

        return new Content(
            view: 'emails.tweet_posted',
            with: [
                'tweet' => $this->tweet,
                'tweet_approval_url' => $tweet_approval_url,
            ],
        );
    }

    /**
     * Get the attachments for the message.
     *
     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
     */
    public function attachments(): array
    {
        return [];
    }
}

Mailable のビューをつくる

では、先ほどのTweetPostedの中でセットしたビューを作成します。
以下のコマンドを実行して下さい。

php artisan make:view emails.tweet_posted

resources/views/emails/tweet_posted.blade.php

ツイートが投稿されました。<br>
投稿の判断をしてください。<br><br>

【ツイート内容】<br>
{!! nl2br($tweet->body) !!}<br><br>

--------------------------------<br>

投稿を承認しますか?<br>
<a href="{{ $tweet_approval_url }}">X に反映させる</a>

コントローラーをつくる

続いてコントローラーです。
以下のコマンドを実行して下さい。

app/Http/Controllers/TweetController.php

<?php

namespace App\Http\Controllers;

use Abraham\TwitterOAuth\TwitterOAuth;
use App\Models\Tweet;
use Illuminate\Http\Request;

class TweetController extends Controller
{
    public function test()
    {
        // テスト用にここでツイート投稿する

        $tweet = new Tweet();
        $tweet->body = "パスタ買って返ったら、\nウチに新品のパスタ2袋も買ってあった。😫\n\n今日からイタリア人になります。🇮🇹✨";
        $tweet->save(); // ここで saved イベントが実行される

        return 'メールが送信されました!';
    }

    public function approve(Tweet $tweet)
    {
        $tweet_result = $this->tweet($tweet);

        if ($tweet_result === true) {

            $tweet->tweeted_at = now();
            $tweet->saveQuietly(); // ここではセーブイベントを実行しない

            return 'ツイート完了しました!';

        }

        return 'ツイートに失敗しました。。';
    }

    private function tweet(Tweet $tweet): bool
    {
        $connection = new TwitterOAuth( // 本来は config から取得するべきです
            env('TWITTER_CONSUMER_KEY'),
            env('TWITTER_CONSUMER_SECRET'),
            env('TWITTER_ACCESS_TOKEN'),
            env('TWITTER_ACCESS_TOKEN_SECRET')
        );
        $connection->setApiVersion(2);
        $parameters = [
            'text' => $tweet->body,
        ];
        $connection->post('tweets', $parameters, ['jsonPayload' => true]);

        return in_array($connection->getLastHttpCode(), [200, 201], true);
    }
}

test()はテスト用につくったもので、アクセスすると自動でツイートが保存され、自動でTweetSavedイベントが実行されるという流れです。

ルートをつくる

では、最後にルートです。

routes/web.php

<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\TweetController;

// Tweet
// 注: 本来はログイン必須にするべきです!
Route::prefix('tweet')->controller(TweetController::class)->group(function () {
    Route::get('test', 'test');
    Route::get('approve/{tweet}', 'approve')->name('tweet.approve');
});

なお、コード中にも書いてありますが、ログイン必須にすべきですし、さらに言うと「投稿できる人」と「承認できる人」の認証タイプ(guard)は分けておくべきです。(投稿した人が承認できると問題なので💦)

では、これ作業は完了です。
お疲れ様でした❗

テストしてみる

では、実際にテストしてみましょう❗
ブラウザでテスト用に作ったURLhttps://******/tweet/test)にアクセスします。

すると・・・・・・

はい❗
メールが送信されたメッセージが表示されました。

では、実際にメールを確認してみましょう。

どうなるでしょうか・・・・・・

はい❗
承認用のメールが送信されていました。

では、画像の中にあるリンクをクリックして承認してみましょう。

うまくいくでしょうか・・・・・・

はい❗
ツイート完了メッセージが表示されました。

で、実際のツイートはというと・・・・・・

このように投稿されていました。

では、テーブルの方も確認しておきましょう。

こちらもきちんとtweeted_atも登録されていました。
このデータを元にすでに投稿されたかどうかをチェックできるわけですね。

すべて成功です 😊✨

企業様へのご提案

今回のようなシステムを組むことでツイートへの炎上を事前に防ぐことが期待できます。

また、今回は一人だけの承認でしたが、

  • 複数人での承認も可能ですし、
  • 全員 or 過半数が OK ならツイートする

というようなシステムをつくることもできます。

また、Twitter APIは月 1,500回までなら無料(2024.5.3 現在)で使用することもできるため費用負担もそれほど必要ではないこともおすすめする理由の1つです。(毎日5ツイートしても150ツイートです)

もしそういったシステムをご利用になりたい場合は、ぜひお問い合わせからご連絡下さい。

お待ちしております。😊✨

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで、今回は「X(Twitter)の見守り機能」を作ってみました。

(利用規約がどうなってるかはわかりませんが)親が管理して子供がツイートする場面とかにも使えるでしょうし、経営権のある複数人がOKしたものだけツイートするという使い方もできるかもですね。

ぜひこれで炎上が減ればいいと思ってます。(というか、ちょっとトガッたことを言うと、自分が炎上しそうで怖い今日この頃です😅)

ではでは〜❗

「ちょっとずつ仕事&プライベート垢
でいいね増えてきました
有料教材のおかげ。迫社長、感謝❗」

このエントリーをはてなブックマークに追加       follow us in feedly