#Basic Pycord Help

1 messages · Page 66 of 1

tiny fractal
#

yea i did

sage tendon
#

lol

tiny fractal
#

i just removed it

sage tendon
#

I'm almost certain it's something weird with that db package

torn barn
#

could you share all of the code? With the try and except blocks

tiny fractal
sage tendon
#

I'd say try to switch to something like async mysql but not sure if you can do that easily

#

otherwise sqlite never fails

lapis dock
#

Can you try running the database script separate from the bot. Just fill in DM data instead of a message

tiny fractal
#

lol, yesterday

#

i am trying to use datetime

#

maybe i need to roll back a few versions. this used to work fine in the past

lapis dock
tiny fractal
#

someone made PR draft for it

#

WEBSOCKET

#

brb making it an http connection

#

progress, just battling with it saying my namespace isn't set. which is a lie

lapis dock
tiny fractal
#

WTF did they do!

#

i used this library months ago and everything was perfect

dry gust
#

Is there any built-in method for implementing cooldowns?
I want to add level system and xp will come from messages. And I want to somehow stop spam-abuse

lofty parcel
dry gust
#

does this work on @bot.event?

#

.rtfm cooldown

lofty parcel
#

No

#

You'd have to implement your own cooldown for that

dry gust
#

okie

lapis dock
#

@cobalt bone What exactly do you mean?
You have to send a message, but your message does not have to have any content other than the view

cobalt bone
lapis dock
#

👍

fresh sierra
#

what is a point of that ?

final bone
#

If I'm manually handling my interaction responses. do I need to do something about the callback method on the modals to regain control over the response?

#

nevermind, I read the source code

lapis dock
lapis dock
#

@round heart moving here to not hijack

Discord gives you a temporary "interaction token" that is valid for 15 minutes. You can use that specific token for 15 minutes. If a user interacts with your view you get a new interaction with a new token.

round heart
lapis dock
#

Everytime a user interacts discord sends a new token you can use for 15 minutes. But you cant have a button that when pressed waits an hour before editing the message without doing extra stuff

round heart
#

extra stuff
ok

#

Is that documented anywhere so I don't ask redundant questions? I've never seen a mention of that (but also didn't go looking for it)

#

(Outside of a persistent view, which isn't necessarily what I'm looking for, either.)

lapis dock
#

I feel like I've had views where interaction after 15 mins was just met with 'interaction failed'
Your bot still has to be listening for the interactions discord sends. I think the default timeout (before pycord stops listening) is 5 minutes. But you could make this as long as you want.

round heart
#

They were with Views with timeout=None

#

I guess what I'm asking is that you shouldn't need to do anything in Pycord to account for this new token, and that interactions should seamlessly work after 15 mins because it's generating that new token?

stray cape
#

hey guys, is there an implementation of the bot.wait_for function that exactly is like that but doesn't take in an event parameter?

#

I need to wait until a certain condition has reached

echo wraith
stray cape
#

when a certain list reaches a length

#

it has to "block" until a certain condition has passed

echo wraith
echo wraith
#

Like how is it edited

stray cape
#

I am using the list as a kind of "pointer" that is shared between multiple views (the views are all the same kind of views)

#

I share the list with every view so that they can modify it

#

and yeah every view has a timeout aswell, which will still append something to the list

#

Kind of structure:

class SomeView(View): 
   def __init__(self, ptr_list: list, *args, **kwargs):
       super().__init__(*args, **kwargs)
       self.ptr_list = ptr_list
   # Here are some buttons that'll append things to the list


confirmations: list[bool] = []
for user in members:
   channel: discord.TextChannel
   await channel.send(user.mention, view=SomeView(confirmations, timeout=...))


#

I could technically wait until the timeout has reached

#

but I just want to directly continue after the length of confirmations has been met

#

I know I am a littlebit vague

echo wraith
# stray cape Kind of structure: ```py class SomeView(View): def __init__(self, ptr_list: ...

import asyncio
from typing import TypeVar, Generic, Optional

T = TypeVar('T')

class WaitingList(list, Generic[T]):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._length_futures: dict[int, asyncio.Future] = {}
    
    def append(self, item: T) -> None:
        super().append(item)
        # Check if we have any futures waiting for this length
        new_length = len(self)
        futures_to_resolve = [
            (length, future) 
            for length, future in self._length_futures.items() 
            if length <= new_length
        ]
        
        # Resolve all futures that are waiting for this length or less
        for length, future in futures_to_resolve:
            if not future.done():
                future.set_result(None)
            del self._length_futures[length]
    
    async def wait_for(self, length: int, timeout: Optional[float] = None) -> None:
        """
        Wait until the list reaches the specified length.
        
        Args:
            length: The length to wait for
            timeout: Optional timeout in seconds. If None, wait indefinitely
            
        Raises:
            asyncio.TimeoutError: If the timeout is reached before the list reaches
                                the specified length
        """
        if len(self) >= length:
            return
            
        # Create a future if we don't already have one for this length
        if length not in self._length_futures:
            self._length_futures[length] = asyncio.Future()
            
        try:
            await asyncio.wait_for(self._length_futures[length], timeout=timeout)
        except asyncio.TimeoutError:
            # Clean up the future if we timeout
            if length in self._length_futures:
                del self._length_futures[length]
            raise

# Example usage:
async def example():
    waiting_list = WaitingList[int]()
    
    # Start waiting for length 3
    wait_task = asyncio.create_task(waiting_list.wait_for(3, timeout=5.0))
    
    # Append items with delays
    await asyncio.sleep(1)
    waiting_list.append(1)
    await asyncio.sleep(1)
    waiting_list.append(2)
    await asyncio.sleep(1)
    waiting_list.append(3)
    
    # Wait for the wait_task to complete
    await wait_task
    print(f"List reached length 3: {waiting_list}")

# Run the example
if __name__ == "__main__":
    asyncio.run(example())

Made this real quick w / chatgpt claude

stray cape
#

oh god

echo wraith
#

Also this only works when you explicitly use .append

echo wraith
#

You could also check for len repeatedly but that would be inefficient

#

Or another option

stray cape
#

gonna review the code since ai can't do anything usefull these days

echo wraith
stray cape
#

@lapis dock were you about to reply to me?

echo wraith
#

would be to make everything after the "wait_for" in another async function, and in the view, in every place where you .append, check for the list's lenght and call the function if applicable

stray cape
stray cape
#

which holds a list I suppose

#

and um

echo wraith
#

so it does everything a list does

#

plus

#

wait for

#

and some shenanigangs in .append

#

everything else it will behave exactly like any list

stray cape
sage tendon
#

when you add it another way

echo wraith
stray cape
#

nuh I am planning to just use the append method

echo wraith
sage tendon
#

also uh just reading it quickly cant you just create a task loop that checks the list every few seconds

sage tendon
#

why "think"

stray cape
#

I am gonna reply to your message

echo wraith
stray cape
#

technically I could also use a while loop if asyncio allowed me

echo wraith
#

Nor reactive at all

lapis dock
# round heart I guess what I'm asking is that you shouldn't need to do anything in Pycord to a...

You will always use the new token in the interaction object passed to your callback.

class MyView(discord.ui.View)
  def __init__(self, original_interaction):
    self.original_interaction = original_interaction // This is the interaction that is used to send the view
    super().__init__(timeout=60*3)

  @discord.ui.button(label="Hi")
  async def hi(self, button, interaction):
    // This will work as long as pycord is listening for interactions on this view
    await interaction.respond("Hi")

  async def on_timeout(self):
    // This will only work if the view was sent less then 15 minutes ago.
    await self.original_interaction.edit(view=self)
    // You could choose to update self.original_interaction everytime you get an interaction and this would allow this to work as long as it was with 15 minutes of the most recent interaction

I think this is a more clear explanation that I am pretty sure is accurate.
Also a note: Py-cord treats timeout as time since last interaction, not time since it was sent. So the timeout can keep being extended

echo wraith
stray cape
echo wraith
#

instead of time

stray cape
#


while len(...) != 10:
   ...
#

won't that be blocking?

echo wraith
#

The thing is if you don't wait at some point in your loop it would really consume ressources

#

And be blocking

round heart
stray cape
#

ill just hold on your modified list

echo wraith
#

but still not really efficient or reactive

lapis dock
stray cape
#

gibberish

round heart
echo wraith
#

why did it uses non breaking spaces lool

#

oh wait no

#

It's me

#

bc when I copy pasted

#

I selected the text

stray cape
#

smart you

echo wraith
#

it's an issue with the interface

stray cape
#

yuh it doesnt render markdown correctly

echo wraith
#

I think they replace spaces with nbsp in codeblocks

#

or smth like that

stray cape
#

Possible I don't make these type of stuff

#

hoping that your list doesn't fail

round heart
#

Yeah @echo wraith, hope your code doesn't suck

echo wraith
#

Feeling the pressure rn

stray cape
#

i dont mean it like that*

echo wraith
#

it's fine haha

stray cape
#

publishing it directly to production is the best way to determine if there are errors or not ig

lapis dock
round heart
#

3 more minutes and I can test something. I have a simple View with a button that just ephemerally replies. I need to know for certain wether it still works after 15 mins. (or if my issue is just with editing the message, which I'm not currently testing)

#

Interesting. So it's not that; clicking the button yielded the expected reply. Must just be message editing. Time to test that.

lapis dock
#

ephemerally messages are only accessible through the original interaction I believe.

round heart
#

I believe you're right. But right now the original message is public

#

so this is my example View

class TestView(discord.ui.View):
    def __init__(self):
        self.number = 0
        super().__init__(timeout=3600, disable_on_timeout=True)

    @discord.ui.button(label='Test', style=discord.ButtonStyle.green)
    async def test(self, button: discord.ui.Button, interaction: discord.Interaction):
        self.number += 1
        await interaction.edit(content=f'Clicked {self.number} times', view=self)

.. interaction.edit_original_response is not the right method, apparently. Update: It's interaction.edit()

#

This is why we need a visual guide on which methods to use for which situation 😅

See you in 16 minutes

lapis dock
#

I am going to make a comprehensive visual guide rn. I have wanted to for so long and after explaining everything I have somewhat confused myself as well

round heart
round heart
stray cape
#

@echo wraith your code somehow worked

#

thank you kindly

echo wraith
round heart
#

Claude never makes mistakes.

#

... actually I am curious how much better Claude is for python than ChatGPT. I've actually not used Claude much

little cobalt
round heart
#

Oh, for sure. Sadly ChatGPT is not super helpful with Pydantic because it insists on v1, or Pycord because it still conflates it with d.py, but for generalized stuff (especially on using comprehensions) it works well.

stray cape
#

human's brain works the best

round heart
#

Not mine, sadly

sage tendon
echo wraith
#

even compared to openai's o1

#

like o1 can sometimes solve better complex algorithmical problems

#

but claude is way better at acutally not wanting to rewrite your entire codebase

#

and it feels less weird overall

round heart
minor basin
#

hello - is it easy to use a rate limit warning message to work out exactly what call is being rate limited?
990888169610285056:None:/channels/{channel_id}/messages/{message_id}
this one was for 13 minutes... and just had another for 19 mins. Not ideal!

minor basin
#

thanks, is there a quick reference that gets you that answer?

echo wraith
#

the api path you sent is the one for fetching messages

#

you can find all of them here

sage tendon
minor basin
#

I'm using get most of the time - in this case I'm trying to establish whether a user has deleted the message sent through a webhook? if there's a better way would be very happy

sage tendon
minor basin
#

and then to edit the message sent through the webhook? The partial doesn't allow much to be done

sage tendon
#

bot.get_message(...).edit no?

#

or wdym webhook

minor basin
#

the bot sends messages through webhooks, and then updates those messages periodically. To edit the message, as far as I can tell, I have to fetch the message?

sage tendon
#

do you have to send messages with the webhook for your use case?

minor basin
#

I think so, yes

#

the bot can't join the other servers

#

in my test case I'm only fetching four messages in ~2 seconds

#

a 19 minute limit seems a bit intense

sage tendon
#

i mean.. if you fetch them once thats enough already, because then you could just manually save the message object

#

and how often do you fetch them anyway

minor basin
#

once an hour

#

hadn't realised fetch was so frowned upon! I can work in saving the objects and only fetch them at startup

#

sloooowly

sage tendon
#

yea i have no clue about webhooks
but yea fetching bad cause fetching is slow and counts towards ratelimits

tiny fractal
#
    @commands.cooldown(1, 300, commands.BucketType.user)

does this not work with on_application_command_error()
command just says "Not responding", but prints in console that its on cooldown

minor crescent
#

i changed nothing and my autocomplete stopped working #1330459008569704478

valid panther
#

I am trying to perform a command with a cooldawn, but the cooldawn is null in the case that a user has the role x. The problem is that the decorator works correctly, but does not apply the action. That is, it assigns cooldawn to all users, even if you have the bypass role. Has this happened to anyone else

sage tendon
#

i think using a dynamic cooldown is easier for that

valid panther
rugged lodgeBOT
valid panther
#

every day this library surprises me more and more

#

Omg thx thx!!

sage tendon
#

np

dry gust
#

what's more optimized: saving data about cooldown in json fine directly in bot's directory, or use database for it? I'm between those stupid and shitty solutions because I don't know how to implement cooldown for discord users other way

sage tendon
#

use the built in cooldowns

#

if it's about command limiting

deft hull
#

Can a bot use another bot's emojis

sage tendon
#

No

#

maybe if both bots are in the same team tho not sure about that

deft hull
#

Nope, I think teams are only for developers

echo wraith
#

@frozen silo either use the built in cooldowns or use a cache db like redis. You can see a custom cooldown implementation above

#

.tag nojson

sly karmaBOT
#

JSON is a convenient and easy-to-read data storage protocol that's widely accepted by most programming languages. However, we caution against its use for storing and retrieving data in an asynchronous environment like a Discord bot. Don’t use json!

  • It's a file-based data storage, which makes it vulnerable to race conditions
  • You'll need to implement your own synchronization primitives to avoid corrupting data
  • If you're not careful, you could accidentally wipe your entire JSON file.

Solution? Use a database. Recommended schema are SQLite, PostgreSQL, and MongoDB.

  • Async libraries exist on pypi for each of these
    sqlite -- aiosqlite (or Danny's wrapper: asqlite)
    postgresql -- asyncpg
    mongodb -- motor
  • Databases organize your data into tables, and are fast at inserting, retrieving, and removing records
  • You can impose uniqueness constraints to ensure against duplication
  • The Python libraries enforce synchronization for you
  • The query language is intuitive, you can get running with simple queries in just a few hours!
sage tendon
#

you should really use the built in ones if it's about command cooldowns tho, as it's all kept in memory as well

ionic wasp
dry gust
sage tendon
#

id just save it in memory, there's not much point in saving it to disk anywhere unless your cooldowns are like, hours

dry gust
#

lmfao I'm so stupid 😭

lapis dock
#

what toothy said, You can just have a dictionary like
{user_id: time_when_cooldown_over}

dry gust
#

yes 😭

dry gust
#

Is there any built-in method to define roles that allowed to use commands outside of code (with other commands in discord chat)?
Like in mee6 you could pin roles to commands in webui

sage tendon
#

you typically do it in the integrations menu inside discord, per-server

dry gust
#

wait I can? o_o

#

thx

round heart
#

I really should use redis with persistence

#

All my stuff is in-bot memory or yaml files 😅

round heart
sage tendon
#

there is some way to get role settings from a web ui into the integrations menu though
dyno is doing it like that, its very weird and i think not really intended but they use that

sage tendon
#

has to be

round heart
#

Yeah. So slight correction: there’s just no bot api for it, but can be done with more advanced oauth setups

#

Also, did they remove search from threads on mobile or did it never exist

sage tendon
#

defi dont become like me :3

round heart
#

But this isn’t trivial theming stuff, this is tangible qol

dry gust
#

I remember using it

sage tendon
#

lol that looks wrong

dry gust
echo wraith
echo wraith
sage tendon
dry gust
round heart
dry gust
#

wait... 3-4 years ago

round heart
dry gust
#

really love how discord saved its native look and in the same time became very advanced

sage tendon
#

define "native look"

dry gust
#

Positions of server list, short user info, channels, chat
its colors

#

design and icon style

sage tendon
#

colors and icon styles changed big time

#

except depresso-gray, thats still the same

upper slate
#

I want to create voice channels that are private for users with the default role so I have:
overwrites = { guild.default_role: discord.PermissionOverwrite(connect=False), }
but, I can't figure out how to create invite links that allow these same users to join the voice channel if they receive an invite.

sage tendon
#

dont think thats possible

#

what are you doing that requires this

upper slate
#

just want my bot to give permission to users to join certain channels if they run a certain command, but do not want to deal with dynamic changing of roles to accomplish this

tiny fractal
sage tendon
#

just create overrides for the specific users

tiny fractal
#
overwrites = channel.overwrites
overwrites[member] = discord.PermissionOverwrite(connect=True, view_channel=True, speak=True, use_voice_activation=True)
sage tendon
#

i just dont see the point if anyone can run said command lol

upper slate
tiny fractal
#

i do

#
@pvc.command(name="invite", description="Invite a member to your private channel.")
    async def invite_member(self, ctx: discord.ApplicationContext, member: discord.Member):
        await ctx.defer()

        # Check if user is in a channel named after them
        if ctx.author.voice and ctx.author.voice.channel.name == ctx.author.display_name:
            channel = ctx.author.voice.channel
            overwrites = channel.overwrites
            overwrites[member] = discord.PermissionOverwrite(connect=True, view_channel=True, speak=True, use_voice_activation=True)
            await channel.edit(overwrites=overwrites, reason="User invited to channel.")
            await ctx.send_followup(f"{member.mention} has been invited to your channel.", ephemeral=True, delete_after=5)
            # mention the member in the channel
            await channel.send(f"{member.mention} you may now connect to this voice channel.")
        else:
            await ctx.send_followup("You are not in your channel.", ephemeral=True, delete_after=5

this is my invite command for private voice channels

sage tendon
#

why do you use followups

#

just use ctx.respond

tiny fractal
#

because it deletes the defer messages

sage tendon
#

ctx.respond handles everything you need to reply to any interaction

#

including followups

#

or wdym

tiny fractal
#

i was experiencing instances where running a defered command would leave the "bot is thinking" text in the channel

#

using followups fix that

sage tendon
#

respond should handle it all Shrug_3 i defer a ton too and never needed explicit followups

minor basin
sage tendon
#

you shouldn't unless you have to

sage tendon
minor basin
#

eg button callbacks that edit the original message

sage tendon
#

dont see why you need a defer for that

minor basin
#
Traceback (most recent call last):
  File "/home/jon/.local/lib/python3.10/site-packages/discord/ui/view.py", line 426, in _scheduled_task
    await item.callback(interaction)
  File "/var/amorphia/fcoc-timetabler/fcoc-timetabler.py", line 2048, in callback
    await interaction.response.edit_message(embed=embed, view=None)
  File "/home/jon/.local/lib/python3.10/site-packages/discord/interactions.py", line 1082, in edit_message
    await self._locked_response(
  File "/home/jon/.local/lib/python3.10/site-packages/discord/interactions.py", line 1243, in _locked_response
    await coro
  File "/home/jon/.local/lib/python3.10/site-packages/discord/webhook/async_.py", line 220, in request
    raise NotFound(response, data)
discord.errors.NotFound: 404 Not Found (error code: 10062): Unknown interaction```

I assume these are happening because users are taking to long to (in this case) confirm deletion of a trip
sage tendon
#

that is your view timing out i think

minor basin
#

or they might be dismissing the ephemeral message rather than confirming...

sage tendon
#

you should set disable_on_timeout to true to make sure the view isnt accessible after it times out

#

default is 5m i think

#

or actually in that message it says the timeout is only 3 minutes so ig thats the default unless you changed it

lapis dock
#

The callback is working, the issue is that your interaction token has expired which happens when

  • You dont respond in 3 seconds
  • 15 minutes passes from the time that the interaction was created.
modern trail
#

Is there a way to restrict a command to only people with a specific role? Or do I need to write my own custom decorator for that?

lofty parcel
#

.rtfm commands.has_role

sly karmaBOT
lofty parcel
#

Youd need to handle the error tho

modern trail
#

hm, interesting

lapis dock
#

Ideally you would leave this up to server admins to setup in the integration settings

modern trail
#

what do you mean?

lapis dock
#

You are using slash commands correct?

lofty parcel
#

If you have a slash command, you can manage the visibility through the integration settings on your server

#

You could set default permissions for the slash command when the bot gets added

#

.rtfm default_permissions

sly karmaBOT
lapis dock
#

Server Settings -> Integrations -> Your Bot -> Your Command

modern trail
#

oh. hm, that's odd

lapis dock
#

Note that this is per server, so if you need the command to only be accessible to people on ONE server with a specific role you should still use a backend check

modern trail
#

so essentially at the application level, all commands are available to anyone, and then i would go into the integration settings on the server to limit access to certain commands?

#

cuz i'm not sure i like that lol

lapis dock
#

Yes, you can also make them guild commands if you only want them on specific guilds

modern trail
#

my bot will only ever be in one guild

lapis dock
#

If you are concerned about it I suggest using both the integration settings and a backend check. Users who are not allowed to use the command in the integration settings will not even be able to see the command

modern trail
#

right, yea i would be fine with doing the integration settings part to make it so people who can't use the command don't see it, but i definitely feel like the backend check should be there

tiny fractal
#

i've always wondered if the integration settings in server settings hid the commands from users.. good to know

tiny fractal
modern trail
#

not sure if i want to use that has_role decorator though, still kind of considering rolling my own. it's weird that it raises an exception

tiny fractal
# modern trail not sure if i want to use that `has_role` decorator though, still kind of consid...
@bot.event
async def on_application_command_error(ctx: discord.ApplicationContext, error: commands.CommandError):
    logger.error(f'Error in command "{ctx.command}" invoked by "{ctx.author}" in "{ctx.channel}": {error}')

    error_messages = {
        commands.CommandOnCooldown: f"This command is on cooldown. Please try again in {error.retry_after:.2f} seconds.",
        commands.MissingAnyRole: "You do not have the required role to use this command.",
        commands.MaxConcurrencyReached: "This command is already in use. Please wait until it's finished.",
        commands.NotOwner: "You do not have permission to use this command.",
        commands.MissingRole: "You do not have the required role to use this command."
    }

    for error_type, message in error_messages.items():
        if isinstance(error, error_type):
            try:
                await ctx.respond(message, ephemeral=True)
            except discord.errors.NotFound:
                logger.error(f"Failed to respond to interaction: {error}")
            return

    try:
        await ctx.respond("An unexpected error occurred. Please try again later.", ephemeral=True)
    except discord.errors.NotFound:
        logger.error(f"Failed to respond to interaction: {error}")

    logger.exception(f"Unhandled exception for command '{ctx.command}' invoked by '{ctx.author}' in '{ctx.channel}': {error}")

thats why i did this

modern trail
#

interesting

#

how does default_permissions work? Doesn't that also hide the command from people without the permission? It'd be nice to have a has_role that worked the same way

tiny fractal
#

i think it just throws, if they don't have a role with XYZ permission

#

dunno about hiding it.

#

well test one sec

#

does not hide

modern trail
#

interesting, so i assume you just get a discord error when trying to use it then

tiny fractal
#

ERROR:discord:Error in command "mod testperms" invoked by "bsd_alt (ADMIN)" in "welcome": You are missing Manage Messages permission(s) to run this command.

modern trail
#

i just asked someone from my server actually what commands they see, and they don't see any of the commands that are decorated with default_permissions with a permission they don't have

tiny fractal
#

oh weird

#

oh im using @commands.has_permissions

modern trail
#

ah

tiny fractal
#

retrying

#

my alt can still see the commands

#

oh weird. it think it has permissions

#

its lying

modern trail
#

maybe restart discord?

tiny fractal
#

browser

#

yea. still visible in both client and browser

modern trail
#

odd

tiny fractal
#

maybe its a cog issue

#

lol yea i can't make any use of @default_permissions at all

#

conflicts with discord.commands and discord.ext.commands

#

yea default_permissions falsely says a user has permissions

#

atleast for me

#

lol this solves the problem

modern trail
#

i'm trying to understand how @default_permissions works. seems to modify default_member_permissions for the command object

#

which is not ideal

round heart
tiny fractal
#

guild_ids=[GUILD_ID] in your slashcommand definition?

#

ive run the same bot in multiple server, and this prevents that

round heart
#

But that requires a code change to update it

lapis dock
#

Technically it does not need to, you could implement something that changes the guild_IDs and syncs

round heart
#

Oh, is it easy to sync a single command?

#

I thought that was one of the things other Pycord devs were struggling with implementing

lapis dock
#

Wellll I dont know how well it works but you should just be able to sync and specify a command and a guild ID

round heart
#

And this was the feature that seemingly doesn't have throttles or limits?

lapis dock
#

You will have a ratelimit of 200 command CREATES per day per guild

round heart
#

It was something about updating a command that apparently was not getting hit with limits.

#

though I guess I don't know how that works in practice since you have to restart the bot to change a command (although I wonder if you could make a versioned cog, unload it, load the new version with whatever changes, and then sync those.)

errant trout
lapis dock
#

yeah, that was a later question tho.

#

BTW I have some changes for your voice encryption PR that I am opening a PR for rn

errant trout
#

go for it

lapis dock
# errant trout go for it

PRed on your branch, I think I did it right but I have never done that before so let me know if I messed up and I will get it fixed tomorrow

deft hull
#

can you use return await ctx.respond?

lapis dock
#

Yes the return just ends the callback though it does not do anything with the return value of respond

hasty meadow
#

Any suggestions for where to host discord bots? Right now I'm using an EC2 instance on AWS but it is getting expensive.

sly karmaBOT
lapis dock
#

I am not an expert on hosting though so I am only relaying the community made list

echo wraith
tiny fractal
#

can you make button views persist through bot reboots?

lofty parcel
#

Yes

#

?tag persistent

limber wagonBOT
#

dynoError No tag persistent found.

sly karmaBOT
#

The Issue

When you send a message with a view, button for example
if your bot restarts, you will lose the ability to use this button.

How To Fix This

  1. Set your view timeout to None
  • By default, the view timeout value is set to 300 seconds
  1. Pass a custom_id value to the view
  • Custom ids must be unique
  • Chose a custom id that has a meaning in relation to your view
  1. Add the view to the bot
  • You can use the method Bot.add_view(YourViewClass())
  • Make sure to add the view when the bot begin ready
rugged lodgeBOT
#

Here's the persistent example.

tiny fractal
#

cheers

tiny fractal
#

where is add_view declared?

#

it doesn't exist anywhere except as teh self.add_view

#

oh this is outside of a cog

lapis dock
tiny fractal
#

yea lol. dawned on me late

lapis dock
#

all good, subclassing bot is not all that common so its a bit weird to look at

tiny fractal
#
 message = await channel.fetch_message(message_id)
                    ^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'fetch_message'
#

but i'm looking at it...

lapis dock
#

How did you get the channel? This sounds like a get_x problem

sly karmaBOT
#

Any function that starts with get_ in Py-cord is retrieving the related object from your bots cache. If the object is not in the bots cache the get_ method will return None. Because of this behavior you should check if the get_x method is None and if it is use the fetch_x method.

Why Is Using fetch_ Without Using get_ First Bad?
The fetch_ method makes a call to the discord API. This API call is unneeded if you already have the information. It will also make your command take longer because it will have to send and than wait for a response from the discord API. It will also contribute to the discord APIs global rate limit of 50 requests per second.

What Is Cache?
The cache is a temporary storage inside your bot. It holds many objects from members to messages. When you restart your bot the cache will be empty. When the cache is full it will delete older objects to make space for the new objects.

tiny fractal
#

there is no get_message though

#

channel = self.bot.get_channel(VERIFY_CHANNEL)

#

its a task, thats why, tasks was firing before the cog was ready

#

unless i can do the same thing with get_partial_message. im using it to update a button view

lapis dock
#

I mean the other way around.
If the bot does not have the channel in cache you need to fetch it

#

Do you need to update the message on startup?

tiny fractal
#

well the button expires after a few minutes and noone can click it ever again

lapis dock
#

Your understanding on that is a bit off.
The bot stops listening for people clicking on the button after a few minutes, but people can still click it

tiny fractal
#

yea but it fails

lofty parcel
#

Then you're setting some timeout

lapis dock
#

When a user clicks a button discord will send you an interaction with a custom ID that you set when creating the button. If you did not set a custom ID pycord set one for you randomly

#

So you need to reverse your logic. Instead of saving the message/channel ID and updating the message with a new button. You should save the custom_id of the button and set up your view to start listening for button presses with that custom_id

tiny fractal
#

yea thats what i did

#

my slash command that creates the message , saves the message_id with custom_id to a json file

#

then on boot i read those values in

lapis dock
#

Then what dark said, you are not setting the views timeout to None

tiny fractal
#

its set to None

lapis dock
#

or you are stopping the view at some point

tiny fractal
#

the only timeout i have is a waiting for a message reply

#

msg = await self.bot.wait_for('message', check=check, timeout=300) # 5 minutes timeout

lapis dock
#

Can you show how you are loading the views on startup

tiny fractal
#
class VerifyView(discord.ui.View):
    def __init__(self, bot, custom_id):
        super().__init__(timeout=None)
        self.add_item(VerifyButton(bot, custom_id))
        

class Verify(commands.Cog):
    def __init__(self, bot):
        self.bot: discord.Bot = bot
        #self.update_button_task.start()
        self.persistent_views_added = False

    @commands.Cog.listener()
    async def on_ready(self):
        if not self.persistent_views_added:
            self.bot.add_view(VerifyView(self.bot, "verify_button"))
            self.persistent_views_added = True
#

ok now it seems to be working on restart with this method

lapis dock
#

and VerifyButton is using the custom_id you pass?

tiny fractal
#

gonna wait for ten minutes till it "expires" again

lapis dock
#

Yeah, this will not work with any "old" messages that dont have a custom ID

tiny fractal
#
class VerifyButton(discord.ui.Button):
    def __init__(self, bot, custom_id):
        super().__init__(label="Verify", style=discord.ButtonStyle.green, custom_id=custom_id)
        self.bot = bot
#

does this just look for any button with "verify_button" and keep it alive?

lapis dock
#

There is nothing to keep "alive"
When you send a message containing that button the custom_id is sent with it. Discord saves the custom_id for each component (on the message object itself). Whenever someone on discord uses a component discord looks at what bot sent it and then sends an interaction to that bot along with the custom_id that was original sent with the component. Then pycord matches the custom_id to a callback and runs that callback. If you dont add the view on startup pycord will not know what callback the custom_id matches, so it just ignores it.

tiny fractal
#

aah ok

#

so then no need for a task loop to keep editing the message

#

lol thanks

lapis dock
#

correct. discord does not want that because that would be a massive amount of api calls at scale doggokek

tiny fractal
#

yeah thats what i was thinking when i started writing that loop

#

this is what i've been working on with that button

round heart
#

I have been wanting to do stuff like that, but unfortunately ChatGPT makes quick work of that

sage tendon
#

I've tried a big bunch of verification systems throughout my time on Discord, and the one that worked for me best was to get a levelling bot, and limit server access to level 1. With only a welcome channel accessible otherwise. Allows you to manually weed out spammers and idiots, while letting genuine people chat for a bit until they reach level one. I also kick anyone who didn't reach level 1 within a week, and I've also made out a few sets of roles bots will always select from onboarding, so I automatically kick those as bots. Also, kicking everyone with a spammer flag is really helpful

lapis dock
#

If they join back and select the same roles does it still kick them?

valid panther
#

I am putting await ctx.defer() at the beginning of a command to wait for the response if I put ephemeral=True, it expects all results to be of type ephemeral. I can decide that x results for example if it gives KO the command shows individually to the user with ephemeral=True and if it gives OK it shows for all?

sage tendon
#

I specifically DM them telling them to select different roles if they rejoin

#

So if it's a bot that rejoins they'll be kicked again and if it's a person who pays attention they won't be
But it's very unlikely to select either of those sets of roles randomly

sage tendon
valid panther
#

Okay

sage tendon
#

you could send a message into the channel or send another response after responding to the defer, that won't be forced to be ephemeral I think

tender python
#

Am I able to have every user in my server in the cache at the same time? My server has under 20 members so I want everyone in the cache.

sage tendon
#

Yup, you need to do .

#

(it's already like that)

#

default cache size is 1000 members iirc

#

just remember you need members intent to actually receive the member objects

errant trout
sage tendon
#

dangit

#

how big is the member cache

errant trout
#

by default every member is cached

sage tendon
#

no limit?? damn

errant trout
#

if the guild is over 75k members or you don't have presences(?) intent then it's limited to online members only

#

ah not quite, those conditions only send members connected to voice

sage tendon
#

odd

errant trout
#

so by default the lib uses Request Guild Members to fill every member in chunks of 1000

edgy nest
round heart
#

7 ram

tiny fractal
#

is there a way to get the join method of users?

errant trout
tiny fractal
#

Bummer

solid sapphire
#

hi! how do I make a slash command guild_only since version 2.6?
I'm trying something like this

import discord

bot = discord.Bot()


@bot.slash_command(guild_only=True)
async def hello(ctx, text: str = ""):
    await ctx.respond("Hello!")


@bot.slash_command(contexts=set(discord.InteractionContextType.guild))
async def test(ctx):
    await ctx.respond("test")

DISCORD_TOKEN = ''

bot.run(DISCORD_TOKEN)
#

and it raises a warning for the hello command with the old methon and an error for the test command with the new one

C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\commands\core.py:736: DeprecationWarning: guild_only is deprecated since version 2.6, consider using contexts instead. See https://discord.com/developers/docs/change-log#userinstallable-apps-preview for more information.
  super().__init__(func, **kwargs)
Ignoring exception in on_connect
Traceback (most recent call last):
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\client.py", line 412, in _run_event
    await coro(*args, **kwargs)
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\bot.py", line 1214, in on_connect
    await self.sync_commands()
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\bot.py", line 742, in sync_commands
    registered_commands = await self.register_commands(
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\bot.py", line 595, in register_commands
    data = [cmd["command"].to_dict() for cmd in filtered_deleted]
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\bot.py", line 595, in <listcomp>
    data = [cmd["command"].to_dict() for cmd in filtered_deleted]
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\commands\core.py", line 962, in to_dict
    as_dict["contexts"] = [ctx.value for ctx in self.contexts]
  File "C:\Users\Admin\PycharmProjects\discordBots\.venv\lib\site-packages\discord\commands\core.py", line 962, in <listcomp>
    as_dict["contexts"] = [ctx.value for ctx in self.contexts]
AttributeError: 'int' object has no attribute 'value'
fresh sierra
#

try like so:
contexts={discord.InteractionContextType.private_channel}

solid sapphire
#

it works now

solid sapphire
sour flint
#

is it possible for a discord bot to monitor the activty of someone in discord just the spotify one
like the bot can track what music they are playing

deft hull
#

Is there an example of @after_invoke?

fresh sierra
deft hull
#

Err it's hard to explain

I want to have my bot to check the user's level and send level up messages after each command.
This would be the structure of a command:

@discord.slash_command()
async def random_command(ctx)
    ... # Command logic
    user = UserData(ctx.user.id)
    ctx.level_data = await user.add_exp(10)
class UserData:
    def __init__(user_id):
        ...
    async def add_exp(amount):
        ... # Some logic and database operations
        return {
            'hasLeveledUp': level_up,
            'level': self._level,
            'rewards': rewards
        }
#

I would like to do something like:

# After invoking the command
if not ctx.level_data['hasLeveledUp']:
    return

await ctx.followup.send(f"{ctx.user.mention}, you are now Level {ctx.level_data['level']}")
round heart
#

Your coro would have to separately look up the user in your level data as ctx.user, but at least keeps you from having to add it to every command

#

But if it’s after invoke, I don’t know if you could use followup. Would need some testing

deft hull
#

I actually want to know how to set up the decorator. Is it just @after_invoke(ctx)?

round heart
#

No, according to the docs it takes a coroutine (an awaitable method). That method is what accepts ctx

deft hull
#

Ah, so like

@commands.after_invoke()
async def something(ctx):
#

because my commands are in a Cog

round heart
#

In a cog I would think it would be (self, ctx)

deft hull
#

is this available as a Cog.listener

#

or do I have to add it to every command?

lapis dock
#

.rtfm cog_after_invoke

sly karmaBOT
lapis dock
#

I think that auto does it after every command in the cog. I have not actually used it though.

#

I don't think there is a way to do it after every listener calls as well if that is what you are asking

tender python
#

I want to have sub commands with discord app commands (e.g. /vc create instead of /vccreate). But setting the command name to vc create does not work.

lapis dock
#

You need to actually use subcommands

#

.rtfm SlashCommandGroup

rugged lodgeBOT
#

Here's the slash cog groups example.

#

Here's the slash groups example.

deft hull
# deft hull I would like to do something like: ```py # After invoking the command if not ctx...

I figured it out, you just name a method as cog_after_invoke

async def cog_after_invoke(self, ctx):
        if not hasattr(ctx, 'level_data'):
            return
        
        if not ctx.level_data['hasLeveledUp']:
            return
        
        rewards = ctx.level_data['rewards']
        level = ctx.level_data['level']

        if rewards > 0:
            await ctx.followup.send(
                f"{ctx.user.mention} Great job on reaching level {level}!\n"
                f"You earned ${rewards:,}"
            )
        else:
            await ctx.followup.send(f"{ctx.user.mention} You are now level {level}!")
indigo grove
#

does pycord support optimization flags and if so whats the max it supports?

sage tendon
#

like what

echo wraith
sage tendon
deft hull
#

That will result in an error because I am already responding to the Context in the command itself

sage tendon
#

respond handles followups

#

just try it

deft hull
#

i see, thanks

boreal coral
#

hi, when you specify debug_guilds, does application commands still take up to an hour to register with that attribute specified ?

sage tendon
#

commands dont take that long to register anymore

#

its effectively instant

#

you just need to restart discord

echo wraith
#

see

boreal coral
#

o, i c. thank u. i'm having a bit of trouble registering application commands rn so i guess im having another issue. i will make a thread for it

echo wraith
#

.tag slashnoshow

sly karmaBOT
#

Application Commands Not Showing Up?

  • Refresh Discord by restarting or pressing Ctrl+R (or Command ⌘ + R)
  • Uninstall libraries that conflict with the discord namespace (e.g. discord.py).
  • Invite your bot with the application.commands scope.
  • Load cogs before bot.run() (e.g. not in on_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.
boreal coral
#

ty

sage tendon
#

really you just need to restart discord

#

lolw

#

if you did the command right

boreal coral
#

idk T-T i made it in a cog and for some reason a test prefix command works but not the slash command

sage tendon
#

if you need slash and prefix you might wanna look into bridge

boreal coral
#

o i just want to make the slash commands tbh but i thought my cog wasnt working so i made a prefix command in it to make sure it was just the application command

sage tendon
#

show your code

#

also (already said above) dont load your cog in on ready

boreal coral
#

i should make it in a separate thread right (?)

#

i mean post

#

or idk what these things are called

echo wraith
boreal coral
#

created ! (ty for the help btw)

dry gust
#

hi! what channel_types exist in discord? Couldn't find them in docs

dry gust
#

oh wait, found it

tranquil thicket
#

I am in a predicament where a slash command that is inside a cog and a slash command that is just in the main bot.py file have the same implementation. They also both have the same exact autocomplete function. The slash command inside the cog is noticably slower, and also does not filter the options properly. video attached. Any ideas?

lapis dock
#

This should not be an issue? Are you sure it is not a difference in time between API/DB calls?

unkempt sable
#

discord.errors.HTTPException: 400 Bad Request (error code: 30032): Maximum number of application commands reached (5).

How can i make more than 5 context menu message commands?

lapis dock
#

I think you can have 5 more guild ones. But in general you cant. It is a discord limitation.

indigo grove
# echo wraith -O and -OO I think

my codebase (that heavily relies on cogs) does in fact work with python optimization flags with python -OO, and i hope this infomation helps greatly with whoever needs to know that when they use the discord search bar

quartz umbra
#

nvm

drowsy prairie
#

Could somebody help, im struggling to set up slash commands cooldown

sage tendon
#

whats the issue

drowsy prairie
#

I just dont get it

sage tendon
#

what part

drowsy prairie
#

Im trying to provide cooldown arg for @bot.slash_command decorator and it wants it to be a an instance of CooldownMapping, but i couldnt find way to create it

sage tendon
#

use the @commands.cooldown decorator below the slash command decorator

drowsy prairie
#

module 'discord.commands' has no attribute 'cooldown'

sage tendon
#

guh

drowsy prairie
#

veah

sage tendon
#

yes it does lol

#

can you show your pip list

drowsy prairie
#

its pretty long

sage tendon
#

from discord.ext import commands then @commands.cooldown()

#

are you importing it like that

drowsy prairie
#

i didnt know you need to

#

sorry

#

it works

sage tendon
#

discord.commands isn't even a thing i think, or its a shortcut for discord.ext.commands
so not sure why it didnt work

drowsy prairie
#

i tried to access it right away

sage tendon
#

yea but according to the error discord.commands exists

#

so im wondering what that points to lol

#

lets see

quartz umbra
#

How come I get this: ```
Forbidden: 403 Forbidden (error code: 50005): Cannot edit a message authored by another user

from this code? ```py
async def getmsgcount(ctx: discord.ApplicationContext, channel: TextChannel):
    message_count = 0
    message = await ctx.respond("Counting...")
    async for message in channel.history(limit=None):  # Fetch all messages
        if message_count % 100 == 0 and message_count != 0:
            await ctx.channel.send(content=f"Got {message_count} messages in the channel <#{channel.id}> so far!")
        if not message.author.bot: 
            message_count += 1
    await message.edit(content=f"Got {message_count} messages in the channel <#{channel.id}>")
sage tendon
#

rename the message var outside of the for loop

drowsy prairie
sage tendon
#

no, it does exist

#

oh bruh yea nvm im dumb it has all the non prefix command stuff

#

its just imported right into the discord namespace so you never use discord.commands.*

drowsy prairie
#

i see ty

maiden bloom
#

Is there a way to get the channels a member/user has access to in a guild without having to loop through each channel and check the permissions of it?

#

I’ve been doing this but in large servers it takes way too long

sage tendon
#

not really i think, what do you need that for

errant trout
maiden bloom
maiden bloom
errant trout
#

i mean, i can't think of any reason for why that would take more than a second or two

sage tendon
maiden bloom
# sage tendon cant you just remove all their roles lol

Yes, that’s also part of the process. It then assigns them an inmate role which has the view permissions set to deny on every single channel. That’s what takes so long is verifying that the inmate role is set properly on all the channels. Otherwise, they’d be able to see channels that @ everyone can see

errant trout
#

what's the actual code

#

this really shouldn't take more than 5 seconds

sage tendon
#

just update the overrides everytime a new channel is made or overrides are changed
or make a command like /jailrole sync or something that verifies the overrides

maiden bloom
errant trout
#

fair

hexed herald
#

hey, I've got a little issue

    @commands.slash_command(
        name="generate_password",
        description="Generate a random password.",
        contexts={
            discord.InteractionContextType.guild,
            discord.InteractionContextType.bot_dm,
            discord.InteractionContextType.private_channel
        }
    )
    async def generate_password(self, ctx: discord.ApplicationContext, length: discord.Option(
        name="password length",
        default=16,
        required=False,
        input_type=discord.SlashCommandOptionType.integer,
        max_value=1024,
        description="The length of the generated password.",)
      ):
        view = PasswordView(length=length)
        await ctx.response.send_message(
            "Please select all elements you password should contain!",
            ephemeral=True,
            view = view
        )

This command raises AttributeError: Option does not take min_value or max_value if not of type SlashCommandOptionType.integer or SlashCommandOptionType.number even through it surely is set to input_type integer.
Also if I try doing it with the decorator it's not set at all, the option shows up but without parameters.

sage tendon
#

try type=

#

and you really should use the decoraotr

hexed herald
sage tendon
#

make sure to restart discord every time

#

else you wont see the updated command

#

and also, use ctx.respond(), you dont need .response.send_message

hexed herald
#
    @commands.slash_command(
        name="generate_password",
        description="Generate a random password.",
        contexts={
            discord.InteractionContextType.guild,
            discord.InteractionContextType.bot_dm,
            discord.InteractionContextType.private_channel
        }
    )
    @discord.option(
        name="password length",
        default=16,
        required=False,
        type=discord.SlashCommandOptionType.integer,
        max_value=1024,
        description="The length of the generated password.",
    )
    async def generate_password(self, ctx: discord.ApplicationContext, length: int):
        view = PasswordView(length=length)
        await ctx.response.send_message(
            "Please select all elements you password should contain!",
            ephemeral=True,
            view = view
        )

This is the current code

sage tendon
#

you arent matching it to the argument lol

#

pass parameter_name="length"

#

and you dont need to pass contexts if you want all three i think

hexed herald
sage tendon
#

docs tell you that :)

hexed herald
hexed herald
#

already thought I am going crazy because it didn't work

tender python
#

Why cant I use ```python
@vc_group.command(name="create", description="Create a voice channel")
async def vccreate(ctx: discord.ApplicationContext, privacy: typing.Literal["Public", "Friends", "Invite only"] = "Public", name: str = None):

How else can I have a multiple choice selector
rugged lodgeBOT
#

Here's the slash options example.

tender python
# rugged lodge Here's the slash options example.

This didn't work and gives Application Command raised an exception: TypeError: issubclass() arg 1 must be a class

@discord.option("privacy", "Privacy of the voice channel", choices=["Public", "Generics", "Invite only"], required=False)
async def vccreate(ctx: discord.ApplicationContext, privacy: str, name: str = None):
lapis dock
#

The second positional argument is the type. So you either need to specify the type or add description= before the description

queen dirge
#

Is there a way to make certain commands only available in a specific server? Everything i see online just checks the server id when the command is run, but I only want the slash command to be visible in one server

lapis dock
#

Yes you can pass guild_ids=[list of ids] to your command decorator.
If you want all commands to only be on one server you can add debug_guilds=[list of ids] to your bot instance call

queen dirge
#

Ohh so like @commands.slash_command(name="name", description="description", guild_ids=[12345])?

lapis dock
#

yes

verbal torrent
#

is there a way to make, that the bot runs some async functions, when the bot gets on a new server?

verbal torrent
#

the on_guild_join?

echo wraith
#

Is it possible, in the pypi pycord version to know if a message contains a voice message ?

sage tendon
#

probably in the raw message data

silk spire
molten timber
#

These are 'NewsChannel' type correct?

lapis dock
#

Yes

molten timber
#

Thanks

lapis dock
#

Pycord does not have a class for that though. It is just a TextChannel

#

Just has is_news() and follow()

molten timber
#

and messages in the channel have the .publish()

deft kestrel
#

creating permissions required for slash commands?

sage tendon
#

Do you want to lock a slash command to certain permissions?

deft kestrel
#

yep

rugged lodgeBOT
sage tendon
#

look into that

deft kestrel
#

how can i make my messages ephemeral?

sage tendon
#

ephemeral=True

deft kestrel
lapis dock
#

yes

deft kestrel
#

thanks

queen dirge
#

How do I embed a link in an embed field title? It seems text only works in descriptions, and I saw online about { title: "title", url: "url" } but it seems to only be for main embed title?
I'm looking for here:

embed.add_field(
  name=[text](link)
  ...
#

Other searches around github issues and such suggest it might be impossible, I just wanted to make sure

queen dirge
#

Ah, thanks anyway!

silk spire
sage tendon
#

the field title is pure text

#

you can't use any markdown or mentions or anything there

lofty parcel
#

Titles and footers indeed don't support markdown

#

Title has its own link kwarg you can set

worthy knoll
#
category = interaction.data['custom_id'].lower()
lessons = file_info.get(category.lower(), [])
print(lessons, category.lower())

I'm trying to print the lessons in a subject in a json file however why does it return empty?

#

1 min

#

The JSON isn't empty but still returns []

lapis dock
#

what is file_info?

worthy knoll
#
data = ReadInfo.read_json()
file_info = data['subjects'][subject]['files']
#
def read_json():
    json_file_path = os.path.join(script_dir, 'subjects_data.json')
    
    with open(json_file_path, 'r') as file:
        data = json.load(file)
        return data
#

This one is in a file (ReadInfo) ^

worthy knoll
#

I think it's due to the accents and symbols?

echo wraith
worthy knoll
#

Thank you.

round girder
#

im having.. unexpected bahavior with views. does the timeout property start the countdown from the last interaction or from when the view is initalized? because ive been working with views for what seems like years now and im just now experiencing the first one, when ive learned to expect the second one THONK additionally there is nothing of help online, from what i can see

echo wraith
#

countdown restarts at every view interaction

round girder
#

gotcha. thanks

#

how long has that been the case?

#

let me guess, im an idiot and its been that way forever

echo wraith
#

Forever I think ?

#

I'm not sure but I never knew it differently

round girder
#

is there any way to force it to timeout in a certain amount of time

#

or would i just have to essentuially redo the timeout system

#

i think ill just do that

round girder
# echo wraith It starts from the last interaction

if i could bum another answer from you quick.. i have a view set to timout in 2 minutes. so as a test i summon the view and wait for 2 minutes but the view expires at arounf 30s. is that normal behavior?

round girder
#

alrighty

#

maybe im slightly less crazy then

round girder
#

thank you for you help

echo wraith
#

there is

rugged lodgeBOT
round girder
echo wraith
#

what I just sent

#

You create an asyncio task

round girder
#

well yeah but id have to make my own timer and everything

#

yeah i know

echo wraith
#

#1132206148309749830 message this

round girder
#

im not saying its hard im just saying its annoying i gotta add it now

echo wraith
#

yeah

round girder
#

thanks for the help man

echo wraith
#

np lmk if anything else

round girder
#

I'm really confused now

echo wraith
round girder
#

I could try yeah

#

it's in a big file. I haven't moved everything away or abstracted anything yet so like I just ran into what I thought was a small problem but now it kinda messes with my whole command. there goes 950 lines of hell

#

very ood

#

I'll add a gh issue tho yeah

round heart
#

I’ve also had some weird inconsistencies with Views. Some expiring after 15 mins despite having a longer timeout. But then when I went to explicitly recreate it, I couldn’t

#

So it’s also entirely possible discord quietly fixed something within the last year and gaslighted us all

lapis dock
#

To debug further you can give the view a timestamp when it is created and compare that timestamp in interactions and the on_timeout event

round heart
#

I know I've seen them in here before.. (doesn't seem to be in #creations) but does anyone have open examples of recording voice per user (preferably with timestamps)?

#

Oh. The sinks already do have it per user.. but is it easy to differentiate between someone speaking for 5 mins at the start of a 1 hour call, and someone only speaking for 5 mins at the end of the call? (i.e. timestamps)

lapis dock
#

Om made a PR for that a while ago I think. Iirc The silent time based on when we received the packet tho. So there can be slight shifts because of network lag

maiden bloom
#

What exactly is this asking for? I gave it a list of SKU IDs and and a list of SKU objects and it throws an error both times
It's under member.entitlements()

lapis dock
#

SKU objects should have worked, what errors are you getting?

lofty parcel
#

You can't pass a list

#

It's a list of discord.Object(id=...)s

lapis dock
#

I think all discord objects inherit from Snowflake tho

#

This is all it is doing on the backend anyways
[sku.id for sku in skus] if skus else None

frosty trellis
#

is there any way to make a bridge between normal slash commands and user commands?

#

similar to how it is possible to make a bridge between prefixed and slash commands

sage tendon
#

just make them both call the same function

frosty trellis
#

alright, thanks 👍

hazy turret
#

Is it possible if I have the author_check enabled on a Paginator that I can then return a custom message when someone tries to use the Paginator so that I don't just get “Interaction Failed”?

#

If I read this correctly in the docs, then I can only implement it manually with interaction_check and on_check_failure and leave out the author_check, right?

deft hull
#

Is there a way I can create a file for each command and register them to the same cog

tiny fractal
#

??? Why would you do that.

deft hull
#

uh my commands are getting a bit long

#

Should I still keep them all in a single file or cog

echo wraith
echo wraith
deft hull
#

yup

#

wait not subcommand group

echo wraith
#

Is that the reason why you want them in the same cog ?

deft hull
#

they're in the same cog file

echo wraith
#

A cog is a class

hazy turret
sage tendon
#

that's the entire point

deft hull
#

well, alright

lapis dock
#

You could look in to not needing cogs at all. Most people do not use the features of cogs anyways. Extensions and cogs are not required to be linked

sage tendon
#

how would you do that then

lapis dock
sage tendon
#

ah yea
kinda unnecessary tho, imo just doing it the regular cog way is simpler and less prone to errors

deft hull
#

Hi, I have a view with some buttons, and whenever a button is clicked, it sends a confirmation message to the user in ephemeral (which is another view). After confirming, the confirmation message gets edited instead of the original one.

lofty parcel
deft hull
#

Something like this

async def callback(self, interaction):
        result = await send_confirmation(
            f"Buy **{self.item_name}** for ${self.price}?",
            user = interaction.user,
            interaction = interaction
        )
        if result:
            await interaction.respond(f"You bought 1 **{self.item_name}**!", ephemeral=True)
            await interaction.edit(embed=ShopEmbed(self.user), view=Shop(self.interaction_user, self.user))
            await self.user.add_wallet(- self.price)
            await self.user.add_item(self.item_id, 1)
lofty parcel
#

That's the conformation callback?

deft hull
#

And here's what send_confirmation_message does

import discord

class Confirm(discord.ui.View):
    def __init__(self, user:discord.Member, embed):
        super().__init__(timeout=30)
        self.user = user
        self.embed = embed
        self.result = None

    async def interaction_check(self, interaction: discord.Interaction):
        ...
        
    async def on_timeout(self):
        ...
        
    @discord.ui.button(label="Cancel", style=discord.ButtonStyle.red)
    async def cancel(self, button:discord.ui.Button, interaction:discord.Interaction):
        self.result = False
        self.disable_all_items()
        self.children[1].style = discord.ButtonStyle.gray
        self.embed.title = "Action Cancelled"
        self.embed.colour = discord.Colour.brand_red()
        await interaction.response.edit_message(embed=self.embed, view=self)
        self.stop()

    @discord.ui.button(label="Confirm", style=discord.ButtonStyle.green)
    async def confirm(self, button:discord.ui.Button, interaction:discord.Interaction):
        self.result = True
        self.disable_all_items()
        self.children[0].style = discord.ButtonStyle.gray
        self.embed.title = "Action Confirmed"
        self.embed.colour = discord.Colour.brand_green()
        await interaction.response.edit_message(embed=self.embed, view=self)
        self.stop()


async def send_confirmation(message, user: discord.Member, ctx: discord.ApplicationContext=None, interaction: discord.Interaction=None, ephemeral: bool=None):
    embed = discord.Embed(title="Pending Confirmation", description=message, color=discord.Colour.yellow())
    view = Confirm(user, embed)

    if ctx:
        view.message = await ctx.respond(embed=embed, view=view, ephemeral=ephemeral if ephemeral else True)
    if interaction:
        view.message = await interaction.respond(embed=embed, view=view, ephemeral=ephemeral if ephemeral else True)

    await view.wait()
    return view.result
deft hull
lofty parcel
deft hull
#

Yup

lofty parcel
#

You then just wait for the view on your original callback

deft hull
#

hmm I'll try that

round heart
#

Are there any known/recommended 'templates' for creating a new bot (including cogs and such)? Given I haven't created one from scratch in years at this point, I'm curious if there are any resources that collect a bunch of best practices

echo wraith
round heart
# echo wraith I made one

I was just looking at this. It does look very cool, but seems more framework-y than I was personally looking for. Although I did learn about the __init__.py file, which might come in handy elsewhere.

echo wraith
round heart
#

Nope. Never built a published package, and it seemed superfluous.

#

I still don't get why there's both __init__.py and __main__.py 🤷‍♂️

echo wraith
#

e.g.

#
pythom -m src # This will run __main__.py
from src import yada, bleh # this will import from __init__.py
round heart
#

Interesting. So you could theoretically build a package as an extension that also contains a full-fledged, runnable bot (if barebones aside from the extension) if run that way?

echo wraith
#

Lots of packages from pypi allow both to be used with code and also executed from cli

sage tendon
ebon swift
#

hey all, I have a few questions , a while back, some helpers told me to not use the has_role() decorator, I need it for my bot because I'm building something that manages roles and build some games around those roles, for example a @knight can't use magic or your not the @king you can't ask @MyBot to do this. Even though I still check user roles, I agree it doesn't mean I have to use a deprecated decorator, so here are my questions:

  • Why shouldn't I use it , does it have to do with how slash commands handles contexts?
  • Is there a newer decorator to check roles of a user ? if no do you think I should make my own decorator ?
sage tendon
#

id just make my own tbh

#

never knew its deprecated tho

ebon swift
#

you're right I don't know why I remembered someone telling me it was deprecated. But in the past you told me I shouldn't use has_role cause it was an old relict

echo wraith
ebon swift
#

I'm using slash commands with has_role actually, so if there is nothing bad with it then I don't need more help

ebon swift
#

no

echo wraith
#

But how do you use has_role if it's in multipe servers

#

the roles are different between servers

ebon swift
#

it checks for specific roles and will create the one needed for the games

echo wraith
#

I'm not sure I understand

#

In any case

#

what Toothy meant was that you should edit the server's integration settings

#

and change there what role can use what command

round heart
# echo wraith I'm not sure I understand

His intention is that the bot manages the needed roles for his application - using his examples earlier, roles named "King", "Knight", etc.

He wants to be sure that application commands, when run, are checked against the named roles.

echo wraith
#

Yeah so has_role is good for that

ebon swift
#

thank you for that it helped a lots !

maiden bloom
lapis dock
#

That looks like a bug in pycord

maiden bloom
#

Oh nice I'll make a report lol

lapis dock
#

We really need to do a 2.7 release

maiden bloom
#

Ah yeah that'd be sweet

#

Guess I'll do it manually for now

lapis dock
#

I have been trying #discussion message

round heart
#

I added a voice to the echo

lapis dock
#

one of the big things is doru is not very active anymore cuz country bans

round heart
#

Oh I forgot about that. Hopefully he has a VPN?

lapis dock
#

yeah, but i think it just makes everything harder

maiden bloom
#

"You get master" 😂

deft hull
#

Hi, anyone knows what this error means?

AttributeError: property "view" of "Button" object has no setter

Update: button already has a built in view property, so renaming the property fixed the issue

high spire
#

Traceback (most recent call last):
File "c:\Users\icesc\Documents\NRTH.venv\Lib\site-packages\discord\ui\view.py", line 426, in _scheduled_task
await item.callback(interaction)
File "c:\Users\icesc\Documents\NRTH\src\cogs\verification.py", line 57, in button_callback
await interaction.response.send_modal(VerificationModal(code=self.code))
File "c:\Users\icesc\Documents\NRTH.venv\Lib\site-packages\discord\interactions.py", line 1221, in send_modal
await self._locked_response(
File "c:\Users\icesc\Documents\NRTH.venv\Lib\site-packages\discord\interactions.py", line 1292, in locked_response
await coro
File "c:\Users\icesc\Documents\NRTH.venv\Lib\site-packages\discord\webhook\async
.py", line 222, in request
raise NotFound(response, data)
discord.errors.NotFound: 404 Not Found (error code: 10062): Unknown interaction

#
class VerificationView(discord.ui.View):
    def __init__(self, *items, code:int):
        super().__init__(*items) 
        self.code = code
        

    @discord.ui.button(label="Enter Verification Code", style=discord.ButtonStyle.primary)
    async def button_callback(self, button, interaction):
        await interaction.response.send_modal(VerificationModal(code=self.code))
#

Line 57 is the await interaction response

#

added self.code as my own attribute for verification

#

I don't understand why the interaction isn't found

high spire
echo wraith
#

Does it always error like that?

high spire
high spire
#

could there be no other possible reasons?

echo wraith
#

try doing

#

await interaction.response.defer ()

high spire
#

I always get this when inputting it

echo wraith
#

Do you have a callback on your modal ?

high spire
echo wraith
#

Or do you have issues with the / command istelf ?

high spire
high spire
#

bc I get this all the time

echo wraith
echo wraith
#

it's not the same issue

#

try changing it like this

class VerificationView(discord.ui.View):
    def __init__(self, *items, code:int):
        super().__init__(*items) 
        self.code = code
        

    @discord.ui.button(label="Enter Verification Code", style=discord.ButtonStyle.primary)
    async def button_callback(self, button, interaction):
        await interaction.response.defer()
        await interaction.response.send_modal(VerificationModal(code=self.code))
#

Also it's not secure to use randint for secure code generation

high spire
echo wraith
#

Yeah no so then you simply can't

#

It's an issue with internet speed

high spire
#

bruh

#

would u recommend any other solutions

#

is there a workaround

echo wraith
#

Basically, once you recieve an interaction from discord, you have 3 seconds to respond

#

and if your internet is too slow, you can't respond in 3 seconds

high spire
#

the user has 3 seconds to respond?

echo wraith
#

No you have

high spire
#

Ohhh

echo wraith
#

once the user clicks on the button

#

or runs the command

#

or anything

#

you have 3 sec to respond with something

high spire
#

why is it that when running commands there is no issue tho?

#

wouldn't they realistically have similar requirements to run it?

lapis dock
#

Pretty sure you can't defer when sending a modal. (I can't tell if that is what you were getting at)

lofty parcel
#

You indeed can't defer to then send a modal.

eternal kite
#

can dynamic cooldown be an asynchronous function?

sage tendon
#

try it

#

i think so

sage tendon
#

i dont see what there makes it a no
i was looking at the docs as well

dense summit
echo wraith
#

That the payload is too large

dense summit
#

basically the image its too heavy?

echo wraith
#

yes

dense summit
#

strange, it worked before

echo wraith
#

if you're sending a message

dense summit
#

they changed something?

dense summit
#

do you know whats the limit?

silk spire
echo wraith
sly karmaBOT
dense summit
echo wraith
#

Oh yeah

#

there was a pr for that I made i'm pretty sure

dense summit
high spire
lofty parcel
#

And whats the error

wary portal
#

discord.errors.ApplicationCommandInvokeError: Application Command raised an exception: NotFound: 404 Not Found (error code: 10015): Unknown Webhook What does this error mean?

lapis dock
silk spire
frail basin
#

Also, convert self.code to a str

late slate
echo wraith
#

that's the latest

late slate
#

Awesome, just thought I was goin crazy for a sec 😅 Thx

high spire
deft hull
#

How do you define autocomplete for an Option? This is my function

def get_matching_items(cls, ctx:discord.AutocompleteContext):
        '''Returns a list of matching item names based on user input.'''
        cls._load_data()

        if not cls._item_metadata:
            return []
        
        all_names = [
            data['name']
            for data in cls._item_metadata.values()
            if 'name' in data
        ]
        
        user_input = ctx.value.lower().replace(' ', '')
        matches = [
            name
            for name in all_names
            if name.lower().replace(' ', '') == user_input
        ][:25]

        return matches
high spire
#

Can anyone tell me why my buttons aren't showing up?

#

Only the Resend Code button shows up

#

No errors or anything

#

nvm figured it out

#

each button needs its own callback function

#

why is that?

#

if it's all under the same decorator and has its own label won't it differentiate it

frail basin
#

If you have multiple functions with the same name, in the same scope, then it will always prioritize the "bottom" one.

high spire
#

ic

high spire
#

why do I keep getting this?

#

I gave the server id

#

I suspect its because discord.Client.get_guild isn't supported? so I just have to use the instance of the discord.Bot setup in my main file, which isn't connected to my cog?

#

So how would I be able to use bot.get_guild() when my cog doesn't inherent the bot

ionic wasp
#

inherit the bot i guess

high spire
ionic wasp
#

doesnt every cog automatically inherit it

high spire
#

i don't think so

silk spire
#

interaction.client will return your bot instance

#

And you're probably also passing the bot to the cog and have defined it as self.bot

high spire
#

actually yes, the cog inherits from discord.ui.Modal

high spire
silk spire
#

Ah you're talking about a class

echo wraith
silk spire
#

Not specifically a commands.Cog

high spire
#

and I'd have to pass it through from the initial Commands.Cog to the View to the Modal

high spire
silk spire
echo wraith
# high spire Ic

Can you please make sure pycord is up to date and you don't have other discor dlibs installed ?

silk spire
#

Get your OOP knowledge up lmao

echo wraith
#

Yeah no then that must be it

#

...

high spire
#

Thanks guys for all the help anyways

silk spire
#

lol

class MyClass:
    def method(self, arg):
        pass

MyClass.method("arg")  # error: MyClass.method() missing 1 required positional argument: 'arg'
MyClass().method("arg") # valid

inst = MyClass()
inst.method("arg") # valid
flat wind
#

Hello !!
Does anyone know how I can avoid these errors ?

  File "/usr/local/lib/python3.12/site-packages/discord/client.py", line 412, in _run_event
    await coro(*args, **kwargs)
  File "/usr/local/lib/python3.12/site-packages/discord/bot.py", line 1214, in on_connect
    await self.sync_commands()
  File "/usr/local/lib/python3.12/site-packages/discord/bot.py", line 761, in sync_commands
    app_cmds = await self.register_commands(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/discord/bot.py", line 538, in register_commands
    prefetched_commands = await self._bot.http.get_guild_commands(
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/discord/http.py", line 368, in request
    raise Forbidden(response, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50001): Missing Access

They are happening when I start the bot

#

nvm it was a guild_ids=[...] argument with a server ID where my bot is not in..

sage tendon
sage tendon
#

for a class to be a cog it needs to subclass discord.Cog

#

if it doesnt its not a cog

#

@high spire @ionic wasp just to get you two straight on vocabulary

inherit means when you take over things from a superclass when you subclass a class
import (which you probably meant) is importing a value from another file, or a module etc

#

just so it doesnt cause confusion later on

wise harness
#

Do grouped slash commands not work with user apps? For example I have this: (which doesn't register)

        discord.IntegrationType.guild_install,
        discord.IntegrationType.user_install,
    }, description="Get general stats of a player.")```
#

but this does:

@commands.slash_command(integration_types={
        discord.IntegrationType.guild_install,
        discord.IntegrationType.user_install,
    }, description="List of commands.")
lofty parcel
#

You probably need to register the whole group as user installable.

#

Subcommands are not treated as separate commands by Discord.

high spire
maiden bloom
#

It’s not possible to set a bot’s status message on a guild-by-guild basis, is it?

sage tendon
#

no

high spire
sage tendon
modern trail
#

Is it possible to prevent a paginator from timing out?

sage tendon
#

timeout=None?

modern trail
#

oh, how did I not see that. So it defaults to 180 seconds?

sage tendon
#

yea

modern trail
#

i got too distracted by the disable_on_timeout kwarg

#

which only applies to the buttons for some reason

#

boy i'm dumb. thanks for being my rubber duck as always toothy

#

perhaps one of these days i'll learn how to read

high spire
#

ohh in setup right

#

so is setup automatically called in the main file?

sage tendon
#

yes

#

god where do people keep getting the fucking if name is main from

high spire
#

i dunno docs i think

#

is that bad practise

sage tendon
#

its completely and entirely unnecessary

high spire
#

ic

lofty parcel
#

It's a common thing

sage tendon
#

i know what it is

#

it is utterly pointless in a discord bot

lofty parcel
#

well

lofty parcel
#

Its worded in a terrible way

#

Its a way to check if the script is the main program

edgy nest
#

it prevents the code inside it from running if the file was imported

#

it only runs if the file was the original script that got ran

ionic wasp
#

does the on_disconnect event happen everytime the shard resumes a session?

tiny fractal
#

400 Bad Request (error code: 50034): You can only bulk delete messages that are under 14 days old.
is this a new thing?

lapis dock
#

Discord has stronger limits on older messages

upper slate
#

Are there built in DOS protections? That is, if someone spams a command for 24 hours + is this inherently dealt with? I know slow mode exists, just wondering if I have to deal with this edge case in my code

sage tendon
#

no

silk spire
#

that's why the lib deletes messages older than 14 days one-by-one in purge

upper slate
lapis dock
upper slate
sage tendon
#

typically you dont need cooldowns unless your code does something else that counts against an APIs ratelimit or is otherwise heavy on compute

upper slate
#

SQL queries take place on the backend so just don't want the workers being unecessarily taxed

modern trail
#

I want to have a job get added to a scheduler in one of my cogs, and was gonna put that logic in cog_load, but i'm realizing pycord doesn't have that. Would it make sense to put this logic in the cog's __init__ method?

lofty parcel
modern trail
#

oh, like i can just throw

@bot.event
async def on_ready():

directly into the class or something?

lofty parcel
#
@commands.Cog.listener()
async def on_ready(self): 
modern trail
#

i see

#

i'll try that, thank you

lapis dock
#

you would want to throw a once=True in the listener

#

What does your situation look like? You could also add it to the setup() function instead of in the cog

modern trail
lapis dock
#

When you say "job" are you talking about ext.tasks or your own system?
And are you planning on running the job ever X seconds?

modern trail
#

i want to have it essentially invoke the weekly command every friday at 4pm ET. So i was gonna schedule it with apscheduler. ext.tasks didn't seem equipped for that to me

lapis dock
#

Yeah, init, event or setup should all work. init is probably the easiest.

modern trail
#

oh so you think it's fine to just dump it in the cog's __init__?

lapis dock
#

I am not familiar with apscheduler but if the add job function is not async then it should be fine. The cogs init gets called once when the cog is added to the bot so it seems like a good place to put it

modern trail
#

gotcha

hasty meadow
#

Anyone else having issues playing audio files within channels on latest discord version (Android) ?

lapis dock
#

Like with a bot or on discord in general?

lapis dock
#

on_shard_disconnect fires everytime the shard disconnects

#

on_shard_resumed fires everytime a shard resumes

hasty meadow
lapis dock
#

This function can be called many times without a corresponding on_connect() call.
This is relevent as well

lapis dock
hasty meadow
lapis dock
#

I dont think mobile ever had audio file playbacks
Note: there is a difference between sending a voice message and an audio file. A voice message will work on mobile

shell radish
#

at least in ios

lapis dock
#

Huh, I might be wrong then.

shell radish
#

it was added fairly recently

#

but yes

high spire
#

i don't understand

#

675238101253226500

#

instead of

#

675238101253226496

#

it's like rounding my user id

#

to the nearest 100

high spire
#

please help

silk spire
ionic wasp
#

for userapps, can i somehow get a event if a specific message of the bot was deleted?

silk spire
#

Not if the bot isn't even in the server

ionic wasp
#

so also not in dms? rip

silk spire
#

That would make it a user bot technically lol