9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

discord.py - commandsフレームワークへの移行

Last updated at Posted at 2021-01-29

はじめに

この記事はdiscord.pyのcommandsフレームワークに移行する方法を書いたものです。
執筆初心者なので、間違いを見つけたらどんどん指摘してください。

環境

- Python v3.8.3-final
- discord.py v1.6.0-final
- aiohttp v3.6.3
- system info: Windows 10 10.0.17134

python -m discord -vの情報)

最初のコード

以下のコードから始めるモノとします:

import discord

client = discord.Client()
RESPONSES = {
    "おは": "おはよう!",
    "おやすみ": "おやすみ!",
    "落ち": "おつかれ!"
}

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    for rk, rv in RESPONSES.items():
        if rk in message.content:
            await message.reply(rv)
    
    if message.content.startswith('$ping'):
        await message.channel.send('Pong!')
    elif message.content.startswith('$greet'):
        await message.channel.send(f'Hello, `{message.content[7:]}`.')

client.run('Th1sIsN0tT0k3n.B3cause.1fiShowB0tWillG3tH4cked')

1. インポート

commandsフレームワークをインポートするには

import discord
+ from discord.ext import commands

のようにします。
普通のdiscordは残しておきます。(isinstanceでの判定やEmbedの作成に必要になります。が、今回は不必要です。)

詳細

実際、

import discord.ext.commands

でも動きはしますが、
毎回

discord.ext.commands.Bot(command_prefix="!")

@bot.command()
@discord.ext.commands.has_permissions(administrator=True)

と書く必要があり、面倒なためfrom~importを使っています。

#2. ClientをBotにする

ClientをBotにしていきます。
移行にはそんな心配は要らず、discord.Clientをcommands.Botに置き換えるだけで移行できます。
Botを使うにはプレフィックス(/!など、コマンドの最初につける文字)を決める必要があります。
今回は$にしました。

- client = discord.Client()
+ bot = commands.Bot(command_prefix="$")

また、clientをbotにしたため、clientをbotに置き換えていきます。

- @client.event
+ @bot.event
async def on_ready():
-     print('We have logged in as {0.user}'.format(client))
+     print('We have logged in as {0.user}'.format(bot))

- @client.event
+ @bot.event
async def on_message(message):
-     if message.author == client.user:
+     if message.author == bot.user:
        return

    for rk, rv in RESPONSES.items():
        if rk in message.content:
            await message.channel.send(rv)
    
    if message.content.startswith('$ping'):
        await message.channel.send('Pong!')
    elif message.content.startswith('$greet'):
        await message.channel.send(f'Hello, `{message.content[7:]}`.')


- client.run('Th1sIsN0tT0k3n.B3cause.1fiShowB0tWillG3tH4cked')
+ bot.run('Th1sIsN0tT0k3n.B3cause.1fiShowB0tWillG3tH4cked')

#3. コマンドを定義する

「commands」フレームワークの名の通り、このフレームワークはコマンドを簡単に作ることができます。
コマンドを作るには@bot.commandが一般的です。
関数名がそのままコマンド名になります。

詳細

@commands.commandで定義後、bot.add_commandで追加する方法もありますがそれほど使わないので割愛。

また、@bot.commandには()が必要なので注意。
@bot.command()
async def ping(ctx):
    await ctx.reply("Pong!")

@bot.command()
async def greet(ctx, name):
    await ctx.reply(f"Hello, `{name}`.")
覚えていると役立つこと

listのように関数名がかぶりそうなときはname=を引数に指定します。

@bot.command(name="greet")
async def command_greet(ctx, name):
    await ctx.reply(f"Hello, `{name}`.")

エイリアスを追加するにはaliases=を指定します。

@bot.command(aliases=["hi", "hello"])
async def greet(ctx, name):
    await ctx.reply(f"Hello, `{name}`.")

空白を無視して受け取りたいときは*,をつけます。

@bot.command()
async def greet(ctx, *, name):
    await ctx.reply(f"Hello, `{name}`.")

これらは全て一緒に使うことが出来ます。

@bot.command(name="greet", aliases=["hi", "hello"])
async def command_greet(ctx, *, name):
    await ctx.reply(f"Hello, `{name}`.")

コマンドを定義したため、on_messageのコマンドを削除します。

@bot.event
async def on_message(message):
    if message.author == bot.user:
        return

    for rk, rv in RESPONSES.items():
        if rk in message.content:
            await message.channel.send(rv)

-     if message.content.startswith('$ping'):
-         await message.channel.send('Pong!')
-     elif message.content.startswith('$greet'):
-         await message.channel.send(f'Hello, `{message.content[7:]}`.')

#4. コマンドを動作させる

on_messageを定義するとコマンドが実行されなくなります。
このようなときにはprocess_commandsを使います。

@bot.event
async def on_message(message):
    if message.author == bot.user:
        return
    
    for rk, rv in RESPONSES.items():
        if rk in message.content:
            await message.channel.send(rv)
   
+     await bot.process_commands(message)

これで移行は終了です。

最終コード

import discord
from discord.ext import commands

bot = commands.Bot(command_prefix="$")
RESPONSES = {
    "おは": "おはよう!",
    "おやすみ": "おやすみ!",
    "落ち": "おつかれ!"
}

@bot.event
async def on_ready():
    print('We have logged in as {0.user}'.format(bot))

@bot.command()
async def ping(ctx):
    await ctx.reply("Pong!")

@bot.command()
async def greet(ctx, name):
    await ctx.reply(f"Hello, `{name}`.")

@bot.event
async def on_message(message):
    if message.author == bot.user:
        return

    for rk, rv in RESPONSES.items():
        if rk in message.content:
            await message.reply(rv)
    
    await bot.process_commands(message)


bot.run('Th1sIsN0tT0k3n.B3cause.1fiShowB0tWillG3tH4cked')

終わりに

この記事が役に立てば幸いです。
読んでいただきありがとうございました。

9
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?