PHP
WordPress
Twitter
TwitterAPI

WordpressからTwitterへ自動投稿する(予約投稿対応)

プラグイン(Jetpack等)を使っても予約投稿時にTwitterに投稿されない等の問題が出たため自作しました。

デモ

post-twitter-min.gif

手順

1. Twitter APIの使用準備

Twitter APIを使うため下記URLにアクセスしてアプリケーションを作成してください。
https://apps.twitter.com

アプリケーションの作成方法は下記記事を参照。
Twitter REST APIの使い方|SYNCER

作成後、consumer_key、consumer_secret、access_token、access_token_secretの4つをどこかに保存しておいてください。あとで使います。

2. ライブラリの導入

下記URLからライブラリをダウンロード。
https://github.com/abraham/twitteroauth
フォルダ名をtwitteroauth-masterからtwitteroauthにリネームしてテーマファイル内にぶち込んでください。

3. コード

下記コードをfunctions.phpにコピペしてお使いください。
やっていることはsave_postでTwitterに投稿する内容と投稿するかしないかのデータをwp_postmetaに保存しています。
そしてtransition_post_statusでTwitterへ投稿するファイル「post-twitter.php」を実行しています。
post-twitter.phpではsave_postで保存した内容を元にTwitterに投稿しています。

全てsave_postに書いても良いと思ったのですが、save_postだと予約投稿時に$_POSTデータ(post_idなど)が受け取れなかったので分けました。

functions.php
// ここではTwitterの投稿だけを行う
add_action('transition_post_status', 'post_twitter', 10, 3);
function post_twitter($new_status, $old_status, $post) {
    if ($new_status == 'publish') {
        // コマンドでTwitterに投稿するファイルを実行(引数にpost_idを渡している)
        $command = "/usr/bin/php ".__DIR__."/post-twitter.php $post->ID > /dev/null &";
        exec($command);
    }
}

// 管理画面が開いたときに実行
add_action('admin_menu', 'add_post_twitter_fields');
// カスタムフィールドを投稿画面に追加
function add_post_twitter_fields() {
    // フィールドを追加
    add_meta_box('post_twitter', 'Twitter', 'post_twitter_field', 'post', 'side', 'high');
}

// 投稿画面に表示するフォームのHTMLソース
function post_twitter_field() {
    global $post;

   $twitter_body = get_post_meta($post->ID, 'twitter_body', true);
    $checked = get_post_meta($post->ID, 'whether_to_post', true);
    if ($checked == 'checked') {
        $checked = 'checked="'.$checked.'""';
    }

   echo '<div style="margin-bottom:5px;"><label><input type="checkbox" name="whether_to_post" id="whether_to_post" value="checked" '.$checked.'>Twitterに投稿する</label></div>';
   echo '<textarea name="twitter_body" id="twitter_body" cols="50" rows="5" style="width: 100%;" readonly>'.$twitter_body.'</textarea>';
    echo <<< EOF
<script>
(function($) {
    // ロード時にチェックが入っていれば編集可に、入っていなかったら可に。
    if($("#whether_to_post").prop('checked')) {
        $("#twitter_body").prop('readonly', false);
        $('#twitter_body').css({'background-color':'','color':'', 'pointer-events':''});
    } else {
        $("#twitter_body").prop('readonly', true);
        $('#twitter_body').css({'background-color':'#fff','color':'#ccc', 'pointer-events':'none'});
    }

    // タイトルを自動入力(フォーカスが外れた時に反映)
    $('#title').change(function() {
        if ($('#twitter_body').val() == '') {
            var title = $('input[name="post_title"]').val();
            $('#twitter_body').val(title + "\\n");
        }
    });

    // チェックを入れると編集可能に、外すと不可に。
    $('input[name="whether_to_post"]').change(function() {
        if($("#whether_to_post").prop('checked')) {
            $("#twitter_body").prop('readonly', false);
            $('#twitter_body').css({'background-color':'','color':'', 'pointer-events':''});
        } else {
            $("#twitter_body").prop('readonly', true);
            $('#twitter_body').css({'background-color':'#fff','color':'#ccc', 'pointer-events':'none'});
        }
    });

})(jQuery);
</script>
EOF;

}

// 下書き・公開・更新ボタンが押されたときに実行される(ゴミ箱に移動したときも呼ばれるかも?)
add_action('save_post', 'save_post_twitter', 10, 3);
// 設定したカスタムフィールドの値をDBに書き込むコード
function save_post_twitter($post_id, $post) {
    if (isset($_POST['whether_to_post']) || isset($_POST['twitter_body'])) {
        $post_type = $post->post_type;
        if ($post_type == 'post') {
           $whether_to_post = $_POST['whether_to_post'] == '' ? '': $_POST['whether_to_post'];
           update_post_meta($post_id, 'whether_to_post', $whether_to_post);

            $twitter_body = $_POST['twitter_body'] == '' ? '': $_POST['twitter_body'];
            update_post_meta($post_id, 'twitter_body', $twitter_body);
        }
    }
}

Twitterに投稿するファイル。
post-twitter.phpをテーマディレクトリに作成し、
下記コードをコピペしてください。(必要箇所は適宜変更)

post-twitter.php
require __DIR__. '/../../../wp-load.php';
require_once __DIR__."/twitteroauth/autoload.php";
use Abraham\TwitterOAuth\TwitterOAuth;

class Twitter {
   private static $consumer_key = "hogehoge";
   private static $consumer_secret = "hogehoge";
   private static $access_token = "hogehoge";
   private static $access_token_secret = "hogehoge";

   public function post($post) {

      // Twitterへ投稿
      $connection = new TwitterOAuth(self::$consumer_key, self::$consumer_secret, self::$access_token, self::$access_token_secret);
      $result = $connection->post("statuses/update", ["status" => $post]);

      if ($connection->getLastHttpCode() == 200) {
          echo "succes";
          return;
      } else {
         // 投稿に失敗したらエラー内容をメールで送る
         mb_language("Japanese");
         mb_internal_encoding("UTF-8");

         $to      = 'to@example.com';
         $subject = 'Twitter Debug';
         $message = "Twitterへの投稿に失敗しました。\n$post\n\nエラーコード:".$result->errors[0]->code."\nエラーメッセージ:".$result->errors[0]->message;
         $headers = 'From: from@example.com' . "\r\n";

         mb_send_mail($to, $subject, $message, $headers);
      }
   }
}
// functions.phpに書いたtransition_post_statusは、
// save_postより先に実行されるので、念のためここで2秒遅らせてる。
sleep(2);

// post_id取得
$post_id = isset($argv[1]) ? $argv[1] : null;

$whether_to_post = get_post_meta($post_id, 'whether_to_post', true);

// checkedじゃなかったら処理中断
if ($whether_to_post != 'checked') return;

$twitter = new Twitter();

// 投稿内容を取得
$post = get_post_meta($post_id, 'twitter_body', true);
// post_url取得
$post_url = get_permalink($post_id);
if(strpos($post_url,'http://') !== false){
    $post_url = str_replace('http://', 'https://', $post_url);
}
// 投稿内容とpost_urlを結合
$post .= "\n".$post_url;
$twitter->post($post);

同じツイートを再度投稿しようとすると失敗して下記のようなメールが届きます。
Twitter-error.jpg