How do I remove mark down in discord.py?
I was making an eval command but I realized that sending it with markdown eg. '```py print("example code")```', breaks it.
I want to make it easier for me and the other admin/mod to use it for debugging purposes in my bot.
#client.command()
async def eval(ctx, *, code):
out, err = io.StringIO(), io.StringIO()
sys.stdout = out
sys.stderr = err
await ctx.channel.trigger_typing()
await aexec(code)
results = out.getvalue()
errors = err.getvalue()
await ctx.send(embed = discord.Embed(title = "Eval", description=f"Output Is \n```bash\n{results}```"))
await ctx.send(embed = discord.Embed(title = "Code", description=f"Input Is \n```py\n{code}```"))
the above code is what I've tried so far..
I've been playing with your code for the past hours, I wanted to figured it out :P
This is the only way i could access the code when there was markdown in the command input.
#client.command()
async def eval(ctx, *, code):
raw = f'{ctx.message.content}'[12:-3] # Get rid of markdown + py and last 3 ```
#Might want to add if statements in case the input doesn't include py / something else.
print (raw) # Testing purpose
out, err = io.StringIO(), io.StringIO()
sys.stdout = out
sys.stderr = err
await ctx.channel.trigger_typing()
exec(raw) # no need for await
results = out.getvalue()
errors = err.getvalue()
await ctx.send(embed = discord.Embed(title = "Eval", description=f"Output Is \n```bash\n{results}```"))
await ctx.send(embed = discord.Embed(title = "Code", description=f"Input Is \n```py\n{raw}```"))
await ctx.send(embed = discord.Embed(title = "Errors", description=f"Errors are \n```py\n{errors}```")) #Added this output to see errors
Related
When I want to append something to a file (with the append mode), it just erases everything before writing what I would like to append.
I have an on_voice_state_update event, when triggered, it checks if the user joined a specific channel. If yes: it creates a voice channel with some permissions for the user who created the voice channel. It is also supposed to append to a file called member_channel.txt this: {member.id}:{the_member's_voice_channel.id} but instead of adding this at the end of the file, it first erases everything and then add what I want to add.
Here are the codes:
#bot.event
async def on_voice_state_update(member, before, after):
if after.channel is not None and after.channel.id == 1059553884286230608:
guild = bot.get_guild(966749409314504774)
everyone_role = discord.utils.get(guild.roles, id = 966749409314504774)
community_role = discord.utils.get(guild.roles, id = 1006304076331483256)
muted_role = discord.utils.get(guild.roles, id = 1059109986258653244)
global member_channel
member_channel = await guild.create_voice_channel(name = f"Vocal de {member.name}")
await member_channel.edit(category = discord.utils.get(get_guild().channels, id = 1057730051321372692))
await member_channel.set_permissions(member, connect = True, manage_channels = True, manage_permissions = True, priority_speaker = True, move_members = True)
await member_channel.set_permissions(everyone_role, view_channel = False)
await member_channel.set_permissions(community_role, view_channel = True)
await member_channel.set_permissions(muted_role, speak = False)
await member.move_to(member_channel)
with open("member_channel.txt", "a") as file: # THIS IS WHAT
file.write(str(member.id) + ":" + str(member_channel.id) + "\n") # IS'NT WORKING
print(f"[{await get_hour()}] {member.name} created a temporary voice channel.")
#then we want to delete the channel if it is empty and equal to a member's channel, and also delete the line in member_channel.txt corresponding to this member and channel
elif before.channel is not None and len(before.channel.members) == 0:
new_file_value = ""
try:
with open("member_channel.txt", "r") as file:
lines = file.readlines()
splited_lines = []
for line in lines:
splited_lines.append((line.split(":")))
for lines in splited_lines:
for line in lines:
line.replace("\n", "")
if str(before.channel.id) in line:
await before.channel.delete()
del splited_lines[line.index(str(before.channel.id))]
for line in splited_lines:
print(new_file_value)
new_file_value += line
for ele in line:
print(new_file_value)
new_file_value += line + ":"
with open("member_channel.txt", "w+") as file:
file.write(new_file_value)
print(f"[{await get_hour()}] I deleted the temporary voice channel {member_channel.name}.")
file.close()
file.close()
except NameError:
return
im trying to do a trivial discord bot, but with a "helper" it reveals you letter by letter the answer, each "x" senconds, but the problem is i can't to send the answer till the help is fully displayed
in the image the problem is cleary visible
this is the whole code
await ctx.send(a) #question
respuestas = b #answer
#reveal
string = respuestas[0]
blanked_string = [x if x.isspace() else "-" for x in string]
nonspace_indexes = [i for i, _ in enumerate(string)]
random.shuffle(nonspace_indexes)
for i in nonspace_indexes:
blanked_string[i] = string[i]
await ctx.send(''.join(blanked_string))
await asyncio.sleep(2)
#checking
def check(msg=discord.Message) -> True:
return msg.content.lower() in respuestas and msg.channel == ctx.message.channel
try:
guess = await bot.wait_for('message', timeout=6, check=check)
return await ctx.send(f"{guess.author.mention} first")
except asyncio.TimeoutError:
await ctx.send("time over")
#problem
https://i.stack.imgur.com/jlatG.png
note: im not trying to do a hangman
async def letters(response: str, channel: discord.TextChannel):
blanked_string = [x if x.isspace() else "-" for x in response]
nonspace_indexes = [i for i, _ in enumerate(response)]
random.shuffle(nonspace_indexes)
for i in nonspace_indexes:
blanked_string[i] = response[i]
await channel.send(''.join(blanked_string))
await asyncio.sleep(1)
#client.command()
async def game(ctx: commands.Context):
await ctx.send("Author of Python programming language...")
response = "Guido van Rossum"
letters_func = asyncio.create_task(letters(response, ctx.channel))
try:
player_response = await client.wait_for('message', check=lambda m: m.author == ctx.author and m.channel == ctx.channel, timeout=30)
except asyncio.TimeoutError:
letters_func.cancel()
await ctx.send("Time's up!")
else:
letters_func.cancel()
if player_response.content == response:
await ctx.send("Correct!")
else:
await ctx.send("Incorrect!")
Here is a possible resolution path for your problem. I took advantage of asyncio's presence to do this. You can test it, it works very well.
Be careful to adapt your response time to the length of your answer
I have a command which allows people to react to a message to enter into a "battle". Then with another command, 2 people are chosen. This is my code:
#client.command(aliases=['start', 'g'])
async def startbattle(ctx):
msg = await ctx.send("React to enter battle")
await msg.add_reaction("🎉")
await asyncio.sleep(10000000000000000)
message = await ctx.fetch_message(msg.id)
for reaction in message.reactions:
if str(reaction.emoji) == "🎉":
users = await reaction.users().flatten()
if len(users) == 1:
return await msg.edit(embed=discord.Embed(title="Nobody has won the giveaway."))
try:
user1 = random.choice(users)
user2 = random.choice(users)
except ValueError:
return await ctx.send("not enough participants")
await ctx.send(f'Battle will be against {user1} and {user2}')
#client.command()
async def pick(ctx):
async for message in ctx.channel.history(limit=100, oldest_first=False):
if message.author.id == client.user.id and message.embeds:
reroll = await ctx.fetch_message(message.id)
users = await reroll.reactions[0].users().flatten()
users.pop(users.index(client.user))
winner1 = random.choice(users)
winner2 = random.choice(users)
await ctx.send(f"The battle will be against {winner1.mention} and {winner2.mention}")
break
else:
await ctx.send("No giveaways going on in this channel.")
This is the error which I get while using the "pick" command,
users = await reroll.reactions[0].users().flatten()
IndexError: list index out of range
the error is in the for loop as it gets the msg and the msg doesnt have any reaction so it there is no list so list is out of range to fix this u have to add try and except there so it skips the msg with no reactions.
code :
#client.command()
async def pick(ctx):
async for message in ctx.channel.history(limit=100, oldest_first=False):
if message.author.id == client.user.id and message.embeds:
reroll = await ctx.fetch_message(message.id)
try:
users = await reroll.reactions[0].users().flatten()
except:
break
users.pop(users.index(client.user))
winner1 = random.choice(users)
winner2 = random.choice(users)
await ctx.send(f"The battle will be against {winner1.mention} and {winner2.mention}")
return # <--- was the break
else:
await ctx.send("No giveaways going on in this channel.")
and a suggestion dont add break in the if statement as it will continuously check for msg if already it got one
I have been trying to find a way to add a countdown in an embed but can't find anything. So when current_time reaches a certain time, it sends an embed and starts counting down in one of the fields.
await client.wait_until_ready()
channel = client.get_channel(auth)
while not client.is_closed():
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print(current_time)
if current_time == "03:09:00":
embed = discord.Embed(
colour = discord.Colour.green(),
title = "test"
)
embed.set_image(url = "(img)") #
embed.set_thumbnail(url = "(img)") #
**embed.add_field(name="Timer", value ="??:??:??", inline = True) #Timer goes at ??:??:??
embed.add_field(name="Location", value ="adding later", inline = True)
await channel.send(embed=embed)
client.loop.create_task(background_task())```
Since its all in a async function, you could do something like this
#client.command()
async def countdown(ctx, *args):
embed = discord.Embed(
title='foo',
description='bar'
)
now = datetime.datetime.now()+datetime.timedelta(minutes=5)
embed.insert_field_at(
index=0,
name='countdown',
value=str(datetime.timedelta(minutes=5))
)
msg = await ctx.send(embed=embed)
while datetime.datetime.now() < now:
embed.remove_field(index=0)
embed.insert_field_at(
index=0,
name='countdown',
value=str(now-datetime.datetime.now())
)
await msg.edit(embed=embed)
asyncio.sleep(5)
Hard to get the title perfect, but pretty much. Got it hooked up that !!changelog is the main command, this will send a list of all the commands available, but issue I am getting is that. Whenever I run the !!changelog message <text> command, the preset "help" message shows up.
Picture here:
Whenever the message is sent, I just want it to say something like "Your message has been sent"
Here is my code:
#commands.group(invoke_without_command=True)
async def changelog(self, ctx):
await ctx.send('Available Setup Commands: \nSet Channel: <#channel>\nChangelog Message: <message>')
#changelog.command()
async def channel(self, ctx, channel: discord.TextChannel):
if ctx.message.author.guild_permissions.administrator:
db = sqlite3.connect('main.sqlite')
cursor = db.cursor()
cursor.execute(
f'SELECT channel_id FROM main WHERE guild_id = {ctx.guild.id}')
result = cursor.fetchone()
if result is None:
sql = ('INSERT INTO main(guild_id, channel_id) VALUES(?,?)')
val = (ctx.guild.id, channel.id)
await ctx.send(f'Channel has been set to {channel.mention}')
elif result is not None:
sql = ('UPDATE main SET channel_id = ? WHERE guild_id = ?')
val = (channel.id, ctx.guild.id)
await ctx.send(f'Channel has been updated to {channel.mention}')
cursor.execute(sql, val)
db.commit()
cursor.close()
db.close()
#changelog.command()
async def message(self, ctx, *, text):
if ctx.message.author.guild_permissions.manage_messages:
est = timezone('EST')
db = sqlite3.connect('main.sqlite')
cursor = db.cursor()
cursor.execute(f'SELECT channel_id FROM main WHERE 1')
channel = cursor.fetchone()
channel_id = self.client.get_channel(int(channel[0]))
message = text.capitalize()
embed = discord.Embed(
title="Changelog", description=f"● {message}", color=0)
embed.set_footer(
text=f'Published: {datetime.now(est).strftime("%Y-%m-%d %H:%M:%S")}')
await channel_id.send(embed=embed)
cursor.close()
db.close()
You can use ctx.invoked_subcommand to check if you are running a subcommand in your group:
async def changelog(self, ctx):
if ctx.invoked_subcommand is None:
await ctx.send('Available Setup Commands: \nSet Channel <#channel>\nChangelog Message: <message>')