九保すこひ@フリーランスエンジニア|累計300万PVのブログ運営中
さてさて、以前このブログでは記事を公開するとき、以下のツイッターでお知らせしていました。
実は当時、あるサービスで自動投稿していたのですが、Twitter
の仕様が変更になった影響で残念ながら利用できなくなってしまいました…。
そして、長らくTwitter
との連携はしてなかったのですが、せっかく記事を書くからには多くの人に読んでもらいたと思いこの度、再開することにしました。
そのため、wordpress
のプラグインを試したのですが、なぜか上手くいかなかったので、もうこの際、自動ツイート機能を自前で作ることにしました。
そこで❗
今回はプラグインなしでwordpress
からTwitter
に自動投稿する機能の作り方をご紹介します。
ぜひ皆さんのお役に立てると嬉しいです😊✨
【追記:2023.9.20】
イーロン・マスクさんがTwitter
をX
に変更するなど大きく改革を行った結果、Twitter
のAPI
もカオスとなってしまい、私自身この方法ではうまくいかなくなってしまいました。おそらく料金を払う方法がベストだと思います。
「試しにツイートしたら「イイネ」をいただいてしまい、
調子にのってすぐ記事を書きました😆」
開発環境: 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
すると、いくつか質問を聞かれますが、適当にEnter
やn
などでも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つ目がリクエスト(この場合アップロード)の最大秒数になります。
おわりに
ということで、今回はwordpress
に独自の自動ツイート機能を追加してみました。
もちろんプラグインを使ってもうまくいくんでしょうが、プラグインは何かとレスポンスを遅くする原因になるので、それがイヤな方はぜひ今回のコードを使ってみてくださいね。
なお、冒頭でも紹介しましたが今後は記事が公開されたタイミングで以下のツイッターでお知らせをしますので、ぜひフォローしてくださいね。
ではでは〜!
「約3年もツイッターを放置してました😂」