#dev-contrib

1 messages Β· Page 24 of 1

patent pivot
#

well we'd have both

#

snekbox allows to ls, users are expected to define a custom layer to add their executables somewhere, users are expected to have their snekbox API clients know where that's going to be

tawdry vapor
#

I think we either have an ls API, or we have a ListExecutables API which is basically like ls but hard-coded to look in a specific directory.

patent pivot
#

i like ls or just /glob or something

#

that way users can load executables into anywhere they want

tawdry vapor
#

I'm open to the idea. My initial feeling is that exposing ls as an API feels really weird.

#

Then again we are effectivly exposing exec as an API already so might not be much of a stretch

#

It's just that ls feels very broad

#

Like, I don't see a use case where someone would want to ls a directory that isn't the one containing their executables

#

But we would allow that anyway for the sake of not hard-coding an executable dir.

patent pivot
#

I don't think we need to expose the binary

#

I'd just take a glob in and return everything that matches the glob with +x set

tawdry vapor
#

Wait wait wait

#

We already allow executing arbitrary binaries

#

And ls should be in the image already

#

So... isn't this already possible?

#

Ah no it's not cause it runs in a jail

tawdry vapor
#

Anyway I'm not totally against the idea

#

It may make more sense in the context of a larger reorganisation of snekbox i.e. splitting it into the three components I mentioned above

patent pivot
#

yeah

#

I particularly dislike the coupling of our specific versions and libraries and snekbox itself

#

and do agree with reorganising

#

I'd prioritise that, splitting the execution and http API is an easier task

patent pivot
#

like PATH + /executables/

tawdry vapor
#

At that point why not restrict the prefix instead? I don't think it's unreasonably restrictive to require executable to be under /snekbin/ if you want them to be discoverable by the API.

#

And with such name it's unlikely to conflict with anything else they might put in the image

patent pivot
#

ya true

tawdry vapor
#

What I like about that is the caller of the API doesn't need to know what the path is.

patent pivot
#

yeah

#

true

#

okay so we make /snekbin/ or whatever exposed over the API, return everything with +x in there and people don't need to worry about paths.

do we still allow for arbitrary paths to be passed in and executed?

tawdry vapor
#

do we still allow for arbitrary paths to be passed in and executed?

Good question. Multiple facets to this:

  1. Do consumers directly expose the API endpoint / with a thin wrapper/proxy? Or do they have a more sophisticated wrapper like our bot? In the former, I can see how restricting the path would be useful, since that is effectively end-user input. In the latter, it's not as useful since the path is either not controlled by end-users, or can be validated/filtered before reaching snekbox.

  2. If a consumer exposes a binary that can execute arbitrary code (namely, the exec syscall and its friends), then such restriction would be moot. That is indeed the case for our use case.

#

That said I do see how it's a bit confusing to only expose binaries in a certain directory, but still allow any path to be executed.

patent pivot
#

re: 2, is it moot? we don't mount additional binaries so the risk of exec(3) into a different executable is mitigated right?

tawdry vapor
#

Hmm yeah

#

We do mount shared libraries though

patent pivot
#

ahh true

tawdry vapor
#

Anyway if you can execute arbitrary code like with Python, you can effectivelly implement whatever binary you'd want to execute anyway?

patent pivot
#

true lol

#

i suppose we don't overcomplicate it, stick to one directory & expose that, and if we get a surprise feature request from the White House in 4 years because they want to run /usr/bin/fortune then we add a flag for allowing arbitrary paths

tawdry vapor
#

Well currently we allow arbitrary paths, so changing the default behaviour would be a breaking change.

#

Though I don't know how many other users of snekbox we have

#

Especially cause we don't really have proper versioning

patent pivot
#

oh yeah so we do

#

I thought we constrained to /snekbin/ already

#

hmmmm

#

i'd change it to a flag then and it's still breaking but purposefully is just an opt-in

#

we do need to consider how we pass in all those env vars for python that we currently have in the nsjail config

tawdry vapor
#

Yeah...

patent pivot
#

we can obv easily dynamically add those like we dynamically amend the nsjail config already

#

but just need to decide where they come from

#

it's getting towards config file but i'm not sure if that's clean or something we want

#

config file to specify those env vars as well as other tweakable attributes doesn't seem a terrible idea

tawdry vapor
#

What makes this tricky is that there are some things in the config that someone would likely never want or need to touch, but other things that they would almost certainly need to change

patent pivot
#

like our limits on threads and whatnot is again something we shouldn't build into the image

#

yeah

#

i think it's reasonable to expose the simple things like max threads, max memory, additional mount dirs & env vars

#

everything else seems like it'd be heading towards compromising the integrity of the sandboxing

tawdry vapor
#

Ehh well I don't want to have to maintain our own config system and translate it to nsjail. Not that it's super difficult, but it just adds complexity

#

It might be sufficient to provide a template and have folks copy it to customise things

patent pivot
#

hmmm yeah

tawdry vapor
#

And we can move some things out of the config and into command-line nsjail args

patent pivot
#

just annotate the heck out of things where removing them will compromise it

#

yea

#

true

tawdry vapor
#

We already have some hard-coded nsjail args which override the config. But currently we only do that out of necessity, since some config values are dynamic

patent pivot
#

yea

#

I suppose first steps here is open an issue and figure what the line is and what goes on the downstream user side

#

i am glad to say goodbye to the init container to install deps lol

tawdry vapor
#

"customer experience" as they call it in the business

#

We do need to flesh out a design

patent pivot
#

DevRel Chief Mark

#

client success officer

trail widget
#

Hi, @patent pivot and @tawdry vapor

#

Nice to meet you all

#

if you have some problem, let me know

lunar oxide
#

i wanna friend πŸ™

toxic wren
#

what's the new smart-eval?

toxic wren
#

How do I run the bot locally to test?

patent pivot
toxic wren
#

<@&831776746206265384>

#

Scammer

patent pivot
#

?

toxic wren
#

Open the likely spammer thing and see the images

patent pivot
#

there aren't any messages there

toxic wren
#

wdym?

patent pivot
#

probably got picked up and banned

toxic wren
#

I see images

patent pivot
#

reload your discord?

toxic wren
#

Oh, now they are gone

#

Probably got lagged out

#

or something

toxic wren
#

finally got it running locally. my computer is kinda bad btw

#

It's so laggy

#

Where do you guys host the bot?

patent pivot
toxic wren
patent pivot
#

they are but we've been using them since before akamai took over

toxic wren
patent pivot
#

which issue are you seeing thay

#

Sentry is our error tracker so only core team members can log in

toxic wren
patent pivot
#

ahhh

cold island
#

the link is for core devs but the issue should have all the relevant details

patent pivot
#

that's a mistake

cold island
#

oh

patent pivot
#

our sentry tickets are in the format BOT-ABC123

#

but it's seen bot-commands and assumed that's a sentry ticket

#

so has tried to add a link to sentry

#

don't worry about the link, it's a mistake that GitHub added thay

#

that*

toxic wren
#

oh, ok It was asking me to login via github and I don't want to login to random websites

cold island
#

the website is safe it'll just reject you lol

toxic wren
#

Just making sure

toxic wren
#

I found lookatmybeard.com in test_snekbox.py line 352. What is it and what does it do?

timid sentinel
#

Probably just made up test data

toxic wren
#

I can't seem to find a connection between the redirects and snekbox commands.

#

I found the connection between redirects and non-snekbox commands

patent pivot
toxic wren
#

where are all the cmds listed?

#

or are they all in different places?

vale ibex
#

!help

stable mountainBOT
#
Command Help

Big Brother
!bigbrother
Monitors users by relaying their messages to the Big Brother watch channel.
!bigbrother unwatch <user> <reason>
Stop relaying messages by the given user.
!bigbrother watch <user> <reason>
Relay messages sent by the given user to the #big-brother channel.

Bot
!echo [channel] <text>
Repeat the given message in either a specified channel or the current channel.
!embed [channel] <text>
Send the input within an embed to either a specified channel or the current channel.

BotSource
!source [source_item]
Display information and a GitHub link to the source code of a command, tag, or cog.

Branding
!branding
Control the branding cog.

vale ibex
#

!src echo

stable mountainBOT
#
Command: echo

Repeat the given message in either a specified channel or the current channel.

Source Code
vale ibex
#

as an example

toxic wren
vale ibex
#

Yah, use the !src command to get a link to that command in the code

toxic wren
#

oh ok

#

I understand it now

toxic wren
#

@patent pivot , I just finished the !eval function to send the original message with the output here is an example:
@toxic wren, here's the output of your command:
Command:
!eval

print("hello")

Output:
βœ… Your 3.13 eval job has completed with return code 0.

hello
patent pivot
toxic wren
patent pivot
#

yeah you just need to take the original message content, create a PasteFile based on that and use that method

#

then the response is something like ```
Here's the output of your command:

<output>

toxic wren
#

I see that the !eval function has a way of splitting the code from the command, How do I do the same thing here?

patent pivot
#

I wouldn't do that -- just make this a generic change to that decorator

#

paste the code verbatim with markdown formatting and the rest should be handled by the pastebin

#

literally just needs to be the original message content

toxic wren
patent pivot
#

no, include with the command so people can just copy paste straight out of the paste

#

but as mentioned use markdown/md formatting instead of python/py

toxic wren
#

so the lexer arg should be md?

patent pivot
#

yea

toxic wren
#

ok

patent pivot
#

maybe markdown i'm not sure exactly whether it wants the extension or lexer name

toxic wren
patent pivot
#

looks like markdown looking at how the web UI does it

toxic wren
#

btw Im adding a fallback for when The pastebin fails it sends the code in the message directly

#

@patent pivot I just got everything working, Ill commit and open a PR and ref the issue. Sound good?

patent pivot
toxic wren
patent pivot
#

raise a warning log and return the current response we have with no link

toxic wren
#

What is the difference between log.trace and log.info ?

#

and which should I use?

patent pivot
#

trace is for development

#

info is the base level shown in production

#

if you're talking about the log for the paste service being down, use log.warning

toxic wren
#

ok

#

@patent pivot

#

Take a look at PR 3377

patent pivot
#

Will do shortly πŸ‘

toxic wren
#

Take your time

patent pivot
#

hang on I'm confused why you've done it here

#

updating the decorator would've been the clean way that then works for all redirected commands

#

the decorator code is linked in the original issue

toxic wren
#

I thought I was only doing the !eval

patent pivot
stable mountainBOT
#

bot%2Fdecorators.py line 112

def redirect_output(```
toxic wren
#

nvm I'll do it in the decorator then

#

πŸ‘

patent pivot
#

the bot#3376 issue I wrote I left generic to cover commands including !eval

toxic wren
#

yeah, its not your fault my english is kinda bad so I thought it was for !eval

#

Ill make the changes

patent pivot
stable mountainBOT
#

bot%2Fdecorators.py line 158

await ctx.send(f"Here's the output of your command, {ctx.author.mention}")```
patent pivot
#

you can do [your command]({paste_response.link}) or whatever and it'll embed a link

#

and an else claude will be needed to carry the context for when we don't ping the user

patent pivot
#

else clause*

toxic wren
#

oh I thought you were talking about the model

patent pivot
#

yeah I'm too claude-addicted

toxic wren
#

I don't really have any paid subscriptions for any of the Ai stuff

tame pebble
#

or else I'll ping volcy

toxic wren
#

The redirect output dec is:

@redirect_output(
        destination_channel=Channels.bot_commands,
        bypass_roles=SNEKBOX_ROLES,
        categories=NO_SNEKBOX_CATEGORIES,
        channels=NO_SNEKBOX_CHANNELS,
        ping_user=False
    )

ping_user=False
but the user gets pinged when redirected

#

for the eval command btw

patent pivot
#

uhhhh

stable mountainBOT
#

bot/exts/utils/snekbox/_cog.py line 596

@redirect_output(```
patent pivot
#

it isn't the decorator pinging

toxic wren
patent pivot
#

yeah, but we should just have it reply in snekbox channels, and not do anything in non-snekbox then enable ping_user

toxic wren
patent pivot
#

I'm on mobile right now so can't validate everything 100%

#

it might not need changing at all

#

but we do need to have the redirect decorator send a message because that's where the paste link will be created

toxic wren
patent pivot
#

it already does that right?

#

either way it's probably out of scope for this issue

#

these things don't need changing

toxic wren
patent pivot
#

basically all this needs to be (in pseudocode) is:

content = original_message.content
paste_link = send_to_paste_service(...)

if ping_user:
  await ctx.send(f"Hey @user! Your output from [your command]({paste_link})")
else:
  await ctx.send(f"The output from [your command]({paste_link})")
#

that's very rough but that's literally all that this needs

#

the new else clause and the pasting of the code

patent pivot
#

so we disabled the redirect doing the ping

toxic wren
patent pivot
#

yes, because there's an if statement where it chooses whether to ping or reply

stable mountainBOT
#

bot%2Fexts%2Futils%2Fsnekbox%2F_cog.py line 441

if ctx.message.channel == ctx.channel:```
patent pivot
#

in theory you don't need to touch that file at all though

patent pivot
toxic wren
patent pivot
#

where do they override decorator behaviour?

#

I don't know what you mean by that

#

the pinging and handling should remain as is and you really shouldn't need to touch _cog.py in snekbox

patent pivot
toxic wren
stable mountainBOT
#

bot%2Fdecorators.py line 158

await ctx.send(f"Here's the output of your command, {ctx.author.mention}")```
toxic wren
#

so it essentially overrides what the decrators says

patent pivot
toxic wren
patent pivot
#

because that's done inside the !eval command

#

ping_user is in case there's a chance a command would be redirected and the command wouldn't ping the user to show that it's been redirected

toxic wren
#

!src eval

stable mountainBOT
#
Command: eval

Run Python code and get the results.

Source Code
patent pivot
#

but we know for snekbox it will always be pinged

patent pivot
#

and you just need that additional else clause which can be a non-pinging version for snekbox

patent pivot
#

pinging: f"Here's the output of [your command]({paste_link}), {ctx.author.mention}"

non-pinging: f"Here's the output of [your command]({paste_link})"

#

and that's what you need in your if-else

toxic wren
#

For the paste service the arg http_session I am passing in self.bot.http_session, which worked in /-cog.py but does not in decorators. What should I pass in

patent pivot
#

I think you can probably safely just create your own client session with a context manager

#

I can't remember if we decided there were or weren't risks of doing that

toxic wren
#

It worked in the _cog.py beautifully but now i get a AttributeError: 'CustomHelpCommand' object has no attribute 'bot'

patent pivot
#

create a new client session

toxic wren
#

is there a method for this?

patent pivot
#

look elsewhere in the code for aiohttp.ClientSession

toxic wren
#

ok

patent pivot
#
from aiohttp import ClientSession

async with ClientSession() as session:
  # pass "session" in here to paste method

# do rest of processing
#

something like that

#

but obviously in the method

#

and only the actual pasting inside that with block so that the session closes afterwards

toxic wren
#

Done. updating PR

#

@patent pivot Take a look when you can

patent pivot
patent pivot
#

also because it's probably going to annoy me (I know it's nitpicky) can you add colons to the end of both the message lines?

toxic wren
#

or the tottal end

patent pivot
#

after the end of the line

#

pinging: f"Here's the output of [your command]({paste_link}), {ctx.author.mention}:"

non-pinging: f"Here's the output of [your command]({paste_link}):"

toxic wren
#

@patent pivot Updated

patent pivot
toxic wren
patent pivot
#

yeah, then just needs a bit of nice conditional logic to handle the message in the following situations:

  • ping, with link
  • no ping, with link
  • ping, no link
  • no ping, no link
#

so instead of the if/else it might be best to build a message gradually

#
msg = ""

if ping_user:
  msg += f"{ctx.author.mention}, "

msg += "Here's the output of "

if paste_link:
  msg += f"[your command]({paste_link}):"
else:
  msg += "your command:"
#

same place you import send_to_paste_service from

#
from pydis_core.utils.paste_service import PasteUploadError, send_to_paste_service
toxic wren
#
except PasteUploadError:
                log.warning("Pastebin Upload Error")

this is the except statement.

patent pivot
#

I'd update to use log.exception

#

captures the exception info

#

also I'd do a bit more of a descriptive line

#

"Failed to upload original command to paste service when redirecting output"

toxic wren
patent pivot
#

maybe throw the original message ID in as well

toxic wren
patent pivot
#

log.exception("Failed to upload message %d in channel %d to paste service when redirecting output", ctx.message.channel.id, ctx.message.id)

#

I think that should do it without being messed by the redirection

patent pivot
patent pivot
#

to build the message

toxic wren
#

Doing something like this.

try:
                paste_link = None
                async with ClientSession() as session:
                    paste_response = await send_to_paste_service(
                            files=[PasteFile(content=ctx.message.content, lexer="markdown")],
                            http_session=session,
                        )
                    paste_link = paste_response.link
                msg="Here's the output of [your command]({paste_link}),"

                if ping_user:
                    await ctx.send(f"{msg} {ctx.author.mention}:")
                else:
                    await ctx.send(f"{msg}:")
                scheduling.create_task(func(self, ctx, *args, **kwargs))
            except PasteUploadError:
                log.exception("Failed to upload message %d in channel %d to paste service when redirecting output", ctx.message.channel.id, ctx.message.id)
patent pivot
#

your try except is too big there

#

the only line that can raise PasteUploadError is the send_to_paste_service, so it's not worth putting everything inside it

#
paste_link = None

async with ClientSession() as session:
  try:
    paste_link = ...
  except ...:
    log.exception(...)

# put my block from above here

await ctx.send(msg)
#

it'll end up looking way cleaner

#

your proposal there still doesn't send when it can't get a paste link which we want it to do

toxic wren
# patent pivot your proposal there still doesn't send when it can't get a paste link which we w...

yeah just fixed it, looks like this now:

try:
                paste_link = None
                async with ClientSession() as session:
                    paste_response = await send_to_paste_service(
                            files=[PasteFile(content=ctx.message.content, lexer="markdown")],
                            http_session=session,
                        )
                    paste_link = paste_response.link

            except PasteUploadError:
                log.exception("Failed to upload message %d in channel %d to paste service when redirecting output", ctx.message.channel.id, ctx.message.id)

            if ping_user:
                await ctx.send(f"Here's the output of [your command]({paste_link}), {ctx.author.mention}:")
            else:
                await ctx.send(f"Here's the output of [your command]({paste_link}):")
            scheduling.create_task(func(self, ctx, *args, **kwargs))
patent pivot
#

that still won't do it

toxic wren
#

I didn''t add the blocks yet

patent pivot
#

the try except needs to be inside the async with

#

the try except needs to literally have 1 line inside it

toxic wren
#

The try has this:

paste_response = await send_to_paste_service(files=[PasteFile(content=ctx.message.content,lexer="markdown")],http_session=session,)
paste_link = paste_response.link
patent pivot
#
paste_link = None

async with ClientSession() as session:
  try:
    paste_response = await send_to_paste_service(...)
    paste_link = paste_response.link
  except ...:
    log.exception(...)

msg = ""

if ping_user:
  msg += f"{ctx.author.mention}, "

msg += "Here's the output of "

if paste_link:
  msg += f"[your command]({paste_link}):"
else:
  msg += "your command:"

await ctx.send(msg)
#

this will do it

#

exactly that with no changes

#

you'll need to fill in the exception and the arguments to send_to_paste_service

#

but don't add any more into the try except or move around where paste_link is defined

#

you've also got some lifting failures for your last commits so you'll need to check those

#

but using the structure I sent above might fix some of them

toxic wren
#

I have 6 lint errors in the decorator file. Fixing βš™οΈ

#

This line is too long log.exception("Failed to upload message %d in channel %d to paste service when redirecting output", ctx.message.channel.id, ctx.message.id)

patent pivot
#
log.exception(
  "... message ...",
  ctx.message.channel.id, ctx.message.id
)
toxic wren
#

@patent pivot Done.

patent pivot
#

you need to remove that first ctx.send from the ping_user block

#

right now it's going to send two messages when ping_user is true

patent pivot
patent pivot
#

bot#3377 ready for staff review for any staff members who read this chat

dusky shoreBOT
toxic wren
#

@patent pivot I am mentioning you in the Accessibility section in GitHub in the issues, for Issues I can fix, Please take a look at them and see If you can Assign them to me.

#

Ill take some for now and take a look at others later.

toxic wren
#

@patent pivot Merging is disabled, Does another member need to review before merging?

thorny obsidian
dusky shoreBOT
thorny obsidian
toxic wren
#

Review requirements: mainWaiting for status to be reported β€” 0/1 rules approved

#

and joe approved the changes hours ago

thorny obsidian
#

You can click in on that for more details about the rules required.

#

You can see we require 2 approvals. One must be from a core dev, the second can be from anyone on staff.

toxic wren
toxic wren
#

I thought 1 approval like normal should be enough

thorny obsidian
#

We require 2 for a lot of our projects, especially for one as critical as our Python bot.

toxic wren
#

Is there like a staff channel where this is posted?

thorny obsidian
#

Well generally if something is time sensitive we have core devs aware and working on it. I don't believe your PR is time sensitive, so there's no harm in waiting.

2 are needed for anything in our bot repo because of how critical it is to this server and what it does.

patent pivot
toxic wren
patent pivot
toxic wren
#

πŸ‘

patent pivot
#

i saw the contributor discussion internally and have put my thoughts there, i have thoughts that go with it about ensuring the PRs received remain high quality

patent pivot
patent pivot
#

also important to mention with all this: the contributor role is a reward that is voted on based on longer term contribution quality, and the things I mentioned were more things to achieve over a longer term rather than trying to speedrun.

there is still a vote that has to be passed and you shouldn't be trying to get as much done expectedly for this, moreso longer contribution will be rewarded with it.

toxic wren
dim pelican
#

I do like the colors

toxic wren
#

Joe, I do not see your commens on GitHub, but I see them in my email. Is this some kinds of issue or have you not commented on the issue yet?

#

I see. them now, some kind of browser issue on my side.

#

Firefox.

toxic wren
#

is there a !src command for the discord site?

patent pivot
#

there is not a !src command for site no, but just searching through with ctrl+f (project wide) generally finds things well on site

toxic wren
#

@patent pivot I have completed changing the accessibility issues site#1382 , site#1381 and site#1406. Should I create a PR?

patent pivot
#

yep create a PR whenever -- however also bear in mind that Mark and Stelercus have left feedback for you on bot#3376

toxic wren
patent pivot
#

or bot#3377 rather

dusky shoreBOT
toxic wren
patent pivot
toxic wren
#

I don't know how to make a ternary condition. And deleting the paste can be done.

patent pivot
#
msg += f"[your command]({paste_link})" if paste_link else "your command"
#

with mark's comment about switching the ordering back it's gonna be like uhhh

toxic wren
#

I don't really understand why we need a ternary condition. For future contibutors the if statement will be easier.

patent pivot
#

it'll end up being neater

toxic wren
#

commiting gimme a minute

patent pivot
#
msg = "Here's the output of "
msg += f"[your command]({paste_link})" if paste_link else "your command"
msg += f", {ctx.author.mention}:" if ping_user else ":"
patent pivot
#

175 to 183

toxic wren
#

This resolves Mark's comment right?

patent pivot
#

yeah

#

generally i'd comment that something is resolved and let the original commenter mark it as resolved so they can acknowledge you have made the changes in the way they're thinking

toxic wren
#

what about Mark's second comment?

#

about the empty message

patent pivot
#

resolved by using the ternaries as above

#

so just comment that it's resolved through the later changes and leave it to be marked as resolved

mild arch
#

not sure if this is like a known issue but i am pretty sure that date is wrong

#

the oct 10th, 2022

mild arch
#

i mean 3.13 was only released in oct 2024 so probably just the year is wrong

#

it’s probably a simple fix

toxic wren
#

yes, it was streamed on oct 9 the 2024

patent pivot
#

yea looks like a copy paste error somewhere lol

toxic wren
#

lmao

patent pivot
#

can be changed when someone looks at accessibility or redoes the timeline next

#

not urgent

toxic wren
#

should I bundle this with my changes?

mild arch
#

all good

patent pivot
mild arch
#

i remember doing a fair bit of work on the timeline a long time ago

#

somehwere deep in git history

patent pivot
#

there's already issues about alt text on that page & staff look at the timeline semi-regularly

toxic wren
#

btw site#1562

dusky shoreBOT
patent pivot
#

ah, then maybe fine to add in a separate commit

toxic wren
patent pivot
#

though if we're not squashing this one you might want to get familiar with git rebasing and force pushing instead of adding loads of commits to git history

#

also your change to that file currently seems to be removing alt text

toxic wren
toxic wren
#

ah

#

timeline.html

patent pivot
#

I haven't fully reviewed it yet and it might make sense for that to be removed

#

so don't take this as a review

toxic wren
#

I was because in one of the issues it said the word "Logo" is generic and the logo provides no value to the person so no alt-text needed

patent pivot
toxic wren
#

but will check it out

patent pivot
#

yea, this will be that use, you can change the wording of old commits and include new changes in old commits

#

then you force push that to github and it's a new history instead of adding new commits to the old history

toxic wren
patent pivot
#

no you can change the commit message

toxic wren
patent pivot
#

not really

#

for example your bot PR

#

it's changing one block of code

#

so it doesn't need 11 commits

#

it needs 1 commit

toxic wren
#

yeah

patent pivot
#

so when we merge that we'll squash it down into 1 commit titled something like "Preserve invocation context when redirecting command output"

toxic wren
#

Oh file name says' 2024 but the inside says 2022

#

interesting

#

pushed site#1562

dusky shoreBOT
toxic wren
#

btw can you assign the issues site#1382 , site#1381 and site#1406 to me? If you are on your laptop.

patent pivot
#

assigned -- but it's really not necessary now you've got a PR and dropped the comments

toxic wren
patent pivot
#

no, the issues close if you write the correct thing in the PR body

#

I'm just editing it in now

toxic wren
#

Oh, I am learning something new everyday.

patent pivot
#

it's this thing

#

assigning the issues doesn't really do anything other than putting your name in the side

toxic wren
#

What I see

#

Only 2?

patent pivot
#

try refresh

#

oh wait

#

yea i unlinked one accidentally

#

fixed

toxic wren
#

yea works now

#

I will rebase the changes on bot#3377

dusky shoreBOT
patent pivot
#

i wouldn't worry -- we'll just squash that one down when we merge it

#

it's literally going to change 1 block of code and isn't worth a force push

#

the only thing left on that is the removal links

#

then stel & mark just need to have a look again

toxic wren
#

Should I do the removal link?

patent pivot
#

that's what the review says yea

toxic wren
#

nvm I will

patent pivot
#

you might need to do a bit of changing about what you store from the paste response

patent pivot
#

worth changing paste_link into just paste_response and instead of using paste_link use paste_response.link

toxic wren
#

ok

patent pivot
#

because then you can use paste_response.removal

toxic wren
#

Ok

#

Do I need to DM them?

patent pivot
#

DM who?

#

oh the author of the command?

#

yeah

toxic wren
#

Person who made the command

#

ok

#

So it's just:await message.author.send(content=f"[Click here](<{paste_response.removal}>) to delete your recent paste.")?

patent pivot
#

yes but change the message to fit this context

toxic wren
#

so like "Click here to delete paste made by the bot from your code"

#

not really good at english

#

So if you find any mistakes let me know

patent pivot
#

f"Your command output was redirected to <#{Channels.bot_commands}>. [Click here](<{paste_response.removal}>) to delete the automatically uploaded copy of your original command."

#

will need splitting across multiple lines

toxic wren
#

Will do

toxic wren
#

message.author.send give me undefined name 'message'

#

doe it need an import

#

is it ctx?

patent pivot
#

you can probably just do ctx.author.send though

toxic wren
#

Errors:
The bot does not send a paste link anymore and goes to the else statement and the removal link does not exist.

#

πŸ˜”

#

Debug session complete βœ… :
The bot goes to the else statement even though the generation of the link is successful and it works(added print in the code). Ternary issue?

patent pivot
#

show your code?

toxic wren
#
paste_link = None
            async with ClientSession() as session:
                try:
                    paste_response = await send_to_paste_service(
                        files=[PasteFile(content=ctx.message.content, lexer="markdown")],
                        http_session=session,
                    )
                except PasteUploadError:
                    log.exception(
                        "Failed to upload message %d in channel %d to paste service when redirecting output",
                        ctx.message.channel.id, ctx.message.id
                    )

            msg = ""

            msg = "Here's the output of "
            print(paste_response.link)
            msg += f"[your command]({paste_response.link})" if paste_link else "your command"
            msg += f", {ctx.author.mention}:" if ping_user else ":"

            await ctx.send(msg)

            #Send a DM to the user about the redirect and pastebin removal
            await ctx.author.send(
                content=
                f"Your command output was redirected to <#{Channels.bot_commands}>. [Click here](<{paste_response.removal}>) to delete the automatically uploaded copy of your original command."
            )

patent pivot
#

yeah because now you're not setting paste_link

#

all references to paste_link need to be paste_response

toxic wren
#

oh, my bad. Im so stupid

patent pivot
#
paste_response = None
async with ClientSession() as session:
  ...

msg += f"[your command]({paste_response.link})" if paste_response else "your command"
#

etc.

toxic wren
#

Yup all good.
bot#3377
site#1562

patent pivot
toxic wren
toxic wren
#

Fixed

toxic wren
#

@patent pivot

try:
                # Send a DM to the user about the redirect and paste removal
                await ctx.author.send(
                        f"Your command output was redirected to <#{Channels.bot_commands}>."
                        f" [Click here](<{paste_response.removal}>) to delete the pasted"
                        " copy of your original command."
                )
            except Forbidden:
                log.warning("Redirect output: Failed to send DM to user. Forbidden.")

and from discord import Forbidden

Is this right and the way you want be to do?

patent pivot
#

but otherwise yeah, if that's the only error we risk raising for non-error scenarios that's fine

oblique cairn
vale ibex
toxic wren
#

I am trying to test DM behavior.
I am testing uploading a .py file directly so the bot will ask me to make a paste bin and DM me the removal link.

It works differently locally and in the server is this a config change?

The server send me removal link but the local bot only send me this
"Hey @toxic wren!
It looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com/"

Where as the server one sends
"Click here to delete your recent paste."

And when I block the bot the server bot still send me a message but it is hidden I can choose to see it.
whereas the local one does not send anything

Why is the behavior different?

toxic wren
#

@patent pivot

patent pivot
toxic wren
patent pivot
#

ahh

#

i'm not entirely sure what you have tried to do here -- but it sounds like you maybe ignored instead of blocked?

toxic wren
patent pivot
#

then i'm not sure -- if you have truly blocked the bot and it attempts to send a DM to you then it will raise Forbidden

toxic wren
patent pivot
#

the behaviour you are describing is not possible

#

the bot cannot send a message "either way", it tries to send a message and gets "Forbidden" back and that's that, no message is sent

toxic wren
#

changes made. pushed.

patent pivot
toxic wren
#

linting errors fix in progress

#

@patent pivot done. ready for review

#

applied arg changes

patent pivot
#

@toxic wren it was not my suggestion, my suggestion was catching the error because it's not actually an error.

When you log things as warning or error in our projects it creates a new Sentry ticket because it assumes that the behaviour should never happen, so catching the error here is good, but I purposefully did not say warning because we don't want to stop it from causing an error and then raise an error ticket anyway

toxic wren
#

site#1562

dusky shoreBOT
idle solar
#

hi folks, I'd love to contribute to python/cpython with performance improvements... Is there a place where this is discussed and I could learn more?

vale ibex
zealous kite
#

Hello everyone,
I'm seeking assistance and feedback on my new open-source package, fastjson-db. It's a lightweight NoSQL database designed for speed and simplicity.
I would greatly appreciate any help with testing, code review, or general feedback on its functionality and usability. Your insights would be invaluable!

This is my first open-source package, so mistakes are expected. Feel free to open issues or pull requests.
Check it out here: https://github.com/MauricioReisdoefer/fastjson-db
Thank you in advance for your time and support!

GitHub

Contribute to MauricioReisdoefer/fastjson-db development by creating an account on GitHub.

celest charm
cedar frigate
#

I love this emote chefskiss ferrisChefKiss

cold island
#

<@&831776746206265384>

amber gyro
#

!compban 1208806390378922005

#

!cpban 1208806390378922005

oblique cairn
#

!compban 755318700357451836

cold island
#

bot's not responding for now

#

you can ban manually and delete

celest charm
cold island
#

ah right right

cold island
celest charm
#

I probably should've been more clear/nuanced, there are two kinds of except clauses:

  • The first one is when you're catching an exception that's part of the function's interface (usually it's a library function), where it's functioning more as a return value. Usually the except clause is aimed at a very specific exception that's a leaf in the exception hierarchy or close to that.
  • The second one is when you're catching when "something goes wrong" but you're not sure what, when or where in the call stack it happens. Usually the except clause has Exception or a broad base class like IOError or e.g aiohttp.exceptions.ClientError
celest charm
cold island
#

yeah it can be useful, just need to figure out how to word it so it's not used in the wrong cases

#

something like !exc-logging

celest charm
# cold island something like !exc-logging

I'm thinking of something like:

When reporting or logging an exception, you might be tempted to call str on the exception or put the exception directly into an f-string like so:

try:
    quack()
except DuckError as exc:
    print("Quacking failed:", exc)  # or: + str(exc)
    logger.error(f"Quacking failed: {exc}")

This is often a bad idea because it removes much of the useful information, including the traceback and even the class of the exception.

>>> fruits = {"apple": "a", "cherry": "c"}
>>> try:
...     print(fruits["banana"])
... except Exception as e:
...     print(f"Something went wrong: {e}")
Something went wrong: 'banana'

When using logging, use the exc_info argument to log the exception with its traceback

>>> try:
...     print(fruits["banana"])
... except Exception as e:
...     logger.error("Bananas out of stock:", exc_info=e)
ERROR:root:Bananas out of stock:
Traceback (most recent call last):
  File "<python-input-19>", line 2, in <module>
    print(fruits["banana"])
          ~~~~~~^^^^^^^^^^
KeyError: 'banana'

If you cannot use logging, you can use the traceback module to format the exception using the print_exception or format_exception functions:

>>> try:
...     print(fruits["banana"])
... except Exception as exc:
...     print("".join(traceback.format_exception(exc)))
Traceback (most recent call last):
  File "<python-input-40>", line 2, in <module>
    print(fruits["banana"])
          ~~~~~~^^^^^^^^^^
KeyError: 'banana'
#

wow this is long

#

unacceptably long even

#

Does discord still not have collapsible embeds?

cold island
#

don't think so

celest charm
#

understandable, they are carrying out other important tasks like moving the search bar

cold island
#

lol

#

they actually did improve embeds recently

atomic ivy
#

/nitpick

celest charm
#

the exc_info parameter is more flexible, you can e.g. include a traceback in a warning (which would be the appropriate level for a retry function, I think)

atomic ivy
#

-# At least to me

celest charm
#

We could have a very condensed tag with more nuance, and link to a larger article

atomic ivy
celest charm
#

the tag would be something like:

When logging an exception, don't pass it to str() or place it inside an f-string placeholder. That removes valuable information from the exception:

>>> fruits = {"apple": "a", "cherry": "c"}
... try:
...     print(fruits["banana"])
... except Exception as exc:
...     print(f"Something went wrong: {exc}")
Something went wrong: 'banana'

Instead, use the exc_info parameter when using logging, or the traceback module to print the exception type, message and its traceback:

>>> try:
...     print(fruits["banana"])
... except Exception as exc:
...     logger.error("Something went wrong: ", exc_info=exc)
...     # or: traceback.print_exception(exc) when not using `logging`
ERROR:root:Something went wrong: 
Traceback (most recent call last):
  File "<python-input-47>", line 2, in <module>
    print(fruits["banana"])
          ~~~~~~^^^^^^^^^^
KeyError: 'banana'
#

actually, that's probably good enough for a tag on its own

#

!embed
When logging an exception, don't pass it to str() or place it inside an f-string placeholder. This removes the traceback and the class from the exception, making it very hard to investigate what happened and debug the problem. ```

try:
... print(fruits["banana"])
... except Exception as exc:
... print(f"Something went wrong: {exc}")
Something went wrong: 'banana'
Instead, use the exc_info parameter when using logging, or the traceback module to print the exception type, message and its traceback:
try:
... print(fruits["banana"])
... except Exception as exc:
... logger.error("Something went wrong: ", exc_info=exc)
... # or: traceback.print_exception(exc) if not using logging
ERROR:root:Something went wrong:
Traceback (most recent call last):
File "<python-input-47>", line 2, in <module>
print(fruits["banana"])

      ~~~~~~^^^^^^^^^^

KeyError: 'banana'

stable mountainBOT
#

When logging an exception, don't pass it to str() or place it inside an f-string placeholder. This removes the traceback and the class from the exception, making it very hard to investigate what happened and debug the problem. ```

try:
... print(fruits["banana"])
... except Exception as exc:
... print(f"Something went wrong: {exc}")
Something went wrong: 'banana'
Instead, use the exc_info parameter when using logging, or the traceback module to print the exception type, message and its traceback:
try:
... print(fruits["banana"])
... except Exception as exc:
... logger.error("Something went wrong: ", exc_info=exc)
... # or: traceback.print_exception(exc) if not using logging
ERROR:root:Something went wrong:
Traceback (most recent call last):
File "<python-input-47>", line 2, in <module>
print(fruits["banana"])

      ~~~~~~^^^^^^^^^^

KeyError: 'banana'

celest charm
#

@cold island thoughts?^

#

btw: if you specify a code block like this without a new line, discord doesn't add huge padding for it, as demonstrated above (compare to any other tag with a code block). Perhaps our bot could automatically perform this fixup

stable mountainBOT
#

No newline ```py
print("hello, world!")


---

With newline
```py
print("hello, world!")

Newline after


With two newlines

print("hello, world!")

Two newlines after

celest charm
#

"With two newlines" is how reasonable Markdown code is usually written

cold island
#

Instead, use the exc_info parameter when using the logging module, or the traceback module, to print the exception type, message and its traceback:

#

Otherwise looks solid

celest charm
#

I think I lost the `s somewhere while copypasting

celest charm
cold island
#

it's just a bit more space under the first codeblock and it makes reading easier

celest charm
#

This is what "with newline" looks like btw. Not with the extra empty space as found in markdown commonly

#

actually apparently our tags already follow this, i'm surprised

#

well, not everywhere

toxic wren
#

what does the !shh command do?

#

in this server

patent pivot
#

silences a channel for moderators to intervene

celest charm
#

!help shh

stable mountainBOT
#
Query "shh" not found.
celest charm
#

!help silence

stable mountainBOT
#
Command Help

!silence [duration_or_channel] [duration=10] [kick=False]
Can also use: hush

Silence the current channel for duration minutes or forever.

Duration is capped at 15 minutes, passing forever makes the silence indefinite. Indefinitely silenced channels get added to a notifier which posts notices every 15 minutes from the start.

Passing a voice channel will attempt to move members out of the channel and back to force sync permissions. If kick is True, members will not be added back to the voice channel, and members will be unable to rejoin.

celest charm
toxic wren
celest charm
#

I think I accidentally left the reply ping off

cedar frigate
fallen patrol
#

(highlight lines on a diff)

cold island
fallen patrol
#

it wasn't always

dusky shoreBOT
toxic wren
#

and site#1562

dusky shoreBOT
austere hornet
#

Hello, just wanted to follow up again on my 2 open Lancebot PRs:
sir-lancebot#1690
sir-lancebot#1694

Would someone be able to review these soon? Thanks in advance for your time.

timid sentinel
#

Pretty busy at the moment so won't make any promises but I will keep in mind that there are other PRs needing review

toxic wren
#

Guys i need review on :
bot#3377
site#1562

fallen patrol
#

sheesh its been a while

fallen patrol
#

well I'm just gonna assume that if the emoji text is right then it works lol

#

fffffun I didn't realise there wasn't a formatter

patent pivot
toxic wren
stable mountainBOT
#

Please react with βœ… to upload your file(s) to our paste bin, which is more accessible for some users.

toxic wren
#

Sorry, for the late commit @patent pivot but in bot#3377 is this what you were talking about?

if RedirectOutput.delete_invocation:
                paste_response = None
                async with ClientSession() as session:
                    try:
                        paste_response = await send_to_paste_service(
                            files=[PasteFile(content=ctx.message.content, lexer="markdown")],
                            http_session=session,
                        )
                    except PasteUploadError:
                        log.exception(
                            "Failed to upload message %d in channel %d to paste service when redirecting output",
                            ctx.message.channel.id, ctx.message.id
                        )
    
                msg = "Here's the output of "
                msg += f"[your command]({paste_response.link})" if paste_response else "your command"
                msg += f", {ctx.author.mention}:" if ping_user else ":"
    
                await ctx.send(msg)
    
                try:
                    # Send a DM to the user about the redirect and paste removal
                    await ctx.author.send(
                            f"Your command output was redirected to <#{Channels.bot_commands}>."
                            f" [Click here](<{paste_response.removal}>) to delete the pasted"
                            " copy of your original command."
                    )
                except discord.Forbidden:
                    log.warning("Redirect output: Failed to send DM to user. Forbidden.")
    
                scheduling.create_task(func(self, ctx, *args, **kwargs))
    
                message = await old_channel.send(
                    f"Hey, {ctx.author.mention}, you can find the output of your command here: "
                    f"{redirect_channel.mention}"
                )
dusky shoreBOT
patent pivot
#

you still need to define paste_response and you don't need any of the message stuff in the if statement

#

it literally needs to be the async with block

toxic wren
# patent pivot it literally needs to be the `async with` block

so, this?

if RedirectOutput.delete_invocation:
                paste_response = None
                async with ClientSession() as session:
                    try:
                        paste_response = await send_to_paste_service(
                            files=[PasteFile(content=ctx.message.content, lexer="markdown")],
                            http_session=session,
                        )
                    except PasteUploadError:
                        log.exception(
                            "Failed to upload message %d in channel %d to paste service when redirecting output",
                            ctx.message.channel.id, ctx.message.id
                        )
patent pivot
#

no, you need to define paste_response outside the if statement

toxic wren
#

I thought you said var too?

#

@patent pivot

patent pivot
#

that's my mistake then

toxic wren
toxic wren
toxic wren
patent pivot
#

What error?

toxic wren
# patent pivot What error?
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint:   git config pull.rebase false  # merge
hint:   git config pull.rebase true   # rebase
hint:   git config pull.ff only       # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.
patent pivot
#

hmmm

#

what did you try do to get here

#

i'd just do git config pull.rebase true and then git pull

toxic wren
patent pivot
#

on your branch or on main?

toxic wren
patent pivot
#

huh

#

your branch shouldn't have changed unless you changed it

#

main has changed

toxic wren
patent pivot
#

run git pull --rebase

toxic wren
# patent pivot run `git pull --rebase`

get this

Auto-merging bot/decorators.py
CONFLICT (content): Merge conflict in bot/decorators.py
error: could not apply 1c256aac... Add if statement
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>", then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase --abort".
Could not apply 1c256aac... Add if statement
patent pivot
#

right then go resolve that conflict

#

and then follow those instructions

toxic wren
#

btw add if statement is local commit

patent pivot
#

the git errors do tell you mostly what you need to do

patent pivot
#

i suspect that's what the conflict is

patent pivot
#

yea that's where the conflict came from

toxic wren
#

rn

#

and my local changes are gone

patent pivot
#

follow the instructions in the error, you need to go open that file and resolve the conflict and then run git rebase --continue

#

the errors in git tell you what you need to do to fix things and not lose your work

#

you shouldn't have had to do any resetting here

toxic wren
patent pivot
#

as long as you have the same history that is currently on github you just need to add that change back and push your new commits

toxic wren
#

how do I update

patent pivot
#

pull

toxic wren
patent pivot
#

yes

#

it will mirror the changes that are in github

toxic wren
patent pivot
#

which changes, your new if statement?

toxic wren
#

I will lose all my work right?

patent pivot
#

run the following ```
$ git stash
$ git pull
$ git stash apply
$ git stash drop

toxic wren
patent pivot
#

right then I'm really confused

#

so you need to update it before you can add your if statement

patent pivot
#

your older changes are on github so you need to have those reflected locally

#

git pull will pull the newer changes from github to your local copy of decorator.py

toxic wren
#

basically I just cloned the cloud repo again

patent pivot
#

so then you don't need to do anything if you've cloned it again?

#

you jsut need to add the new changes and commit and then push that

toxic wren
patent pivot
#

oh right

toxic wren
#

fyi I am on preserve-invocation-context branch

patent pivot
#

so you mean how do you update the changes from python-discord back in so your branch isn't out of date

#

is your local copy of main up to date?

#

try run git rebase main whilst you are on your preserve-invocation-context branch and then run git push --force

toxic wren
patent pivot
#

oh right

#

well do that first

#

go to your fork in github and update the fork

toxic wren
patent pivot
#

no because you'll need to sync the fork

toxic wren
#

oh, on github

patent pivot
#

yes

#

and then run git pull on main

toxic wren
patent pivot
toxic wren
patent pivot
#

yep

toxic wren
#

@patent pivot Done. Check it out bot#3377

dusky shoreBOT
toxic wren
#

and btw can you take a looka t site#1562

dusky shoreBOT
patent pivot
toxic wren
patent pivot
toxic wren
# patent pivot 2

2 staff memebers right? Markoz is core dev and jschrist is staff I think, so I need 1 more staff

patent pivot
#

mark is staff

#

it says there you have "1/2 required approvals"

toxic wren
patent pivot
#

yes

#

trust me i wrote these rules

#

you need 1 more approval

#

mark approved as a core dev and staff, that means there is 1 more staff or core dev approval needed

#

all core devs are staff

toxic wren
fallen patrol
#

but now lol

patent pivot
#

huh

#

waht

fallen patrol
#

yeah

#

policy bot is entirely behind github auth now

patent pivot
#

yeah i know that

#

buti'm confused why you can't use the oauth login

#

can you not see it>?

#

maybe because it's an org app or something

fallen patrol
#

I'm already logged in and not authenticated

#

if I'm logged out

#

it 404s for me because 404 is 403

patent pivot
fallen patrol
#

yeah

#

what app did you call it

patent pivot
#

huh yeah

fallen patrol
#

yeah says its a private app

patent pivot
#

interesting

patent pivot
fallen patrol
#

@patent pivot what bot does this? (I know its self hosted)

patent pivot
#

Palantir project

fallen patrol
#

gotcha

fallen patrol
#

I have so many questions about how does this anagram code work because I don't think that's a word

patent pivot
#

hmmm

#

competing is

#

coempting is also a word β€” but going by google results primarily in scrabble lol

#

the source word/concept

#

i do feel like we could potentially try pick from a bit of an easier english dictionary for that feature though

#

instead of just picking a full dictionary we look for like top 10k words or something

celest charm
#

smh why is there no type checker in CI

patent pivot
#

oooo

#

good spot

#

I wonder how many get flagged on current bot lol

celest charm
patent pivot
#

wtf really lol

celest charm
patent pivot
celest charm
stable mountainBOT
#

pydis_core/__init__.py line 19

__all__ = [module.__name__ for module in __all__]```
celest charm
#

basedpyright just gives up on this

#

was someone's " key broken that day?

patent pivot
celest charm
#

Let's see if I can find any actual bugs with a type checker

patent pivot
#

lol

#

given the number of sentry alerts we receive on bugs that are solvable via type checking

#

i'm sure you will

celest charm
#

a useless but technically valid bug: replace items in typing that were deprecated by PEP 585 (like List and Collection)

#

well, I found a typing bug in frontmatter...

patent pivot
#

excellent

outer oasis
celest charm
#

A lot of the errors are going to be of the form Cannot assign "X | None", X expected

patent pivot
#

yeah

#

see that's the problem i have had and I think chris has had with a lot of our discord.py stuff

celest charm
#

I might have to think with the brain to resolve those ones

patent pivot
#

the typing on discord.py means that contextually we know that something can never be the case, but the type validator will want us to explicitly check a lot of things

celest charm
#

But the good thing about baseline is, we can leave them alone and think with brain later

patent pivot
#

like we know if we put a predicate on a command to make it guild only then ctx.guild is going to exist, but the type checker obviously doesn't know that and doesn't see that

celest charm
#

!pep 505

stable mountainBOT
celest charm
#

with how much python developers love None, it's annoying to deal with it sometimes. smh

patent pivot
#

I suppose we stop typing stuff as Context and create some sort of narrowed subtype GuildOnlyContext

#

because we have a type error on basically every command that uses ctx.guild because we always use a guild only decorator

#

can you validate signatures that get passed into decorators?

#

using a static type validator that is

celest charm
#

wdym

patent pivot
#

like if I have ```py
class GuildOnlyContext(Context):
guild: Guild # redeclare as non-optional

Disallow this

@guild_only
@bot.command()
def do_something(ctx: Context) -> None:
print(ctx.guild.name)

Allow this

@guild_only
@bot.command()
def do_something(ctx: GuildOnlyContext) -> None:
print(ctx.guild.name)

#

basically that

celest charm
#

it would have to be in this order ```py
@bot.command()
@guild_only

#

or you could override command in our bot such that, if ctx is annotated with GuildOnlyContext, it automagically makes the command guild-only

patent pivot
#
P = ParamSpec("P")
R = TypeVar("R")

def guild_only(
    func: Callable[[GuildOnlyContext, *P.args, **P.kwargs], R],
) -> Callable[[Context, *P.args, **P.kwargs], R]:

    @wraps(func)
    def wrapper(ctx: Context, *args: P.args, **kwargs: P.kwargs) -> R:
        ...

    return wrapper
#

something like that right?

celest charm
#

yeah

patent pivot
#

i guess there is the newer syntax for that without paramspec etc.

celest charm
#

you also might need inspect.markcoroutinefunction

#

because @wraps doesn't propagate the fact that func is an async def function

patent pivot
#

however, the baseline mode you sent the link to is quite cool

#

and absolutely could be fun to try on a repo

celest charm
#

It's fine to add hacks or unsound things, and we could just # type: ignore like we do with ruff lints

patent pivot
celest charm
#

sadly it might be too slow to run in a pre-commit hook

patent pivot
celest charm
patent pivot
#

if we use baseline then yeah i'd just add this as another non-required workflow

celest charm
#

Here's an example of a None issue that's not related to discord: https://github.com/python-discord/bot/blob/fe2dabfc54e14ab360d7e1147dd9ce43caf31cfc/bot/exts/backend/branding/_repository.py#L206

blah blah blah download_url could be None
relevant class: ```py
class RemoteObject:
sha: str # Hash helps us detect asset change.
name: str # Filename.
path: str # Path from repo root.
type: str # Either 'file' or 'dir'.
download_url: str | None # If type is 'dir', this is None!


A more static-typing-oriented approach would be making a class for a file and another for a directory (or something to that effect), and then the `fetch_directory` method would have to somehow link the `types`. For example:
```py
@overload
async def fetch_directory(self, path: str, types: Literal["file"]) -> dict[str, RemoteFile]: ...
@overload
async def fetch_directory(self, path: str, types: Literal["dir"]) -> dict[str, RemoteFile]: ...
@overload
async def fetch_directory(self, path: str, types: Literal["*"] = ...) -> dict[str, RemoteFile | RemoteDir]: ...
``` or something more complicated. It is 100% true that it will be extra work, but it will catch some bugs
stable mountainBOT
#

bot/exts/backend/branding/_repository.py line 206

meta_bytes = await self.fetch_file(contents["meta.md"].download_url)```
celest charm
#

so just like with tests, maybe errors could be fixed in code that's frequently edited, or is critical to our operation. And other errors can be left as is

#

Branding updates? Doesn't really matter if it breaks

patent pivot
#

yea

stable mountainBOT
#

bot/exts/help_channels/_channel.py lines 194 to 199

try:
    # Fetch the post again, to ensure we have the latest info
    post = await get_or_fetch_channel(bot.instance, post_id)
except discord.HTTPException:
    log.trace(f"Not closing missing post #{post} ({post.id}).")
    return```
celest charm
#

"post" is unbound

patent pivot
#

hhaahaha

#

yeah

#

looks like the log was copied from the same template a couple of lines below

celest charm
#

small bug in discord's typing:

    @_cog_special_method
    def cog_check(self, ctx: Context[BotT]) -> bool:
        """A special method that registers as a :func:`~discord.ext.commands.check`
        for every command and subcommand in this cog.

        This function **can** be a coroutine and must take a sole parameter,
        ``ctx``, to represent the :class:`.Context`.
        """
        return True
``` return type should've been `-> bool | Coroutine[Any, Any, bool]`

seems like we're going to encounter a lot of annoying things like this
stable mountainBOT
#

bot/utils/messages.py lines 206 to 211

def sub_clyde(username: str | None) -> str | None:
    """
    Replace "e"/"E" in any "clyde" in `​username`​ with a Cyrillic "Π΅"/"Π•" and return the new string.

    Discord disallows "clyde" anywhere in the username for webhooks. It will return a 400.
    Return None only if `​username`​ is None.```
celest charm
#

The cursed substitution aside, str | None -> str | None just for the convenience of when you might have none is something that won't work well with type checkers. In a statically typed language you have stuff like Option::map, but alas we don't

tawdry vapor
celest charm
#

I don't like how import = automatically export in Python.

fallen patrol
fallen patrol
fallen patrol
timid sentinel
#

I'm really not a fan of baseline checks, at least not for now.

#

As I think a lot of issues require refactoring or changes to multiple areas of code, and a baseline would make adding new code a pain before these are done.

halcyon jetty
#

yo

timid sentinel
#

I think it would work fine for people to just make PRs improving typing without using a type checker in CI, as they should be improvements regardless.

patent pivot
#

not required for merge

#

i mean we could even dynamically generate that baseline state for the PR if we wanted -- very clearly demonstrate exactly what's going on with typing for a subset of changes

toxic wren
#

@patent pivot @oblique cairn I have made the changes in site#1562 check it out!

dusky shoreBOT
toxic wren
#

yes! finally bot#3377 is merged.

dusky shoreBOT
patent pivot
#

very nice

#

#bot-commands message and working

toxic wren
fallen patrol
patent pivot
#

huh

#

why did that trigger a devops review lol

#

oh

#

pahahahahahahaha

#

pattern is .github/*

#

but it's regex not a globbing pattern

#

very funny

cold island
#

where did the forward slash go πŸ€”

patent pivot
#

hahaha

#

* is zero or more

cold island
#

oooh lmao

patent pivot
#

fix was ^\.github/

cold island
patent pivot
#

hahahaha

#

going by the other patterns in that file, it appears i wrote it as both a regex and glob at the same time

fallen patrol
snow yacht
#

I am having issues getting the test environment up and running, docker compose works to start everything inside docker, but it looks like the bot gets stuck waiting to acquire a lock for 'filtering.check_bad_name'

#

i.e. when I go to bot commands on the test server and type !help, it reacts and checks whether the channel is a help channel, but always ends on this log line and doesn't create a message on the test server

bot-1        | 2025-09-24 23:39:20 | DEBUG | bot.utils.lock | _check_bad_display_name: acquiring lock for resource 'filtering.check_bad_name':158020687850766338...
toxic wren
snow yacht
#

Sec PC just crashed

toxic wren
snow yacht
#

This is what I was using

#

Let me double check there is nothing I skipped

toxic wren
snow yacht
#

I've made no changes other than string values (that don't impact logic)

#

unless there was a broken state on main

toxic wren
snow yacht
#

by envserver script you mean the configure task? I did this

#

ok

toxic wren
cold island
snow yacht
#

do you want me to nuke the venv too? or only the repo stae

toxic wren
#

oh it exsits

stable mountainBOT
#
Contribute to Python Discord's open source projects

Looking to contribute to Open Source Projects for the first time? Want to add a feature or fix a bug on the bots on this server? We have on-going projects that people can contribute to, even if you've never contributed to open source before!

Projects to Contribute to

  • Sir Lancebot - our fun, beginner-friendly bot
  • Python - our utility & moderation bot
  • Site - resources, guides, and more

Where to start

  1. Read our contribution guide
  2. Chat with us in #dev-contrib if you're ready to jump in or have any questions
  3. Open an issue or ask to be assigned to an issue to work on
toxic wren
#

Was this in !help?

#

I dont remember seing this

patent pivot
#

do any other commands work? !ping etc.

#

have you also added the "admins" role (whatever role you have that configured to in your env file) to yourself?

snow yacht
snow yacht
#

I did no extra config other than running the config uv script

#

and writing the .env files

patent pivot
#

to maybe help a bit, can you do the following:

  • add a new env variable BOT_TRACE_LOGGERS=*
  • start the bot and attempt to run a command like !help or !ping
  • quit the bot
  • upload the logs to https://paste.pythondiscord.com/

you might want to read through the logs before you upload to check there's nothing sensitive in there

#

it'll generate a lot of noise

#

basically turning all the loggers to max

toxic wren
cold island
#

you still need to apply the role

patent pivot
snow yacht
#

I used the template

patent pivot
#

yeah

patent pivot
#

the bot doesn't look at ownership

#

it looks at roles

snow yacht
#

I did it manually because I thought it might give me access to the /command for the voice gate message

toxic wren
snow yacht
#

(give myself the role)

patent pivot
#

it's unlikely that's the problem because even unprivileged commands aren't working here

#

but yeah i'd get a trace log dump together and we can have a look what's going on in there

cold island
snow yacht
#

the self role assignment appears to work

toxic wren
snow yacht
#

maybe an issue with being unable to create new messages?

toxic wren
#

Giving it privileged gateway intents?

patent pivot
snow yacht
#

yes

patent pivot
#

there's no need to start afresh, we can try and debug what is going on here long before we need to suggest people reclone repos, all that does is help people lose work

patent pivot
#

and if we're assumging a permissions error you'd definitely see that logged in some way

toxic wren
snow yacht
toxic wren
#

And it cant give itself those roles

patent pivot
#

there should be a role for bots in the template with the necessary permissions

toxic wren
#

so yeah

snow yacht
#

surely not !help though right

cold island
#

I'd elliminate the easy to see problems first Β―_(ツ)_/Β―

toxic wren
patent pivot
#

i can't remember the other permissions in that template, it's unlikely to be the problem, but ensuring that both you and the bot have roles is a godo start

cold island
#

For example the bot might have perms to see the channel but not write in it

#

Having the right role solves that

toxic wren
#

For my contrib I gave it the "Python" role and it worked

#

for commands such as eval, help,etc

patent pivot
#

yea

toxic wren
#

there are roles such as "Super bot"

#

Which I did'nt need for normal setup, so this is not a permissions error, unless the config is wrong.

#

bot-1 | 2025-09-24 23:39:20 | DEBUG | bot.utils.lock | _check_bad_display_name: acquiring lock for resource 'filtering.check_bad_name':158020687850766338...

#

was the error

cold island
#

it's not an error

patent pivot
#

that is not an error

toxic wren
#

I mean log

cold island
#

I would start with giving the bot admin perms and then continue with what joe outlined

toxic wren
#

check_bad_display_name? is that referring to the people in the server?

cold island
#

yes

snow yacht
#

alright, I stopped and deleted all running containers, am now running

toxic wren
#

or is it just a check

cold island
#

it's a check on the names of people who write in the server

toxic wren
#

only you?

snow yacht
#

me and the bot

toxic wren
cold island
#

the check runs anyway

patent pivot
# toxic wren who is in the server?

(if you are asking because of that debug log I assure you it's unrelated -- it's very out of the way of the command processing logic in the bot)

cold island
#

it's not related to whether it succeeded or not

snow yacht
#

ah wait I should paste the entire log

cold island
#

Just so we're on the same page here, did you give the bot the necessary role?

snow yacht
#

I just assigned it admins and superbot

#

but not before attempting the first message

#

no difference

#

I am trying !help in #bot-commands (on the test server obviously ^^)

patent pivot
#

asking some questions that might be obvious, but just sanity checking:

  • are you using the right prefix (i know you said the bot was reacting, but just double checking)
  • are any other commands working? (e.g. !ping)
snow yacht
#

same deal for !ping

#

how can I tell if another prefix is configured at runtime?

#

it's sourced from .env right?

cold island
#

yes

#

did you set it in .env?

snow yacht
#

fml

#

(usually use either nvim or pycharm)

cold island
#

you should turn on auto-save

snow yacht
#

I do, but I am remaking my config from scratch

#

ty (sorry for noob issue ^^)

cold island
#

no worries

snow yacht
#

is there a test hook for metricity to initialize it with given state to test voice gate behavior (or anything else relying on metrics)?

patent pivot
#

there isn't but you can generally just send a few messages and then insert a few more rows matching that format

snow yacht
#

I was thinking more of the 10 minute blocks, but I'm sure I can figure out a way to do it manually, was just making sure I wasn't manually doing something that was automated somewhere :)

patent pivot
snow yacht
#

ah, gotcha

patent pivot
#
UPDATE messages SET created_at = created_at - INTERVAL '15 minutes' WHERE id = '<some message id>';
#

shifts the timestamps which will shift the block calculation

snow yacht
toxic wren
#

asking anyone here, is there a command/feature you wish you had in any of the bots or site(I know Github Issues exist).

snow yacht
#

Not really a bot feature per se but there should probably be some etiquette guidelines for asking for help with LLM output the asker hasn't even tried to understand

#

Maybe in the form of a bot command

#

!slop ?