88x31 button you can draw on
i hope this isn't a mistake :3
I made this 88x31 button which you can draw on with GET
requests. It's added to my home page. Feel free to automate anything you want to draw on it. The
interface is very simple on purpose and I don't plan to add any more functionality to it. This is scary,
please be nice <3
For example, go to
https://cqql.site/chaosbtn/draw?x=3&y=1&r=255&g=255&b=255
to make a pixel turn white. (first from the top and third from the left, counting from 0). The r/g/b
values go from 0 to 255 and x/y go from 0 to 87 and 30 respectively.
Here's what the button looks like now, so you can see your changes!
I might set up my own automations for it (with some generative art) in the future.
Have fun!
creatures
lexi
I woke up to there being a boykisser on the button, so i looked at the history of changes and found who was messing with it from their pfp :3
lexi (@orthoplex) wrote code to draw boykissers at random positions on the button
here's the script:
import time, random, urllib.request, matplotlib.image
im = (255 * matplotlib.image.imread("boykisser.png")).astype(int)
while True:
X = random.randint(1,88)
Y = random.randint(1,31)
print(f"drawing boykisser @ {X},{Y}")
for y,row in enumerate(im):
for x,(r,g,b,a) in enumerate(row):
if a == 0: continue
url = f"https://cqql.site/chaosbtn/draw?x={(x+X)%88}&y={(y+Y)%31}&r={r}&g={g}&b={b}"
while b"OK" not in urllib.request.urlopen(url).read():
time.sleep(1)
snow
then snow joined with this defacing campain /j
with code in go
func draw() error {
f, err := os.Open("img.jpg")
if err != nil {
return err
}
img, err := jpeg.Decode(f)
if err != nil {
return err
}
for {
for x := 0; x < 88; x++ {
for y := 0; y < 31; y++ {
r, g, b, _ := img.At(x, y).RGBA()
uri := fmt.Sprintf("https://cqql.site/chaosbtn/draw?x=%d&y=%d&r=%d&g=%d&b=%d", x, y, r/257, g/257, b/257)
req, err := http.NewRequest("GET", uri, nil)
if err != nil {
return err
}
_, err = http.DefaultClient.Do(req)
if err != nil {
return err
}
}
}
}
}
boykisser vs. windows
... then snow broght out the big guns with this code
which she says
> skips all pixels that are already windows
> so i can defend my defacement art more efficiently :3
and the fight started
but then she updated the code...
> made it stop caring about the request's response so it can hammer harder
> just send it off and move on we dont neeed to waste 200ms waiting for an "ok"
what 88 threads do to a mf
at that point, the server software hosting this button kept dying from those two DDoSing it but then
docker-compose restart: always
kept bringing it back to life, over and over forever. in a
loop of death and revival.
so i decided to optimize the server software a bit, because it was choking on saving each /draw
request as a file - too much io. i made it save to disk only once per second but the in-memory button
(which is what's served) gets updated on every request.
this is insane, so i decided to step in (we can't let windows win). i told snow that i'll run lexi's code on the vps itself (lower latency but not modifying the server software, so it's not cheating!).
for a brief moment the boykisser won
but snow said she may buy a vps in the same datacenter as this
to get shorter request times.
hyperfocused adhd creatures are scary...
well, turns out she didn't have to.
> i already had a vps in the same datacenter as you
> so yeah just quickly rsync'd over my script and launched it there
> saves me like 15ms per request :hehe:
now, running lexi's code on localhost, we started seeing only a sprinkle of boykisser on the windows logo.
but there's no winning with snow, at least using python as the weapon. through trial and error, she got a vps on the same physical machine as my vps. and showed off her sub millisecond ping
finally, we conceded. i'll have to buy snow coffee for this.
nix
nix joined!
and drew on the button with a makefile
:o
(after a while of waiting for me to finish debugging)
it would be too long to paste it here but this is how fae generated it
from PIL import Image
def start():
im = Image.open("aceEnby.png", "r")
pixelData = list(im.getdata())
with open("Makefile", "w") as f:
f.write(".PHONY: draw\ndraw:")
for x in range(0, 88):
for y in range(0, 31):
f.write(" draw" + str(x*31+y))
f.write("\n\n")
for x in range(0, 88):
for y in range(0, 31):
f.write("draw"+str(x*31+y)+":\n")
f.write("\tcurl 'https://cqql.site/chaosbtn/draw?x=")
f.write(str(x))
f.write("&y=")
f.write(str(y))
f.write("&r=")
f.write(str(pixelData[x+y*88][0]))
f.write("&g=")
f.write(str(pixelData[x+y*88][1]))
f.write("&b=")
f.write(str(pixelData[x+y*88][2]))
f.write("'\n")
start()
fae released the code under cc0 / public domain.
also fae discovered:
> fun fact I basically just learned today:
> if you start make like this
> make -j
> without specifying a number, it takes it as meaning infinite threads
this silly idea turned out to be overpowered because make -j
lead to all draws happening in
individual threads
baba
later, nix's flag was joined by baba. i don't know who drew it.
Alyssa
I saw Alyssa experimenting at different moments, drawing DANK in different ways on the button.
another nice use of transparency and only redrawing pixels that need changing. her code is available here: why2.py
ariel
the gradient in the button above came from a linguist catboy who used python pandas dataframes to store the image data.
same with this one, which came before nix's acenby flag.
his script can draw any gradient on the button from user input, up to 5 colors. it's really cool (and universal). you should give it a try, the code is available here: gradient.py
return of snow
it's necessary to mark snow's achievement, while still letting others have their fun. from this point on, there always has been a big unconquerable snowflake in the middle of the button that everyone just decided to draw around.
lexi is back
very important addition from lexi.
silt
silt joined the party in style as usual, with a script in uiua.
⍜°⍉↙₃⁅×255◌°img&frab"button.png"
°¤↙₁⤸₂⍜°⍉↙₂°⊡
⍜♭₂⤸₁⍉⊂∩°⍉
?
wait≡spawn(⍢∘(⍣(
$"GET /chaosbtn/draw?y=_&x=_&r=_&g=_&b=_ HTTP/1.1\r\nHost: cqql.site\r\nConnection: close\r\n\r\n"
&s $"REQUEST _".
⍜(&tlsc "cqql.site:443"|&rs∞⊸&w:)
&s ⤚$"REPLY _ _" ⧻⊚⌕"\"OK\"".
&p ""
≠1
|1)))◌⍥(:°⊂)⊸⧻⇌
it runs every pixel in a separate thread.
this is the button silt wanted to draw:
but snow's snowflake prevails
do you want to have your own?
I also hosted everything to allow more creatures to host their own buttons like this, including a safeguard to easily revert the button to its original state. It's a perk for any supporters on my Ko-Fi page (reach out to me if you'd like one).