#dev-contrib

1 messages · Page 146 of 1

patent pivot
#

not sure what you are on about

fallen patrol
#

like

#

actually i can't find the exact article

patent pivot
#

this is completely irrelevant

#

it's for verification

#

metricity will not be verified

fallen patrol
#

argh they rewrote the page

patent pivot
#

the data metricity collects is essential to the operation of the community, opting out is leaving the community, the data is only viewable to admins now, and in future users if they want to through Discord (and already technically, if you send me an email I can collect all data PyDis has on you)

#

i'll ask in dapi #devs chat if there is concern about policy, but I was pretty scrupulous at the time to ensure we were compliant

fallen patrol
#

i can't find it because they rewrote the documentation page ;-;

#

but it intially said this was against the developer tos

thorny obsidian
#

The goal isn't to totally stop people from straight up running the code snippets, because that would be an impossible task. The goal is to put a barrier that results in them being penalized by time if they do try to get the code snippet and run it

fallen patrol
#

ah ok

gritty wind
#

Somehow the type of person that can do that doesn’t strike me as the type that will cheat in a fun game with no rewards

cold island
#

A webhook ID is the ID at the beginning of its URL right? before the hashed string

green oriole
#

yes

vocal prairie
#

yeah, the format is https://discord.com/api/webhooks/<id>/<token>

trail pilot
#

@thorny obsidian Question --
Is it fine if I remove the scoreboard at trivianight stop instead of adding it in trivianight start and removing previous ones?

the questions, which load depends on, needs the scoreboard, which by hte current logic shouldn't be existing before trivianight start

#

So essentially to prevent scoreboards from lingering resetting the scoreboard at trivianight stop would be fine I presume?

#

because right now .trivianight start doesn't do anything since the scoreboard is already added in the __init__ constructor of the cog

#

Another question, I'm wondering if the unicode trickery (zero width spaces) should be done on the end of the JSON before being loaded in, or should be done by the bot?

trail pilot
#

Question to anyone here I suppose:
I keep getting an error regarding No running event loop, which is odd, because it has worked other times but this time it's talking about how there isn't an event loop

fallen patrol
#

At what point of changes of a file that I borrowed from somewhere, am I able to remove or lessen the license from the third party?

#

or,,, how do I edit it to affirm that I've made a lot of changes to it

trail pilot
trail pilot
#

there are a few bugs and a few more things to add, but the first iteration is close to being finished 🎊

cold island
#

Looks really good! maybe the chosen answer can have a more distinct color?

trail pilot
cold island
#

Ah wait nvm

#

I realized it's the same buttons for all users

trail pilot
#

Yeah

#

I might add some stats in there for the correct answer embed

#

It’s a bit bana

#

banal

#

Like how many users got it right or wrong

cold island
#

Maybe an ephemeral message saying what you chose as an answer. Not sure what the limitations are on those

trail pilot
#

Interacts with the actual question

cold island
#

Yeah. Basically let you know that you picked what you intended

trail pilot
#

Ohh so when you’re actually clicking the answers?

#

When he question is ongoing

cold island
#

yes

trail pilot
#

Will do

cold island
#

Although

#

If many people click at once

#

I'm not sure if there are any rate limits on ephemeral messages

trail pilot
cold island
#

It's async like anything in d.py, but I'm wondering if Discord will throttle the amount of messages that can be sent

#

For example, the bot can't send an unlimited amount of messages

#

It's X messages per Y seconds

trail pilot
cold island
#

Yeah possibly

#

But we'll need to make sure of it

short snow
#

does incidents archive work for you guys? I need to add this extra line to make it work, it doesn't detect None as MISSINS

#

(Btw, how about displaying comments like we display code snippets)

cold island
#

It's working although I remember a recent PR to fix it. Maybe you need to merge main

short snow
#

👍

austere hornet
#

Hey I've been having some trouble with running my Madlibs program (sir-lancebot#901) in my test server the past week or so. If anyone is interested in helping, just let me know and I can DM you an invite to my test server. I'm thinking most likely there is something wrong with my code that's causing it to not run, but I literally am out of ideas at this point. This is my code: https://paste.pythondiscord.com/tofisojopu.py
(It's not currently committed in the PR, that's why I pasted it here)

dusky shoreBOT
short snow
#

could you push the latests changes to the pr, so i can pull and test it out

#

you can squash them later if you want

#

the json remains the same right?

#

nvm i would just copy that bin code then

austere hornet
#

But that's most likely not what's causing the problem

#

It's more the way I might have set up the test server

#

But I'm pretty sure I did everything in order as stated in the set up guide

short snow
#

ok yeah i got it, gimme a minute

#

you never call self._loaded_templates(), you just use as a variable

#

@static functions are functions but they just don't use the class variables, rest all is the same

#

also templates should go down in resources

#

and madlibs module should be made into a single file

austere hornet
short snow
#

its inside madlibs/madlibs.py should be made into just `madlibs.py

austere hornet
#

Ohhh I didn't commit it

#

That's why

short snow
#

await self.bot.wait_for(event='message', timeout=TIMEOUT)

Also here you need to catch for timeout error otherwise it would catch an error IIRC

#

rest good job 👍

austere hornet
austere hornet
short snow
#

yeah

austere hornet
#

Ok, I will add that

#

Thanks!

short snow
#

see any other cog using it, maybe connect4

#

yeah no worries 👍

austere hornet
#

@short snow (sorry for pinging you a bunch of times lol) question: I'm getting unresolved reference errors here, is that a problem or can I ignore it?

vocal prairie
#

Unless it errors when running, ignore it. If that's PyCharm, it might have to do with docker/poetry.

vocal wolf
#

@austere hornet you should probably install the poetry plugin for pycharm

austere hornet
vocal wolf
#

settings -> plugins -> extension marketplace -> search poetry -> install the plugin

#

after a restart that you'll probably need of the program, create a virtual environment using poetry and that should resolve the missing imports

vocal prairie
#

poetry install should do it oh wait, it's PyCharm, nvm

vocal wolf
#

When using pycharm there should be a section in the bottom right corner to select your interpreter.

austere hornet
#

That? ^

vocal wolf
#

You can click on that, add interpreter, select poetry environment

#

Make sure "Install packages from pyproject.toml" is checked

#

hitting ok after that should do it

austere hornet
#

What's the poetry executable?

vocal wolf
#

you should install poetry

austere hornet
rapid igloo
vocal wolf
#

hmmmmmmmmmmmmm

#

Are you on windows?

austere hornet
austere hornet
vocal wolf
#

Darn, I don't know how to locate the executable on Windows

#

maybe you don't need it

rapid igloo
#

iirc where in cmd or something

rapid igloo
austere hornet
rapid igloo
#

try where poetry

austere hornet
#

Thanks!

rapid igloo
#

nice!

austere hornet
#

Lmfao @vocal wolf

#

But then

#

I took the first screenshot right before the second

#

So in the end I still have errors

vocal wolf
rapid igloo
#

does everything else work? like the REPL or running a single file from pycharm

austere hornet
rapid igloo
#

yeah I mean the python console

#

(I dont use pycharm so idk the terminology)

austere hornet
rapid igloo
#

looks like pycharm is using the python interpreter from poetry's venv... which may not be activated unless poetry is run

austere hornet
rapid igloo
#

I could still run the python from poetry's venv when it's not activated. Can you try copying the path in the error from that image and run it manually from cmd to see if cmd shows the same error?

vocal prairie
austere hornet
rapid igloo
austere hornet
#

Haha

rapid igloo
austere hornet
rapid igloo
rapid igloo
austere hornet
#

Lol @rapid igloo it's not even gonna let me cd into it so nvm

rapid igloo
#

if you wanna cd to it, it's gotta be a directory. the /Scripts/ is a directory and python.exe is a (executable) file, so you gotta remove the python.exe from your command above.

austere hornet
#

Ok thanks

rapid igloo
#

I didn't actually mean cd to it (which is why I didnt tell you to remove the python.exe part) but cd can tell us whether the dir exists oo

#

so it's ok

rapid igloo
austere hornet
#

So I did this, what should I do next @rapid igloo ?

short snow
#

pycharm would auto-enable the venv inside the cmd if you have selected it in the right-hand corner (python interpreter)

short snow
#

earlier you did poetry run task lint right?

rapid igloo
austere hornet
short snow
#

so poetry run basically ran the command inside the poetry shell

short snow
#

so poetry run task lint would become task lint if you are inside the peotry shell

rapid igloo
short snow
# austere hornet

don't enable it from there, go to right hand corner python interpreter

#

and make a new poetry environment

#

select your poetry path as what is the output of where poetry

#

i dunno the windows command for where

rapid igloo
#

they did that earlier

short snow
#

ok so what are you trying to do now

austere hornet
austere hornet
#

Trying to resolve them

short snow
#

do poetry install in your commandline

austere hornet
short snow
#

when you selected an interpreter did you create a new one or choose an existing one?

austere hornet
short snow
#

ok, i am not sure what has happened, so i had just do the thing again, go to ../pupoetry/Cache and delete the sir lancebot venvs (all of them)

#

then go pycharm select the poetry venv tab, put your python3.9 path and the poetry executable path and wait for a venv to be created

#

pycharm should have installed the deps for you so it should work then

short snow
#

if it doesn't, go the commandline inside the cwd of the sirlancebot repo

short snow
austere hornet
short snow
#

should be working now

rapid igloo
short snow
#

yeah that ^

austere hornet
short snow
#

also removing the venvs won't cause any problem 🙃

#

i going afk, it is doesn't work, gimme a ping, i might come back

austere hornet
#

Ok @short snow looks like everything works now, but I'm a bit confused. The errors in the code are gone now but I'm still getting an error in the console

rapid igloo
#

looks like the same behaviour as we had earlier

short snow
#

did you choose your python path as system path or poetry venv python path

rapid igloo
#

what does the warning on the discord import say? unresolved import still?

short snow
austere hornet
#

It's just a warning

austere hornet
rapid igloo
#

does pycharm have an integrated terminal

short snow
#

yeah

#

also when do you get the warning, by doing what

austere hornet
short snow
austere hornet
#

Yup, the path in the error exists

austere hornet
short snow
#

alright, i dont't htink you can do it now, but in while making the venv from python it asks you select the python path

#

so what did u select for that

rapid igloo
austere hornet
#

I'm not sure tbh 😄

#

I might have put the output of where poetry without realizing it lol

short snow
#

ok, lemme see if it is possible now, a sec

#

try copy pasting the error on google and searching

#

try using the run option to run python -m bot, so we can check if the python interpreter is getting selected properly and packages are there

#

if the above works, then there is some problem in activating the venv in the console

austere hornet
short snow
#

remove your path, jsut keep the common error

austere hornet
#

So just this: CreateProcess error=2, The system cannot find the file specified?

rapid igloo
#

yeah, maybe include something like poetry virtualenvs, and pycharm

short snow
#

.idea/workspace.xml what does this contain

austere hornet
short snow
#

inside your repo cwd

#

it would be a folder

#

and the last possible thing i can think of rn is you can go to Settings | Build, Execution, Deployment | Console | Python Console and check for the python path

stable mountainBOT
#

Hey @austere hornet!

It looks like you tried to attach file type(s) that we do not allow (.xml). We currently allow the following file types: .gif, .jpg, .jpeg, .mov, .mp4, .mpg, .png, .mp3, .wav, .ogg, .webm, .webp, .flac, .m4a.

Feel free to ask in #community-meta if you think this is a mistake.

austere hornet
#

Dang it

#

One sec

#

I'll paste in a sec

short snow
#

everything looks correct 🤷‍♂️

#

uhhh

austere hornet
#

sigh

short snow
#

just ignore that error and continue working lol

#

also, scale uses pycharm onwindows

austere hornet
short snow
#

@gritty wind any idea?

austere hornet
rapid igloo
#

for now

short snow
#

i have a empty windows pc at school, i can try setting up pycharm and see if i get the same error

#

empty in the sense there is no pycharm/poetry setup

austere hornet
short snow
#

tizzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzy

austere hornet
rapid igloo
#

or use an editor without python support if you don't like the errors, lol

#

at least pycharm has autocomplete

austere hornet
#

It's called Sublime Text

rapid igloo
#

ooh does it have LSP integration like go to definition, find references etc?

rapid igloo
#

lol sublime text is great then!

#

I mean for editting

#

also wut, goto anything wonder what that does

austere hornet
austere hornet
#

Well now that we got that out of the way I'm still having trouble running the game in my test server. I commited the updated code with @short snow 's requests and it still isn't working...I remember seeing a message from you that said to try poetry run task start, right?

rapid igloo
#

I think jason said that

austere hornet
#

Let me try

rapid igloo
#

not a dream nope :)

austere hornet
#

This is what I get when I run that command:

#

When I try to run .madlibs in my test server

#

@vocal wolf What do you think is going on here?

fallen patrol
#

@austere hornet the tldr is this

#

eg, the folder needs to be a module

#

which is as simple as just adding that file, even if empty

short snow
#

didn't i tell you to make it a single non module file like fun/madlibs.py as we aren't using a sub _utils.py or anything similar

fallen patrol
#

the bot has a detection system for detecting all of the extensions, and any new folder needs __init__.py to be detectable

fallen patrol
#

🥲

#

👍

austere hornet
fallen patrol
#

it should work now

austere hornet
#

Nope

#

It's still not working

fallen patrol
#

tbf

#

why are you commiting before testing 😅

austere hornet
fallen patrol
#

Well yeah, but you're commiting before testing if it works locally

austere hornet
#

But still shouldn't it still work now?

fallen patrol
#

it should, got any logs?

austere hornet
fallen patrol
#

yeah, before that?

austere hornet
#

Do you still want to see it?

fallen patrol
#

ye

austere hornet
fallen patrol
#

!paste

stable mountainBOT
#

Pasting large amounts of code

If your code is too long to fit in a codeblock in discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the floppy disk icon in the top right, or by typing ctrl + S. After doing that, the URL should change. Copy the URL and post it here so others can see it.

vocal prairie
#

The madlibs cog isn't being loaded, hmmm

fallen patrol
#

hm

#

could you verify the file is in the right position?

vocal prairie
#

I'm looking at the repository, setup function seems fine as well

austere hornet
fallen patrol
#

trying saving this to a file and running it from the project root:

from bot.utils import extensions
from pprint import pprint as print


exts = [x for x in extensions.walk_extensions()]
print(exts)
print('madlibs' in exts)
fallen patrol
#

i mean, the file extension doesn't matter for the above snippet 😛

#

python thing will work if its named thing

austere hornet
#

@fallen patrol I guess it has to be a Python file?

fallen patrol
#

i mean, what did you name it as?

austere hornet
fallen patrol
#

python thing.txt

austere hornet
#

Well now I get this:

fallen patrol
#

ah, needs to be ran in the project venv 😅

austere hornet
fallen patrol
#

honestly, idk

austere hornet
vocal prairie
#

Does poetry run python thing.txt work?

#

From wherever you're running it

austere hornet
fallen patrol
#

hmm

#

it does show up

vocal prairie
#

So madlibs is there, weird

fallen patrol
#

in retrospect could've asked you to run .ext list lmfao

austere hornet
fallen patrol
#

nah as a bot command

austere hornet
vocal prairie
stable mountainBOT
#

bot/exts/fun/madlibs.py lines 97 to 100

Embed(
    title="Here's your story!",
    description=random_template["value"]
)```
vocal prairie
#

Maybe that's unrelated, but I don't see it doing anything

austere hornet
vocal prairie
austere hornet
#

Whooooops

fallen patrol
#

that's not the bug tho

#

the problem was the command wasn't be registered somehow

fallen patrol
vocal prairie
#

The setup function looks fine, which is making me confused

fallen patrol
#

have you tried running the .ext list command in your server? @austere hornet

fallen patrol
#

did madlib show up?

#

hmmmm

#

try looking for it on the help command

short snow
#

gimme 2 minutes, will have a look

austere hornet
fallen patrol
#

hmmm

#

.ext load madlib?

#

(^ bot command)

austere hornet
#

Something is weird with my bot ngl

#

It duplicates messages and I don't know why

#

It's driving me crazy

#

It was doing that when I ran the .ext list command

fallen patrol
#

....

#

you have two bots running

#

kill the other bot

austere hornet
fallen patrol
#

heck, kill them all

#

not sure where they are running and dont care either tbh, you can just eval an exit

#

.eval exit()

austere hornet
#

Can I assume it worked?

#

Nvm it did it again

#

But anyways why isn't this working?

#

I don't get it

vocal prairie
#

Why is every command running twice, do you know? That may or may not be part of the problem.

vocal prairie
#

If you don't know, the easiest thing to do would be to go regenerate the token and only start it once with the new token.

fallen patrol
austere hornet
austere hornet
#

@vocal prairie Can you remind me where I have to update the bot token after I regenerate it?

vocal prairie
#

In the .env, I believe

austere hornet
vocal prairie
#

Same, good night

austere hornet
#

💤

short snow
#

got it

#

@austere hornet

random_template = choice(self._load_templates)

should be self.templates

#

sorry had to cook breakfast, parents are out

#

self._load_templates is a static function which is calleld in init and stored in self.templates

#

also no matter what, all functions are called with () even if they are static

#

static functions just don't use the class variables

#

rest everything is same

#

line 56

short snow
austere hornet
austere hornet
#

How did I not catch that earlier?

short snow
#

isnt't it late for you? go sleep

austere hornet
#

Yeah ik I'm heading to bed now gn

short snow
#

lemon_sleepy gn

clever wraith
#

Hell yea

thorny obsidian
short snow
#

we wouldn't need Unicode trickery if we have an image as the question, which sounds better

thorny obsidian
#

unicode trickery is less intensive than an image

#

My original plan was an image, but Chris also suggested some unicode stuff

green oriole
short snow
#

nope

green oriole
#

Sadge

thorny obsidian
#

Plus images aren't friendly to those on low bandwidth internet, while text still renders

short snow
#

ah yeah, valid point

#

are there devices which don't support unicode characters pithink

thorny obsidian
#

probably some linux distros, but I don't think catering to non-fully set up unix distros is worth it

green oriole
#

right, bandwidth is a good point

short snow
#

🤷‍♂️ both hold the same weigth imo

green oriole
#

do they?

#

Also Unicode usually work on every distro, only emojis aren't working on some of them

thorny obsidian
#

Yeah, someone operating on a wacky unix distro that doesn't support unicode out of the box does not hold the same weight to me as someone in a region with not as stable internet.

short snow
#

Some unicodes present in ot channels didn't work on 16.04 ubuntu earlier and i had to install some font

thorny obsidian
#

in my mind that's the dangers of operating on those systems and it's on the person to get the relevant font packages.

green oriole
#

This is a scheduled event that will get an announcement and all, right kat?

thorny obsidian
#

mhm

#

although, I really think this is an edge case and I don't want to put out a warning for something so minor that the person should honestly have figured out when initially setting up the distro

green oriole
#

we can include some symbols in the announcement and tell people to fix their install if it doesn't render lol

#

But yeah, we already use a bunch of emojis in our channel names

#

It should be obvious something is off

short snow
#

or maybe have a list of unicodes which work on most os_es_

#

and only use them

green oriole
#

I don't know how you'd select those characters

#

Seems like a lot of trouble for nothing

short snow
#

nor do i know lol

thorny obsidian
#

So we're just gonna go with the unicode we can think of and renders on the systems for whoever is going to PR and review this feature. This is not worth the time.

short snow
#

sounds good 👍

green oriole
#

@thorny obsidian we could sneak in some Unicode chars in the announcement and if someone tells us in #community-meta why the heck they can't read some chars they can go fix their system lol

short snow
#

write teh whole announcement using unicodes

trail pilot
vale ibex
# trail pilot

There's an assumption here that answers will always have 4 options, and that we want the buttons to be a, b, c and d. Is this an acceptable assumption @thorny obsidian?

#

or would you prefer that the buttons themselves had the answers in them, and the number of buttons is determined by the number of defined answers

trail pilot
thorny obsidian
molten perch
#

Hey! Could someone take a look at api#23? I'd really appreciate it! 😄
(With the merge of this PR , the migration of API endpoints to FastAPI could officially begin, I think...(?) 😄 )

dusky shoreBOT
clever wraith
#

@vale ibex when you have time can you look at bot#1889?

dusky shoreBOT
clever wraith
#

I remembered the number hell yeah

#

Oh nvm I'm blind

#

while I'm here, could people look at bot#1889? Just needs one more approval

dusky shoreBOT
green oriole
#

OOOOOHHH

#

So that's why I had to change the HSV values

#

the blurple color did change

#

well now you have failing tests @static canyon :P

dim pelican
#

Could I get a core dev approval for sir-lancebot#859 ? It's been stale for a hot minute

dusky shoreBOT
marsh cloud
#

.

rapid igloo
stable mountainBOT
#

bot/resources/fun/trivia_quiz.json line 814

"answer": "assignment-expression operator"```
vocal prairie
#

The official name is assignment-expression, walrus is a nickname

#

During discussion of this PEP, the operator became informally known as "the walrus operator". The construct's formal name is "Assignment Expressions" (as per the PEP title), but they may also be referred to as "Named Expressions" (e.g. the CPython reference implementation uses that name internally).
https://www.python.org/dev/peps/pep-0572/

rapid igloo
#

alright that's fair the question says "official" explicitly

trail pilot
#

The python quizzes could really use more questions since people memorize them now

#

I think that's an issue that got accepted actually

rapid igloo
stable mountainBOT
#

bot/resources/fun/trivia_quiz.json line 834

"answer": "@"```
vocal wolf
#

Sorry I took a while to get back to you, I was doing stuff and things

dim pelican
#

Haha alrighty, I guess it can sit for a bit longer. And no worries at all

vocal wolf
#

anyway I've approved and it be squashing now

dim pelican
#

Oh snap

#

You da bomb

vocal wolf
#

I'm going to have to trust you on the regex part

dim pelican
#

Blue and I both tried to break it

vocal wolf
short snow
#

that's the semi-main thing lol, teh regex part

vocal wolf
#

ok it's merged

short snow
#

god that commit description, use refined github pls

vocal wolf
#

refined github?

rapid igloo
#

its a browser extension I think

short snow
vocal wolf
#

ty m8

#

.wtf

dusky shoreBOT
#
You blew it.

Your input was invalid: query is a required argument that is missing.

Usage:```
.wtf_python <query>

vocal wolf
#

@dim pelican noice

dim pelican
#

.wtf del

dusky shoreBOT
dim pelican
#

Well that ain't right

short snow
#

np, i got double co authored lol

#

it says 4 authors in the commit

thorny obsidian
#

what's wrong with that commit description though? It's lengthy, but I don't think that's a bad thing necessarily

short snow
#

Its just not needed when you have the pr linked

thorny obsidian
#

but what about when you're offline and can't necessarily access github?

short snow
#

its much easier to go through the pr rather than going through the commit description

#

which is imo not at all readable

#

well i can't help then

austere hornet
#

@vocal wolf If you have a moment. If you remember yesterday, I couldn't get my test bot to run my Madlibs game in my test server. Even after I fixed what @short snow pointed out (#dev-contrib message, it's still not working. However, when I run .ext load madlibs, it tells me I already have it loaded. But if I run .help, I don't see it there. I find this incredibly weird. Please tell me what I should do in this situation.

thorny obsidian
#

Well, that's the big blocking thing for me. I frequently go offline with projects and not having a descriptive commit message and instead relying on "go look at the PR" wouldn't be a solution

short snow
vocal wolf
#

@short snow I don't think there's anything wrong with the long commit message.

austere hornet
dusky shoreBOT
vocal wolf
#

how are you running the bot?

austere hornet
vocal wolf
#

what happens if you reload the help extension?

#

after loading/reloading madlibs

short snow
#

It's not about long commit messages, it's about the commit message which is formed when you squash down all the commits into one, all the commits are merged into and when you look at the description it's not really readable, everything is squished together. Rather than that will you understand more if you look at the PR? Yes, you have the commit messages separately and you have the code changes with them and you get more context, I know going offline is a valid point raised by kat but I can't help that.

austere hornet
#

I reloaded it and it's there now

thorny obsidian
#

well, .madlibs won't show anything due to an error in your PR currently

austere hornet
short snow
#

you gotta test before pushing 🙂

austere hornet
#

Again, this is my first time contributing, I'll get the hang of it at some point I'm sure 😄

short snow
#

👍 yeah, stay cool

rapid igloo
# short snow It's not about long commit messages, it's about the commit message which is form...

I think the squashed commit message is more readable since the PR has a lot of reviews which go in between the commits. By looking at the commit message you know exactly what the commit is, plus some additional details if any. Someone from the future may not want to look at the reviews or discussion behind each commit, perhaps just what got changed and why. Despite the message being long, I think it's much more concise than scrolling through the PR

short snow
#

there is a commits tab

rapid igloo
#

the commit tab is the same thing except it has user icons, more padding between each commit, plus a need to click an additional button to expand and see its full commit message

short snow
#

yeah, basically the commit description in a neater way giving more context

thorny obsidian
short snow
#

remove the ()

austere hornet
thorny obsidian
#
  1. self.templates is an attribute, not a function. So you want to remove the ()
#
  1. Look at what self.templates looks like.
#

Print it out and figure out what piece of data you're trying to extract. You need to drill down one more level.

austere hornet
thorny obsidian
austere hornet
thorny obsidian
#

you want to see what it looks like before that line, because that line is going to error out

clever wraith
#

can i get reviews on bot#1889

dusky shoreBOT
short snow
#

are you using an online editor?

austere hornet
rapid igloo
#

you don't need to commit your temporary changes

austere hornet
thorny obsidian
#

you only need to commit once the changes you made are finalized and you've verified they're working or are complete. In the meantime you can just save locally without committing

rapid igloo
austere hornet
austere hornet
short snow
#

Ah, you thought you need to push to make the changes registered in the bot?

#

git is just an online copy of your code nothing else, the bot runs just like all your other python scripts

vocal wolf
#

@austere hornet do you have the pre-commit hook installed?

vocal wolf
#

aka if you do git commit -m "some message", you'll get a bunch of checks that'll either pass or fail?

vocal wolf
austere hornet
#

poetry task run pre-commit, right?

short snow
#

yeah

austere hornet
#

What does that mean?

short snow
#

poetry run task

austere hornet
#

Oh oops

#

There we go

short snow
austere hornet
#

This is driving me crazy. I think I asked yesterday about this, but something's definitely not right. Does anyone know what might be causing this?

thorny obsidian
#

two instances running?

austere hornet
thorny obsidian
#

hmmm, what happens if you do docker container ls in terminal?

austere hornet
#

The ls part

thorny obsidian
#

it will run just fine

austere hornet
#

Oh ok I tried nvm

thorny obsidian
#

(ls will also run in windows)

austere hornet
#

That's what comes up when I run that

thorny obsidian
#

what happens if you do .ping in your test server?

rapid igloo
#

definitely two instances

thorny obsidian
#

okay, so definitely two instances running. At any point did you run this command? poetry run task start?

vocal prairie
#

Did you try regenning the token like I suggested yesterday? If you can't find a running process anywhere, that's the most surefire way to stop them all.

thorny obsidian
#

.int e exit() I think will kill them?

#

let me test

#

yup, .int e exit() should kill the bots

#

then you can restart just the one you're interested in

austere hornet
#

Yup it worked @thorny obsidian ty!

thorny obsidian
#

whoo

austere hornet
#

But I still can't get the program itself to run in my test server....sigh

rapid igloo
#

did you see the output of the print() you added?

austere hornet
rapid igloo
#

no, in your terminal because print prints to standard output

#

check the logs in your terminal

thorny obsidian
#

so, self.templates looks something approximating:

{'templates': [{'title':'sdasdf', ...}]}

which is a dictionary, right? The dictionary has one key, templates and the value is a list of the templates.

rapid igloo
#

yeah @austere hornet you'll see that printed in the terminal when you have the print line

austere hornet
rapid igloo
#

but it would raise an error because the content is too long, so nothing will show in the test server

rapid igloo
#

be sure to check your logs

#

it tells you everything

thorny obsidian
#

I have to head off to bed, but my recommendation is to break it down to the basics.
The line random_template = choice(self.templates) is trying to select a single random template.

You know what self.template looks like, a dictionary with a key of templates. How do you use random.choice() to pull a value from a key in a dictionary? Then apply that answer to your code and see how it could work together.

short snow
#

use print debugging 🙃 that's what i do with bots

austere hornet
rapid igloo
#

print() things which you think is sus and then check your terminal output to inspect it

short snow
#

basically add print("here: the list contains this") so you would know where all it went and where it doens't go

#

and yeah like hedy said

rapid igloo
#

you might then notice some variable doesn't contain what you think it has, which would then help you debug the problem :)

short snow
#

I haven' used the pycharm debugger with bot so not sure how we would go about with that

short snow
#

got it working?

austere hornet
# short snow got it working?

So I'm kinda confused on what I need to do. What exactly do I need to print? Like what exactly goes inside the parentheses?

rapid igloo
#

what variable do you want to inspect?

#

or, what do you think isn't working?

short snow
#

also send your code i will have a look

austere hornet
# rapid igloo or, what do you think isn't working?

Honestly I'm not even sure what's not working atp
I've tried pretty much everything I could and I still can't get the program to run
All I want right now is just to be able to run my program as is in my test server so I can see how it currently works

rapid igloo
#

do you know where you can find the logs or terminal output?

austere hornet
rapid igloo
#

where are you running the bot from? is it from your terminal or from docker dashboard or something else?

rapid igloo
#

by logs I mean something like this btw

austere hornet
rapid igloo
#

I'll look into it too

short snow
#
Traceback (most recent call last):
  File "/home/shivansh/.cache/pypoetry/virtualenvs/sir-lancebot-AEHeZmjC-py3.9/lib/python3.9/site-packages/discord/ext/commands/core.py", line 167, in wrapped
    ret = await coro(*args, **kwargs)
  File "/home/shivansh/Programming/pydis_projects/sir-lancebot/bot/exts/fun/madlibs.py", line 56, in madlibs
    await ctx.send(self.templates)
  File "/home/shivansh/.cache/pypoetry/virtualenvs/sir-lancebot-AEHeZmjC-py3.9/lib/python3.9/site-packages/discord/abc.py", line 1422, in send
    data = await state.http.send_message(
  File "/home/shivansh/.cache/pypoetry/virtualenvs/sir-lancebot-AEHeZmjC-py3.9/lib/python3.9/site-packages/discord/http.py", line 335, in request
    raise HTTPException(response, data)
discord.errors.HTTPException: 400 Bad Request (error code: 50035): Invalid Form Body
In content: Must be 4000 or fewer in length.
rapid igloo
#

yeah that's for await ctx.send which I've said above

short snow
#

just use poetry to run sirlancebot it doesn't necessarily need anything else

rapid igloo
#

yeah poetry run task start (iirc) or docker-compose up from the terminal, it's easier to find and view logs

rapid igloo
#

then pick one :)

austere hornet
#

Running docker-compose up now

rapid igloo
#

cool, after you send .madlibs in your test server you should see a lot of output in your terminal

rapid igloo
#

there we go! you got your error now

austere hornet
#

What does it mean by "overridden context"?

rapid igloo
#

it just means you are allowed to use that command because you have good permissions, but you don't have to worry about that. the problem is with the error traceback at the bottom

#

you can try using print instead of await ctx.send, that will show self.templates's content in your terminal directly

short snow
#

this will display all the stdout, so all the logs and print messages

austere hornet
#

Changed it to print() and that's what I got

rapid igloo
#

did you rerun docker-compose up?

austere hornet
rapid igloo
#

yeah

austere hornet
#

Ok one sec

rapid igloo
#

be sure to stop it first though, else you'd get two instances like before

austere hornet
#

I have learned my lesson

rapid igloo
#

great 😄

austere hornet
#

@rapid igloo Let's go! (sorry that's tiny)

rapid igloo
#

nice!

#

scroll up a bit and you'd see the start of self.templates then you should think about how you can change your choice() line to do what you want it to do

austere hornet
#

In the screenshot above?

rapid igloo
#

yup that's what self.templates contain

#

but you'd have to change the choice(self.templates) a bit to actually get a random choice from the list of templates

austere hornet
rapid igloo
#

remember that the templates in [templates] isn't a variable here, it'd need to be a string

austere hornet
rapid igloo
#

well have a try and see :)

austere hornet
rapid igloo
#

can you send your current code?

rapid igloo
#

weird, did you change anything else since your last commit?

austere hornet
rapid igloo
#

because it does this for me

austere hornet
#

For some reason it's printing the dictionary form instead of just the story

#

If that makes sense

rapid igloo
#

you can fix that later, but the bot isn't sending anything into the channel atm right?

rapid igloo
#

can you try doing git restore . and then update the choice() line again? you should only do this if you're ok with losing any other uncommitted changes

austere hornet
rapid igloo
#

in your terminal from the sir lancebot directory

hoary haven
#

i fairly frequently toggle my DMs on and off for this server. was it an intentional decision for !helpdm on to have to be re-run every time i turn my DMs back on?

rapid igloo
#

not sure, but it probably isn't intentional

austere hornet
rapid igloo
#

okay update your choice() line again because the changes are reset, then try running it

dusky shoreBOT
rapid igloo
# austere hornet

oh yeah and remove the await ctx.send line, I forgot that was in the commit sorry

austere hornet
#

@rapid igloo HOORAY!!

rapid igloo
#

nice!

austere hornet
#

Well let's end this on a good note I have to head to bed now

#

Thank you so so so much for your help!

rapid igloo
#

gn, looks like you forgot that you changed something else in your code earlier :)

green oriole
#

@vale ibex rapidfuzz 3.10: gx_check

#

I've updated the issue

hoary haven
dusky shoreBOT
green oriole
#

Oh, I assume we turn them off if we get a 403

hoary haven
#

is that specific to this feature, or in general?

green oriole
#

We get a 403 when the user has DMs disabled and the bot tries to DM them

#

It seems like if it happens in the helpdm cog we run !helpdm off for them

hoary haven
#

is it "expensive" in any way to not do that and let the setting stay as is?

green oriole
#

Hmm, it is one more API call that doesn't need to be done, but I think it should fine? You could raise an issue on the bot repo and we can discuss this idea

vale ibex
#

I think it makes sense to leave them there

#

one extra api call isn't bad really

#

Just need to delete line 602 and update the trace log to reflect the new behaviour

hoary haven
#

i don't recall ever getting that message on line 605 (i might've and just don't remember) but it will still be nice to get that message so i can be reminded to turn DMs back on

gritty wind
#

It is deleted after a few seconds, do you get ghost pings from bot-commands?

hoary haven
#

OOOOO that could very well be it

#

i didn't realize it goes there

#

i'm often on mobile when helping so don't check pings right away

#

if it's going to send the message in bot-commands might we consider just not deleting it? or making the time before deletion longer?

green oriole
#

really simple PR right there, would appreciate some reviews [python-discord/bot] Pull request opened: #1904 Modlog: explicitly write thread names

#

._.

#

bot#1904

dusky shoreBOT
brisk brook
green oriole
#

I do not know, I'd guess yes but it is supidely large, it is just to stop erroring apps

#

Like if you try to connect to the gateway more than three hundred of so times to the gateway in a minute it will reset your token

brisk brook
brisk brook
green oriole
#

Heh, I'm usually the one being worried about rate limits 😁 I think it is fine there

green oriole
fervent sage
#

nothing more

#

unless you repeatedly spam the gateway across multiple sessions

#

damn i was close

#

4008 is rate limited

brisk brook
#

But I am talking about the "enough 400 errors", not hitting the IDENTIFY limit

cold island
#

Will appreciate if bot#1895 can be merged this weekend, currently blocking another PR of mine

dusky shoreBOT
fervent sage
#

unless youre somehow bullying the gateway endpoint in such a way to get bad request responses

#

and i wasnt referring to the identify limit anyway thats a totally different thing

brisk brook
#

I was thinking about this

#

But that's higher than I remembered it being

molten perch
#

Hey! Could someone take a look at api#23? I'd appreciate it!
(With the merge of this PR , the migration of API endpoints to FastAPI could officially begin, I think...(?) 😄 )

dusky shoreBOT
stable mountainBOT
#
ROGER THAT

Your reminder will arrive on <t:1634938115:F>!

vale ibex
#

Can I get another review on bot#1906

dusky shoreBOT
vale ibex
#

@gritty wind @vocal wolf @cold island

#

currently blocking !infr search

#

Nice, ty

gritty wind
#

Y'all better stay around in case we need a revert too 😛

vale ibex
#

lol

gritty wind
#

Nah just kidding, already saw it on chris' bot

#

Would be great if the bot would redeploy already :P

#

Okay, deploying now

stable mountainBOT
#
It has arrived!

Here's your reminder: review migrations pr
[Jump back to when you created the reminder](#dev-contrib message)

austere hornet
#

Hope you had a nice vacation!

austere hornet
#

Hi, I have a question. So I (finally) got my Madlibs program to work in my test server, but whenever I run the command (ex. .madlibs 5 7), I get the following error. Here is my code: https://paste.pythondiscord.com/pijozocawa.py
I think the problem lies on line 58, but I can't seem to figure out what exactly is causing the problem.
Would appreciate any assistance. Thank you!

#

Never mind, I think the problem is that the range I entered is too short lol

#

Right now I have the range set to minimum 5 and maximum 15. Does anyone think I could change that?

cold island
#

But thanks for fixing it

vale ibex
#

Yea, notes and warns were fine, it was only if the search included an infraction with an expiry

#

I didn't find it during my testing of your PR either 😅

brisk brook
cold island
short snow
brisk trellis
#

Hello. I want a code modified in Python. Who should I talk to?

The problem is with:
lstrip() and rstrip() cause conflict when it comes to LTR and RTL.

@ RUST
trim_start(), trim_end()

" ياخشىمۇسىز بالىلار. "
" Merhaba arkadaşlar. "

cold island
short snow
cold island
#

Ok, I'll just resolve it

#

Or maybe you should post it there anyway for posterity

short snow
#

(message got deleted ^)

brisk trellis
cold island
#

Quick PR for anyone interested site#617

dusky shoreBOT
cold island
#

Hmmm @short snow your message link regex uses {15, 20}, but the regex used in discord.py is {15, 21}

#

Not sure what the API says

vale ibex
#

we're at 18 right now

#

gonna hit 19 next year

brisk brook
stable mountainBOT
#

@brisk brook :white_check_mark: Your eval job has completed with return code 0.

20
vale ibex
#

got a long time until 20 lol

brisk brook
#

It takes up to 20 digits to display a 64-bit integer

cold island
#

Hmmmm

#

!e
print((int('1' * 64, 2))

#

!e
print((int('1' * 64, 2)))

stable mountainBOT
#

@cold island :white_check_mark: Your eval job has completed with return code 0.

18446744073709551615
brisk brook
#

Ah, right that's signed actually

cold island
#

yeah that's what I was checking

brisk brook
#

So double it

#

!e ```python
print(len(str(int('1' * 64, 2) * 2)))

stable mountainBOT
#

@brisk brook :white_check_mark: Your eval job has completed with return code 0.

20
brisk brook
#

Still 20

cold island
#

So why is dpy using 21 🤔

vale ibex
#

!e ```py
import datetime

DISCORD_EPOCH = 1420070400000
id = 1000000000000000000
print(len(str(id)))
timestamp = ((id >> 22) + DISCORD_EPOCH) / 1000
print(datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc))

stable mountainBOT
#

@vale ibex :white_check_mark: Your eval job has completed with return code 0.

001 | 19
002 | 2022-07-22 11:22:59.101000+00:00
vale ibex
#

ok, we're gonna hit 19 next year

#

!e ```py
import datetime

DISCORD_EPOCH = 1420070400000
id = 10000000000000000000
len(str(id))
timestamp = ((id >> 22) + DISCORD_EPOCH) / 1000
print(datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc))

stable mountainBOT
#

@vale ibex :white_check_mark: Your eval job has completed with return code 0.

2090-07-20 17:49:51.015000+00:00
vale ibex
#

20 has us for a few years

cold island
#

lmao

brisk brook
vale ibex
#

!e ```py
import datetime

DISCORD_EPOCH = 1420070400000
id = 100000000000000000000
print(len(str(id)))
timestamp = ((id >> 22) + DISCORD_EPOCH) / 1000
print(datetime.datetime.fromtimestamp(timestamp, tz=datetime.timezone.utc))

stable mountainBOT
#

@vale ibex :white_check_mark: Your eval job has completed with return code 0.

001 | 21
002 | 2770-07-09 10:18:30.155998+00:00
vale ibex
#

Discord.py using 21 like it's going to survive world war 7

cold island
brisk brook
#

Because of the fact that it's stored in milliseconds

cold island
#

wdym

brisk brook
#

A normal timestamp can store 64 1s of seconds

#

But Discord stores it in milliseconds

#

Which equal out to less seconds

#

Actually no my brain is foggy I don't think I can explain this better

#

Tl;Dr less space and more precision

cold island
#

no yeah I get that

#

But Chris did / 1000

brisk brook
#

Yeah because of milliseconds

#

Oh... Ahh

#

I'll just leave that in the air with a thinking emoji

#

🤔

molten perch
#

Hi! Could someone take a look at api#23? I'd love start working on other issues of api, but that PR is blocking them right now! 😄

short snow
#

that has been a long wait

#

one more review please 🥺

fallen patrol
vale ibex
#

Yup

molten perch
#

Thank you! If you have any questions with setting it up, let me know! 🙂

fallen patrol
# vale ibex Yup

the only reason i recognise it is because i was trying to patch dpy use arrow for created_at times

#

and that method is the method to patch since every created_at method uses it

#

however, some of them use from utils import snowflake_time so you have to patch them in the methods

trail pilot
#

@thorny obsidian Should I implement error catching for .trivianight question # if the question number isn't in the bank or should I just keep it as a guarantee that the correct number will be entered

thorny obsidian
#

You don't need to error check the provided the json for the MVP. You can assume the info you need is there and complete

trail pilot
#

I assume I can take off the draft mark once the MVP is done

#

for the PR

thorny obsidian
#

mhm, I'll then review it~

trail pilot
thorny obsidian
#

yeah, you'll need pagination

trail pilot
#

Ah alright

thorny obsidian
#

well....

#

okay yes, you need pagination, but for the scoreboard

#

the list does not have to be an embed

trail pilot
trail pilot
thorny obsidian
trail pilot
#

Does that need to be in the MVP or should I add it later?

thorny obsidian
#

I would like at least a top 50 for the MVP

trail pilot
#

Alright, I can do that

#

the only problem is how would I test it out

vocal prairie
#

I doubt you'll get 50 of us, but I'm willing to join your test server and help

trail pilot
vocal prairie
#

ok

thorny obsidian
#

We can probs get a test event going and get some staff and regulars to join

trail pilot
#

@thorny obsidian Hm, I'm wondering if I should do a dropdown with the scoreboard pagination because I can't do buttons since it'll be an ephemeral

vale ibex
#

buttons and dropdowns are both views, why can you do one and not the other?

trail pilot
#

can you edit ephemerals?

vale ibex
#

Not sure, but wouldn't that be the same with dropdowns?

#

I'm not quite sure what you're proposing, could you explain it a bit more?

vocal prairie
trail pilot
trail pilot
vale ibex
#

Ah right, IG you could do the same for buttons anyway

#

but why not show all 50 in one embed?

vocal prairie
trail pilot
vocal prairie
#

Does it need to be a field?

vale ibex
#

Why do you need to use fields?

#

embeds can have 6000 characters

trail pilot
#

Hm true

#

I'll just put it in the description then

#

descriptions can only contain up to 1024 characters though, I think

#

nvm it's 4026

#

4096*

vale ibex
#

Yea

#

They got bumped a few months ago

trail pilot
#

4096 should allow a decent amount of users to be shown, around ~256

#

imo it might look better as just the top 100 or even less

#

and then a button that allows the user to get their individual rank (ephemeral)

vale ibex
#

Since its a case of changing a limit number, could you show us an example of both when you get a chance?

#

we may want to limit it to 50 anyway for size

trail pilot
vale ibex
#

Just populate it with a list of random names

trail pilot
#

alright

trail pilot
#

it's very long

#

I think it should be top 10, and then have a button where the user can get their rank

#

How about just having top 25 as inline fields in an embed?

#

And then the user can get their own rank separately

austere hornet
#

I like that idea a lot

vale ibex
# trail pilot

Can you put them on one line, and only separate every 10 users

#

No need for the one average in each row either

#

since it's in the title

#

and, you have 3 decimal places, but are the numbers actually that precise?

trail pilot
#

I wonder if we could just get the top 25 and place them in inline embeds though

vale ibex
#

Yea, 1 is fine

trail pilot
vale ibex
#

Could you see what mine looks like first?

#

if it's still too much, we can reduce it

trail pilot
#

@vale ibex

vale ibex
#

Not quite what I had in mind.

#
  1. namehere (1s)
  2. namehere (2s)
    ...
  3. namehere (4s)

  1. namehere(34s)
trail pilot
#

@vale ibex This looks pretty decent

vale ibex
#

looks good

#

I'd prefer the title to be in sentence case though

trail pilot
vale ibex
#

you have each word capitialised

#

That's title case, not sentence case

trail pilot
#

to and a are not capitalized

vale ibex
#

Yea, still title case

trail pilot
#

Ah

#

so
Average time taken to answer a question?

vale ibex
#

Yea

trail pilot
#

awesome

#

Should I limit it to 30 users?

#

for the scoreboard

#

cause it's a bit long

vale ibex
#

Sure, seems good

trail pilot
vale ibex
#

Yea, might as well

#

It won't ping since it's in the embed

trail pilot
#

I originally had them as Member instances, so I could just get the mention

trail pilot
#

sir-lancebot#910
I (think) I'm done with the MVP for it
@thorny obsidian If you wanna review it when you're free

I went with Chris' way of the scoreboard though let me know if you want me to change it

dusky shoreBOT
molten perch
#

I'd be keen on having some reviews on api#23 as well 😄

trail pilot
molten perch
#

No worries! 🙂

gritty wind
#

Hmm I can probably do that tomorrow

#

!remind 12H Are you free for a review :P

stable mountainBOT
#
You got it!

Your reminder will arrive on <t:1635070820:F>!

thorny obsidian
trail pilot
brisk brook
#

How come the bot docker-compose doesn't need ```yml
volumes:

  • ./postgres-data:/var/lib/postgresql
in the docker-compose?
patent pivot
#

the docker image defines a volume, so I think it's always persisted

#

it's just that with that we bind it to ./postgres-data (which project is this?), otherwise it'll just reside in the docker dameon data directories

brisk brook
#

which project is this?

I am writing my own docker-compose.yml and looking at the bot's one.

patent pivot
#

ahh

brisk brook
patent pivot
#

it's implicit

#

because uhhh

#

one sec

patent pivot
#

there is a VOLUME instruction which means docker will create a docker volume, not a bind mount

#

so it's defined at the image scope - rather than the docker-compose scope

brisk brook
#

Ah, awesome

patent pivot
#

in prod you should almost always put a volume elsewhere, be it a bind mount or with kubernetes some sort of pvc

#

but for dev implicit volumes are fine

brisk brook
#

So you guys use another docker-compose when deploying the bot?

patent pivot
#

we don't use docker-compose at all in production

#

all our docker-compose files are entirely development purposed

brisk brook
#

Ah right, awesome

stable mountainBOT
brisk brook
#

For sale?

vocal prairie
#

Reviews on demand 😎

#

Anyway, I'll see if I can test it sometime this morning

dusky shoreBOT
rapid igloo
#

okay 👍

gritty wind
#

I could sell my time

#

Anyways, I'll have a look over it now

#

Do we need dev-ops around for the merge

#

Well, we need it for the review at least

molten perch
#

If you're talking about the API PR, then yeah. I modified the Dockerfile. :/

gritty wind
#

That PR should probably also add an action, which will also need Devops sign off

#

That should be fairly simple though, it'll follow what most of our other repos do

#

I tried requesting the dev-ops team on the PR, but I didn't have the permissions

#

Joe and Volcy will do though 🤡

gritty wind
#

To build and publish the docker container, so we can actually use it in prod

#

It also means we can verify the integrity of migrations in CI

molten perch
#

Oh, I see.
There are no endpoints as of now. But in the future, of course 😄

gritty wind
#

Well, we don't need any endpoints now to add the action now lol

#

If you don't want to do it, that's okay we can PR it later, but I think it does fit under the scope of this PR

molten perch
#

What do you mean by verifying the integrity of the migrations?

gritty wind
#

If alembic upgrade throws an error right now, we wouldn't know since it's not running in CI

#

Though ig it wouldn't run anyways lol

molten perch
#

I mean.. isn't it Initial? 😂

#

It's sort of straightforward in that context.

#

Btw. the Initial migration is an autogenerated migration, so it should be fine, I guess. 😄

molten perch
gritty wind
#

I don't think that's a good idea. If we end up with multiple PRs adding endpoints at the same time (I imagine we will), you'll have all of them blocked on one PR that handles unrelated functionality

Less relevantly, it'd be out of scope for those PRs

molten perch
#

Alright, then. I'll add it.

gritty wind
#

If you follow one of the existing actions, it should be fairly straight forward

#

Perhaps bot or site would have a good base

molten perch
#

Okay, thanks! 😄

green oriole
#

We have an action right now running on the site that checks the migration history

gritty wind
#

Yeah site should be fairly copy-paste for this