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

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

新規登録して質問してみよう
ただいま回答率
85.35%
Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

6612閲覧

Pythonでのdiscord bot作成、ユーザーリストの自動取得

退会済みユーザー

退会済みユーザー

総合スコア0

Discord

Discordは、ゲーマー向けのボイスチャットアプリです。チャット・通話がブラウザ上で利用可能で、個人専用サーバーも開設できます。通話中でも音楽を流したり、PC画面を共有できるなど多機能な点が特徴です。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

1クリップ

投稿2020/03/24 07:09

編集2020/03/24 08:02

前提・実現したいこと

C言語やJavaScriptなどをすこし理解できているくらいの人間なのですが、
discordでBOTを作りたくて初めてPythonを触り始めました。
グループ内でお昼ご飯を注文するために以下の条件で絞り込み、お知らせしたいと考えています。

①指定した時間に
②特定のチャンネル内にいる
③お昼ご飯を注文したい人で(ロールを付与しておく)
④オンラインの人から(オフラインの人は除外)
⑤ランダムで一人代表者を決める
⑥メンションを付けてお知らせメッセージを飛ばす

試したこと・発生している問題

①と⑤はできそうなのですが、②~⑤の条件をかなえるための手法をご提案いただきたいです。
調べたところ、コマンド入力をしてメッセージを受け取ったチャンネルにおいてメンバーの取得はできましたが、
時刻をトリガーとして自動で選び、お知らせしてほしいです。

該当のソースコード

Python

1from datetime import datetime 2from discord.ext import tasks 3import random 4import asyncio 5import discord 6 7client = discord.Client() 8 9BOT_TOKEN = "hogehoge" 10CHANNEL_ID = hogehogenumber 11 12 13@client.event #ログインの確認 14async def on_ready(): 15 print('Logged in as') 16 print(client.user.name) 17 print(client.user.id) 18 print('------') 19 #ループ処理実行 20 loops.start() 21 22# 60秒に一回ループ 23@tasks.loop(seconds=60) 24async def loops(): 25 # 現在の時刻 26 now = datetime.now().strftime('%H:%M') 27 print(lunchtime) 28 channel_sent = client.get_channel(CHANNEL_ID) 29 30 #お知らせの設定時刻 31 if now == '11:00': 32 m = "今日のお昼ご飯当番を選ばなきゃ!!\n`/members` と入力してね!" 33 await channel_sent.send(m) 34 35 36@client.event 37async def on_message(message): 38 39 # メンバーのリストを取得して表示 40 if message.content == '/members': 41 s = message.channel.members 42 m = "今日のお昼ご飯当番は" + s[0].mention + "さんです!!" 43 await message.channel.send(m) 44 45 46 47 48 49# Botの起動とDiscordサーバーへの接続 50client.run(BOT_TOKEN)

わからないこと

discordにおける
・channel と guild
・member と user
など、区別がついてないなど初歩的な躓きも多いので、
もし合わせてご教授いただけますと幸いです。

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

数日前にインストールしたばかりのため
・Python3.8.2
・discord.py 1.3 (rewriteのほう)
だと思います。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

2~5の条件を一つずつ解決していくと良いでしょう。

2. 特定のチャンネル内にいるメンバーの取得

on_message 内の message.channel.members と同様に、
discord.TextChannel.members を使用すると良いでしょう。(ドキュメント

loops内では channel_sent の内容が discord.TextChannel インスタンスですね。
つまり、channel_sent.members がそのメンバーのリストになります。

3. 特定のロールを付与されているメンバーの取得

discord.Role.members を使用します。(ドキュメント
なお、2.で取得したメンバーリストと重複するメンバーを抜き出すなら、一度それらを集合型に変換して、その積集合を取ると良いでしょう。

4. オンラインのメンバーの取得

既にメンバーのリストを取得しているので、その中からオンラインのメンバーを抽出します。
メンバーのステータスは discord.Member.status で取得することができます。
これは、discord.Status クラスで定義されているいずれかの値を取ります。
オンラインの場合、discord.Status.online になります。

実際の抽出方法についてですが、様々な実装方法があると思います。
内包表記を使ったり、filter() 関数を利用するとスマートです。

以下はメンバーのリストからオンラインのものを抜き出す例です(membersを抽出前のそれと定義します)

py

1onlines = [] 2for member in members: 3 if members.status == discord.Status.online: 4 onlines.append(member) 5 6onlines = [member for member in members if member.status == discord.Status.online] 7onlines = list(filter(lambda member:member.status == discord.Status.online,members))

5. ランダムで一人代表者を決める

リストから特定の要素をランダムに選択する場合、random.choice() を使用するのが良いでしょう。
random.choice はランダムに選択した要素をそのまま返します。

実装例

このように実装できるのでは、と思います。
(動作確認は行っていません、ご了承ください)

基本的には上記の内容をそのまま実装しているつもりです。
質問内容との齟齬があれば、すみません。

py

1ROLE_ID = 123456789123456789 # ここにはロールのIDを記述することを想定しています 2 3# 60秒に一回ループ 4@tasks.loop(seconds=60) 5async def loops(): 6 # 現在の時刻 7 now = datetime.now().strftime('%H:%M') 8 print(lunchtime) 9 channel_sent = client.get_channel(CHANNEL_ID) 10 lunch_role = channel_sent.guild.get_role(ROLE_ID) # ROLE_ID のロールを取得 11 12 tmp = list(set(channel_sent.members) & set(lunch_role.members)) 13 # 特定のチャンネル内にいる、お昼ご飯を注文したい人のリスト。積集合を取っています 14 15 online_members = [member for member in tmp if member.status == discord.Status.online] 16 # 先のリストから、ステータスがオンラインのメンバーのみのリストを作成。 17 18 19 #お知らせの設定時刻 20 if now == '11:00': 21 m = f"今日のお昼ご飯当番は {random.choice(online_members).mention} さんです!!" 22 await channel_sent.send(m)

わからないこと について

discord.User はDiscordのユーザーそのものを指し示すクラスです。
つまり、Discord全体から見た一個人です。

discord.Member は、あるサーバーのメンバーを指し示すクラスです。
これは、一つのサーバーから見た一個人です。

discord.User にサーバー特有の情報(持っている役職など)を付け加えたものが discord.Member 、という感じでしょうか?

投稿2020/03/28 06:47

coolwind0202

総合スコア708

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2020/05/16 04:16

ご丁寧にありがとうございます!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問