0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHP + Laravel でTwitterBot作成 #2『実装』

Last updated at Posted at 2022-12-04

仕様

作成するBotの仕様は前記事同様、以下の通りです。
特定ジャンルで多数RTされているツイートを自動でRTするようになっています。

事前準備

  • 事前に対象ジャンルのインフルエンサーをBotのアカウントで複数フォローしておく

以下を定期的に実行

  • タイムライン上でRT数が一定以上のツイートをRT
  • 特定のキーワード(対象ジャンルに関連の深いワード)で検索し、一定以上のRT数、かつ24時間以内に投稿されたツイートをRT
  • トレンドのキーワードのうち、TLのツイートに含まれるものを対象ジャンルとみなし、該当キーワードで検索。24時間以内、かつ一定以上のRT数のツイートをRT

この機能を満たすように実装していきたいと思います。

 

ファイル構成

ファイル構成は以下のようにしたいと思います。
Constsフォルダのみ独自に作成。あとはLaravelで用意されたフォルダを使用しています。

ファイル構成
app/
  ├ Consts/
    ├ Constants.php … 各Twitterアカウントで使い回せる定数定義用
    └ appConfig.php … 各Twitterアカウント固有の設定定義用
  └ Models/
    ├ Tweet.php … ORM用Tweetクラス
    └ TwitterAPIAccessor.php … TwitterAPI操作用ビジネスロジック
  └ Http/
    └ Controllers/
      └ TweetController.php … Tweet関連のコントローラ

 

ソース

実際の実装内容はGitHubを参照ください。
肝の部分だけ書いておきます。

 

TwitterAPI関連

 
TwitterAPIを使用するビジネスロジックをTwitterAPIAccessor.phpに記述していきます。
以下では各APIのパラメータの組み合わせを実際に確認できるため便利です。

タイムライン

TwitterAPIでTLから一定以上のRTのツイートを取得する処理です。
今回はAPIv2のTimelines関数を使用し、そこから一定以上のRT数のものを取り出します。

各APIに渡すパラメータ、受け取る値は以下を参照ください。

TwitterAPIAccessor.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use Abraham\TwitterOAuth\TwitterOAuth;
use App\Consts\Constants;
use App\Models\Tweet;

/**
 * TwitterAPIアクセス用クラス
 * 
 * [索引]
 *  □ 0. コンストラクタ
 *  □ 1. タイムラインからツイートを取得
 *  □ 2. 1件のツイートのRTを実行
 *  □ 3. 対対象キーワードの検索結果のツイートデータを取得
 *  □ 4. トレンドのキーワードのうち、ホームタイムラインでつぶやかれているキーワード一覧を取得
 */
class TwitterAPIAccessor
{
    // API connection
    private $connection;

    // 自分のTwitterID(数値文字列形式。APIから取得)
    private $myTwitterID = '';

    //======================================================
    //
    // 0. コンストラクタ
    //
    //======================================================

    /**
     * コンストラクタ
     *  ・TwitterAPI接続
     *  ・自分のTwitterIDをセット
     */
    function __construct() {
        try {
            // API接続
            $this->connection = new TwitterOAuth(Constants::API_KEY, Constants::API_SECRET, Constants::ACCESS_TOKEN_KEY, Constants::ACCESS_TOKEN_SECRET);
            // 自分のTwitterIDをセット
            $this->setMyTwitterID();
        } catch (\Exception $e) {
            Log::error($e);
        }
    }

    //======================================================
    // 自分のTwitterIDをセット
    //======================================================

    /**
     * 自分のTwitterIDをセット
     *  ・数値文字列形式のIDをセット
     * 
     * @return void
     */
    public function setMyTwitterID()
    {
        try {
            // API Ver2を使用
            $this->connection->setApiVersion("2");
            // 自分のTwitterIDをセット
            $res = $this->connection->get('users/me', ['expansions'=> ['pinned_tweet_id']]);
            $this->myTwitterID = $res->data->id;
        } catch (\Exception $e) {
            Log::error($e);
        }
    }

    //======================================================
    //
    // 1. タイムラインからツイートを取得
    //
    //======================================================

    /**
     * タイムラインからツイートを取得
     *  ・APIv2でタイムラインからデータを取得
     * 
     * @return array
     */
    public function getTweetsFromTimeLine()
    {
        $tweets = [];

        try {              
            // APIv2でタイムラインからデータを取得
            $this->connection->setApiVersion('2');            
            $res = $this->connection->get("users/{$this->myTwitterID}/timelines/reverse_chronological", 
                ['tweet.fields' => ['public_metrics,created_at,source,author_id'], 'user.fields' => ['name,username'], 'expansions'=> ['referenced_tweets.id,author_id']]);   

            // エラー時はロギング
            if (isset($res->errors)) {
                Log::error("Twitter API TimeLine Connect Error. {$res->errors[0]->message}");

                return $tweets;
            }

            // APIのツイートを走査
            foreach($res->data as $d) {
                // APIのユーザオブジェクトデータをセット
                $u = $this->getUserDataFromAPIResVal($res, $d->author_id);
                // APIのツイートオブジェクトデータからTweetクラスのデータをセット
                $tw = new Tweet;    
                $tw->setValsFromAPITwObj($d, $u);

                // 配列に追加
                array_push($tweets, $tw);
            }                              
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $tweets;
    }

    //======================================================
    // APIのレスポンスデータから該当ユーザのオブジェクトデータを返す
    //======================================================

    /**
     * APIのレスポンスデータから該当ユーザのオブジェクトデータを返す
     *  ・APIのinclueds->usersフィールドから該当ユーザIDに該当する要素を返す
     * 
     * @param mixed $apiRes
     * @param string $uid
     * @return mixed
     */
    function getUserDataFromAPIResVal($apiRes, $uid)
    {
        try {
            // APIのユーザデータを連想配列にセット                
            foreach($apiRes->includes->users as $u) {
                if ($u->id == $uid) {
                    return $u;
                }
            }
        } catch (\Exception $e) {
           Log::error($e);
        }

        return null;
    }

APIv2では自分のTwitterIDを使用するものが多いため、コンストラクタではAPIへの接続、自分のTwitterID(数値文字列形式)のTwitterAPIからの取得処理を実装しています。

リツイート

続けてリツイート処理を実装。
v2のretweet関数を使用します。

TwitterAPIAccessor.php
    //======================================================
    //
    // 2. 1件のツイートのRTを実行
    //
    //======================================================

     /**
      * 1件のツイートのRTを実行
      *  ・RT実行
      *  ・ロギング、画面上に出力
      *
      * @param Tweet $tw 
      * @return void
      */
     public function retweetTargetTweet(Tweet $tw) {
        try {  
            // RT実行    
            $this->connection->setApiVersion('2');
            $res = $this->connection->post("users/{$this->myTwitterID}/retweets", ['tweet_id' => $tw->id_str_in_twitter], true);
            // エラー時はロギング
            if (isset($res->errors)) {
                Log::error("Twitter API Retweet Error. {$res->errors[0]->message}");

                return;
            }

            // 結果をロギング、画面上に出力
            $txt = '  [RT実施]' . $tw->user_name . ' (' . $tw->client_name . ')' . $tw->rt_count . 'RT ' . $tw->tweet_text;
            echo($txt);
            Log::debug($txt);            
        } catch (\Exception $e) {
            Log::error($e);
        }
    }

検索

続けて検索処理。APIv2使用。
こちらもAPI発行時にはTwitterIDが必要です。

対象キーワードで検索してキーワードを本文に含むツイートを取得します。

TwitterAPIAccessor.php
    //======================================================
    //
    // 3. 対象キーワードの検索結果のツイートデータを取得
    //
    //======================================================

    /**
     * 対象キーワードの検索結果のツイートデータを取得
     *  ・検索用のパラメータをセット。RT、メンションは除外。日本語のみを検索。24時間以内のツイートのみを取得
     *  ・APIv2で検索実行
     *  ・本文にキーワードが含まれないツイートはスキップ(名前も検索に引っかかるため)
     *  ・NGワードを含むツイートはスキップ
     * 
     * @param string q 検索キーワード
     * @return array Tweetデータの配列
     */
    public function getTweetsBySearch(String $q) 
    {        
        $tweets = [];

        try {
            // 検索用のパラメータをセット
            $params = $this->getSearchParams($q);
            // APIv2で検索実行
            $this->connection->setApiVersion('2');
            $res = $this->connection->get('tweets/search/recent', $params);
            // エラー時はロギング
            if (isset($res->errors)) {
                Log::error("Twitter Search Retweet Error. {$res->errors[0]->message}");

                return $tweets;
            } 

            // APIの検索結果のツイートを走査
            foreach($res->data as $d) {
                // ユーザデータをセット
                $u = $this->getUserDataFromAPIResVal($res, $d->author_id);                              
                // Tweetデータをセット
                $tw = new Tweet;
                $tw->setValsFromAPITwObj($d, $u);

                // ツイート本文にキーワードを含まなければスキップ
                if (strpos($tw->tweet_text, $q) === false) {
                    continue;
                // NGワードを含めばスキップ
                } elseif ($this->checkTargetTweetContainsNGWords($tw)) {
                    continue;
                }

                array_push($tweets, $tw);                                
            }             
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $tweets;
    }

    //======================================================
    // 検索用のパラメータを返す
    //======================================================

    /**
     * 検索用のパラメータを返す
     *  ・RT、メンションは除外。日本語のみを検索
     *  ・24時間以内のツイートのみを取得
     *  ・関連性の高いツイートを取得
     * 
     * @param string $q
     * @return array
     */
    function getSearchParams(string $q)
    {
        $params = [];

        try {
            // 検索キーワードをセット。キーワード + 日本語のみ、かつRT、メンション除外
            $qParamTxt = $q . Constants::SEARCH_KEYWORD_POSTFIX;
            // 24時間前をテキストでセット
            $sdtTxt = date('c', strtotime('now -' . Constants::SKIP_PAST_HOUR .' hours'));
            // パラメータをセット
            $params = [
                'query'        => $qParamTxt,
                'start_time'   => $sdtTxt,
                'tweet.fields' => 'public_metrics,referenced_tweets,created_at,source,author_id', 
                'expansions'   => 'author_id,referenced_tweets.id',
                'user.fields'  => 'name,username',
                'sort_order'   => Constants::SEARCH_TWEET_BY_RECENCY_OR_RELEVANT,
                'max_results'  => Constants::SEARCH_COUNT 
            ];
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $params;
    }

    //======================================================
    // 該当ツイートがNGワードを含むかを返す
    //======================================================

    /**
     * 該当ツイートがNGワードを含むかを返す
     *  ・定数のNGワードを本文、ユーザ名、TwitterClientに含めばTrue
     * 
     * @param Tweet $tw
     * @return bool
     */
    private function checkTargetTweetContainsNGWords(Tweet $tw)
    {
        try {
            foreach (Constants::RT_NG_KEYWORDS as $q) {
                // 本文に含めばTrue
                if (strpos($tw->tweet_text, $q) !== false) {
                    return true;
                }
                // クライアント名に含めばTrue
                if (strpos($tw->client_name, $q) !== false) {
                    return true;
                }
                // 名前に含めばTrue
                if (strpos($tw->user_name, $q) !== false) {
                    return true;
                }
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return false;
    }

トレンド

トレンドから対象ジャンルのキーワードを取得する処理。APIv1.1を使用。
現在の日本のトレンドのワードのうち、自分のアカウントのTLでつぶやかれているものを対象ジャンルとみなしてセットします。

TwitterAPIAccessor.php
    //======================================================
    //
    // 4. トレンドのキーワードのうち、ホームタイムラインでつぶやかれているキーワード一覧を取得
    //
    //======================================================

    /**
     * トレンドのキーワードのうち、ホームタイムラインでつぶやかれているキーワード一覧を取得
     *  ・日本のトレンドのキーワードを取得
     *  ・タイムラインのツイートを取得
     *  ・タイムラインに含まれているツイートのみを配列にセット
     * 
     * @return array キーワードの配列 
     */
    public function getTrendKeywordsInHomeTimeLine()
    {
        $relatedTrWords = [];

        try { 
            // 日本のトレンドのキーワードを取得
            $allTrWords = $this->getJPTrendWords();
            // タイムラインのツイートを取得
            $htTweets = $this->getTweetsFromTimeLine();
            // トレンドのキーワードを走査
            foreach ($allTrWords as $q) {
                // タイムラインに含まれなければスキップ
                if (!$this->checkTimeLineTweetsContainsTargetWord($htTweets, $q)) {
                    continue;
                }

                // デバッグ用ロギング
                Log::debug("[トレンドから取得した検索ワード] {$q}");
                // 配列に追加
                array_push($relatedTrWords, $q);
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $relatedTrWords;
    }

    //======================================================
    // 日本のトレンドのキーワードを配列で取得
    //======================================================

    /**
     * 日本のトレンドのキーワードを配列で取得
     * 
     * @return array
     */
    function getJPTrendWords()
    {
        $trWords = [];

        try { 
            // 日本のトレンドを取得
            $this->connection->setApiVersion('1.1');                   
            $res = $this->connection->get('trends/place', ['id' => Constants::JAPAN_WOEID]);
            // エラー時はロギング
            if (isset($res->errors)) {
                Log::error("Twitter Trend Retweet Error. {$res->errors[0]->message}");

                return $trWords;
            } 

            // キーワードを配列に追加
            foreach ($res[0]->trends as $tr) {
                array_push($trWords, $tr->name);
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $trWords;
    }

    //======================================================
    // タイムラインのツイートに該当キーワードが含まれているかを返す
    //======================================================

    /**
     * タイムラインのツイートに該当キーワードが含まれているかを返す
     *  ・RTされたツイートはスキップ(フォローしているユーザ以外のツイートは該当ジャンル以外を含む可能性があるため)
     * 
     * @param array $tweets タイムラインのツイートデータ
     * @param string $q キーワード
     * @return bool
     */
    function checkTimeLineTweetsContainsTargetWord(array $htTweets, string $q)
    {
        try {
            // ツイートを走査
            foreach ($htTweets as $tw) {
                // RTされたツイートはスキップ
                if (strpos($tw->tweet_text, 'RT @') !== false) {
                    continue;
                }

                // キーワードを含めばtrue
                if (strpos($tw->tweet_text, $q) !== false) {
                    return true;
                }
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return false;
    }

 

モデル

続けてTweetテーブルのモデル。
APIv2のResponseオブジェクトからデータをセットする関数を用意しました。

Tweet.php
<?php

namespace App\Models;

use PHPUnit\TextUI\XmlConfiguration\Constant;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;

/**
 * TweetテーブルのORM用クラス
 * 
 * [索引]
 *  □ 1. TwitterAPIレスポンスからデータをセット
 */
class Tweet extends Model
{
    use HasFactory;

    //======================================================
    //
    // 1. TwitterAPIレスポンスからデータをセット
    //
    //======================================================

    /**
     * TwitterAPIレスポンスからデータをセット
     *  ・ユーザ名、ユーザの@形式のアカウント名はAPIレスポンスのユーザのオブジェクトデータからセット
     *  ・上記以外はAPIレスポンスのツイートのオブジェクトデータからセット
     *  ・本文は改行を除去してセット
     * 
     * @param mixed $td APIレスポンスのdata内の1件のツイートオブジェクト
     * @param mixed $ud APIレスポンスのinclues->users内の該当ユーザのオブジェクト
     * @return void
     */
    public function setValsFromAPITwObj($td, $ud)
    {        
        try {
            // ツイートID
            $this->id_str_in_twitter = $td->id;
            // ユーザ名
            $this->user_name = $ud->name;
            // ユーザの@形式のアカウント名
            $this->user_screen_name = $ud->username;
            // 本文。改行を除去してセット
            $this->tweet_text = str_replace(array("\r\n", "\r", "\n"), '', $td->text);
            // RT数
            $this->rt_count = (int)$td->public_metrics->retweet_count;
            // クライアント名
            $this->client_name = $td->source;
            // 投稿日時
            $this->posted_date = date($td->created_at);
        } catch (\Exception $e) {
            Log::error($e);
        }            
    }
}

 

コントローラ

上記を呼び出すコントローラを実装します。

TweetController.php
<?php

namespace App\Http\Controllers;

use App\Models\TwitterAPIAccessor;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;
use App\Consts\Constants;
use App\Models\Tweet;

/**
 * ツイート関連のコントローラクラス
 * 
 * [索引]
 *  □ 1. タイムラインからRTを実施
 *  □ 2. 検索キーワードからRTを実施
 *  □ 3. トレンドのキーワードからRTを実施
 */
class TweetController extends Controller
{

    //======================================================
    //
    // 1. タイムラインからRTを実施
    //
    //======================================================

    /**
     * タイムラインからRTを実施
     *  ・タイムラインからツイートを取得
     *  ・リツイート対象外(一定のRT数未満、かつDB保存済)のツイートはスキップ
     *  ・該当ツイートをRTしDBに保存
     */
    public function rtFromTimeLine(Request $request, Response $response) {
        try {
            // タイムラインからツイートを取得
            $twApiAccessor = new TwitterAPIAccessor();
            $tweets = $twApiAccessor->getTweetsFromTimeLine();
            // ツイートを走査
            foreach ($tweets as $tw) {
                // リツイート対象外ならスキップ
                if (!$this->isRTTarget($tw)) {
                    continue;
                }

                // DB保存
                $tw->save();
                // RT実行
                $twApiAccessor->retweetTargetTweet($tw);   
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $response;
    }

    //======================================================
    // RT対象かを返す
    //======================================================

    /**
     * RT対象かを返す
     *  ・DB保存済ならfalse
     *  ・RT数が一定未満ならfalse
     *  ・該当ツイートが他のツイートをRTしたものであり、該当ツイートをスキップする設定の場合はfalse
     * 
     * @param Tweet $tw
     * @return bool
     */
    function isRTTarget(Tweet $tw)
    {
        try {
            // DB保存済ならfalse
            $res = Tweet::where('id_str_in_twitter', $tw->id_str_in_twitter)->exists();
            if ($res) {
                return false;
            }
            // RT数が一定未満ならfalse
            if ($tw->rt_count < Constants::RETWEET_LEAST_RT) {
                return false;
            }
            // 該当ツイートが他のツイートをRTしたものであり、スキップする設定ならfalse
            if (strpos($tw->tweet_text, Constants::RT_TWEET_KEYWORD)) {
                if (Constants::SKIP_TIMELINE_RT_TWEET) {
                    return false;
                }
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return true;
    }

    //======================================================
    //
    // 2. 検索キーワードからRTを実施
    //
    //======================================================

    /**
     * 検索キーワードからRTを実施
     *  ・定数の検索キーワードで検索してツイートを取得
     *  ・一定のRT数未満、かつDB保存済(RT済)のツイートはスキップ
     *  ・該当ツイートをRTしDBに保存
     */
    public function rtFromSearch(Request $request, Response $response) {
        try {
            $twApiAccessor = new TwitterAPIAccessor();

            // 検索キーワードを走査
            foreach(Constants::SEARCH_TARGET_KEYWORDS as $q) {                
                // 検索キーワードからツイートを取得
                $tweets = $twApiAccessor->getTweetsBySearch($q);
                // ツイートを走査
                foreach ($tweets as $tw) {
                    // リツイート対象外ならスキップ
                    if (!$this->isRTTarget($tw)) {
                        continue;
                    }

                    // RT実施
                    $twApiAccessor->retweetTargetTweet($tw);
                    // DB保存
                    $tw->save();
                }
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $response;
    }

    //======================================================
    //
    // 3. トレンドのキーワードからRTを実施
    //
    //======================================================

    /**
     * トレンドのキーワードからRTを実施
     */
    public function rtFromTrend(Request $request, Response $response) {
        try {
            // トレンドのキーワードのうち、タイムラインに含まれるのものを取得
            $twApiAccessor = new TwitterAPIAccessor();
            $trWords = $twApiAccessor->getTrendKeywordsInHomeTimeLine();

            // キーワードを走査
            foreach ($trWords as $q) {
                // 検索キーワードからツイートを取得
                $tweets = $twApiAccessor->getTweetsBySearch($q);
                foreach ($tweets as $tw) {
                    // リツイート対象外ならスキップ
                    if (!$this->isRTTarget($tw)) {
                        continue;
                    }

                    // RT実施
                    $twApiAccessor->retweetTargetTweet($tw);
                    // DB保存
                    $tw->save();
                }                
            }
        } catch (\Exception $e) {
            Log::error($e);
        }

        return $response;
    }
}

また、DB関連の操作はLaravelだと簡単なので、CRUD操作もコントローラ内で実装しています。
 

定数

定数の定義です。
アカウント固有の設定やAPIのキーは別ファイルAppConfig.phpに記述しています。

Constants.php
<?php

namespace App\Consts;
use App\Consts\AppConfig;

/**
 * 定数定義用クラス
 *  ・複数アカウントで使い回せる値を定義
 *  ・アカウント固有の値はAppConfigに記載
 */
class Constants 
{
    //======================================================
    // リツイート設定
    //======================================================

    // この時間(h)より以前のツイートは無視
    const SKIP_PAST_HOUR = 24;

    // TLから1度に取得するツイートの数
    const TWEET_GET_COUNT_FROM_TL = 200;

    // 検索時、最新のツイートを検索するか recency = 最新のツイートを検索, relevancy = 関連性の高いツイートを検索
    const SEARCH_TWEET_BY_RECENCY_OR_RELEVANT = 'relevancy';

    // 検索時、何件のツイートを検索するか MAX:100
    const SEARCH_COUNT = 100;

    // 他の人のツイートをRTしているツイートに含まれるキーワード
    const RT_TWEET_KEYWORD = 'RT @';

    // この数以上のRT数でリツイート
    const RETWEET_LEAST_RT = AppConfig::RETWEET_LEAST_RT;

    // タイムライン上でRTされたツイートをRT対象外にするか
    const SKIP_TIMELINE_RT_TWEET = AppConfig::SKIP_TIMELINE_RT_TWEET;


    //======================================================
    // 検索キーワード
    //======================================================

    // 検索キーワード このキーワードで検索し、RT数の多いツイートをRT
    const SEARCH_TARGET_KEYWORDS = AppConfig::SEARCH_TARGET_KEYWORDS;

    // RT時のNGワード このキーワードを含むツイートはRTしない
    const RT_NG_KEYWORDS = AppConfig::RT_NG_KEYWORDS;

    // 検索時にキーワードの末尾につける文字列。日本語、RT以外、メンション以外をセット
    const SEARCH_KEYWORD_POSTFIX = ' lang:ja -is:retweet -has:mentions';


    //======================================================
    // トレンド
    //======================================================

    // 日本のWOEID トレンドで使用
    const JAPAN_WOEID = 23424856;


    //======================================================
    // Twitterアカウント
    //======================================================

    // API_KEY
    const API_KEY = AppConfig::API_KEY;

    // API Secret
    const API_SECRET = AppConfig::API_SECRET;

    // AccessToken Key
    const ACCESS_TOKEN_KEY = AppConfig::ACCESS_TOKEN_KEY;
    // AccessToken Secret
    const ACCESS_TOKEN_SECRET = AppConfig::ACCESS_TOKEN_SECRET;
}

 

ルーティング

web.phpにはコントローラの3つの関数をルーティングに追加。

web.php
<?php

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

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

// ルーティング タイムラインからRTを実施
Route::get('/timeline', [TweetController::class, 'rtFromTimeLine']);

// ルーティング 検索キーワードからRTを実施
Route::get('/search', [TweetController::class, 'rtFromSearch']);

// ルーティング トレンドの関連キーワードからRTを実施
Route::get('/trend', [TweetController::class, 'rtFromTrend']);

 
以上で実装完了です。
あとは本番環境に置いてcurlで定期的にアクセスすれば各処理が実行されます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?