I wanted to give my bot a presence that changes after a certain amount of time. (In this case 5 minutes)
#client.event
async def on_ready():
while True:
presence = randint(1, 5)
if presence == 1:
await client.change_presence(game=discord.Game(name='with commands', type=1))
elif presence == 2:
await client.change_presence(game=discord.Game(name='you', type=3))
elif presence == 3:
await client.change_presence(game=discord.Game(name='and watching', type=2))
elif presence == 4:
await client.change_presence(game=discord.Game(name='Youtube Videos', type=3))
elif presence == 5:
await client.change_presence(game=discord.Game(name='like a boss', type=1))
time.sleep(300)
problem is that after the 300 seconds my bot goes offline on discord, while the python file is still running, and doesn't show any errors. Anyone who knows what's causing this? Thanks.
time.sleep(300) block your programm and the connection time out.
Use await asyncio.sleep(300) insead.
dont make loops like that in discord.py use the built in loop function from discord.ext import tasks, commands
can be used like this:
from discord.ext import tasks, commands
#client.event
async def on_ready():
loop.start()
#tasks.loop(seconds=0.3)
async def loop():
presence = randint(1, 5)
if presence == 1:
await client.change_presence(game=discord.Game(name='with commands', type=1))
elif presence == 2:
await client.change_presence(game=discord.Game(name='you', type=3))
elif presence == 3:
await client.change_presence(game=discord.Game(name='and watching', type=2))
elif presence == 4:
await client.change_presence(game=discord.Game(name='Youtube Videos', type=3))
elif presence == 5:
await client.change_presence(game=discord.Game(name='like a boss', type=1))
Related
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)
First time posting here, but I just couldn't find what I'm looking for or wrap my head around it.
As of now, I have this:
#client.event
async def on_message(message):
if message.author == client.user:
return
if message.content == '!generate':
await message.channel.send(f"{message.author.mention}\n"
f"Sample question: (**Important**: Type a \"!\" in front):\n```"
"> A\n> B\n> C\n> D```")
def check(m):
return m.content == '!A' and m.channel == message.channel
msg = await client.wait_for('message', check=check)
await message.channel.send('Correct!'.format(msg))
So if the user inputs "!generate!", they get a question and a list of available answers. Now the bot already successfully waits for an answer, but only if it's A ("!A") does it actually respond further.
How can I change this so it can be any answer from the list, in this case A, B, C or D?
I already tried this:
def check(m):
sample_list = ['!A', '!B', '!C', '!D']
return m.content == f'{sample_list[0:3]}' and m.channel == message.channel
But that didn't work. To be fair, I'm very new to python and have barely any clue of what I'm doing, so I might be making some stupidly obvious mistake here.
But anyway, I hope this gives a good enough picture of what I'm trying to achieve. I appreciate any help! Thank you!
I think this is what you're looking for :
#bot.command()
async def generate(ctx):
options = ["a", "b", "c", "d"]
already_sent_res = None # Safe to remove, used for demo
await ctx.send(
f"{ctx.author.mention}\n"
f'Sample question: (**Important**: Type a "!" in front):\n```'
"> A\n> B\n> C\n> D```"
)
def check(m):
return (
m.content.startswith("!")
and m.content.lower()[1:] in options
and m.channel.id == ctx.channel.id
)
while True:
msg = await bot.wait_for("message", check=check)
# msg.content now contains the option. You may now proceed to code here
# The below code from here are used for demonstration and can be safely removed
if already_sent_res is None:
sent_message = await ctx.send(
f"**{str(msg.author.name)}** has chosen option **{str(msg.content).upper()[1:]}**"
)
already_sent_res = not None
else:
await sent_message.edit(
f"**{str(msg.author.name)}** has chosen option **{str(msg.content).upper()[1:]}**"
)
Here I used command handling with bot.command() instead of listening under on_message it is fine, you can use any which you are comfortable with.
The above code will result in the following :
Remember that the bot will keep on listening for message event in the channel so be sure to have a timeout or an abort command.
Here's the full code I used incase you need it :
import discord
import os
from discord.ext import commands
bot = commands.Bot(command_prefix="!", case_insensitive=True)
#bot.event
async def on_ready():
print(f"Sucessfully logged in as {bot.user}")
#bot.command()
async def generate(ctx):
options = ["a", "b", "c", "d"]
already_sent_res = None # Safe to remove, used for demo
await ctx.send(
f"{ctx.author.mention}\n"
f'Sample question: (**Important**: Type a "!" in front):\n```'
"> A\n> B\n> C\n> D```"
)
def check(m):
return (
m.content.startswith("!")
and m.content.lower()[1:] in options
and m.channel.id == ctx.channel.id
)
while True:
msg = await bot.wait_for("message", check=check)
# msg.content now contains the option. You may now proceed to code here
# The below code from here are used for demonstration and can be safely removed
if already_sent_res is None:
sent_message = await ctx.send(
f"**{str(msg.author.name)}** has chosen option **{str(msg.content).upper()[1:]}**"
)
already_sent_res = not None
else:
await sent_message.edit(
f"**{str(msg.author.name)}** has chosen option **{str(msg.content).upper()[1:]}**"
)
bot.run(os.getenv("DISCORD_TOKEN"))
I wanted to create a clear command where if example .clear #user#0000 100 it will clear the last 100 messages #user#0000 sent. Here is my code:
#commands.command()
#commands.has_permissions(manage_messages=True)
async def clear(self, ctx, amount=1):
await ctx.channel.purge(limit=amount + 1)
#clear.error
async def clear_error(self, ctx, error):
if isinstance(error, commands.MissingPermissions):
await ctx.send('Sorry, you are missing the ``MANAGE_MESSAGES`` permission to use this command.')
This code i provided only deletes depeneding how many messages will be deleted in a channel. I want to make a code where the bot will delete messages from a specific user. If this is possible, please let me know. I will use the code as future reference. Much appreciated.
You can use check kwarg to purge messages from specific user:
from typing import Optional
#commands.command()
#commands.has_permissions(manage_messages=True)
async def clear(self, ctx, member: Optional[discord.Member], amount: int = 1):
def _check(message):
if member is None:
return True
else:
if message.author != member:
return False
_check.count += 1
return _check.count <= amount
_check.count = 0
await ctx.channel.purge(limit=amount + 1 if member is None else 1000, check=_check)
Alright so guys i need some help. Basically i am making an discord bot. I'm having problems with clear(purge) command. So this is my code so far:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount : int):
if amount == None:
await ctx.channel.purge(limit=1000000)
else:
await ctx.channel.purge(limit=amount)
my problem here is this if amount == None .
Please help me!
Im getting an error that i have missing requied argument...
That's because you're not giving amount the default value None. This is how you should define the function:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount=None): # Set default value as None
if amount == None:
await ctx.channel.purge(limit=1000000)
else:
try:
int(amount)
except: # Error handler
await ctx.send('Please enter a valid integer as amount.')
else:
await ctx.channel.purge(limit=amount)
This one is working for me
#client.command()
#has_permissions(manage_messages = True)
async def clear(ctx , amount=5):
await ctx.channel.purge(limit=amount + 1)
I got it from a youtuber channel, you can put the number of the messages u want to clear after the clear command, EX:
-clear 10
Try this:
#client.command(aliases = ['purge', 'delete'])
#commands.has_permissions(manage_messages = True)
async def clear(ctx, amount: int = 1000000):
await ctx.channel.purge(limit = amount)
This should work, as I have a clear command that looks almost exactly like this. The amount param is being converted to an int and if the client doesn't give parameters, the amount will be set at 1000000.
This is the one I'm using atm.
#bot.command(name='clear', help='this command will clear msgs')
async def clear(ctx, amount = 50): # Change amount
if ctx.message.author.id == (YOUR USER ID HERE):
await ctx.channel.purge(limit=amount)
else:
await ctx.channel.send(f"{ctx.author.mention} you are not allowed")
I've just added an 'if' statement for being the only one who can use that command. You can also allow an specific role.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='>')
#client.event
async def on_ready():
print("Log : "+str(client.user))
#client.command()
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount: int):
await ctx.channel.purge(limit=amount+1)
await ctx.message.delete()
client.run("token")
you can do this:
#client.command(aliases= ['purge','delete'])
#commands.has_permissions(manage_messages=True)
async def clear(ctx, amount :int = -1):
if amount == -1:
await ctx.channel.purge(limit=1000000)
else:
await ctx.channel.purge(limit=amount)
I think it should work, if the client doesn't give parameters, the amount will be set at "-1"
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