#dev-contrib
1 messages · Page 3 of 1
hm? it's there, Union[..., None]
bot/exts/moderation/infraction/infractions.py line 431
is_temporary = kwargs.get("expires_at") is not None```
why is there a kwargs.get instead of it just being a keyword argument 
Just makes calling the function easier I guess
yeah I'll just leave it like that
It is admittedly a bit weird, but yeah, I'd leave it

=========================== short test summary info ============================
FAILED tests/bot/exts/moderation/infraction/test_infractions.py::VoiceMuteTests::test_voice_mute_user_left_guild
FAILED tests/bot/exts/moderation/infraction/test_infractions.py::CleanBanTests::test_cleanban_doesnt_purge_messages_if_clean_cog_available
FAILED tests/bot/exts/moderation/infraction/test_infractions.py::CleanBanTests::test_cleanban_falls_back_to_native_purge_without_clean_cog
FAILED tests/bot/exts/moderation/infraction/test_utils.py::TestPostInfraction::test_first_fail_second_success_user_post_infraction
FAILED tests/bot/exts/moderation/infraction/test_infractions.py::VoiceMuteTests::test_permanent_voice_mute
FAILED tests/bot/exts/moderation/infraction/test_utils.py::TestPostInfraction::test_normal_post_infraction
FAILED tests/bot/exts/moderation/infraction/test_infractions.py::VoiceMuteTests::test_temporary_voice_mute
7 failed, 457 passed, 1 skipped, 14 warnings in 56.14s
Yeah, you'll have to rewrite tests
oh right yeah
E Expected: mock(<MockContext spec_set='Context' id='140294470527200'>, <MockMember spec_set='Member' id='140294470525136'>, 'foobar', expires_at=None)
E Actual: mock(<MockContext spec_set='Context' id='140294470527200'>, <MockMember spec_set='Member' id='140294470525136'>, 'foobar', duration_or_expiry=None)
Or rather, update them
so this is an issue
@patch("bot.exts.moderation.infraction._utils.post_user", return_value="bar")
async def test_first_fail_second_success_user_post_infraction(self, post_user_mock):
"""Should post the user if they don't exist, POST infraction again, and return the response if successful."""
payload = {
"actor": self.ctx.author.id,
"hidden": False,
"reason": "Test reason",
"type": "mute",
"user": self.user.id,
"active": True,
"dm_sent": False
}
self.bot.api_client.post.side_effect = [ResponseCodeError(MagicMock(status=400), {"user": "foo"}), "foo"]
actual = await utils.post_infraction(self.ctx, self.user, "mute", "Test reason")
self.assertEqual(actual, "foo")
self.bot.api_client.post.assert_has_awaits([call("bot/infractions", json=payload)] * 2)
post_user_mock.assert_awaited_once_with(self.ctx, self.user)
I can't assert the expected static payload because the new time entry is dynamic
should I patch the datetime.now function? Or 
Hmm not sure what the correct approach is here
I patched it
I'm not overly familiar with the workings of the testing library
¯_(ツ)_/¯
But patching should suffice
It failed lol
yeah the patched ones didn't work 
what
TypeError: can't set attributes of built-in/extension type 'datetime.datetime'
Yeah, you can't patch that apparently
I wonder if there's a env var or something that gets set which files can use to know tests are running
Probably not the correct approach anyway though
I think I need to mock the whole datetime class
lemme see
The answer could be to remove the test but that's not ideal
like @patch("bot.exts.moderation.infraction._utils.datetime", wraps=datetime)
Don’t patch it
Instead separate the assert into an assert_awaited (without the with), and compare the call
One of the assert methods will check that the arguments provided match (rather than both dicts being the same)
Can’t find it, it might not be in unittest
But I’d still go with a similar approach, just remove that argument from the dict
!help ban
!ban <user> [duration=None] [reason=None]
You cannot run this command.
*Permanently ban a user for the given reason and stop watching them with Big Brother.
If duration is specified, it temporarily bans that user for the given duration.*
I'd also be inclined to update all the command param to duration_or_expiry too, making it more obvious you can supply an end date as opposed to relative (nb: also have to update docstring)
Up to you I guess @fossil veldt
that makes sense yeah
I'm just trying to find where it is
is it just the docstring?
Nope, it read the actual parameters
But the docstring (of the ban at least) references the duration name
So if we change the parameter, you also need to change the docstring if it references the parameter
A function's parameters are the bit on a "codeblock", and the description underneath in italics is the docstring
ah ok
If you're updating anyway, maybe also mention you can specify end iso
So "...bans that user for the given duration or until specified timestamp" or something
this is the current tempban docstring
"""
Temporarily ban a user for the given reason and duration.
A unit of time should be appended to the duration.
Units (∗case-sensitive):
\u2003`y` - years
\u2003`m` - months∗
\u2003`w` - weeks
\u2003`d` - days
\u2003`h` - hours
\u2003`M` - minutes∗
\u2003`s` - seconds
Alternatively, an ISO 8601 timestamp can be provided for the duration.
"""
!src ban
Permanently ban a user for the given reason and stop watching them with Big Brother.
also what is that ∗? it's not the ascii *? 
That's the one for !ban
!help tban
!tempban <user> <duration> [reason=None]
Can also use: tban
You cannot run this command.
*Temporarily ban a user for the given reason and duration.
A unit of time should be appended to the duration. Units (∗case-sensitive):
y - years
m - months∗
w - weeks
d - days
h - hours
M - minutes∗
s - seconds
Alternatively, an ISO 8601 timestamp can be provided for the duration.*
that one is fine I guess?
just change duration parameter?
and then ban would need the docstring update
Yeah, I think that's good
Since it does mention that a timestamp can be mentioned
Just need to update the parameter, yea
"""
Permanently ban a user for the given reason and stop watching them with Big Brother.
If a duration or ISO 8601 timestamp is specified, it temporarily bans that user for
the given duration.
"""
Not sure how I feel about "for the given duration" given a timestamp isn't a duration
It doesn't overly matter though, and I can't really think of anything better
And since we're editing this anyway, I'd put reason in backquotes to indicate that it's a parameter
I.e. py """ ...for the given `reason` and stop... """
I was thinking of that as well but
I could just copy the bottom part of the tempban, though...
Yeah, I think that works
I mean it's the permanent ban command anyways...?
why do we have 2 commands again 😂
"If a duration is specified, it temporarily bans the `user` for the given duration. Alternatively, an ISO 8601 timestamp..."
Oh yeah, backquotes around user too
One permanent and one temporary. But because the mods are lazy (myself included when I was a mod), we often use the permanent version when we want it temporary to save ourselves 4 (1 if use alias) characters
so
"""
Permanently ban a `user` for the given reason and stop watching them with Big Brother.
If a duration is specified, it temporarily bans the `user` for the given duration.
Alternatively, an ISO 8601 timestamp can be provided for `duration_or_expiry`.
"""
So the permanent version also allows passing a duration/expiry, and it all gets handled in apply_ban / apply_mute / etc.
Backquotes around user in the first sentence and then it looks good 👍
Wait, actually
"Alternatively, an ISO 8601 timestamp representing the expiry time can be provided..."
Just to be super explit
"""
Permanently ban a `user` for the given reason and stop watching them with Big Brother.
If a duration is specified, it temporarily bans the `user` for the given duration.
Alternatively, an ISO 8601 timestamp representing the expiry time can be provided
for `duration_or_expiry`.
"""
^
is it not backquoted? 
Sorry, reason
ohhh
Also have you got Alternatively on a new line?
I think same line works better
Oh nvm, it'll be too long
Where in Sir Lancebot's code is the part where others can react to bookmark messages and get it to done? I can't seem to find it
bot/exts/utilities/bookmark.py lines 143 to 153
while True:
try:
_, user = await self.bot.wait_for("reaction_add", timeout=TIMEOUT, check=event_check)
except asyncio.TimeoutError:
log.debug("Timed out waiting for a reaction")
break
log.trace(f"{user} has successfully bookmarked from a reaction, attempting to DM them.")
await self.action_bookmark(ctx.channel, user, target_message, title)
bookmarked_users.append(user.id)
await reaction_message.delete()```
ahh okay thanks
Can anyone help me with the implementation of https://github.com/python-discord/sir-lancebot/issues/932#issuecomment-1197856210 please
I wish dependabot was a bit quicker 😅
8 minutes+ to rebase
I wonder if we can self host so that we have our own job queue
I think it’s throttled because GitHub is large
Use one of the cups
is it possible to test bot with a site PR that's not merged yet?
specifically site#751
Yes check out and build the site image
Change the docker compose on bot to use the local image instead of the remote GHCR one
not sure if dependabot caches its package fetching, or allows package manager to cache their data behind the scenes. that's likely the cause as poetry will take roughly 2-3 minutes + to update a package
there's the added thing that they bump the pyproject.toml which means when checking they have to lock each and every update individually which means the cache likely isn't possible and that's the major slowdown
@static canyon PR at bot#2234 if you'd like to take a look 😅
anyone?
I suggest you post your question as a comment on the issue on GitHub.
If no one responds for a while then you can link it here
But right now it's not clear what you need help with
Can numba be added to the docs?
Added :)
thanks!
Yep! Thanks 😄
Busy today but will take a proper look when I can
!remind 26h
Your reminder will arrive on <t:1659180673:F>!
@gritty wind I think the issue is "inactive" will still show as if the infraction applied to a person was valid, it has just since expired.
Void just means to keep it in the database, but if you query a user's infractions, it won't show up.
The thing is I had considered that, but that’s not a thing I think matters. For mods, I’d still want it to be visible because it does no harm when it exists, and I think it can just be exploited. For users it doesn’t matter either way because they can only see a count. One infraction more or less makes no difference when they can also have 10 notes and it’ll all look the same
I also think void would be the wrong term in this case
Void is the correct term though. It means "mark invalid, but still keep"
Currently, if there's a mistaken infraction, mods will have to pardon it and then add a note or amend the reasoning, or ask Joe to delete it from the DB.
The first option will still bias the infraction count and if this happens to a reformed user, it could skew the perspective.
Historically we’ve turned down almost every single request to remove from DB btw
I do remember some instances where it was removed, but okay
And if we’re at a point where we’re reviewing by infraction count that’s a larger issue
Yes I do too, but then we stopped
It wasn’t deemed worthwhile
I just... I'm not sure why you're so against adding in a way to make sure that our infractions are correct and there's a process to mark incorrect ones as invalid, instead of adding in a reason that you then need to trawl through notes and reasoning for
I’m not against adding a way to explicitly mark invalids, I am against a way to make them not visible
That is a system which requires oversight
Something which historically we’ve never required
So you want them visible if you query infractions against a user, even though a mod maybe grabbed the wrong ID?
How do you programmatically separate when a mod grabs the wrong ID, and when it’s an explicitly exploitative action
But yes
I'm not sure how it would be an exploitative action to mark an infraction as not valid if it's a mod command. Would you then be concerned about the ban command and the reasoning adjustments also being exploited?
This is the entire principle of zero trust. Don’t provide a way for things to be exploited even if you trust your entire team. The way it can be exploited is by hiding actual infractions from the moderation team, say by a compromised account or malicious actor. Reasoning adjustments for something like a ban are less likely to be exploited in this way because if I see a positive ban reason I’m not likely to exactly believe that
When I see an infrac say please ignore, I check the audit log for it’s history
But if you can’t see the actual infraction at all, that’s when the issue arises
If we want, we could remove it from the count, but I don’t think that’s necessary. I still want it to be visible to mods
We could provide a separate command to view voided infractions for a user
keeping a record of them doesnt necessarily mean returning them on an infraction search
yeah what wookie said ^
I don’t think mods will use it though
Why look it up if you don’t suspect foul play already
At which point just check the infraction audit log
i dont think checking the providence of voided infractions should be a normal part of a mods job anyway
Tbh I'm really not worried about that. I can't see how it would practically be exploited
Like, if there's a user that repeatedly broke our rules we'd notice soon enough if their infractions went missing
Normal mod: !note Wookie Is a known troll
Compromised account: !hide Wookie is a known troll
This can be run in a mod spam channel
Yes
But wouldn't you have the same concern over the !ban command then if the account is compromised? Shouldn't we be concerned about all the other mod commands?
That seems like a very petty thing for a compromised account to do when they could also be banning hundreds of users
We can show that there are X voided infractions below the summary of infractions in the user embed, and not show it to the user in #bot-commands. That being said I still have the opinion that there are very very specific situations where we'll want to void infractions, and this isn't something we should normally do, so I'm a bit eh on building an entire system around it
From my time spent with the mod team, I know this isn’t true. There are very few truly prolific trolls, but a lot of the time most things are not going to be noticed, or have a long time in between. This means that a lot of time id find that I’m relying on previous infracs to make a decision
I don’t think “oh you could be doing worse” is a valid excuse for allowing something bad
Yes, @sharp charm was looking into zero trust for admin roles
Wrong Joe
lol
grabbing the wrong ID is pretty common (not that I would ever do that)
yes, but that was different than restricting base mod commands and the entire premise around it was different than categorically denying a feature
I didn’t deny a feature though
I just asked they still be shown
I don’t know what the issue with that is
If the infraction can still be reached somehow I'm ok with voiding in that instance
wait so what are you saying?
you're denying the void feature. You closed the issue.
Mark it as void, for instance make it an infraction field in the search, but do show it
I'm saying that if people feel strongly in favor of it, I'm ok with it under some limitations, but I think it's pretty low priority
I closed that issue believing it was something we had based on my understanding of the issue description, and said to discuss it on bot
Hardly saying no to the feature, especially with what I said in the discussion above
If the infraction can still be reached somehow
wdym?
@wild prism above + having a way to look up voided infractions for a user
But I'd like a warning explaining when to void infractions before confirming the action
I don't feel massively strongly about the issue but I disagree wholeheartedly with the idea of shutting it down because of "zero trust". The exploit has a very low chance of happening and in practice I think the impact would also be very low.
At least to me, it seemed like you want it always shown and to not adjust the count, which is no different than just amending the reasoning for the existing infraction to be "whoops"
we could even build in a requirement that the infraction is <1hr old or something
This is misconstruing what I said badly. I said we shouldn’t make it a way to hide infractions, we should still be able to see so we don’t need trust. And I think just having systems in place which aren’t safe to exploiting mean we should make all future systems like that
I’ve literally said we can change the count, and I’m indifferent on that aspect. But yeah I do want to show them, and yeah it’s no different than amending it. But it’s not exactly a big deal to read three extra words so yeah
Your issue with the count seems to entirely be based on moderators moderating entirely on a count
Which is a larger issue if we have it
its not just the infraction message or the count, it clutters the infraction search
No, I just think it's important to have a correct representation of infractions.
Some people have tooooons of infractions, one infraction because of a wrong ID is hardly clutter, especially if it’s easily visible that it wasn’t intentional
Me too, hence not wanting to make them essentially invisible
Zig’s solution is a middle ground, though I prefer the full solution
Full is not the right term, my proposed solution
Isn't that what zero trust is?
Isn’t what
Sorry I'm not sure where your solution is in everything sent here
This
I pinged you like this a couple weeks ago didn’t I
ye
Since an infraction search is usually coupled with !u I think showing that the user has voided infracs there in mod channels is ok. And have a field yeah
That is something I’m fine with, I just want it to be noticeable
yeah I agree
If a user has 10 voided infracs, that’ll cause further investigation so it resolves what I had issue with
Most users would probably have 0 based on the proposed use cases
(Accidentally using the wrong ID)
Are you saying to show the voided infractions in full or just the number of voided infractions?
That being said I don't look at it from a security perspective. As long as the infrac isn't deleted this isn't a critical exploit, and a very unlikely scenario even in the unlikely event a mod gets compromised. It would require the attacker to be familiar with our commands and setup, and risk getting caught when they can do so much more with the account. Rather, I want it because infractions are records of interactions between the mod team and server members, whether they were made erroneously or not, and should still be visible somehow, and because everyone makes mistakes sometimes.
number of infracs in user embed
My ideal solution is to show it in full, the idea being that voided infractions would be rare enough that they always require investigation. Having it shown by default makes it so mods have it right there instead of looking for another command
The middle ground would just be showing the count
I don’t think “they can do so much worse” is a valid reason to not try and proof newer commands, but I’ve already said that :P
If we were to show them in full I don't think it's worth implementing given you can mention it's invalid in the reason
Look at it this way, it’s easier to implement stricter security when some things are up to standard, than trying to make everything secure from being insecure
And I think as we grow as an org and get more mods, and get more likely compromises and malicious actors, it’s something we should consider if we can
i would like a void count visible to mods, and not visible to users when they run !user
undecided on whether we show the full details in infraction search or not
This is only an issue if we have hundreds of incorrect infractions
I don’t think that’s the case
Which goes back to this
I don't understand
Like as a mod you might go over hundreds of infractions
You might see every few thousand one which falls under the proposed voiding criteria
He's saying it's not worth the implementation effort if we show everything anyway
I really don’t think that’s an issue of my implementation
I think this whole thing was blown out of proportion
We’re acting like mods read hundreds of infractions which we’d mark as void
Yeah I didn't mean that as an argument against your implementation
(So far the only proposed use case is when we copy a wrong ID)
Just in general if we decided we wanted to show it in full that probably means it's not worth implementing
Maybe, I think people get pretty serious about the counts, though I’ve never considered it as the only factor when moderating
No one does, it does subconsciously bias you when it's the first thing you see though
i would still like it, for yes what Zig just said above
I’d agree if it was more than like 1 invalid infraction every 10000 users
Seeing a number go from 1 to 2 is not enough to seriously influence, and 10 to 11 is a drop in an ocean
Ah I see what you mean (counts in user embed), sorry I thought zig meant something else
i'd much rather see a void infraction count of 1 and ban & warning count of 0, than a ban count of 1, 100% of the time. i think this is a worthy issue to pursue and it has come up a couple times, but i agree with Zig it's usually overshadowed by more pressing things
so we still have this bot issue open for now, i think: bot#240
besides grabbing the wrong user ID, i think this also benefits the few cases where a moderator genuinely misreads a situation and issues a warning that we'd later like to retract. so i'm all for having a 'void' option
i would like to get moderation team feedback on this though, so will probably bring this issue to their attention in mod channels
I really don't want it to veer into appeals territory, this isn't what this should be for imo
yeah that's fair. i also think we might want to feed messages to mod-meta whenever an infraction is made void
looks at site page and notices extra incorrect punctuation.
who put that there!!
checks
is me
Never seen this one before. What exactly is it comparing against?
I believe it means the cache is out of date
Yeah. The bot parses all the inventories for symbols when the cog is loaded. When a symbol's documentation is requested, it actually enqueues doc parsing for all symbols on the same page as the requested symbol.
To know which symbols are on the same page, it uses the data it gathered about inventories when the cog loaded, which could have been some time ago.
But when it's processing the page, that symbol may not actually exist anymore.
!d r
Here's your reminder: @static canyon PR at bot#2234 if you'd like to take a look 😅
[Jump back to when you created the reminder](#dev-contrib message)
@vale ibex merged site#751
this PR is up for grabs: site#622
@rapid swallow
The story, all names, characters, and incidents portrayed in this issue and incidents implied are fictitious. No identification with actual persons, moderators (living or deceased), places, buildings, and products is intended or should be inferred.
@gritty wind as i understand it the reason for that bot issue is so that we can prevent accidental clearing of messages server-wide if a user ID is not given
When I start my Sir Lancebot with the code at the link below and I run the .s command (alias for .sudoku), it's saying that it can't find the Sudoku cog (see the screenshot below). Does anyone know why this is happening?
https://paste.pythondiscord.com/qaziqomeju
Where did you put the file?
...\GitHub\sir-lancebot\bot\exts\fun\sudoku
@vale ibex so um, after site#751 it seems the API still doesn't return the last_applied field on a GET, is there some other change we need to do? 
could this possibly need to be changed also?
https://github.com/python-discord/site/blob/main/pydis_site/apps/api/serializers.py#L175-L187
pydis_site/apps/api/serializers.py lines 175 to 187
model = Infraction
fields = (
'id',
'inserted_at',
'expires_at',
'active',
'user',
'actor',
'type',
'reason',
'hidden',
'dm_sent'
)```
It would need to be changed, but we should get everything ready first
is there a documentation for how to make authenticated GET/POST to apis like /bot/infractions/?
like just a raw get for testing, I'm not sure how to structure it and what token I should use 
We don't have a proper guide or anything, but it's all documented in the site repo
https://github.com/python-discord/site/blob/main/pydis_site/apps/api/viewsets/bot/infraction.py#L38
pydis_site/apps/api/viewsets/bot/infraction.py line 38
## Routes```
https://github.com/python-discord/site/blob/main/manage.py#L15
I might have misunderstood you, but, site defaults to this api key if not set otherwise
manage.py line 15
"DEFAULT_BOT_API_KEY": "badbot13m0n8f570f942013fc818f234916ca531",```
how should I use it when making a GET call?
As a Bearer token
Yeah that’s a query parameter, not the header
You probably won’t be able to easily set the header in browser
You can use an http client such as postman to set the headers
And it obviously allows you to do other things like change the method
I personally use insomnia, good app when it works
I usually just spin up a project with requests installed 😂
The fact it’s not httpx is the worst part
when it works
Hehe
I mean, it's just for manual testing 😅
Yeah
I like httpx for this stuff because it has a much better client interface
So you just set the headers and base once
Then all the other requests are clean
Requests makes it a pain
Yeah, makes sense
this didn't work somehow 
gonna go try just running httpx in python I guess
import requests
from requests.structures import CaseInsensitiveDict
url = "http://localhost:8000/api/bot/infractions/infractions-list"
headers = CaseInsensitiveDict()
headers["Accept"] = "application/json"
headers["Authorization"] = "Bearer badbot13m0n8f570f942013fc818f234916ca531"
resp = requests.get(url, headers=headers)
print(resp.status_code)
print(resp.json())
401
{'detail': 'Authentication credentials were not provided.'}
I'm so confused

that should be my key as well, I haven't changed the docker compose, it still has this line
environment:
BOT_API_KEY: badbot13m0n8f570f942013fc818f234916ca531
Oh lol it’s Token not bearer
oh yup works now 👍
Oh right lol, I even had to modify the code jam mgmt to use token instead of bearer so that I can use the botcore api client, silly me.
!rule 9 7
7. Keep discussions relevant to the channel topic. Each channel's description tells you the topic.
9. Do not offer or ask for paid work of any kind.
Bump (please ping when responding, thanks!)
requests has Sessions, which can store hearers and such
did you name the file suduku.py?
or just suduku, like in your message
Yes, it's named sudoku.py
cool, are you running in docker?
Yep
Have you restarted the container since saving the file?
Yep
Could you send a screenshot of the folder structure you have?
oh, you have it in a new folder?
Yeah cuz I have 2 files
you need to add an empty __init__.py in that folder
Ohhh
You will need to change a bit more than that actually, to have a multi-file folder like this
since it will try ot load all the files in there
look at the snakes folder for an example
the init has the setup function, and all other files start with _
the _ means they donn't get auto-loaded
You wouldn’t have an underscore before your cog
You mean the file with the cog class?
Yeah
Gotcha
you would if the setup func is in the init file
which is the current pattern used elsewhere
I'm getting this error now when I try to start my Docker container:
seems like a docker issue, haven't seen that one before
what does google say about the error?
when in doubt, turn it off and on
Well it was off already
Ok so I was able to get the bot started, but it's giving another error:
Not sure what a circular import is
did you remove the _ from the file with the cog class?
Oh yeah I forgot, let me try again
did you, or not?
if you have the setup function in your init file, then you should have the _
Oh gotcha, yeah I had the _ when I got that error, then I removed it and still had the error
add the _ back
and you will need to update your import to have the _ too
since the name of the file has changed
So I would have to put from bot.exts.fun._sudoku import Sudoku in the init file?
is that where the class is?
Yes
your folder is named _sudoku?
Oh no, the file _sudoku.py
Then you'll need to add the folder to the import path too
Oh, so from bot.exts.fun.sudoku._sudoku import Sudoku?
is that where your class is?
Yeah I think that's right
cool, try it and see
Yep, that worked, but now I'm getting errors related to my code which I can fix later, thanks for your help!
cool
hmmm
for more info
Ah, that's acutally paid
https://stackoverflow.com/a/37126790 should describe it well enough
.bm
You can just raise it and it’ll behave the same
!docs discord.ext.commands.BadArgument
exception discord.ext.commands.BadArgument(message=None, *args)```
Exception raised when a parsing or conversion failure is encountered on an argument to pass into a command.
This inherits from [`UserInputError`](https://discordpy.readthedocs.io/en/latest/ext/commands/api.html#discord.ext.commands.UserInputError "discord.ext.commands.UserInputError")
When trying to run python -m pre_commit run --all-files to format a PR for pythondiscord/site i get this error, i installed all the hooks with python -m pre_commit install, but i still get this error, anyway i can fix it?😅
Try to activate your poetry environment first
Also it’s going to be pre-commit not pre_commit
well since im in windows i think it has to be with an underscore😅
as in?
It’s the package name, which doesn’t care about the Os
How did you install
well a long time ago i tried using it like that and it didnt really work, so i used _ which one of my cj9 partners helped me with
the repo? with github desktop, if youre asking if i have a poetry env i do actually
alright
alright just did but now it cant find precommit
Could you post the error
Try running poetry install again to make sure your environment is in sync
It also couldn’t find flake8 in your previous screenshot
Can pre-commit be run with python -m?
Yes
I thought it was a.... Oh, no, it is just a Python package isn't it
yeah lol
Yeah
poetry install what exactly and how can i😅
im not very skilled with poetry lol
Just poetry install
ahh, its for installing dependencies
Yeah that’s the main purpose of it
that goes to the env file? or
What goes to the env file?
sorry, where do the dependencies get installed to your computer?
It creates a virtual environment in your app data folder
Packages get installed to that
The path to it is the one here
Yup yup, feel free to ask if you run into any other issues
I’d also suggest running pre-commit install again
yep i did actually
Nice
i did
poetry install
pre-commit install
pre-commit run --all-files
@fossil veldt hey i've tested your branch for bot#2240 but the command doesn't work for me. it works for you?
like it doesn't show the help message?
or the purging doesn't work
purging doesn't work
!clean does though
oh that wasn't ever supported
for message ID
purge only supported duration / timestamp
i only ever used user IDs with purge
woop i'm all over the place
ok we gucci, !purge works fine
That happened for me too. I think it was because cleaning across all channels only includes channels which everyone can view, so I had to set the permissions for everyone to view channels by default. Not sure if it's the same for you
yes when i was sending messages in a random test channel i made (which bot can view, but not everyone) it didn't work
does bot check perms for all these channels?
for purge it sends * channels
and it goes into this
if channels == "*":
channels = {
channel for channel in ctx.guild.channels + ctx.guild.threads
if isinstance(channel, (TextChannel, Thread))
# Assume that non-public channels are not needed to optimize for speed.
and channel.permissions_for(ctx.guild.default_role).view_channel
}
Yeah it was the view channel permissions thing at the end which made it not work for me
!purge
At least one user must be specified.
!purge [users]... [age=None]
*Clean messages of users from all public channels up to a certain message age (10 minutes by default).
Requires 1 or more users to be specified. For channel-based cleaning, use clean instead.
age can be a duration or an ISO 8601 timestamp.*
lovely, thank you @fossil veldt !

@timid sentinel I'm not entirely sure where a comment like that would go
Since in every other test we do the same thing (import the file, rather than the cog directly)
it is a gotcha though, so I wonder if there is a way we can lint against it
also nice one on digging up the root cause, I tried for a bit and then gave up since I cared more about the solution 😅
oh yeah um for the last_applied addition to site, do you know what else we need to do on the site side? Since I think the last_applied attribute is still not in the API response after the pr merge
did I forget that
pydis_site/apps/api/serializers.py lines 175 to 187
model = Infraction
fields = (
'id',
'inserted_at',
'expires_at',
'active',
'user',
'actor',
'type',
'reason',
'hidden',
'dm_sent'
)```
yea, that'll be it
do I just need to add last_applied to the end? 
pydis_site/apps/api/viewsets/bot/infraction.py lines 153 to 159
serializer_class = InfractionSerializer
queryset = Infraction.objects.all()
pagination_class = LimitOffsetPaginationExtended
filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter)
filter_fields = ('user__id', 'actor__id', 'active', 'hidden', 'type')
search_fields = ('$reason',)
frozen_fields = ('id', 'inserted_at', 'type', 'user', 'actor', 'hidden')```
but I guess that's just for filters? Unless I have to add it as a frozen_field as well?
we shouldn't need to alter any of those
frozen_fields are fields that can't be editted iirc
and we want to edit this field
Yeah true. I don't think it's worth putting a comment in every file and it would be silly to just put it in one. Let's leave it for now and we can always come back to it another time if we come across a solution.
I can't check right now but assuming the nose plugin was just enabled by default and is what caused it there might be a way of disabling it. Would need some testing and a bit out of scope for that PR anyway though
I linked the actual cause, it’s not nose
The line you linked is only activated for nose plugins as you've said
It doesn't activate for us
However, lower in the code it adds that fixture
Which is for our style of tests
Docs here btw https://docs.pytest.org/en/7.1.x/how-to/xunit_setup.html
That's the only one I see that checks for the name setup though
Other ones are setup_module or something else
I mean you have the traceback there 😛
I don't know where it's set, but hopping in with a debugger does show the right function
If you don't have a debugger, turn the setup sync and run pytest tests\bot\exts\backend\test_error_handler.py --pdb
I've not even run it 😅, I'm on my phone. The traceback you posted doesn't seem to contradict what I said though.
It does, it doesn't go into the nose branch
You almost had the right line, just a bit too high
setup_module in that call you show is defined a few lines earlier, I assumed from the nose branch rather than the others because of the name setup, just that line wouldn't be shown in the traceback because that bit doesn't error (the actual error happens a few lines later as you say)
It does also seem like the nose plugin is enabled by default https://github.com/pytest-dev/pytest/blob/main/src/_pytest/config/__init__.py#L234
Right, yeah
This should probably be raised as an issue upstream
It checks if it's callable
Should probably check if it's async too
Yeah
Oh I guess this would also fix it (eventually) https://github.com/pytest-dev/pytest/issues/9886
yup tested working fine now after that 1 line, at site#758
but also the deploy failed and I'm not sure why 
it's a known issue with netlify
there's a fix in progress site#742
it affects all our projects that use netlify
should I just rerun it later or
I dropped a message in the pytest server for now, will see what they say #810244286293213204 message
When'd we fix the github embeds
Do you mean the previews that @dusky shore gives? If so, then sir-lancebot#1077
Nice
What user agent would be correct to use when making a req from sir-lancebot?
Does the API ask for a user agent in a specific format to be sent?
Not really, but I'm scraping it so I thought it would be better to add it.
which issue is this for?
I can't see anything on their website that would say they allow webscraping, nor is there anything that says it is disallowed
Have you contacted them? Might be a good idea to ask them it they are ok with it, and if they want us to use a particular user agent.
I attempted to contact the via discord a while ago and got no reply. The forum also seems to be quiet regarding this topic. I'll try one more time.
They have a contact form on their website.
In the footer of the page there's a "Contact Us" link
I've contacted through discord and it's a gray area for him, but he is planning an API so I'll just close the issue and if it releases ask for it to be reopened.
Sounds good
I am going to be working on implementing File IO for snexbox and eval command. This would likely require mounting an empty to start, temporary directory/file system and such on each eval. I just wanted to ask, for mounting this directory and other things, I would do this in the EvalResource class, correct?
I think anything related to actually running code/interacting with the running process should be in nsjail.py (https://github.com/python-discord/snekbox/blob/main/snekbox/nsjail.py)
EvalResource is just the eval endpoint
https://github.com/python-discord/snekbox/pull/113 might give some inspiration as I think it should be a similar idea (?)
ah ok thank you
I want to add a listener to automatically give the bots read perms when a channel is opened. Where should I stick it?
Internal? not sure that fits
Hmm is it backend? It's just a qol thing
backend is where all the background stuff goes
Wait I remember we had a listener that added the bots to threads whenever one opened
Where did we put it?
Off the top of my head, there's going to be one in the mod logs, and probably something in the bump code
@timid sentinel in general I'm wondering whether a warning in tests in worth complicating our code for
I found the previous code a little confusing. Passing around coroutines feels like a bit of a hack in this case.
Using functions feels more intuitive given that's what they're meant for, and prevents the behaviour of getting confusing warnings if you don't use the action
hmmm it's just an object like any other, not sure why it's a hack. Also not sure what you mean by "that's what they're meant for". It's just that defining a function in the middle of the function, which is just a wrapper for one line with no immediate effect you could have written outside of it feels clumsy. Makes me immediately think "let's replace the function call with the line inside it". Maybe even a partial would be better. I'd also be interested to know why those actions aren't run, and why they can't be closed in that case.
I'm interested in finishing up bot#2017; may I be assigned to it?
Creating a specific "action" function to be passed to a more general function is a common code pattern throughout async and non async code, (given whether it's async is irrelevant). Just passing a coroutine reads to me like a lazy substitution for that pattern with weird and hidden side effects (only works with async code which makes it a bit esoteric, given the pattern has nothing to do with being async; raises a warning if you don't use the function; prevents you from using the function multiple times; and splits up the standard await func() you expect to see when simply executing a function).
Maybe even a partial would be better
I considered that, although a function felt more explicit, and reads more clearly to me. I don't really mind though.
I'd also be interested to know why those actions aren't run
The function that would have called them is mocked in the tests. it could have been patched with a function that just closes the action, but to me it felt like an issue with the code, rather than the tests.
Done 👍
Thanks 👍
Alright, fair enough. I'm ok with the current PR as long as this choice is properly documented in code like I mentioned in the PR
I just pushed a commit adding a note to the docstrings of the functions, is that alright?
Thanks
RE bot#2017
Just realised that since it's not a branch on the python-discord repo, I can't actually edit it. Should I just make a new PR and start over?
It should be editable, it’s an option you’d have to explicitly turn off when making PRs
Right, then how do I push to this PR? And get the current contents of it locally?
I kinda just assumed I wouldn't be able to push, but if you're saying I can I don't know how
This is what remotes are for
I do not know what those are lol
I know pycharm will allow you to automatically setup a new remote and check out the branch of a PR with a button click
Don’t know about other IDEs
Anyway the command is just
git remote add <name> url
I am using PyCharm fwiw
Look at the PR tab and check out from there
Apparently I already have a remote for that repo from a different PR 
So I apparently already have a remote but I'm not really sure what to do with that info
Most git commands take what’s called a refspec which you’re probably familiar with as just the name, but you can also specify a lot of stuff in it, such as the remote, and what the branch will be called locally
You can also just do it directly from pycharm
Either through the git tab, or the pull request tab
Yeah, idk how to change that
See if the plus allows you to switch to a different repo
Nvm found it
It was the settings button
Does this matter?
I managed to checkout the branch but got that
So I've just pushed the changes, and it didn't link correctly. It seems to have pushed changes to a new branch on bot, instead of linking to the already existing PR (the branch links to the PR, but the PR doesn't link to the branch)
The created branch being https://github.com/python-discord/bot/tree/fix-issue-2015
Not really sure how to make bot#2017 use that branch
Because it's a remote of onerandomusername/bot instead of python-discord/bot
wait what
but it shows as our branch?
https://github.com/python-discord/bot/tree/fix-issue-2015
Because I just messed it up
The original one should be here https://github.com/onerandomusername/bot/tree/fix-issue-2015
it doesn't have you commits
That's exactly what I'm saying
Can you actually edit the original branch?
@gritty wind said I didn't need to (from what I understood) and to use remotes and use the pycharm "pull requests" menu so I did but now this happened
.
.
Yes that’s what the error above was
.
It tried to set arl as your remote for that branch and failed
I know there's an option related to this https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/allowing-changes-to-a-pull-request-branch-created-from-a-fork
So it just made it a local branch
did the original fork owner not enable it?
Right, that makes sense
So... do I try again or what?
Scaleios said it's enabled by default, so it should be enabled but idk how to check 🤷
apparently the way to check is
Try this git push arl <branch>
try to edit one of their files on github web, and if you can't it will say do you want to make a fork
looks like it is editable though so
Didn't seem to really do anything @gritty wind
That’s done it
Seems to have worked as the commits now show up on bot#2017
You can now set the tracking branch locally so you’d just use git push instead of specifying arl
How do I delete the branch I created on python-discord? (This one)
There about 14 different ways lol
Ah nice lol
Do you wanna do it on GitHub, git, or your ide
Someone didn't follow python's Zen lol
IDE is probably easiest
In the git tab, expand the origin folder, find the branch, and delete
Make sure it’s under origin, not local branches
@timid sentinel in https://github.com/python-discord/bot/pull/2245/commits/4e59178d9cc4e23ed4c7b40a2c672ca61e6c9843 it was previously looking for the first message, but now it's looking for the last. Isn't it breaking something?
Also keep in mind that a message can be broken at any point, so you're not guaranteed to have this part in a single message (while the previous string was guaranteed since it'll always be within the first 2000 characters)
It shouldn't matter which message it gets, as long as it gets one for each nomination, but yeah you're right, looking for the first message makes more sense (I just looked for the longest fixed text, forgetting that the text itself could be split).
The alternative would be making sure that each part is in a single message if possible
I was considering trying to change it so all votes were one message and any information that didn't fit was posted into the thread, but it seemed a bit involved to ensure it would work nicely in all cases.
Could be revisited at some point but for now I think I'll stick with the original method I used
I think the case where it might break is if a helper put for Helper! in their nomination reason and it ended up as part of a second message
I could always add \n\n**nominated by** or whatever it is if we want to be more sure
In bot#2245 I have a tasks.loop, and two commands (one to enable and one to disable it). After disabling it i'm getting this error:
bot_1 | Traceback (most recent call last):
bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/core.py", line 200, in wrapped
bot_1 | ret = await coro(*args, **kwargs)
bot_1 | File "/bot/bot/exts/recruitment/talentpool/_cog.py", line 105, in autoreview_enable
bot_1 | self.autoreview_loop.start()
bot_1 | File "/usr/local/lib/python3.9/site-packages/discord/ext/tasks/__init__.py", line 392, in start
bot_1 | raise RuntimeError('Task is already launched and is not completed.')
bot_1 | RuntimeError: Task is already launched and is not completed.
Should I be using loop.cancel() instead of loop.stop() in the disable command, or do I need to do something else? I'm not sure I properly understand the difference in this case
Also which should be in the cog_unload
It might be simpler to just leave the cog running and check if it's enabled when it is triggered
Stop allows the current task to complete
Not sure about the error
Hmm wait it looks like it's erroring on start
in autoreview_disable don't do await self.talentpool_settings.set(AUTOREVIEW_ENABLED_KEY, False) until the loop is actually stopped
So I'm guessing the task didn't complete after the stop
Does cancel try to stop the inner task after it started? Or just the scheduler?
cancel will stop the running task
await self.reviewer.maybe_review_user() isn't a long-running task right?
it just grabs a nominee and posts the review right?
If so, we can porbbaly call task.stop() in async def autoreview_disable(self, ctx: Context) -> None: and wait for task.is_running() to be false before actually setting AUTOREVIEW_ENABLED_KEY to False
it just might mean that commadn may take a few seconds to run if a task is currently being ran
so we may want to but a 🔁 emoji on the invocation or something
Wouldn’t doing it in that order open up a race condition
What if we switch setting the keg and stopping the loop
There's a possibility for a couple different API calls (checking current messages, getting nominations from site, posting messages for review, creating thread) so it could take a couple seconds
wdym? set the key first and then stop the loop?
Yeah
That's what is causing the error above,
if the key is false, but the task is still running, another person can come in and set to to start again
so calling task.start() will error
as it's still running
Ah
I'd rather a autoreview start call not work because it's still shutting down, than try to start something that is still running
Wouldn’t it still fail if someone tried to start something else while it was stopping if you flip it
Right
That’s fair
How about a lock on the commands and only set the key once it's finished?
or do I not need the lock
Isn't the AUTOREVIEW_ENABLED_KEY in essance a lock already?
just don't set it to false until it's successfully stopped
that way a call to start will fail, as AUTOREVIEW_ENABLED_KEY is still true
You could still have two enable or two disable running at once, would that be an issue?
oh yea, having separate locks for both commands seems good
thought you were suggesting a shared lock
a discord.ext.commands.max_concurrency probably does the job
a global currency limit of 1 on each command, with wait set to false
I noticed that stop is not async which seemed strange so I looked into the dpy source code. I believe stop just sets a flag (_stop_next_iteration) and then returns. This flag is only checked each time after the task has finished executing, so if the 1hr loop last ran 10m ago, calling stop would make it run again in 50m like normal, and then stop.
discord/ext/tasks/__init__.py lines 238 to 248
try:
await self.coro(*args, **kwargs)
self._last_iteration_failed = False
except self._valid_exception:
self._last_iteration_failed = True
if not self.reconnect:
raise
await asyncio.sleep(backoff.delay())
else:
if self._stop_next_iteration:
return```
That leaves cancel, which i'm also not too sure about, as it cancels the scheduling task, but that could also be in the middle of running the reviewer code, and cancelling that arbitrarily could leave it in an inconsistent state (e.g. if the message has been posted but the user hasn't been marked as reviewed in the database yet).
So the two solutions i'm seeing are
this
or
run the reviewer code in an asyncio.shield so it can finish running if cancelled (and use loop.cancel)
yea this might just be best then
leave the task running and have it check the is enabled flag
simplifies the disable/enable logic too
I guess the only issue would be that starting the autoreviewer again won't cause the task to start right away
it will be whenever the next iteration is
We could solve that by calling task.restart I guess?
good point
or just manually call the post review funciton within start again
That seems to .cancel the current task internally 🥲
then I should probably put a lock on the review function lol
I'm guessing maybe_review_user already enforces limits on how often they're posted by the way it's written
so probably not terrible to call it more than needed
only by looking at messages in the channel, so if it's called twice it could pass the check for both before sending two new reviews
ah, is that the case if it's called twice a the same time?
IE it would be fine if say we called it now, and the task called it in 5 mins or somthing
yeah
Cool, yea a lock on that maybe_review_user func seems like it'll work then
and we just call it from within the review enable command
and just contextlib.supress the resource locked error
might need to write a task @error handler too
I went for a sort of mix of solutions in the end https://github.com/python-discord/bot/commit/7f86f1b4689dc0be1b21c4cb0a9946495d6dcf0b
Basically, the review task aquires a lock while running, and the disable command also needs to aquire that lock to cancel the task
looks good
Aren't new channels supposed to go to the bottom of the help category? #☕help-coffee was just opened and is at the top of the category #☕help-coffee message
Looks like it was a one-off glitch cause the others are in the correct order
Yeah it happens once in a while
Anyone else having trouble running sir-lancebot?
What kind of trouble?
I'm getting this on running the main branch
Traceback (most recent call last):
2022-08-08T16:08:57.711411470Z File "/usr/local/lib/python3.9/runpy.py", line 197, in _run_module_as_main
2022-08-08T16:08:57.712313179Z return _run_code(code, main_globals, None,
2022-08-08T16:08:57.712335470Z File "/usr/local/lib/python3.9/runpy.py", line 87, in _run_code
2022-08-08T16:08:57.712974345Z exec(code, run_globals)
2022-08-08T16:08:57.712987345Z File "/bot/bot/__main__.py", line 13, in <module>
2022-08-08T16:08:57.715552095Z bot.load_extension(ext)
2022-08-08T16:08:57.715914637Z File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 732, in load_extension
2022-08-08T16:08:57.717033137Z self._load_from_module_spec(spec, name)
2022-08-08T16:08:57.717047595Z File "/usr/local/lib/python3.9/site-packages/discord/ext/commands/bot.py", line 663, in _load_from_module_spec
2022-08-08T16:08:57.718709845Z raise errors.ExtensionFailed(key, e) from e
2022-08-08T16:08:57.718738512Z discord.ext.commands.errors.ExtensionFailed: Extension 'bot.exts.fun.fun' raised an error: ModuleNotFoundError: No module named 'pyjokes'
but I definitely should have pyjokes installed in poetry 
I running via docker-compose up
docker-compose up --build
rebuild the container, make sure you're not using cached poetry
package changes require rebuilds
In general or specifically for @dusky shore ?
can I still update cogs and do reload?
--build worked btw thanks 
Updating the packages won't affect the functionality of the program
I mean like just usually with docker if I update a source file and the bot can dynamically reload it, how does that work?
I thought they built into images?
After the image is built, you're editing the source file inside the built image
ah, but if dependencies change I'd have to rebuild the image?
Or you're editing locally, and all the other layers are cached, so it just takes a couple seconds to update just the layer that contains the source files
If you change a source file, Docker can tell that it's changed, so it will rebuild the layer that contains the source files.
But Docker isn't using your Poetry environment, it's creating it's own inside the image, so it doesn't have anything to compare against to invalidate the cached layer, so you have to trigger the rebuild manually
okay yeah makes sense 
btw apparently the notion lancebot env is missing a trashcan emoji so I added it
right now it's defaulting to the hardcoded one from here
yep, from bot too
also do we really need stuff like this?
can we just assume that all cogs will be present?
what do you mean by persistent 
I guess the only thing is that the command could be invoked possibly before the other cog loaded on restarts?
I don't know if that's even possible
if you unload a cog, and restart the bot, that unload is persisted, or so i recall
oh hm
Can't you !cogs unload <cog>? What happens then?
yeah that would cause it to not be present
maybe the bigger issue here is using cogs as static libraries 
I'm pretty sure these functions should just be in an imported module instead
its a PR, not merged yet, sir-lancebot#745
I agree
oop
How long do you think it'll take to rewrite the whole bot?
also these were marked as protected with _
but used externally
🥴
I really want these refactored, but I'm just reviewing aboo's PR for the uwu embed fix, not sure if this is relevant to throw in there
They were originally only used there, but the first PR to update UWU moved the logic to a different file, and didn't rename the method.
There are still a couple of PRs open for UWU, right? Let's just do reviews and get everything merged, and then we can make a "cleanup PR"?
Don't have the full context but try to keep PRs like that minimal in scope
Can you explain a bit more about what you mean?
Makes sense
You can't change something that doesn't exist
You'd have to select the line above, and start expanding the suggestion from there
but it's logically 1 suggestion, it just happens to be segmented by that modified comment line

PRs that edit a lot of files are slow to review and end up getting many merge conflicts from other merged PRs that make the authors miserable. Not sure if that's the case here
But check the 4th pin 🙂
It's just one file, we just had three different authors pick up three different features at the same time.
I was just trying to suggest we make sure all three get merged before we start trying to cleanup/refactor
Fair enough, I'm just triggered by "cleanup" 😄
Would you do something different?
I'm new to working with other people, so I'm open to suggestions
I don't mind some refactoring, just making sure that it doesn't encompass more than it needs to. Didn't have the full context like I said
I always see refractor work to be inherently tied to feature work.
Refactoring something just for the sake of it is wasted effort in itself
If multiple cogs are using a single function from one of the cogs, then that function should be in one of the utility modules, simply marking the function as public isn't enough imo
Zig hears "clean up" and immediately thinks back to our Spring Cleanup PR
But a pr to do just that one change is wasted review and testing effort as it doesn't "add" anything. Of course if we ever touch this area of the code again, it can be brought up in review then
That depends on the context, if it's bad then doing some refactoring can make the code clearer and more welcoming to future contributors. But yeah, ideally most of these changes should come as part of the review process of the PRs that caused the issues. For example if PR 1 gets merged, then PR 2 can merge main and do some of the refactoring
If you don't want to ask the PR 2 author to do it then you have my blessing to commit to their branch / fork in that case (assuming they gave write access to people who have it upstream)
👍
We're all staff, so no forks
sir-lancebot#1080 is on a fork though 👀
can I just set it as remote? 
Well, look who made a liar out of me
It's fine as is
"allow members of the upstream organization to edit" is enabled by default, and Zig's question was only a hypothetical anyways
well uh @wide elm what do you think, cuz it's your PR :p
If you want I can add a commit to your branch to refactor fun_cog._get_text_and_embed and fun_cog._convert_embed into module functions of somewhere like bot/utils/messages.py, and updating their local usages in the Fun cog.
Also I felt the issue your PR was addressing was more of an upstream one dealing with the _get_text_and_embed static function anyways, so the fix you proposed might be better suited in that static function anyways. Since this will likely come up again if that static function is ever used somewhere else.
oh what, I could've just made a branch
hmm, yeah, it might be better to stick those there as utilities
I'll address your comments on the PR too
yeah cuz I mean, first of all it's against convention to use those 'protected' methods like this. And also this dynamic cog library loading makes typing pretty wonky.
Right now, if the Fun cog is unloaded, the embed parsing feature of .uwu just fails silently and returns nothing
Surely that's not... an expected feature?
its not :p
I'll address your comments, commit that, and you can refactor your changes after that, if you'd like
You can work on the refactoring as well if you'd like. Essentially it's just moving the current calls to the 2 Fun cog functions to their own file, probably one of the bot/utils/
and then making _get_text_and_embed also grab reply context / embeds so Uwu doesn't have to worry about it
lemme know if anything comes up, I'll be here to review it again after changes as well :3
sure
er, I have to head out now, but I can get to this once I get back - is that alright?
no worries
@wide elm if it were to get approved, did you want to implement bot#2246 yourself? If not I'm happy to
If it gets approved by tomorrow, yes. I'll be out of town/AWOL for ten or so days after that
Ah no worries. There's no rush to get it done so I'll let you do it :)
It's a pretty small PR but if you do need any help feel free to @ me
And I'll happily review when you're done
Sure!
I'll go ahead and refactor methods like Fun._get_discord_message as well to utils
@fossil veldt I've finished the refactoring, mind taking a look when you can? https://github.com/python-discord/sir-lancebot/pull/1080
@fossil veldt right, I'm out (again :p) I can get your changes in in like half an hour
There's no rush Aboo, do it in the time you have thank you.
!d r
When I run the tests for bot#2017 locally, I'm getting 32 of this error that isn't even relevant to the PR:```
_________________________________________________________ ERROR at setup of ErrorHandlerTests.test_error_handler_already_handled _________________________________________________________
[gw1] win32 -- Python 3.9.5 c:\users\tizzy\appdata\local\pypoetry\cache\virtualenvs\bot-6mljcnek-py3.9\scripts\python.exe
bot = <module 'tests.bot.exts.backend.test_error_handler' from 'C:\Users\tizzy\bot\tests\bot\exts\backend\test_error_handler.py'>
def setup(bot: Bot) -> None:
"""Load the ErrorHandler cog."""
bot.add_cog(ErrorHandler(bot))
E AttributeError: module 'tests.bot.exts.backend.test_error_handler' has no attribute 'add_cog'
bot\exts\backend\error_handler.py:333: AttributeError
Hmm it’s defined on the mock bot explicitly
Update your branch first
It’s very far behind main
No clue how to
Every time I try to I get errors
Mainly that it's not a tracked branch
But when I go to make it tracked it decides that there's no root
And if I go to specify the root as onerandomusername/fix-issue-2015 it can't find that branch, even though it exists https://github.com/onerandomusername/bot/tree/fix-issue-2015
Isn’t the local “arl”
Yeah
Not one random username
So I specificy arl/fix-issue-2015 but it doesn't find it
What’s the command
Gotcha, not sure what it’ll look like for pycharm
Uhh what if you just copy the branch name in and hit update
Nothing happens
It remains untracked (whether I tick the "Set as tracked branch" or not)
Alright let’s approach this differently, what was the error when you tried to update the branch up to main
Why would that be an issue anyway, you can update local branches
What are you clicking
The wrong thing 
Oh
I did git merge main and that seemed to work
Made a load of changes
Tests seem to be fixed
Eh, maybe not
Yeah tbh it’s likely not going to work
This is fixed but I now have a load of different errors
That branch is more commits behind main than GitHub can show
FAILED tests/bot/exts/test_cogs.py::CommandNameTests::test_names_dont_shadow - ImportError: cannot import name 'interactions' from 'botcore.utils' (c:\users\tizzy\appdata\local\pypoetr...
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_add_channel_adds_channel - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_add_channel_skips_start_with_channels - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_add_channel_starts_loop - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_notifier_private_sends_alert - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_notifier_skips_alert - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_remove_channel_removes_channel - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED ```
tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_remove_channel_skips_stop_with_channels - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceNotifierTests::test_remove_channel_stops_loop - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceCogTests::test_kick_move_to_error - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceCogTests::test_sync_move_to_error - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceCogTests::test_voice_kick - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceCogTests::test_force_voice_sync - TypeError: __init__() missing 1 required positional argument: 'loop'
FAILED tests/bot/exts/moderation/test_silence.py::SilenceCogTests::test_force_voice_sync_no_channel - TypeError: __init__()```
I think you need to reinstall deps
poetry install?
That’s likely not going to work, I’m assuming the branch was still on dpy 1
I’d run poetry run pip uninstall discord.py then poetry install
Check the installed version to make sure it worked
I think the branch is on dpy2.0
Since pip freeze points to a zip with 2.0 stuff like interactions.py
Which zip version is it pointing to
I think discord.py-45d498c1b76deaf3b394d17ccf56112fa691d160 if that's what you mean
I don’t think that’s right, we’re on a newer version
The one on main is
0eb3d26343969a25ffc43ba72eca42538d2e7e7a
Right okay
Let's try this then
PS C:\Users\tizzy\bot> poetry run pip uninstall discord.py
Found existing installation: discord.py 2.0.0a0
Uninstalling discord.py-2.0.0a0:
Would remove:
c:\users\tizzy\appdata\local\pypoetry\cache\virtualenvs\bot-6mljcnek-py3.9\lib\site-packages\discord.py-2.0.0a0.dist-info\*
c:\users\tizzy\appdata\local\pypoetry\cache\virtualenvs\bot-6mljcnek-py3.9\lib\site-packages\discord\*
Proceed (Y/n)? y
Successfully uninstalled discord.py-2.0.0a0
So far so good
PS C:\Users\tizzy\bot> poetry install
Installing dependencies from lock file
AttributeError
module 'virtualenv.create.via_global_ref.builtin.cpython.mac_os' has no attribute 'CPython2macOsArmFramework'
at ~\AppData\Local\Programs\Python\Python39\lib\importlib\metadata.py:79 in load
75│ """
76│ match = self.pattern.match(self.value)
77│ module = import_module(match.group('module'))
78│ attrs = filter(None, (match.group('attr') or '').split('.'))
→ 79│ return functools.reduce(getattr, attrs, module)
80│
81│ @property
82│ def module(self):
83│ match = self.pattern.match(self.value)

According to google
This error occurs because two different and incompatible version of virtualenv are installed.
So yeah, guess I need to
Can't really remember how to though
I’m not sure about the conflicting version thing but there’s a poetry command to delete the env
then poetry env rm env_name
I wouldn’t suggest using it though
PS C:\Users\tizzy\bot> poetry env list
bot-6mLjCNeK-py3.9 (Activated)
```seems to only have the one
huh. I never noticed that
It always left the virtual env and packages, so it basically deleted it from the list of available envs and deleted some metadata files
So it just lives rent free on your disk
Could also poetry run pip -VVV to get the path
Works when I’m too lazy to remember commands
... C:\users\tizzy\appdata\local\pypoetry\cache\virtualenvs\bot-6mljcnek-py3.9\lib\site-packages\pip (python 3.9)
So delete\virtualenvs\bot-6ml...?
Yeah
If you want to do the command first then delete the folder that works
Make sure to deactivate first, I learned that the hard way one time
Apparently I do have two envs for bot 🤔
It happens sometimes when things change a lot and I guess it doesn’t register it as being the same env? Frankly I don’t understand how it works completely
How do you deactivate?
Just deactivate should do it
the env name is generated from the path of the directory
PS C:\Users\tizzy\bot> deactivate
PS C:\Users\tizzy\bot> poetry env list
bot-6mLjCNeK-py3.9 (Activated)
```seems to still be activated?
you activated it by doing poetry shell, right?
If it fails, it’s deactivated
It doesn't fail
PS C:\Users\tizzy\bot> deactivate
PS C:\Users\tizzy\bot> poetry env list
bot-6mLjCNeK-py3.9 (Activated)
PS C:\Users\tizzy\bot> deactivate
PS C:\Users\tizzy\bot> deactivate
PS C:\Users\tizzy\bot>
Did you activate with ^?
I would've activated it like a year ago so no clue lmao

Probably whatever the guide on site says to do
Is it activated from pycharm?
I guess
Oh that just uses the venv commands to activate
Well it’s fine, you don’t need to deactivate
Just delete the folder and close and open your terminal
Should I delete the other one too?
Okay, I've restarted the terminal
Now poetry install?
Or do I need to create a new venv
Yep, it's installing
PS C:\Users\tizzy\bot> poetry install
Creating virtualenv bot-6mLjCNeK-py3.9 in C:\Users\tizzy\AppData\Local\pypoetry\Cache\virtualenvs
Installing dependencies from lock file
...```
Awesome
just curious, why not use Docker? 
Package operations: 98 installs, 0 updates, 0 removals
• Installing pyparsing (3.0.9)
• Installing wrapt (1.14.1)
• Installing async-timeout (4.0.2)
• Installing deprecated (1.2.13)
• Installing frozenlist (1.3.0)
• Installing multidict (6.0.2)
• Installing packaging (21.3)
• Installing idna (3.3)
• Installing aiosignal (1.2.0)
• Installing atomicwrites (1.4.1)
• Installing certifi (2022.6.15)
• Installing colorama (0.4.4)
• Installing iniconfig (1.1.1)
• Installing attrs (21.4.0)
• Installing mccabe (0.6.1)
• Installing hiredis (2.0.0)
• Installing pluggy (1.0.0)
• Installing pycodestyle (2.8.0)
• Installing charset-normalizer (2.1.0)
• Installing lupa (1.13)
• Installing pycparser (2.21)
• Installing pyflakes (2.4.0)
• Installing py (1.11.0)
• Installing redis (4.3.1)
• Installing six (1.16.0)
• Installing sortedcontainers (2.4.0)
• Installing tomli (1.2.3)
• Installing urllib3 (1.26.10)
• Installing yarl (1.7.2)
• Installing aiohttp (3.8.1)
• Installing aioredis (1.3.1)
• Installing cffi (1.15.1)
• Installing filelock (3.7.1)
• Installing platformdirs (2.5.2)
• Installing pytest (7.1.1)
• Installing requests (2.28.1)
• Installing soupsieve (2.3.2.post1)
• Installing fakeredis (1.7.5)
• Installing distlib (0.3.5)
• Installing snowballstemmer (2.2.0)
• Installing pyreadline3 (3.4.1)
• Installing flake8 (4.0.1)
Terminate batch job (Y/N)? y
```this doesn't seem to be everything?
E.g. discordpy isn't there
Or bot-core
So it doesn't display everything it installed?
Because that's it
I think I shouldn't've terminated
it would but you cancelled the install
I use that for running the bot but that's it
does PyCharm not support running inside the container like VSCode does?
🤷
That fixed it, thanks @gritty wind 👍
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_mentions_exceeding_limit - AttributeError: 'str' object has no attribute 'bot'
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_mentions_within_limit - AttributeError: 'str' object has no attribute 'bot'
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_ignore_bot_mentions - AttributeError: 'str' object has no attribute 'bot'
```now I just need to resolve these
The code being resolved.author.bot (where resolved should be a discord.Message)
It does, but I personally like running on host anyway
Makes some thing easier
Did you run install again after terminating
Yeah, and everything is installed now
I can get into it somewhere else, don’t want to derail this convo 😅
Just need to figure out why this isn't working
I imagine I need a mock MessageReference object or something?
I’ve gotta run right now but if you’re still stuck we can go over it
PS C:\Users\tizzy\bot> poetry run task test tests/bot/rules/test_mentions.py
================================================================================================ test session starts ================================================================================================
platform win32 -- Python 3.9.5, pytest-7.1.1, pluggy-1.0.0
rootdir: C:\Users\tizzy\bot
plugins: cov-3.0.0, forked-1.4.0, xdist-2.5.0
gw0 [3] / gw1 [3] / gw2 [3] / gw3 [3] / gw4 [3] / gw5 [3]
... [100%]
================================================================================================ 3 passed in 10.84s =================================================================================================
PS C:\Users\tizzy\bot> poetry run task test
================================================================================================ test session starts ================================================================================================
platform win32 -- Python 3.9.5, pytest-7.1.1, pluggy-1.0.0
rootdir: C:\Users\tizzy\bot
plugins: cov-3.0.0, forked-1.4.0, xdist-2.5.0
gw0 [465] / gw1 [465] / gw2 [465] / gw3 [465] / gw4 [465] / gw5 [465]
.............................................................................................................................................................................................................. [ 44%]
.....................................................................................................................................s................................................................FF.F.... [ 88%]
..................................................... [100%]
...
============================================================================================== short test summary info ==============================================================================================
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_ignore_bot_mentions - AttributeError: 'str' object has no attribute 'bot'
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_mentions_exceeding_limit - AttributeError: 'str' object has no attribute 'bot'
FAILED tests/bot/rules/test_mentions.py::TestMentions::test_mentions_within_limit - AttributeError: 'str' object has no attribute 'bot'
I'm so confused. If I run tests then the 3 in /rules/test_mentions.py fail, but if I run the tests in that file directly they all pass
Just ran tests again without changing any code and now it works??? 🤷py PS C:\Users\tizzy\bot> poetry run task test ================================================================================================================================================================================ test session starts ================================================================================================================================================================================= platform win32 -- Python 3.9.5, pytest-7.1.1, pluggy-1.0.0 rootdir: C:\Users\tizzy\bot plugins: cov-3.0.0, forked-1.4.0, xdist-2.5.0 gw0 [465] / gw1 [465] / gw2 [465] / gw3 [465] / gw4 [465] / gw5 [465] ............................................................................................................................................................................................................................................................................................................................................................................... [ 78%] ...........s...................................................................................... [100%]
The code for the tests is here: https://paste.pythondiscord.com/nahemuyuto
So I've run these tests dozens of times and it seems that poetry run task test tests/bot/rules/test_mentions.py will always work, but poetry run task test will sometimes fail and sometimes not
Could you push your updated branch
Yeah, gimme a sec
Pushed to bot#2017
I guess we'll see what happens on the github tests
But from locally it sometimes passes and sometimes fails
Oh these are tests for your code gotcha
You’re still a little out of sync btw but that’s probably unrelated
I didn’t realize this was an issue with new code, and I’ll need a PC to properly look over it
I can’t get to that till tonight at the earliest
Yeah no worries
For context, the issue was that the tests passed the message author as the string 'bob' instead of a MockMember with the name set to 'bob'.
Prior to this the rule the code didn't use .author.xxx so it didn't matter, but now it does, so I've replaced it with MockMember(name='bob').
That then meant the return types didn't match, so I also updated the return types to be the MockMember as well
But now for some reason there's still strings somewhere causing the 'str' has no attribute 'bot' on resolved.author.bot
hey @gritty wind could you add an id to this step? :D
https://github.com/HassanAbouelela/actions/blob/main/setup-python/action.yaml#L61-L64
setup-python/action.yaml lines 61 to 64
- name: Setup python
uses: actions/setup-python@v2
with:
python-version: ${{ inputs.python_version }}```
ID?

