-
@ ocknamo
2023-12-12 18:30:40この記事はNostr (2) Advent Calendar 2023 13日目の記事です。
概要
ノーコードツールのn8nでNostrのボットを作ることができるノード(ノーコードツールの部品のようなもの)を作ったので使い方を解説します。
n8n-nodes-nostrobots
- MIT Licenseで公開しています
- はじめて作って公開したのは半年以上前です
https://github.com/ocknamo/n8n-nodes-nostrobots
n8nとは
ノーコードツールです。ノーコードツールといえば有名どころにZapierやIFTTTなどがありますがそういう感じのワークフロー自動化ツールです。
公式の説明を引用します。
n8n - ワークフロー自動化ツール n8n は、拡張可能なワークフロー自動化ツールです。 フェアコード配布モデルにより、n8n は常にソース コードが表示され、セルフホストで利用でき、独自のカスタム関数、ロジック、アプリを追加できます。 n8n のノードベースのアプローチにより、汎用性が高く、あらゆるものをあらゆるものに接続できます。 (機械翻訳)
https://github.com/n8n-io/n8n
n8nで組み合わせて使用できるワークフローの部品を"ノード"と呼びます。
コミュニティノードとは
だれでも自由に作成できてみんなに共有できるノードです。Node.jsで作成することができます。
作成方法はこちら。 - https://docs.n8n.io/integrations/creating-nodes/
雛形やチュートリアルがあるのでそこまで難しくありません。今回は作成方法などは紹介しません。
n8nの準備
n8nはコードが公開されておりセルフホストも可能です。
利用する簡単な方法としてはお金を払うか、セルフホストする方法があります。
お金を払う
月20ユーロでプラットフォームを使用できまるようです。
https://n8n.io/pricing/
セルフホスト
DockerもしくはNode.jsを扱えるエンジニアであれば簡単にセルフホストできます。
https://docs.n8n.io/hosting/
またUmbrelを運用している人であればアプリがストアにあるのでワンクリックでインストールできます。
https://apps.umbrel.com/app/n8n
コミュニティノードのインストール方法
コミュニティノードの利用はリスクもあるため必ず公式のドキュメントを読んでから自己責任でインストールしてください。
https://docs.n8n.io/integrations/community-nodes/
ここではn8n-nostrobotsのインストール方法だけ解説します。
サイドメニューの
Settings
からCommunity nodes
をページに移動し、インストールしますnpm Package Nameに
n8n-nodes-nostrobots
と入力してインストールを実行しますしばらく待つと
Community nodes
一覧に追加されるのでこれでインストール完了です。RSS Feed ボットの作成
簡単なチュートリアルとしてRSS Feed ボットを作成してみましょう。
準備
先程説明した方法で
n8n-nodes-rss-feed-trigger
というコミュニティノードをインストールしてください。https://github.com/joffcom/n8n-nodes-rss-feed-trigger
(一応実装を見たかったので私はコードもかるく確認していますが自己責任でお願いします)
ワークフロー作成
Workflows画面の
Add Workflow
からワークフローを追加できます。トリガーノードの作成
はじめにトリガーとなるノードを設定します。(n8n-nostrobotsにはまだトリガーノードは実装されていません) "+"をクリックして追加メニューを開きます。
トリガーノードとして
n8n-nodes-rss-feed-trigger
を使用したいので"rss"と入力するとRSS Feed Trigger
が選択肢に現れるので選択してください。とりあえずPollタイムをデフォルト値のままにしておきます。
FeedURLはLorem RSSがテストとして使用できます。
Feed URLに以下のURLを設定してください。 -
https://lorem-rss.herokuapp.com/feed?unit=second&interval=30
(30秒間隔でテスト用のFeedを取得できる設定)設定できたら
Fetch test Event
ボタンでテスト実行を行います。画像のようにテスト用のRSS Feedのデータが取得できます。
クレデンシャルの作成
サイドメニューからCredentialsを選択します。'Add Credential' ボタンで作成モーダルを開きます。 フォームに"nostr"と入力すると"Nostrobots API"がサジェストされるので選択してください。ちなみに表示されない場合はコミュニティノードのインストールが完了していない可能性があります。
クレデンシャルの作成画面が開くのでSecretKeyを入力してください。HEXでもbech32(nsecで始まる形式)どちらでも大丈夫です。
ワークフローの作成途中は使い捨て可能なテストアカウントを作成して使用することをおすすめします。
Nostrへの投稿の実行
RssFeedTriggerノードの右側に出ている"+"をクリックして後に続くノードを追加します。
nostrで検索すると
Nostr Read
とNostr Write
の2つのノードが表示されるのでNostr Write
を選んでください。選択肢が表示されたら(どれでもいいですが)
Basic Noteactions
を選ぶとノードが追加されます。ノードの設定画面が開くので以下のように値を設定します。'Credential to connect with'には先程自分が作成したクレデンシャルを設定します。
設定値は以下です。 - Resource: BasicNote - Operation: Send - Content: Hello nostr - Custom Relay:
wss://nostr.mom
Custom Relayはテスト用に一つだけに設定しました。デフォルトに戻したい場合、項目のメニューから
Reset Value
を実行してください。設定が完了したら
Execute node
ボタンをクリックしてノードを実行します。実行が完了するとOUTPUTに実行結果が表示されます。
content:Hello nostr
を含むイベントが作成されており、sendResultが0:[accepted]: wss://nostr.mom
になっていれば成功です。他のクライアントからも確認できます。(Custom Relayに設定したリレーをクライアントに設定する必要があります)
RSSとの接続
INPUTに
RSS Feed Trigger
の結果がSchema形式で表示されていると思います。A conten
という項目をドラッグしてNostr Writeの'Content'のフォームドロップしてください。これだけで実行済みのノードの結果のデータをコンテントに埋め込んで渡すことができます。
この状態でテスト実行して確かめてみましょう。
RSS Feedの内容を投稿できました。
有効化
あと有効化して実行するだけです。
右上の赤い
Save
ボタンをクリックして保存したら、その左のInactive
と書かれたトグルボタンを有効化してください。確認モーダルが表示されるので確認してGot it
を選択します。以上で完了です。
クライアントから投稿ができているか見てみましょう。
1分ごとに投稿ができており、一度に2投稿できているので成功です!
お疲れ様でした。これでRSS Feedボットの作成完了です。
機能の解説
以下は細かい機能解説になります。ドキュメント用に書いたものなので、興味がなければ読みとばしていただいで必要なときに参照してください。
Nostr Read
'Strategy'
- type: セレクトボックス
リレーからイベントを取得する方法を指定します。以下の2つのオプションを選ぶことができます。 リレーに送るフィルタとしてなにを設定するかを選んでいるだけです。
- UserPublickey
- EventId
UserPublickey
対象のユーザを示す公開鍵文字列を指定できます。HEXでもbech32(npub)方式でもどちらでも指定できます。
EventId
対象のイベントのeventIdです。eventIdにリレーの情報が含まれる場合、指定したリレーに加えてそのリレーにも取得リクエストを送ります。
HEXでもbech32(nevent)方式でもどちらでも指定できます。
期間の範囲指定
イベントの取得対象期間を指定します。StrategyがUserPublickeyの場合のみ指定できます。 以下のオプションを指定できます。
- 'Relative'
- 'From'
- 'Unit'
- 'Since'
- 'Until'
'Relative'
- type: トグルスイッチ
期間の指定方法です。Relativeがオンの場合は過去に遡っていつから取得するかを相対的に指定することができます。(もちろん現在まで取得します)
'From'
- type: 数字
現在から遡っていつから取得範囲にするかを指定することができます。Relativeが有効な場合のみ指定できます。
'Unit'
- type: セレクトボックス
単位を選択肢から選ぶことができます。Relativeが有効な場合のみ指定できます。
- 'Day'
- 'Hour'
- 'Minute'
NOTE: 例えばFromを"1"に設定してUnitを"day"に設定した場合取得範囲は、”1日前からノードの実行時刻”までのイベントが対象になります。
'Since', 'Until'
- type: 日時
Relativeを無効にした場合期間範囲指定は'Since', 'Until'を使用します。 その名の通り'Since'の日時から'Until'日時までの期間指定でイベントを取得することができます。
'Custom Relay'
- type: テキスト
問い合わせ先のリレーを指定します。リレーのURLを入力してください。複数を指定する場合はカンマ(,)でつなげて書いてください。 デフォルト値としてリレーを8件設定しているため、ここは修正しないでそのまま使用してもらって構いません。ただし、当たり前ですがデフォルトリレーが正常に動いていることは保証できません。
- デフォルトリレー
wss://relay.damus.io,wss://relay-jp.nostr.wirednet.jp,wss://nostr-relay.nokotaro.com,wss://nostr.fediverse.jp,wss://nostr.holybea.com,wss://nos.lol,wss://relay.snort.social,wss://nostr.mom
'Error With Empty Result'
- type: トグルスイッチ
有効にした場合取得イベントが存在しない場合はエラーになってワークフローを停止することができます。無効の場合はイベントがなくても、エラーにはならず空配列を次のノードに実行結果として送ります。
Sample
jackの直近1時間のイベントを取得してみた実行結果です。3件のイベントを配列で取得できました。
- 設定値
- Strategy: 'UserPublickey'
- Pubkey: 'npub1sg6plzptd64u62a878hep2kev88swjh3tw00gjsfl8f237lmu63q0uf63m'
- Relative: True
- From: 1
- Unit: Hour
- Custom Relay: <デフォルト>
- Error With Empty Result: False
[ { "id": "6c1428c9afdd315f07a9b6e22118ce45c31b2a8de12ef694121ae1cfd06ee2df", "kind": 1, "pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2", "created_at": 1702389559, "content": "Only for you. Of course", "tags": [ [ "e", "4e222fdb7edb65172f85f262eff95a53132bcac6ccd2842b23c79f8bc0872e15" ], [ "e", "9295e82f3b802728dc18ef888bad81b3110711679982dc94e719f5a20e7e2528" ], [ "p", "e88a691e98d9987c964521dff60025f60700378a4879180dcbbb4a5027850411" ] ], "sig": "ad3b4873c8c4103555f5bdec4ad39cc0b029f000d88e67964a72e41359981440b776aea6e3758257346ae8c5efde6efe8cda2490abdfc3d0b02f675f06c9bada" }, { "content": "สวัสดีชาว bitcoiners ชาวไทย", "created_at": 1702388695, "id": "309dea1a6e298fe3b591e8c4f87736528ee867a94ffa820b3225aa9169c6a009", "kind": 1, "pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2", "sig": "e113577b3281eb6637abf5ee60aef6b7a0dd700bf6254196e862fee96d4806eefa80c37292919f4e38dedbdc2f1d2a16d58c4d3c1a7d1dab40514868f48d3277", "tags": [ [ "e", "4e222fdb7edb65172f85f262eff95a53132bcac6ccd2842b23c79f8bc0872e15", "", "reply" ], [ "p", "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2" ] ] }, { "id": "4e222fdb7edb65172f85f262eff95a53132bcac6ccd2842b23c79f8bc0872e15", "kind": 1, "pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2", "created_at": 1702388333, "content": "nostr:naddr1qq9rzdesxgensvpnxuusygxv5lh4g8dcx6y5z0vht38k5d0ya3eezk39jmrhqsfdj2rwwv33wcpsgqqqwens60xga9", "tags": [], "sig": "7f5d80867650d5fa2a7da55d20fd604423a785e028595d0c9fb56b80a2be0d555997e06e4f3a2d9930c183122fafa51bd8035e8eb9fe83d3cc47b13e040b29d8" } ]
Nostr Write
Nostrのリレーにイベントの書き込みを行うノードです。 このノードを使用する前に書き込みを行いたいアカウントの秘密鍵をn8nにクレデンシャル情報として登録する必要があります。
'Credential to connect with'
- type: セレクトボックス
作成したクレデンシャル情報を選択して投稿するアカウントを決めます。クレデンシャルを複数作成すると複数のアカウントが選択肢に追加されます。 ワークフローの作成途中は使い捨て可能なテストアカウントを作成して使用することをおすすめします。
'Resource'
- type: セレクトボックス
どのような方法でイベントを作成するか選択することができます。以下の3つのオプションがあります。
- 'BasicNote'
- 'Event(advanced)'
- 'Raw Json Event(advanced)'
'BasicNote'
一番単純なノートイベント(
kind1
)です。SNS用のクライアントで見ることができるイベントです。'Content'に本文を設定すれば使用できるため使い方も一番簡単で、おそらくNostrプロトコルをあまり理解していなくても利用可能です。'Event(advanced)'
BasicNoteと異なりkindやtagsを設定することができます。利用するには少なくともNIP-01を理解する必要があると思われます。
BasicNoteから追加になるメニュー項目がかなりたくさんあります。以下に箇条書します。
- Kind
- Tags
- ShowOtherOption
- EventId
- Pubkey
- Sig
- CreatedAt
ShowOtherOptionを有効にするとEventId以下のメニューを表示できます。これらを使う機会はかなり限られるためデフォルトで非表示にしています。
注意点としてShowOtherOptionが有効な場合Sig(署名)が必須となるため'Credential to connect with'で選択したアカウントでは署名を行いません。自力で署名する必要があります。
Kind
- type: 数字
イベントのkindナンバーを設定できます。 詳しくはNIPを確認してください。 - Event Kinds https://github.com/nostr-protocol/nips#event-kinds'
Tags
- type: json
イベントに追加するタグを設定できます。jsonを入力する必要があります。jsonでパースできない場合やタグの配列形式ではない場合、実行時エラーとなることに注意してください。設定時にはバリデーションされません。
タグの指定方法はクライアントでまちまちだったりして結構難しいです。これも基本的にNIPを確認してください。 - Tags https://github.com/nostr-protocol/nips#standardized-tags
FYI. メンションを行う場合のタグのサンプル
[["e","dad5a4164747e4d88a45635c27a8b4ef632ebdb78dcd6ef3d12202edcabe1592","","root"], ["e","dad5a4164747e4d88a45635c27a8b4ef632ebdb78dcd6ef3d12202edcabe1592","","reply"], ["p","26bb2ebed6c552d670c804b0d655267b3c662b21e026d6e48ac93a6070530958"], ["p","26bb2ebed6c552d670c804b0d655267b3c662b21e026d6e48ac93a6070530958"]]
otherOption
これは細かく説明する必要もないかと思います。名前の通りの項目です。
- EventId
- type: テキスト
- Pubkey
- type: テキスト
- Sig
- type: テキスト
- CreatedAt
- type: 数字
- unixtimeです
'Raw Json Event(advanced)'
生のjsonをそのまま設定できるオプションです。使い方は限られますが、Nostr Readで取得したイベントをそのままパブリッシュしたい場合などが考えられます。
json
- type: テキスト
'Raw Json Event(advanced)'の場合のみ表示されます。jsonには完全な署名済みイベントのjsonを入力してください。したがって'Credential to connect with'で選択したアカウントで署名しません。
'Content'
- type: テキスト
イベントの本文です。Resourceの選択肢で'BasicNote'か'Event(advanced)'を選択した場合に利用できます。
'Operation'
- type: セレクトボックス
実行するオペレーションを選択します。いまは作成したイベントをリレーにパブリッシュする
Send
しかありません。Custom Relay
- type: テキスト
イベントを送信するリレーを指定します。スキーマやデフォルトリレーはNostr Readと同じです。
実行時の挙動について
- イベント投稿時のタイムアウトは10秒です。そのためノードの実行に10秒以上かかる場合があります。
- 投稿が正常に完了すると結果をノードが出力します。
[<statu:s>]: <Relay URL>
- 例(成功):
[accepted]: wss://nos.lol
- 例(失敗):
[failed]: wss://nos.lol
- 例(タイムアウト):
[timeout]: wss://nos.lol
まとめ
網羅的にn8n-nostrobotsの利用方法について書きました。チュートリアルもやってみていただけると嬉しいです。
個人的にNostr関係では一番ドッグフーディングしているプロジェクトなので、欲しい機能があればこれからもちょくちょくアップデートを続けようと思います。おかしなところがあったらissueで報告していただけると助かります。
https://github.com/ocknamo/n8n-nodes-nostrobots/issues
他の人みたいに英語化もして書こうと思いましたが時間がないので諦めました。正月の宿題にします。
さてあしたのアドベントカレンダーは
- sinnchan: Nostrとの出会いから、SNS放浪生活?になった1年について https://adventar.org/calendars/8880
- hikari.huang: 新時代のSNS Nostrで小泉進次郎botを作った話 https://adventar.org/calendars/8794
の2本立てです。楽しみですね。