I've been working on a private discord bot for a week or so now to get familiar with creating discord bots. All of my commands run fine and there are currently no known bugs except this one. For some reason, when my discord bot sends error messages from this function it will send a duplicate of the original embed it sent.
Here is my code:
#commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
if isinstance(error, commands.BadArgument):
embed = discord.Embed(
title = '!!! BAD ARGUMENTS !!!',
description = f'Please check your arguments and try again. Error: {error}',
color = 0xFF0000
)
elif isinstance(error, commands.MissingRole):
embed = discord.Embed(
title = '!!! MISSING PERMISIONS !!!',
description = f'You do not have permission to use this command.',
color = 0xFF0000
)
else:
embed = discord.Embed (
title = "!!! ERROR !!!",
description = "A unknown error has occured. This error has been logged and will be looked into shortly.",
color = 0xFF0000
)
with open("unkown_errors.txt", "a") as f:
f.write(f"{ctx} | {error}\n")
await ctx.send(embed = embed)
That code is what I'm using for basic error handling. It will decide the embed based on the error and send the embed at the end of the message. The odd thing is it will send the embed once, and then send the same one again immediately after. It will be the exact same except the embed color on the second one is not the same as the first, it goes back to the default color. I'm unsure of why this is happening and I've tried looking for a solution. Is there any way I can fix this? Screenshot:
#Verve!
The method that you are using is incorrect, I think you should try this:-
#commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
if isinstance(error, commands.BadArgument):
embed = discord.Embed(
title = '!!! BAD ARGUMENTS !!!',
description = f'Please check your arguments and try again. Error: {error}',
color = 0xFF0000
)
return await ctx.send(embed = embed)
elif isinstance(error, commands.MissingRole):
embed = discord.Embed(
title = '!!! MISSING PERMISIONS !!!',
description = f'You do not have permission to use this command.',
color = 0xFF0000
)
return await ctx.send(embed = embed)
else:
embed = discord.Embed (
title = "!!! ERROR !!!",
description = "A unknown error has occured. This error has been logged and will be looked into shortly.",
color = 0xFF0000
)
await ctx.send(embed=embed)
with open("unkown_errors.txt", "a") as f:
f.write(f"{ctx} | {error}\n")
return
Mostly this shall work, if it doesn't it might be a bug. If it is a bug please open a issue :- https://github.com/Pycord-Development/pycord/tree/master/
Related
I'm a beginner in programming and I have a problem making a label on my GUI to change its text value to inform the user of word's meaning (working on English dictionary). I would like the label to update itself with every loop, and so to show all the the definitions of a given word. However, the program only updates itself once the entire for loop is completed, and displays only the last definition of a word.
I've learned that I should use a QTimer, and tried it as it's shown in documentation, but with no success.
I would appreciate any help of how to make the label to update itself. Thank you.
Here is the code I am using:
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox
from PyQt6.QtWidgets import QLabel, QPushButton, QLineEdit, QComboBox, QScrollArea
from PyQt6.QtCore import Qt, QTimer
import json
from difflib import get_close_matches
data = json.load(open("data.json"))
def translate(word):
word = word.lower()
if word in data:
return data[word]
elif word.title() in data:
return data[word.title()]
elif word.upper() in data:
return data[word.upper()]
elif len(get_close_matches(word, data.keys())) > 0:
msg = QMessageBox()
msg.setWindowTitle('Get close matches')
msg.setText("Did you mean %s instead? Press Yes if yes, or No if no: " % get_close_matches(word, data.keys())[0])
msg.setIcon(QMessageBox.Icon.Question)
msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
msg.setDefaultButton(QMessageBox.StandardButton.Yes)
ret = msg.exec()
if ret == QMessageBox.StandardButton.Yes:
return data[get_close_matches(word, data.keys())[0]]
else:
return "We didn't understand your entry. Please double check it."
else:
return "The word doesn't exist. Please double check it."
def translate2():
output = translate(text.text())
if type(output) == list:
i = 1
for item in output:
output_label.setText("%s. %s" % (i,item))
i+=1
else:
output_label.setText(output)
app = QApplication([])
window = QWidget()
window.setWindowTitle('Word Definition')
layout = QVBoxLayout()
layout1 = QHBoxLayout()
layout.addLayout(layout1)
layout2 = QVBoxLayout()
layout.addLayout(layout2)
text = QLineEdit()
layout1.addWidget(text)
btn = QPushButton('Convert')
layout1.addWidget(btn, alignment=Qt.AlignmentFlag.AlignBottom)
btn.clicked.connect(translate2)
output = QWidget()
output_label = QLabel('')
output_label.setFixedSize(600, 50)
layout2.addWidget(output_label)
window.setLayout(layout)
window.show()
app.exec()
The code does what is supposed to do, but after each button press it says "This interaction failed". Pressing the button edits the embed to change it to another. How would I get rid of that interaction failed message after pressing a button?
the issue: https://i.stack.imgur.com/i4dTd.png
code received from: https://github.com/elixss/YouTube/blob/main/source/buttons.py
Here is the code:
#bot.group(invoke_without_command=True)
async def help(ctx):
# buttons
one = Button(style=1, label="Commands", id="em1")
two = Button(style=1, label="Depression", id="em2")
three = Button(style=1, label="Moderator", id="em3")
four = Button(style=1, label="Language", id="em4")
# embeds
em1 = Embed(title="Commands Plugin",color=0x5865F2)
em2 = Embed(title="Depression Plugin", description="placeholder", color=0x5865F2)
em3 = Embed(title="Moderator Plugin", description="placeholder", color=0x5865F2)
em4 = Embed(title="Language Plugin", description="placeholder", color=0x5865F2)
# main help embed
help_embed = Embed(description="> **Help Module**\nPress on any button to view the commands for that selected plugin.",
color=discord.Color.random())
# buttons to embeds
buttons = {
"em1": em1,
"em2": em2,
"em3": em3,
"em4": em4
}
msg = await ctx.send(embed=help_embed,
components=[[one, two, three, four]])
while True:
event = await bot.wait_for("button_click", timeout=60.0)
if event.channel is not ctx.channel:
return
if event.channel == ctx.channel:
response = buttons.get(event.component.id)
await msg.edit(embed=response)
if response is None:
await event.channel.send("error, try again.")
As Elias said, you have to response to interactions, else it will show "This interaction failed", but not with a regular ctx.send() but with (in your case)
await event.respond(type=4, message="Responded!")
If you don't want to send a message as a response to a button click or selection in a select, you can just use type=6 without message:
await event.respond(type=6)
For more types, see the documentation.
The best way to do this is to either remove all buttons after it's been pressed, or add a cooldown that will remove the buttons automatically after a certain time.
In your situation, it would look something like this:
msg = await ctx.send(embed=help_embed, components=[[one, two, three, four]])
try:
res = await client.wait_for("button_click", timeout = 60)
except asyncio.TimeoutError:
await msg.edit(components = []) #removes buttons from message
else:
if res.author == message.author:
#when button is clicked
await msg.edit(components = [])
This also prevents being rate limited, so you don't have buttons constantly waiting for a response.
im new to discord py i want a command that will send a random image from a file and send it but i can get it to work i tried to use Discord bot to send a random image from the chosen file one but still could not get it to work so then i tried this but i still no work if anyone can help me plz do
#put your images into the image folder
#images that are uploaded will be moved to the sent_images folder so they won't be reposted
import discord,os,random,asyncio
from datetime import datetime
from discord.ext import commands
bot=commands.Bot(command_prefix='!')
send_time='12:00' #time is in 24hr format
image_channel_id='ChannelID' #channel ID to send images to, replace with your channel ID
image_types=('.jpg','.png','.gif','.jpeg') #add image types if needed
folders={'Image Folder':'images','Sent Folder':'sent_images'}
for folder in folders.values():
if not os.path.isdir(folder):
os.mkdir(folder)
#bot.event
async def on_ready():
print(bot.user.name)
print(bot.user.id)
async def send_image():
for item in os.walk('./{}'.format(folders['Image Folder'])):
images=list(pic for pic in item[2] if pic.lower().endswith(image_types))
if len(images) == 0:
await bot.send_message(image_channel,"Oops! I'm all out of images to send. Notify my owner!")
else:
image= random.choice(images)
await bot.send_file(image_channel,'./{}/{}'.format(folders['Image Folder'],image))
os.rename('./{}/{}'.format(folders['Image Folder'],image), './{}/{}'.format(folders['Sent Folder'],image))
async def time_check():
global image_channel
await bot.wait_until_ready()
image_channel=bot.get_channel(image_channel_id)
while not bot.is_closed:
now=datetime.strftime(datetime.now(),'%H:%M')
if now == send_time:
await send_image()
await asyncio.sleep(60)
bot.loop.create_task(time_check())
bot.run('TOKEN')```
From your question, I understood that you have a bunch of folders with a bunch of images in them and you want to make a command that sends a random image.
import os, random
#bot.command()
async def random_image(ctx, category: str = None):
root_dir = os.listdir('./images')
# If the user doesn't specify a category send a random image from a random folder
if category is None:
# Getting a random directory and file
dir = random.choice(root_dir)
image = random.choice(os.listdir(os.path.join(root_dir, dir)))
path = os.path.join(dir, image)
elif category in root_dir:
# Getting a random file from the category
image = random.choice(os.listdir(os.path.join(root_dir, category)))
path = os.path.join(dir, image)
else:
await ctx.send("Couldn't find that category")
return
# Sending the image in an embed
file = discord.File(path)
embed = discord.Embed(title=category.title(), colour=discord.Colour.greyple())
embed.set_image(url=f'attachments://{image}')
await ctx.send(file=file, embed=embed)
{prefix}random_image ← will send a random image from a random dir
{prefix}random_image dog ← will send a random image from ./images/dog dir
Let me know if that's what you were asking for.
#bot.command()
async def random_image(ctx):
Images = ['./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png',
'./Folder/Image_Name.png']
await ctx.send(file=discord.File(f'{random.choice(Images)}'))
I am using the Discord API to make a bot that changes the role colour. When I run this code it produces no errors but does not change the color
import discord
import time
from discord.ext import commands
bot = commands.Bot(command_prefix='>')
colors = [0xFF0000, 0xF0A804, 0xFFFF00, 0x008000, 0x0000FF, 0x800080]
#bot.command()
async def rainbow(ctx):
username = ctx.message.author
print(username)
roleid = 123
role = discord.utils.get(username.guild.roles, id=roleid)
await username.add_roles(discord.utils.get(username.guild.roles, id=roleid))
await ctx.send('You found the Rainbow!') # (The rainbow hates you)
for i in range(6):
await role.edit(colour=discord.Colour(colors[i]))
time.sleep(0.5)
print(colors)
await username.remove_roles(discord.utils.get(username.guild.roles, id=roleid))
bot.run('bot token')
I'm having this problem as well. I've noticed that whenever you modify a role, after some time, you will no longer be able to modify it anymore for some reason. I'm still trying to figure out why.
I'm not really accustomed to writing the UI in the code, so I need a few pointers.
I'm trying to create a simple, horizontal scrolling dialog on my N900, but I can't figure out how to do this.
This is what I have so far:
def __init__(self,parent = None):
QDialog.__init__(self,parent)
#if name == None:
self.setWindowTitle('Testing scrolling')
self.scrollArea = QScrollArea(self)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setMinimumSize(100,150)
self.aWidget = QWidget(self.scrollArea)
self.aWidget.setMinimumSize(20,200)
self.aWidget.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding)
self.scrollArea.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding)
self.scrollArea.setWidget(self.aWidget)
scroller = self.scrollArea.property("kineticScroller").toPyObject()
scroller.setEnabled(True)
_layout = QGridLayout(self.aWidget)
_layout.setSpacing(60)
_layout.setMargin(11)
_layout.addWidget(QPushButton('Test0'),0,0)
_layout.addWidget(QPushButton('Test1'),0,1)
_layout.addWidget(QPushButton('Test2'),0,2)
_layout.addWidget(QPushButton('Test3'),0,3)
_layout.addWidget(QPushButton('Test4'),0,4)
_layout.addWidget(QPushButton('Test5'),0,5)
_layout.addWidget(QPushButton('Test6'),0,6)
Pls, check if an example below would help you out, it should create a dialog with horizontal scroll area and buttons in it.
class MyDialog(QDialog):
def __init__(self,parent = None):
QDialog.__init__(self,parent)
self.setWindowTitle('Testing scrolling')
self.setGeometry(250, 200, 350, 400)
widget = QWidget()
widgetLayout = QHBoxLayout()
for i in range(0, 25):
button = QPushButton("test button {0}".format(i))
widgetLayout.addWidget(button)
widget.setLayout(widgetLayout)
scrollArea = QScrollArea()
scrollArea.setWidget(widget)
dialogLayout = QVBoxLayout()
dialogLayout.addWidget(scrollArea)
self.setLayout(dialogLayout)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dlg = MyDialog()
dlg.show()
sys.exit(app.exec_())
hope this helps, regards