How to index into the channel.members list and take out the name? Closed - discord

So I'm trying to get the names of all the people in a voice channel, but the bot returns a list like so:
[<Member id=704069756717629472 name='Eedward' discriminator='8402' bot=False nick=None guild=<Guild id=807690875802878003 name='lfg testing' shard_id=None chunked=True member_count=3>>]
Is there any way I can take that "name" part out of the list? Or is there a better way to do something like this? This is my code:
#client.command()
async def lfg(ctx, game, *,extra=None):
if not ctx.message.author.voice:
await ctx.send(f"{ctx.author.name}, you need to connect to a voice channel first to use this command.")
return
else:
channel = ctx.message.author.voice.channel
link = await channel.create_invite(max_age = 300)
members = len(ctx.message.author.voice.channel.members)
members1 = ctx.message.author.voice.channel.members
max_ = channel.user_limit
if max_ == 0:
max_ = 'None'
if max_ == 'None':
p = f'{members}, No Limit'
else:
p = f"{members} out of {max_}"
em = Embed(color=discord.Color.gold())
em.add_field(name='LFG Request', value=f"**{ctx.author.mention} is looking for a group in voice channel `#{channel}`**:\n\n**Game: {game}**\n\n**Extra Info:** {extra}\n\n**Connected Users:**{(members1)} ({p})\n\n**VC Invite: [Click here to join]({link})**")
em.set_footer(text=f'Type !lfg (message) to create this embed | This LFG request was made by {ctx.author.name}')
await ctx.send(embed=em)
Sorry if it's a bit hard to read, thanks in advance! :D (Btw I'm trying to display the names of the users in the vc in the "Connected Users" section of the embed)
Edit: I figured it out, for those who want the code, here it is:
members = len(ctx.message.author.voice.channel.members)
count = 0
members1 = ""
for _ in range(int(members)):
members1 += f"{ctx.message.author.voice.channel.members[count].mention}"
count += 1

try adding .name to the member. This should get the name from the member.

Related

Discord.py user command counter

I am currently trying to implement a counter to show how many times a user has used a command like "*kiss #randomuser", and then it would show in the embed footer or under title "user has kissed someone {number} of times"
I have tried the solution found here How do I get a counter to work within a discord.py command function?
but nothing I have tried has worked, I apologize but im not every good with this
bot.counter = 0
#bot.command()
##commands.cooldown(1,10,commands.BucketType.user)
async def Random(ctx, member:discord.Member = None):
bot.counter += 1
if member == ctx.author:
em = discord.Embed(title=f'{ctx.author.display_name}, You can not perform this action on yourself ', color = random.randint(0, 16777215) )
await ctx.reply(embed=em)
else:
e = discord.Embed(title=f'{ctx.author.display_name} is doing something random to {member.name}', color = random.randint(0, 16777215))
content = []
link = random.choice(content)
e.set_image(url=f'{link}')
e.set_footer(text=f"This user has used this command {bot.counter}")
await ctx.reply(embed=e)
```

How do I get a list of all members in a discord server, preferably those who aren't bot

I'm attempting checks if a username is in a valid username in the server. The check is done by the following code
intents = discord.Intents.all()
bot = commands.Bot(command_prefix='!logan',
intents=intents,
helpCommand=helpCommand)
Users = [# Need help getting users]
async def Fight(ctx, User):
if ctx.author.name != User:
if User in Users:
open_file = open(str(ctx.author.name), "w")
open_file.write(User + "\n300\nTurn")
open_file.close()
open_file = open(User, "w")
open_file.write(str(ctx.author.name) + "\n300\nNot")
open_file.close()
await ctx.author.send("You are now fighting " + User)
#await ctx.User.send("You are now fighting " + ctx.author.name)
else:
await ctx.send("User is not in this server")
else:
await ctx.send("You Cannot Fight Yourself")
I've tried googling, but I haven't found a valid answer
There are other ways to get your guild name, but here's a possible method to get it and get the member list from it.
In member (and user so), there is the ".bot" that is a boolean, 0 if not a bot.
listMembers = []
#bot.command(name="init")
async def FuncInit (ctx) :
global listMembers
guilde = ctx.message.guild
for member in guilde.members :
if not member.bot :
listMembers.append(member.name)

How can I change the order of correct answers or accept more than just one global answer?

I am still working on my question bot and now I want you to be able to give multiple correct_answers. Here is what I had in mind: Each user can execute a command 3x to give an answer. But to each question I want a different solution to be considered correct, so not always just A, as an example. How can I make the bot consider the following answers as correct in the order: A, B, A or A, B, C etc.
At the moment I have the following code:
correct_answers = "A" #Only possibility
#commands.command()
async def answer(self, ctx, answer):
self.answer.enabled = False
global correct_answers
if correct_answers != answer:
await ctx.author.send(f "You guessed {answer} which is **wrong**. Good luck next time!")
await ctx.message.delete()
return
[shortened]
await ctx.message.delete()
await ctx.author.send(f'The right answer was **{correct_answers}**, you guessed **correctly**!')
await asyncio.sleep(10)
self.answer.enabled = True
My embed code where I want to decide after which edit which answer is correct:
#commands.command()
async def trivia_c(self, ctx):
e = discord.Embed(color=discord.Color.gold())
e.title = "New question, new luck."
e.description = "**When was Steve Jobs born?**"
e.add_field(name="1️⃣", value="02/24/1955", inline=False)
e.add_field(name="2️⃣", value="03/24/1955", inline=False)
e.add_field(name="3️⃣", value="02/24/1965", inline=False)
e.set_footer(text="You have x-x to answer this question.", icon_url=self.bot.user.avatar_url)
e.timestamp = datetime.datetime.utcnow()
question = await ctx.send(embed=e)
await asyncio.sleep(10)
e2 = discord.Embed(color=discord.Color.gold())
e2.title = "New question, new luck."
e2.description = "Test1"
e2.add_field(name="1️⃣", value="02/24/1955")
e2.add_field(name="2️⃣", value="03/24/1955")
e2.add_field(name="3️⃣", value="02/24/1965")
e2.set_footer(text="You have x-x to answer this question.")
e2.timestamp = datetime.datetime.utcnow()
await question.edit(embed=e2)
await asyncio.sleep(10)
e3 = discord.Embed(color=discord.Color.gold())
e3.title = "Test2"
e3.description = "When was Steve Jobs born?"
e3.add_field(name="1️⃣", value="02/24/1955")
e3.add_field(name="2️⃣", value="03/24/1955")
e3.add_field(name="3️⃣", value="02/24/1965")
e3.set_footer(text="You have x-x to answer this question.")
e3.timestamp = datetime.datetime.utcnow()
await question.edit(embed=e3)
await asyncio.sleep(10)
My approach would have been to do it via an enumeration, i.e.
first, second, third = "A", "B", "A" or correct_answers = ["A", "B", "B"] but in both cases it doesn't work. Would I have to go through a list and how exactly do I do that? I also read that you can get the results via an index, but then it fails for me.
In summary:
The first execution of the command should recognize A as correct, then the second time for example B, and the third time for example C.
Using the embed code provided I have used wait_for like my previous example. Still reduces the need for a second command. If you wanted you would have to implement a storage system. I have done the first command as an example. If you wanted to set a limit you can use timeout=seconds in the wait_or
#commands.command()
async def trivia_c(self, ctx):
def check(m):
return m.author == ctx.author and m.channel == ctx.message.channel
e = discord.Embed(color=discord.Color.gold())
e.title = "New question, new luck."
e.description = "**When was Steve Jobs born?**"
e.add_field(name="1️⃣", value="02/24/1955", inline=False)
e.add_field(name="2️⃣", value="03/24/1955", inline=False)
e.add_field(name="3️⃣", value="02/24/1965", inline=False)
e.set_footer(text="You have x-x to answer this question.", icon_url=self.bot.user.avatar_url)
e.timestamp = datetime.datetime.utcnow()
question = await ctx.send(embed=e)
try:
reply = await client.wait_for('message', check=check)
if reply.content == "a":
print("Good")
else:
print("bad")
await reply.delete()
except:
return await question.edit(content="You took too long, so the question is gone.")
await asyncio.sleep(10)
# Next
import random
#commands.command()
async def question(self, ctx):
def check(m):
return m.author == ctx.author and m.channel == ctx.message.channel
question_one = "How many lives do cat's have?"
answers_one = {"9":"a","1":"b","10":"c"}
questions = {question_one:{"9":answers_one}, "Pineapple on pizza?":{"yes":{"yes":"a",
"no":"b"}}}
# get a question
question = random.choice(list(questions.keys()))
data = questions.get(question)
correct_answer = list(data.keys())[0]
answers = list(list(data.values())[0].items())
question_msg = ""
answers_msg = ""
numbers_list = []
answers_list = []
for answer, number in answers:
numbers_list.append(number)
answers_list.append(answer)
while numbers_list != []:
num = random.choice(numbers_list)
ans = random.choice(answers_list)
answers_msg += f"{num}. {ans}\n"
answers_list.remove(ans)
numbers_list.remove(num)
question_msg = f"{question}\nPlease pick one of the following:\n{answers_msg}"
question_sent = await ctx.send(question_msg)
try:
reply = await client.wait_for('message', check=check)
except:
return await question_sent.edit(content="You took too long, so the question is gone.")
await reply.delete()
if reply.content == correct_answer:
await ctx.send("Well done!")
else:
await ctx.send("Nope. How can you get confused!")
This uses wait_for which means you can share the data and not need multiple commands.
This supports the use of multiple questions.
During testing I got:
How many lives do cat's have?
Please pick one of the following:
c. 1
b. 10
a. 9
How many lives do cat's have?
Please pick one of the following:
a. 10
b. 9
c. 1

How would i get live updates when a user joins and leaves a discord voice channel

Is there a way too do a callback or a background task to see when a user joins and leaves a voicechannel? Currently when I cmd the bot I only am able to see the users that are currently in the voicechannel only. Sorry if it might not make sense.
import asyncio
import config
client = discord.Client()
#client.event
async def on_ready():
print("We have logged in as {0.user}".format(client))
#Voice channel
lobby_voicechannel = client.get_channel(708339994871463986)
#Text channel
txt_channel = client.get_channel(702908501533655203)
team_one = []
team_two = []
member_id = []
lobby_queue = lobby_voicechannel.members
for x in lobby_queue:
#change mention to name or nick for variations
member_id.append(x.mention)
player_num = len(member_id)
joined_user = str(member_id)
#check how many players in total for queue
if player_num == 5:
user_convert = tuple(member_id)
embed = discord.Embed(
title="**{}/10** players joined `{}`".format(player_num, lobby_voicechannel),
description="\n".join(user_convert),
color=0x00f2ff)
await txt_channel.send(delete_after=None, embed=embed)
else:
if player_num == 0:
embed = discord.Embed(
title="**{}/10** players joined `{}`".format(player_num, lobby_voicechannel),
description=f"***```No players in {lobby_voicechannel}```***",
color=0x00f2ff
)
await txt_channel.send(delete_after=None, embed=embed)
client.run(config.Token)```
You can use the on_voice_state_update event. This event gets triggered whenever a member joins/leaves or when a members state changes in a voice channel. For more info see link.
However you still need to check whether or not the member left/joined. This can be done through the before and after VoiceState objects received from the event: on_voice_state_update(member, before, after):.
Example:
#commands.Cog.listener()
async def on_voice_state_update(member, before, after):
if before.channel == None and after.channel != None:
state = 'joined'
else if before.channel != None and after.channel == None:
state = 'left'
else:
state = 'unchanged'
# Continue with some code

Using Discord.py rewrite to delete messages

As the title states, I'm trying to delete messages using my !purge command. I have this down already:
#bot.command()
#commands.has_permissions(manage_messages=True)
async def purge(ctx):
await delete_messages(ctx, member)
await ctx.send("Deleted messages")
It's saying that delete_messages is not defined. Please help me!
So we are in year 2019. I'll help you with your code.
delete_messages is a method of a TextChannel object.
In your line await delete_messages(ctx, member), add ctx.message.channel. just before delete_messages.
Your line would then go like this:
await ctx.message.channel.delete_messages(ctx, member)
Hope that clears things up.
If it did, don't hesitate to 'accept' the answer by clicking the check mark.
This will delete only up to 99 messages (+ the purge command) at a time and the messages must be under 14 days old.
#bot.command(pass_context=True, name='purge', aliases=['purgemessages'], no_pm=True)
async def purge(ctx, number):
number = int(number)
if number > 99 or number < 1:
await ctx.send("I can only delete messages within a range of 1 - 99", delete_after=10)
else:
author = ctx.message.author
authorID = author.id
mgs = []
number = int(number)
channel = ctx.message.channel
async for x in bot.logs_from((channel), limit = int(number+1)):
mgs.append(x)
await delete_messages(mgs)
await ctx.send('Success!', delete_after=4)

Resources