Discord.js で自分のメッセージを自分で消せないようにする

1 min read読了の目安(約1200字

動機

Discord は実に天才的なソフトウェアです。何でもできる。
しかし、一つ問題があって。自分のメッセージを自分で消すという行動を制御できないんですよあれ。どうにかするにはボットで外部的に介入するしかないらしく、しましょう。

方針

Discord.js はイベント駆動なので、「メッセージを削除した」というイベントを吸って吐けばどうにかなります。ここで重要なのは「結果論的に消せない」ということで、「消すというアクション自体は禁止しない」ことです。ここは課題。

しかし、全員削除を禁止するというのも何かと面倒です。ここでは「消すのを禁止」したロール(以下削除ロール)を生やして、削除ロールで権限管理をすることとします。

そして何かと便利なのでボット自体にも自身のメッセージ削除を禁止します。コード側で実装すると環境依存のパラメタが増えて大変ですが、Discord のロール管理で解決できれば汎用的に処理できるのでそのようにします。

処理フローは以下のようになります。

  1. (メッセージ削除を禁止するロールを追加して、ID を持ってきて、.env に書いておく)
  2. (そもそも .env が設定されているかチェックする)
  3. メッセージ削除イベントを受け取る
  4. メッセージの削除したユーザが削除ロールを持っているか判別する
    • 持っていれば続行
    • 持っていなければ終了
  5. 削除されたメッセージの本人タグ・内容を取得する
  6. ボットが代理で消されたメッセージを代わりに投稿する

コード

Discord.js のアーキテクチャ自体は示さないので、どうにかしてください。

client.on('messageDelete', ctx => {
    // dotenv で .env から権限管理ロールを吸ってくる
    const permission = process.env['MESSAGE_PROHIBIT']

    if (!permission) {
        return
    }

    if (!ctx.member?.roles.cache.has(permission)) {
        return
    }

    const author = ctx.author?.tag
    const content = ctx.content

    // こうしないとボットのメッセージを消すと一生タグが増える、やればわかる
    if (ctx.author?.bot) {
        ctx.channel.send(`${content}`)
        return
    }

    ctx.channel.send(`${author} ${content}`)
})

最後に

今やったことぐらいバニラの Discord でどうにかできるようにしてほしい。