注意: このガイドは、Discourse フォーラム上で承認されたボットを運用していることを前提としています。具体的には、User API または Admin API Key を使用している場合を想定しています。ボットが管理者によってブロックされている場合は、ボットの目的について管理者と議論し、そのブロックを回避しようとしてはいけません。
ボットをサーバー上で実行した方が適切でしょうか?その場合は、プラグインの作成を検討してください: Developing Discourse Plugins - Part 1 - Create a basic plugin
はじめに
このガイドでは、ボットユーザーがアクセス可能な Discourse フォーラム(ダイレクトメッセージを除く)で投稿されたすべての投稿を検査および処理するためのアルゴリズムを示します。
単一の整数、つまり正常に処理された最高ポスト ID の永続的ストレージが必要です。例えば、これを Redis またはプレーンテキストファイルに書き込むことができます。Redis を使用することで、プロセスの再起動間でもメッセージバスサブスクリプションを維持できます。
ボット用の新規ユーザーアカウントを作成することを強く推奨します。これにより、必要に応じてグループやダイレクトメッセージに追加できるようになります。@system アカウントの使用は避けてください。
以下のアルゴリズム群は、WHATWG 仕様のスタイルを模倣して記述されており、段階的に新しい投稿を継続的に監視するアルゴリズムへと構築されます。
アルゴリズム仕様
フォーラムベース URLとは、末尾のスラッシュのないサイトの URL とします。例えば、https://meta.discourse.org や、サブフォルダインストールの場合は https://www.contoso.com/forum です。
次の最近の投稿を取得する
整数の 最高閲覧ポスト ID と、フラグの メッセージバスによってトリガーされた を指定して次の最近の投稿を取得するには、以下の手順を実行します。
- 最大レスポンスポスト IDを、最高閲覧ポスト ID に 50 を加算した結果とします。
- リクエスト URIを、フォーラムベース URL、
/posts.json、?before=、および 最大レスポンスポスト ID を連結したものとします。 - レスポンスを、リクエスト URI と 認証情報 を用いた
レート制限を遵守した JSON のフェッチ の結果とします。 - レスポンス が HTTP エラーの場合、エラーとしてこれらの手順を中止します。
- 投稿を、レスポンス 内のパス
latest_postsにある JSON 配列とします。 - 新しい投稿が閲覧された フラグを未設定にします。
- 投稿 内の各 JSON オブジェクト post を逆順に処理し、以下の手順を実行します。
- ポスト IDを、post 内のパス
idにある JSON 数値とします。 - 最高閲覧ポスト ID を ポスト ID に設定します。
- 新しい投稿が閲覧された フラグを設定します。
post を発行します。(
つまり、実行したい任意のカスタム処理に投稿を送信します。)- emit がバックプレッシャー信号を返した場合、このループを中断します。
- ポスト IDを、post 内のパス
-
上記のループは逆順に実行されるため、コードは最も古い投稿を最初に、最も新しい投稿を最後に確認します。 - 新しい投稿が閲覧された フラグが設定されている場合:
- 最高閲覧ポスト ID を用いて
状態をストレージに永続化する の手順を実行します。
- 最高閲覧ポスト ID を用いて
- 最高閲覧ポスト ID を返してこれらの手順を終了します。
既存の高位ポスト ID をプローブする
既存の高位ポスト ID をプローブするには、以下の手順を実行します。
- 最新プローブリクエスト URIを、フォーラムベース URL と
/posts.jsonを連結したものとします。 - 最新プローブレスポンスを、最新プローブリクエスト URI と 認証情報 を用いた
レート制限を遵守した JSON のフェッチ の結果とします。 - 最新プローブレスポンス が HTTP エラーの場合、エラーとしてこれらの手順を中止します。
- プローブ投稿を、最新プローブレスポンス 内のパス
latest postsにある JSON 配列とします。 - プローブ投稿 内の各 JSON オブジェクト post について:
- ポスト IDを、post 内のパス
idにある JSON 数値とします。 - ポスト ID を返してこれらの手順を終了します。
- ポスト IDを、post 内のパス
- エラーとしてこれらの手順を中止します。
最新からバックフィルする
オプションの整数 最高閲覧ポスト ID を指定して最新からバックフィルするには、以下の手順を実行します。
- 最小ポスト IDを、最高閲覧ポスト ID が存在する場合はその値、そうでない場合は 0 とします。
- 既存の高位ポスト IDを、既存の高位ポスト ID をプローブする の結果とします。
- 最大ポスト ID がエラーの場合、エラーとしてこれらの手順を中止します。
- 最小ポスト ID と 既存の高位ポスト ID を指定して、バックフィル の手順を実行します。
バックフィル
2 つの整数 最小ポスト ID と 既存の高位ポスト ID を指定してバックフィルするには:
- 現在の最小ポスト IDを 最小ポスト ID とします。
- 以下の手順を繰り返します。
- 現在の最小ポスト ID と未設定の メッセージバスによってトリガーされた フラグを指定して、次の最近の投稿を取得する の手順を実行します。
- 次の最近の投稿を取得する の手順が正常に完了しなかった場合:
- 指数バックオフアルゴリズムを失敗信号で更新し、指定された時間待機します。
- 現在の最小ポスト ID を更新せずに、次のループ反復に進みます。
- 候補最大レスポンスポスト IDを、現在の最小ポスト ID に 50 を加算した結果とします。
- 候補最大レスポンスポスト ID が 既存の高位ポスト ID 以上の場合、
これらの手順を終了します。 - 現在の最小ポスト ID を 候補最大レスポンスポスト ID に設定します。
新しい投稿を継続的に監視する
新しい投稿を継続的に監視するには、以下の手順を実行します。
- 最高閲覧ポスト IDを未設定のオプション整数とします。
ストレージから状態を復元するの結果として 最高閲覧ポスト ID を設定します。- 最高閲覧ポスト ID が未設定の場合:
- 初期ポスト IDを、既存の高位ポスト ID をプローブする の結果とします。
- 初期ポスト ID を用いて
状態をストレージに永続化する の手順を実行します。 - 最高閲覧ポスト ID を 初期ポスト ID に設定します。
- 通知を、チャネル
/latestを指定して
メッセージバスにサブスクライブする の手順を実行した結果とします。 - 以下の手順を繰り返し実行します。
- メッセージバス更新が発生した場合は メッセージバスによってトリガーされた フラグを設定し、最高閲覧ポスト ID を指定して、次の最近の投稿を取得する の結果を 新しい最高閲覧ポスト ID とします。
- 次の最近の投稿を取得する の手順が正常に完了しなかった場合:
- 指数バックオフアルゴリズムを失敗信号で更新し、指定された時間待機します。
- 次のループ反復に進みます。
- 新しい最高閲覧ポスト ID が 最高閲覧ポスト ID と異なる場合:
- 指数バックオフアルゴリズムを成功信号で更新します。
- 最高閲覧ポスト ID を 新しい最高閲覧ポスト ID に設定します。
- 通知 上のメッセージを待つか、実装定義のタイムアウトが発生するまで待機します。このタイムアウトは 10 分以上でなければならず、合理的には 24 時間、あるいはそれ以上まで範囲を広げることができます。
実装が必要なアルゴリズム:
レート制限を遵守した JSON のフェッチ。リクエスト URI とオプションの認証情報を引数に取ります。
- 429 エラーが発生した際、指数バックオフアルゴリズムおよび/またはサーバーから提供される
Retry-After情報を使用して自動的にバックオフおよび再試行する必要があります。
- 429 エラーが発生した際、指数バックオフアルゴリズムおよび/またはサーバーから提供される
ストレージから状態を復元する
状態をストレージに永続化する。整数を引数に取ります。
メッセージバスにサブスクライブする