見出し画像

Discord Botの作り方 ~基礎から実用まで~

はじめに

こんにちは、Sattです。
今回は、discord.pyを使った実用的なDiscord botの作り方を紹介しようと思います。noteやQiitaにもbotに関する記事がたくさん上がっていますが、どれも基礎的か発展的な事項のみのものが多く、参考にしづらかったため、この記事を作成した次第です。
なお、筆者はPython&discord.py歴が1か月もないため、見苦しいコードではありますが、放念していただきたいです。




準備

Discord Developer Portalでbotを登録する

Discordでbotを作るために、まずDiscord Developer Portalで自分のbotを登録し、サーバーに招待する必要があります。
下のやり方と参考画像を見ながら行ってください。

  1.  Discordアカウントでログイン。

  2. 右上の"New Application"のボタンを押して新しくアプリケーションを作成する。

  3. NAMEの欄に任意の名前を入れ、Createを押す。

  4. 左のメニューからBotを選び、少しスクロールすると"Privileged Gateway Intents"というオプションがあるので、その下にある三つの設定を全てオンにする(これをしないと、botが動かない可能性があります)。

  5. 左のメニューからOAuth2を選び、"OAuth2 URL Generator"の中の"SCOPES"から"bot"を選ぶ。

  6. "BOT PERMISSIONS"から"Administrator"(設定は楽になるが、botを乗っ取られた際の危険性が上がる)か"TEXT PERMISSIONS"と"VOICE PERMISSIONS"の中にある全ての設定(サーバー管理はできなくなるが、安全性が上がる)をオンにする。

  7. 一番下の"GENERATED URL"からリンクをコピーし、botを任意のサーバーに招待する。

2. のNew Applicationボタン
3. のイメージ画像


4. のイメージ画像
5. のイメージ画像
7. のイメージ画像

これで、招待の部分は完了です。

Pythonをインストールする

Visual Studio Codeをインストールする

これは言うまでもないと思うので、ダウンロードリンクだけつけておきます。
Python ダウンロード
Visual Studio Code ダウンロード

どちらもインストールが終わったら、Visual Studio Code(以下VSCode)を開き

画面のイメージ

Open Folder…を押して、任意のフォルダを開いてください。


基礎

まずは、元となる"main.py"から作っていきましょう。VSCodeで、右上のメニューから先ほどのフォルダに"main.py"という名前のファイルを作り、

ここを押してファイルを作成し
main.pyと名前を付ける
import discord
from discord.ext import commands
from atproto import Client # type: ignore
import json
import pretty_help
from pretty_help import PrettyHelp
import datetime
initial_extensions = (
)

description = '''こんにちは!'''

# チャンネル指定
Manage_Channel = # ここに管理用チャンネルのIDを挿入

# ずんだもん
zunda = 'https://i.imgur.com/6bgRNLR.png'

# helpコマンドのembedの下の文字
ending_note = "Pasted from Satt \nFor help: {help.clean_prefix}{help.invoked_with}"

class MyBot(commands.Bot):
    def __init__(self):
        intents = discord.Intents.all()
        super().__init__(command_prefix='!', #コマンドの前に付く記号を指定
                         description=description, # 概要欄
                         intents=intents,
                         help_command=PrettyHelp(menu=pretty_help.AppMenu(),
                                                 index_title="助けが必要ですか?", # embedのタイトル
                                                 color= 0x191919, # 色
                                                 ending_note=ending_note, # フッター
                                                 thumbnail_url=zunda, # サムネイル
                                                 send_typing=False,
                                                 sort_commands=True
                                                 )
                        )
    
    async def setup_hook(self) -> None: # ログインする前に実行されるイベント
        await bot.load_extension("jishaku") # jishakuをロードする
        for extension in initial_extensions: #cogをロードする
            try:
                await self.load_extension(extension)
            except Exception as e:
                print(e)
                print(f"Failed to load extension {extension}.")

    async def on_ready(self): # 起動時に実行されるイベント
        print(f'{self.user.name}#{self.user.discriminator} ({self.user.id})としてログインしました!')
        channel = bot.get_channel(Manage_Channel)
        await channel.send(f'botが起動しました! @{datetime.datetime.now().strftime("%H:%M:%S")}')

bot = MyBot()
# tokenをロード
bot_token = ''
with open("data/!important/bot_token.json", "r", encoding="utf-8") as f:
    bot_token = json.load(f)

bot.run(bot_token)

以上のコードを書いてください。
次に、botのtokenをDiscord Developer Portalから入手します。
左のメニューからbotを開いて、TOKENから"Reset token"のボタンを押して、tokenをコピーします。
そして、VSCodeに戻り、先ほどのフォルダにdataフォルダ、その下に!importantフォルダを作り、その中にbot_token.jsonを作成します。コピーしたtokenをダブルクォーテーション(")で囲んで保存します。ᅠ

フォルダ
┗data
  ┗!important
    ┗bot_token.json

このようなフォルダ構成になっていれば正解です。
上のメニューから"Terminal"を選んで、

pip install discord.py
pip install jishaku
pip install discord-pretty-help

をそれぞれ実行します。
discord.pyは名前のまま、botの基本となっているもの、jishakudiscord-pretty-helpはそれの拡張機能のようなものです。jishakuの使い方は後々説明します。

ここまでくれば、あとは実行するだけです!先ほど使用した"Terminal"で

python main.py

を実行し少し待てば、Manage_Channelで指定したチャンネルに"botが起動しました! @XX:XX:XX"と表示されるはずです。
任意のチャンネルで、"!help"を送った際に、

このように表示されたら成功です!

これで基礎は終了です。次の章では、実際の機能を追加していきます。

コマンドに反応する機能

先ほどの"!help"のような、コマンドに応答する機能はかなり基本的なもので、簡単に作ることができます。
フォルダ内にcogsフォルダを作成し、その中にcommand.pyを作ります。

フォルダ
  ┗cogs
    ┗command.py
  ┗data
    ┗!important
      ┗bot_token.json

このような構成になると思います。
そして、command.pyの中に

import discord
from discord.ext import commands
import random
from atproto import Client # type: ignore
import asyncio
import json
from cogs.diyembed import diyembed

# 磨かれるもののリスト
items = [
    "歯", "靴", "金属(例えば、銀)", "宝石", "車のボディ", "鏡", "メガネ", "木材", 
    "陶器", "ステンレス", "ガラス", "メタルフィギュア", "時計", "銅製品", "銀器", 
    "磁器", "照明器具", "スチール", "アルミニウム", "レザー製品", "チタン", "金", 
    "ステンレス製のカトラリー", "アクセサリー", "タイル", "プラスチック", "銅線", 
    "シルバーアクセサリー", "ノートパソコンの表面", "スマートフォン", "カメラレンズ", 
    "音楽機器", "彫刻", "家具", "イヤリング", "ブレスレット", "リング", "ペンダント", 
    "スポーツ用具", "自転車のフレーム", "ヘルメット", "メダル", "ビンの口", 
    "磨き仕上げされた石", "アート作品", "眼鏡のフレーム", "すり鉢", "すりこぎ", 
    "鋼材", "磨かれた大理石", "自動車部品", "ドアノブ", "銀のカップ", "風鈴", 
    "酒器", "スポーツカップ", "ペンケース", "織物の装飾", "磨き上げられたトロフィー", 
    "工具", "アンティーク家具", "鉄製品", "電子機器の筐体", "金属製の装飾品", "ホイール", 
    "キッチン用品", "スポーツウェア(光沢加工されたもの)", "襟章", "高級筆記具", 
    "研磨剤で磨かれた木彫り", "革製のベルト", "ステンレス製の調理器具", "スポーツボトル", 
    "美術品のフレーム", "メタルパーツ(機械の一部)", "陶磁器", "木製の楽器", 
    "高級タバコケース", "ビリヤードのキュー", "船の部品", "武道の装備", 
    "楽器の金属部分", "医療機器", "スポーツ用具(クラブなど)", "カメラのボディ", 
    "音響機器", "装飾的な金属パーツ", "磨き上げられた真鍮製品", "釣り具", 
    "高級ワインのボトル", "名刺入れ", "電気器具", "金属製の家具部品", "高級な鍵", 
    "アートのフレーム", "スポーツのメダル", "車のホイールリム", "歴史的な硬貨", 
    "装飾的な宝飾品", "高級時計のケース"
]

# cogを作成
class command(commands.Cog): # commandはcogの名前(ファイル名と同じにすると良い)
    def __init__(self, bot: commands.Bot) -> None:
        self.bot = bot

    @commands.command()
    async def migaku(self, ctx):
        migaku_item = random.choice(items)
        await ctx.reply(f'今日は**{migaku_item}**を磨きましょう')

async def setup(bot: commands.Bot):
    await bot.add_cog(command(bot))

を入力し、main.pyの

initial_extensions = (
)

この部分を

initial_extensions = (
    "cogs.command", # ロードするcogを選択
)

これに書き換えてください。
さて、突然ですが、このbot制作においてはdiscord.pyのcogという機能を使っているので、botが起動しているときに新しいcogを作ったとしても、起動した状態のままロードすることができます。早速やってみましょう。
任意のチャンネルで!jsk load cogs.commandと送って、

このように返答が返ってきたら成功です。こうならなかった場合は、手順のどこかで間違ったことになります。その後、!migakuと送るとリプライが返ってくるはずです。

他にも、任意の文字列から始まるメッセージに反応させたかったら

@commands.Cog.listener()
    async def on_message(self, message):
        if message.author == self.bot.user or message.author.bot:
            return
        if message.content.startswith('[ここに任意の文字列を挿入]'):
            await message.channel.send('[レスポンス]')

これを先ほどの@commands.commandの群の下に挿入すればできますし、

 if message.content.startswith('[ここに任意の文字列を挿入]'):

 if '[ここに任意の文字列を挿入]' in message.content:

に変えれば部分一致に、

 if message.content =='[ここに任意の文字列を挿入]':

に変えれば完全一致になります。
これらや、discord.pyの公式docsを参考にしつつ拡張していっていただければと思います。

おわり


いいなと思ったら応援しよう!