How to call async function for discord bot - python

I have a (working) command that reads a file from my hard drive and plays it through my discord bot that reads:
#client.command(pass_context=True)
async def fp(ctx, file):
where file is the name of the item from a list. As some commands are used more often, I was wondering how I would go about referencing this function in another for the more common commands. Something along the lines of:
#client.command(pass_context=True)
async def crab(ctx):
client.commands.fp(ctx, "crab")
but I can't get this working after much tinkering. Any help is appreciated!

You can use the .invoke function like Patrick mentioned
#bot.command()
async def crab(ctx):
await fp.invoke(ctx, "crab")
or use a .callback function
#bot.command()
async def fp(ctx, file):
// do something.
bot.command(name="crab")(fp.callback)

Related

discord py how to create function

how to create a function that gives a role and calls it.
I need a function that give a role and how to call it
I try to
async def test():
await bot.get_channel(870197219192614943).send('test')
and
asyncio.run(test())
but it's no working
Refer to the docs to learn how to use discord.py.
U need to use this:
#bot.command()
async def test(ctx):
await bot.get_channel(870197219192614943).send('Hello, World!')
Now if you send a test message with the bot prefix at the beginning to the guild chat, where there is a bot message, you will receive a response to the channel with this id
Just name the function differently if I understand you correctly
async def name_():
pass
async def name():
pass

Discord bot with discord.py

The context is that I want to make a discord bot with discord.py and when reading its documentation, it says that I can put attributes to the classes, but I don't know where to put them.
class discord.ext.commands.Command(func, **kwargs)
#discord.ext.commands.command(name=..., cls=..., **attrs)
If I put !test_1 hello world it returns only hello, but if I put !test_1 "hello world" it returns hello world.
the !test_2 command makes it so that there is no need to use quotes so !test_2 this is an example returns this is an example.
According to the documentation, with the rest_is_raw attribute I can make test_2 behave like test_1 and take only the first argument.
So my problem is that I don't know where to place the attribute.
My code:
`
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix= '!', intents=discord.Intents.all())
# Example command 1
#bot.command()
async def test_1(ctx, arg):
await ctx.send(arg)
# Example command 2
#bot.command()
async def test_2(ctx, *, arg):
await ctx.send(arg)
#Ping-pong
#bot.command()
async def ping(ctx):
await ctx.send('pong')
#bot.event
async def on_ready():
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="!help"))
print('My bot is ready')
bot.run('mytokenissecret')
`
I tried to understand the documentation, and I put the attribute where I thought it would work, but no attempt worked.
I searched for videos but none answered my problem.
Documentation really helps you to find out what's argument used for your command. In your case test_1(ctx, arg) and test_2(ctx, *, arg) are completely different. Because, in test_2 you passing whatever you type and send in Discord. Using * make you passing all argument. Normally if there's no *, 1 argument only can accept 1 word. By using *, it can accept all of the words/sentence that you send in

I want to create this command for my discord bot that stores a list of messages that a bunch of users say then have a command to randomly choose them

For more detail I would like to create a command for my bot that takes in messages stores it somewhere like in a new file or something like that and have a new command send a message from that new file. I am wondering if I should use json or make a .txt file.
My Code:
#bot.event
async def on_message(message):
if message.author.bot:
return
if message.content == "echo":
echomessage = (message.content)
await message.channel.send(f"{echomessage} has been added to a list of messages")
await bot.process_commands(message)
#bot.command()
async def echo(ctx):
await ctx.send(f"{ctx.author.mention} {echomessage[random.randint(0, len(echomessage) - 1)]}")
I know that I have a event I would like to make it a command at some point but if I cant then imma just keep it as it.
Thanks for anyone who takes a shot at helping me! I really appriciate it.
You can simply save it to a file and randomly pick one.
Using readlines, simply write each word to use into its own line, and a random one will be picked automatically.
#bot.command()
async def addword(ctx, *, word: str):
with open('words.txt', 'a') as f:
f.write(f'{word}\n')
#bot.command()
#commands.cooldown(5, 20.0, commands.BucketType.guild) # Highly recommended, io is precious. You can also keep this file permanently opened and store it in your client at startup.
async def echo(ctx):
with open('words.txt') as f:
await ctx.send(random.choice(f.readlines()))

(discord.py) functions in a cog

I've been trying to develop a discord bot in python, and I want to make a bunch of "hidden" commands that don't show up in help. I want to make it so that whenever someone activates a hidden command, the bot sends them a pm. I tried to make a function to do it, but so far it doesn't work. Here is the code in the cog file:
import discord
from discord.ext import commands
class Hidden(commands.Cog):
def __init__(self, client):
self.client = client
def hidden_message(ctx):
ctx.author.send('You have found one of several hidden commands! :shushing_face:\nCan you find them all? :thinking:')
#commands.command()
async def example(self, ctx):
await ctx.send('yes')
hidden_message(ctx)
def setup(client):
client.add_cog(Hidden(client))
When the example command is run, the bot responds normally, but the function isn't called. There are no error messages in the console. I'm still pretty new to python so could someone tell me what I'm doing wrong?
You need to use await when calling async functions like ctx.author.send, and so the function you're wrapping that with needs to be async too
async def hidden_message(self, ctx):
await ctx.author.send('You have found one of several hidden commands! :shushing_face:\nCan you find them all? :thinking:')
And then
#commands.command()
async def example(self, ctx):
await ctx.send('yes')
await self.hidden_message(ctx)
Finally, to make a command hidden from the default help command, you can do
#commands.command(hidden=True)
In order to send a message, hidden_message would have to be a courotine, i.e. it uses async def instead of just def.
However, there is a second issue that arises because of how hidden_message is called. Calling hidden_message as hidden_message(ctx) would require the function to be defined in the global scope. Since it is a method of class Hidden, it needs to be called as such.
Highlighting the edits:
class Hidden(commands.Cog):
...
async def hidden_message(self, ctx):
...
#commands.command()
async def example(self, ctx):
await ctx.send("yes")
await self.hidden_message(ctx)

How do I resend user input after a command (e.g. User: !send 1234 Bot: 1234) in discord.py?

I have recently started programming my own discord bot as many other people are doing...
So far what I have got is this:
#bot.command
async def on_message(message):
if message.content.startswith("t!send"):
await client.send_message(message.content)
It doesn't crash but it doesn't work either...
It seems as if you're using a tutorial for an old version of discord.py.
There are some big changes in the most recent version - rewrite. Please take some time to look for more updated tutorials, or read the documentation linked above.
Here are the cases for using both the on_message event and commands:
#bot.command()
async def send(ctx, *, sentence):
await ctx.send(sentence)
######################################
#bot.event
async def on_message(message):
args = message.content.split(" ")[1:]
if message.content.startswith("t!send"):
await message.channel.send(" ".join(args))
else:
await bot.process_commands(message) # only add this if you're also using command decorators
References:
commands.Context() - if not familiar with using command decorators
discord.on_message()
Bot.process_commands()
So first of all, on_message doesn't belong here and you also don't have to use it. (on_message() would use the decorator #bot.event) Assuming you have setup a prefix for your bot using bot = commands.Bot(command_prefix = 't!') you could do something like this:
#bot.command()
async def send(ctx, *args):
message = " ".join(args)
await ctx.send(message)
*args is everything the user types in after t!send. So for example: if the user types in t!send Hello world! args would be ["Hello", "world!"]. With .join we can join them together into a single string (message)

Categories

Resources