#Basic Pycord Help
1 messages Β· Page 64 of 1
idk if the everyone tag even works for threads, but direct mentions and role mentions (under 500 members) do
yeah the way i was thinking of setting it up was to tell people if they want notifications to just click this
so that way we could get around having to use roles for mentioning
but it doesnt seem to alrert the same way, like it doesnt have the red badge
oh i didn't even know that existed
but yeah it only sends a notification without mentioning the user or making them join the thread
which is kinda what i want
because otherwise then their left hand sidebar would just get flooded
Application Commands Not Showing Up?
- Refresh Discord by restarting or pressing
Ctrl+R(orCommand β + R) - Uninstall libraries that conflict with the
discordnamespace (e.g.discord.py). - Invite your bot with the
application.commandsscope. - Load cogs before
bot.run()(e.g. not inon_ready). - Do not override
on_connect. - Update to the newest version of
py-cord(see?tag install). - Turn off
User Settings > Accessibility > Chat Input > Use legacy chat input. - Share your code and errors.
you can use ``` for multiline codeblocks
You can define your embed outside of the command btw
since it dosen't change between comman inokations
Idek what that means π€£
Had this bot made for me, but now trying to add a single simple new /slash command that just gives the member updates on what's to come
@echo wraith Here u go π
thy
And this is the thing I'm trying to get added pretty much
this code is not pycord code
What then?
@bot.command(name="menu", description="Open the methods menu")
async def menu(interaction: discord.Interaction):
idk
this is not pycord.
I did pip show py-cord, says It's pycode
Also the code is messed up, it uses blocking code
I hope if you paid you didn't pay much for that...
yeah
damn
you got kind of scammed there
yeah true
So since the bot code is so messed up, I won't be able to add this new code / feature to it?
I'll do some cleanup for you.
How's it coming along @echo wraith
The more I look at the code the more messet up it looks
It should probably in theory, but I can't test it out and understand why it wouldn't work if the code is all over the place.
Damn okayπ
I think the issue I'm having is the /slash command not showing after i do CTRL+C and then doing Python main.py
https://paste.pythondiscord.com/GGSA
try with this. You will need to
pip install python-dotenv aiofile
in your terminal first
and create a file called .env in the root, containing th eofllowing
TOKEN=<your bot token here>
testing π
works on my side btw
pip install typing_extensions too
what is your python version
Python 3.11.9
yeah then you need to install typing_extensions
python main.py π
Some error
means your bot token is invalid
Just double checked, it isn't
Yeah, let me do that
1. Uninstall discord.py or any other forks of discord.py you might have with the namespace discord.
python -m pip uninstall discord.py discord -y
2a. Install py-cord
python -m pip install py-cord
2b. Update py-cord
python pip install -U py-cord
Installing other builds:
Note: You need to have git installed. Use ?tag git to find out how to install git.
Updating the module to master branch (unstable):
pip install -U git+https://github.com/Pycord-Development/pycord
just to be sure
So first;
python -m pip uninstall discord.py discord -y
Then;
python -m pip install py-cord
And lastly;
python pip install -U py-cord
update the token in the .env file
and save that file too
you don't need the < >
also, please delete that picture
It's online
/menu is showing and works, but not /upcoming
for the commands to show
Ohh wait
Yeah now it works
Thank you so so much @echo wraith
Really appriciate it
Oh wait
some of the /menu doesn't work
π alr alr
keep it as is, just change json.load to json.loads with an s
keep the await and all
Works perfect now man, thank you so much π
happy to help !
Is it possible to have multiple default emojis for a thread, or disable them all together and have the bot add 2 every time a thread is created?
the second option is possible afaik
Yeah it seems like on the forum view it still only shows one at a time βΉοΈ
yes
trying to play with this... whats the proper way to react on a thread?
thread = await channel.create_thread(name=thread_name, embed=embed, applied_tags=tags, auto_archive_duration=auto_archive_duration)
# Add Verify and Invalid reactions to the thread
await thread.add_reaction("β
")
I think you need to react to the original message
does the default emoji on the thread automatically sync to the first message?
ah nvm got it thanks! - looks to be so
thread = await channel.create_thread(name=thread_name, embed=embed, applied_tags=tags, auto_archive_duration=auto_archive_duration)
message = await thread.fetch_message(thread.id) # Fetch the first message of the thread
# Add Verify and Invalid reactions to the thread
await message.add_reaction("β
")
playing with this some more and seeing some pretty weird behavior, when i do this
message = await thread.fetch_message(thread.id) # Fetch the first message of the thread
await message.add_reaction("β")
await message.add_reaction("β
")
On the discord desktop app it shows the last reaction (the green check) as the default, but on the mobile app it shows the first X as the default?
you might have a default emoji set, and the client is handling it wrong
Also, instead of making an api call you can use get_partial_message
.rtfm Thread.get_partial
When I try to install py-cord 2.6.1, I get this error:
building 'aiohttp._websocket.mask' extension
error: Microsoft Visual C++ 14.0 or greater is required.
I went and downloaded what I thought was needed from the MS build tools and restarted, but it's still showing this error. Is there something else I need to install?
Using Python 3.12.8
SOLVED: I installed the ARM version of Python and after switching to the regular Windows x64 release, the py-cord install worked fine and I didn't need anything additional from Visual Studio.
Hi, this piece of code splits options into multiple select menus to adhere to the limit of 25 options per menu:
def create_select_menus(self, options):
MAX_OPTIONS = 25
option_chunks = [options[i:i + MAX_OPTIONS]
for i in range(0, len(options), MAX_OPTIONS)]
print(len(option_chunks))
for i in option_chunks:
print(len(i))
select_menus = []
for idx, chunk in enumerate(option_chunks):
select_menus.append(discord.ui.Select(
placeholder=f"Menu {idx + 1}",
min_values=1,
max_values=1,
options=[discord.SelectOption(
label=option, value=option) for option in chunk]
))
return select_menus
From the output, there are a total of 5 select menus (which is the limit) for this interaction and total of 124 options:
5
25
25
25
25
24
yet i'm receiving DiscordServerError: 500 Internal Server Error (error code: 0): 500: Internal Server Error..?
typically if you get 500 its not your fault
well, i did try this exact same command which had 50 or so options and that one doesn't throw this error, so i assume it had to do something with running too close to the limit or something
oh, i think you can only have 5 UI rows on one message, and you have 6
weird that that gives a 500 tho
No, the first print which shows 5 is the number of select menus
these are the number of options per select menu:
25
25
25
25
24
i did some further testing by truncating the list of options, this works:
25
25
25
25
19
but this doesn't:
25
25
25
25
20
This is very likely some bug or it's a discord limit that i may not know of?
if anything its a discord bug
is paginator.update() not too kind with ephemerality?
paginator = Paginator(
pages=mypage, timeout=898, author_check=False)
class MyModal(discord.ui.Modal):
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.add_item(discord.ui.InputText(
label="Enter Page number:"))
async def callback(self, interaction: discord.Interaction):
page_num = int(self.children[0].value)
try:
await paginator.goto_page(page_num-1)
except IndexError:
await interaction.response.send_message("Invalid page number.", ephemeral=True)
class MyView(discord.ui.View):
@discord.ui.button(label="Switch page", row=1, style=discord.ButtonStyle.primary)
async def button_callback(self, button, interaction):
await interaction.response.send_modal(MyModal(title="Travel to your desired page."))
await paginator.update(custom_view=MyView())
try:
await paginator.respond(ctx.interaction, ephemeral=get_ephemeral_setting(ctx))
except discord.Forbidden:
return
except discord.HTTPException:
return
got this thing which throws AttributeError: 'NoneType' object has no attribute 'edit'
yea ephemeral messages are a bit weird so there's a change that function doesnt account for that
I have a pr open but it is not for this issue afaik. I will open another, can you just send me a short minimal reproductible example ?
The code I appended is pretty much that. Basically there's the default paginator instance and i am appending a button (for modal) in the second row using the paginator.update() method, and goto_page() to travel to the page number.
Also, something related:
I tried enclosing paginator.update() in a try-except block, but i just do nothing in the except block. This allows me to get the combination that I want even in ephemeral state (in the screenshot below), however when goto_page() is invoked in the callback, this error is thrown: discord.errors.NotFound: 404 Not Found (error code: 10008): Unknown Message
is there a reason an InputText returns different values for self.children[0].value and self.children[0].to_component_dict()['value']
putting in an self.children[0].value = self.children[0].value seems to fix it but it's a little weird
like what two values do you get
self.children[0].value returns the value after the modal is submitted but self.children[0].to_component_dict()['value'] returns the value it was initialized with
and if value wasn't set during creation, it doesn't exist in the dict
to_component_dict is used internally for sending the data to discord iirc
it was just a command the IDE popped up with that seemed to fit what i wanted
i just assumed it was from a parent class
yeah, It probably should be private. It is working as intended, and it is not intended to be used externally from the lib
it's literally one of the first things pycharm brings up lmao
but got it, not intended to be used
but back to the other part of it, why does self.children[0].value = self.children[0].value cause anything to happen at all?
just an update if anyone is interested, passing interaction parameter to both update() and goto_page() and enclosing them in try-except blocks provides a workaround fix for ephemerals
adding this in causes the value to be used as the new default value when the modal is reused. but the value is reset to the original otherwise
I have no idea why this would change anything.
It could be a weird quirk with how the setters work on value
Yeah, I looked closer .value is never supposed to be assigned externally either
so i suppose the intended method would be to delete and replace the InputText instead?
or i guess at that point there isn't much reason to reuse the modal
i just thought it was a handy feature that setting value to itself would keep its values between uses
when you click the little [source] button next to InputText in the docs, it does seem to have a setter. and to_component_dict() is there too
but yeah i can see where the weirdness comes from now that i've read through it all
but imo value shouldn't be being reused for two different things (_input_value and _underlying.value) depending on the context. it's a bit confusing
it's probably a minor oversight, if you think the behaviour should be different then submit a PR.
hi, i know nothing about coding and stuff, i need help on downloading pycord
pip install py-cord
and if you're brand new to programming I highly recommend doing some very basic stuff in python first and not to start with py-cord as your first thing ever
@halcyon totem
yeah, you should create your own programming language first to get familiar with the tech before using python /s
would someone be willing to help me with a small issue, I shortened my bot to the straight basics, it has a cog with a \ping command, I enter a discord_token_for_test_server the ping is available and works but when I just switch discord_token_for_real_server ping command isn't listed and doesn't work, does anyone have any idea why this would occur ? (if you think I should create a new space on the forum let me know)
did you reload discord
can you show the command code
import discord
from discord.ext import commands
from discord.ext.commands import Context
from loguru import logger
class Fun(commands.Cog):
def __init__(self, bot):
self.bot = bot
@commands.slash_command(name="ping", description="Check if the bot is alive.")
async def ping(self, ctx):
await ctx.respond(f"Pong! thanks for checking on me {ctx.author.mention} !")
def setup(bot):
bot.add_cog(Fun(bot))
can you show your main file
it's irrelevant to their issue
as for the import question I shortened the bot here and removed a ton of stuff so this is still here cause it as used before but not rn
does it show up in guild settings > integrations
see if it has any commands listed there
reinvite with the applications.commands scope
though bot is meant to include that by default
see lara has slash command stuff
reinvite it
ok
sorry if I sound dum which scope should I take appart from bot, I always forgot ?
is only bot enough ?
bot and application.commands
it's included by default, but try add applications.commands
thank you
this didn't worked but that's definitely the issue
cause I have the slash command icon on my test server
maybe I'll jsut fully recreate it on dev portal
eh... did you ever set guild_ids on any commands?
I didn't
try changing the command name and restart the bot again
and restart discord if you havent yet
I did
I'll try to change command name
changing the command name indeed worked
could it be a conflict issue with an already existing bot ?
no
that what I thought, still the behavior is kinda strange
I'll dig into it and see if I can see where this comes from
discord generally refers to commands by their name, so changing the name forces them to recognise it as a new command
discord's entire backend is strange
ok well thank you I'll keep that trick in mind if that ever happens again
(though this is also somewhat the fault of our syncing method)
when I get my bot up and running as I want it I think I'll dig into pycord core
see how it's made
I'm sure I'll learn a lot of stuff
I'd say most of it is kind of just replicating Discord stuff like, well, guilds, channels, etc
i mean thats kind of the point of the library lol
yes I was more talking about the way to communicate with the discord api and such
http requests :]
eh... maybe at the request level, but "replicating the library" is pretty broad
You know what I mean
looking into any library to see how it works is worthwhile
thank u
yea
just need to solve some docker issues now , thanks again for the help see ya !
which permission should I use for bridge commands?
wdym?
discord.default_permissions or the basic one
ah, no idea
I mean iirc you can use that
Default perms
As it's discord.permissions object no?
and that object just gives out bools
Sooooo theoretically if you know what the bools values are gonna be you can even input them manually \o/
doesn't that just ... Wait hold on a min.
xd
I have a list of users that the bot is intended to send DMs to and the basic function layout is like this
async def functionName(ctx):
ctx.defer()
for u in usersList:
x = await get_or_fetch_user(u)
x.send("hello")
ctx.followup.send(f"sent message to {x.name}")
asyncio.sleep(4)
ctx.followup.send("sent messages to everyone")
My idea was if I wait 4 seconds between fetches + sends, I'd be able to make 30 requests to the discord api per minute to avoid being rate limited. The problem I'm facing now is that the bot stops are 45 DMs but there's no error messages in the console. How do I go about bettering this? Thank you for your time!
You will just get your bot flagged for mass dming
Don't do that
Even with the users consent? They use a /join and that's how I get a list.
I'm not spamming them with ads or anything malicious. It's a secret santa bot so dms are somewhat necessary for secrecy reasons
If you dm more than 50 people in less than an hour you will more likely be flagged I think
mee6 easily DMs 500 a minute
Traceback (most recent call last):
File "/home/container/.local/lib/python3.12/site-packages/discord/ui/modal.py", line 341, in dispatch
await value.callback(interaction)
File "/home/container/cogs/ticket.py", line 182, in callback
await cog.create_ticket(interaction, self.name.value, self.problem.value)
File "/home/container/cogs/ticket.py", line 293, in create_ticket
await interaction.followup.send("You already have an open ticket!", ephemeral=True)
File "/home/container/.local/lib/python3.12/site-packages/discord/webhook/async_.py", line 1794, in send
data = await adapter.execute_webhook(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/container/.local/lib/python3.12/site-packages/discord/webhook/async_.py", line 222, in request
raise NotFound(response, data)
discord.errors.NotFound: 404 Not Found (error code: 10015): Unknown Webhook```
Itβs a verified bot
just sending an error here with zero explanation isnt how you get help
pls include the relevant code, but at a glance use interaction.respond instead of followup; it handles send_message/followup for you
Does https://docs.pycord.dev/en/stable/api/abcs.html#discord.abc.Messageable.typing not automatically end with ctx.respond?
An abstract base class(also known as an abc) is a class that models can inherit to get their behaviour. Abstract base classes should not be instantiated. They are mainly there for usage with isinst...
This is my code, but it keeps typing for a few seconds or so after the respond
yea im also a bit unsure how to handle this rn because my command is kinda weird
lol
probably a dumb thought anyway
so ig typing only goes away with a .send?
What I really wanna do isn't really possible.. I kind of have just an LLM chatbot in my bot
currently i do it with a slash command and the result looks like this
which is kind of annoying to decouple in the code, the user-part and the bot-response part
It should technically stop typing after the with block ends
i thought of doing it with pings, but idk, i kinda like doing it with a slash command
well, it stays until ~10s total have passed i think
which i thought it only does with trigger_typing
either way im really unsure whether a slash command or an @bot hello would be best
tho my users are used to the slash command now
soory
in my testing typing state does go away after respond
(strictly speaking discord handles that)
weird
how long on average does your typing block take
2-3 seconds at most
hmmm this is kinda silly but you could attempt to manually cancel the task py async with typing() as t: ... await t.task.cancel()but this shouldn't be necessary because your code takes under 5s and the respond should have it naturally end anyway
you could change it to trigger_typing and not bother with the typing block; that's only necessary if the code takes more than 10s
can somebody send me the docs for peristent views? trynna make a button work after bot restart
Here's the persistent example.
thanks!
can somebody tell me how i can set optional options for commands cause i couldnt find anything about it
required = False
thanks π
Hey everyone. I'm a lil dumb. Basically I'm trying to make a command that creates a new post in a forum channel. So, the command is executed in a forum post, which gets that post's parent (the forum), and creates a thread. I know usually it needs a starting message. I tried using the ...create_thread(name="test", message="test")but its not valid, neither is type. Pls help.
async def test(ctx):
print(ctx.channel.id)
main_channel = ctx.channel.parent
print (main_channel.id)
await main_channel.create_thread(name="test", auto_archive_duration=60)```
I made a bot to give a role to online members and sync on message in a channel. It worked for my test server but didn't work for main server which is bigger. There is no perms or intents issue.
This is the code.
Does the server size have a impact on this ?
The target role in main server is a moderator role which has only 17 members
"didn't work" means what?
did you make sure to change the role IDs when changing servers first of all? hardcoded IDs are a nightmare
what error do you get
Means it does record the message event but no role changes. Yeah I changed all server and role ids correctly
I also put a print message for on message to check if it gets triggered
does your bot have all the permissions
and is its role above the to be assigned role
It's admin and above all roles
In both servers
Also intents is set to all and all intents are enabled
I believe this is related to server size
The main server has 215k+ members and test server had just 7 (my accounts and some bots)
do you get any error or anything at all?
Nope
and no roles are ever assigned or removed
Nope. All logs are clean
are you triple sure you got all the IDs right
100%
I changed all one by one
All 4
Even added a print function to print that it actually recd the message event and it prints that it did
and do the prints inside the ifs print too?
The for member in target role ?
I will make it print all members in mod role with their status
no, you have prints for "assigned role to name" and "removed role from name"
do those work
Yes those work
Those were printed for test server
It correctly assigned and removed everytime
can you print your assigned_role
Okay. I will add that and try
but you are testing it with other people and not yourself (if you are the owner) right?
It's for moderator role. So it would assign online moderator role to PPL in moderator role who are online in main server
That's what I want to achieve
yea i know, i just wanna make sure you test it with a member that isnt you if you own the server
bots cant do a lot of stuff on server owners
I am not owner in any. Although bot has second highest in main but it's above both roles and even actual online mods were not assigned
Also no error in console confirms no perms issue
unless you have a global error handler that eats the errors silently somehow lol
I'll get more logging
Like log everyone in mod role and print the status. To see what's actually the problem
Attribute errors or 404s
show the error
code looks fine as long as it's executed in a forum thread (or well, it works in a normal channel too I think)
oh wow. I changed nothing. went home and just ran it again. it works now π
lol
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 138, in wrapped
ret = await coro(arg)
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 1082, in _invoke
await self.callback(ctx, **kwargs)
File "c:\Users\Usuario\Desktop\Bot Dev\vote2.py", line 16, in test
await main_channel.create_thread(name="test", auto_archive_duration=60)
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\channel.py", line 1319, in create_thread
data = await state.http.start_forum_thread(
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\http.py", line 374, in request
raise HTTPException(response, data)
discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In message: This field is required
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\bot.py", line 1137, in invoke_application_command
await ctx.command.invoke(ctx)
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 435, in invoke
await injected(ctx)
File "C:\Users\Usuario\AppData\Local\Programs\Python\Python310\lib\site-packages\discord\commands\core.py", line 146, in wrapped
raise ApplicationCommandInvokeError(exc) from exc
discord.errors.ApplicationCommandInvokeError: Application Command raised an exception: HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In message: This field is required```
You need to provide some sort of content, embed, attachments or etc
https://docs.pycord.dev/en/stable/api/models.html#discord.ForumChannel.create_thread
Models are classes that are received from Discord and are not meant to be created by the user of the library. Attributes key, url. Methods def is_animated, async read, def replace, async save, def ...
has anyone used testcord with pycord?
It would most likely not work
unfortunate
yeah but I would like to have it to make sure things are going into the data base correctly and I don't make an error when I change something, retesting everything by hand is a pain in the butt.
then verify the data in your db connector
Kind, does anyone know of any known issues related to the fact that discord.ui.Select().add_option(). It just stops the thread execution and the bot just doesn't respond to the command.
Now it is just in async def ApplicationCommand, maybe this is the reason, because in another command it works calmly from class foo(discord.ui.View).
Naturally this is not straight discord.ui.Select().add_option().
mselect = discord.ui.Select()
mselect.add_option(label=str(some<100),description=str(some<100), value=str(some<100))
It turns out add_option() doesn't do argument conversion or does it incorrectly.
I lied a bit above by writing value=str(some<100) because the int with role id was passed to value, which caused a hang. Actually adding str() fixed the problem.
because snowflake ID ints are too long for the type of integer discord uses
thats why they have to be passed as strings
@meager mantle
Hi, How can i translate commands?
when i do /rank in a english server and /rang in a german server
its never server dependent, it depends on user locale
https://docs.pycord.dev/en/stable/api/application_commands.html#discord.SlashCommand look at the _localizations here
Command Permission Decorators: Commands: Shortcut Decorators: Objects: Attributes full_parent_name, qualified_id, qualified_name. Methods@ after_invoke,@ before_invoke,@ error, def get_cooldown_ret...
same for command options
ah nice thx
If I want for some reason to make requests to the api in a raw manner, as long as I do it trough httpclient they are rate limited correctly ?
Through pycord's HTTPClient.request method? Yes
anybody have experience using environment variable to enable/disable commands? something like this:
# .env
ENABLED_COMMANDS=slash_command_1,slash_command_2
# config.py
import os
from typing import List
def get_enabled_commands() -> List[str]:
commands_str = os.getenv('ENABLED_COMMANDS', '')
return [cmd for cmd in commands_str.split(',')]
# bot.py
from config import get_enabled_commands
def setup(bot):
enabled_commands = get_enabled_commands()
bot.add_cog(AdminCog(bot, enabled_commands))
# main.py
from dotenv import load_dotenv
load_dotenv()
yeah not sure whats going on there lol it would just be [cmd for cmd in commands_str.split(',')]
also you dont need to import List from typing since like, 3.10 or something
i didn't write this code, 4o did
i'm just asking about being able to use environment variables to toggle enabled commands
i mean sure you can
are there code examples?
no, this isnt really something common to do lol
is there a better way to easily enable/disable commands in production without rebuilding the image?
wdym rebuild the image
you'll most likely need this and this, and you probably need to sync commands after doing that as well
Bots: Attributes activity, allowed_mentions, application_flags, application_id, auto_sync_commands, cached_messages, cogs, debug_guilds, default_command_contexts, default_command_integration_types,...
the easier way is probably just to raise an error whenever a disabled command is called (within each command) then respond to that appropriately in your error handler
but with those functions the commands will be completely removed from view
yeah that would be easier but i'd rather have the command not show up at all if possible
HI;
async def update_rate(self, ctx: discord.ApplicationContext):
xp_rate = await level_db.fetch_rate(ctx.guild.id)
timestamp = ctx.message.created_at
print(timestamp)```
Ignoring exception in on_application_command_error
Traceback (most recent call last):
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 138, in wrapped
ret = await coro(arg)
^^^^^^^^^^^^^^^
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 1078, in _invoke
await self.callback(self.cog, ctx, **kwargs)
File "g:\Development\Python\Xenority\extensions\level\main.py", line 455, in update_rate
timestamp = ctx.message.created_at
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'created_at'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\client.py", line 412, in _run_event
await coro(*args, **kwargs)
File "g:\Development\Python\Xenority\extensions\error_handler\main.py", line 121, in on_application_command_error
raise error
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\bot.py", line 1137, in invoke_application_command
await ctx.command.invoke(ctx)
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 435, in invoke
await injected(ctx)
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 138, in wrapped
ret = await coro(arg)
^^^^^^^^^^^^^^^
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 1486, in _invoke
await command.invoke(ctx)
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 435, in invoke
await injected(ctx)
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\commands\core.py", line 146, in wrapped
raise ApplicationCommandInvokeError(exc) from exc
discord.errors.ApplicationCommandInvokeError: Application Command raised an exception: AttributeError: 'NoneType' object has no attribute 'created_at'
applocation command has no associated message
it does, but only in some cases
you can find when an interaction was sent with discord.Object(ctx.interaction.id).created_at
message is only set on component interactions
what about a defer?
that is not a component interaction
yea but isnt the defer counted as message?
does it?
im 99% sure its included in channel.history (i know cuz of a command i have)
that has nothing to do with the context's message attr
ApplicationContext.message shortcuts Interaction.message which uses this value
hm ok weird
Why its not ehp?
# Leaderboard Befehl mit Paginator
@level_cmd.command(name="leaderboard", description="Zeige die Rangliste an.")
async def leaderboard(self, ctx):
await ctx.defer()
guild_id = ctx.guild.id
all_levels = await level_db.fetch_all_levels(guild_id)
all_levels = [level for level in all_levels]
if len(all_levels) == 0:
await ctx.respond("Es gibt noch keine Benutzer in der Datenbank.", ephemeral=True)
return
# Sortiere nach Level und XP
all_levels.sort(key=lambda x: (x["level"], x["xp"]), reverse=True)
# Bereite Seiten vor
pages = []
for i in range(0, len(all_levels), 10): # 10 Benutzer pro Seite
description = "### Rangliste der Top-Benutzer \n\n"
for j, level in enumerate(all_levels[i:i + 10], start=i + 1):
user = ctx.guild.get_member(level["user_id"])
if user:
##description += f"`{j}.` {user.mention} Level **{level['level']}** XP **{level['xp']}**\n"
description += f"{j}. {user.mention} - Level: {level['level']} | XP: {level['xp']}\n"
embed = await self.create_embed(
ctx,
title="XP Rate",
description=description
)
pages.append(Page(embeds=[embed]))
# Paginator starten
paginator = Paginator(pages=pages)
await paginator.respond(ctx.interaction, ephemeral=True)```
because you deferred without ephemeral=True
await paginator.respond(ctx.interaction, ephemeral=True)
Your defer isn't ephemeral
The response won't be ephemeral if your defer wasn't
ohhh
Here's the persistent example.
@hardy abyss you need to use persistent views. See the example above
select = Select(placeholder="test", options=role_options)
is it possible to say i can select all values in teh dropdown
The library has helpers to help create component-based UIs. Shortcut decorators: Objects: Attributes children, disable_on_timeout, message, parent, timeout. Methods cls View.from_message, def add_i...
please read the docs
When a guild isn't chunked and I try to create a role in it, the attempt fails with a forbidden error even though the bot has the required permissions. Is there a way to create the role even if the guild isn't chunked?
you shouldn't get forbidden as long as you have proper permissions
The code is pretty much just what's below, but users sometimes have to wait an hour or so for the guild to be chunked before the role is created. They send screenshots that the bot has the manage roles permission enabled and after not changing any permissions it works after waiting for the guild to be chunked.
try:
await guild.create_role()
except discord.errors.Forbidden:
# Send the user a message it didn't work.
and guild there is ctx.guild?
Yes
what if you fetch the guild?
Yeah good point, I just thought of that lol. I'll have to try it and see if it helps
Hastebin is a free web-based pastebin service for storing and sharing text and code snippets with anyone. Get started now.
Traceback (most recent call last):
File "C:\Users\jurek\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\site-packages\discord\ui\view.py", line 426, in _scheduled_task
await item.callback(interaction)
File "g:\Development\Python\Xenority\extensions\level\main.py", line 650, in add_channel_select
embed = await Levelsys.LevelSetupEmbed(Levelsys, interaction)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "g:\Development\Python\Xenority\extensions\level\main.py", line 607, in LevelSetupEmbed
embed = await self.create_embed(
^^^^^^^^^^^^^^^^^^
TypeError: Levelsys.create_embed() missing 1 required positional argument: 'ctx'
can where help me im confuse how can i fix this
You did not include the create embed function. My guess is you forgot to include self as the first parameter of that function
is on_ready() but in a cog a thing? or would on_ready() just work in a cog
i have a self.something variable i'm setting in __init__ of the cog but it's not being filled properly because it runs too early (i think)
can you show the code
__init__ is run the moment you load_extension/load the cog; assuming you load cogs before the bot starts, this is always before on_ready
tbh i just moved the line from the command code to __init__ and tacked on a self. so it wouldn't repeat the line across all commands
idk if this is the right way to do this but it workedβ’ before and doesn't now
so this'll result in logchannel being None
yeah that's exactly what i'm getting
because get_channel doesn't work before the bot's started
(if it isn't the right way please enlighten me)
if you want, you can have an individual on_ready listener in your cog using the @commands.Cog.listener() decorator
(but you should make sure to define in both init and on_ready since reloading the cog won't run on_ready again)
though, what i personally like to do is set @property for objects i frequently access across the cog ```py
@property
def guild(self):
return self.bot.get_guild(SOME_ID)
(reloading the cog?)
do you ever reload_extension
it reloads a cog and the code for the listeners and commands inside it
so you don't have to restart for purely code changes, though sometimes it's finnicky with slash commands and if you want to update command metadata like names/options you still need to restart
that's just accessed with self.guild?
if so what's the point of making a property instead of just self.get_guild()
probably just looks better .guild.name rather than .get_guild(SOME_ID).name
just for convenience across commands
guild was probably a poor example because most of the time you're using ctx.guild anyway
but if there's a common cached resource i'm accessing in a cog then setting properties is nice
yea but I'm wondering what the proper benefit is because get_thing() and thing() isn't really that much different
or what do you use it for
there isn't, i just prefer self.thing vs self.bot.get_thing
90% of coding decisions is just preference
properties are 100% builtin right?
yeah
Yes
Is this good for automatically creating commans or is there a better approach?
i tried just defining it with the decorator inside of the create_social_command function but it didn't do the trick
and im struggling to pass the cog correctly, no matter how i try it, ctx.command.cog is None
setting command.cog = self causes some weird error, and setting command._cog directly causes an error upon command invocation
overall i just cant find the intended way to do this apart from decorators which i (seemingly) cant use lolw
Okay i managed this now.. is this an IDE error? type(command_function) is SlashCommand, so its correct
ok apparently setting the cog can be achieved like this
this is inside of a function
I kinda do the same with name and description adding, I dont have to add it to every command anymore
also with decorators in a function?
I use bot._pending_application_commands for it
create custom slash commands is the weird thing for me
your method is correct
like it doesnt make a lot of sens since it will be block pretty easily if its a public bot and if its not create prefix seems more logical since you will not have any limite and user will not have to restart their discord
but else if it works it works
The only reason I'm doing this because before, i had about 30 commands that were all the exact same save for a few strings
im not creating them during runtime
why not making a command like /action with an autocomplete after ?
yea i thought about that too but that would've required me to have the same mapping of a bunch of strings i already have like this, so i thought might as well do it the fancy way and keep the commands seperate
ok i see
any idea how should i format my tree ?
because rn i feel like its messy
eh, seems fine? unless you want to subdivide into even more folders
each folder inside the slash has like
some of my issue are for exemple i have a folder name event where i put some config but not all of them are event
like there is some cog to check if there is some blocking code, some other to just wrap all the istener to check if there is an error and get it etc
yes
I forgot to respond earlier
but yes, that's how you should do it
why do you have a single folder for every command
that's not really how cogs are intended lol
its a folder for each group of command
and i have a file for each command because i find it more clear
yea, IMO you divided everything much, much too far
at the very least you can put all subcommands into a single cog
also makes them easier to manage and you dont need multicog
nah that will be way too much messy consiering the length of the command
unless its >300 lines its fine imo
i have a custom thing that make everything os i dont really have to do anything with multicog or bridge
it is more
also some of my other issue is my yaml file that is 10k line...
10k for french, then 10k line for english etc
this is like all the answer of the bot
7k sorry
like this is hell to maintain
maybe i can do for each folder of subcommand something like that :
one folder for all translation for this group
one folder for all view
one file for each utils functions
and other like normal thing
but even this seems big asf
what?
Localization
If an ephemeral view has it's timeout set to None, await view.wait() is called, and the user presses the Dismiss message button, what happens to the function that called .wait()? Will it hang forever?
Example code:
@discord.slash_command(name="test")
async def test(self, ctx: CustomApplicationContext):
view= TrueFalseSelectView("Yes", "No")
await ctx.respond("Test", view=view, ephemeral= True)
await view.wait()
print(view.final)
class TrueFalseSelectView(discord.ui.View):
def __init__(self, true_button_label: str, false_button_label: str):
super().__init__(timeout=None)
self.final: bool | None = None
false_button = discord.ui.Button(style=discord.ButtonStyle.red, label=false_button_label)
false_button.callback = self.false_callback
self.add_item(false_button)
true_button = discord.ui.Button(style=discord.ButtonStyle.green, label=true_button_label)
true_button.callback = self.true_callback
self.add_item(true_button)
async def false_callback(self, interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
await interaction.delete_original_response()
self.final = False
self.stop()
async def true_callback(self, interaction: discord.Interaction):
await interaction.response.defer(ephemeral=True)
await interaction.delete_original_response()
self.final = True
self.stop()
Based on my testing, it never returns, however I'd like some additional confirmation on this.
And if this is indeed the case, is there some sort of workaround to check whether the message has been Dismissed?
for what do you need .wait()?
It would be a universal "Confirm" / "Cancel" view for warnings.
Take the following as an example use case
btw you can use ctx.respond as a shortcut
You can check if the message still exists. By getting the interactions original response. Ideally you would have a timeout instead though. Ephemeral messages are supposed to be temporary so you should not treat them as persistent. I don't think you can check if the message exists after 15 minutes as this is when the interaction token expires (which is used to get the message)
Timeout it is then. Purely out of curiousity, would my code in its current state leak little bits of memory with each Dismissed view?
Not 100% sure but I think so. Unless the message gets marked as unavailable some other way later on
The intellisense does not like it for some reason, and I can never spell ephemeral
how lol
Β―_(γ)_/Β―
man vsc really is incapable of even the most basic IDE task
Same on the spelling part XD
Ephermial I add an I for some reason.
I guess it does not like that its a property?
not even sure why it is
like its a function why is it a property lol
oh nvm makes sense
is there an error for a subcommand that doesnt exist being invoke ?
like command not found but subcommand not found
I am getting this when issuing a command but then it seems like the command still runs its just taking a bit? is there a default time pycord uses when issuing a command that can be modified?
do you use ctx.send or ctx.respond?
yes the command does work in some scenarios, but when there is more processing in backend that has to happen it seems to timeout
?
ah sorry thought you were asking if using either. yes using ctx.respond @little cobalt
Discord gives you 3 seconds from the moment the user runs the command until they expect to recive the response.
For longer running commands you can use ctx.defer(). This tells discord that you need extra time and then allows you to have 15 minutes to respond. You should defer at or near the top of your command callback as the defer needs to be received by discord in 3 seconds as well.
does not look like it
Exactly what i needed, thank you... follow up though as to the question now in trying to establish why the command is taking so long
The command I have looks into previous threads to see if a specific link was already included in the embeds posted in each thread. I only want it to look at threads that have not been archived, and the default archive time I have the threads is 24 hours. IT seems like even with this code though it may be searching through every thread, including the archived ones... is there something im missing here?
async def find_existing_thread(channel, link):
for thread in sorted(channel.threads, key=lambda t: t.id, reverse=True): # Sort by ID descending
if not thread.archived:
first_message = await thread.fetch_message(thread.id)
embed = first_message.embeds[0] if first_message.embeds else None
if embed and any(f.name.lower() == "claim" and f.value.lower() == f"[click here]({link})".lower() for f in embed.fields):
logger.info("Found existing thread with matching claim link.")
return thread
return None
you should use https://docs.pycord.dev/en/stable/api/models.html#discord.Thread.starting_message and not make an API request for every thread to get its message
Models are classes that are received from Discord and are not meant to be created by the user of the library. Attributes key, url. Methods def is_animated, async read, def replace, async save, def ...
Does this work if the first message is only an embed? following code prints None
for thread in sorted(channel.threads, key=lambda t: t.id, reverse=True): # Sort by ID descending
if not thread.archived:
first_message = thread.starting_message
print(first_message)
well if the message isnt in cache you need to fetch it
arent i then hitting the api again though?
yea but you should default to using cache
so something like this?
first_message = await get_or_fetch(bot, "message", thread.id)
so just do first_message = thread.starting_message or thread.fetch_...
Neither of above worked, this seemed to do it though
first_message = thread.starting_message or await thread.fetch_message(thread.id)
That being said though, still taking very long to run and i think its still going through the archived messages
oh yea you need to await
i mean then print the thread names and check lol
https://docs.pycord.dev/en/stable/api/models.html#discord.Guild.active_threads
This gets a list of all active threads in a guild, not specific to a channel. I dont think discord provides a channel specific list
i mean their code should work no?
yeah thats what i thought, thanks tho
yeah i was just doing this as i typed it. either its automatically not fetching the archived, or nothing is actually getting archived
because this didnt print anything...
elif thread.archived:
print(thread.id)
channel.threads gives you all the threads in the bots cache
oop wrong reply
print the thread names and check if it prints any unarchived ones
Tried that above with the elif statement
Nothing printed
Is there a way in the discord UI to determine if a thread is archived? β¦perhaps nothing is actually getting auto archived?
Because Iβm still seeing everything even thatβs older than like 2 days and I have it set to 24 hrs
In forum channels: It shows under the "Older Posts" header
no, print all thread names you get in your original code please
maybe it doesnt even apply to forum posts
It does, we have it here
yeah i dont have that. - should "close post" be already selected on archived posts?
ah shit - baby just woke up gotta run, will be back in a bit to keep tinkering thanks so far
π Yeah, "archived" is the API name "closed" is the public name
If it is archived it will say "open post"
Yeah so not getting archived thenβ¦guess the auto archive isnβt working :/. alright at least I know the issue now will try and figure out why thatβs not working later
actually you might be right. I dont think anything more recent than a month is archived here and the default is 3 days
threads and posts should have been 2 seperate classes
not sure if discord themselves differentiate it
Discord treats them the same.
archived for forum posts might mean forcibly closed
Posts like this one were probably not forcibly closed but are still archived
https://canary.discord.com/channels/881207955029110855/1306742100439859281
it is closed though
It is closed but I dont think anyone closed it I think it was automatic
Unless someone closed threads not using the /close command
i do that rarely
oh i remember manually closing that rhread because the bot was down
... well that was a big coincident.
Do you do that a lot? There are a bunch of other threads that follow the same pattern
not recently
the older posts section is all archived posts
archive is set to 3 days
yeah, but why are posts that are more than 3 days old not auto archived. I just closed a bunch but they were inactive for 20+ days
It happens a lot
remember
its a feature added past discord's prime
so it HAS to have some bugs in its core functionality
its the law

Hey checking back in here - seems like this is an actual issue with discord itself not py-cord?
Could it have anything to do with the βauto_archive_thresholdβ arg?
and if not, does the api call to manually archive the thread still work? Maybe we just need a background job every hour to check total age of the thread and archive accordingly
Yeah, it seems that there is something strange with how discord closes threads. A manual API call to archive would work.
Alright Iβll try writing something up when back at pc later tn
Perhaps itβs something that should be built into pycord though? Since all the args for setting thresholds prob arenβt working for everyone using them
Is there a possibility to have an attachment as a parameter to an ext.command just like slash or should I iterate over ctx.message.attachments ?
you can just do like so :
async def upload(self, ctx: LumabotContext, file: discord.Attachment):
that didn't work :/ I think I might have messed up smth
oh well
in the end I am just iterating over the attachments so I can have my own logic
strange
maybe it does not work with more than 1 arg
- why prefix
Idk. But users want it so I don't really care, I give both options with, most of the time, more options for slash, and they do whatever they want
Alright not entirely sure what i did, was just playing with archiving manually and it seems like ive now entirely hidden a few channels π
I can still get to them by doing like #rules and clicking it but its hidden from the sidebar... how do i get it back?
i do have onboarding enabled but where is that show all channels setting?
because now its not even showing in the 'browse all channels'
Did you somehow enable server guide?
ah okay that did it - but how do i force those channels to always show like how you guys have the #rules in info
my rules channel has this in the settings...
and theres no 'dont hide' option
enable them as default in onboarding
thats for threads
Is your rules channel a forum channel? nvm
they are
i dont think so? lol
the same issue is happening for FAQ though
(or remove those channels)
not sure you can remove the rules
ahhh you guys have server guide and SEPERATE channel for rules
thats really confusing... discord has like 3 seperate places for 'rules' and none of them are linked
we did here
really just 2
nope
you need to make a speerate channel
onboarding, rules channel, and then a seperate server guide rules
server guide uses the normal rules channel
its not possible to make the server guide not hide the channels?
ah alright think i got it set up how i want... how do you remove the events and other crap up there?
yep fair - i saw it wasnt in your guys thing at the top so figured id ask
1 last pycord question... is this the most efficient way to get a channel by its name?
async def find_channel_by_name(channel_name: str):
guild = await get_or_fetch(bot, "guild", GUILD_ID)
# Look for a text channel with the provided name
channel = discord.utils.get(guild.channels, name=channel_name)
return bot.get_channel(channel.id) if channel else None
the first question is why do you need to do that
trying to go through all my code now and optimize where i dont need to be fetching every time
its a helper function.. i have multiple commands that can be invoked that then should write to specific channels... i could hardcode the channel IDs i guess but wanted it to be somewhat dynamic in case i change channels later
only mods see it if no event is active
im pretty sure you can just remove the bot.get_channel line since discord.utils.get should already return the channel object
ah yep thanks!
same for the if channel else None
async def find_channel_by_name(channel_name: str):
guild = await get_or_fetch(bot, "guild", GUILD_ID)
# Look for a text channel with the provided name
return discord.utils.get(guild.channels, name=channel_name)
works thanks!
but keep in mind getting channels by name is really not ideal
Yeah i know - this is a custom bot just for my 1 server though so cutting a few corners
just note that fetch here is pointless because a guild from fetch_guild doesn't include channels
(a small bot like yours will always have the guild cached, so you rarely need to fetch anything really)
Well wouldnβt it always just use get first then if cached with this function?
right, which is why im saying there's not much reason to use get_or_fetch
Yah I guess my style is more βhave and not needβ than βneed and not haveβ
Thereβs no harm in having as itβll use cache and if it doesnβt need to fetch
How to make slash_command only visible in a certain guild
(my point being that if it ever fetches, your system breaks)
add a list of guild_ids to the command decorator
That's a code change. Say you have a bot that is in multiple guilds (I don't, but let's pretend); is there a way to selectively enable/disable a command for a particular guild?
no
Is that a Discord limitation, or a pycord one?
well for starters, discord has no concept of "disabling" a command
it either exists or it doesn't
when we set guild_ids, it creates a new individual command on every guild through their individual endpoint
So when you refresh commands with Discord, you have to send them all? There's no way to say 'this specific command is no longer available'?
there's a few different sync methods
pycord by default does a bulk sync and overwrite
the important part is if for some reason a command is "deleted" or not included in an overwrite sync, you'll also lose any user customizations such as permissions
which obviously isn't ideal for a public bot
I'm not saying it's not complex, but is it theoretically possible - given available methods from Discord - to manage available commands per server on-the-fly? Whether via a bulk sync or with some of the other type of sync you hinted at
oh it absolutely is
just a pain lol
ideally pycord v3 will also make it easier, the current sync system sucks for anyone trying to even remotely do their own thing
It seems like such a giant oversight to not allow permissions to be added with command registration. It's not like they don't have Role settings on every other model.
well it wasssss
but when permissions v2 came, it was moved to user control
thus if you want to programatically set permissions you need oauth instead (which is why large scale dashboard bots can do it)
mm, that makes sense (but is overly complex for smaller bots, especially bespoke ones.)
I can just imagine there's been a non-zero number of times privileged commands were accessed by commonfolk because the integrator forgot, or didn't get to it in time
at least we do have default perms which is a decent enough compromise, but yeah at the time it was a pretty big deal
Are there any downsides to using py-cord[speed]?
for what is speed even?
I found it on the pypi page
I think it's uvloop, or what is it ?
like 3 extra dependencies
that are intended to make the library run marginally faster
Sounds worth it to me
Sorry, why would it break?
Because fetch_guild doesn't return channels
That was my original point
I made my own help command and added it to my botβs help_command setting. However, it isnβt responding with it. Does it take a while to load the command like how slash commands do?
did you restart discord and the bot
also i think help_command is kind of a remnant of prefix times, not sure how well it works with slash
I donβt have it set up as a slash, I was just wondering if it had the same load bearing as slash does when it comes to being a global command. I restarted the bot, but not discord. Everything else didnβt need a discord restart so tbh I didnβt think about that.
Iβve tried even getting just the Minimal Help Command to appear, but it just wonβt register the command
Prefix commands are not registered to discord so you only need to restart your bot. If it is not working immediately after restarting your bot you have something wrong in your code.
It is recommended to use slash commands at this point in time though.
Ah, i see you talked about it in #general
Yeah, I'm just going to bail on prefix commands. It's good to know now that they're useless. It's getting easier as I translate my commands. Finished file 1/7 so far, and was able to cut out a lot of commands since a lot of it was 'help adjacent'. Makes it so much easier since discord will handle that.
Yeah, I'm very quickly learning that lol
Each feature is reducing in code by a large margin
So much error handling is automatically taken care of if I do typing
I'm def going to do typing for my own sanity
hey sorry what is the proper way you are saying i should query the guild then?
just bot.get_guild because it's always cached in your scenario
Hey guys I made a bot that uses views (with the bot ui kit), but it seems like that if I run my project on my local computer, it runs on time, it doesn't have any delay or anything. But when I run it on my vps, it has slightly delay with timeout, it timeout's a minute later what might be the cause?
How are you setting your timeout?
I sounds like you mean that the timeout is actually 1 min 15 seconds on your VPS or similar?
VPS system time might be wrong would be my first guess
This is how I create my views and set my timeout:
class AnnounceView(discord.ui.View):
def __init__(self, someone: discord.Member, *args, **kwargs):
super().__init__(timeout=600, *args, **kwargs)
self.someone = someone
view = AnnounceView(...)
its like a minute delay
check if the time of your vps is correct
its more a shared hosting but does this have to do something with the timezone difference?
doesnt matter if its shared or not, check the time of the server lol
and no, timezones are 30m minimum
what specifically do you want me to check about the time of my vps?
whether its correct or off by a minute lol
1 hour delay thats it
luxkatana@nest:~/cautious-computing-machine$ date
Mon Dec 30 10:06:24 PM UTC 2024
so the minute is correct? hm
the timeout is dynamic by the way, but it has some pattern
That is strange. If the VPS time was off it should not effect something that happens X seconds in the future as that is a duration not a specific time.
it might have taken the time from which the message is sent as a timestamp, thats how i imagined it
The timeout resets every time you interact with the view. Are you aware of this?
hm?
I sent the view already, at that point the timeout time should go off, right?
This is what I mean (the time currently is 23:17 or 11:17 PM for you dumb americans)
This is how the timeout is decided:
Current time + 10 minutes
current time seconds will be zero so that'll timeout when it is exactly after 10 minutes
So you mean that, if someone interacts with any of the buttons or selects, then the timeout will reset?
Yes the timeout is how long the view needs to be inactive before it does its timout things
Oh?
I want to make this behaviour that it should last for n amount of seconds how can I do that then?
With a task
run view.stop() after that amount of time
and before that, view.disable_all_items() i think
so the buttons become inactive
so I should be cnstantly checking the time using time.time()?
manually
no lol
hm actually not quite sure how id do it tho rn
probably running a function in a new asyncio runner that then waits 10m exactly and then disables all items and stops the views
but the time that it should disable is dynamic
tasks can have dynamic timings
@tasks.loop
oh i also thought you were talking about pycord tasks lmao
so yea we mean the same thing
cant I just wait using asyncio.sleep for the amount of time directly? And disable the items of the views after the sleep?
Yeah but that would block your code execution
oh that it'll block access to another commands?
It doesn't block the thread
thats impossible right because its asynchronous.. right?
if you use time.sleep then it will block?
asyncio.sleep doesn't block the bot
Yeah
so it shouldnt be a problem to use asyncio.sleep ig
It does
On my stuff like that I just check the time when someone interacts and if it is passed the end time I say "sorry to late" then disable/stop the view. This works well for longer timeouts
because it still pauses code execution on that branch
so, unless im wrong, the view will never respond to events or your command code wont resume (assuming something happens in the command used to send that view)
after 10 minutes, it'll do another stuff (creating channels, handling other views and stuff)
might be wrong tho
my project only consists of just one task not any other command :p
i should be trying stuff out ig, but thanks guys!
i read my role wrong thought it said transistor
I think it doesn't block the view either
I remember using it somehwrre
asyncio.sleep will only block the code after it, nothing else
(that's the entire point)
yea but i worried about the init never finishing and thus that branch of code never returning the command until after those 10m but since there's apparently no command is fine
quick question, what feature is this bot using to generate profiles programmatically?
Webhooks
Hey guys qq - I am using autocomplete for an arg on one of my commands, but the command is still able to be executed with a value taht is not in the list... is there a way to force the user to only be able to execute by using a value from the autocomplete?
@bot.slash_command(guild_ids=[GUILD_ID], description="Share a promo the community!")
async def promo(
ctx,
name: discord.Option(str, "specify the name", autocomplete=discord.utils.basic_autocomplete(name_autocomplete)),
):
use options
I cant because there are more than 25 or whatever the limit was
Then you will need to check against the autocomplete options and return an error message
Or use multiple select menus
yep okay thats fine i can write a manual check just didnt know if there was a quick arg that could be set
New day, new question. I have a global error handler to handle (obviously) errors. I also have command specific errors. My global handler is interfering and dealing with errors that only my command specific error handlers should touch. Is there a way to prevent this?
are you actually setting handlers or do you just do the handling right in the command code
if you set handlers, you can add this to the top of your global handler and it should work
if ctx.command.has_error_handler():
return
Hey guys another quick one - is it possible to respond as ephemeral when returning the function?
I am trying to do something like this but it seems like the bot response is still showing public to everyone
msg = f"[{category.capitalize()} Posted]({thread.jump_url})"
logger.info(msg)
return await ctx.respond(msg, ephemeral=True)
If not, is there a way to hide the args that were passed to the command when clicking on used <command> ?
you need to defer ephemerally if you wanna respond ephemerally
oh so every function essentially then that has a response should have the first line be the ctx.defer?
ohh wait you mean pass the ephemeral arg as True to the defer?
yes
got it thanks!
Iβm setting error handlers
.
Thanks!
I had something similar that worked with prefixes, it was a hasattr(command, βerrorβ)
It broke once I swapped to slash commands
is my server subscription tier bugging out, or does discord upcharge the fee on ios devices?!
wow okay thought i was going crazy with messing up a tier
Anyone know if this actually works either or do I need to write a custom greet message in pycord? Have people signing up and no message :/
I wonder if its because there is a week free trial, so maybe after the trial ends it procs?
but they do put in the credit card and everything when they click 'subscribe'
not charged tho
hmm yah i guess
have an actual py-cord question now... are there any examples of how to determine when someone joins, what invite they used and then subsequently who created that invite (i.e. who invited them?) ..Thinking of doing a referral type system
only indirectly
you need to actively track the number of uses of each invite and recheck after a join
but joining is just on_member_join
Yeah so i worked up something like this with that thinking, was hoping there was a better way though
@bot.event
async def on_member_join(member):
guild = member.guild
# Fetch the current invites from the server
invites = await guild.invites()
# Find the invite with increased uses
for invite in invites:
if invite.uses > 0:
inviter = invite.inviter
if inviter:
print(f"{member.name} joined using invite by {inviter.name}.")
# Store inviter-invitee relationship
inviter_tracker[member.id] = inviter.id
break
yea thats how you need to do
but this would obv need some tweaking to check against a cache
when you need them past a bot restart
Ok Iβm losing my mind here. How do I get the SKU id for a premium shop item??? I want to verify that a user has the correct SKU, but have no idea how to do so because discord does NOT explain how to do so in their documentation. Iβve been staring at it for literal hours.
Am I just missing something??
Isnβt it entitlement.id ?
And user_id for the other v
I think all purchases on the mobile apps are more expensive. Tell your users to buy on PC or discord web if they only have a phone. I know there is a fees breakdown in one of discord minimization writeups
This is not gonna work
You need to compare the old invite count to the new one, here it will just always show the same person who has an invite greater than 0
Thatβs what I thought, but I donβt know where to get that from. Is it from the ApplicationContext being passed through? Via obtaining the bot/client from the context for the botβs SKU and obtaining the user for the userβs SKU? In that case, how do I know which SKU belongs to the subscription I am trying to reference? From what I can tell there are no names within an entitlement object, just idβs. I havenβt looked at a SKU object, so maybe itβs there, but I find it weird that I canβt find the SKU id before having to grab it via the application command. That would mean Iβd have to call the method to read all entitlements available and then pick and choose until the right entitlement is selected
If you open the edit shop menu the sku ID is the last ID in the url
you can also use Client.fetch_skus
This is the exact answer I was looking for. Thanks
Does this grab the entitlements that are in the guild? Or the one that the invoking user has within the guild?
that would grab entitlements attached to guild subscriptions
Ah ok. I think I have mine set up to user subscriptions instead. Would I instead just grab the user from context and do user.entitlements, giving the same result?
yes
Thanks π«‘
both of these use Client.entitlements, they just specify the guild/user parameters respectively
Cool. So if I did Client.entitlements it would pull all entitlements, regardless of guild/user?
yes
additionally if you're using interactions, Interaction.entitlements should return everything that applies to that interaction
(both user & guild)
I am indeed using interactions. I have application commands returning ApplicationContext, which give me access to the user and the interaction within it
So either way I can grab the entitlements
I just had no clue where to grab the SKU I need for comparison
Inter.entitlements is preferred because it's not an extra API call :3
Even ChatGPT told me it was displayed on the discord applications page π
Iβll keep that in mind then
yes but actually no
Yeah. It displays it, just not next to the SKU (which is what it said lmao)
it does in analytics but you can't copy it :p
Weird
i guess they expected people to just fetch it over the api
Is there a way in discord to pin that response? I wonβt be able to get around to the fix until day after tomorrow
Yeah I think so
I just donβt want to open another API connection
Iβm lazy
So lazy that I already started making my own database for entitlements instead of fetching from the API
yeah
you can cache them in memory, you just have to fetch them on startup
then listen to events
I have event listeners up for entitlements, just didnβt wire them to the DB yet. Going to do this solution instead
Yeah Iβm going to try and write something today - was hoping someone else in the community already had an example to work off of
Check the invite create to save all of the invite with there use
Then when a member join check which invite is greater than the one you save
And then you will now which one invite the member
logically it would be every API call or even every heartbeat ig
hey guys got a discord.File object how can I get the link of it to use it for example as an image for an embed or as thumbmail?
you need to upload it as attachment to the message then make the image link a certain thingy
wait, there's a tag for it
f = discord.File("some_file_path", filename="image.png")
e = discord.Embed()
e.set_image(url="attachment://image.png")
await messagable.send(file=f, embed=e)```
yes that
show your code, depends on what you do
Currently I am taking a file from a slash command
yea show your code
async def apply_as_helper(ctx: discord.Interaction, image: discord.File) -> None:
if SEARCHING_FOR_HELPERS is False:
await ctx.response.send_message("Helper applications are closed.", ephemeral=True)
else:
STAFF_CHAT = await ctx.guild.fetch_channel(1323056105835991050)
embed = discord.Embed(title=f"{ctx.user.name} is applying for helper", description=f"{ctx.user.mention} is applying for helper")
await ctx.response.send_message("Cool, thanks for applying as a helper, we're gonna make our decision later!", ephemeral=True)
ctx is not discord.Interaction
and I'm pretty sure files uploaded to slash commands are discord.Attachment
and you can use ctx.respond() as a shortcut
and :3 you shouldn't fetch the channel but rely on cache (get_channel)
ctx is discord.ApplicationContext?
yes
is there a small chance that the channel is not cached?
and that it returns None?
and no if you get an attachment from a slash command like that you don't have to close anything
not if your bot is only in one or a few servers
typically only becomes a problem with big bots
ohh alright
also idk what ctx.user exactly points to but usually you use ctx.author
sorry for being annoying I love to nitpick
ctx.author is a shortcut for . user
ok
is there a way to remove webhook messages of a channel?
delete them like normal messages
For anyone else who may be interested... this seems to be working
server_invites = []
@bot.event
async def on_ready():
# Cache Server invites
global server_invites
guild = bot.get_guild(GUILD_ID)
server_invites = await guild.invites()
@bot.event
async def on_member_join(member):
global server_invites
new_invites = await member.guild.invites()
for old, new in zip(server_invites, new_invites):
if old.code == new.code and old.uses < new.uses:
update_referral(member.id, new.inviter.id) # Custom function to do something with the data
break
server_invites = new_invites # Update cached invites
why do you declare the global twice lol
or rather why make it global at all
oh bc its not in a cog
You lack one thing, if a invite was not saved it will not work
So you will have to update the invite also during invite create
yeah i actually just just realized that after posting... trying something like this now
@bot.event
async def on_member_join(member):
global server_invites
new_invites = await member.guild.invites()
old_invites = {invite.code: invite.uses for invite in server_invites}
for invite in new_invites:
if invite.code in old_invites and invite.uses > old_invites[invite.code]:
update_referral(member.id, invite.inviter.id)
break
server_invites = new_invites
and i think the assumption i still need to add is that IF there is a new code, that is the one to use... not sure how to account for if more than 1 code is created though before someone new joins
Just also use the invite create event to update the event
oh wait great idea... just use the event create to update the server_invites
Basically what you can do is
invite_create and invite_delete => update ur list of all invite.
member_join : check which invite is greater and update the list of invite
And consider saving the invite inside ur on_ready too
something like this?
async def refresh_invite_cache():
global server_invites
guild = bot.get_guild(GUILD_ID)
server_invites = await guild.invites()
@bot.event
async def on_ready():
logger.info(f"Caching server invites...")
await refresh_invite_cache()
@bot.event
async def on_invite_create(invite: discord.Invite):
await refresh_invite_cache()
@bot.event
async def on_invite_delete(invite: discord.Invite):
await refresh_invite_cache()
@bot.event
async def on_member_join(member):
global server_invites
new_invites = await member.guild.invites()
old_invites = {invite.code: invite.uses for invite in server_invites}
for invite in new_invites:
if invite.code in old_invites and invite.uses > old_invites[invite.code]:
update_referral(member.id, invite.inviter.id)
break
server_invites = new_invites
invite create & delete you can just manually update the cache instead of refetching all of them
since only one invite changed
but i wouldnt get the uses if i manually added the code...would I? ah wait nvm i could add the object
but feels safer to just pull a refresh?
safer technically but unnecessary
This is very unreliable and prone to issues
f
latest but if you have more recommendations please share! #1132206148309749830 message
If you want to do it that way you'll need to add a bunch of error handling including for cases when for some reason your db is not in sync with the guild invite information and a database to work between restarts.
There is no db use
For the guild invites...
And he used the on_ready to sync again between restart
For a single guild bot this seems to be good
If it's a single guild then yeah ig...
Because I donβt really see any scenario where it will not works
Or it will not work for 1 member if discord has an issue
Still needs error handling imo, e.g. server is a bit unresponsive and multiple users join at similar times
Race condition basically
Yeah, for a single bot it should be good but ofc it can be better
The race condition issue doesn't depend on the number of guilds. But yeah I get the fact that it's for a single guild. Although imo that tracking method is still hacky and duct taped
I would make it so that server_invites = new_invites is in a finally block or else it could link a user to the wrong invite if an issue happens for another user at first
At least
Then have some kind of lock on server_invites and run the appropriate logic with that lock
Sorry stepped away for a bit thanks for the tips here - yes single server use only but lock is a good idea for race condition even if itβs an edge case
can i asign custom values to slash commands directly from
@discord.slash_command(name="", description="")
so that these custom values show up in bot.application_commands
What do you mean by custom values ?
@discord.slash_command(name="", description="", custom_value="banana")
So then in bot.application_commands i could do
command.custom_value and it would return banana
for what purpose
uh
a commands webpage, id like to mark owner only ones etc
I mean you should be able to do command_function.attr = " "
right under the definition of the function
i dont think that works
that works
But I'm unsure why you would want to do that
to say it doesn't work without even trying is wild
@ionic wasp Do you mind sharing a bit more about your exact use case so we can find maybe a better implementation ?
if you address the functions like this it'll be SlashCommand objects btw so just make sure you're not overwriting a preexisting name
thanks
how to get user's bio (about me)?
not possible
You would probably be better of subclassing SlashCommand in that case to add your own attributes. Something like
class MySlashCommand(discord.SlashCommand):
def __init__(self, *args, **kwargs):
self.owner_only = kwargs.pop("owner_only", False)
super().__init__(*args, **kwargs)
def slash_command(**kwargs):
return discord.application_command(cls=MySlashCommand, **kwargs)
@slash_command(yada yada)
async def cmd(ctx:...):
...
π cheers
Thanks for the tip, how do you think this looks?
server_invites = []
server_invites_lock = asyncio.Lock()
async def refresh_invite_cache():
global server_invites
async with server_invites_lock:
guild = bot.get_guild(GUILD_ID)
invites = await guild.invites()
server_invites = invites
@bot.event
async def on_invite_create(invite: discord.Invite):
await refresh_invite_cache()
@bot.event
async def on_invite_delete(invite: discord.Invite):
await refresh_invite_cache()
@bot.event
async def on_member_join(member):
global server_invites
async with server_invites_lock:
new_invites = await member.guild.invites()
try:
old_invites = {invite.code: invite.uses for invite in server_invites}
for invite in new_invites:
if invite.code in old_invites and invite.uses > old_invites[invite.code]:
update_referral(member.id, invite.inviter.id)
break
finally:
server_invites = new_invites
This looks good ! If you wanted, you could have all that in a Cog so that you could do self.server_invites instead of using global but that's more a preference than anything.
hey guys what's the default timeout of a View
I was thinking of doing cogs but it seemed to add a lot of other challenges as i have a few other things happening in this file as well that would cause some circular import references. As it stands the whole file right now is only like 500 lines of code so was trying to just keep it simple
5 or 15m I believe I can never remember
cogs make everything easier
the only real challenge with cogs is spreading a single command group across multiple cogs
everything else can easily be put either in helper files or synced via the bot object
Well so for example the issue i was having is that in my main.py right now, i also have the bot spinning up a fastapi webserver. so in a theoretical webserver.py where i define the fast api app and all its endpoints, i couldnt figure out how to call commands that require the bot because in the main.py where i have the bot, it also needs to import the app so it can spin up the server
@tasks.loop(count=1)
async def run_fastapi():
logger.info("Starting FastAPI server")
config = uvicorn.Config(app, host="0.0.0.0", port=8080)
server = uvicorn.Server(config)
await server.serve()
so in main.py i need to import app (defined in webserver.py) but in webserver.py i would need to import bot (defined in main.py)
so i just kept it all in main.py π
oh
how do i run it then?
if __name__ == "__main__":
bot.run(SWEEPY_TOKEN)
check the cog guide please
hmm okay i did give it a try but maybe i misunderstood will try reading again
I was on this page and thought i understood how to essentially define all the cogs as modules, then add them in main.py with something like bot.add_cog(Greetings(bot)) .... but i though you still would have to actually start it after adding all the cogs call bot.run() It doesnt say on this page how to start the bot a different way unless its documented somewhere else?
There comes a point in your botβs development when you want to organize a collection of commands, listeners, and some state into one class. Cogs allow you to do just that. The gist: Each cog is a P...
oh is this not the right page?
that's the docs
you do bot.add_cog(...), then bot.run(...)
That should be it
where can i find the guide?
