Hexoの記事とLemmyのコメント欄を連動させた。

https://earphones.juggler.jp/2021/Moondrop-SSP/

  • blog記事に拡張タグをつけてclean-deployを2回行うと、自動的にLemmyサイトに投稿を作成する。
  • blog記事の「コメントを投稿する」リンクからlemmyの投稿に飛んでコメントできる。
  • コメントはblog記事に表示される。

おおむねHexo側のカスタマイズで実現している。Lemmy側は何も変更しておらずAPIを普通に呼びだしてるだけだ。


Lemmyにした理由

  • マイクロブログと違い、後から投稿を編集できる。ブログからLemmy側へ自動転載した後、手動で記事を調節できる。
  • リンクアグリゲータなので、URLでの記事検索がやりやすい。自動転載する前に既存記事を検索することで、重複ポストを防止できる。
  • 近い将来にActivityPub対応予定がある。

1: 拡張タグの実装

記事データの最後に {% lemmyComment %} を書いておく。記事ごとにタグを書くのは面倒くさいが、現状Hexoのサイト生成処理でasyncできるのは拡張タグだけだ。HTTPリクエストなどを行う必要上、他の手はない。

hexoの作業フォルダの下にscripts/lemmyCommentTag.js を用意する。hexoは初期化時にそれを読むので拡張タグを実装できる。

拡張タグの登録。

hexo.extend.tag.register('lemmyComment', function(args){
	const self =  decycle(this);

	for( const key of ["date", "updated", "raw","tags","content","categories","site"] ){
		self[key]=`(${typeof self[key]})`;
	}
	if(verbose) console.log(`self=${ JSON.stringify(self, null, 2)}`)

	return lemmyCommentImpl(self,args);
}, {async: true});

呼び出された関数のthisオブジェクトに記事の情報が色々入っている。args には拡張タグの引数が渡される。サイト設定 _config.yml の内容は hexo.config で参照できる。

async function lemmyCommentImpl() の内容を大雑把に書くと:

  • assets folder に lemmyComment.png があるか確認する。記事だと誤認識されないように拡張子をpngに偽装しているが、中身はjsonだ。
  • json中にpostId(lemmyサイトの投稿ID)がなければ検索したりログインして投稿したりしてpostIdを用意する。用意したら lemmyComment.png に保存しておく。
  • 関数の返り値は拡張タグの展開結果のHTML断片で、今回は空のdiv要素と関数呼び出しを行うscript要素だ。

2: lemmyサイトからデータを取得するプロクシAPI

lemmy側を改造せずにオリジン間リソース共有(CORS)の制約を突破するため、単純な中継APIを用意する。

(A)ブログのサーバにnodejsで簡単なHTTPサーバを書く。 postIdを指定すると GET https://lemmy.juggler.jp/api/v2/post?id=xxx してその内容を返す。

(B)ブログのサーバのnginxを設定して /api/ へのアクセスを上記HTTPサーバに中継する。


3: ブラウザ側スクリプト

hexo のtheme/{themeName}/layout/_partial/head.ejsの下の方に以下の内容を追記する。

<script src="/markdownToHtml.js"></script>
<script src="/hexo-comment-lemmy.js"></script>
<link rel="stylesheet" href="/hexo-comment-lemmy.css">

hexoのsourceフォルダに以下のファイルを追加する。

  • source/hexo-comment-lemmy.css
  • source/hexo-comment-lemmy.js
  • source/markdownToHtml.js

markdownToHtml.js は npmのmarkedモジュールをbrowserifyで適当にブラウザ用スクリプトに変換したもの。

hexo-comment-lemmy.css はコメント表示部分のスタイルを適当に。

hexo-comment-lemmy.js に定義した関数は拡張タグの変換結果から呼び出される。 (2)で用意したプロクシAPIを非同期に呼び出して、応答に含まれるコメントデータをDIV要素に追加する。


4: 動作状況

まだちゃんと動作確認していない。


5: その他

もし自動投稿が不要なら拡張タグは必要ない。記事のfront matterにlemmyPostIdを定義して、theme中のejsでそれを見てDOM要素を追加すれば済む。