LoginSignup
6
9

More than 1 year has passed since last update.

discord.py を使用したdiscord botの作り方を基本から応用まで

Last updated at Posted at 2023-03-10

discord.py チュートリアル

注:以下コードは古い場合があります。
discord.py 2.1.0でも動作を確認していますが、基本的にはdiscord.py 1.6.0 ver 対応のコードです。

他にも思い出したり面白い応用コードがあれば追記します。

基本操作

ログイン

1.6.0 ver

import discord

# Discord botクライアント
client = discord.Client()

# botが起動したときの処理
@client.event
async def on_ready():
    print("Botが立ち上がったよ!")

# Discord APIトークン
DISCORD_API_TOKEN = "discord developerで取得したトークンをこちらに"

# botを起動
client.run(DISCORD_API_TOKEN)

2.1.0 ver

import discord

# Discord botクライアント
client = discord.Client(intents=discord.Intents.all())

# botが起動したときの処理
@client.event
async def on_ready():
    print("Botが立ち上がったよ!")

# Discord APIトークン
DISCORD_API_TOKEN = "discord developerで取得したトークンをこちらに"

# botを起動
client.run(DISCORD_API_TOKEN)

タスク作成

import discord
from discord.ext import commands, tasks

# botが起動したときの処理
@client.event
async def on_ready():
    print("Botが立ち上がったよ!")
    loops.start()

# 10秒おきに「やあ」というだけ
@tasks.loop(seconds=10)
async def loops():
    print("やあ")

discord上で誰かがしゃべった時の処理

import discord

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    # 「おはよう」に対して「うるせえ」と返すだけ
    if message.content.startswith("おはよう"):
        await message.channel.send("うるせえ")

discord上で誰かがリアクションした時の処理

import discord
from discord.utils import get

# リアクション追加時の処理
@client.event
async def on_raw_reaction_add(payload):
    #📝のリアクションが特定のメッセージで2回以上押された場合、「📝のリアクションが2回以上押されたよ!」と言う
    if payload.emoji.name == "📝" :
        channel = client.get_channel(payload.channel_id)
        message = await channel.fetch_message(payload.message_id)
        reaction = get(message.reactions, emoji=payload.emoji.name)
        if reaction and reaction.count > 2:
            print("📝のリアクションが2回以上押されたよ!")

embed送信

import discord
import datetime

embeds=discord.Embed(title="テスト", url="https://www.google.com/",description="これはテストです", color=0x000000)
embeds.add_field(name="ぶんぶんはろー", value="ゆうちゅーぶ",inline = True)
embeds.set_footer(text=str(datetime.datetime.now().strftime('%Y.%m.%d, %H:%M:%S')))
msg = await client.get_channel("INT形式のチャンネルID").send(embed=embeds)

結果
キャプチャ.JPG

名前やIDの取得

import discord

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    print(message.author) #あああ#1111
    print(message.author.id) #12345678909887
    print(message.author.name) #あああ

実際に使用した応用編

期間中にたくさん喋った人を確認する

import discord
import datetime
from discord.utils import get
import collections

channel = client.get_channel(int("チャンネルID"))
before = await channel.fetch_message(int("このメッセージIDと以前のメッセージを取得する"))
after = await channel.fetch_message(int("このメッセージIDと以降のメッセージを取得する"))
chat_list = []
async for i in channel.history(after=after.created_at+ datetime.timedelta(seconds=-1),before=before.created_at+ datetime.timedelta(seconds=1)):
    chat_list.append(i.author.id)
chat_ranking = collections.Counter(chat_list).most_common()
for count,userdata in enumerate(chat_ranking):
    user = await server.fetch_member(int(userdata[0]))
    if count == 0:
        print(f"{user.name}さんは{userdata[1]}回発言し全体の1位です!")
    else:
        print(f"{user.name}さんは{userdata[1]}回発言しました")

画像を保存してzipファイルにしてあげなおす

import discord
import requests
import shutil
import os

def download(url, file_name):
    r = requests.get(url, stream=True)
    if r.status_code == 200:
        with open(file_name, 'wb') as f:
            f.write(r.content)

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    # !imageという呪文で開始
    if message.content.startswith('!image'):
        os.mkdir("pic")
        message = channel.fetch_message(int("メッセージID"))
        for i in message.attachments:
            # 拡張子
            ext = i.url.split(".")[-1]
            # discordimg.拡張子 というネームで画像を保存する
            download(i.url,f"./pic/discordimg.{ext}")
        
        #フォルダをフォルダをzipに変換し送信
        shutil.make_archive('./discordpic', 'zip', root_dir='./pic')
        await message.channel.send(file=discord.File("discordpic.zip")) 
        shutil.rmtree("pic")

会話を無限に継続する

import discord
import asyncio

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    if message.content.startswith('!talk'):
        await message.channel.send("ずっとオウム返ししてやるよ!")
        while True:
            try:
                # 話してるのが該当ユーザーか確認し、30秒たつと自動的にエラーを返す
                msg = await client.wait_for("message",check=lambda m: m.author == message.author, timeout=30.0)
                # 会話を抜け出す
                if msg.content == "!end":
                    await message.channel.send("もうギブアップかい!")
                    break
                else:
                    await message.channel.send(msg.content)

            except asyncio.TimeoutError:
                await message.channel.send('時間だよ!')
                break
        
        return

特別なロールの人からしか受け付けない

import discord

admin = ["admin"]
# メッセージが送信されたときの処理
@client.event
async def on_message(message):
        if message.content.startswith('!check') and list(set([z.name for z in message.author.roles])&set(admin)):
            await message.channel.send("youは管理者だね")

サーバーで登録した絵文字をリアクションとして使う

import discord
from discord.utils import get

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    if message.content.startswith('!addreact'):
        #サーバーにkaomojiという名前で登録した絵文字を使う
        react = get(message.guild.emojis, name='kaomoji')
        await message.add_reaction(react)

リアクションで反応するスライド式embedを作成

意外と説明書だったり使えるのがこれ

import discord

# メッセージが送信されたときの処理
@client.event
async def on_message(message):
    if message.content.startswith('!read'):
        #embedを事前に作成
        embed_1 =discord.Embed(title="やあ", description="こんにちは", color=0x000000)
        embed_2 =discord.Embed(title="Hi", description="Hello", color=0x000000)
        embed_3 =discord.Embed(title="你好", description="你好", color=0x000000)

        #最初にembed_1を表示
        page = "🇯🇵"
        msg = await message.channel.send(embed=embed_1)
        
        #リアクションを追加
        await msg.add_reaction("🇯🇵")
        await msg.add_reaction("🇺🇸")
        await msg.add_reaction("🇨🇳")
        
        #リアクションやユーザーが正しいかを確認
        def check(reaction, user):
                return user ==  message.author and str(reaction.emoji) in ["🇯🇵", "🇺🇸", "🇨🇳"] 

        while True:
            try:
                reaction, user = await client.wait_for("reaction_add", timeout=60, check=check)
                #違うページから押された場合は該当のembedに更新。リアクションのカウントを戻す
                if str(reaction.emoji) == "🇯🇵" and page != "🇯🇵":
                    page = "🇯🇵"
                    await msg.edit(embed=embed_1)
                    await msg.remove_reaction(reaction, user)
                elif str(reaction.emoji) == "🇺🇸" and page != "🇺🇸":
                    page = "🇺🇸"
                    await msg.edit(embed=embed_2)
                    await msg.remove_reaction(reaction, user)
                elif str(reaction.emoji) == "🇨🇳" and page != "🇨🇳":
                    page = "🇨🇳⚾"
                    await msg.edit(embed=embed_3)
                    await msg.remove_reaction(reaction, user)

            except asyncio.TimeoutError:
                #タイムアウトするとメッセージを削除
                await msg.delete()
                break

リアクションを押すことによってメッセージが変化
キャプチャ.JPG
キャプチャ1.JPG

6
9
0

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
6
9