【22日目】スラッシュコマンドを使おう【PythonでDiscordBOTを作ろう！】

# 便利なアイツ
スラッシュコマンドです。
これって便利ですよね。

これ、便利ですよね。ユーザーとしては本当に便利です。

これからは、Cogにコマンドを追加していく前提でやっていきます。
一部のデコレーターやコマンド引数が通常とは異なりますので、ご留意ください。
また、`nextcord`前提で記載してます。

# 書いてみよう
```diff_python:dog.py
+ import nextcord
  from nextcord.ext import commands

  class Dog(commands.Cog):
      def __init__(self, bot: commands.Bot):
          self.bot = bot

+     @nextcord.slash_command()
+     async def inu(self, interaction: nextcord.Interaction):
+         await interaction.send("ｲﾇｩU^ェ^U")

      @commands.command()
      async def dog(self, ctx: commands.Context):
          await ctx.reply("わおーん！")

  def setup(bot):
     bot.add_cog(Dog(bot))
```

さて、`interaction`とかいう知らないものが出てきましたね。
一応これで実行してみましょう。

...と、スラッシュコマンドには注意点があります。

## スラッシュコマンドの種類
スラッシュコマンドには2種類あって、`グローバルコマンド`と`ギルドコマンド`があります。
グローバルコマンドは、BOTが加入しているサーバー全てで使えるスラッシュコマンド。
ギルドコマンドは、指定したサーバーでのみ使えるスラッシュコマンド。

詳しくは、下記の方の記事が参考になると思います。

https://qiita.com/CyberRex/items/2ce560f88427f4764425#どのサーバーでも使えるコマンドとそうでないもの

さて、デバッグしている最中なのでコマンドは即時反映して欲しいものです。
なので、Guild Commandにしましょう。

まずは、サーバーID（GuildID）を取得しなければなりません。

これについては、Discordの記事を見た方が早いです。


[ユーザー/サーバー/メッセージIDはどこで見つけられる？ - Discord Support](https://support.discord.com/hc/ja/articles/206346498-ユーザー-サーバー-メッセージIDはどこで見つけられる-)

```diff_python:dog.py
  import nextcord
  from nextcord.ext import commands

  class Dog(commands.Cog):
      def __init__(self, bot: commands.Bot):
          self.bot = bot

-     @nextcord.slash_command()
+     @nextcord.slash_command(guild_ids=[サーバーID])
      async def inu(self, interaction: nextcord.Interaction):
          await interaction.send("ｲﾇｩU^ェ^U")

      @commands.command()
      async def dog(self, ctx: commands.Context):
          await ctx.reply("わおーん！")

  def setup(bot):
     bot.add_cog(Dog(bot))
```

さて、このままではスラッシュコマンドは使えません。（多分）
12/6に、流れのまま`bot`にだけチェックを入れたからです。

https://discord.dev

Discord Developer Portalから、`Applications`→自分のBOT→`OAuth2`→`URL Generator`から、`bot`と`applications.commands`にチェックを入れて、出てきたURLで再度認証してください。

![47475E60-5AB2-4C71-A1C1-4FFF0E94A14C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/3916613c-02fe-626d-76b2-e5754580cea6.jpeg)


これでBOTを起動してみましょう。
そして、指定したサーバーで`/`と打つと`/inu`のコマンドが表示されると思います。
実行すると犬がやってきますね。

![4430B87D-8D92-4C98-8471-45870BA04342.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/0caf2223-d7c9-59e2-0d1a-20cb4bb6d107.jpeg)


`interaction`は、コンテキストコマンドで言うところの`ctx`です。
メッセージを送信したりできます。

# スラッシュコマンドの時間制限
さて、今はコマンドが実行されたらすぐに返信していますが、何か沢山処理があったら実はとあることが発生します。
それはこれです。

Discordは、スラッシュコマンドを送信してから（インタラクションを送信してから）3秒経過までにデータが送られなかった場合は、このように「アプリケーションが応答しませんでした」と表示されます。
これがちょっとめんどくさいんです。

対策はもちろんあります。
3秒以内に`await interaction.response.defer()`を実行すると、3秒の猶予が長くなります。
具体的にどれぐらい長くなるかというと、2分か3分か15分です（私の記憶が定かではない（まぁ早いに越したことはない））。

# スラッシュコマンドのオプション

スラッシュコマンドでは文字を入力したり、ユーザーを選択したりロールを選択することができる`SlashOption`という機能があります。

```diff_python:dog.py
  import nextcord
  from nextcord import commands

  class Dog(commands.Cog):
      def __init__(self, bot: commands.Bot):
          self.bot = bot

      @nextcord.slash_command(guild_ids=[サーバーID])
-     async def inu(self, interaction: nextcord.Interaction):
+     async def inu(
+         self,
+         interaction: nextcord.Interaction,
+         dogtype: str = nextcord.SlashOption(
+             description="Type of dog",
+             required=True
+         )
+     ):
+         if dogtype == "annoy":
+             await interaction.send("しろい　こいぬ。 ぐっすり　ねむっている…")
+         else:
+             await interaction.send("ｲﾇｩU^ェ^U")
-         await interaction.send("ｲﾇｩU^ェ^U")

  @commands.command()
  async def dog(self, ctx: commands.Context):
      await ctx.reply("わおーん！")

  def setup(bot):
     bot.add_cog(Dog(bot))
```

これで実行してみましょう。
![F591C7FA-BA8E-4539-B818-7A79B57D2A9C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/027439c9-cce7-713c-64f8-1d3da0f79e00.jpeg)

すると、`dogtype`という選択肢が現れます。
ここに`annoy`と入れると、[うざいイヌ](https://wikiwiki.jp/undertale_/うざいイヌ)が現れます。
他の文字を入れると普通の犬が現れます。

![C588B0A8-F5BA-40BD-985B-1C6EB061353D.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1107984/ed70297d-bd23-c68f-3613-20a566418f61.jpeg)

（上は`normal`と入力。下は`annoy`と入力。）

# 以上がスラッシュコマンド！！
年末商戦に向けて頑張ってる方々、頑張ってください！
私は、アドベンドカレンダー書いてて2回目の絶賛体調不良です！

では次回の記事は「非同期処理で書こう。」です！
よろしくね！！！