Discord bot written in python, shows tons of error, mostly (TypeError: add() missing 1 required positional argument: 'movie_details') - discord.py

so I have just started getting interested in creating discord bots for my own server and mostly for fun, so I'm a a bit of a beginner in that, and this time I'm trying to create a discord bot that logs movies I have watched with my friends and also let's me search through the list of movies, delete a movie or if i just want to list the movies, and I'm trying to use davinci-003 model from the openai API to extract the movie detail that I have added, in case i give it an incomplete movie name so it would complete it for me, or so it would add the movie year and extra details about the movie I'm trying to add, at least that was my intention.
however first of all the very first issue is my bot doesn't show any status when i run it (i.e say watching a movie in the status of the bot), and also none of the / commands work on discord, they all return "The application did not respond" on discord and I get this error in the terminal where the code is running:
when I use /add moviename
Task exception was never retrieved
future: <Task finished name='Task-19' coro=<add() done, defined at /usr/local/lib/python3.10/dist-packages/interactions/client/models/command.py:930> exception=TypeError("add() missing 1 required positional argument: 'movie_details'")>
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/interactions/client/models/command.py", line 970, in wrapper
raise e
File "/usr/local/lib/python3.10/dist-packages/interactions/client/models/command.py", line 939, in wrapper
return await coro(ctx, *args, **kwargs)
TypeError: add() missing 1 required positional argument: 'movie_details'
and same error for /delete moviename and /search moviename with their own functions though (i.e delete() or search() which is missing 1 required positional argument: 'query'), for /list however, on discord I still get "The application did not respond" even though it's just supposed to return my empty movie list.
and here is my code:
import openai
import discord
import os
import interactions
from dotenv import load_dotenv
# Load environment variables from .env file
try:
load_dotenv()
except FileNotFoundError:
print("Could not find .env file")
openai.api_key = os.getenv("API_KEY")
if openai.api_key is None:
print("API key not set. Set the API key using openai.api_key = 'YOUR_API_KEY'")
else:
print("Connected to OpenAI API key...")
# Create a bot object using the interactions library
bot = interactions.Client(
token=os.getenv("DISCORD_BOT_TOKEN"),
activity=discord.Activity(type=discord.ActivityType.watching, name="a Movie")
)
# This function is used to get the list of movies from the logger (by reading from the movie-log.txt file)
def get_movie_list():
movie_list = []
try:
with open("movie-log.txt", "r") as movie_log_file:
for line in movie_log_file:
movie_list.append(line.strip())
except FileNotFoundError:
return "movie-log.txt file not found"
else:
return "\n".join(movie_list)
# This function is used to search for movies in the logger (by searching the movie-log.txt file)
def search_movies(query):
search_results = []
try:
with open("movie-log.txt", "r") as movie_log_file:
for line in movie_log_file:
if query.lower() in line.lower():
search_results.append(line.strip())
except FileNotFoundError:
return "movie-log.txt file not found"
else:
if not search_results:
return "No results found"
return "\n".join(search_results)
# This function is used to add a movie to the logger (by appending to the movie-log.txt file)
def add_movie(movie_details):
if not movie_details:
return
# Check if the movie already exists in the logger
if movie_details in search_movies(movie_details):
return
try:
with open("movie-log.txt", "a") as movie_log_file:
movie_log_file.write(f"{movie_details}\n")
except FileNotFoundError:
return "movie-log.txt file not found"
# This function is used to delete a movie from the logger (by overwriting the movie-log.txt file)
def delete_movie(movie_details):
movie_list = get_movie_list()
if movie_details not in movie_list:
return "Movie not found"
try:
with open("movie-log.txt", "w") as movie_log_file:
for movie in movie_list:
if movie != movie_details:
movie_log_file.write(f"{movie}\n")
except FileNotFoundError:
return "movie-log.txt file not found"
# This function is used to handle errors
def handle_error(error):
try:
return f"Error of type {type(error)} occurred: {error}"
except Exception as e:
return "Unable to create error message"
# Debug intents
debug_guild = int(os.getenv("DEBUG_GUILD"))
debug_channel = int(os.getenv("DEBUG_CHANNEL"))
# Define the on_ready event handler
#bot.event
async def on_ready():
print("Bot is up and running...")
print("Bot is ready to use!")
# Define the /add command using the command decorator
#bot.command(
name="add",
description="Adds a movie to the movie log",
scope=debug_guild,
)
async def add(ctx: interactions.CommandContext, movie_details: str):
try:
response = openai.Completion.create(
engine="davinci-003",
prompt=f"/add {movie_details}",
max_tokens=1024,
temperature=0.5,
)
except Exception as e:
# Handle any errors that occurred
await ctx.send(handle_error(e))
else:
# Add the movie to the logger
result = add_movie(response.text.strip())
if result:
await ctx.send(result)
# Define the /delete command using the command decorator
#bot.command(
name="delete",
description="Deletes a movie from the movie log",
scope=debug_guild,
)
async def delete(ctx: interactions.CommandContext, movie_details: str):
try:
response = openai.Completion.create(
engine="davinci-003",
prompt=f"/delete {movie_details}",
max_tokens=1024,
temperature=0.5,
)
except Exception as e:
# Handle any errors that occurred
await ctx.send(handle_error(e))
else:
# Delete the movie from the logger
result = delete_movie(response.text.strip())
if result:
await ctx.send(result)
# Define the /search command using the command decorator
#bot.command(
name="search",
description="Searches for movies in the movie log",
scope=debug_guild,
)
async def search(ctx: interactions.CommandContext, query: str):
# Search for movies in the logger
result = search_movies(query)
if result:
await ctx.send(result)
# Define the /list command using the command decorator
#bot.command(
name="list",
description="Lists all movies in the movie log",
scope=debug_guild,
)
async def list(ctx: interactions.CommandContext):
# Get the list of movies from the logger
result = get_movie_list()
if result:
await ctx.send(result)
# Handle command errors using the on_command_error event
#bot.event
async def command_error(ctx, error):
# Send an error message if a CommandNotFound error occurred
if isinstance(error, interactions.CommandNotFound):
await ctx.send("Command not found")
# Run the bot
bot.start()
Please let me know if anything is unclear or if I don't make sense ;-; Thank you!
What I've tried:
Well, at first I was using commands from discord.ext library but then none of my / commands were even showing up on discord, and I searched the web and found out that it's outdated and that I should switch to using interactions library, I used the docs from https://discord-py-slash-command.readthedocs.io/ to switch to interactions, my / commands started showing up when tried to call on discord however I don't know if I coded them correctly.

Related

How do I fix the error? discord.ext.commands.errors.CommandNotFound

Whenever I do ?+"My question" in the discord, the error comes up
import discord
import openai
from discord.ext import commands
bot = commands.Bot(command_prefix="?", intents=discord.Intents.all())
token = "MTA2MzkxMzQ0NTcyNjEwNTYxMA.Gzwl09.Z7z5AFSoXSzqPl9qoNy1vkSOCL7sRvvNk_2WUk"
#bot.event
async def on_ready():
print("\033[32m\033[1m" + "Success: Bot is connected to Discord!")
#bot.command()
async def test(ctx, *, arg):
query = ctx.message.content
response = openai.Completion.create(
api_key='7bc82fafd22190d6e7e0dff98b662ab7169a7799386dbafe05de90b7f5e71335',
model="text-davinci-003",
prompt=query,
temperature=0.5,
max_tokens=60,
top_p=0.3,
frequency_penalty=0.5,
presence_penalty=0.0`your text`
)
await ctx.channel.send(content=response['choices'][0]['text'].replace(str(query), ""))
bot.run(token)
discord.ext.commands.bot Ignoring exception in command None
discord.ext.commands.errors.CommandNotFound: Command "hallo" is not found
First off, you leaked both your bot token and your OpenAI API key so you should go reset both of them.
Next, you're saying that the error appears when you send ?+"My question" in Discord. You don't have a command that matches this, as your error suggests. the only command you have is called test, so that is the only command you can use.
The error is telling you that someone tried to invoke a command that doesn't exist. If you don't care, you can create an error handler and ignore this exception. This Gist explains how to do so: https://gist.github.com/EvieePy/7822af90858ef65012ea500bcecf1612

welcome message code for multiple servers

I recently started to learn discord.py and I wanted to add a welcome message for multi-channels and I found this post Discord.py welcome message for multiple servers I tried the code and seems to be working without any errors but I'm facing a problem creating a welcome message with this code because I don't have experience with discord.py I will have the code listed below and at the very bottom I will have the welcome code I tried if somebody can help it would be great
Thank you
#client.event
async def on_guild_join(guild):
#loads json file to dictionary
with open("welcome-message.json", "r") as f:
guildInfo = json.load(f)
guildInfo[guild.id] = guild.text_channels[0] #sets key to guilds id and value to top textchannel
#writes dictionary to json file
with open("welcome-message.json", "w") as f:
json.dump(guildInfo, f)
#allows server members to set channel for welcome messages to send to
#client.command()
async def welcomeMessage(ctx):
with open("welcome-message.json", "r") as f:
guildInfo = json.load(f)
guildInfo[ctx.message.guild.id] = ctx.message.channel.id #sets channel to send message to as the channel the command was sent to
with open("welcome-message.json", "w") as f:
json.dump(guildInfo, f)
# welcome code
#client.event
async def on_member_join(ctx, message):
with open("welcome-message.json", "r")as f:
guildInfo = json.load(f)
channel = guildInfo[ctx.message.guild.id]
embed = discord.Embed(title="Welcome ""!",
description=f"We're so glad you're here !", color=discord.Color.green())
await channel.send(embed=embed) ```
You have to specify the member intent to receive on_member_join events. You can do this while creating your bot object by adding an intent option:
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(intents=intents, other_options)
Note
If your bot is verified you require the SERVER MEMBERS INTENT which you can request on the bot page of your application.
Also:
On this line here:
embed = discord.Embed(title="Welcome ""!", it will error out as there are quotes in a quoted string, if you want to keep those quotes switch the quotes to single quotes (')

Discord py anime character database

How to make Api anime character database function with my discord python bot? I am new add discord python bot. This sample api link for anime character database:
https://www.animecharactersdatabase.com/api_series_characters.php?character_q=naruto
I think this should work, try this! i commented out some stuff for it to be easy to understand
# Requrired modules
import discord
from discord.ext import commands
import requests
import random
import platform
# Creating the bot with the bot prefix as `?`
client = commands.Bot(command_prefix="?")
#client.event
async def on_ready():
print(f'Discord.py API version: {discord.__version__}')
print(f'Python version: {platform.python_version()}')
print(f'Logged in as {client.user.name}')
print('Bot is ready!')
# The commandsstarts here
#client.command()
async def anime(ctx, *, query="naruto"): # 'anime' is the name of the command
# This command can be used as `?anime character_name_here`
# The default value will be 'naruto' for the query
try:
reqcont = requests.get(f"https://www.animecharactersdatabase.com/api_series_characters.php?character_q={query}")
if reqcont.content==-1 or reqcont.content=='-1': # i found out that the website returns: -1 if there are no results, so here, we implement it
await ctx.send("[-] Unable to find results! - No such results exists!")
else:
# If the website doesnt return: -1 , this will happen
try:
reqcont = reqcont.json()
except Exception as e:
# Please enable this line only while you are developing and not when deplying
await ctx.send(reqcont.content)
await ctx.send(f"[-] Unable to turn the data to json format! {e}")
return # the function will end if an error happens in creating a json out of the request
# selecting a random item for the output
rand_val = len(reqcont["search_results"])-1
get_index = random.randint(0, rand_val)
curent_info = reqcont["search_results"][get_index]
# Creting the embed and sending it
embed=discord.Embed(title="Anime Info", description=":smiley: Anime Character Info result for {query}", color=0x00f549)
embed.set_author(name="YourBot", icon_url="https://cdn.discordapp.com/attachments/877796755234783273/879295069834850324/Avatar.png")
embed.set_thumbnail(url=f"{curent_info['anime_image']}")
embed.set_image(url=f"{curent_info['character_image']}")
embed.add_field(name="Anime Name", value=f"{curent_info['anime_name']}", inline=False)
embed.add_field(name="Name", value=f"{curent_info['name']}", inline=False)
embed.add_field(name="Gender", value=f"{curent_info['gender']}", inline=False)
embed.add_field(name="Description", value=f"{curent_info['desc']}", inline=False)
embed.set_footer(text=f"Requested by {ctx.author.mention}")
await ctx.send(embed=embed)
except Exception as e:
await ctx.send(f"[-] An error has occured: {e}")
client.run("NeverShareYourToken")

Check if a user id is in a list of user ids to allow command access - discord.py

im fairly new to python and have been writing a discord bot for a server with me and a few friends as practice. I've added a few commands that could be pretty disruptive if all users had access to them at all times and have been trying to add a method to enable and disable access to them without using discord roles but a python list instead. I added a command that i can use to to add their user id to a list, but when the user tries to use the command they receive a permission error.
the code below is the problematic code from a cog
modlist = []
def ListCheck():
async def IsInList(ctx):
member = ctx.message.author.id
return member in modlist
return commands.check(IsInList)
#commands.command()
async def AddUser(self, ctx, *, question):
modlist.append(question)
#commands.command()
async def ViewModList(self, ctx):
await ctx.send('User ids that have access:')
for i in range(0, len(modlist)):
await ctx.send(modlist[i])
#commands.command()
async def ClearModList(self, ctx):
modlist.clear()
await ctx.send('Modlist cleared')
#commands.command()
#ListCheck()
async def PermTest(self, ctx):
await ctx.send('user is in modlist')
Any help would be hugely appreciated
One way you could do it would be to use commands.check(). The function in the code below checks if the message author, ctx.author, is in the given list, modList. If the author is in this list when the command 'test' is invoked, then the bot will send "You are a mod!", otherwise it will raise a check error.
modList = [394506589350002688, 697725862128386048] # just some ids as examples
def check_Mod(ctx):
if ctx.author.id in modList:
return ctx.author.id in modList
#commands.command()
#commands.check(check_Mod)
async def test(ctx):
await ctx.send("You are a mod!")
The above working is shown in the image below:
To answer is there is a way to add user ids to the list via a command?, you may either use a json or text file. In this case, I will use a text file since it's simpler, and also because my json isn't as fluent as others.
Here's an example of how your text file may look like:
394506589350002688
697725862128386048
First you need to read the file and check whether the author's id is in the file. We will be changing the check_Mod function for this. If you want to know more about reading through a text file, or feel that you may need a more efficient way, you may have a look at this: How to search for a string in text files?
def check_Mod(ctx):
with open('Mod.txt') as f: # do change the 'Mod.txt' to the name that suits you. Ensure that this file is in the same directory as your code!
if str(ctx.author.id) in f.read(): # this is reading the text file and checking if there's a matching string
return ctx.author.id
Now for writing the author id into your text file.
#commands.command()
#commands.check(check_Mod)
async def add_Mod(ctx, user:discord.Member=None):
if user == None:
await ctx.send("Please provide a user to add as a Mod!")
return
# First we'll make some functions for cleaner, more readable code #
def is_Mod(user_id):
## This function will check if the given id is already in the file. True if in file, False if not ##
with open('Mod.txt', 'r') as f:
if str(user_id) in f.read():
return True
else:
return False
def add_Mod(user_id):
## This function will add the given user id into the given text file, Mod.txt ##
with open('Mod.txt', 'a') as f: # 'a' is used for appending, since we don't want to overwrite all the ids already in the file
f.write(f"{str(user_id)}\n")
f.close()
# Now we put those functions to use #
if is_Mod(user.id) == True:
await ctx.send(f"The user {user} is already a Mod!")
else:
add_Mod(user.id)
await ctx.send(f"{user} added as a Mod!")
The above should work as seen in the image below.
p.s. If you have any other questions, please post them as a new question, thank you!

Why does discord.py-rewrite bot.loop.create_task(my_background_task()) execute once but does not repeat

Using Discord.py-rewrite, How can we diagnose my_background_task to find the reason why its print statement is not printing every 3 seconds?
Details:
The problem that I am observing is that "print('inside loop')" is printed once in my logs, but not the expected 'every three seconds'. Could there be an exception somewhere that I am not catching?
Note: I do see print(f'Logged in as {bot.user.name} - {bot.user.id}') in the logs so on_ready seems to work, so that method cannot be to blame.
I tried following this example: https://github.com/Rapptz/discord.py/blob/async/examples/background_task.py
however I did not use its client = discord.Client() statement because I think I can achieve the same using "bot" similar to as explained here https://stackoverflow.com/a/53136140/6200445
import asyncio
import discord
from discord.ext import commands
token = open("token.txt", "r").read()
def get_prefix(client, message):
prefixes = ['=', '==']
if not message.guild:
prefixes = ['=='] # Only allow '==' as a prefix when in DMs, this is optional
# Allow users to #mention the bot instead of using a prefix when using a command. Also optional
# Do `return prefixes` if u don't want to allow mentions instead of prefix.
return commands.when_mentioned_or(*prefixes)(client, message)
bot = commands.Bot( # Create a new bot
command_prefix=get_prefix, # Set the prefix
description='A bot for doing cool things. Commands list:', # description for the bot
case_insensitive=True # Make the commands case insensitive
)
# case_insensitive=True is used as the commands are case sensitive by default
cogs = ['cogs.basic','cogs.embed']
#bot.event
async def on_ready(): # Do this when the bot is logged in
print(f'Logged in as {bot.user.name} - {bot.user.id}') # Print the name and ID of the bot logged in.
for cog in cogs:
bot.load_extension(cog)
return
async def my_background_task():
await bot.wait_until_ready()
print('inside loop') # This prints one time. How to make it print every 3 seconds?
counter = 0
while not bot.is_closed:
counter += 1
await bot.send_message(channel, counter)
await channel.send(counter)
await asyncio.sleep(3) # task runs every 3 seconds
bot.loop.create_task(my_background_task())
bot.run(token)
[]
From a cursory inspection, it would seem your problem is that you are only calling it once. Your method my_background_task is not called once every three seconds. It is instead your send_message method that is called once every three seconds. For intended behavior, place the print statement inside your while loop.
Although I am using rewrite, I found both of these resources helpful.
https://github.com/Rapptz/discord.py/blob/async/examples/background_task.py
https://github.com/Rapptz/discord.py/blob/rewrite/examples/background_task.py

Resources