検索ツールのバージョンアップやらごちゃごちゃ色々やったので、忘れないうちにJavaScript及びHTMLの覚え書き。

【検索ツールのアップデート】

「誰かの投稿を検索するやつ」、2023/08/30現在のバージョンは1.6.1。改版履歴はこちらの「README」に

「Nostrで検索ツールを作った話」という記事で言及していた「今後の課題」の対応状況

1.結果の降順表示

 この件は上記の記事の「追記」部分で言及しているが、一応ここでも書いておく。

 最初、「昇順表示」になっていたのは実はたまたまだった。リレーにREQを送る時に件数上限(limit)をつけないと自動的に「昇順で500件」返される仕様だった。500件ではあまりに少ないので「limit:5000」と指定したところ、降順でデータが返ってくる。なのでそれをそのまま表示すると自動的に降順表示になった。
 (リレーの挙動についてはこちらを参照のこと→『保存済みイベント取得時のリレー間挙動差異』)

 せっかくなので、「500件(昇順)」と「5000件(降順)」を選べるようにした。

 ボタンクリックで関数を呼ぶ時に引数を渡して、その引数の値で処理を変えるようにしてある。
 <button id="submit" onclick="serch_post(1);">検索(降順)</button>

2,検索結果をコピーするボタン

 最初、「検索結果をクリアする」ボタンだけがあった(クリアしないと検索のたびにどんどん下に追加されていく)。そこに「コピーしてクリア」「コピーのみ」というボタンを付け足した。

 検索結果表示エリアはtextarea指定なので、nullを入れてやればきれいさっぱりクリアになる。
 document.getElementById("log").textContent = "";
 コピーする際はtextareaの内容を「navigator.clipboard.writeText」とやらでクリップボードに書き込む。 
 let data = document.getElementById("log").textContent;
   navigator.clipboard.writeText(data);

3.検索対象リレーの選択

 ラジオボタンで「きりのさんリレー」と「やぶみリレー」を選択できるようにした。ラジオボタンの値を取得する関数は本(『JavaScript本格入門』)からの丸写し。
function getRadioValue(name) {
   let result = " ";
   let elems = document.querySelectorAll(`input[name="${name}"]`);

  for(let elem of elems) {
    if (elem.checked) {
      result = elem.value;
      break;
    }
  }
  return result;
}

4.URLやnoteIDにリンクを貼る

 これは無理。textarea内ではhtmlタグが機能しないので、実現したければ検索結果表示エリアを別のやり方で実現しなくてはならない。そうなると上記の「コピー」や「クリア」のやり方も変わってくる(たぶん)ので、かなり大がかりな改修になってしまう。そこまでしなくてもいいかなぁという気持ち。

 ちなみにテキストの中からURLリンクを検出して<a>タグで挟むだけなら以下のようなコードで実現できるらしい。
 const exe_url = /(https?:\/\/[\w/:%#\$&\?\(\)~\.=\+\-]+)/g;
 let linktext = aaa.replace(exe_url, '<a href="$1">$1</a>');

5.村民npubリストを作る

 これは自分用には作ってみようかと思っているが、公開するとなると「私のアカウント入ってない!」「俺は村民認定されてないのか」みたいなことになって、どんどんリストが長くなり、結果「サッと目的の公開鍵を見つける」ができなくなりそう。
 「主要」とか付けるとさらにアレだし、おそらく実装はなし(そもそも実装できるとは言ってない)。

【Nostrログ保存ツール(自分用)を作った】

そもそも「検索」はおまけで、期間指定で自分の投稿を抽出してEvernoteやtxtファイルに保存したい、というのが開発動機(偉そう!)だった。

「検索結果をコピー」ボタンを付けることでその目的はおおむね果たせたのだが、「ちまちまコピーするんじゃなくてサクッとファイルに保存できたら楽なのに」と思っていた。そうしたら。

「それ、“標準出力をリダイレクト”でできます!」

と教えてもらい、早速やってみることに。

1.ひゅうが、リダイレクトを知る

「標準出力」というのは要するに「console.log」。デバッグの強い味方、あっちにもこっちにも「console.log」を書いてプログラム途中の動きを確かめよう、というアレ。
プログラム実行時に
node abc.js > 123.txt
と書くと「console.log」でコンソールに表示している内容をファイルに書きだしてくれる。「>> 123.txt」とするとアペンド(追記)で書き込む。(ファイルが存在しない場合は新規作成してくれるので、最初からアペンド利用で大丈夫)

えええ、マジか。早く言ってよ!

演習1-2を改造して自分の投稿を1日分ずつ取ってくるプログラムで早速やってみると、あっさり「123.txt」が作られたのだが。

2.ひゅうが、文字化けの罠にはまる

ファイルの中を見ると、見事に日本語(2バイト文字)が文字化けしている。日付等の半角英数字は大丈夫なのだが、これでは使い物にならない。

なんでじゃー、どうしてじゃー!とNostrのフォロイーさん達まで巻きこんで悩んだのだが、原因は「Powershellで動かしたこと」だった。
試しにコマンドプロンプトから実行してみたらあら不思議、何の問題もなく(文字化けせず)保存されているじゃあ~りませんか。

Powershell、おまえだったのか(´・ω・`)

ちなみにコマンドプロンプトやPowershellに表示される文字のコードはShift-JISで、JavaScriptのファイルはUTF-8。コマンドプロンプトから実行して作られたテキストファイルの文字コードはUTF-8になるのだが、Powershellから実行するとUTF-16になってしまって文字化けする。そのファイルをUTF-8で読み込み直してもうまく表示されない。

なんやねんな。
もうPowershellなんか使たらへんぞ(´・ω・`)

3.ひゅうが、バッチファイルを作る

コマンドプロンプトから実行すれば無事ログがテキストファイルに書き込まれることがわかったので、2月からのNostr投稿をちまちま1日ずつ保存していった。

しかしさすがに「1日ずつ」は面倒くさい。プログラムの方で期間指定を長く取っても良いのだが、例の「昇順だと500件」制限があるので、取りこぼさないようにと考えるといっぺんに取れるのは「5日分」ぐらい。

やっぱバッチファイルで自動的に繰り返し処理させるのが楽ちんだよね、というわけで。
for /l %%i in (20230501,1,20230531) do (
  node abc.js %%i >> 123.txt
)
みたいなループ処理のバッチファイルを書いて動かした。「コマンドライン引数を20230501から20230531まで1ずつ増やしてabc.jsを動かせ」

バッチファイルの拡張子は「.bat」。そして。

バッチファイルはShift-JISで作らなければ文字化けする!!!!!

えええ……。「abc.js」が「\Nostr演習」というフォルダに入っているので、ループの前に「cd \Nostr演習」とチェンジディレクトリを書いたら、「演習」部分が文字化けして、「そんなフォルダはない」と言われるのだ。その時俺はバッチファイルをUTF-8で保存していた。ぐぬぬ。

ともあれ無事これまでのNostrログをテキストファイルに保存し終えたのであった。満足。

【パブチャ同時投稿窓を作った】

Nostrには通常の、Twitter的なタイムラインとは別に、「パブリックチャット」という機能がある。そして数か月おきに「パブチャをもっと活用しよう」という気運が高まる。

Nostr相撲部というチャンネルも3月に作ってあるのだが、残念ながらほぼ私しか使っていない。一人でずっと相撲部チャンネルで喋っているのも寂しいし、かと言って使わないでいると本当に存在を忘れられるし、通常のタイムラインでも多少は相撲の話をしたいし……。

そうだ、同時投稿、しよう。

すでに演習1-3を改造した投稿窓はあるので、そこにチャットルームの選択と、同時投稿の機能を付け足せば良いだけ(だけ?)。


通常投稿は「kind1」、CHATへの投稿は「kind42」で、tagsの部分にチャットルームのチャンネルID(HEX)を指定する。
tags: [
      ["e",
      "(チャンネルID)",
      "(リレーのURL)",
      "root"]
],
実際に「同時投稿」をどれくらい使うかはわからないのだが、いちいちチャンネルを切り替えなくても複数の部屋に「CHATのみ」で投稿できるので地味に便利である。ノス廃御用達。

まぁこの先パブチャ対応のクライアントが増えてくればあまり出番はないかもしれない。

「検索ツール」の方も「kind1」だけでなく「kind42」も読み込むよう改修済み。こちらはREQを送る時に
kinds: [1, 42]
とするだけなので簡単。


演習をしがみたおすのもだいぶやり尽くした感があるけど、さて、まだ何かできることがあるだろうか――。


【関連記事】

Nostrでbotを作った話

Nostr本演習のアンチョコ(JavaScript覚え書き)~その1~

Nostr本演習のアンチョコ(JavaScript覚え書き)~その2~

Nostr本演習のアンチョコ(JavaScript覚え書き)~その3・延長戦~

Nostrで検索ツールを作った話