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()メソッドで処理することもできます.実装しなくても大丈夫といえば大丈夫です.ログにエラー出力されますけどね.
利用这个来修正上次文章中写的代码。
代码如下所示。
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}]”)
チャンネルの制限
まずは現在の状態を確認しておきましょう.チャンネルの制限をしていない場合は以下の通りです.
-
- generalでminecraft serverを起動し
- minecraft_channelで停止ができている
這是一個狀態。如果有重要的資料需要查找,這個東西將會阻礙。因此,我們只需要在minecraft_channel時才做出反應。
Groupにinteraction_check()を追加しましょう.このGroupはminecraft serverの起動と停止をするコマンドグループです.よって,ここに反応するチャンネルを制限しておきます.そのためにはチャンネルIDを取得する必要があります.
让我们修改代码吧。
- 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)
在旁边,就在Minecraft频道那边。
と送られました.そしてminecraft_channelの方でコマンドを入力すると
無事に実行することができました.
人の制限についても,interactionのuserを比較すればできると思います.
冷却时间
命令可以无限次输入。因此,可以多次输入命令。
画質がめっちゃ荒いですが,なんとなく想定している動作ではないことはわかるでしょう.この原因は短時間に何度もコマンドが動作してしまうからです.そのため,一度コマンドを打ったら,再度実行できるまで猶予をもらいましょう.
そのために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)
运行后的结果如下所示。
虽然出现了一些错误,但总体上能够完成想做的事情。不过每次执行命令都会显示在冷却中。
以上就是。
-
- コマンドを打つことができるチャンネルの制限の設定
- コマンド連打対策のためにcommandにcooldownを設定すること
我解释了。辛苦了。