#dev-contrib

1 messages · Page 92 of 1

cold island
#

Yeah I could do [*object] but... I think I'd rather keep the current version for readability

sharp timber
#

Please do lol

#

[*t] is esoteric python

short snow
#

Is sir-lancebot#561 on high priority? Or i can get it done later, kinda packed rn

green oriole
#

It is not

#

All is fine, all is good

#

Take your time

green oriole
short snow
#

Ok cool.

sharp timber
stable mountainBOT
#

@sharp timber :white_check_mark: Your eval job has completed with return code 0.

{'a': 1, 'b': 1, 'c': 2}
sharp timber
#

since 3.5ish

sleek steppe
#

What I'm confused about is why asyncio.create_task doesn't use asyncio.get_event_loop

green oriole
#

Unpacking in dict literals? It has always been a thing afaik

sharp timber
#

Yeah, but not two at once

tawdry vapor
green oriole
#

I believe it has always been possible

sharp timber
# green oriole I believe it has always been possible
Python 2.7.18 (default, Aug  4 2020, 03:44:25)
[GCC 4.2.1 Compatible Apple LLVM 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = {"a": 1}
>>> b = {"b": 2}
>>> c = {**a, **b}
  File "<stdin>", line 1
    c = {**a, **b}
          ^
SyntaxError: invalid syntax
>>> c = {**a}
  File "<stdin>", line 1
    c = {**a}
          ^
SyntaxError: invalid syntax
>>> c = dict(**a)
>>> c = dict(**a, **b)
  File "<stdin>", line 1
    c = dict(**a, **b)
                ^
SyntaxError: invalid syntax
green oriole
#

Interesting

#

Maybe only 3.x?

green oriole
#

Fair enough

green oriole
#

Hmm so they yeeted the unpacking in a comprehension part of the PEP, how sad

#

Maybe someone should restart the conversation pithink

short snow
sleek steppe
#

can bot#1471 get approved lemon_pensive

short snow
#

Soon™️

#

Look at my long list, not long but still..

green oriole
#

I mean, we are aware that those PRs needs reviewing

#

They would already been merged if we had time to

#

And as far as I can see, none of those are time sensitive

#

I can understand that you want to see your feature merged quickly, but we are doing it as fast as we can

short snow
#

Yeah ik and hence I put it after a 2 week gap, one questions, for trivia quiz, what type of constants go in the bot/constants.py, since earlier there was total chances for wiki which was not something like ids or keys

green oriole
#

Sounds like something that should go into the resources

short snow
#

No i mean like we have file constants and class constants and root level constants, how are they differentiated

green oriole
#

Uuhhh

#

I am honestly not sure

#

What do you want to add?

short snow
#

don’t wanna add, just generally

green oriole
#

Well, probably depends on what you wanna add

short snow
#

Uhh ok

cold island
#

@timid sentinel I left a couple of comments to your review

timid sentinel
#

Thanks, will have a look in a minute

cold island
#

no rush

timid sentinel
#

@cold island btw did you manage to confirm what the behaviour would be on the first start up in terms of currently nominated people ready for review?

cold island
#

Will check soon. It crossed my mind when I started working on this, and then for some reason I decided it was already handled.

#

In case it's not, the solution I had in mind is suppressing reviews when they're over a week overdue. Can't think of something more elegant

#

Actually one day overdue should work as well, no reason for the bot to be down for that long

sleek steppe
#

How's this? (old/new)

#

The author is also clickable

green oriole
#

What is last commit about?

sleek steppe
#

Uhh, the last commit to the repo?

green oriole
#

Is it like clickable?

sleek steppe
#

Nope

green oriole
#

Oh

#

The date

#

I am being silly

sleek steppe
#

Oh lol

green oriole
#

But I prefer the new version overall

sleek steppe
#

👍

#

Should I put created_at as strftime and last commit as timestamp?

#

How's this?

clever wraith
#

@sleek steppe what will it do if the repo doesn't exist?

sleek steppe
clever wraith
#

niiice

#

change page to repo maybe?

sleek steppe
#

👍

timid sentinel
#

niiice, will have a look now

sleek steppe
green oriole
#

Maybe we shouldn't repeat the page name, but sure

sleek steppe
#

Like The requested repo was not found. ?

cold island
#

repository sounds better imo

brazen charm
#

Repeating the input string doesn't look too useful

sleek steppe
#

Yeah I took that out

#

I changed the cooldown to 1, 10 per user (because it was 60 seconds for and I had to test it), should it be changed?

sleek steppe
#

sir-lancebot#632 is open.

cold island
#

@timid sentinel thanks! thoughts about whether the commands should use the nomination id or the user id?

timid sentinel
#

Hmm, either is fine

#

user id might make more sense from a practical point of view, but from a technical point of view you're posting/marking reviewed a specific nomination

#

I think it's fine as is though

#

but... if you think user id would be better feel free to change it

tough imp
#

could it maybe do both?

cold island
#

Hmmm

#

Honestly just user ID is probably fine. Every time I wanted to mark someone as reviewed during testing I had to look up the nomination ID

#

it's usually not the first bit of information you have available

thorny obsidian
#

user id please!

cold island
#

lol

#

coming right up

sleek steppe
#

bot#632 needs review

dusky shoreBOT
vocal prairie
#

That's closed.

short snow
#

sir-lance 632 ^

vocal prairie
#

Oh.

sleek steppe
#

oh wrong repo lol

#

sir-lancebot#632

fallen patrol
#

👀 didn't stop typing

vocal prairie
#

Discord is weird sometimes.

fallen patrol
#

https://pythondiscord.com does not have a robots.txt or a terms of service for scraping.
@patent pivot seems like a bit of an oversight given the privacy policies and such.

gritty wind
#

We have an issue open for it

#

Here:

#

Site#354

#

It’s currently awaiting dewikification

#

Bot decided not to link it

patent pivot
#

no privacy policy means an implicit yes to scraping through robots.txt

#

if there is no robots file then the RFC recommends you continue

#

So we can add one, but it's a nicety rather than a requirement

short snow
#

In the github pr by ToxicKid, should this 🍴 be used rather than for forks

brazen charm
#

⑂ seems more familiar as a "fork" to me in this context

short snow
#

but it is not that clear in the text imo

vale ibex
#

@whole forge The changes look good, could you fix whitespace error and I'll merge the commit into my branch

whole forge
#

!remind 3h do that

stable mountainBOT
#
Aye aye, cap'n!

Your reminder will arrive in 3 hours!

vale ibex
#

👍 If you're doing it locally, you can do pipenv sync --dev && pipenv run precommit to install dev deps and install the pre-commit hook

#

pipenv run pre-commit will run the hook manually if needed then too

short snow
#

@sharp timber Since reactions purge is gonna be similar to clean, can i just add it to that group?

#

and its doc-string is misleading

#

The deleted messages are saved and uploaded to the database via an API endpoint, and a URL is returned which can be
used to view the messages in the Discord dark theme style.

#

this never happens

vale ibex
#

What doesn't happen?

short snow
#

what is said in the docstring, doesn't happen

vale ibex
#

What part though? It it uploads the log via the site api and sends an embed to the mod log with a link to the messages

short snow
#

it does, lemme see, couldn't find it

vale ibex
#

look for calls to mod_log.upload_log() and mod_log.send_log_message()

short snow
#

yeah, found it

#

well wherever I add it, it is gonna take the same amount of code, so I will just make a new file

balmy sparrow
#

all deleted messages are stored?

#

didn't know that

vale ibex
#

Messages deleted via the clean command are stored, yes. This is because the clean command is generally used to remove messages that break our rules

#

Our privacy policy describes everything that we store on our members

whole forge
#

i can figure it out tho

vale ibex
#

I've noticed in lancebot we're doing this sort of check within commands quite often

if some_optional_param is None:
    await invoke_help_command(ctx)
    ctx.command.reset_cooldown(ctx)
    return

Would it not be better to mark the param as required, rather than optional, and let the error_handler deal with it?

#

Since our error handler excepts UserInputErrors and resets the cooldown itself

sleek steppe
#

It would be better

#

Besides the cooldown part

vale ibex
#

Yea, maybe we should make the error handler use your new help command

#

rather than a basic error embed

sleek steppe
#

Yeah that makes sense

stable mountainBOT
#

@whole forge

It has arrived!

Here's your reminder: do that.
[Jump back to when you created the reminder](#dev-contrib message)

whole forge
#

!remind 3h more time

stable mountainBOT
#
Sure thing!

Your reminder will arrive in 3 hours!

sleek steppe
#

I'm guessing it's a bad idea to commit suggestions

gritty wind
#

It should be fine if the suggestions themselves are fine?

sleek steppe
#

The trailing whitespace failed

gritty wind
#

Yeah the suggestion had a linting problem

#

It's fine to commit suggestions in general though

sleek steppe
#

Alright

fallen patrol
gritty wind
#

It implicitly means all scraping is allowed

#

that being said, you should probably also check out any available secondary resources such as the site's ToS or what not, just to be sure

gritty wind
#

(where is it pulling the forms description from 🤔)

patent pivot
#

meta tags

gritty wind
#

nice

patent pivot
#

what I am more confused about is how it is pulling a title out of this what the fuck lol

gritty wind
#

Smh you doubt my web design prowess

#

But yeah that's unexpected lmao

#

sadly didn't pull the description

patent pivot
#

lmfao

stable mountainBOT
#

@whole forge

It has arrived!

Here's your reminder: more time.
[Jump back to when you created the reminder](#dev-contrib message)

sleek steppe
vocal prairie
#

That's nice.

#

Much better and more readable.

sleek steppe
#

Should I specify timezone?

vocal prairie
#

Does that use Timestamp?

gritty wind
#

We don't really specify timezones anywhere

#

just UTC everywhere

patent pivot
#

if you use the discord native embed time stamp it adjusted

sleek steppe
#

Alright pushed

short snow
#

Ah ok.

sharp timber
short snow
#

Yeah, i kept it different.

whole forge
stable mountainBOT
#
Yeah okay.

Your reminder will arrive in 2 hours!

sleek steppe
#

Maybe bot#1471 should get a status: needs review label?

subtle kraken
#

we dont have any "needs review" label or anything remotely resembling that

#

any PR needs to be reviewed as matter of a fact

sleek steppe
#

Makes sense

stable mountainBOT
#
Bad argument

1769 is not a valid duration string.

whole forge
#

@vale ibex i've finally done the pre-commit checks

vale ibex
patent pivot
#

literally a one line change to codeowners 🙂

#

wow scale so fast

#

wow chris so fast

#

okay should auto-merge once ci passes

vale ibex
patent pivot
#

yeah look at that

#

auto-merge is so cool

timid sentinel
#

I look away for one second and when I look back it's merged haha

#

that was fast

gritty wind
#

don't look away

#

ez

vale ibex
#

tis easy when all you gotta do is make sure the username is spelt right 😛

gritty wind
#

you did that????

vale ibex
#

smh scale blindly accepting PRs

vocal wolf
gritty wind
#

gotta keep that graph active

vocal wolf
#

my graph fukin died over the last week

whole forge
vale ibex
whole forge
#

also, would it have been correct to make a PR for this, even though ultimately the changes are part of the same PR?

#

i thought that might over complicate things more than a manual merge, requiring reviews on changes for a branch that has open reviews on the same feature etc.

vale ibex
#

It's a PR into the branch my PR is based off

#

so it'll just be put into my PR as commits once merged

#

afaik anyway

whole forge
#

right but before it can be merged, it has to go through the whole approval deal too.

and as im writing this, it was merged....

vale ibex
#

hah, only PRs into main are protected

#

yea, that would have been a pain 😛

whole forge
#

i was boutta say, that would be a good reason for me to just never touch any bot code at all

pure knot
#

good

fallen patrol
#

Should 404 pages have a link to the home page?

#

Seems more useful than a discord server invite.

#

yes I know they can coexist, just having a link to the top level page would be more beneficial than the invite

vocal prairie
#

That's a good idea.

calm blade
#

anyone here work for apple lol

sleek steppe
#

Probably not

fierce willow
#

Wby doesn't the python bot have a translation cog? Because since people speak different languages it would help if there was a a translation cog

gritty wind
#

We don’t allow different languages on this server.

#

It’s not because English is the best language or anything

#

But because it would be quite difficult for us to moderate other languages if we can’t read it

#

Translation can only be so accurate, but we can lose meaning and context

fierce willow
#

Oh ok. I understand that

#

Thanks

vale ibex
#

@timid sentinel I agree with your comment, what do you think of this instead? ```diff
-[channels.add(channel.id) for channel in category.text_channels]
+channels.update(channel.id for channel in category.text_channels)

timid sentinel
vale ibex
#

👌

short snow
#

any smarter way to do this?

#

for reaction purge command

clever wraith
#

I don't think so

sleek steppe
#

Oh you can use the after kwarg

cold island
#

@short snow a heads up, the clean command is in the process of some changes, so it might affect PR's related to it

#

The implementation should also take into account that functionalities such as fetching the the messages in a certain range already exist

short snow
vocal prairie
#

I have a suggestion. Maybe add a note in the !code command about the pastebin, so that people know that that's another alternative for large code blocks.

#

It doesn't have to be large, just something that let's people know..

short snow
#

we have !paste for that

#

we could probably link it there

#

If your code is too long to fit in a codeblock in discord, you can see !paste

vocal prairie
#

I know that exists, but the people who use the commands often don't want to use both and cover the chat.

vocal prairie
vocal prairie
#

On the site, the name of the page is showing up at the top above the page description. I don't think that's supposed to be there.

#

It's showing up for a lot of pages.

short snow
#

that is supposed to happen

#

those are breadcrumbs

#

it is for all the pages

vocal prairie
#

Oh

#

I didn't realize that.

#

Also, can we update the images on the site for the help channel guide?

#

Some people may be confused about what the old names mean.

gritty wind
#

I tried doing that

#

but I literally have no idea what page you're talking about

#

can you link it lol

vocal prairie
#

That one has the old screenshots.

gritty wind
#

Alright, thank you

#

updated

sleek steppe
#

Dev log is awfully quiet today 👀

vocal prairie
#

Thanks Scaleios!

fervent sage
green oriole
#

I think Mondays are just quiet in general pithink

whole minnow
#

I was like looking at it and I dont really get how to do it

green oriole
#

It is quite simple actually, you can just send a POST request to /eval with a json body

whole minnow
#

tried that

#

the url in the

#

uhh

green oriole
#

In the body you need to give it the input key mapping to the code to execute

whole minnow
#

the config.yml file in the python bot they had a url

#

so I used that

green oriole
#

Ah, the URL will only work in our cluster

#

How are you running snekbox?

whole minnow
#

running?

#

uhhhh

#

I didnt really do anything to setup yet cuz idk what I needed to do

green oriole
#

Ah, we don't run any public snekbox instance

whole minnow
#

oh

#

so how would I run it

green oriole
#

We have a docker container

whole minnow
green oriole
#

Yep

whole minnow
#

do I run that command somewhere

green oriole
#

On your computer, yes

whole minnow
#

cmd prompt?

green oriole
#

Do you have docker installed?

whole minnow
#

I dont think soooo

#

if it doesnt come with anything then no, I never installed it by itself at least

green oriole
#

Alright, Docker is a pretty big piece of software, particularly if you are on the Home edition, but it will be quite useful during your programmer journey

whole minnow
#

alr

#

wait if Im gonna like host my bot elsewhere not locally would I have to do something different

green oriole
#

You'd usually dockerize your bot, put it inside a Docker container, to deploy it

#

But you will need to run snekbox on the same platform as your bot

whole minnow
#

I mean

#

I need docker on that too right?

#

How would I get docker there

green oriole
#

Yeah, you'd usually have your whole "stack" (the bot and snekbox, plus anything else you might need) in containers and deploy them on your server

whole minnow
whole minnow
#

it said uhh

#

this

#

the link was confusing

whole forge
#

did you select the wsl backend during the installer?

#

i wouldn't recommend that.

whole minnow
#

no

whole forge
#

while its neat, its very early in development and probably better to go with the default vm

whole minnow
#

the

#

wait

#

do I reinstall now

#

😔

#

welp time to uninstall docker

#

wait

#

but the docker command works tho

whole minnow
#

I just clicked cancel on that one

whole forge
#

if you want to try getting the wsl to work i recommend carefully following the isntructions it links to

whole minnow
#

is that necessary for snekbox

whole forge
#

if you dont want to deal with that, the other option is reinstalling with a different backend

#

either should work

#

tho

#

be aware that docker on windows is not great, and you should run a deployment version of snekbox on a linux based server

whole minnow
#

sad

#

welp

#

if it doesnt work locally then

#

is it possible to run it on repl

whole forge
#

hell no

#

docker is a really big piece of software meant to run on servers.

#

you could potentially run it on a rasberry pi

vocal prairie
#

You could run a Linux VM through Azure.

whole minnow
#

k soo

#

I do have a raspberry pi

whole forge
#

which version?

whole minnow
#

3b or something

whole forge
#

thats fine

#

as long as its not < 3

whole minnow
#

ah

#

Im gonna try running snekbox on pc rn as a test myb

#
docker: error during connect: This error may indicate that the docker daemon is not running.: Post http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/create: open //./pipe/docker_engine: The system cannot find the file specified.
See 'docker run --help'.
#

😔

green oriole
#

Snekbox won’t run on rpis

whole minnow
#

wut

green oriole
#

It is compiled for x86_64

#

Not for armh64

whole minnow
#

*confusion*

#

so I gotta run it on pc rn

green oriole
#

Yep

whole minnow
#

k

whole minnow
#

or keep it as it is

whole minnow
green oriole
#

I am not sure, I never ran docker on windows

whole minnow
#

😔

#

Ill try reinstalling it I guess

vocal prairie
#

Do a clean uninstall.

whole minnow
#

k

vocal prairie
#

Sometimes large programs do weird things if you don't.

whole forge
#

especially something as complex as docker for windows.

whole minnow
#

welp now time to install it again

whole minnow
whole forge
#

not sure, there should be a option somehwere ot use a VM instead of wsl

whole minnow
#

Nope

#

thats the only checkbox lmao

whole forge
#

then dont have it checked

#

i think you can select the engine later

whole minnow
#

theres another one thats like: add shortcut to desktop

#

but thats it

#

ok

whole minnow
#

before it worked when I checked the other thing

#

nvm it works

whole minnow
#

but yea apparently I need the WSL 2 thing

#

@whole forge which one should I get

#

Im not quite familiar with these sorry

green oriole
#

Are you familiar with linux?

whole minnow
#

not really

green oriole
#

Otherwise I’d recommend debian

whole minnow
#

ok

balmy sparrow
#

are you sure you want to be running your own instance of snekbox though?

#

there are public APIs available out there which will evaluate code for you

whole minnow
#

is there any other choice

#

there is?

balmy sparrow
#

google wandbox

whole minnow
#

yea that

balmy sparrow
#

i've also heard of piston

whole minnow
#

Ive heard of wandbox

#

I googled wandbox api

#

and a pypi package came up

#

but the readme on there was also not very clear

#

no documentation lemon_angrysad

sleek steppe
#

You don't need an api wrapper you can just make requests to the api

#

Especially because that probably uses requests which is not async

whole minnow
#

true

#

but

#

I googled the api

#

nothing came up but that

#

and the site itself

balmy sparrow
#

looking at the source code of that wrapper, it seems like they're making requests to 'https://wandbox.org/api'

whole minnow
#

and npm package

balmy sparrow
#

either ways, off-topic for this channel now

whole minnow
#

404 not found tho

#

oop ok then

sleek steppe
#

Also, what is coveralls?

green oriole
#

It is a website giving you your test coverage percent, among other things

terse hill
#

So... Trying to restore working snekbox after full software update, but getting 500 on every request to API, logs are:

2021-03-22 17:24:33,589 |     8 |     snekbox.api.resources.eval |    ERROR | An exception occurred while trying to process the request,
  File "/snekbox/snekbox/api/resources/eval.py", line 75, in on_post,
Traceback (most recent call last):,
    result = self.nsjail.python3(code),
  File "/snekbox/snekbox/nsjail.py", line 181, in python3,
    cgroup = self._create_dynamic_cgroups(),
  File "/snekbox/snekbox/nsjail.py", line 96, in _create_dynamic_cgroups,
    (mem / "memory.limit_in_bytes").write_text(mem_max, encoding="utf-8"),
  File "/usr/local/lib/python3.9/pathlib.py", line 1274, in write_text,
    with self.open(mode='w', encoding=encoding, errors=errors) as f:,
  File "/usr/local/lib/python3.9/pathlib.py", line 1241, in open,
    return io.open(self, mode, buffering, encoding, errors, newline,,
    return self._accessor.open(self, flags, mode),
  File "/usr/local/lib/python3.9/pathlib.py", line 1109, in _opener,
PermissionError: [Errno 13] Permission denied: '/sys/fs/cgroup/memory/snekbox-19ecdd18-49c4-4136-8ab2-5f26995421ef/memory.limit_in_bytes'```
#

It was working before updating, i tried some old images, but getting similar errors

green oriole
#

Interesting

#

How are you running it?

terse hill
#

in docker, via docker-compose

  snekbox:
    container_name: snekbox
    ipc: none
    privileged: true
    restart: always
    ports:
     - 8060:8060
    image: ghcr.io/python-discord/snekbox
    deploy:
      resources:
        limits:
          cpus: 0.25
          memory: 256M
    volumes:
      - /home/fixator10/snekbox.cfg:/snekbox/config/snekbox.cfg```
#

same happens without resource limiting and volume mounting

#

with docker command from readme the same happens

green oriole
#

Hmmmm I am a bit clueless here

#

After a system upgrade you said?

terse hill
#

yes

green oriole
#

Tried restarting?

terse hill
#

twice already

green oriole
#

That’s normal I believe

gritty wind
green oriole
#

can you run ls -la /sys/fs/ on the host?

#

It looks like a perm issue on the host

terse hill
#
drwxr-xr-x  7 root root 0 мар 22 19:56 .
dr-xr-xr-x 13 root root 0 мар 22 19:56 ..
drwx-----T  2 root root 0 мар 22 19:56 bpf
dr-xr-xr-x 12 root root 0 мар 22 19:59 cgroup
drwxr-xr-x  4 root root 0 мар 22 21:38 ext4
drwxr-xr-x  3 root root 0 мар 22 19:56 fuse
drwxr-x---  2 root root 0 мар 22 19:56 pstore```
terse hill
green oriole
#

Alright, root cannot write to /sys/fs/cgroups

#

I wonder if that’s normal

terse hill
#

looking at another host with Ubuntu (the issue on Arch), seems like its not really normal
drwxr-xr-x 17 root root 420 Dec 25 13:07 cgroup

#

after setting w+, still same error

#

drwxr-xr-x 12 root root 0 мар 22 19:59 cgroup

green oriole
#

No idea sorry

#

Maybe @tawdry vapor would know

terse hill
#

maybe i should try setting w+ recursively for cgroup, but not sure if thats a good idea

green oriole
#

As long as it is owned by root, you should be fine

#

Assuming that you are giving write only to owner

tawdry vapor
#

It's definitely an issue with the host. I don't know why it's this way. Consider searching or asking in the arch forums.

terse hill
#

I guess, i will, ye. Just noticed that on ubuntu host there is memory in cgroup, but not on arch

tawdry vapor
#

I use this on arch too and I've had no problems. I haven't tried recently though.

stable mountainBOT
#

You are not allowed to use that command here. Please use the #bot-commands channel instead.

green oriole
#

It works fine on my manjaro install as of a couple of weeks ago

clever wraith
#

What was the problem?

pallid phoenix
#

yeah

vocal prairie
#

Why was !code changed?

#

It doesn't show syntax highlighting anymore.

#

!code

stable mountainBOT
#

Here's how to format Python code on Discord:

```py
print('Hello world!')
```

These are backticks, not quotes. Check this out if you can't find the backtick key.

vocal prairie
#

Wait, not that one.

#

I mean the embed theat pops up when you paste code without syntax highlighting.

tawdry vapor
#

It hasn't changed for like half a year

#

Not sure what you are referring to

vocal prairie
#

Oh, it seems to have been a one time thing.

#

I don't know why that happened then.

tawdry vapor
#

Do you have a link to the embed?

#

@vocal prairie

vocal prairie
#

Nope, the person used the trash can thing.

#

Sorry.

tawdry vapor
#

It won't show a Python code block if it can't detect with reasonable certainty that the code is Python code.

vocal prairie
#

Oh

#

That makes sense.

#

That must've been what happened.

#

Thanks for letting me know!

tawdry vapor
#

No problem

terse hill
#

So, apparently, im on testing repo of arch, and its switched cgroups to v2 by default

short snow
#

what is stream yard?

short snow
#

new sponsor, hmm

hardy gorge
#

It's basically a livestream utility, fully in browser, that allows you to have several people connect to your stream

#

It makes it much easier to have multiple live on stream and it also allows you to stream to multiple destinations, like both YouTube and Twitch. We're probably not going to use that just yet, but maybe we'll find another interesting destination besides YouTube in the future.

whole minnow
#

For python-bot's docs command I was just looking through it: what exactly is self.inventory

#

like I would expect that it makes a request with the "symbol" as a param but instead it searches the inv dict for it not exactly sure what it does

vale ibex
#

it's an internal cache of symbols

#

it also provides the means of getting the data from the various docs, if the symbol isn't already in the cache

brazen charm
#

The inventories dict maps the symbols that can be searched by users here to the urls where their docs are located

clever wraith
#

Hey @patent pivot , I noticed you were using kubernetes to host a lot of the server services. What platform are you using, and how much does it cost? I'm looking for a cheap place to host some stuff

patent pivot
clever wraith
#

okay, thanks! 2k is about 1750 bucks too much

patent pivot
#

😄

fallen patrol
ember cloud
#

There should be something like !pypi package1, package2, package3 instead of !pypi package1 !pypi package2 !pypi package3 because I feel like the first one is much easier, and looks much cleaner if it were all combined in an embed, let's say as a field not inline or something like that.

#

for the pypi command

#

just a suggestion 👀

short snow
#

cc: @vocal wolf this

vocal wolf
#

detecting spam wouldn't do too well

short snow
#

we can limit to <5

vocal wolf
#

it would make it easier to spam pypi with requests

#

even if it doesn't trigger our spam filter

#

so it's a maybe, but I'm not too sure as of now

#

pretty good idea, but we'd have to find a way for it to not get abused

short snow
#

cooldown and limiting to number of packages can prevent that

vocal wolf
#

I guess so, yeah

short snow
#

should i add the riddle command with the quiz command?

#

since there is a issue open about it

#

and i don't see a need to copy paste quiz's code into riddle

short snow
#

the spelling of github should be GitHub right? in a doc string.

vocal prairie
#

Yeah, I think so.

#

Yup!

whole minnow
#

I was thinking that

#

normally for these kinda search things

#

it would just directly make a request and then parse the html

#

so that kinda got me confused when i was looking through it

gritty wind
#

I believe it still does

#

the cache is just the symbol to url

whole minnow
#

thinkChill huh

gritty wind
sleek steppe
#

The docs command is gonna be faster when that super big and old PR gets merged right?

whole minnow
#

was it ever slow?

#

huh

sleek steppe
#

Uhh, yeah

whole minnow
#

oh yea nvm

#

tru

#

nvm

#

it pretty cool that it can also get documentation from non built in libs tho

#

oh

#

not all of them

#

nvm

gritty wind
#

If the library provides somewhere we can get documentation, we can add it

#

I don't think we've had suggestions for any specific libraries before, but if you feel like something would be a nice addition, feel free to suggest it

fallen patrol
#

heck

#

does python or snek or sir or anything color its stdout logger output?

#

because uh, im trying to do so and well, lol

patent pivot
#

I think we use coloredlogs

fallen patrol
#

basically how im doing it is uh

#

logging everything twice

#

i figured out its when i do from bot import Bot in any cog it now starts to log everything twice

#

which is extremely annoying

gritty wind
#

We use coloroma in.. something

fallen patrol
#

the import is for the class, to get typcasting

#

i'm not importing my bot instance ffs

gritty wind
#

Try

#

One sec I’m on mobile

fallen patrol
#

that's fine

#

i haven't even practiced git yet so uh

#

yeah

gritty wind
#
if typing.TYPE_CHECKING:
    import ...
#

that will only run when you're running type checking, so it won't actually import when running

fallen patrol
fallen patrol
#

like, what are you guys using

gritty wind
#

we don't set up logs in the init or main

#

let me get you how we do it on python

fallen patrol
#

but, you do

gritty wind
#

huh, I guess we do lol

fallen patrol
#

so

fallen patrol
#

but wait

#

nope

#

it works to import it but not when trying to run it

gritty wind
#

yeah this is specifically if you want to type hint something

fallen patrol
#
if typing.TYPE_CHECKING:
    from bot import Bot


class SomeCommands(commands.Cog):
    """A couple of simple commands."""

    def __init__(self, bot: Bot):
        self.bot = bot

#

that works fine for writing but errors when running because Bot isn't defined

#

so its impossible to actually typehint

fallen patrol
gritty wind
#

try type hinting as "Bot"

fallen patrol
gritty wind
#

yeah

patent pivot
fallen patrol
#

...that works

#

but my main concern here is

gritty wind
#

can you give a POC

fallen patrol
#

it works fine on @stable mountain but not for me

gritty wind
#

I'm struggling to see what you want to do

fallen patrol
#
class SomeCommands(commands.Cog):
    """A couple of simple commands."""

    def __init__(self, bot: "Bot"):
        self.bot = bot
#

trying to typcast the bot in the cog so i get completion from my editor

sharp timber
#

commands.Bot perhaps?

fallen patrol
#

made a custom instance

gritty wind
#

and what do you have in your init

#

or rather, where are you defining the class

fallen patrol
#

i'm launching the bot directly from python3 bot.py

gritty wind
#

and bot.py is where the class is?

fallen patrol
#

and the bot class is defined in that file

#

yes

gritty wind
#

nice

#

alright, I'll give that a shot

fallen patrol
#

the issue is actually in the colorizer i believe

#

so im gonna try what joe linked

#

since uh this colorizer seems a bit odd anyways

#

yep

#

coloredlogs seems a bit easier

#

just a bit

#

down to coloredlogs.install(level='DEBUG') from like 15 lines to do it lmao

#

smh i forgot to import it
NameError: name 'coloredlogs' is not defined

gritty wind
#

One thing you can try to do is instead of adding a logging handler blindly, is to only add it if it doesn't exist. Alternatively add the code that needs to only be run once to a if __name__ == "main" block

#

Assuming coloredlogs doesn't do that

fallen patrol
#

smh

#

god

#

oh wait okay

#

that was already a thing

#
if __name__ == '__main__':
    bot = Bot(command_prefix='=', description=DESCRIPTION)
    bot.create_http_pool()
    bot.load_extensions()

    bot.run(TOKEN)
#

whew

gritty wind
#

where is the logging stuff

fallen patrol
#

in the

#

in the

#

why

#

its at line 67

#

above my constants

#

i uh

#

for one, i have no file structure

gritty wind
#

lol

fallen patrol
#

it was like, "oh, i should put this here, i'll put it above where i use it"

#

WOW

#

THAT WAS THE BUG

#

sigh

#

~~now i realize this was more a help channel thing, oops

#

thanks for the help, @gritty wind….

#

as annoyed as I am at what the bug actually was

sleek steppe
#

Lol

short snow
#

633 can now be merged 🎉

#

.issue 633

#

cool 😄

gritty wind
#

is the command not whitelisted here?

#

sir-lancebot#633

gritty wind
#

I'm guessing wrong bot

short snow
cold moon
#

Huh, .issue command is not, but <repo>#<nr> is?

#

They are basically same

short snow
#

yes

#

make a commit on main?

gritty wind
#

We revoked that permission

#

It's fine to PR

short snow
#

it is just one line, hence said

cold moon
#

For lancebot too?

gritty wind
#

Yes

#

Did we not?

#

yeah we did

cold moon
#

Core Devs is losing more and more permissions...

gritty wind
#

Or another way to look at it: pydis is becoming safer and safer lol

cold moon
#

More permissions = better

gritty wind
#

Core devs used to have the permission to deploy code that could annihilate the entire server, which imo is not very good

#

I think that sentiment was shared by quite a few core devs when we made that decision

brazen charm
#

issue should be allowed here unless someone reverted it

short snow
#

PR made

short snow
gritty wind
#

cc: @crude gyro

crude gyro
#

I forget all the details but essentially we wanted an interactive graphical component sort of like this one:

#

where you could hover and click the channels and see little Python chats

#

maybe with duckies for avatars

#

so we'd move some stuff around to make space for this component

#

@glass pecan himself will have to explain the rest, but I'm super excited about this component

balmy sparrow
#

just not mentioning any arguments there will also work fine

sharp timber
#

Hm

green oriole
#

!unsubscribe so you can type anything you want after it

#

Maybe

#

maybe not

balmy sparrow
#

you can do that if you just define the function as

async def unsubcribe(self, ctx):
green oriole
#

Oh there is a whitelist

#

Not sure then

short snow
glass pecan
#

a lot of work indeed amegablobsweats

short snow
#

It could be better if there is place where all this is noted, so people could help out

crude gyro
#

this particular thing is probably a one-man job.

#

should maybe still be an issue, but it's no big deal.

#

it sounds really fun to work on and I might spend a little vacation time on it.

#

@glass pecan how's your time next week?

green oriole
#

Peer coding for this could be fun

crude gyro
#

I have the entire week off, you see.

#

might be fun to jump in a stream together and work on it

glass pecan
#

It's not a coding thing pithink

#

but yeah lemon, happy to chat about it next week to get a solid outline

green oriole
#

CSS is a programming language

#

So it is coding

glass pecan
#

CSS is not the majority of the work for this

green oriole
#

Yes, but it allows me to not be wrong

short snow
#

design is.

crude gyro
#

I think it's 50/50 style and graphical assets

#

and I'm happy to do either.

#

bet the two of us in a stream could make short work of it, though.

green oriole
#

Looking forward to see the new design

glass pecan
#

I was thinking of seeing if we could make it a canvas element but that sounds pretty intense too lol

crude gyro
#

sounds overkill. I'd solve this with css, html and illustrator.

glass pecan
#

maybe, depends on the goal and functionality I guess. we'll see what we come up with in discussion

crude gyro
#

wanna set a time for a prelim voice chat about it?

sharp timber
#

It definitely looks css-able

glass pecan
#

css is definitely involved, yes

crude gyro
#

remember, we want interactive stuff

glass pecan
#

it'll be a bunch of annoying js too

sharp timber
#

There's a trick, if you've got a fixed size space--like this will have, I believe

#

You can use a bunch of position: absolute to force the elements on top of each other, then shuffle their z-index with the + selector to bring things to the front

#

I have a demo of this somewhere

glass pecan
#

yep, we do similar atm for the waves

#

that's just a simple version of it though

#

the canvas i mentioned before wouldn't make it overtly complex either lemon, it's still just html/css/js with graphical assets or css shapes

#

the only difference is that a canvas is a fixed positional area to work in while also having a bonus of low latency to any animations, as the browser will prioritise it

crude gyro
#

I'm open to it, I'd probably want to mostly do graphics.

glass pecan
#

ducky avys all over the place lol

crude gyro
#

yep! ducks and whatever you need, I'd be happy to produce that.

glass pecan
#

are we able to try make them non-same though or is that too much to ask for

#

like different poses and shiz

crude gyro
#

of course.

glass pecan
#

niiice

crude gyro
#

but seriously, we should put together a StreamYard session for this.

#

I think it'd be really fun

#

great content potential

glass pecan
#

hmmm

green oriole
#

Having the duck pond animation on the front page would be sick

glass pecan
#

duck pond animation?

crude gyro
#

from the most recent video, I guess.

green oriole
#

Yep

glass pecan
#

oh right

#

was thinking of the channel

#

i'm fine if you want to stream working on it yourself lemon, but I dunno if I want to personally be in a stream. so would that be ok

crude gyro
#

we'll figure it out.

short snow
#

probably on discord, so even others could join...

green oriole
glass pecan
#

lol more joining in is even worse

green oriole
#

Eeeh allowing random users to join sounds like a good way to get platform banned

crude gyro
#

stream was just an idea. I wanna do pair programming streams this year and thought this might be a fun opportunity.

glass pecan
#

probs is, it's just two things i aint a fan of mashed together lol

crude gyro
#

ducks and programming?

#

you and I?

glass pecan
#

permanent personal public exposure and pair programming

crude gyro
#

triple p expo

glass pecan
#

lots of p

crude gyro
#

as they say

glass pecan
#

haha

crude gyro
#

well in this case pair programming would be more like me doing graphics and you writing code

#

more like teamwork than formal PP

glass pecan
#

yeah i'm super self-concious about how badly I code so I never stream it lol

sharp timber
#

permanent personal public performance pair programming

glass pecan
#

nice

crude gyro
#

but not gonna pressure you into p6

glass pecan
#

i was looking at the thesaurus just now but that's good enough for me

#

howd you manage to both get different ways to represent that lol

sharp timber
#

My brain goes one way, yours goes another lol

crude gyro
#

I don't want to do any permanent personal public performance pair programming peer pressure.

glass pecan
#

dammit lemon

#

!otn add permanent personal public performance pair programming peer pressure

stable mountainBOT
#

:ok_hand: Added permanent-personal-public-performance-pair-programming-peer-pressure to the names list.

crude gyro
#

hahahahaha

green oriole
#

Oh no

crude gyro
#

that's sooo long

glass pecan
#

did it topple the other long one

#

will it even work

#

did we have a constraint that matches discords limit

green oriole
#

Jetbrain editions?

gritty wind
gritty wind
green oriole
#

I think we do have a 50 chars constraint

#

User what?

glass pecan
#

lol

#

"the user totally won't be bad and break the limit"

#

mhm

sharp timber
#

discord's limit is actually really big

glass pecan
sharp timber
#

its 127 chars I think

gritty wind
#

shame you can only ever see 10 of them

sharp timber
#

ikr..

glass pecan
#

lol

#

better that than wrapping tho

#

imagine...

#

actually don't, it hurts

sharp timber
#

I do bad things on my test server

green oriole
#

Oh

#

No

gritty wind
#

wowzers

glass pecan
#

seems legit

crude gyro
#

goodness

green oriole
#

time to otn that /s

sharp timber
#

I wonder if adding spaces will make it worse pithink

#

oh. oh no.

clever wraith
#

how did you do that? wow

green oriole
#

Help, I have been kicked by kutie's broom

obsidian patio
#

The worst part is that nicknames can get really disturbing like that, since they cover half the screen (on some platforms)

#

But I think it’s best not to give people ideas

sharp timber
#

this is a good point

green oriole
#

By the way, @vocal prairie, would you like to open a PR for the contributing tag?

green oriole
vocal prairie
green oriole
#

Cool, I'll assign you to the issue if that's fine with you

short snow
#

a nickname can't be more than 32 chars long...

vocal prairie
#

Those characters were really long.

short snow
#

I have a comment left on bot#1154 , if someone could answer that.

dusky shoreBOT
vocal prairie
#

It would be simpler to use a markdown file with certain links stored with keywords. It could also be a json or yaml.

#

Why reference an API when it's not needed?

short snow
#

We would need to add them manually every time

#

(and I have updated the comment.)

vocal prairie
#

It wouldn't be hard to add them quickly, would it?

short snow
#

you can't add star and fork count manually...

vocal prairie
#

Do we need that?

short snow
#

It would be good to have them

sleek steppe
#

lmao how did I not notice that

placid ermine
#

lmao

fallen patrol
green oriole
#

Firstly, it isn't me

#

It is all @gritty wind's fault

vale ibex
#

I feel like scale is the true culprit

green oriole
#

And secondly it is the BSD value for a connection error

#

EX_UNAVAILABLE (69) A service is unavailable. This can occur if a sup­port program or file does not exist. This can also be used as a catchall message when something you wanted to do doesn't work, but you don't know why.

gritty wind
fallen patrol
#

you put it where there would be connection issues and did it

fallen patrol
gritty wind
#

Different to what

fallen patrol
#

wtf

#

what is your color grading

eager fable
#

ikr, it's different each picture

fallen patrol
#

FF784D

vocal prairie
#

What about a color command for Sir Lancebot?

cold moon
vocal prairie
#

Oh.

#

Nice

#

I was thinking something like: .colo(u)r 00ffdb giving

patent pivot
#

hmmm

#

@cold moon let's migrate that discussion here

#

this is what we said internally

#

we have pillow to generate images, if we want to do conversions we have colorsys

#

colorsys is great for generating random (yet vibrant) colors with random HSV values rather than RGB

#

I guess the only thing that the color API gives us is the colour names

vocal prairie
#

We could hardcode some color names.

cold moon
#

We can get like color names, and then we can avoid using our resources for generating

vocal prairie
#

Into a markdown, json, or yaml file.

patent pivot
#

our resources can handle it

#

like I think that

thorny obsidian
#

+1 to colorsys. I'd rather rely on our resources than an API where we have to manage an API key and ratelimits

patent pivot
#

sir lancebot can be a glorified API wrapper

#

or we can actually write some cool shit like this 👽

#

and I think in the long run having stuff like

  • color generator with pillow
  • random vibrant colours with colorsys (which is really useful for all sorts of stuff!)
  • color conversions with colorsys
#

like colorsys is totally underated, and I think this is a good usage of lancebot to help teach something new

vocal prairie
#

I think it's better to give Lancebot full control over as much as we can (with being reasonable). So I think not using an API is better.

patent pivot
cold moon
#

Can we cache color Pillow objects? So we don't need to regenerate them every time.

patent pivot
#

it isn't really an expensive generation, but if we have to we can look at caching to filesystem temporarily

cold moon
#

I remember we had some issues with performance of image generation recently

patent pivot
#

We upgraded enough that it isn't a problem

#

lancebot can consume a whole CPU core and we're still sailing fine

vocal prairie
#

Dang. That's some serious power.

patent pivot
#

I think Chris is working on ensuring image commands get queued rather than all run concurrently

#

we could also look into switching to pillow-simd

#

but yeah I think in general

#

where there are two fairly equivalent difficult solutions and one is an API and one is implemented by us

vocal prairie
#

I think our own implementation would be a nice learning experience.

#

Especially if you involved multiple members of the community.

patent pivot
#

yeah

#

it fits the goals of the lancebot project to implement stuff ourselves

sleek steppe
#

or he didn't do it yet

patent pivot
#

hmmmmm

#
green oriole
#

Scal asked what to put here, so I took my BSD manual out to check it out

fallen patrol
#

👀

#

bsd manual

sleek steppe
patent pivot
#

that's what the PRs do

#

it's all transparent to the user

sleek steppe
#

But I'm looking at the code and there's no queuing EyeShake

green oriole
#

Not yet

sleek steppe
#

Oh ok. That was what I was asking the entire time

patent pivot
#

ahh, yeah, nothing yet, that's why it's an issue + open PR

sleek steppe
#

although queuing it is as easy as

    @commands.max_concurrency(1, wait=True)
    @commands.group()
    async def pfp_modify(self, ctx: commands.Context) -> None:
#

or is it channel

gritty wind
#

The built in buckets won’t work for this because it needs to be one bucket for all commands

sleek steppe
#

oh

#

alright I edited it

#

because by default it's on BucketType.default

gritty wind
#

It won’t work because the bucket has to act on multiple sub commands

#

The sub commands would each get their own bucket

sleek steppe
#

That only would happen if group.invoke_without_command = True

gritty wind
#

Which they are

sleek steppe
#

This one isn't

gritty wind
#

They will hopefully maintain the current commands

#

Which don’t take a group

#

Also I’m not sure that’s true

#

We tested the built in buckets for this when the issue was originally opened

sleek steppe
#

I just tested it now though

#

actually yeah I don't think it works

vale ibex
#

yea, wrapping the group with ```py
@commands.group(invoke_without_command=False)
@commands.max_concurrency(1, per=commands.BucketType.user, wait=False)
async def pfp_modify(self, ctx: commands.Context) -> None:

#

I think we're likely going to need to define our own bucket

sleek steppe
#

I thought max_concurrency worked the same as cooldown but I guess they worked differently

#

Checks work on groups, but this isn't a check

vale ibex
#

Yea

#

I don't think it'll be a huge task to implement a custom bucket

#

I just haven't found time to investigate yet

vale ibex
whole forge
#

@vale ibex how are bot restarts/outdated caches handled now?

vale ibex
#

During init we use the fallback method, if either of the caches are empty we also use the fallback

whole forge
#

could you elaborate, im not sure i understand?

vale ibex
#

When the bot starts up it needs to determine how long to schedule the close task for, in that case we use the fallback method (idle_claimant+last message timestamp)

#

once the init is done, it then uses the cached messages, unless either cache is empty for that channel, in that case it also uses the fallback

whole forge
#

the cache wont ever be empty tho, since mark wanted us to not use cache clearing.

vale ibex
#

I guess it covers us for the upgrade path, and if redis does ever get cleared

#

i can't see any harm in having outdated stamps in the cache

sleek steppe
#

@vale ibex why should we quote the username?

vale ibex
#

it's less that it's a username, but more the fact that we're giving user input control over the end of a url

#

so they could add query parameters on the end as an exmaple

sleek steppe
#

oh right that makes sense

vale ibex
#

I'm not sure of an attack vector for that currently

sleek steppe
#

I thought of that but didn't bother because .github already does that

vale ibex
#

Yea, it's not something specifically you've added, but something we should try to avoid where possible

#

I can't think of an attack vector atm, but it could mean users can request things we're not expecting

#

Also, is there a chance that github will return html escaped chars in the response?

#

if so we should unescape them

sleek steppe
#

@tawdry vapor why did you use typing.Type?

tawdry vapor
#

Cause we're passing a type not an instance

sleek steppe
#

Ah I see

vale ibex
#

@tawdry vapor Your point about the logic is good though, I could convert it to be easier to read, since inverse blocks like that aren't intuative

tawdry vapor
#

Yeah, if you want. I don't really like multi-line if statement either tbh.

#

You should just use message.created_at and get the timestamp from it

#

I think that function could be clearer in control flow too

vale ibex
#

update_message_caches()?

tawdry vapor
#
if not claimant_id:
  return

if message.author.id == claimant_id:
  ...
else:
  ...
vale ibex
#

Thoughts about ```py
if is_empty or not init_done or non_claimant_last_message_time is None or claimant_last_message_time is None:
...

#

I think that's far clearer than ```py
if is_empty or not all(
init_done,
non_claimant_last_message_time,
claimant_last_message_time,
):
...

whole forge
sleek steppe
vale ibex
sleek steppe
#

Maybe check if there's a ??

vale ibex
#

I mentioned that for a similar reason as the other one, since users can add arbitrary query params

#

How are you quoting it? I'm not sure where those %22 are coming from

sleek steppe
#

%22 is "

vale ibex
#

Yea, where are those coming from?

sleek steppe
#

it just formats like that

vale ibex
#

Could you send the snippet of code?

#

Also, any core devs lurking please feel free to step in if you think this isn't needed

sleek steppe
#

these are all of the parameters though

vale ibex
#

i could send a username of test/blocks or test/hovercard as an example and access arbitrary paths

#

which might cause weird behaviour/errors in the bot

#

!e !e ```py
from urllib.parse import quote as quote_url
ENDPOINT = 'https://.../user'

username = 'ChrisJL'
username2 = 'ChrisJL/blocks?some_random=param'

print(f"{ENDPOINT}/{quote_url(username, safe='')}")
print(f"{ENDPOINT}/{quote_url(username2, safe='')}")

stable mountainBOT
#

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

001 | https://.../user/ChrisJL
002 | https://.../user/ChrisJL%2Fblocks%3Fsome_random%3Dparam
sleek steppe
#

because it needs owner/repo

vale ibex
#

.src github repo

dusky shoreBOT
#
Command: github

Fetches a user's GitHub information.

Source Code
sleek steppe
#

That's a new command btw

vale ibex
#

ahh ok 1 sec

sleek steppe
#

safe='/'?

#

or something else...

vale ibex
#

ahhh I see, I'm not sure about that one then, since we want the user to enter a /

#

possibly 2 args, rather than a single one?

sleek steppe
#

make sure repo.count('/') is 1?

vale ibex
#

I mean at this point we're getting quite far down a rabbit hole for a possible non-issue

sleek steppe
#

maybe lol

sleek steppe
vale ibex
#

Yea, maybe just leave my comments there and see if the core devs reply when they review

sleek steppe
#

Something like this is fine?

#
repo_data = await self.fetch_data(f"{GITHUB_API_URL}/repos/{quote(repo, safe='/')}")

And then add / to safe

vale ibex
#

safe defaults to / so you can skip that 😄

sleek steppe
#

oh ok

vale ibex
#

Since you can't do datetime.min.timestamp() would setting the timestamp to 0 indicate that it's the smallest timestamp possible?

#

or is there an easier to read way to do that?

#

nevermind, got a better way that makes the flow make more sense.

fallen patrol
#

if there's no owner, default to pydis?

patent pivot
#

Nope

#

Why

fallen patrol
#

doesn't redirect

patent pivot
#

yep, redirects

fallen patrol
#

👀

#

no?

gritty wind
#

It redirected me

fallen patrol
#

perhaps I have an extension or something that is somehow blocking it

gritty wind
#

Most likely something with your local browser

fallen patrol
#

but its not redirecting with me

gritty wind
#

Nah probably just need a hard reload

patent pivot
fallen patrol
#

the other things aren't

#

oh okay

gritty wind
fallen patrol
#

clearing cache with ctrl f5 worked