Discord Bot Construction Kit 🤖

このプラグインの目的

このプラグインは以下のことを実現します:

  1. Discourse サーバーを介して Discord ボットを動作させ、両システムを連携させる機能を提供します。このリポジトリをフォークし、簡単な Ruby コードを追加することで、あらゆるボット機能を実装できます。

  2. 既存の機能は例や便利なユーティリティとして機能します:

  • 特定の条件を満たすコンテンツの双方向自動投稿を提供します。
  • 任意のタイミングでメッセージを Discourse にコピーするコマンド
  • Discord サーバーのロールメンバーシップと Discourse インスタンスのグループメンバーシップを同期させるコマンド

このプラグインは、追加機能を実装するための拡張可能なスケルトンを提供します。一般的に有用な追加機能の PR は歓迎します。


これらは同期コマンドそのものではなく、可能なボット相互作用の一例です。スクリーンショットの 2 番目のコマンドは開発中に非推奨となりました;)

設定にはある程度の複雑さが伴いますが、両システムのファンで、少なくとも機能的・概念的なレベルで各システムの仕組みを理解する時間を割く意欲がある方には最適です。このプラグインを最大限に活用するには、Discourse と Discord のユーザー管理の仕組みに関する基礎知識が必要です。

ボットコマンド

以下の 4 つのコマンドがあります:

  1. Ping!
  2. !disckick
  3. !discsync
  4. !disccopy

Ping!

ボットが応答しているか確認するには、「Ping!」と入力してください。ボットは「:robot: : Pong!」と応答するはずです。素晴らしいですね:D(これはちょっとしたネタです!)

!disckick <min_trust_level: デフォルト 2>

このコマンドを入力すると、Discourse 上に存在するが、指定した値より低い信頼レベル(Trust Level)を持つユーザーが全員キックされます。値を指定しない場合、デフォルトは 2 です。

例:

!discsync <clean up: デフォルト false, min_visibility: デフォルト 0, include automated groups: デフォルト false>

このコマンドは、指定された条件(または指定がない場合はデフォルト)に一致するすべてのグループを Discord のロールにコピーしようとします。その後、Discourse のグループメンバーシップに基づいてロールを埋めようとします。これは一方向の同期のみで、Discourse のデータは一切変更されません。

!disccopy <number_of_messages> <optional_target_category_name> <optional_target_topic_name>

Discord チャット内から、Discord のメッセージ履歴を Discourse インスタンスにコピーできます。一度に数千件のメッセージを処理可能ですが、その場合は時間がかかります。

双方向通信

設定は以下の通りです。

  • プラグイン設定で、Discord の「Announcements Channel」を指定できます。
  • 割り当てられた Discord の Announcements Channel にメッセージを入力すると、プラグイン設定で指定された Discourse のトピックに投稿されます。
  • 誰かが特定のカテゴリに投稿したり、新しいトピックを作成したり(またはその両方)した場合に、Discord の Announcements Channel に投稿する Discourse のカテゴリリストを設定できます。
  • 自動化されたメッセージ単位のチャットコピー:チャンネル名がカテゴリ名と一致する場合、そのチャンネルのメッセージが自動的に Discourse にコピーされます。

image

さらに、discordrb API がサポートする Discord イベントを管理するための新しいファイルを追加しました。Announcements ロジックが最初の例です(コミュニティ全体に有用であれば、新しいものを開発して PR を送ってください)。

NB:Discord から Discourse にコピーされたメッセージについては、ユーザーは正しく表示されます(そのユーザーが Discord ログインを使用して Discourse にログインしている場合)。つまり、Discord ボットはユーザーをマッチングできます。

このプラグインの現状

このプラグインは設定が複雑です。これは避けられないことでした。

しかし、一度セットアップが完了すれば、使用するのは子供のお遊びのように簡単です。

コードは現在ベータ版として扱ってください。テスト済みであり、本番環境でも動作していますが、バグが含まれている可能性があります。本番環境のメイン Discord サーバーに適用する前に、まずは新しい Discord サーバーでテストすることを推奨します(新規構築中の場合は除きます)。

バグが発生した場合、Discourse インスタンスよりも Discord インスタンスの方が影響を受けやすいです。なぜなら、Discourse 側には変更が加えられないからです。ただし、ほとんどの事象は回復可能であり、通常は操作を繰り返すだけで問題を解決できます。Discourse はメンバーシップとグループ情報のマスターとして使用され、このデータを使用して Discord サーバーのメンバーシップとロールが更新されます。

設定手順

前提条件

  1. 管理者権限を持つ Discord サーバー
  2. Discord アプリ(下記参照)
  3. Discord ボット(下記参照)
  4. Discourse サーバーへの ssh ルートアクセス
  5. プラグインをインストールするための app.yml の更新
  6. プラグインをインストールするとログインページに Discord OAuth ログインが表示されるため、Discourse のすべてのユーザーは Discord OAuth ログインでログインする必要があります。

Discord アプリ

こちらにアクセスしてアプリを作成してください:

「New Application」をクリックします。

ボットを作成する必要があります。以下のような画面になります(「public」にはしないようにしてください):

ブラウザでボットを承認する必要があります。詳細は OAuth2 - Documentation - Discord を参照してください。

ボットの設定が完了したら、トークンをコピーしてください。後で Discourse にこのトークンを入力する必要があります。

app.yml の変更

plugin

Discord Social Login が Discourse コアにネイティブで組み込まれた現在、必要なプラグインはこれだけです(やったー :tada:

その後、通常通りプロンプトで ./launcher rebuild app を実行してください。

これで問題なく動作するはずです。

Discourse の設定画面でボットの認証情報をまだ入力していないため、初回ビルド時にコンソールやログにボットの起動失敗を示すエラーが表示される可能性があります(これをより graceful に処理するタスクが残っており、完了次第この部分は削除します)。ただし、害はなく、Discourse 自体は正常に動作します。

Discourse の管理画面に入ったら、「Plugin Settings」に以下の情報を入力してください:

ID は Discord のインターフェースから取得します。これらの ID をコピーできるようにするには、開発者モードを有効にする必要があります。Discord で「Settings」→「Appearance」→「ADVANCED」へ進み、開発者モードを有効にしてください:

その後、インターフェースから ID を取得できます。例:

Discord OAuth 設定も入力する必要があります。Client ID と Secret は、先ほど作成した同じ Discord アプリから取得します。

これらを設定したら、Linux のルートプロンプトに戻り、以下を入力してください:

./launcher restart app

Discord と Discourse サーバーが正しく設定されていれば、ボットがサーバーに参加しているのが確認できるはずです。

万が一ボットがダウンした場合(オフラインになる)、同じ手順を繰り返して再起動させる必要があります。Discourse コアサーバーからのボットの独立性を高めることは今後の課題です。とはいえ、長期間本番環境でボットを運用してきましたが、まだダウンしたことはありません。

今後のコマンドについて

Discourse と Discord の連携を活用し、コミュニティ全体に有用だと考えられる新しいコマンドのアイデアがあれば、返信でお知らせください。実装の可能性を検討します。NB:このボットは Discourse の範囲外のタスクを実行するものではありません。

制限事項

このプラグインの主な目的は、ユーザーが自身の Discord サーバーで、Discourse サーバーを動力源とするボットを作成し、基本的なメンバーシップ管理機能を実行できるようにすることでした。また、将来の両システム間の追加のボットのような相互作用のための基盤も提供します。ボットを使用する動機の一つは、単にそれがとても面白いからです。

ボットコマンドは本質的に任意(ad hoc)です。

既知の問題

  • サーバー上で rails console セッションに入ると、ボットが自身のインスタンスを起動してしまいます。これにより、ボットが二重に応答しているように見えます(実際にはボットが 2 つ起動しています)。rails console では、::DiscordBot::Bot.discord_bot.stop と入力して追加のボットを停止してください。 これはもはや必要ありません!

  • ‘online’ Discourse アップグレード中は、ロボットがアップグレードプロセス中に再起動され続けるため、少しおしゃべりになります。これは、ウェブサーバーから分岐したスレッドではなく、独立した管理プロセスでボットを実行する良い方法を見つけることに関連しています。ただし、これはすべて無害であると考えられますし、ボットの出力が Discord の管理者チャンネルにのみ表示されるのであれば、気にするでしょうか? ボットがリビルド中に 2 回のみ自己紹介を行うように変更したため、ほぼ解決しました。

謝辞

このプラグインの完成までに長い時間を要しましたが、@Wedgebert@FoohonPie などのバックラーの方々に感謝します。Jeff さんの寛大なご支援に感謝します。また、@angus さんには激励と金銭的サポートの対応に感謝します。

このプラグインは、以前の段階で @Watercolor_Games さんが行った仕事に触発されたものであり、@featheredtoast さんが構築した Discord OAuth プラグインに依存しています。

また、準公式の Discord 対応 discordrb Ruby ライブラリ と、システムをアクセス可能にするための Discord チームの素晴らしい取り組みに依存しています。依存関係の解決に非常に迅速に対応してくれた @Falco さんにも感謝します。

もちろん、Discourse の素晴らしいプラグインエコシステム(やったー!)がなければ、これは不可能でした。

この手順書の現状

時間とともに改善され、フィードバックを歓迎します。不明な点が残っている箇所もあるでしょう。

「いいね!」 47
Discord<-> Discourse Selective Group Sync
Discord login and obtain discord roles in discourse
Discord and Discourse - Better Together | Blog
Convert Existing Plugin to do Discord to Discourse role/group sync
Slack Bot Construction Kit :robot:
2019: The Year in Review
Creat a user automatically when granted a Discord Role?
Discord Sync: sync a Discourse forum with a Discord server
Creating bot on discourse
Using "custom" ruby gems
Discourse Trust Levels for Discord
Discord is taking aim at Discourse. How does Discourse remain unique and stand out from the crowd?
Discord is taking aim at Discourse. How does Discourse remain unique and stand out from the crowd?
Copy + Pasting text from Discord into Discourse mangles paragraph breaks
Discord Role Badge Sync
Discord Bot: Topics not Posts
How do I go about making a very customized theme?
API feature request for additonal info about external accounts
Can anyone help me to add chat option of discord on forum?
How to Integrate/Sync Discord User MEE6 Points with Discourse Leaderboard?
LF Developer, Theme Creator, and Discord/Discourse Hero
Discord Sync: sync a Discourse forum with a Discord server
[PAID] Discourse/Discord integration needed (roles/user groups)
Can anyone help me to add chat option of discord on forum?
Discord and Discourse - Better Together | Blog
How to easily make Discourse bots?
Discourse to Discord bot possible?
Migrating from Discord to Discourse
Convert Existing Plugin to do Discord to Discourse role/group sync
Is migration from other chat apps supported?
Partially enable login option
Introducing Discourse Chat (BETA)
Which instant messenger do you use with Discourse?
Request widgetbot.io
Discord Sync: sync a Discourse forum with a Discord server

Hey I’m super interested in this.

Would the opposite be possible? I’d love a way to be able to create a Discourse setup for my Discord server. I’m not sure if there’s a Discord API event for roles being given but you could probably check when someone logs in with Discord or with CRON.

「いいね!」 2

Yes, absolutely.

You could either build that as a bot command for ad hoc application, but with a repeat feature that reran the command after a period (nice but not very transparent and no way to individually manage these recurrences)

OR

As I alluded to above, have it scheduled as a job in Discourse as a sidekiq job. That might be a separate plugin (I actually started on the skeleton of that approach before moving to a bot only solution mainly because the ‘bot’ approach was kind of the Discord ‘thing’, fun and offered a unique approach and result), but if I can get Discourse to fire off bot commands then that’s moot (not yet had the chance to test that), and then we can write stuff once and have it work either way (nice!).

Both these solutions would rely on the same OAuth login though.

Whilst this is an excellent idea, it can’t be a priority for me at present because I have a lot of other client work at the moment I need to deliver, but if you wish to support such an extension, we can discuss offline on a PM and schedule it in.

「いいね!」 4

It might be interesting to play around with, but I have nowhere near the skill level required to volunteer to develop/maintain an addon like this. I might make a messy fork at some time but I certainly don’t want my name on anything official. :slight_smile:

「いいね!」 3

Absolutely get messy. It’s the only way to learn. :).

「いいね!」 4

Minor bug fix deployed:

Got this during rebuild:

Bot is still offline. Triple checked everything and it’s all set up correctly. Not sure how to proceed now… Maybe I need to open a port on my server instance?

「いいね!」 2

Thanks for testing this out and so soon after the update. Let me try to reproduce and I will revert. I did not change anything wrt to the port config.

「いいね!」 2

No issues rebuilding here, Bot comes up fine … have you changed anything in your server config in between?

Your 400 Bad Request sounds like your server sent a corrupt or bad request to the Discord server and this was the response. This suggests it received it fine and was not blocked.

You can get this for:

  • malformed requests
  • lack of authorisation
  • exceeding rate limits

Unfortunately the error message doesn’t appear to help us determine which of these was the particular issue.

Presumably your Discourse is up? Check all the plugin settings are populated correctly.

Just to rule out a temporary gremlin run ./launcher restart app when you get chance … this will take your site down for a few seconds only (sorry about that!).

I see it runs the bot in the after_initialize block, so it will prevent migrations (and rebuilds) if the bot is misconfigured, or if Discord is down.

Maybe try to handle this exception and just log it?

「いいね!」 5

It runs on a separate thread? So I expect that not to be an issue?

However this callback seems to run several times in a rebuild, so the main issue will be that a misconfigured bot could actually breach rate limits if authorisation fails too many times in quick succession. If that happens the account, in worse case, could be blocked for some time.

In any case, I’ll do a quick patch to do that with the current implementation to lessen the impact. Thanks for the suggestion.

UPDATE: @falco, this is done, e.g.:

image

「いいね!」 3

First I want to say thank you for making this, once I can get it working its going to be a huge help for us managing our discourse and discord for a volunteer community.
I am running into a 400 error when trying to run this bot. Prior to this plugin being added we have been successfully using the official discord auth plugin and webhooks via the chat integration plugin. I’ve validated that those are both still working appropriately.

I created the bot within the same discord app I’d previously created authorized the bot within the discord server, it shows up in the member list as offline. Your documentation didn’t say what permission value to apply, but given most bots I’ve encountered for discord asked for it I went ahead and set it up with a permissions value of 8 for Administrator.

Within the discord server I then copied the ID of the Role it created, which was named after my app, and the id of the channel for admin text.I added the app Role to that channel with full rights, just to be sure, then added the IDs to discourse and restarted.

Unfortunately no matter what I try I’m getting a 400, I even tried a rebuild just to be sure.

「いいね!」 3

Thank you, kind words. It was also enabled by the generosity of funders.

Yes, that’s great. It should have Admin.

This is the second report of this issue.

If you intentially remove the last char of the token in settings (remember what this is) do you get a 401 instead?

Let’s move this to PM because it might get messy :wink: (we can always post the solution here).

「いいね!」 4

Just to post an update in case anyone else sees this, we’re actively looking into the issue but haven’t yet narrowed down the cause. I’d say if anyone else is running into this issue please say so would help to have others testing.

「いいね!」 1

This is now fixed. It was a weird one to track down.

Thanks to @ransim for raising and working with me to get to the bottom of it.

Huge thanks to the #ruby_discordrb gang on Discord API for their patient and instant help!

@neemiasvf

「いいね!」 5

@merefield no problem,Your plugin is great.But I have encountered some problems now.
such this:

Discourse Sync:  Starting.  Please be patient, I'm rate limited to respect Discord services.
Discourse Sync:  Checking if there are any eligible groups for sync ...
Discourse Sync: 1 eligible group(s) were found
Discourse Sync:  Preparing list of users who also have a registered account on Discord ...
Discourse Sync:  Preparing list of groups that users who have a registered account on Discord belong to on Discourse ...
Discourse Sync: 0 eligible group(s) were found with Discord users
Discourse Sync:  No users were found in elibigle groups for sync using provided or default criteria!

my commond is : !discsync 4

and commond changed: !discsync false 5 false

Discourse Sync:  Starting.  Please be patient, I'm rate limited to respect Discord services.
Discourse Sync:  Checking if there are any eligible groups for sync ...
Discourse Sync: 10 eligible group(s) were found
Discourse Sync:  Preparing list of users who also have a registered account on Discord ...
Discourse Sync:  Preparing list of groups that users who have a registered account on Discord belong to on Discourse ...
「いいね!」 1

Hey @p0nda, sorry for slow reply.

If you include any parameters, you need to include all of them. It might be interpreting things strangely.

「いいね!」 3

Unable to get the extended bot settings to show up? I have the changes to the app.yml and plugins installed. I have the OAuth setup working, but not the bot settings. Any ideas?

「いいね!」 1

The OAuth setting are there but no bot settings

「いいね!」 1

image
These

「いいね!」 2