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
Related
I'm trying to make a command that takes a channel name as input (or argument) and locks that channel but for only the students in the channel. Here's the code:
# bot.GUILD = bot.get_channel(guild_id) [In on_ready method in bot class]
#bot.command()
async def lock(ctx, channel_name):
user_dm = await bot.create_dm(ctx.author)
channels = await bot.GUILD.fetch_channels()
roles = await bot.GUILD.fetch_roles()
channels = list(filter(lambda c: c.name.lower() == channel_name.lower(), channels))
student_roles = list(filter(lambda r: r.name.endswith("students"), roles))
# print(channels, roles) [This works fine]
if channels:
for channel in channels:
for role in student_roles:
await channel.set_permissions(role, send_messages=False)
await user_dm.send(f"✅ {channel_name} has been locked!")
else:
await user_dm.send(f"❌ {channel_name} does not exist!")
I don't know why it's not sending any message to my dm. Because it's an if-else statement so at least I get a message from the bot whether positive or negative but that doesn't happen. And yes my bot has the necessary permissions. I really hope you can help me with this 😕🥺
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)
I'm trying to make an embed system that asks multiple questions and then put them together and send the embed with all the info given, but I can't figure out how to get multiple inputs in one command.
Based on what I understand from your question, you're only checking for one possible input with m.content == "hello". You can either remove it or add an in statement. Do view the revised code below.
#commands.command()
async def greet(ctx):
await ctx.send("Say hello!")
def check(m):
return m.channel == channel # only check the channel
# alternatively,
# return m.content.lower() in ["hello", "hey", "hi"] and m.channel == channel
msg = await bot.wait_for("message", check=check)
await ctx.send(f"Hello {msg.author}!")
In the case of the newly edited question, you can access the discord.Message class from the msg variable. For example, you can access the message.content. Do view the code snippet below.
#commands.command()
async def test(ctx):
def check(m):
return m.channel == ctx.channel and m.author == ctx.author
# return message if sent in current channel and author is command author
em = discord.Embed()
await ctx.send("Title:")
msg = await bot.wait_for("message",check=check)
em.title = msg.content
# in this case, you can continue to use the same check function
await ctx.send("Description:")
msg = await bot.wait_for("message",check=check)
em.description = msg.content
await ctx.send(embed=em)
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.
How to get how many messages have been sent by a user, I tried doing it myself but it didn't work out for me can anyone help me.
This is what I came up with:
#client.command(aliases =["m"])
async def messages(ctx, Discord.user=User):
counter = 0
async for message in channel.history():
if message.author == client.user:
counter += 1
await ctx.send(f'{ctx.author.mention} sent {counter} messages.')
Your user parameter is not valid. = indicates default, what you want to use are type hints which are indicated with a :. This is the correct way to pass your user parameter: user: discord.Member.
#client.command(aliases=["m"])
async def messages(ctx, user: discord.Member):
channel = ctx.message.channel
counter = 0
async for message in channel.history():
if message.author == user:
counter += 1
await ctx.send(f'{ctx.author.mention} sent {counter} messages.')