質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.59%

Discordのチーム分けbotが正常に動かない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 1,595

score 36

前提・実現したいこと

DiscordAPIを用いて発言者が参加しているボイスチャンネルにいるメンバーを,ランダムに2組に分けて違うボイスチャンネルに移動させるプログラムをPythonで書いています.

発生している問題・エラーメッセージ

まずコマンドを受け取ったらメンバーリストを取得するのですが,(多分)2人がメンバーリストに入っていないせいで,移動させることができません.

追加:どうやら特定の人が認識されていなかったのですが、何度かテストユーザをボイスチャンネルに参加させて実行してみると、そもそもuser_IDやuser_nameという名前のリストに格納されていないことが新たな問題として浮上しました。

該当のソースコード

import discord
import random
import asyncio

client = discord.Client()

TEXT_CHANNEL_ID = テキストチャンネルID
GENERAL_VOICE_CHANNEL_ID = GENERALというボイスチャンネルID
TEAM_1_VOICE_CHANNEL_ID = TEAM1のボイスチャンネルID
TEAM_2_VOICE_CHANNEL_ID = TEAM2ボイスチャンネルID

token = "Token"

@client.event
async def on_ready():
    print('-----Logged in as------')
    print(client.user.name)
    print(client.user.id)
    print('-----------------------')


@client.event
async def on_message(message):

    team_cahnnel_text = client.get_channel(TEXT_CHANNEL_ID)

    if message.content == '!team':  #チーム分け
        if message.author.guild_permissions.administrator:

            user_name = [member.name for member in message.author.voice.channel.members]  #ボイスチャットに接続中のメンバーネームを得る
            user_ID = [member.id for member in message.author.voice.channel.members] #ボイスチャットに接続中のメンバーのIDを得る

            index = [0] * len(user_name)

            if len(index) % 2 == 0:

                tmp1_name = [""] * int(len(user_name) / 2)
                tmp2_name = [""] * int(len(user_name) / 2)
                tmp1_id = [0] * int(len(user_name) / 2)
                tmp2_id = [0] * int(len(user_name) / 2)

                for i in range(len(user_name)):
                    index[i] = i
                random.shuffle(index)

                n = int(len(index)/2) #indexの要素数/2

                index = random.sample(index,len(index))

                index_1 = index[:n]
                index_2 = index[n:]

                for i in range(len(index_1)):
                    tmp1_name[i] = user_name[index_1[i]]
                    tmp1_id[i] = user_ID[index_1[i]]

                for i in range(len(index_2)):
                    tmp2_name[i] = user_name[index_2[i]]
                    tmp2_id[i] = user_ID[index_2[i]]



#----------------------------テキストチャンネルにメンバー出力-------------------------
                t1 = ""
                t2 = ""

                for name in tmp1_name:          #チーム分け(名前)
                    t1 += name + '\n'

                for name in tmp2_name:
                    t2 += name + '\n'

                team = "```\n"  
team += "====team1====\n"  
team += t1  
team += "\n"  
team += "====team2====\n"  
team += t2  
team += "\n"  

rnd = random.randint(0,1)  

team += "====CT:T=====\n"  
if rnd == 0:  
team += "CT:team1\nT:team2"  
else:  
team += "T:team1\nCT:team2"  

team += "\n```"
                await team_cahnnel_text.send(team)

#--------------------------------------------------------------



#------------------------------移動させるメンバー---------------------------
                move_team1 = [0] * int(len(user_name)/2)
                move_team2 = [0] * int(len(user_name)/2)

                if len(user_name) % 2 != 0:                     #チーム分け配列(ID)
                    move_team1 = [0] * int(len(user_name)/2)
                    move_team2 = [0] * int(len(user_name)/2)

                for i in range(len(move_team1)):
                    move_team1[i] = tmp1_id[i]

                for i in range(len(move_team2)):
                    move_team2[i] = tmp2_id[i]            



                move_voice = client.get_channel(TEAM_1_VOICE_CHANNEL_ID)
                for tm1_member in move_team1:
                    mv_tm1 = discord.Guild.get_member(message.guild,tm1_member)
                    await mv_tm1.move_to(move_voice)
                    await asyncio.sleep(0.1)


                move_voice = client.get_channel(TEAM_2_VOICE_CHANNEL_ID)
                for tm2_member in move_team2:
                    mv_tm2 = discord.Guild.get_member(message.guild,tm2_member)
                    await mv_tm2.move_to(move_voice)
                    await asyncio.sleep(0.1)


            else:
                await team_cahnnel_text.send("奇数人なのでランダムに抽選し,1人移動させます.")
                move_voice = client.get_channel(TEAM_2_VOICE_CHANNEL_ID)
                rand_move = random.choice(user_ID)
                mv_tm2 = discord.Guild.get_member(message.guild,rand_move)
                await mv_tm2.move_to(move_voice)
                await team_cahnnel_text.send("もう一度「!team」を入力してください.")
        else:
            await team_cahnnel_text.send("あなたは管理者ではありません.")

#---------------------------------------------------------------------



    if message.content == '!random':
        user_ID = [member.id for member in message.author.voice.channel.members]
        move_voice = client.get_channel(GENERAL_VOICE_CHANNEL_ID)
        move = random.choice(user_ID)
        mv_general = discord.Guild.get_member(message.guild,move)
        await mv_general.move_to(move_voice)





    if message.content == '!delete':    #チャットを削除
        if message.author.guild_permissions.administrator:
            await message.channel.purge()
        else:
            await team_cahnnel_text.send("あなたは管理者ではありません.")


    if message.content == '!map':   #マップを選択
        if message.author.guild_permissions.administrator:
            map_list = ['A','B','C','D','E']
            pick_map = random.choice(map_list)
            await team_cahnnel_text.send(pick_map)
        else:
            await team_cahnnel_text.send("あなたは管理者ではありません.")



    if message.content == '!help':  #helpを表示
        bot_message = "Usage:\n\t!team:発言者が参加中のボイスチャンネルの中から2チームに分けます。\n\t管理者権限を持っているユーザのみ使用可能です。"
        bot_message += "\n\t!delete:発言したテキストチャンネルのチャットを削除します。"
        bot_message += "\n\t!map:マップ名をランダムに発言します。"
        bot_message += "\n"
        await team_cahnnel_text.send(bot_message)



client.run(token)

試したこと

10人が参加している状況を想定して作成していますが,8人で実行しても発生している問題が起きます.
メンバーの名前とUserIDをテキストチャンネルに出力させたところ,正しく表示されていました.

補足情報(FW/ツールのバージョンなど)

MacBook Pro (13-inch, 2017, Four Thunderbolt 3 Ports)
macOS Catalina version 10.15.7
discord.py 1.5.1
Python3.8.6

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Member Intentsをオンにしていないとメンバーを取得できません(正確にはキャッシュされていないメンバー)。
Developer Portalの特権インテントのMembersをオンにして、コードを下のように変えてください。

intents = discord.Intents.default()
intents.members = True
client = discord.Client(intents=intents)


intentsについては下を見てくれれば。
猿でもわかる!discord.pyのIntentsについて!

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/11/15 11:09

    おっしゃられた通り、Dsicord.py の仕様が変わっていたことを知りませんでした。正しく動作しました。ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.59%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る