I want to get the values of two variables in a command function. In the example, I want to use a variable to define par.count(par2)
#commands.command()
async def count(self, ctx, par, par2):
x = par.count(par2)
emBed = discord.Embed(title="try count", description="", color=0x6F9DC3)
emBed.add_field(name="Output", value='text = "{0}"\nx = text.count({1})\nprint(x)' .format(par, par2))
emBed.add_field(name="Result", value='{0}' .format(x))
await ctx.channel.send(embed=emBed)
This is my result on discord embed when I input in discord "count i love you so much love" it defines the letter i as the text variable and love as the count variable, Any ideas to make the user input two variables to make my commands work?
Output Result
text = "i" 0
x = text.count(love)
print(x)
You can use * before the variable that will catch the rest of the command context.
#commands.command()
async def count(self, ctx, word, *, text):
x = text.count(word)
...
Example usage:
count love I love you so much, love
(<command> <word you want to count> <text>)
Hi I am not completely sure what u want but as I understand it the following could help:
#bot.command()
async def test(ctx, *args):
await ctx.send('{} arguments: {}'.format(len(args), ', '.join(args)))
https://discordpy.readthedocs.io/en/stable/ext/commands/commands.html#variable
Related
I want to start working with SlashCommand autocompletion in pycord. Since I think that my request in the previous question is impossible, I thought to myself that maybe I can change the autocomplete based on the user's choice in one of the slash-command entries and display the desired entry to the user earlier.
I'm asking this because I don't found any good resource for learning this and I don't understand docs
there is an example from the Pycord documents, I think if you experiment with this part of the code, you will understand how it can work
https://github.com/Pycord-Development/pycord/blob/master/examples/app_commands/slash_autocomplete.py
If you want use them in cogs
there's my part for cogs
import discord
from discord import option
from discord.ext import commands
mycolors = ["red", "white", "yellow"]
class ExampleAutocompletion(commands.Cog):
ctx_parse = discord.ApplicationContext
def __init__(self, bot: discord.Bot):
self.bot = bot.user
#staticmethod
def colorAutocomplete(self: discord.AutocompleteContext):
return mycolors
#staticmethod
def flowertypeAutocomplete(self: discord.AutocompleteContext):
chosen_color = self.options["color"]
match chosen_color:
case "red":
return ["Rose", "Georgina"]
case "white":
return ["Chrisantem", "Gortensia"]
case "yellow":
return ["Sunflower", "Narciss"]
case _:
return ["There is no flower with this color"]
#commands.slash_command(
guild_ids=["Your Guild ID for test"],
description="")
#option("color", description="What's your favourite color?",
autocomplete=colorAutocomplete)
#option("flowertype", description="and that's your flower shape!",
autocomplete=flowertypeAutocomplete)
async def beautyflowers(self, ctx: ctx_parse,
color: str, flowertype: str):
await ctx.respond(f"My flower is {flowertype} and its color is {color}!")
def setup(bot):
bot.add_cog(ExampleAutocompletion(bot))
I am making a discord bot that is going to make 2 teams out of a list that the user created with one command. I just don't know how to create a list out of the elements that the user inputs. I want the user to write for example !team a b c d e f which should create a list that looks like this: list = ["a", "b", "c", "d", "e", "f"]. I want the command that the user inputs in discord to start with !team, and after that the user is going to write all of the list elements.
Something like this:
async def on_message(self, message):
items = message.content.split()
print(items)
First, you might want to use a command rather than an on_message event like another user had suggested. To get a list from a command, you can use *args. You can view more about variables in commands in the discord.py docs. *args, when used, would return a list such as ('a', 'b', 'c') depending on the given input. Do view the example below.
#client.command() # or #bot.command() depending on what you're using
async def team(ctx, *args): # command would be run as !team a b c d e
print(args) # printing how the list would look like
await ctx.send(', '.join(args)) # makes it look neater rather than sending a normal list
Here is how the above command would look.
If you use commands instead on the on_messags event this will be easier:
#bot.command(name='listcommands')
async def list_commands(ctx, *message):
List = message.split()
await ctx.send(response)
But you could do this with an on_message event:
#client.event
asynce def on_message(message):
If (message.author == client.user)
return
If message.content.startswith('$commands')
List = message.content.split('$commands ', 1)
So I have a command which allows you to create a channel and a role based on what the user gives. The problem arises when the channel name is over a word. For example:
>newrealm Space Invaders (emoji) (mention)
This command will raise an error because now it's assuming "Invaders" is the emoji.
Which is why I am now using something like this:
>newrealm Space-Invaders (emoji) (mention)
Now the problem with this command is that while creating the role, the name is Space-Invaders OP. Is there a way to remove the - in the role's name?
My code:
#commands.command()
#commands.has_permissions(manage_roles = True)
async def newrealm(self, ctx, realm, emoji, user: discord.Member):
author = ctx.message.author
guild = ctx.message.guild
channel = ctx.message.channel
color = discord.Colour(0x3498DB)
role = await guild.create_role(name= realm + " OP", color = color)
category = discord.utils.get(guild.categories, name = "Realm Channels List Test")
await category.create_text_channel(realm + "-" + emoji)
await ctx.send("Created Channel and Role!")
await user.add_roles(role)
Any suggestions or tip's would help a lot!
There are several options that would solve this problem:
encase the name in quotes so the function recognizes it as one argument.
receive the name last with a special syntax:
async def newrealm(self, ctx, emoji, user: discord.Member, *, realm):
The second method is more elegant but it is not in order, the first method is less elegant because of the quotes but it is in order, Choose your preference.
MY GOAL
I am working on a discord bot similar to "Discord Delivers" and "Pizza Byte". And I am trying to take a list of terms/keywords and check if the arguments after the command (The code for the command is at the end of this post); So if they do >order BadWord then it checks if it contains one of the previously specified blacklisted terms, and if so, does like await ctx.send("Due to your order containing one of the blacklisted terms, your order will not be placed.") Or something like that. I am sorry for not saying what i have tried, as all i can think of, is doing things like if args in blacklist: or something like that for each word.
MY CODE
#bot.command(pass_context=True)
async def order(ctx, *, orderItem):
channel = bot.get_channel(CHANNEL ID OF THE CHANNEL)
link = await ctx.channel.create_invite(max_age = 300)
global baseNumberID
baseNumberID += 1
global orderIDdf
global df
df[str(baseNumberID)] = ctx.author.name
embed=discord.Embed(title="New order", color=0xfc57ff)
embed.add_field(name="Who and Where", value="{} in {} in the {} channel".format(ctx.message.author, ctx.message.guild.name, ctx.message.channel.mention), inline=False)
embed.add_field(name="What", value="{}".format(orderItem), inline=False)
embed.add_field(name="Invite", value="{}".format(link), inline=False)
embed.add_field(name="Order ID", value="Order ID is {}".format(baseNumberID), inline=False)
embed.add_field(name="Time", value="{} GM time".format(strftime("%Y-%m-%d %H:%M:%S", gmtime())), inline=True)
embed.set_footer(text="End of this Order")
#Second embed that will be used later.
deliverIDInfo = str(baseNumberID)
deliverInfoEmbed=discord.Embed(title="Order Info")
deliverInfoEmbed.add_field(name="Who and Where", value="{} in {} in the {} channel".format(ctx.message.author, ctx.message.guild.name, ctx.message.channel.mention), inline=False)
deliverInfoEmbed.add_field(name="What", value="{}".format(orderItem), inline=False)
deliverInfoEmbed.add_field(name="Invite", value="{}".format(link), inline=False)
deliverInfoEmbed.add_field(name="Order ID", value="Order ID is {}".format(baseNumberID), inline=False)
deliverInfoEmbed.add_field(name="Time", value="{} GMT time".format(strftime("%Y-%m-%d %H:%M:%S", gmtime())), inline=True)
deliverInfoEmbed.set_footer(text="End of this Order")
orderIDdf[deliverIDInfo] = deliverInfoEmbed
await ctx.author.send("Your order has been placed!")
await ctx.author.send(embed=embed)
await channel.send(embed=embed)
EXTRA
And if possible, could the blacklisted terms be in like either a json file or a text file? Thanks.
EDIT: CLARIFICATION
I thought i should clarify that I do in fact define the variables that are used. Everything works properly.
Without the json library:
blacklist = ['test', 'yolo'] #Your blacklisted words here
#bot.command(pass_context=True)
async def order(ctx, *, orderItem):
if orderItem.lower() in blacklist:
await ctx.send("Due to your order containing one of the blacklisted terms, your order will not be placed.")
else:
#Your code here
Using the json library:
The json file (which will contain every blacklisted words)
['test', 'yolo']
from json import loads
#bot.command(pass_context=True)
async def order(ctx, *, orderItem):
with open('blacklist.txt', 'r') as file:
blacklist = loads(file.read())
if orderItem.lower() in blacklist:
await ctx.send("Due to your order containing one of the blacklisted terms, your order will not be placed.")
else:
#Your code here
How do I have my bot take the end of a message and repeat it with a message behind it? Here's my code:
elif message.content.startswith('/ban'):
bant = message.content.endswith('') and ('has been bant')
await client.send_message(message.channel, bant)
If I say for example /ban chiken
I want it to say: chiken has been bant
Or if I say /ban jeff
I want it to say: jeff has been bant
message.content is a string like "/ban jeff"
We can use str.split to split the message on the first space
_, target = message.content.split(' ', 1)
target will be "jeff"
For longer strings, /ban jeff andy, we are only spliting once, so target will be "jeff andy".
We can then use this to build our response
bant = '{} has been bant'.format(target)
discord.Message.content returns a string, so you would need to do simple string manipulation. Luckily python is a very nice language to do this in.
# There are various ways to address the issue.
# These are ranked from most recommended to least
# assuming content is: '/ban daisy boo foo'
arguments = message.content.lstrip('/ban')
# returns 'daisy boo foo'
arguments = message.content.split(' ', 1)
# returns 'daisy boo foo'
arguments = shlex.split(message.content)[1:]
# returns ['/ban', 'daisy', 'boo', 'foo']
# but we slice it to just ['daisy', 'boo', 'foo']
arguments = message.content[len('/ban'):]
# returns 'daisy boo foo'
If you're considering using this if/elif content startswith certain pattern methodology to suppliment a commands feature to your bot I wouldn't reccomend it, discord.py comes packed with its own commands extentsion to suit these issues directly.
As a basic example of how to use the commands extension to do this, here is some code.
(Assuming discord.py rewrite 1.0.0a)
import discord
from discord.ext import commands
bot = commands.Bot(command_prefix='/')
#bot.command()
async def ban(ctx, user: discord.Member):
await user.ban()
#ban.error
async def ban_error(ctx, error):
await ctx.send(error)
bot.run('token')