プログラミング

【備忘録】WordPressの投稿をプラグインを使わずに自動ツイートさせる方法

こんにちは!
今回はWordPressを投稿した際に、自動的にツイートさせて、プラグインを使わない方法を解説していきます。

そもそも、なぜプラグインを使わない方法を採用しているというと
プラグインを使うと余計な機能があったり、カスタマイズができないからです。

では早速解説をしていきます。

下準備

・WordPressの子テーマ
・Twitter開発者の登録
(keyが必要)

が下準備となっております。

ちなみに、WordPressのテーマはJINを使っていますので、
下記サイトの手順よりできるかと思います。
それ以外の場合、各自お調べください。

Twitter開発者の登録は結構、面倒です。
この手順を踏みたくなければ、jetpackのプラグインを使ったほうがいいですね。
下記サイトの手順で多分できるかと思います。

参考にしたサイト

最初に参考にしたサイトを載せておきます。
多分、『WordPress 投稿 自動ツイート プラグインなし』など調べて来ていれば、
上位表示されているサイトばかりだと思います

①twitter_api.phpの作成

①ftpから今のテーマの子テーマのディレクトリーにアクセスをする。

②子テーマの『jin-child』に『twitter』のフォルダーを作成します。
③『twitter』のフォルダーに『twitter_api.php』を作成する

④作成した『twitter_api.php』をエディタソフトで開き下記コードを貼り付けます。
vscodeを使用しています。
コードを貼り付ければ『twitter_api.php』の作成は完了します。

<?php

class TwitterApi
{
 const TWEET_URL = 'https://api.twitter.com/1.1/statuses/update.json';
 const MEDIA_UPLOAD_URL = 'https://upload.twitter.com/1.1/media/upload.json';

 private $_consumer_key;
 private $_consumer_secret;
 private $_access_token;
 private $_access_token_secret;

 public function __construct($consumer_key, $consumer_secret, $access_token, $access_token_secret)
 {
  $this->_consumer_key = $consumer_key;
  $this->_consumer_secret = $consumer_secret;
  $this->_access_token = $access_token;
  $this->_access_token_secret = $access_token_secret;
 }

 private function _create_signature($url, $params)
 {
  $signature_key = rawurlencode($this->_consumer_secret) . '&' . rawurlencode($this->_access_token_secret);

  $oauth_params = array(
   'oauth_token' => $this->_access_token,
   'oauth_consumer_key' => $this->_consumer_key,
   'oauth_signature_method' => 'HMAC-SHA1',
   'oauth_timestamp' => time(),
   'oauth_nonce' => md5(uniqid(rand(), true)), // ランダムな文字列であればOK
   'oauth_version' => '1.0'
  );

  // 署名の作成
  $merge_params = array_merge($params, $oauth_params);
  ksort($merge_params); // パラメータ名でソートされていないとダメらしい
  $req_params = http_build_query($merge_params);  // key=val&key=val...
  $req_params = str_replace(array('+', '%7E'), array('%20', '~'), $req_params);
  $req_params = rawurlencode($req_params);
  $encoded_req_method = rawurlencode('POST');
  $encoded_url = rawurlencode($url);
  $signature_data = $encoded_req_method . '&' . $encoded_url . '&' . $req_params;
  $hash = hash_hmac('sha1', $signature_data, $signature_key, TRUE);
  $signature = base64_encode($hash);
  $merge_params['oauth_signature'] = $signature;

  return $merge_params;
 }

 /**
  * 画像をアップロードします
  *
  * @param $img_url
  * @return string
  */
 public function post_media($img_url)
 {
  // バイナリまたはBase64エンコードした画像をアップロードする
  // バイナリの場合、"media"パラメータを指定
  // Base64の場合、"media_data"パラメータを指定
  $img_bin = file_get_contents($img_url);
  //  $img_b64 = base64_encode($img_bin);

  // バウンダリーの定義
  $boundary = '-------------------------------------------' . md5(mt_rand());

  // リクエストボディの作成
  $req_body = '';
  $req_body .= '--' . $boundary . "\r\n";
  $req_body .= 'Content-Disposition: form-data; name="media";'; // name="media_data" if base64
  $req_body .= "\r\n";
  $req_body .= "\r\n" . $img_bin . "\r\n";
  $req_body .= '--' . $boundary . '--' . "\r\n\r\n";

  $params = $this->_create_signature(TwitterApi::MEDIA_UPLOAD_URL, array());

  // 送信データの作成
  $options = array('http' => array(
   'method' => 'POST',
   'header' => array(
    'Authorization: OAuth ' . http_build_query($params, '', ','), // Authorization: OAuth key=val,key=val...
    'Content-Type: multipart/form-data; boundary=' . $boundary
   ),
   'content' => $req_body
  ));
  $options = stream_context_create($options);

  // 送信
  $json = file_get_contents(TwitterApi::MEDIA_UPLOAD_URL, false, $options);
  return $json;
 }

 /**
  * ツイートを投稿します。$media_idを指定すると画像付きで投稿します
  *
  * @param $status
  * @param $media_id
  * @return string
  */
 public function tweet($status, $media_id = null)
 {
  // ツイート本文
  $post_params = array(
   'status' => $status
  );
  if ($media_id != null) {
   $post_params['media_ids'] = $media_id;
  }

  $params = $this->_create_signature(TwitterApi::TWEET_URL, $post_params);

  // 送信データの作成
  $options = array('http' => array(
   'method' => 'POST',
   'header' => array(
    'Authorization: OAuth ' . http_build_query($params, '', ',')  // Authorization: OAuth key=val,key=val...
   ),
   'content' => http_build_query($post_params) // key=val&key=val...
  ));
  $options = stream_context_create($options);

  // 送信
  $json = file_get_contents(TwitterApi::TWEET_URL, false, $options);
  return $json;
 }

 /**
  * メディアアップロードのレスポンスからmedia_idを取得します
  *
  * @param $media_response
  * @return string
  */
 public function get_media_id($media_response)
 {
  $res = json_decode($media_response, true);
  if (isset($res['media_id_string'])) {
   return $res['media_id_string'];
  }
  return null;
 }
}

function.phpの編集

①子テーマの『jin-child』の『function.php』をエディタソフトで開き、下記コードを貼り付けます。

//Twitter

function hook_transition_post_status($new_status, $old_status, $post)
{
	// 投稿のステータスが「新規追加」または「下書き保存」または「レビュー待ち」または「予約投稿」から
	// 「公開」へ変わった時にTwitterに自動投稿する
	if (($old_status == 'auto-draft'
			|| $old_status == 'draft'
			|| $old_status == 'pending'
			|| $old_status == 'future')
		&& $new_status == 'publish' && $post->post_type == 'post'
	) {

		// Twitter API
		$twitter = new TwitterApi(TW_CONSUMER_KEY, TW_CONSUMER_SECRET, TW_ACCESS_TOKEN, TW_ACCESS_TOKEN_SECRET);

		// ツイートを投稿
		$posttags = wp_get_post_tags($post->ID);
		if ($posttags) {
			foreach ($posttags as $tag) {
				$hashtags .= "\n" . "#" . $tag->name;
			}
		}

		$status = $hashtags . '{{BR}}{{TITLE}}{{BR}}{{URL}}';  // TODO: ツイート本文のテンプレートを適当なところから取得
		$status = str_replace('{{TITLE}}', $post->post_title, $status);
		$status = str_replace('{{URL}}', get_permalink($post->ID), $status);
		$status = str_replace('{{BR}}', "\n", $status);
		$twitter->tweet($status);
	}
}
add_action('transition_post_status', 'hook_transition_post_status', 10, 3);


//Twitter用
include('twitter/twitter_api.php');

// Twitter APIキー
define('TW_CONSUMER_KEY', 'カスタムキー');
define('TW_CONSUMER_SECRET', 'シークレットカスタムキー');
define('TW_ACCESS_TOKEN', 'アクセストークン');
define('TW_ACCESS_TOKEN_SECRET', 'シークレットアクセストークン');

②TwitterAPIキー下準備で準備したキーをそれぜれに入れていきます。

③記事を投稿して、投稿されているかテストをする。

タグとタイトルとURLが出力されていれば完了です。

コードの解説

ここからはコードの解説をしていきます。
といっても、参考にしたコードをそのままコピってきていじっているだけですが。

参考にしたサイトではハッシュタグの位置が変だったのと画像を取得してしまっているため、URLがカードに変更されなかったため、そのへんをいじっています。

①アイキャッチ画像関連のコードを削除
参考にしたサイトは下記コードがありましたが、不要なため削除しました。

<?php
//アイキャッチ画像が設定されているならば画像のアップロード
if (has_post_thumbnail($post->ID)) {
 $image_url = _get_post_thumbnail_url($post->ID, 'large');
 $json = $twitter->post_media($image_url);
 // 添付画像のIDを取得
 $media_id = $twitter->get_media_id($json);
} else {
 // 添付画像なし
 $media_id = null;
}

/**
 * アイキャッチ画像のURLを取得します
 */
function _get_post_thumbnail_url($post_id, $size)
{
	$image_id = get_post_thumbnail_id($post_id);
	$images = wp_get_attachment_image_src($image_id, $size);
	$image_url = $images[0];
	return $image_url;
}

②ハッシュタグの出力場所を一番最初に来るようにコード追加
参考にしたサイトにも似たような記述がありましたが、ハッシュタグの出力が最後になっていたのが嫌だったのでコードを変えました。

		$posttags = wp_get_post_tags($post->ID);
		if ($posttags) {
			foreach ($posttags as $tag) {
				$hashtags .= "\n" . "#" . $tag->name;
			}
		}

以上がコードの解説になりますが、
基本的に投稿の中身を取得して、ループなり、直接出力するので
ディスクリプションやカテゴリー、カスタムフィールドなどもツイートさせることができると思います。

ちなみに、毎回『投稿』→『Twitterで確認』→『下書き』→『修正』
を繰り返してテストをしていましたが、ローカルサーバーにWordPressを持っていれば

<?php
$posttags = wp_get_post_tags($post->ID);
if ($posttags) {
 foreach ($posttags as $tag) {
  $hashtags .= "\n" . "#" . $tag->name;
 }
}

$status = $hashtags . '{{BR}}{{TITLE}}{{BR}}{{URL}}';  // TODO: ツイート本文のテンプレートを適当なところから取得
$status = str_replace('{{TITLE}}', $post->post_title, $status);
$status = str_replace('{{URL}}', get_permalink($post->ID), $status);
$status = str_replace('{{BR}}', "\n", $status);

single.phpにvar_dumpやecho で$statusを出力すれば
ツイートの内容が確認できます。
(最初からやっていればよかった)

まとめ

①twitter_api.phpの作成
②function.phpの編集

プラグインを使わないで投稿を自動でツイートさせる方法でした。
TwitterAPIのキーさえ取得できていれば、簡単にできると思います。
カスタマイズには多少のコーディングの知識が必要ですが、そのままでも
ハッシュタグとタイトルを出力できるので十分かなと思います。

参考になれば幸いです。
もし、質問などがあれば、答えられる範囲でお答えします。