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

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

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

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

Python

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

Q&A

解決済

1回答

1385閲覧

ディスコードで見たい人のプロフィールを表示したい

poketatsu

総合スコア19

Discord

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

Python

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

0グッド

0クリップ

投稿2021/11/27 01:42

編集2023/03/21 05:28

前提・実現したいこと

discord.pyでプロフィールを表示したいのですが、
一件ずつなら表示できるのですが、
複数メンションで表示したり、
今のところp show メンションで個別に表示はできます。
通話部屋に入っている人全員のプロフィールをp listで一気に表示できるようにしたいです。

#該当のソースコード

python

1# main2.py 2 3import discord 4import discord as discord 5from discord.ext import commands 6from motor import motor_asyncio as motor 7intents=discord.Intents.all() 8# intents = discord.Intents.default() 9intents.members = True 10users: [int, int] = {} 11allowed_mentions = discord.AllowedMentions(replied_user=False) 12 13bot = commands.Bot(command_prefix="p ", intents=intents, allowed_mentions=allowed_mentions) 14dbclient = motor.AsyncIOMotorClient("データベースの情報色々") 15db = dbclient["ProfileBot"] 16profiles_collection = db.profiles 17 18 19@bot.event 20async def on_ready(): 21 print(f"Logged in as {bot.user}") 22 23 24 25 26 27 28 29 30 31 32@bot.command(name="delete", aliases=["del"]) 33async def delete_profile(ctx): 34 result = await profiles_collection.delete_one({ 35 "userid": ctx.author.id 36 }) 37 if result.deleted_count == 0: 38 return await ctx.reply("みつからなかったロト~") 39 return await ctx.reply("けしたロト~") 40 41@bot.event 42async def on_member_remove(member: discord.Member): 43 result = await profiles_collection.delete_one({ 44 "userid": member.id 45 }) 46 # メッセージを送りたいチャンネルを指定してください。 47 channel = 675304479976980501 48 if result.deleted_count == 0: 49 return await channel.send("見つかりませんでした。") 50 await channel.send("削除しました。") 51 52 53 54 55bot.run("トークン")

試したこと

@bot.command(name="list")
async def show_profile(ctx: discord.User):
profile = await profiles_collection.find({
"userid": {
"$in": ????
}
}, {
"_id": False
}).to_list(None)
embed = discord.Embed(title=f"みんなのプロフィール", description=profile["text"])
return await ctx.reply(embed=embed)
にしたらできるかと思いましたが、よくわからなくなってしまいました。
教えてくださる方いましたらご教授お願いいたします!!

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

python 3.8.10

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

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

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

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

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

pecop

2022/09/02 05:27

やってみますが質問です。 指定したボイスチャンネルのユーザー情報を取得したいということですか? 取得できなかったユーザー情報(登録されていないなど。)は表示しないのか該当なしと書くのか教えてください。
poketatsu

2022/09/04 08:23

連絡が遅れて申し訳ないです。 同じボイスチャンネルに上がっている現在のメンバーを一気に表示できるようにしたいです。 取得できなかったユーザー情報については、@AA さん 該当なしですと記載するようにしたいです。 あとはサーバーからいなくなった人の情報の削除が自分のみならできるのですが、 サーバーから消えた人の情報をすべて消すという方法がなかなかうまくいかなかったです。
guest

回答1

0

ベストアンサー

vlist チャンネルメンション で発火します。
変えたい場合は関数の中でchannelがVCチャンネル型になるようにしてください。(そうしないとチャンネルのIDが取得できません。)

(もしチャンネルIDから取得したい場合は channel = await bot.get_channel(int(channel)) をしてください。名前からとることもできますが省略。)
以下サンプルコード。

py

1@bot.command(name="vlist") 2async def show_profile_in_vc_channel(ctx: commands.Context, channel: discord.VoiceChannel = None): 3 if channel is None or not isinstance(channel, discord.VoiceChannel): 4 return await ctx.send("ボイスチャンネルのメンションをしてください。\n<#チャンネルID>") 5 6 # 指定されてボイスチャンネルのメンバーのリストが返ります。 7 vc_members = channel.members 8 9 # 登録されているすべてのユーザー情報が返ります。 10 result = profiles_collection.find() 11 _list = await result.to_list(None) 12 _match = [] 13 14 for member in vc_members: 15 for data in _list: 16 17 # もしボイスチャンネルのメンバーと登録されているユーザーIDがあれば、 18 if member.id == int(data["userid"]): 19 20 # _matchリストにメンション、表示するテキストの入ったタプルが入ります。 21 # また、Dict.get()では、第2引数でキーがなかった時のデフォルトを設定することができます。 22 _match.append((member.mention, data.get("text", "該当なし"))) 23 24 description = "\n".join(f"{m[0]}: {m[1]}" for m in _match) or "該当なし" 25 embed = discord.Embed(title="ユーザー情報", description=description) 26 await ctx.send(embed=embed)

例:
サンプル


メンバーが離れた時のアクション。

py

1@bot.event 2async def on_member_remove(member: discord.Member): 3 result = await profiles_collection.delete_one({ 4 "userid": member.id 5 }) 6 # メッセージを送りたいチャンネルを指定してください。 7 channel = ... 8 if result.deleted_count == 0: 9 return await channel.send("見つかりませんでした。") 10 await channel.send("削除しました。")

投稿2022/09/02 06:12

編集2022/09/04 09:34
pecop

総合スコア409

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

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

poketatsu

2022/09/04 21:45 編集

vlistは反映できました!ありがとうございます!!チャンネルIDの取得は以下でよろしかったでしょうか。 deleteに関しましては、メッセージがでてこなかったです。 @bot.command(name="vlist") async def show_profile_in_vc_channel(ctx: commands.Context, channel: discord.VoiceChannel = None): if channel is None or not isinstance(channel, discord.VoiceChannel): return await ctx.send("ボイスチャンネルのメンションをしてください。\n<#チャンネルID>") channel = await bot.get_channel(int(channel)) # 指定されてボイスチャンネルのメンバーのリストが返ります。 vc_members = channel.members # 登録されているすべてのユーザー情報が返ります。 result = profiles_collection.find() _list = await result.to_list(None) _match = [] for member in vc_members: for data in _list: # もしボイスチャンネルのメンバーと登録されているユーザーIDがあれば、 if member.id == int(data["userid"]): # _matchリストにメンション、表示するテキストの入ったタプルが入ります。 # また、Dict.get()では、第2引数でキーがなかった時のデフォルトを設定することができます。 _match.append((member.mention, data.get("text", "該当なし"))) description = "\n".join(f"{m[0]}: {m[1]}" for m in _match) or "該当なし" embed = discord.Embed(title="ユーザー情報", description=description) await ctx.send(embed=embed)
poketatsu

2022/09/04 21:46 編集

たびたびすみません… 全部のチャット消すのは昔やったのですが、 サーバーを抜けた時に抜けた人のチャットとp setしたときのリプライを全て消すことは可能でしょうか?
pecop

2022/09/04 23:18

> サーバーを抜けた時に抜けた人のチャットとp setしたときのリプライを全て消すことは可能でしょうか? 抜けた人が送信したメッセージ 抜けた人がsetコマンドを送信したメッセージ、またBotが反応したそのEmbed 抜けた人のメンションが含まれたEmbed どれですか?
pecop

2022/09/04 23:25

> チャンネルIDの取得は以下でよろしかったでしょうか。 bot.get_channel()は非同期関数ではないのでawaitは必要ありません 上数行 ``` @bot.command(name="vlist") async def show_profile_in_vc_channel(ctx: commands.Context, channel_id: str = None): # channel IDが無効な数値(例えばaaaaaaとか)が入った場合の処理がstr#isdigit()で判別できます。 if channel_id is None or not channel_id.isdigit(): return await ctx.send("ボイスチャンネルのIDを指定してください。") channel = bot.get_channel(int(channel_id)) # チャンネルが見つからなかったときNoneを返すので、NonetypeErrorが発生するのを防ぐ。 if channel is None: return await ctx.send("無効なチャンネルIDです。") ```
poketatsu

2022/10/01 09:44

返信がおくれて申し訳ございません。 抜けた人がsetコマンドを送信したメッセージ、またBotが反応したそのEmbedを消したいです。 本当は、ボイスチャンネルを指定ではなく、ボイスチャンネルに入室後、p vlistを打ったら、 自分が入っている、ボイスチャンネルの人たちのリストを出力したいです。
pecop

2022/10/04 04:13 編集

Embedのみを削除します。 削除するメッセージを`message` 変数に代入してください。 ```py @bot.event async def on_voice_state_update( member: discord.Member, before: discord.VoiceState, after: discord.VoiceState ): if len(before.channel.members) < len(after.channel.members): return # メンバー参加 # DBなどで保存した`set`messageのauthorが発したメッセージを取得 message: discord.Message = ... # embedのみ削除 await message.edit(content=message.content, embed=None) ``` > 抜けた人がsetコマンドを送信したメッセージ、 setコマンド, embedを送信したメッセージの送信者とチャンネルID,またそのメッセージIDをsetコマンド送信時に保存する必要があります。 そうしないとどのメッセージを削除するのかがわからないので。
poketatsu

2023/03/02 23:49

こちらの方も返信が遅れてすみません。 お忙しい中すみません。 時間が、ある時に返信してくだされば大丈夫です! p setするチャンネルは男性、女性というチャンネルに分けています。 その2つのチャンネルのうち、サーバーを抜けた人の p setの文章と、その下のリプライを消せるようにしたいです。 抜けた人のidとチャンネルIDは2つしか使わないので、 チャンネルの中を調べらればいけそうかもですね やってみないとわからないですがこちらでもやってみます。
pecop

2023/03/04 08:02 編集

> p setするチャンネルは男性、女性というチャンネルに分けています。 これはDBに登録されているんですか? Discordのユーザーからはわかりませんよ。
poketatsu

2023/03/04 08:18

現在はMongoDBというところに登録しています。 本当はテキストチャンネルのものから検索してもってくるようにした方がいい気はしますが。。。
pecop

2023/03/04 08:32

PREFIX = "p " bot = commands.Bot(command_prefix=PREFIX, intents=discord.Intents.all()) users: dict[int, tuple[int, int]] = {} @bot.event async def on_voice_state_update( member: discord.Member, before: discord.VoiceState, after: discord.VoiceState ): global users if before.channel is not None and after.channel is None: channel_id, message_id = users[member.id] if channel_id is None or message_id is None: return channel = await bot.fetch_channel(channel_id) message = await channel.fetch_message(message_id) await message.delete() @bot.event async def on_ready(): print(bot.user.id) @bot.command("set") async def _set(ctx: commands.Context, *args): global users messages = ctx.channel.history(limit=None) async for message in messages: if message.content.startswith(f"{PREFIX} set")\ and ctx.author.id in list(users.keys()): users[ctx.author.id] = (ctx.channel.id, ctx.message.id) --- これでチャンネルから出た時にp setの書かれてあるメッセージを1つ削除します
poketatsu

2023/03/04 11:28 編集

返信ありがとうございます。 こちらだとエラーがTypeError: ‘set’ object is not subscriptableと出てしまうので 以下のように変更致しました。 users: dict[int, tuple[int, int]] = {} ⇒users: [int, int] = {} 現在以下のようなエラーが出てしまい、 全ての機能が止まってしまっている状況です。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-04 20:18:35 INFO discord.client logging in using static token 2023-03-04 20:18:36 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 22d606538671de906bb546a39faa085c). Logged in as ボット名 2023-03-04 20:19:35 ERROR discord.ext.commands.bot Ignoring exception in command set Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped ret = await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 36, in set_profile result = await profiles_collection.replace_one({ RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop
poketatsu

2023/03/04 11:44

ソースコードを上記の該当のソースコードに反映致しました。 ご確認お願い致します。
pecop

2023/03/04 12:18

上でエラーが出てるみたいなのであとで確認してみます
poketatsu

2023/03/04 13:31

承知致しました。 どうぞ宜しくお願い致します。
pecop

2023/03/05 23:16 編集

チャットが流れたので再度確認がしたいです。 deleteコマンドで指定したメンバーの情報を消す ボイスチャンネルに入室後、p vlistを打ったら自分が入っている、ボイスチャンネルの人たちのリストを出力 p setするチャンネルは男性、女性という2つのテキストチャンネルのうち、サーバーを抜けた人の p setの文章と、その下のリプライ(Botが反応したEmbed)を消す ここに追加、変更はありますか?
poketatsu

2023/03/05 11:20

すみません。 deleteコマンドというよりはサーバーを抜けた瞬間にその人のsetの文章とその下のリプライを消せるようにしたいです。 デバッグして確認したところ、入力自体は受け付けていそうでした。 もし、削除もれがあった場合に、deleteコマンドでp setの文章とその下のリプライを消せたら尚良いとは思います。 あと確認なのですが、on_member_removeはサーバーに抜けた瞬間にその人のsetの文章をDB上から削除しているという認識でよろしかったでしょうか。検索で見つかないようになっているので、おそらくは消えていると思うのですが。。。
pecop

2023/03/05 23:49 編集

> deleteコマンドというよりはサーバーを抜けた瞬間にその人のsetの文章とその下のリプライを消せるようにしたいです。 送ったメッセージ(p set ○○)からその返信メッセージを取得することはできません。 なので消せるのはsetコマンドを発したメッセージですが、大量にあった場合、delete_messages()関数で削除可能ですが多少時間かかります。 メンバーがサーバーから抜ける → on_member_remove()が発火→ メンバーIDに紐づいたデータを削除→削除したまたは見つからなかった旨のメッセージ表示 です Mongodb, MAN_CHANNEL_ID, WOMAN_CHANNEL_IDを指定してください。 コード: https://gist.github.com/a37dad4b912e931599d5a60723fd064f
poketatsu

2023/03/06 23:40 編集

IDの指定を致しました。 ご修正ありがとうございます。 やはり、setやshowの方も動かないままみたいです。 privateテキストチャンネルでp vlit ボイスチャンネルIDを入力すると チャンネルが無効の分岐に入ってしまうようです。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-06 20:51:37 INFO discord.client logging in using static token 2023-03-06 20:51:38 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 1d39c0ddbecb43c4b7d963b25683f06d). Logged in as ボット名 2023-03-06 20:51:45 ERROR discord.ext.commands.bot Ignoring exception in command set Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped ret = await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 34, in set_profile result = await profiles_collection.replace_one({ RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop ちなみになのですが、以下のコードは、コマンドを打った人がボイスチャンネルに入っていない時点でp vlist ボイスチャンネルIDのコマンドを打った場合のif文の認識でよろしかったでしょうか。 # チャンネルに参加していない時 if state is None: return await ctx.send("ボイスチャンネルに参加してください。")
pecop

2023/03/06 19:09

vlistで使用するチャンネルIDは男女のテキストチャンネルです(テキストチャンネルは分かれているっぽいので)。 次に、チャンネルが無効でない時、メンバーのボイス状態を確認します。 stateがNoneの場合、メンバーはvcにいないのでreturn その後に、メンバーのいるvcとそのメンバーを取得します。 > ちなみになのですが、以下のコードは、コマンドを打った人がボイスチャンネルに入っていない時点でp vlist ボイスチャンネルIDのコマンドを打った場合のif文の認識でよろしかったでしょうか。 メッセージ主がvcにいない時にif文に入ります。 --- got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop これが気になりますねぇ。。自分の環境だとうまくいくんですが。。
poketatsu

2023/03/07 11:46 編集

If文の件承知致しました いつも動作確認は、pycharmを使っているのですが、なにか違うもので動作確認をした方がよろしいでしょうか。おすすめとかありましたら教え欲しいです。 実環境のvpsでも他のコマンド含め動作を確認できませんでした。 こちらは、コマンドを打つところが、 男性と女性のチャンネル以外で入力するから、 こちらの分岐に入るようになっていたのですね。 基本的にp set以外はプライベートテキストチャンネルで打つようにしていますので、リストはとりあえず前回のままで大丈夫です。 指定のチャンネルで入力されていない時 if ctx.channel not in (man_text, woman_text): return await ctx.send("無効なチャンネルです") ちなみにpecoさんの方では、p set やshowなどのコマンドも使えていますでしょうか?
poketatsu

2023/03/07 22:08

[2022-08-23 14:32:12] [WARNING ] discord.ext.commands.bot: Privileged message content intent is missing, commands may not work as expected.のwarning(intentに関するエラー?)が起きていたので、 intents.message_content = Trueにしましたが、以下のエラーがでてしまいました。 vpsでも同じエラーがでてしまっています。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-08 06:45:40 INFO discord.client logging in using static token 2023-03-08 06:45:42 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 6e151a8792e394466e66d890a8e0379e). Logged in as ボット#1000 2023-03-08 06:46:00 ERROR discord.ext.commands.bot Ignoring exception in command set Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped ret = await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 28, in set_profile result = await profiles_collection.replace_one({ RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop
pecop

2023/03/08 09:38

自分のコード: https://gist.github.com/6f029d574c477e720660437eb8a81bc9 ---結果--- 無効なチャンネル: https://gyazo.com/54fdacf73d921a208b54a96500b6d9e8 p set, show, vlist: https://gyazo.com/3c713bdcb40fb61016c549923e727c61 意図的なp del(メンバー脱退時のものではない): https://gyazo.com/bdd02876eaa61832e2882db21c62a903 ちなみに自分はintellijでやってます。同じjetbrainsのものなので動作はあまり変わりないと思います。
poketatsu

2023/03/08 11:50

ご返信ありがとうございます。 setは男性・女性以外のときとp setのみを入力したときの分岐まで入ることはできました。 設定が完了するところはこちらでは確認できませんでした。 私の方でも、もう少し探ってみます。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-08 20:46:15 INFO discord.client logging in using static token 2023-03-08 20:46:16 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 4029c2b50b045b1388746f9a9ae3f30f). 2023-03-08 20:47:07 ERROR discord.ext.commands.bot Ignoring exception in command set Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped ret = await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 59, in set_profile result = await profiles_collection.replace_one( RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop The above exception was the direct cause of the following exception: Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke await ctx.command.invoke(ctx) File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke await injected(*ctx.args, **ctx.kwargs) # type: ignore File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\ext\commands\core.py", line 238, in wrapped raise CommandInvokeError(exc) from exc discord.ext.commands.errors.CommandInvokeError: Command raised an exception: RuntimeError: Task <Task pending name='discord.py: on_message' coro=<Client._run_event() running at C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py:441>> got Future <Future pending cb=[_chain_future.<locals>._call_check_cancel() at C:\Users\hopef\AppData\Local\Programs\Python\Python38-32\lib\asyncio\futures.py:360]> attached to a different loop
poketatsu

2023/03/08 13:33 編集

たしかにintellijだと正常に動きますね さくらvpsとpycharmは同じ動きをしてなにが違うのかがわかりませんが。。。 検索したらこのようなのが出てきたのですが、私にはわかりませんでした。 pecoさんがいっていたエラーだと思ったので、こちらに載せておきます。 https://blog.hirokiky.org/entry/2019/01/04/183048
pecop

2023/03/08 15:21

@bot.event async def on_ready(): print(dbclient.io_loop == bot.loop) これを追加してTrueかFalseを教えてください 自分はTrueで成功しているのでFalseになる可能性もあると思いました。
poketatsu

2023/03/08 21:38

printしてみたところFalseになっていました。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-09 06:36:05 INFO discord.client logging in using static token 2023-03-09 06:36:07 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: f4d68aa6c3315703d096c420ad59a7fd). False
pecop

2023/03/08 23:09

これはasyncio モジュールの loop が異なる(attached to a different loop)ことから起きると考えられます。 自分の方ではデバッグのしようがないのでそちらにやってもらう感じになりますが・・
poketatsu

2023/03/08 23:54

そうですね。 自分の方で見るしかないと思います。
pecop

2023/03/09 02:23

on_ready()関数に asyncio.set_event_loop(bot.loop) を追記してみてください。 (またはasyncio.set_event_loop(dbclient.io_loop))
poketatsu

2023/03/09 04:26

家についたら追記してみます!
poketatsu

2023/03/09 12:47 編集

一旦コマンドはすべて使えるのを確認致しました。 vpsも無事動きました 続きになるのですが、サーバーを誰かが抜けた時に、 以下の分岐になるのはif文がなにか間違っているのでしょうが Guildではいかないのでしょうか。 サーバー全体から人が減った際に発火させたかったのですが・・・ @bot.event async def on_member_remove( member: discord.Member, before: discord.Guild, after: discord.Guild ): result = await profiles_collection.delete_one({ "userid": member.id }) global users # if member.channel is not None and after.channel is None: if len(before.members) < len(after.members): return if len(before.members) > len(after.members): channel_id, message_id = users[member.id] manchannel = await bot.fetch_channel(MAN_CHANNEL_ID) womanchannel = await bot.fetch_channel(WOMAN_CHANNEL_ID) message = await manchannel.fetch_message(message_id) message2 = await womanchannel.fetch_message(message_id) await message.delete() await message2.delete() await message.edit(content=message.content, embed=None) await message2.edit(content=message2.content, embed=None) ↓==========setコマンド==========↓ @bot.command("set") async def set_profile(ctx: commands.Context, *, profile: str = None): # man = bot.get_channel(MAN_CHANNEL_ID) # woman = bot.get_channel(WOMAN_CHANNEL_ID) # if ctx.channel.id not in (MAN_CHANNEL_ID, WOMAN_CHANNEL_ID): # return await ctx.send(f"無効なチャンネルです。\n" # f"男性: {man.mention}\n" # f"女性: {woman.mention}") if profile is None: return await ctx.send("プロフィールを書いてください。") new_data = { "userid": ctx.author.id, "text": str(profile) } result = await profiles_collection.replace_one( { "userid": ctx.author.id },new_data) if result.matched_count == 0: await profiles_collection.insert_one(new_data) global users messages = ctx.channel.history(limit=None) async for message in messages: if message.content.startswith(f"{bot.command_prefix} set") \ and ctx.author.id in list(users.keys()): users[ctx.author.id] = (ctx.channel.id, ctx.message.id) await ctx.reply("設定が完了しました。") ↓=======エラー=========↓ 023-03-09 21:31:59 ERROR discord.client Ignoring exception in on_member_remove Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py", line 441, in _run_event await coro(*args, **kwargs) TypeError: on_member_remove() missing 2 required positional arguments: 'before' and 'after' 2023-03-09 21:36:16 ERROR discord.client Ignoring exception in on_member_remove Traceback (most recent call last):
pecop

2023/03/10 02:49

@ on_member_remove() は1つの引数のみを取ります。 https://discordpy.readthedocs.io/ja/latest/api.html#discord.on_member_remove 引数メンバーはそのサーバーにいた人の情報を含みます。 引数before,afterはサーバーの変化について書こうと思っているのかもしれませんが、メンバー参加時は @ on_member_join() を使います。 https://discordpy.readthedocs.io/ja/latest/api.html#discord.on_member_join イベントに関する情報は https://discordpy.readthedocs.io/ja/latest/api.html#event-reference ここにあるので参考にしてみてください。
poketatsu

2023/03/10 04:24

ご返信ありがとうございます。 こちらの方でもやってみます。
poketatsu

2023/03/11 00:13 編集

すみません こちらでやってみたのですが、 if文でサーバーに所属しているメンバーのlengthをとりたかったのですが、 こちらではとれないのでしょうか。 @bot.event async def on_member_remove( member: discord.Member ): before: discord.Guild after: discord.Guild result = await profiles_collection.delete_one({ "userid": member.id }) # global users # guild = message.guild # if member.channel is not None and after.channel is None: if len(before.member_count) < len(after.member_count): return if len(before.member_count) > len(after.member_count): channel_id, message_id = users[member.id] manchannel = await bot.fetch_channel(MAN_CHANNEL_ID) womanchannel = await bot.fetch_channel(WOMAN_CHANNEL_ID) message = await manchannel.fetch_message(message_id) message2 = await womanchannel.fetch_message(message_id) await message.delete() await message2.delete() await message.edit(content=message.content, embed=None) await message2.edit(content=message2.content, embed=None) # メッセージを送りたいチャンネルを指定してください。 # channel = 11111111 # if result.deleted_count == 0: # return await channel.send("見つかりませんでした。") # await channel.send("削除しました。")
poketatsu

2023/03/13 04:27

ありがとうございます。 もう少し頑張ってみます!
poketatsu

2023/03/14 12:58

こんばんは~ 試しに以下のようにやってみたのですが、できなかったです channelsまでは、認識しているようなのですが。。。 その下のリプライをどのように取得すればいいか想像がつきませんでした。 async def on_member_remove( member: discord.Member ): result = await profiles_collection.delete_one({ "userid": member.id }) await member.guild.text_channels[1].delete(member.id);
pecop

2023/03/14 18:55

どのチャンネルのメッセージを取得したいのですか? setメッセージが発せられたと思われるすべてのチャンネルですか?
poketatsu

2023/03/14 22:18 編集

サーバーを抜けた時に set メッセージが発せられたであろうすべてのチャンネルからsetメッセージとすぐ下のリプライを消せるようにしたいです
poketatsu

2023/03/14 22:28 編集

テキストチャンネルが6しかない場合ですが 全てのチャンネルを回す場合はこちらであっていますでしょうか? または for num in len(member.guild.text_channels): こういった回し方はできますか? async def on_member_remove( member: discord.Member ):   result = await profiles_collection.delete_one({   "userid": member.id   })   for num in range(6):     await member.guild.text_channels[1].delete(member.id);
pecop

2023/03/15 01:00 編集

メッセージ送信元の取得方法がわかりました。以前できないといいましたができるようです。(そのメッセージが削除されていない時) https://gist.github.com/d9d8b07730030c83c26ccbfd0b98c867 参考になるかな。 import main.environmentsはこちらのデバッグのTOKEN等を入れてあり、こちら独自のものなので消してください。 ----- https://gist.github.com/peco2282/d9d8b07730030c83c26ccbfd0b98c867#file-on_member_remove-py-L25 もしメッセージを送信したい場合はここにIDを入れてください。
poketatsu

2023/03/15 12:08 編集

すみません、以下であっていました。 if message.author == member and message.content.startswith( にして分岐に入り、resolvedのところでundifinedがでてきてしまっている状態です。
poketatsu

2023/03/15 12:52

現在、以下のようなエラーが出ています。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-15 21:51:04 INFO discord.client logging in using static token 2023-03-15 21:51:06 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: 3293654ddc865571148f4429556b78d4). 2023-03-15 21:51:40 ERROR discord.client Ignoring exception in on_member_remove Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py", line 441, in _run_event await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 176, in on_member_remove resolved = message.reference.resolved AttributeError: 'NoneType' object has no attribute 'resolved'
pecop

2023/03/15 23:51

すみません。これだとすべてのメッセージがリプライにらないと条件は通りませんね、、。 https://gist.github.com/peco2282/d9d8b07730030c83c26ccbfd0b98c867#file-on_member_remove-py-L60 この部分を --- reference = message.reference if reference: >resolved = message.reference.resolved ># resolvedが存在 >if resolved: >># botの反応も消す場合 >>await resolved.delete() >>i += 1 --- 又は --- try: ># メッセージ送信元を取得 (削除されたものはNoneが返る) >resolved = message.reference.resolved # AttributeError: 'NoneType' object has no attribute 'resolved' # が出た時、tryを抜ける except AttributeError: >pass # trry文に引っかからずにresolvedが存在した時 # botの返信メッセージも削除します。 else: ># resolvedが存在 ># botの反応も消す場合 >await resolved.delete() >i += 1 --- に変更してみてください。 > はインデントです。 if2重構造が見にくいと思う場合は下がおすすめです。 注意: これを実行可能にする場合、setコマンドのすべての応答メッセージをsend()ではなくreplyにする必要があります。そうすることでメッセージの1つのつながり(Aに対するBという返信のような)としてDiscord側もとらえるので。 要は ctx.send(○○, reference=ctx.message) ctx.reply(○○) のどちらかを使うべきかと。
poketatsu

2023/03/16 10:56

現在、このようなエラーが出ていて調査中です! 2023-03-16 19:54:43 INFO discord.client logging in using static token 2023-03-16 19:54:44 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: e346c86be7b9144b77d6b11f5871b684). 2023-03-16 19:55:03 ERROR discord.client Ignoring exception in on_member_remove Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py", line 441, in _run_event await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 178, in on_member_remove if resolved: UnboundLocalError: local variable 'resolved' referenced before assignment
poketatsu

2023/03/16 11:34 編集

メッセージを消せるところまではいけました。 reference = message.referenceが Noneになってしまうため if reference:へ 入れないのかもしれません。 拡張for文も回るようになったので、 あとはここのif文が通ればうまくいきそうですね。
poketatsu

2023/03/17 22:46 編集

やはりメッセージは消してくれますが、リプライだけのこってしまいますね デバッグの結果 resolvedのところでエラーが起きてしまいます。 こちらのエラーはif文のときでも同様に起こっていました。 {NameError}name 'resolved' is not defined if文の方でもUnboundLocalErrorは発生しなくなりました。 setの方はこちらで返しています await ctx.reply("設定が完了しました。")
pecop

2023/03/18 03:51

すみませんこれだとsetコマンドのメッセージのリプライ元を削除しようとしていますね。。(存在しないのに) https://gist.github.com/551146b4ecf45b363ab8bbce9cae1442 botのメッセージを取得して、そこからリプライ元を探すようにしました。
poketatsu

2023/03/18 07:14 編集

すみません。 try文があまりよくわかってなくて、 なにか問題が発生した場合は、 exceptionに移行して、 正常処理はelseに落ちるということでよろしいでしょうか? また、ユーザーがメッセージを消したあとに退出した場合、 メッセージが削除されましたの下にあるリプライを消すには、 以下のように分岐させたかったのですが、できませんでした。 if resolved.content.startswith(f"{bot.command_prefix}set") and resolved.author.id == member.id: # botのレスポンスを削除 await message.delete() # resolvedが存在 # botの反応も消す場合 await resolved.delete() i += 1 if resolved.content.startswith(f"{bot.command_prefix}set") and resolved.author.id is None: await message.delete() i += 1
pecop

2023/03/18 07:35

try文: try ->エラー発生-> except( -> finally どんな状態でも実行) try -> 処理成功 -> else( -> finally どんな状態でも実行) まぁ詳しいのはネットにあると思います。 --- 以下長文になります。 流れとして、 脱退したギルドの全てのテキストチャンネルをfor文で回す text.history(limit=None)を使って過去のメッセージをすべて取得する 過去のメッセージのうち、自分のbotが送信したメッセージの時、(メッセージ送信者のidがbotのidと同じかどうかを確認) try: botが送信したそのメッセージにリプライ元を`resolved`変数に代入(await ctx.reply()で返信したもの) もし、メッセージに送信元があればmessage.referenceに送信元メッセージの情報(MessageReferenceクラス)が、逆に無ければNoneが入る。 情報の内容は https://discordpy.readthedocs.io/ja/latest/api.html#discord.Message.reference にあります。Optional[MessageReference]は`MessageReference`又はNoneが入っているということです。 この時、referenceからresolved属性を取る必要があるが、 Noneの時、そこにresolvedという属性(attribute)が存在しないので、`AttributeError`というエラーが発生します。 except AttributeError: Attr..が発生した場合、ここに回ります。for文の中にcontinueがあるとfor文の次の内容に回ります。(この場合次のメッセージ) (UnboundLocalError?知らん。continueに回すか。) else: resolved変数にNoneは入っていないので、変数の内容は`MessageReference`クラスになる。 その中にresolved属性が存在するので、 https://discordpy.readthedocs.io/ja/latest/api.html#discord.MessageReference.resolved その送信元のメッセージが存在すれば、`Message`クラスが、削除されていれば`DeletedReferencedMessage`クラスが入っている(resolved変数に) なのでそのメッセージが削除されていれば、DeletedRef...になり、if not isinstance(resolved, Message)に引っかかる。 残ったものがMessageクラスになる。 そのメッセージがsetコマンドが使用されていたら、if文に入る。 最終的にresolved(送信元)、message(botの反応)の2つを削除。 ---- 簡単にまとめると、 全てのチャンネルからメッセージを回し、そのメッセージがsetコマンドの返信したものであれば、両方とも削除する、という感じです。
poketatsu

2023/03/18 09:33 編集

そうだったのですね ご回答ありがとうございます。 流れはよくわかりました。 ==同じ人が同じチャンネル もしくはほかのチャンネルで p setを2回してしまった場合== 男性というチャンネルで p set a 設定が完了しましたの2つは削除成功 グループチャットというチャンネルでは自分でp setしたメッセージのみを残し リプライだけ残し、試してみたのですが、 他の人の、リプライも一緒に消してしまいました。 continueがよくなかったのでしょうか それとも単純にfinallyなのがいけなかったのでしょうか。 finally: await message.delete() continue また、 continueを無しにするとリプライのみを残したものは削除 p setとリプライの2つが存在した場合は削除してくれなくなってしまいました。 C:\Users\hopef\PycharmProjects\discordbot\venv\Scripts\python.exe C:/Users/hopef/PycharmProjects/discordbot/bot.py 2023-03-18 18:02:43 INFO discord.client logging in using static token 2023-03-18 18:02:44 INFO discord.gateway Shard ID None has connected to Gateway (Session ID: f8ce108c255bbf3e0b509b8fc2f31b7d). 2023-03-18 18:03:12 ERROR discord.client Ignoring exception in on_member_remove Traceback (most recent call last): File "C:\Users\hopef\PycharmProjects\discordbot\venv\lib\site-packages\discord\client.py", line 441, in _run_event await coro(*args, **kwargs) File "C:/Users/hopef/PycharmProjects/discordbot/bot.py", line 194, in on_member_remove if resolved.content.startswith(f"{bot.command_prefix}set") and resolved.author.id == member.id: AttributeError: 'DeletedReferencedMessage' object has no attribute 'content'
pecop

2023/03/18 10:50

ここマークダウン効かなくて書きにくいので(discord) pingpong#2842までDMいただけません?そこから最終的なものをここに書けば。。
poketatsu

2023/03/19 04:52 編集

申請送りました
poketatsu

2023/03/18 12:39

できました! elseのところにtryとexceptionを設置してAttributeErrorが発生したときにリプライを消すようにしたらできました!
poketatsu

2023/03/19 04:52 編集

すみません。 1つ質問なのですが、男性、女性のチャンネルにそれぞれ60人以上にもなってくると、メッセージを削除はしてくれますが、2、3分後に削除になってしまうのですが、仕方ないものでしょうか。 ディスコードのフレンド認証していただけると幸いです。
pecop

2023/03/19 05:00

> 男性、女性のチャンネル 2つのチャンネルからのみ削除するんですか? それ以外のチャンネルは無視する場合は少し早くなるかもしれません。
poketatsu

2023/03/19 06:59

やっぱりそういうことですよね。。。 一旦全チャンネルにしておきます。 とりあえず、1,2分放っておけばとりあえず消してくれるので、 今回は一旦ここまでにします。
pecop

2023/03/21 02:15

解決したみたいなのでお疲れ様です。
poketatsu

2023/03/21 05:26

ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問