レ点腫瘍学ノート

pukiwikiカスタマイズ箇所/自作プラグイン/tweet.inc.php の履歴の現在との差分(No.3)


#author("2021-06-27T22:08:27+09:00;2021-06-27T20:25:27+09:00","default:tgoto","tgoto")
現在ver2.1が最新版です。
旧版についてはこちらのver1.0、ver2.0のページを参照してください。
#author("2023-01-09T18:00:51+09:00;2021-12-24T18:41:01+09:00","","")
&tag(pukiwiki,プラグイン);

#ogpi(https://oncologynote.com/?7d0c74f30e)
#ref(https://oncologynote.jp/img/b723fa4260.png,nolink)

----
PukiwikiにTwitterの単体のツイートを埋め込むだけのプラグインです。現在ver2.3が最新版です。

#ref(https://oncologynote.com/img/b723fa4260.png,nolink)
#ogp(https://github.com/m0370/pukiwiki_tweet)

PukiwikiにTwitterの単体のツイートを埋め込むだけのプラグインです。

TLの複数のツイートを埋め込んだり検索結果を表示するような高度な機能は備えていません。JavaScriptを利用しているので自分のpukiwikiサーバにはほとんど負荷をかけません。自分のpukiwikiを「はてなダイアリー」的なブログのように利用するために自作して自分だけで使っていたプラグインですが、せっかく作ったので公開しておきます。

ver1.0と比べての変化点は、TwitterのサイトからJSONでツイート内容を取得してキャッシュしておく機能が付いた点です。また、ver2.0からver2.1に変わるときにキャッシュファイルの形式を変更しました(拡張子も.datから.txtに変更し、互換性はありません)。
pukiwiki 1.5.3およびPHP 7.0〜PHP 8.0で動作することを確認しています。

#contents

*ライセンス [#u97d1be2]

- GPL v3

* ver2.3 [#jf9c6b20]

** ver2.1までの変更点 [#rdb6fee6]

ver1.0と比べての変化点は、TwitterのサイトからJSONでツイート内容を取得してキャッシュしておく機能が付いた点です。また、ver2.0からver2.1に変わるときにキャッシュファイルの形式を変更しました(拡張子も.datから.txtに変更し、互換性はありません)。

** ver2.2の変更点 [#j541b0d3]

https://platform.twitter.com/widgets.jsを遅延読み込みで呼び出す方法を、lazysizes.jsを使わずにこのプラグイン単独で対応しています。

具体的には初回スクロール(scroll)または初回マウス移動(mousemove)で発火するjavascriptを使ってwidget.jsを読み込んでいます。このjavascriptはスキンの$head_tagの中に配置するようにしています。初回スクロールで発火するjavasriptは下記のサイトを参考にさせていただきました。なお、widgets.jsをpreloadで読み込むようにすることでさらに高速化が図れます。

#ogp(https://q-az.net/lazy-load-script/)

** ver2.3の変更点 [#aee2921e]

第2引数以降の引数にnoimgまたはnoconvとつけると、それぞれ画像を非表示にしたりリプライツイートのスレッドを非表示にできます。両方を併用することもできます。

*しくみ [#e912c2a4]

Twitter Publishで発行されるHTMLタグを出力するだけなので単純な構造です。プラグインの第1引数にツイートIDかツイートのURLのどちらかを記載します。これによって、[[旧版ver1.0>https://oncologynote.com/?f6353f6b5e]]ではフォールバックを記載しておくことができましたが、ver2.0以降ではJSONキャッシュから自動でフォールバックが作成されます。
Twitter Publishで発行されるHTMLタグを出力するだけなので単純な構造です。プラグインの第1引数にツイートIDかツイートのURLのどちらかを記載します。これによって、[[旧版ver1.0>https://oncologynote.jp/?f6353f6b5e]]ではフォールバックを記載しておくことができましたが、ver2.0以降ではJSONキャッシュから自動でフォールバックが作成されます。

 #tweet(1375069974583074816) // ツイートIDを書く場合
 #tweet(https://twitter.com/m0370/status/1375069974583074816) // ツイートURLを書く場合

上記のように記載すれば、下記のようなツイートが表示されます。

#tweet(1375069974583074816)

**昔すぎるツイートは読み込めません [#m6057daa]

ツイートのURLでもツイートIDでも使用できるようにしていますが、ツイートIDかどうかを判定するところを暫定的に9桁で判定しているので、非常に昔のツイート(ツイートIDが8桁以下だった時代)のツイートは読み込めません。

ぼくがTwitterを始めた2007年6月の時点ですでにツイートIDは9000万台なので、ツイートIDが8桁と言えば2007年夏頃までの古いツイートでしょうか…(ちなみに当時のTwitterはまだインターフェイスが日本語化されておらず非常にマイナーでした)。

#tweet(1375069974583074816)

**遅延読み込みを有効にするには [#deca4313]
*プラグインの中身(ver2.3) [#d0d59eba]

lazysizes.jsを使用しているサイトでは遅延読み込みを使用することができます。遅延読み込みをしない場合のツイート埋め込みは、ページ読み込み速度を評価するPagespeed Insightのスコアが非常に悪くなり、ひいてはSEOにも悪影響を与えるので、lazysizes.jsを使っているサイトでは設定の遅延読み込み部分をTRUEにすることをオススメします。
[[github>https://raw.githubusercontent.com/m0370/pukiwiki_tweet/main/tweet.inc.php]]に公開しました。(2021.12)

 define('PLUGIN_TWEET_LAZYLOAD', 'TRUE'); //遅延読み込み有効(lazysizes.jsが必要です)
 define('PLUGIN_TWEET_LAZYLOAD', 'FALSE'); //遅延読み込み無効
#ogp(https://github.com/m0370/pukiwiki_tweet)

なお、この設定をTRUEにする場合のlazysizesは、blockquote要素でも遅延読み込みを有効にするためのunveilhooksプラグインを併用する必要があります。当サイトではJavaScript用CDNのjsdelivrを使っていますので、下記のHTMLタグをスキンに設置しておいて外部からこのjsファイルを読み込ませています。もちろんローカルに設置してもかまいません。
&ref(tweet_23.inc.php);

 <script src="https://cdn.jsdelivr.net/combine/npm/lazysizes@5,npm/lazysizes@5/plugins/unveilhooks/ls.unveilhooks.min.js" async></script>

*プラグインの中身(ver2.1) [#d0d59eba]

 <?php
 // ver1.0 初期バージョン
 // ver2.0 JSON取得してキャッシュする。widgets.jsはローカルに置くようにした。
 // ver2.1 データ保管方式を .datから.txtに変更、ブラウザのnative loading="lazy"などに対応
 // ver2.2 lazysizes.jsなしでの遅延読み込みに対応
 
 define('PLUGIN_TWEET_LAZYLOAD', FALSE); // lazysizes.jsを使っているサイトはTRUEに、使っていないならFALSEに
 define('PLUGIN_TWEET_LAZYLOAD', TRUE); // 初回スクロールに反応しての遅延読み込みを有効にするにはTRUEに、使っていないならFALSEに
 define('PLUGIN_TWEET_JSURL', 'https://platform.twitter.com/widgets.js'); //デフォルトは https://platform.twitter.com/widgets.js、ローカルにスクリプトを置いている場合はそのURL
 
 //設定ここまで
 
 function plugin_tweet_convert()
 {
 $tw = func_get_args();
 preg_match('/[0-9]{9,30}/', $tw[0], $tweetids); //URLでもツイートIDでも投稿できるように
 $tweetid = end($tweetids);
 $tweeturl = 'https://twitter.com/user/status/' . $tweetid ;
 $datcache = CACHE_DIR . 'tweet/' . $tweetid . '.txt';
 
 //オプション設定
 $options = array(
 	CURLOPT_SSL_VERIFYPEER => false,
 	CURLOPT_RETURNTRANSFER => true,
 	CURLOPT_TIMEOUT => 3 //タイムアウト(秒)
 );
 
 if(file_exists($datcache)){
 	//キャッシュがある場合
 	$json = file_get_contents($datcache);
 	$arr = json_decode($json, true);
 	$html = html_entity_decode($arr['html']);
 } else {
 	//キャッシュがない場合
 	$json_url = 'https://publish.twitter.com/oembed?maxwidth=550&dnt=true&url='. urlencode($tweeturl);
 	$ch = curl_init($json_url);
 	curl_setopt_array($ch, $options);
 	$json = curl_exec($ch);
 	$arr = json_decode($json, true);
 	curl_close($ch);
 	
 	if ($arr === NULL) {
 		//json取得失敗
 		$html = '<blockquote class="twitter-tweet"><a href="https://twitter.com/user/status/' . $tweetid . '">' . $tw[1] . '</a></blockquote>';
 	} else {
 		//json取得成功
 		$html = html_entity_decode($arr['html']);
 		//キャッシュする
 		file_put_contents($datcache, $json);
 	}
  global $head_tags;
  $tw = func_get_args();
  preg_match('/[0-9]{9,30}/', $tw[0], $tweetids); //URLでもツイートIDでも投稿できるように
  $tweetid = end($tweetids);
  $tweeturl = 'https://twitter.com/user/status/' . $tweetid ;
  $datcache = CACHE_DIR . 'tweet/' . $tweetid . '.txt';
  //オプション設定
  $options = array(
   CURLOPT_SSL_VERIFYPEER => false,
   CURLOPT_RETURNTRANSFER => true,
   CURLOPT_TIMEOUT => 3 //タイムアウト(秒)
  );
  if(file_exists($datcache)){
   //キャッシュがある場合
   $json = file_get_contents($datcache);
   $arr = json_decode($json, true);
   $html = html_entity_decode($arr['html']);
  } else {
   //キャッシュがない場合
   $json_url = 'https://publish.twitter.com/oembed?maxwidth=550&dnt=true&url='. urlencode($tweeturl);
   $ch = curl_init($json_url);
   curl_setopt_array($ch, $options);
   $json = curl_exec($ch);
   $arr = json_decode($json, true);
   curl_close($ch);
   if ($arr === NULL) {
    //json取得失敗
    $html = '<blockquote class="twitter-tweet"><a href="https://twitter.com/user/status/' . $tweetid . '">' . $tw[1] . '</a></blockquote>';
   } else {
    //json取得成功
    $html = html_entity_decode($arr['html']);
    //キャッシュする
    file_put_contents($datcache, $json);
   }
  }
  if (PLUGIN_TWEET_LAZYLOAD) {
   //scriptをlazyloadに置換
   $twjs1 = '<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>';
   $twjs2 = '';
   $twjs3 = '<script>function lazyLoadScript(scriptSrc) {var scrollFirstTime = 1;window.addEventListener("scroll", oneTimeFunction, false);window.addEventListener("mousemove", oneTimeFunction, false);function oneTimeFunction() {if (scrollFirstTime === 1) {scrollFirstTime = 0;var adScript = document.createElement("script");adScript.src = scriptSrc;document.body.appendChild(adScript);window.removeEventListener("scroll", oneTimeFunction, false);window.removeEventListener("mousemove", oneTimeFunction, false);}}}lazyLoadScript("' . PLUGIN_TWEET_JSURL . '");</script>';
   $html = str_replace($twjs1, $twjs2, $html);
   if( !in_array($twjs3, $head_tags, true)) {
    $head_tags[] = $twjs3 ;
   }
  }
  if( in_array('noimg', $tw)){
   $twjs4 = 'class="twitter-tweet"';
   $twjs5 = 'class="twitter-tweet" data-cards="hidden"';
   $html = str_replace($twjs4, $twjs5, $html);
  }	
  if( in_array('noconv', $tw)){
   $twjs6 = 'class="twitter-tweet"';
   $twjs7 = 'class="twitter-tweet" data-conversation="none"';
   $html = str_replace($twjs6, $twjs7, $html);
  }
  return <<<EOD
  $html
  EOD;
 }
 
 if (PLUGIN_TWEET_LAZYLOAD) {
 	//scriptをlazyloadに置換
 	$twjs1 = '<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>';
 	$twjs2 = '<div class="lazyload" data-script="https://platform.twitter.com/widgets.js"></div>';
 	$html = str_replace($twjs1, $twjs2, $html);
 }
 
 return <<<EOD
 $html
 EOD;
 }
 ?>

#description(PukiwikiにTwitterの単体のツイートを埋め込むだけのプラグインです。ツイートが読み込めないときのフォールバックを設定できます。遅延読み込みにも対応しています。)

*旧版はこちら [#kb81c6d2]

#ogpi(https://oncologynote.jp/?9278ef6c87)
#ogpi(https://oncologynote.jp/?f524b1ad47)
#ogpi(https://oncologynote.jp/?7d0c74f30e)
#ogpi(https://oncologynote.jp/?f6353f6b5e)
#pcomment