Discord bot is incorrect if several players are trying to get a part at the same time.
-
I'm writing discord bot (discord.py) and I need a function that will add a role to the player immediately (the user can choose the role himself) or in passing the test (which is sent to the LC participant). That's what I wrote:
@bot.command() async def select_faculty(ctx): """Функция select_faculty позволяет выбрать сразу или пройти тест для определения факультета. """ member = ctx.message.author channel_roles = [ "gryffindor - ученик", "slytherin - ученик", "hufflepuff - ученик", "ravenclaw - ученик", "gryffindor - наставник", "slytherin - наставник", "hufflepuff - наставник", "ravenclaw - наставник", "ждущие зачисления", "ученик", "наставник", ] start_emb = discord.Embed(title="Приветствую тебя, маг!", colour=discord.Colour.orange(), description="Выбери вариант распределения:") who_emb = discord.Embed(title="Для начала выбери кто ты:", colour=discord.Colour.purple()) select_fac_emb = discord.Embed(title="Выбери факультет:", colour=discord.Colour.red(), description="Выбери понравившийся тебе факультет.") send_fac_menu = ctx.send(embed=select_fac_emb, components=[ [Button(style=ButtonStyle.green, label="Гриффиндор", emoji=""), Button(style=ButtonStyle.blue, label="Слизерин", emoji="")], [Button(style=ButtonStyle.red, label="Когтевран", emoji=""), Button(style=ButtonStyle.gray, label="Пуффендуй", emoji="")], [Button(style=ButtonStyle.blue, label="Пожиратели смерти", emoji="")] ]) answer = await ctx.channel.send(embed=start_emb, components=[[ Button(style=ButtonStyle.green, label="Выбрать сразу"), Button(style=ButtonStyle.blue, label="Пройти тест")]]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Выбрать сразу": for role in [role.name for role in ctx.author.roles]: if role != "@everyone" and role.lower() in channel_roles: user_role = discord.utils.get(ctx.message.author.roles, name=role) await member.remove_roles(user_role) await ctx.message.delete() await answer.delete() answer = await ctx.send(embed=who_emb, components=[ [Button(style=ButtonStyle.green, label="Ученик с жаждой знаний", emoji="")], [Button(style=ButtonStyle.blue, label="Мудрый наставник", emoji="")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Ученик с жаждой знаний": await send_fac_menu response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Гриффиндор": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["gryff"])) elif response.component.label == "Слизерин": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["slyth"])) elif response.component.label == "Когтевран": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["raven"])) elif response.component.label == "Пуффендуй": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["huff"])) elif response.component.label == "Пожиратели смерти": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["death"])) await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["apprentice"]["apprentice"])) await answer.delete() elif response.component.label == "Мудрый наставник": await send_fac_menu response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Гриффиндор": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["gryff"])) elif response.component.label == "Слизерин": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["slyth"])) elif response.component.label == "Когтевран": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["raven"])) elif response.component.label == "Пуффендуй": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["huff"])) elif response.component.label == "Пожиратели смерти": await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["death"])) await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles["mentor"]["mentor"])) await answer.delete() elif response.component.label == "Пройти тест": faculties = { "gryff": 0, "slyth": 0, "huff": 0, "raven": 0 } who = "" faculty = "" question1_emb = discord.Embed(title="Давай пройдём небольшой тест.", colour=discord.Colour.green(), description="Первый вопрос - какой ты?:") question2_emb = discord.Embed(title="Второй вопрос:", colour=discord.Colour.orange(), description="Какое животное тебе нравится больше всего?") question3_emb = discord.Embed(title="Третий вопрос:", colour=discord.Colour.purple(), description="Какая стихия нравится тебе больше всего?") question4_emb = discord.Embed(title="Четвёртый вопрос:", colour=discord.Colour.blue(), description="Какие комбинации цветов нравятся тебе больше всего?") question5_emb = discord.Embed(title="Пятый вопрос:", colour=discord.Colour.red(), description="Какое привидение из Хогвартса нравится тебе больше всего?") await ctx.message.delete() await answer.delete() answer = await member.send(embed=who_emb, components=[ [Button(style=ButtonStyle.green, label="Ученик с жаждой знаний", emoji="")], [Button(style=ButtonStyle.blue, label="Мудрый наставник", emoji="")], [Button(style=ButtonStyle.red, label="Министр магии", emoji="⚖️")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Ученик с жаждой знаний": who = "apprentice" elif response.component.label == "Мудрый наставник": who = "mentor" await answer.delete() answer = await member.send(embed=question1_emb, components=[ [Button(style=ButtonStyle.red, label="Храбрый"), Button(style=ButtonStyle.green, label="Хитрый")], [Button(style=ButtonStyle.gray, label="Упорный"), Button(style=ButtonStyle.blue, label="Мудрый")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Храбрый": faculties["gryff"] += 1 elif response.component.label == "Хитрый": faculties["slyth"] += 1 elif response.component.label == "Упорный": faculties["huff"] += 1 elif response.component.label == "Мудрый": faculties["raven"] += 1 await answer.delete() answer = await member.send(embed=question2_emb, components=[ [Button(style=ButtonStyle.red, label="Лев"), Button(style=ButtonStyle.green, label="Змея"), Button(style=ButtonStyle.gray, label="Барсук"), Button(style=ButtonStyle.blue, label="Орёл")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Лев": faculties["gryff"] += 1 elif response.component.label == "Змея": faculties["slyth"] += 1 elif response.component.label == "Барсук": faculties["huff"] += 1 elif response.component.label == "Орёл": faculties["raven"] += 1 await answer.delete() answer = await member.send(embed=question3_emb, components=[ [Button(style=ButtonStyle.red, label="Огонь"), Button(style=ButtonStyle.green, label="Вода"), Button(style=ButtonStyle.gray, label="Земля"), Button(style=ButtonStyle.blue, label="Воздух")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Огонь": faculties["gryff"] += 1 elif response.component.label == "Вода": faculties["slyth"] += 1 elif response.component.label == "Земля": faculties["huff"] += 1 elif response.component.label == "Воздух": faculties["raven"] += 1 await answer.delete() answer = await member.send(embed=question4_emb, components=[ [Button(style=ButtonStyle.red, label="Красный и жёлтый"), Button(style=ButtonStyle.green, label="Зелёный и серебрянный")], [Button(style=ButtonStyle.gray, label="Жёлтый и чёрный"), Button(style=ButtonStyle.blue, label="Синий и бронзовый")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Красный и жёлтый": faculties["gryff"] += 1 elif response.component.label == "Зелёный и серебрянный": faculties["slyth"] += 1 elif response.component.label == "Жёлтый и чёрный": faculties["huff"] += 1 elif response.component.label == "Синий и бронзовый": faculties["raven"] += 1 await answer.delete() answer = await member.send(embed=question5_emb, components=[ [Button(style=ButtonStyle.red, label="Почти Безголовый Ник"), Button(style=ButtonStyle.green, label="Кровавый Барон")], [Button(style=ButtonStyle.gray, label="Толстый Монах"), Button(style=ButtonStyle.blue, label="Серая Дама")] ]) response = await bot.wait_for("button_click") await response.edit_origin() if response.component.label == "Почти Безголовый Ник": faculties["gryff"] += 1 elif response.component.label == "Кровавый Барон": faculties["slyth"] += 1 elif response.component.label == "Толстый Монах": faculties["huff"] += 1 elif response.component.label == "Серая Дама": faculties["raven"] += 1 await answer.delete() for k, v in faculties.items(): if v == max(faculties.values()): faculty = k for role in [role.name for role in ctx.author.roles]: if role != "@everyone" and role.lower() in channel_roles: user_role = discord.utils.get(ctx.message.author.roles, name=role) await member.remove_roles(user_role) emb = discord.Embed(title=f"Вы зачислены в {faculty}!", colour=discord.Colour.green()) await member.send(embed=emb) await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles[who][faculty])) await member.add_roles(discord.utils.get(ctx.channel.guild.roles, id=roles[who][who]))
But there's one problem - if the role is chosen by a few players, the bot starts to work in an inadequate way: the test uses the answers of other users to add a role to you when the participant presses the button, he gets a mistake of interaction, and the bot makes this mistake:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback Ignoring exception in command select_faculty: Traceback (most recent call last): File "C:\Users\belog\hat_dispenser\venv\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped ret = await coro(*args, **kwargs) File "C:\Users\belog\hat_dispenser\main.py", line 226, in select_faculty await response.edit_origin() File "C:\Users\belog\hat_dispenser\venv\lib\site-packages\discord_components\interaction.py", line 244, in edit_origin await self.defer(edit_origin=True) File "C:\Users\belog\hat_dispenser\venv\lib\site-packages\discord_components\interaction.py", line 93, in defer await self.respond(type=5 if not edit_origin else 6, ephemeral=ephemeral) File "C:\Users\belog\hat_dispenser\venv\lib\site-packages\discord_components\interaction.py", line 185, in respond raise NotFound( discord.errors.NotFound: 404 Not Found (error code: 0): Interaction is unknown (you have already responded to the interaction or responding took too long)
How can a few users choose a role immediately?
-
In this case, you have a mistake.
response = await bot.wait_for("button_click")
♪ You're just waiting for a push. any buttons, even other users. Add the test condition.def check(inter): return inter.message.id == message.id and inter.user == ctx.author
await bot.wait_for(event='button_click', check=check)
P.S. Previously, I answered yours. https://ru.stackoverflow.com/questions/1346060/%D0%9E%D1%88%D0%B8%D0%B1%D0%BA%D0%B0-runtimewarning-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5-%D0%B2%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%BA%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D1%8B-%D0%B2-discord-%D0%B1%D0%BE%D1%82%D0%B5 (sighs) https://ru.stackoverflow.com/a/1346550/436670 ) What didn't satisfy you in my past implementation?