Discord机器人的冷却和交互检查

前提 tí)

这篇文章是一个关于在Discord机器人上操作Minecraft服务器的 9天目 的圣诞日历活动。
简单来说,它介绍了如何通过Discord机器人来操控Minecraft服务器。

    • コマンドを打つことができるチャンネルの制限の設定

 

    コマンド連打してくる悪い人への対策のためにcommandにcooldownを設定すること

会详细解释一些琐碎的事情。

    • WSL

Ubuntu 22.04.1

Python 3.10.6
discord.py

这是一个环境。
而且,discord中的服务器和minecraft的服务器可能有点复杂,所以我们将discord中的服务器称为公会。

限制对命令的响应。

discord botにおいて,コマンドは基本誰でもどこでも利用できます.どこでもというのは,どのギルドでも,どのチャンネルでも,誰でも利用できるということです.そのため,あちこちに反応されると大事なログが流れるかもしれません.
その対策として,反応するチャンネルや反応するユーザーを制限しましょう.ギルドの制限に関しては,そもそもそのアプリを必要としているからbotを入れているわけですから,まあ今回は考えないことにしましょう.

さて,反応するチャンネルや反応するユーザーを確認するためinteraction_check()というものを利用します.

检查交互_interaction_check()

interaction_check()はui.View()やCommandTree,Groupなどで利用できるメソッドです.
これはinteraction,つまりコマンドを打ち込んだときに実行されるものです.引数にinteractionを取ります.返り値はコマンドを実行して良いかどうかのboolです.
また,返り値としてfalseとなった場合,on_error()メソッドで処理することもできます.実装しなくても大丈夫といえば大丈夫です.ログにエラー出力されますけどね.

利用这个来修正上次文章中写的代码。
代码如下所示。

discord bot x minecraft serverのコードMinecraftCommand.py
from discord import app_commands, Interaction
from MCServer import MCServer

class MinecraftCmd(app_commands.Group):
def __init__(self, server):
super().__init__(name=”minecraft”)
self.server: MCServer = server

@app_commands.command()
async def start(self, interaction: Interaction):
await interaction.response.send_message(‘minecraft server is starting…’)
started = self.server.start()
if started:
await interaction.followup.send(f”{interaction.user.mention}! server start successfully!”)
else:
await interaction.followup.send(f”{interaction.user.mention}, sorry. server cannot start”)

@app_commands.command()
async def stop(self, interaction: Interaction):
await interaction.response.send_message(‘minecraft server is stopping…’)
stopped = self.server.stop()
if stopped:
await interaction.followup.send(f”{interaction.user.mention}! server stop successfully!”)
else:
await interaction.followup.send(f”{interaction.user.mention}, sorry. server cannot stop”)

discordbot.py
from MCServer import MCServer
from MinecraftCommand import MinecraftCmd
from discord import Intents, Client
from discord.app_commands import CommandTree

class MCClient(Client):
def __init__(self, intents: Intents) -> None:
super().__init__(intents=intents)
self.tree = CommandTree(self)
self.server = MCServer()

async def setup_hook(self) -> None:
self.tree.add_command(MinecraftCmd(self.server))
await self.tree.sync()

async def on_ready(self):
print(f”login: {self.user.name} [{self.user.id}]”)

チャンネルの制限

まずは現在の状態を確認しておきましょう.チャンネルの制限をしていない場合は以下の通りです.

undefined
undefined
    1. generalでminecraft serverを起動し

 

    minecraft_channelで停止ができている

這是一個狀態。如果有重要的資料需要查找,這個東西將會阻礙。因此,我們只需要在minecraft_channel時才做出反應。

Groupにinteraction_check()を追加しましょう.このGroupはminecraft serverの起動と停止をするコマンドグループです.よって,ここに反応するチャンネルを制限しておきます.そのためにはチャンネルIDを取得する必要があります.

image.png
image.png
image.png

让我们修改代码吧。

- from discord import app_commands, Interaction
+ from discord import app_commands, Interaction, Client
+ from discord.app_commands import AppCommandError
from MCServer import MCServer


class MinecraftCmd(app_commands.Group):
-   def __init__(self, server):
+   def __init__(self, server, client: Client):
        super().__init__(name="minecraft")
        self.server: MCServer = server
+       self.allowed_channel_id = 1050795597852053565
+       self.client = client

    @app_commands.command()
    async def start(self, interaction: Interaction):
        await interaction.response.send_message('minecraft server is starting...')
        started = self.server.start()
        if started:
            await interaction.followup.send(f"{interaction.user.mention}! server start successfully!")
        else:
            await interaction.followup.send(f"{interaction.user.mention}, sorry. server cannot start")

    @app_commands.command()
    async def stop(self, interaction: Interaction):
        await interaction.response.send_message('minecraft server is stopping...')
        stopped = self.server.stop()
        if stopped:
            await interaction.followup.send(f"{interaction.user.mention}! server stop successfully!")
        else:
            await interaction.followup.send(f"{interaction.user.mention}, sorry. server cannot stop")

+   async def interaction_check(self, interaction: Interaction, /) -> bool:
+       return interaction.channel_id == self.allowed_channel_id
+
+   async def on_error(self, interaction: Interaction, error: AppCommandError, /) -> None:
+       allowed_channel = self.client.get_channel(1050795597852053565)
+       await allowed_channel.send(f"{interaction.user.mention}. plese this channel to run command")
+       print(error)

image.png

在旁边,就在Minecraft频道那边。

image.png

と送られました.そしてminecraft_channelの方でコマンドを入力すると

image.png

無事に実行することができました.
人の制限についても,interactionのuserを比較すればできると思います.

冷却时间

命令可以无限次输入。因此,可以多次输入命令。

undefined

画質がめっちゃ荒いですが,なんとなく想定している動作ではないことはわかるでしょう.この原因は短時間に何度もコマンドが動作してしまうからです.そのため,一度コマンドを打ったら,再度実行できるまで猶予をもらいましょう.
そのためにcooldownを設定します.またリファレンスにサンプルがあるのでそれを参考にします.

冷却时间是在appcommands.checks中的一个装饰器。它的参数包括使用次数限制、冷却时间长度和限制范围。

以下是已应用冷却时间的代码。

from discord import app_commands, Interaction, Client
from discord.app_commands import AppCommandError
from MCServer import MCServer


class MinecraftCmd(app_commands.Group):
    def __init__(self, server, client: Client):
        super().__init__(name="minecraft")
        self.server: MCServer = server
        self.allowed_channel_id = 1050795597852053565
        self.client = client

    @app_commands.command()
+   @app_commands.checks.cooldown(1, 30)
    async def start(self, interaction: Interaction):
        await interaction.response.send_message('minecraft server is starting...')
        started = self.server.start()
        if started:
            await interaction.followup.send(f"{interaction.user.mention}! server start successfully!")
        else:
            await interaction.followup.send(f"{interaction.user.mention}, sorry. server cannot start")

    @app_commands.command()
+   @app_commands.checks.cooldown(1, 30)
    async def stop(self, interaction: Interaction):
        await interaction.response.send_message('minecraft server is stopping...')
        stopped = self.server.stop()
        if stopped:
            await interaction.followup.send(f"{interaction.user.mention}! server stop successfully!")
        else:
            await interaction.followup.send(f"{interaction.user.mention}, sorry. server cannot stop")

    async def interaction_check(self, interaction: Interaction, /) -> bool:
        return interaction.channel_id == self.allowed_channel_id

+   async def on_error(self, interaction: Interaction, error: AppCommandError, /) -> None:
+       if isinstance(error, app_commands.CommandOnCooldown):
+           await interaction.response.send_message(str(error), ephemeral=True)
+       elif isinstance(error, app_commands.CommandOnCooldown):
+           allowed_channel = self.client.get_channel(1050795597852053565)
+           await allowed_channel.send(f"{interaction.user.mention}. plese this channel to run command")
+           print(error)

运行后的结果如下所示。

undefined

虽然出现了一些错误,但总体上能够完成想做的事情。不过每次执行命令都会显示在冷却中。

以上就是。

    • コマンドを打つことができるチャンネルの制限の設定

 

    コマンド連打対策のためにcommandにcooldownを設定すること

我解释了。辛苦了。

广告
将在 10 秒后关闭
bannerAds