【wordpress】プラグインなしでTwitterに自動投稿する

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

さてさて、以前このブログでは記事を公開するとき、以下のツイッターでお知らせしていました。


【お知らせをしていたツイッター】

実は当時、あるサービスで自動投稿していたのですが、Twitterの仕様が変更になった影響で残念ながら利用できなくなってしまいました…。

そして、長らくTwitterとの連携はしてなかったのですが、せっかく記事を書くからには多くの人に読んでもらいたと思いこの度、再開することにしました。

そのため、wordpressのプラグインを試したのですが、なぜか上手くいかなかったので、もうこの際、自動ツイート機能を自前で作ることにしました。

そこで❗

今回はプラグインなしでwordpressからTwitterに自動投稿する機能の作り方をご紹介します。

ぜひ皆さんのお役に立てると嬉しいです😊✨

【追記:2023.9.20】
イーロン・マスクさんがTwitterXに変更するなど大きく改革を行った結果、TwitterAPIもカオスとなってしまい、私自身この方法ではうまくいかなくなってしまいました。おそらく料金を払う方法がベストだと思います。

「試しにツイートしたら「イイネ」をいただいてしまい、
調子にのってすぐ記事を書きました😆」

開発環境: WordPress 5.4

前提として

自動投稿に必要なTwitter APIのトークンを「ツイッターでAPIキーとアクセス・トークンを取得する」を参考にして用意しておいてください。

また、トークンを取得したら、どこからでも呼び出せるようにwp-config.phpに次のよう書き込んでおいてください。

/wp-config.php

// Twitter API
define('TWITTER_CONSUMER_KEY', '(ここにAPI key)');
define('TWITTER_CONSUMER_SECRET', '(ここにAPI secret key)');
define('TWITTER_ACCESS_TOKEN', '(ここにAccess token)');
define('TWITTER_ACCESS_SECRET', '(ここにAccess token secret)');

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

今回はcomposerを使ってパッケージをインストールするので、まずwordpressのフォルダ内で以下のコマンドを実行してcomposer.jsonを作成します。

composer init

すると、いくつか質問を聞かれますが、適当にEnternなどでもOKです。

そして、composer.jsonが作成されたら、以下のコマンドでパッケージを保存します。

composer require abraham/twitteroauth

これで「/vendor」フォルダにパッケージがインストールされました。

子テーマをつくる

wordpressではよく知られたテクニックですが、テーマ本体を改造してしまうと、その後アップデートがあると変更部分を全て失ってしまうことになるため、「子テーマ」という部分的に改変されないファイルをつくります。

子テーマ用のフォルダをつくる

/wp-content/themes」フォルダ内に子テーマのフォルダを作ります。
今回は、twentyseventeenの子テーマを作るので、twentyseventeen-childというフォルダを作りますが、名前はお好みで変更してください。

必要なファイルを用意する

次に作成した子テーマのフォルダに移動し、以下2つのファイルを作成します。

  • functions.php
  • style.css

そして、それぞれ中身を次のように変更します。

/wp-content/themes/twentyseventeen-child/functions.php

<?php

add_action('wp_enqueue_scripts', function(){

    wp_enqueue_style('parent-style', get_template_directory_uri() .'/style.css');

});

/wp-content/themes/twentyseventeen-child/style.css

/*
Theme Name: Twenty Seventeen Child
Theme URL: http://example.com
Description: Twenty Seventeen Child
Theme Author: Your Name
Author URL: http://example.com
Template: twentyseventeen
Version: 1.0.0
Text Domain: twentyseventeen-child
*/

そして、wordpressにログインし、ページ左側にあるメニューから「外観」をクリック。

すると、テーマ一覧の中に先ほど作った子テーマがあるのでマウスを合わせて「有効化」ボタンをクリックしてください。

これで、子テーマの部分は完了です。

Twitterを自動送信する部分をつくる

では、記事が投稿されたらTwitterに自動投稿する部分を作っていきましょう。

投稿内容のイメージは、こんなカンジです。

「●●●●●●」という記事を公開しました! 👈 記事タイトル

http://****/**** 👈 URL

#Laravel #Vue.js 👈 カテゴリ名がハッシュタグ

では実際のコードです。

/wp-content/themes/twentyseventeen-child/functions.php

add_action('transition_post_status', function($new_status, $old_status, $post){

  global $wpdb;

  if($new_status === 'publish' && in_array($old_status, ['draft', 'future'], true) && $post->post_type === 'post') { // 初回投稿の時だけ

    $tweet = "「{$post->post_title}」という記事を公開しました!\n\n{$post->guid}";

    // 👇 ハッシュタグ
    $categories = get_the_category($post->ID);

    if(count($categories) > 0) {

      $tweet .= "\n\n";

      foreach($categories as $category) {

        if(intval($category->term_id) === 1) { // 👈 未分類は除外

          continue;

        }

        $category_name = str_replace(['.'], '', $category->name);
        $tweet .= "#{$category_name} ";

      }

    }

    // 👇 アイキャッチ画像
    $table = $wpdb->prefix .'postmeta';
    $thumbnail_meta = $wpdb->get_row(
      $wpdb->prepare("SELECT * FROM {$table} WHERE post_id = %d AND meta_key = %s", [
        $post->ID,
        '_thumbnail_id'
      ])
    );
    $image_path = '';

    if(!is_null($thumbnail_meta)) {

      $thumbnail_id = $thumbnail_meta->meta_value;
      $attachment = wp_get_attachment_metadata($thumbnail_id);
      $image_path = wp_upload_dir()['basedir'] .'/'. $attachment['file'];

    }

    // Twitter投稿
    require_once ABSPATH .'vendor/autoload.php';
    $connection = new \Abraham\TwitterOAuth\TwitterOAuth(
      TWITTER_CONSUMER_KEY,
      TWITTER_CONSUMER_SECRET,
      TWITTER_ACCESS_TOKEN,
      TWITTER_ACCESS_SECRET
    );
    $parameters = ['status' => $tweet];

    if(!empty($image_path)) { // 👈 画像アップロード

      $connection->setTimeouts(15, 30); // タイムアウト時間を伸ばす

      try {

        $media = $connection->upload('media/upload', [
          'media' => $image_path
        ]);
        $parameters['media_ids'] = $media->media_id_string;

      } catch (\Exception $e) {}

    }

    $connection->post('statuses/update', $parameters); // 👈 Twitterに投稿

  }

}, 10, 3);

【追記:2022.2.27】
カテゴリ名に「ドット」が入っているとハッシュタグが途中で切れてしまうので、ドットは取り除く処理を入れました。

【追記:2023.4.4】
みなさん知ってのとおり、Twitter APIの制限ルールが変わってしまったため、コードを以下のとおり変更しました。

【追記:2024.2.18】予約投稿を使った場合、2回実行される可能性があるのでコードを修正しました。

なお、この変更に伴って、APIバージョンは2に変更になっていますので、Abraham/TwitterOAuthのパッケージも3.0.0以上にする必要があります。

また、Twitter APIのバージョン2にはファイルをアップロードするエンドポイントは存在していない(😫)ため、Open Graph and Twitter Card TagsというプラグインでTwitterカードに対応させ、ツイート内容にブログ記事のURLを含めるようにしています。

add_action('transition_post_status', function($new_status, $old_status, $post){

    global $wpdb;

    if($new_status === 'publish' && in_array($old_status, ['draft', 'future'], true) && $post->post_type === 'post') {

        $tweet = "{$post->post_title} \nという記事を公開しました!\nぜひご覧ください。\n\n{$post->guid}";


        // Category
        $categories = get_the_category($post->ID);

        if(count($categories) > 0) {

            $tweet .= "\n\n";

            foreach($categories as $category) {

                if(intval($category->term_id) === 1) {

                    continue;

                }

                $category_name = str_replace(['.', ' '], '', $category->name);
                $tweet .= "#{$category_name} ";

            }

        }

        require_once ABSPATH .'vendor/autoload.php';
        $connection = new \Abraham\TwitterOAuth\TwitterOAuth(
            TWITTER_CONSUMER_KEY,
            TWITTER_CONSUMER_SECRET,
            TWITTER_ACCESS_TOKEN,
            TWITTER_ACCESS_SECRET
        );
        $connection->setAPiVersion('2');

        $parameters = ['text' => $tweet];
        $connection->post('tweets', $parameters, true); // 第3引数は重要(JSON化しないといけないので)

    }

}, 10, 3);

【追記:2024.2.18】予約投稿を使った場合、2回実行される可能性があるのでコードを修正しました。

ここで、先に言っておかないといけないのが、初回投稿の場合、タイトルとURLだけしかツイートできないことがある😫ということです。

実は、こちらのバグ報告ページであるようにRest APIで初回投稿したときは、設定されたカテゴリが取得できません。(transition_post_statusが実行された後でカテゴリ登録されるみたいです)そして、これはアイキャッチ画像についても同じです。

そのため、もしハッシュタグとアイキャッチ画像も一緒に自動ツイートしたい場合は、予約投稿にする必要があります。

※予約投稿とは、今すぐに投稿するのではなくあらかじめ公開する日時を決めておく設定のことです。(すみません、グーテンベルクは好きじゃないので下の画像はクラシックバージョンですが、ほぼ同じものがあると思います😊)

【追記:2020.4.10】wordpress 5.4で試したところ、予約投稿であっても画像は投稿できないようでしたので、直接DBからデータ取得するよう変更しました。
【追記:2020.4.15】プラグインによっては登録時にTwitter投稿が実行されてしまうので、$post->post_typeのチェックを追加しました。

※なお、classic editorではRest APIを使っていないようで、初回投稿でもカテゴリと画像を投稿できました。

では、コードの内容です。

まずtransition_post_statusが用意してくれる$new_status$old_statusで初回投稿を判別し、自動投稿を実行します。(つまり、更新のときはツイートされない)

そして、先ほどの通常の初回投稿の問題があるので、ハッシュタグに使うカテゴリとアイキャッチ画像は、もし情報が取得できた時だけ一緒に投稿するようにしています。

後は、パッケージがほとんどの部分をやってくれるのでpost()メソッドを呼び出すだけで完了します。

【追記:2023.7.12】
(3ヶ月ぶり2回目)みなさん知ってのとおり、Twitter APIの制限ルールが変わってしまったため、もうTwitterに自動でツイートすることはあきらめました。そこで考えたのが自分自信にメールで通知する方法です。

つまり、Intentリンクを自分に送信し、そのリンクをクリックしたら自動でツイート内容がセットされた状態にするわけです。そして、画像はちょっとメンドクサイですが、メールに添付して手動でダウンロードしてツイートに貼り付けます。

この方法次の項目ご覧ください。

Intent リンクをメール送信する方法

先ほどの項目でも触れましたが、Twitter APIがその後もカオス状態になり、もう正直あまり未来は明るくないな…と感じたため、私自信APIを使うことはあきらめて(今後もこんな感じならTwitter自体を移行かも…🤔)Intent リンクをメール送信する方法に切り替えました。

Intentリンクというのはシンプルに言うと「ツイート内容が埋め込まれたURL(リンク)」のことで、クリックするだけでそのツイート内容がセットされた状態から始めることができます。

つまり、メールが届いたらクリックして自分でツイートするという作戦ですね。

では、やりかたです。

まず、wordpressにはwp_mail()という関数が用意されているのですが、私の環境ではそもそもmail()関数が使えないようになっていたので、この関数を改造してgmail経由でメール送信するようにしました。(そのため、もしメール送信できる環境であればここは飛ばしてもOKです)

/wp-includes/pluggable.php

// Send!
try {

    // GMail 経由でメール送信
    $phpmailer->IsHTML(true);
    $phpmailer->IsSMTP();
    $phpmailer->Host = 'smtp.gmail.com';
    $phpmailer->Port = 465;
    $phpmailer->SMTPAuth = true;
    $phpmailer->Username = '(あなたのユーザー名)';
    $phpmailer->Password = '(ここはあなたのアプリパスワード)';
    $phpmailer->SMTPSecure = 'ssl';
    
    $send = $phpmailer->send();

※ 太字部分を追加しました。

これでGMail経由でメール送信できるようになります。

続いては、functions.phpです。(前項目で紹介したものを入れ替えてください)

add_action('transition_post_status', function($new_status, $old_status, $post){

  global $wpdb;

  if($new_status === 'publish' && in_array($old_status, ['draft', 'future'], true) && $post->post_type === 'post') { // 初回投稿の時だけ

    // ツイート内容
    $tweet_content = "{$post->post_title} \nという記事を公開しました!\nぜひご覧ください。\n\n{$post->guid}";

    $categories = get_the_category($post->ID);

    if(count($categories) > 0) {

      $tweet_content .= "\n\n";

      foreach($categories as $category) {

        if(intval($category->term_id) === 1) {

          continue;

        }

        $category_name = str_replace(['.', ' '], '', $category->name);
        $tweet_content .= "#{$category_name} ";

      }

    }
    
    $message = '🐦 ダウンロード&コピペして Twitter へ投稿する<br>';
    $message .= '<textarea>https://twitter.com/intent/tweet?text='. urlencode($tweet_content) .'</textarea>';

    // アイキャッチ画像
    $table = $wpdb->prefix .'postmeta';
    $thumbnail_meta = $wpdb->get_row(
      $wpdb->prepare("SELECT * FROM {$table} WHERE post_id = %d AND meta_key = %s", [
        $post->ID,
        '_thumbnail_id'
      ])
    );
    $image_path = '';

    if(!is_null($thumbnail_meta)) {

      $thumbnail_id = $thumbnail_meta->meta_value;
      $attachment = wp_get_attachment_metadata($thumbnail_id);
      $image_path = wp_upload_dir()['basedir'] .'/'. $attachment['file'];

    }

    $to = '(ここにメールを受信したいメールアドレス)'; // 送信先のメールアドレス
    $subject = get_bloginfo('name') .'の記事を Tweet しましょう!';
    $attachments = [$image_path];

    wp_mail($to, $subject, $message, [], $attachments); // ここでメール送信

  }

}, 10, 3);

【追記:2024.2.18】予約投稿を使った場合、2回実行される可能性があるのでコードを修正しました。

送信する内容としては、先ほど言ったIntent URLを作成し、もしアイキャッチ画像があるなら添付してメール送信する流れです。

テストしてみる

ということで、ダミーの投稿をしてタイムラインをチェックしてみると次のように表示されていました。

成功です😊✨

ちなみに:エラーが出たら

ちなみに画像のアップロードで以下のようなエラーがでたら、それは、画像をアップロードしようとしたけど時間内に完了できませんでした。という意味になります。

Uncaught Abraham\TwitterOAuth\TwitterOAuthException: Operation timed out after (数字)

もしこのエラーが発生した場合は、setTimeouts()を調整してください。

$connection->setTimeouts(15, 30);

1つめの引数が接続の最大秒数、2つ目がリクエスト(この場合アップロード)の最大秒数になります。

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

おわりに

ということで、今回はwordpressに独自の自動ツイート機能を追加してみました。

もちろんプラグインを使ってもうまくいくんでしょうが、プラグインは何かとレスポンスを遅くする原因になるので、それがイヤな方はぜひ今回のコードを使ってみてくださいね。

なお、冒頭でも紹介しましたが今後は記事が公開されたタイミングで以下のツイッターでお知らせをしますので、ぜひフォローしてくださいね。


ぜひフォローお願いいたします😊✨

ではでは〜!

「約3年もツイッターを放置してました😂」

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