Discord.py "Za Warudo" Bot Command - discord

I'm making a bot command that...
Locks the channel; making no one able to send messages.
Sends an image and a message.
Waits 10 seconds before unlocking the channel, allowing others to send images.
However, I have tried different messages such as changing the role name and different sleep times, and the bot does not send a message, modify commands, or what it was intended to do. It is only this command that doesn't function, and no errors pop up in the console.
Could someone help me, please?
#commands.has_permissions(manage_messages=True)
async def warudo(ctx):
await ctx.channel.set_permissions(ctx.verified, send_messages=False)
await ctx.send('***Za Warudo!***')
await ctx.send(file=discord.File('https://pics.me.me/thumb_you-thought-it-was-an-emoji-but-it-was-me-71487398.png'))
await ctx.send( ctx.channel.mention + "has paused.")
await asyncio.sleep(10)
await ctx.channel.set_permissions(ctx.verified, send_messages=True)```

Related

Is there a way to have multiple arguments in a command with discord py

I’m creating a discord bot using discord py and would like to have a kick command that dms the user a reason upon being kicked.
-kick #user reason
When I kick the user with a reason attached it doesn’t kick the user and I get an error in console saying can not find the user
Here is the code
#client.command(aliases=['Kick'])
#commands.has_permissions(administrator=True)
async def kick(ctx,member : discord.Member,*,reason= 'no reason'):
await ctx.send(f'{member.name} was kicked from the Server!\nand a Dm was sendet by me as a Information for him')
await asyncio.sleep(5)
await ctx.channel.purge(limit=2)
await member.send(f'**You was kicked from {ctx.guild.name}\nthe Stuff Team dont tell me the reason?**')
await member.kick(reason=reason)
print(f"{ctx.author} ----> just used {prefix}kick")
And yes I have tried Google, the discord py API guide with no luck
Can anyone help? Thanks
You can give a nice error message. It raises MemberNotFound.
Then you can make a local error handler.
#kick.error
async def kick_command_error(ctx, err):
if isinstance(err, commands.MemberNotFound):
await ctx.send('Hey! The member you gave is invalid or was not found. Please try again by `#`mentioning them or using the ID.')

Invalid Webhook Token on interaction

I'm making a slash command bot for Discord and there is an issue with interactions. Apparently the webhook token is only valid for 15 minutes, after that I can no longer edit the message embed. This is usually not enough time for my users as the embed relies on a transaction to hit the blockchain (which these days can take about 30 minutes).
Is there a way to refresh the webhook token for my interaction so I can extend it past 15 minutes?
I do not believe that Discord supports refreshing webhook tokens, however, if you are waiting for your blockchain transaction to be completed before replying, you could defer the reply until that is done. You can do this with the MessageComponentInteraction.deferReply() method.
EDIT: After further thought, I realize that this may not actually solve your problem. You might be forced to use a standard message.reply() workflow for sending this.
Unfortunately, Discord (not discord.js) expires all interaction tokens after 15 minutes. This is a Discord limitation, and you will have to bring this up to Discord to give feedback. However, there is a workaround.
This is the recommended approach if you have a lot of requests coming through. According to your JSON data, you do not need ephemeral messages, which means that you can simply send the message as a bot user.
Note: This requires you to have the bot scope when users are inviting your bot.
const embed = new MessageEmbed()
.setTitle("Waiting for transaction to finish...")
// ...
await interaction.reply("See below message.");
const msg = await interaction.channel.send({ embeds: [embed] });
// Once the transaction finishes
const updatedEmbed = embed
.setTitle("Transaction finished!")
// ...
await msg.edit({ embeds: [updatedEmbed] });
By using a bot that sends a message, you get unlimited time to edit the message, even past 30 minutes.
Another workaround if you don't have the bot scope on your user's servers is to manually create server webhooks (not interactions) and edit them when needed. This requires them to invite the bot with webhook permissions, though.
This approach does not require the bot scope, however, requires webhook permissions.
const webhook = await interaction.channel.createWebhook("My Bot Name", {
avatar: "" // link to your bot's avatar (optional)
});
const embed = new MessageEmbed()
.setTitle("Waiting for transaction to finish...")
// ...
await interaction.reply("See below message.");
const msg = webhook.send({ embeds: [embed] });
// Once the transaction finishes
const updatedEmbed = embed
.setTitle("Transaction finished!")
// ...
await msg.edit({ embeds: [updatedEmbed] });

How to make a slash command bot do not reply messages

#slash.slash(name='spam', description='I will spam your content for times!', options=optionsspam, guild_ids=[847769978308526090])
async def spam(ctx, text: str, times: int="15"):
if bool(times):
Times = 15
else:
Times = times
for i in range(int(Times)):
await ctx.send(text)
await asyncio.sleep(.7)
And the result is:
It keeps replying to the first message that the bot sent. I don’t want the bot to reply. I want it to just send a normal message. How?
An interaction (slash-command) will always require a direct response towards the user. If you do not use ctx.send(str), the interaction will fail.
You've got 2 options to make it seem, like you are not responding to the slash command
Hide the response
You can post a hidden answer ctx.send('ok', hidden=True) and then send the intented message into the channel ctx.channel.send(str).
This will make the initial 'ok' only visible for the invoking users and all other members of the server will neither see the request, nor the first response.
Delete the response
Your second option is to automatically delete the answer after a very short period (ctx.send('ok', delete_after=1)), followed by a normal message into the channel ctx.channel.send(str).
Defering the response
You might need to defer your response if you can't respond within 3 seconds of the invocation. Defering an interaction (ctx.defer(hidden=True) or ctx.defer()) must be called with the same hidden attribute as your future ctx.send().
If you want to hide your respons ctx.send('ok', hidden=True), you need to defer in the same state ctx.defer(hidden=True).
You could get the channel and send message to the channel directly. However, you then must use something like ctx.defer() so that the interaction doesn't get displayed as failed.
#slash.slash(name='spam', description='I will spam your content for times!', options=optionsspam, guild_ids=[847769978308526090])
async def spam(ctx, text: str, times: int="15"):
channel = ctx.channel
if bool(times):
Times = 15
else:
Times = times
for i in range(int(Times)):
if channel != None:
await channel.send(text)
await asyncio.sleep(.7)
await ctx.send("Done")

discord.py get webhooks of channel

I'm trying to make a webhook so if anyone says 'ez' it deletes it and sends a message with the webhook with a random message. Originally what I was doing was
if "ez" in message.content:
webhook = await message.create_webhook(name=ctx.author.name)
await webhook.send(ezmessages[random.randint(0, len(ezmessages))-1], username=message.author.name, avatar_url=message.author.avatar_url)
await message.delete()
await webhook.delete()
but the problem is this gets rate limited if webhooks are created and deleted too quickly. So instead what I want to do is check if the bot already has a webhook for the text channel, and if there is one use that but if not use a different one. I thought this would work:
for webhook in message.channel.webhooks:
await webhook.send(ezmessages[random.randint(0, len(ezmessages))-1], username=message.author.name, avatar_url=message.author.avatar_url)
but I get the error
TypeError: 'method' object is not iterable
Even though it should return a list
Anyone know how to correctly iterate over this?
TextChannel.webhooks it's not an attribute, its a function and a coroutine, so you need to call it and await it
webhooks = await message.channel.webhooks()
for webhook in webhooks:
...
docs

How can I delete a message in discord.py after a command was executed by an user?

I am trying to program a function that deletes the message with the command sent by the user.
E.g.:
User sends command /delmes
Bot sends a response to the command
Bot deletes the message sent by the user
Everything I was able to find until now (that would help me) was this Stack Overflow Thread: discord.py delete author message after executing command
But when I used the code, as described in the solutions, I only received AttributeError: 'Bot' object has no attribute 'delete_message'.
The discord.py API Reference (https://discordpy.readthedocs.io/en/latest/migrating.html#models-are-stateful / https://discordpy.readthedocs.io/en/latest/api.html?highlight=delete%20message#message) only revealed that some of the code had changed with newer versions.
So to speak client.delete_message would change to Message.delete(), if I interpreted it correctly!
After changing the code to what I thought it must be I received: NameError: name 'Message' is not defined
This is my code at the very last moment. (I am relatively new to discord.py and only used Python in school)
import discord
from discord.ext import commands
import random
import json
client = commands.Bot(command_prefix = '/', case_insensitive=True)
#client.command(pass_context=True)
async def delcommes(ctx):
await ctx.send("This is the response to the users command!")
await Message.delete(ctx.message, delay=3)
I couldn't understand your question very good but as far as I understand, when command executed, then after bot sends message, you want to delete the command message, in that case it's /delmes. You can use await ctx.message.delete().
#client.command(pass_context=True)
async def delcommes(ctx):
await ctx.send("This is the response to the users command!")
await ctx.message.delete()

Resources