import everything!

This commit is contained in:
tezlm 2024-05-22 04:03:59 -07:00
commit ac21716d38
Signed by: tezlm
GPG key ID: 649733FCD94AFBBA
120 changed files with 9953 additions and 0 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
media
private

36
.pnpm-debug.log Normal file
View file

@ -0,0 +1,36 @@
{
"0 debug pnpm:scope": {
"selected": 1
},
"1 debug pnpm:package-manifest": {
"initial": {},
"prefix": "/home/zestylemonade/content"
},
"2 debug pnpm:context": {
"currentLockfileExists": false,
"storeDir": "/home/zestylemonade/.pnpm-store/v3",
"virtualStoreDir": "/home/zestylemonade/content/node_modules/.pnpm"
},
"3 debug pnpm:stage": {
"prefix": "/home/zestylemonade/content",
"stage": "resolution_started"
},
"4 error pnpm": {
"code": "ERR_PNPM_FETCH_404",
"hint": "xterm-addot-fit is not in the npm registry, or you have no permission to fetch it.\n\nNo authorization header was set for the request.",
"request": {
"url": "https://registry.npmjs.org/xterm-addot-fit"
},
"response": {
"size": 0
},
"pkgName": "xterm-addot-fit",
"pkgsStack": [],
"err": {
"name": "pnpm",
"message": "GET https://registry.npmjs.org/xterm-addot-fit: Not Found - 404",
"code": "ERR_PNPM_FETCH_404",
"stack": "pnpm: GET https://registry.npmjs.org/xterm-addot-fit: Not Found - 404\n at RetryOperation._fn (/usr/lib/node_modules/pnpm/dist/pnpm.cjs:85709:19)\n at processTicksAndRejections (node:internal/process/task_queues:96:5)"
}
}
}

View file

@ -0,0 +1,8 @@
{
"m.homeserver": {
"base_url": "https://celery.eu.org"
},
"org.matrix.msc3575.proxy": {
"url": "https://syncv3.celery.eu.org"
}
}

View file

@ -0,0 +1,3 @@
{
"m.server": "celery.eu.org:443"
}

4
.well-known/mta-sts.txt Normal file
View file

@ -0,0 +1,4 @@
version: STSv1
mode: enforce
max_age: 86400
mx: celery.eu.org

BIN
adderall.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

52
adderall.md Normal file
View file

@ -0,0 +1,52 @@
::: header
# adderall
:::
::: section
I was prescribed adderall a few years ago, but stopped because of
the side effects (trouble sleeping and bad dreams from what I can
remember). Fast forward to about a month ago, and I was having a lot of
trouble focusing. I stumbled upon the old adderall pills, and because
nothing can ever go wrong, took them.
The effects were great, so I went to a psychiatrist to try to get a
prescription. I was successful and and got some new pills.
![A photograph of three adderall pills. Two are oblong, with the one on
the right being circular.](adderall.jpg)
From left to right: old pills, new pills, and extra bonus pills (pure
amphetamine salts) that aren't relevant. The old pills have "adderall
xr" printed on them (are brand name) and the new ones say "ELI-511"
(manufactured from "elite laboratories"). Both of the doses are are
10mg. The new pills were clearly visually different, but I assumed that
adderall was tightly regulated so they'd have the same effect.
The effects were *noticably* different. I tried taking the new pills one
day then the old pills on another, and it was almost like two different
medications.
I did a bit of precursory research to see if it was only me and found
some people grumbling about how it's a tiktok trend and mass hysteria,
except that I have never used tiktok in my life.
Searching for the brand name, it seems
like there are recurring problems with elite labs
([one](https://rd.celery.eu.org/r/ADHD/comments/164zo38/elite_pharmaceutical_adderall/),
[two](https://rd.celery.eu.org/r/ADHD/comments/15tzbkk/generic_adderall_xr_from_elite_laboratories/),
[three](https://rd.celery.eu.org/r/ADHD/comments/cwgshb/generic_adderall_switch_teva_to_elite/)).
The descriptions (especially "it feels like sleep deprevation" and "it
makes me jittery") matches my experience pretty well! Every once in a
while, I felt like I was going to have a heart attack.
## going further
todo: self blinded trials
## notes
to look at:
- https://news.ycombinator.com/item?id=35111061
- https://en.wikipedia.org/wiki/Adderall
- https://www.npr.org/sections/health-shots/2019/05/12/722216512/bottle-of-lies-exposes-the-dark-side-of-the-generic-drug-boom
:::

76
adhd.html Normal file
View file

@ -0,0 +1,76 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8" />
<title>adhd</title>
<link rel="stylesheet" href="/assets/style2.css" />
</head>
<body>
<header>
<h1>adhd</h1>
</header>
<section>
<p>
It's not overstimulation, it's <em>under</em>stimulation. Everything else is
always more interesting than the thing you're currently doing. That link
is more interesting than the tab I'm looking at, and now I have 279 (at
the time of writing) tabs open. That hobby is more interesting than what
I'm doing, and now have have 30 hobbies and suck at all of them. I have
something important tomorrow, but there's 100 things more interesting
right now. I get bored after approximately ten seconds.
</p>
<p>
Normal people get bored and distracted too, but the difference is
this is chronic and is always on and can cause incredibly absurd or
at least interesting results over the long term. If there's a way
to get stimulation, adhd people will try it. For example: complex
music (ie. breakcore, dnb, psytrance), strong food flavors, doing
random bullshit and seeing what happens, and maybe some masochistic
tendancies. But once it becomes the new normal, it doesn't work as well;
the default is to be understimulated.
</p>
<p>
The task of focusing on things is like a solid brick wall, but mental
instead of physical. Some people don't think it exists, or that I'm
making it up. People who do want to help usually can't, since they don't
really understand having adhd. Useless advice is ubiquitous: "That solid
brick wall doesn't really exist!" or "Use your inner strength to break
through the solid brick wall!" or "I did xyz to reach my goal behind
this distinct lack of solid brick wall!" or "Just do the thing lol".
</p>
<p>
Some people like natural methods to help with it, such as exercise or
meditation. It's certainly possible to scale the solid brick wall, and
get better at it over time. However, I'd rather take the easy way out
and take what's effectively a magical pill that removes this pain from
my life (adderall). I'm still not sure if adhd has any nice benefit,
or if its a completely waste of time; "hyperfocus" is nice, but honestly
I'd rather be able to focus normally so I don't lose track of time.
</p>
<p>
At this point, it's probably a good idea to declare attention bankrupcy
and close every tab and start fresh. I probably won't though, since I
don't like closing unread tabs.
</p>
<blockquote>
When focus is precious and slippery, willpower and energy become rare
and valuable resources.
</blockquote>
<p>Some other neat side effects</p>
<ul>
<li>
My memory is broken. I remember some things perfectly but forget other things within seconds.
</li>
<li>
I can starve or get dehydrated by accident by forgetting to eat/drink
</li>
<li>
Adderall makes me shit a lot for some reason? It seems to happen to a
lot of people, but nlm doesn't have anything. If anyone knows, please
tell me <!-- i'm reachable at @tezlm:celery.eu.org on matrix and
ZestyLemonade#1012 on discord. yup, i still have a numeric username -->
</li>
</ul>
</section>
</body>
</html>

55
adhd.md Normal file
View file

@ -0,0 +1,55 @@
::: header
# adhd
:::
::: section
It's not overstimulation, it's *under*stimulation. Everything else is
always more interesting than the thing you're currently doing. That link
is more interesting than the tab I'm looking at, and now I have 279 (at
the time of writing) tabs open. That hobby is more interesting than what
I'm doing, and now have have 30 hobbies and suck at all of them. I have
something important tomorrow, but there's 100 things more interesting
right now. I get bored after approximately ten seconds.
Normal people get bored and distracted too, but the difference is
this is chronic and is always on and can cause incredibly absurd or
at least interesting results over the long term. If there's a way
to get stimulation, adhd people will try it. For example: complex
music (ie. breakcore, dnb, psytrance), strong food flavors, doing
random bullshit and seeing what happens, and maybe some masochistic
tendancies. But once it becomes the new normal, it doesn't work as well;
the default is to be understimulated.
The task of focusing on things is like a solid brick wall, but mental
instead of physical. Some people don't think it exists, or that I'm
making it up. People who do want to help usually can't, since they don't
really understand having adhd. Useless advice is ubiquitous: "That solid
brick wall doesn't really exist!" or "Use your inner strength to break
through the solid brick wall!" or "I did xyz to reach my goal behind
this distinct lack of solid brick wall!" or "Just do the thing lol".
Some people like natural methods to help with it, such as exercise or
meditation. It's certainly possible to scale the solid brick wall, and
get better at it over time. However, I'd rather take the easy way out
and take what's effectively a magical pill that removes this pain from
my life (adderall). I'm still not sure if adhd has any nice benefit,
or if its a completely waste of time; "hyperfocus" is nice, but honestly
I'd rather be able to focus normally so I don't lose track of time.
At this point, it's probably a good idea to declare attention bankrupcy
and close every tab and start fresh. I probably won't though, since I
don't like closing unread tabs.
> When focus is precious and slippery, willpower and energy become rare
> and valuable resources.
Some other neat side effects
- My memory is broken. I remember some things perfectly but forget other
things within seconds.
- I can starve or get dehydrated by accident by forgetting to eat/drink
- Adderall makes me shit a lot for some reason? It seems to happen to a
lot of people, but nlm doesn't have anything. If anyone knows, please
tell me <!-- i'm reachable at @tezlm:celery.eu.org on matrix and
ZestyLemonade#1012 on discord. yup, i still have a numeric username -->
:::

6
assets/code.css Normal file
View file

@ -0,0 +1,6 @@
.hljs-number, .hljs-literal { color: #ff9e64; }
.hljs-string { color: #9ece6a; }
.hljs-attr { color: #7dcfff; }
.hljs-keyword { color: #bb9af7; }
.hljs-comment { color: #565f89; }
.hljs-built_in { color: #e0af68; }

28
assets/directory.css Normal file
View file

@ -0,0 +1,28 @@
table {
width: 100%;
font-family: ui-monospace, "Segoe UI Mono", "Source Code Pro", monospace;
}
table td:nth-child(1), table th:nth-child(1) {
text-align: left;
}
table td:nth-child(2), table th:nth-child(2),
table td:nth-child(3), table th:nth-child(3) {
width: auto;
text-align: right;
padding-left: 0.5em;
}
table td:nth-child(3), table th:nth-child(3) {
width: 15%;
}
.git {
padding: 1em;
border: solid #41ead4 2px;
border-radius: 4px;
background: #41ead422;
margin-bottom: 1em;
}

21
assets/essay.css Normal file
View file

@ -0,0 +1,21 @@
@font-face {
font-family: "times"
src: url("/assets/fonts/TimesNewerRoman-Regular.otf");
}
* {
font-family: "times" !important;
line-height: 2;
}
body {
max-width: 550px;
padding-top: 2em;
background: #fdfdfd;
color: #222222;
}
a {
color: #4361ee;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

26
assets/index.css Normal file
View file

@ -0,0 +1,26 @@
canvas {
position: fixed;
top: 0;
left: 0;
}
main {
bottom: 0;
left: 0;
position: fixed;
padding: 8px;
}
#pre {
background: transparent;
margin: 0;
}
#main {
font-family: monospace;
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
}

68
assets/index.js Normal file
View file

@ -0,0 +1,68 @@
// the cool spinning circles on index.html
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const rnd = (n) => Math.floor(Math.random() * n);
const colors = ["#f0d644", "#63eebe", "#9e4adf"]; // i like neon
const points = [];
let time = 0;
// handle page resizes without ruining everything
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.width = canvas.width;
ctx.height = canvas.height;
}
// math moment
function rotation(point) {
return point.rot + time * point.speed;
}
function length(point) {
return Math.min(time * point.speed, point.speed * 4);
}
function arc(point) {
const angle = rotation(point);
return [angle, angle + length(point)];
}
// initialize the canvas
function init() {
resize();
window.addEventListener("resize", resize);
for (let i = 0; i < 10 + rnd(4); i++) {
points.push({
color: colors[rnd(colors.length)],
radius: Math.random() * 600 + 300,
speed: Math.random() / 10 + 0.1,
rot: Math.random() * 2 * Math.PI,
});
}
}
// the heart and soul of the circles
function anim() {
// center points
const cx = ctx.width / 2;
const cy = ctx.height / 2;
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.globalAlpha = time / 3; // fade in
ctx.lineWidth = 4;
for (let point of points) {
ctx.beginPath();
ctx.strokeStyle = point.color;
ctx.arc(cx, cy, point.radius, ...arc(point));
ctx.stroke();
}
time += 0.01;
setTimeout(anim, 1000 / 60);
}
init();
setTimeout(anim, 1000);

133
assets/index2.js Normal file
View file

@ -0,0 +1,133 @@
const pre = document.getElementById("main");
// the cool spinning circles on index.html
const rnd = (n) => Math.floor(Math.random() * n);
const points = [];
let time = 0;
let charRows, charCols, charHeight;
// handle page resizes without ruining everything
function resize() {
const canvas = new OffscreenCanvas(100, 100);
const context = canvas.getContext("2d");
context.font = getComputedStyle(pre).font;
const measured = context.measureText("x");
charHeight = measured.fontBoundingBoxAscent + 5;
charRows = Math.floor((window.innerHeight) / charHeight);
charCols = Math.floor((window.innerWidth - 5) / measured.width);
}
const shades = " .:=+*#%".split("");
// const shades = "01234567".split("");
const shaders = [
// stripes
(t, x, y) => {
return shades[Math.floor(Math.abs((x * t / 30) + (y * t / 15)) * t / 10) % 8]
},
// circles
(t, x, y) => {
return shades[Math.floor(Math.sqrt(x ** 2 + y ** 2) * (t / 10)) % 8]
},
// mandelbrot
(t, x, y) => {
const scale = 20000 / (t + 100) ** 2;
let x0 = x * scale - .803, y0 = y * scale - .167, x1 = 0, y1 = 0, i = 0;
for (; i < 100 && x1 ** 2 + y1 ** 2 <= 2 ** 2; i++) {
const tmp = x1 ** 2 - y1 ** 2 + x0;
y1 = 2 * x1 * y1 + y0;
x1 = tmp;
}
return shades[Math.floor(i) % 8];
},
(t, x, y) => {
const xs = x * t / 3;
const ys = y * t / 3;
return shades[Math.floor(Math.abs((xs % ys || 0) - (ys % xs || 0))) % 8]
},
(t, x, y) => {
const s = ((x / y + t / 10) & 1 / y & 1) && y > 0;
return shades[Math.floor(s) % 8]
},
(t, x, y) => {
return shades[(Math.cos(50*Math.sin((y)/(x))+5*(t/30))+1)*4<<0];
},
// FIXME: broken on some screen resolutions
// (t, x, y) => {
// const rows = [
// " __ ",
// " ________ / /__ _______ __ ___ __ __ ____ _________ _",
// " / ___/ _ \\/ / _ \\/ ___/ / / // _ \\/ / / // __ \\/ ___/ __ `/",
// "/ /__/ __/ / __/ / / /_/ // __/ /_/ // /_/ / / / /_/ / ",
// "\\___/\\___/_/\\___/_/ \\__, (_)___/\\__,_(_)____/_/ \\__, / ",
// " /____/ /____/ ",
// ];
// const tween = Math.sin(t / 30 + x * 2) * 3;
// const ch = rows[Math.round(tween + y * (charRows / 2)) + (rows.length / 2)]?.[Math.round(x * (charCols / 2)) + rows[0].length / 2];
// return ch || " ";
// },
];
// const shader = shaders[Math.random() * shaders.length << 0];
const shader = shaders[2];
function shade(x, y) {
return shader(
time,
(x / (charCols / 2)) - 1,
(y / (charRows / 2)) - 1,
);
}
const rows = [];
function draw() {
if (rows.length !== charRows) {
while (rows.length) rows.pop().remove();
for (let i = 0; i < charRows; i++) {
const el = document.createElementNS("http://www.w3.org/2000/svg", "text");
el.setAttribute("x", 5);
el.setAttribute("y", i * charHeight + charHeight);
el.setAttribute("fill", "grey");
el.style.fontSize = "16px";
el.style.whiteSpace = "pre";
el.textContent = "you are at celery.eu.org";
rows.push(el);
pre.append(el);
}
}
for (let y = 0; y < charRows; y++) {
let buf = "";
for (let x = 0; x < charCols; x++) {
buf += shade(x, y);
}
rows[y].textContent = buf;
}
requestAnimationFrame(draw);
}
function init() {
resize();
window.addEventListener("resize", resize);
for (let i = 0; i < 10; i++) {
points.push({
shade: "celry"[Math.floor(Math.random() * 5)],
radius: Math.random() * 600 + 300,
speed: Math.random() / 10 + 0.1,
rot: Math.random() * 2 * Math.PI,
});
}
draw();
}
init();
setInterval(() => time++, 1000 / 60);

104
assets/read.css Normal file
View file

@ -0,0 +1,104 @@
body {
background: #fdfdfd;
color: #333333;
font: 20px/1.6 Georgia, "Times New Roman", serif;
padding: 2em;
margin: 0 auto;
max-width: 650px;
}
input {
box-sizing: border-box;
padding: 4px;
}
h1, h2, h3 {
margin: 1em 0 4px;
line-height: 1.2;
}
p {
margin-top: 1em;
}
ol, ul {
list-style-position: inside;
}
body > ol, body > ul {
margin: 1em 0 0;
padding: 0;
}
a {
color: #4361ee;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
code, pre {
font-family: ui-monospace, "Segoe UI Mono", "Source Code Pro", monospace;
line-height: 1.2;
background: #eaeaea;
padding: 1px 2px;
border-radius: 2px;
}
pre {
padding: 6px;
border-radius: 4px;
overflow-x: auto;
}
blockquote {
margin: 0;
padding-left: 1em;
border-left: solid #888888 3px;
font-style: italic;
color: #343434;
}
img, video {
display: block;
width: 100%;
height: auto;
max-height: 500px;
object-fit: scale-down;
}
figure {
margin: 0 auto;
display: table;
}
figcaption {
color: #888;
display: table-caption;
caption-side: bottom;
}
iframe {
width: 100%;
}
@media (prefers-color-scheme: dark) {
body {
background: #1d1d23;
color: #fbfbfb;
}
a {
color: #7fdeff;
}
code, pre {
background: #18181e;
}
blockquote {
color: #cacaca;
}
}

39
assets/rss.css Normal file
View file

@ -0,0 +1,39 @@
ul {
list-style: none;
padding: 0;
}
ul a {
text-decoration: none !important;
}
article {
background: var(--background15);
border: solid var(--background2) 1px;
padding: 8px;
}
h3 {
margin: 0;
font-weight: normal;
font-size: 1.2rem;
display: inline-block;
}
h3:hover {
background: #41ead422;
}
article p {
margin: 4px 0;
color: var(--color);
}
footer {
font-size: .8rem;
color: var(--color2);
}
li + li {
margin-top: 16px;
}

94
assets/style.css Normal file
View file

@ -0,0 +1,94 @@
:root {
--background: #222225;
--color: #dddddd;
}
body {
background: var(--background);
color: var(--color);
font: 16px/1.4 system-ui, "Segoe UI", "Cantarell", sans-serif;
padding: 2em;
margin: 0 auto;
max-width: 800px;
}
h1, h2, h3, h4 {
margin: 1em 0 4px;
}
h1, h2, h3, h4, h5, code, pre {
font-family: Consolas, monaco, monospace;
}
a {
color: #41ead4;
text-decoration: underline #318479;
}
a:hover {
background: #41ead422;
}
p {
margin-top: 1em;
}
ol, ul {
list-style-position: outside;
padding-left: calc(2rem);
}
body > ol, body > ul,
details > ol, details > ul {
margin: 1em 0 0;
}
code, pre {
background: #1a1a1a;
padding: 1px 2px;
border-radius: 2px;
}
pre {
padding: 4px;
overflow-x: auto;
}
blockquote {
margin: 0;
padding-left: 1em;
border-left: solid #444444 3px;
font-style: italic;
}
img {
display: block;
max-width: 100%;
max-height: 500px;
}
details {
border: solid #444444 1px;
padding: 8px;
background: #202021;
}
summary {
cursor: pointer;
}
.copytext {
cursor: pointer;
color: #cb72dc;
text-decoration: underline #8d5098;
}
.copytext:hover {
background: #cb72dc22;
}
.copytext a {
color: inherit;
text-decoration: inherit;
background: inherit;
}

101
assets/style2.css Normal file
View file

@ -0,0 +1,101 @@
:root {
--background1: #222225;
--background15: #1b1b1f;
--background2: #151519;
--color: #cccccc;
--color2: #aaaaaa;
}
body {
background: var(--background1);
color: var(--color);
font: 16px/1.4 system-ui, "Segoe UI", "Cantarell", sans-serif;
margin: 0;
}
header, section, main {
padding: 16px max(calc(50vw - 300px), 16px);
}
header {
background: var(--background2);
padding: 114px max(calc(50vw - 300px), 16px) 16px;
}
h1, h2, h3, h4 {
padding-top: 16px;
margin-bottom: -8px;
}
h1, h2, h3, h4, h5, code, pre, kbd, .eval {
font-family: Consolas, monaco, monospace;
}
a {
color: #41ead4;
text-decoration: underline #318479;
}
a:hover {
background: #41ead422;
}
p {
margin-top: 1em;
}
ol, ul {
list-style-position: outside;
padding-left: calc(2rem);
}
body > ol, body > ul,
details > ol, details > ul {
margin: 1em 0 0;
}
code, pre, kbd {
background: #1a1a1a;
padding: 1px 2px;
border-radius: 2px;
}
pre {
padding: 4px;
overflow-x: auto;
}
blockquote {
margin: 0;
padding-left: 1em;
border-left: solid #444444 3px;
font-style: italic;
}
img {
display: block;
max-width: 100%;
max-height: 500px;
}
details {
border: solid #444444 1px;
padding: 8px;
background: #202021;
}
summary {
cursor: pointer;
}
.eval {
color: #aaa;
font-style: italic;
margin-top: -.9rem;
font-size: .9rem;
}
kbd {
border: solid #3a3a3a 1px;
box-shadow: 1px 1px #2f2f2f;
}

90
batch-sync.md Normal file
View file

@ -0,0 +1,90 @@
::: header
# batch and sync
:::
::: section
I'd like to introduce a new api architecture. I know someone has probably
invented it before me and can't wait to find out, so I won't try to
create a new name for it.
In this api architecture, you have a single querying endpoint and
many batched action endpoints. At a high level, the client sends
a QUERY message and receives continual SYNCs when any interesting
data in the query updates. Think of this kind of like the [elm
architecture](https://guide.elm-lang.org/architecture/) over the network.
For example, imagine the client dispatches a query for user
preferences. Later the user settings are changed on a different (or
the same) client. The first client automatically gets the new settings,
because it has an active query for it.
## on the client
How does this look like on the client side in practice? You may be
tempted to use websockets, but use long polling instead. It isn't as
inefficient as you may think, and has some benefits.
- able to use quic/http3
- automatic throttling on low bandwidth
- can do single/one time queries easily, much easier to script
- simpler to implement since you don't need to do the websocket authentication dance
This can be implemented with `POST /sync[?after=position]`, where a
new position is returned with each sync. You can also cache the current
state and position to resume when the tab is loaded later. Maybe even put the
api client in a SharedWorker so every tab shares one logical connection.
Feel free to use whatever you like though, this high level architecture
can apply to most things. Though, don't be tempted to create multiple ways
to receive data, instead having a single source of truth. Querying/syncing
doesn't use requests/responses, and instead is fully asynchronous.
For querying, it can be as simple as getting a few keys and values
to graphql or even a minature sql dialect if you need that much
flexibility. Some queries don't need to be reactive, like searching.
Besides the single data receiving endpoint, have batching for all
other endpoints where it makes sense (ie. don't allow bulk account
registering).
## on the server
As long as you have only one writer/reducer (but as many readers/syncers
as you want), it's fairly simple. Give every record in your database
that you want to sync a "last updated at" timestamp. The position you
return to the client is the larges timestamp of all the items you're
returning. For higher availability, use something like raft to choose
a new reducer/writer if the main one fails.
If you must be Web Scale™ and have multiple reducers, timestamps don't
quite cut it since servers can be desynced.
To keep readers up to date, consider use a pubsub mechanism. If you're
using postgres, there's already one built in. If you need more scale,
there's plenty of existing software - I advise against making your own
since its one of those things that looks simple at first but gets more
complex over time.
For ratelimiting things that only affect local user by requests per second,
ratelimit things that affect other users by total batched items per second
## issues
For small apps that don't need realtime data or complex querying, you
probably don't need to bother with syncing: while simple to implement,
it's still unneeded complexity. I do recommend trying to [make apis
batched](https://matklad.github.io/2023/11/15/push-ifs-up-and-fors-down.html#Push-Fors-Down)
whenever though, since it's pretty much free performance.
Sorting can be hard with reactivity, but is fine if you only ever answer
queries once.
Pagination is annoying to implement, but still reasonable. Again, this
is one of those things that this architecture doesn't handle well and
rest is better at. I'd probably add extra GET endpoints to paginate.
## conslusion
I'm not sure how well this scales in practice, but it seems nice from an
initial inspection. Rest is a fairly leaky abstraction, since not every
action happens on a single object.
:::

50
caft-63e645b.md Normal file
View file

@ -0,0 +1,50 @@
# ifritserv/caft docs
- minecraft server: <span class="copytext" onclick="navigator.clipboard.writeText(this.innerText);return false">ifritserv.zapto.org:2023</span> (click to copy)
- discord guild: https://discord.gg/jK58DJ58Zh
## features
- Compatible with vanilla 1.20.1
- Terralith worldgen
- Incendium nether worldgen + nether items
- Every mob can drop its head
- Serverside Carpet
- Wear any item in your helmet slot
- `/flex` to show off the item you're holding in chat
- `/skin` to change your skin
- `/deathboard` to see a death leaderboard
- `/whereis` to find items in nearby inventories
## how to
<details>
<summary>how to use the raid (shadow legends) farm</summary>
1. Get bad omen from any pillager outpost. There's one directly accessible from the nether.
2. Go to the raid farm.
3. Immediately go into the water elevator (or you lose bad omen)
4. If you're not on your first raid, skip to step 9
5. A raid will start. Ignore it for now.
6. Stand below the chest.
7. Put all your items into the chest except some food and a sword.
8. Organize your inventory in a way that it's filled with the items you want to collect. If you want totems, leave some empty space in your inventory. ![screenshot of inventory setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/bb2ad5b01f62d9fc566bbc3e3946694d5c26adf91725949427471876096) <br />
9. Do the same thing with the hopper: ![screenshot of hopper setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/446b74ac4550035f00eb9d56d8fa616a9514516e1725949428184907776) <br />
10. Wait for the horns to stop ("ominous horn blaring", with subtitles)
11. Flip the lever. The fence gate should be closed.
12. Attack through the gap between the hopper and the chest until everything is dead.
13. If there's too many items on top of the hopper, take the lava bucket from the chest and place it on top of the hopper so the items burn.
14. Make sure to put back the lava bucket.
15. If you're done, take your items.
16. Flip the lever. The fence gate should be open.
17. On the ladders, go as far forwards as you can, then stop pressing w and you will drop right into the water.
18. If you want, repeat from step 3. Otherwise, you can leave the farm without doing anything special.
**Note:** you might also want to see [the video by ianxofour](https://youtube.com/watch?v=hVHFIfZAL54) for more background information.
</details>
## server map
// todo

74
caustic.md Normal file
View file

@ -0,0 +1,74 @@
::: header
# caustic
:::
::: section
In some communities, there exists difficult users. They don't break
any rules and aren't outright hostile, but are subtly caustic and
annoying. Left unchecked, they can kill a healthy community. Or at the
very least drastically change the culture.
They take many forms. Maybe when someone asks for help on some code, they
comment on the code style or formatting. Maybe they do give some bits
of advice, but they always seem to say "you're doing xyz wrong" instead
of explaining how to fix xyz. Worst of all, some of them participate
constantly. Then I think of myself, and other interactions across the
web. It seems like the culture of the internet is being pushed in this
direction.
This all kind of ties into modern internet culture a little. I don't have
a word for it but i call it "polite hostility", or sometimes "advertiser
friendly hostility". People tend to superficially follow the rules,
follow the social norms, follow what is said while ignoring what is
not. But when you look under the hood and they show their true colors,
there's still toxicity.
There are several theories I can draw from these observations. Perhaps
website design is pushing people for more "in-the-moment"
discourse. It promotes reactionary responses; quick emotional
or empty responses are rewarded, while more in depth thought is
discouraged. Go to a popular sites (youtube, tiktok, twitter/x,
reddit). Read the comments. How many are fluff or reactions, with
no substance? Is it more like a village, where everyone knows
each other, or a [train station; a liminal space strangers pass
through](https://www.marginalia.nu/log/82_killing_community/)?
Another theory is that people want to
find their tribe; to fit in. [Humans are social
creatures](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2527715/),
who want to recognize and be recognized. Even without peer pressure,
people will adopt other cultures over time. Time procures normalcy. And
this begs the question: what culture have we brought to the internet? Is
it a culture we're happy with?
When you make a bad decision, you're a moron. When a good
decision is made, it retrospectively was the [obvious choice all
along](https://en.wikipedia.org/wiki/Hindsight_bias). It's easier to doubt
than to hope, if only to stop yourself from becoming an outcast. People
like to follow the trends, be it fashion, news, other people, or thoughts.
People who follow trends rarely create them. For fashion, blindly
following trends can be harmless fun. When it comes to thoughts, parroting
without thinking can be dangerous. Because it's the trendy thing to do,
people tend to superficially follow thoughts, follow the social norms,
follow what is said while ignoring what isn't.
Everyone has the right to express themselves, the right to speak their
mind. Preventing people from freely expressing thought is the most
effective ways to stop free thought. And yet, there exist [things you
can't say](http://www.paulgraham.com/say.html). Things that should be
said, and things that probably shouldn't. What's good and bad and in
fashion is in constant flux, but getting more ideas into the world would
certainly be nice.
Everyone also has the right to ignore what others have to say. You get
free speech, but nobody has to listen to you. Try to push your ideas
into places where they're not wanted, and you'll lose your friends and
get ignored. Maybe the ideas come in the form of unwanted or irrelevant
cynicism. Maybe it's commenting on the code style or formatting when
someone asks for help on some code. Worst of all, it might be talking
without letting other people chime in. Get your own space to talk
about yourself.
Read between the lines.
:::

34
comms.md Normal file
View file

@ -0,0 +1,34 @@
::: header
# theory of communications
*[warning: this is a draft]*
:::
::: section
I've noticed there are only really 4 unique ways people on the internet
communicate with each other:
- **irc**-like: instant and ephemeral, synchronous
- **email**-like: personal async
- **usenet**-like: forums, communal async
- **rss**-like: broadcast
While the naming is mostly for fun, I do think that in essence these
really are the four horsemen of communication. On the irc side, you
have software like slack, discord, or matrix, along with a plethora
of bad recreations across thousands of apps. Rss has been forked into
microblogging and youtube. Usenet is the great grandpapi of forums like
reddit. And there's email, which to this date nobody has been able to
make any significant improvement on.
Now, there's no reason why you couldn't combine rss, usenet, and email
in one client. Unfortunately, irc kind of does its own thing compared to
email/usenet/rss, and since nearly every system since then copied its
mannerisms its difficult to work irc-like into a system that tries to
combine all four together.
to write about:
- interoperability between multiple similar systems, federation and standard apis
- interoperability between different systems, and getting irc to work well with them (prior art zulip + discord forum channels, autothreading)
- inbox vs feeds, when they switch between subscriptions to recommendations, benefits/downsides
:::

60
conduit-faq.md Normal file
View file

@ -0,0 +1,60 @@
::: header
# conduit faq
this should be moved into the [actual website](https://conduit.rs) at some point
:::
::: section
## what features are supported?
- room versions 3-5 (unstable) and 6-10 (stable)
- spaces
- threads (although somewhat in a beta state)
- voice calls, with [coturn](https://github.com/coturn/coturn) set up
- appservices (meaning bridges will work)
## can i prune old media/events?
no
## why isn't conduit working?
a few common problems:
1. do you have a publicly reachable domain name? and a public + static ip address?
2. does that domain name have a valid tls certificate? (look at [certbot](https://certbot.eff.org/) or [caddy](https://caddyserver.com/) (reverse proxy))
3. is conduit running, and can you contact it from localhost?
4. what about from outside localhost?
5. is the response for `/` "hello from conduit!"?
6. have you previously had a different matrix homeserver (synapse, dendrite) running on the same domain? if so, wait a day or two for the other servers to forget the old key
## how do i make the first user account on conduit?
1. enable registration
2. register an account then quickly disable registration
(yeah, maybe not the best method at the moment)
## how do i configure conduit to ______?
in config.toml:
- disable federation: `enable_federation = false`
- disable appending a lightning bolt to my display name: `enable_lightning_bolt = false`
- use that coturn thing i set up: [check out this document](https://gitlab.com/famedly/conduit/-/blob/next/TURN.md?ref_type=heads)
## what is conduit using as its database, and how do i back up rocksdb?
[rocksdb](https://github.com/facebook/rocksdb/wiki). conduit technically
supports sqlite, but it's not recommended (conduit currently abuses
sqlite as a key/value rather than a relational database).
to back up the database, stop conduit, start conduit (to compact the db),
stop conduit again, backup the files in the data directory, then start
conduit. yes, unfortunately it is this janky. if you use zfs or btrfs,
snapshots may work, though i haven't tested it.
## how do i migrate from {synapse, dendrite}?
you can't
:::

69
design.md Normal file
View file

@ -0,0 +1,69 @@
::: header
# design
:::
::: section
## Steps
1. Good design leads to good software. There are three main parts that need to work together:
1. **Technology**: This is the foundation. Bad theory leads to bad design.
2. **Interface**: If the interface is clunky or annoying to use, it won't be used.
3. **Humans**: It needs to complement human tendencies. Don't encourage bad habits.
2. Implement your design. Don't bother with perfection, instead make it only complete enough to be usable.
3. Test your design and look for weak spots. If you find any, do a quick repition of steps 1 and 2. If you think your design is flawed, take a moment to think about it - some parts may be salvageable.
## Tips
1. Build for yourself. Don't worry about what other people think. Some of the best software is designed and used by only one person.
2. Try to be extensible, being able to adapt to any needs.
3. Try to be composable, being able to work together with other stuff.
4. It's better to have the three parts of your design complement each other than have one get all the attention. I've seen flashy interfaces that don't work, incredible ideas that aren't implemented, and cool technology that is unusable.
5. Not everything needs to be implemented. If you have a good idea that doesn't fit, write it down in a "ideas for later" or "sequels" notebook or document.
## Ideas
With that being said, here are some ideas I've had. It's my sequels page,
and feel free to take as many or as little as you want! These have both
random fragments that can be integrated to larger projects, or large
projects on their own. There they are in no particular order:
1. **vote tagging**: Think of this like chat reactions for tagging posts. Instead of the creator or moderators tagging their post, other users do the tagging. A good news post could get many #news reactions.
1. negative tags: Instead of only being able to upvote tags, it's possible to downvote tags.
2. tag pages: You can see the newest, hottest, top, etc tagged posts. Each tag forms its own ad-hoc subreddit-like group which can be subscribed to.
2. **subjective moderation**: Instead of a few moderator actions being canonical for everyone, people can subscribe/unsubscribe from someone's moderation.
1. filters: You could combine block/approve lists into collections of filters. This doesn't need to be for moderation and can also be ie. "show me funny posts" or "show me posts about $topic"
3. **your world of files**: A social media platform where instead of sharing posts, people share files. Kind of like a shared drive.
1. as a blog: People could be authorized to write to their own files in subfolders, ie. have `posts/hello-world/hello.md` and `posts/hello-world/comments/` where people can write comments.
2. as a wiki: Maybe file changes could be tracked, and people could create shared wikis
3. as a repository: This could be used like a git repo, where you have a `code/` folder with `issues/`, `patches/` (prs/mrs), `discussions/` and so forth
4. **logical inbox**: Some kind of software that combines inboxes and notifications between many other platforms into one platform.
1. like rss: Rss is wonderful, but unfortunately not supported everywhere. Something that converts email to rss or gives an http api would be nice, where it could then be added to the inbox.
2. chat segmentation: Take a chat log from {discord, slack, matrix, etc} and split it into topic-based threads for the inbox.
3. all the comments: Find a way to combine comments and their ranking/scores from many different platforms together.
4. semantic deduplication: Sometimes you can get repeats in multiple places. Being able to deduplicate and merge comments, replies, activity into one entry would be incredible.
5. **language model functions**: It would be wonderful to have a server that lets you create "functions" to process and transform text. It could let you finetune t5-base to do whatever you want, and expose and endpoint for "calling" it as a function.
1. model library: Maybe have a registry that people can publish stuff to, ie. "extract recipe json from html" or "summarize text".
2. other models: t5 has an insane payoff/speed ratio, but I get that sometimes you need a decoder-only model for long running interactions.
3. serverless, but actually: The server could let you export (quantized, distilled?) models (maybe in onnx) and let you run them where they need to be.
6. **find everything**: Some way to find everything on your computer.
1. now with semantics: Index the embeddings of media like images, audio, and video instead of only subtitles/ocr
2. custom google: Search the web by crawling specific domains or using an index, maybe from some kind of index repository
3. history is important: A way to do a full text search across all the websites you've visited, maybe combined with "logical inbox" above
7. **rust x typescript**: This would be my ideal scripting language. Rust is great, but needs more work to setup and prototype in. Typescript doesn't have `match` or `enum`. I'm not sure whether borrow checking is good in a scripting language or not, but having some way to check how data moves is great.
1. easy ffi: It should be easy to move from a small script into rust, or rust to the small script.
2. raii: Even if there isn't any borrow checking.
3. targeting wasm: I think webassembly is a perfectly cromulent target.
4. or a minimal runtime: Alternatively, it could be easily embeddable.
8. **language design**: These are a some ideas that could be integrated into programming languages.
1. `fn main(ctx: Context)`: Main takes a context which is the gateway to all io and side effects. 3rd party modules can't access the filesystem unless you explicitly pass `ctx.fs`. Different contexts exist for different platforms.
2. rich stdlib and extlib: The extended library extra useful and well supported stuff that shouldn't be in a minimal stdlib, like sqlite or images
3. tabular tables: A helper around struct-of-arrays. It's meant to be a dataframes replacement, but does have nice things like joins and views into the table. Maybe like C# and linq, but less baked into the language.
4. content addressing: Packages are content addressed, like with ipfs. (see scrapscript?)
5. time management: Dealing with time is hard because you're dealing with a localized format. Stdlib only deals with unix time, with extra libraries to do intl (ie. `Temporal::new().with_timezone(...).with_calendar(...).with_format(...)` which is used for parsing and serialization). You can only do things like "get the day/year" with the extra library.
6. layered cloning: `.clone()` is implicit and automatic, and is a mix of cow/arc/references.
9. **helpful documentation**: I think some projects, like nixos, could benefit from better documentation. But there are also entire areas that need better docs.
1. debugging: How do you debug? How do you use a debugger? A lot of people still resort to print() because debuggers seem too foreign.
2. performance tips: Too many people focus on things like Big O notation, while low hanging fruit with greater effect are untouched. Optimizing memory access and batching/vectorization, for example, are pretty useful to understand.
3. computers in general: This isn't ain't your grandma's book. These are things like staying safe online, using software, and making computers work for you. While I do think things should be improved by design if possible, I also don't people should use fisher-price computers. People are smarter than you think and will read helpful and consise documentation if it exists and is readily available.
4. writing: There's so many holes for educational resources and so many people who could write helpful docs for it, but that won't happen if technical users don't know how to simplify their writing for the noobs.
:::

34
federation.md Normal file
View file

@ -0,0 +1,34 @@
::: header
# federation
:::
::: section
I think federation is overrated. Federation lets instances with different
rules and moderation interoperate with each other. It's difficult to
spam proof and has scaling issues.
A better alternative would be to have oauth2/oidc apis integrated into
the browser and standardized apis. There's already rss for anything
feed-like, but there should be additional apis for reading and managing
items.
I do think federation can have potential with changes. My favorite design
idea is being offline-first with servers existing as dumb relays and
pointers to names. Alternatively, servers aggregate in a state based
protocol (like matrix or bluesky) rather than op based (activitypub),
giving more consistency and reliability.
Of course, the protocols themselves aren't the only part of the
problem. If you want to be successful, there's also ui/ux, culture,
and the network effect. The network effect is hard to overcome, so don't
bother designing something for the world; instead, design something you
and your friends would like and slowly.
By far the biggest issue I've seen is choosing a server, which
interestingly enough isn't a tech problem. People understand how to use
email servers, which are chosen for the domain name and stability. On
the other hand, activitypub users try to tell people to choose servers
based on hobbies or interests, which is confusing since regular people™
have multiple interests or might not want to tie their identity to one
specifically.
:::

8
fetch Normal file
View file

@ -0,0 +1,8 @@
⢸⣿⣷⣶⣦⣤⣀  ZestyLemonade
⢸⣿⣿⣿⣿⣿⣿⣷⣦⡀  -------------
⢀⡀ ⢸⣿⣿⣿⣿⣿⣿⣿⣿⣷⡄  Matrix: @tezlm:celery.eu.org
⢰⣿⣿⣦⣄⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷  Email:  tezlm@celery.eu.org
⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿  Website: https://celery.eu.org
⣹⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠃ 
⣀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠟⠁  
⠙⠛⠿⢿⣿⣿⣿⣿⣿⣿⠿⠟⠋⠁ 

BIN
guhsunsbud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

15
index.html Normal file
View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>celery</title>
<meta charset="utf8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/style.css"></link>
<link rel="stylesheet" href="/assets/index.css"></link>
<script defer src="/assets/index.js"></script>
</head>
<body>
<canvas id="canvas"></canvas>
<div style="font-style: italic; color: #aaa">celery.eu.org is currently undergoing unplanned mainenence</div>
</body>
</html>

16
index2.html Normal file
View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>celery</title>
<meta charset="utf8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/assets/style.css"></link>
<link rel="stylesheet" href="/assets/index.css"></link>
<script defer src="/assets/index2.js"></script>
</head>
<body>
<svg id="main">
<noscript>you are at celery.eu.org</noscript>
</svg>
</body>
</html>

71
index2.js Normal file
View file

@ -0,0 +1,71 @@
const pre = document.getElementById("main");
// the cool spinning circles on index.html
// const ctx = canvas.getContext("2d");
const rnd = (n) => Math.floor(Math.random() * n);
const colors = ["#f0d644", "#63eebe", "#9e4adf"]; // i like neon
const points = [];
let time = 0;
// handle page resizes without ruining everything
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.width = canvas.width;
ctx.height = canvas.height;
}
// math moment
function rotation(point) {
return point.rot + time * point.speed;
}
function length(point) {
return Math.min(time * point.speed, point.speed * 4);
}
function arc(point) {
const angle = rotation(point);
return [angle, angle + length(point)];
}
// initialize the canvas
function init() {
resize();
window.addEventListener("resize", resize);
for (let i = 0; i < 10 + rnd(4); i++) {
points.push({
color: colors[rnd(colors.length)],
radius: Math.random() * 600 + 300,
speed: Math.random() / 10 + 0.1,
rot: Math.random() * 2 * Math.PI,
});
}
}
// the heart and soul of the circles
function anim() {
// center points
const cx = ctx.width / 2;
const cy = ctx.height / 2;
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.globalAlpha = time / 3; // fade in
ctx.lineWidth = 4;
for (let point of points) {
ctx.beginPath();
ctx.strokeStyle = point.color;
ctx.arc(cx, cy, point.radius, ...arc(point));
ctx.stroke();
}
time += 0.01;
setTimeout(anim, 1000 / 60);
}
pre.textContent = "you are at celery.eu.org"
init();
setTimeout(anim, 1000);

31
inochi2d.md Normal file
View file

@ -0,0 +1,31 @@
# inochi2d guide
## prerequisites
- git
- python3 and pip
- a webcam
- openseeface
## building openseeface
```bash
git clone https://github.com/emilianavt/OpenSeeFace
cd OpenSeeFace
pip install onnxruntime opencv-python pillow numpy
python3 facetracker.py -v 4 --fps 60
```
## inochi2d-session
1. [Download the latest release](https://github.com/Inochi2D/inochi-session/releases)
2. Run it
3. Open your `.inp` model (in File > Open)
4. View → Virtual Space → enter a name and hit the plus arrow → select your new zone → set to OpenSeeFace → osf_bind_port = 11573, osf_bind_ip = 127.0.0.1 → save changes → save
5. Drag away the Scene Settings window because all the actually important things are hiding under there
6. Drag Tracking to wherever you like
7. Hit "Refresh"
8. Play around with the settings a little bit until it suits you
You can zoom in by selecting your puppet and c-scroll. Double-click to
hide ui. Set the background in Scene Settings if you like.

52
llm-arch.md Normal file
View file

@ -0,0 +1,52 @@
::: header
# language model architectures
:::
::: section
By now, many people have heard of transformers. And yeah, they're cool,
but there are other architectures that are also worth taking a look at.
## word2vec
While not technically not generative nor a single architecture,
[word2vec](http://jalammar.github.io/illustrated-word2vec/) is the
earliest language models worth talking about. It takes in input text and
creates [embeddings](https://en.wikipedia.org/wiki/Word_embedding),
numerical representations of the words. What makes
embeddings so special is that they capture semantic
meaning. Famously, the input `queen` and `king-man+woman` give
[similar](https://datascience.stackexchange.com/a/45253) embeddings.
Under the hood, it
## rnns
Recurrent neural networks are able to take an input state and input token,
and produce the next best token.
## rnns + lstm
[long short term memory](https://en.wikipedia.org/wiki/Long_short-term_memory)
## transformer (encoder/decoder)
The [transformer](http://jalammar.github.io/illustrated-transformer/) takes input text and transforms it into output text, token by token. Previous models, like [rnns](https://colah.github.io/posts/2015-08-Understanding-LSTMs/) and
## transformer (decoder only)
What if you only want to generate text? Then
you only need the decoder. This is what
[gpt2](https://openai.com/research/better-language-models) uses.
## transformer (encoder only)
What if you only want to embed text? Then you only need the encoder. Only
having embedding is still useful for similarity search, to be able to
compare the embeddings of the query and content.
## rwkv
transformers x rnns
## samba state
a newer model, haven't researched this one yet

138
mac.html Normal file
View file

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html>
<head>
<title>macimas's ui thing</title>
<style>
* {
box-sizing: border-box;
}
body {
padding: 20px;
margin: 0;
background: #151518;
color: #eaeaea;
font-family: sans-serif;
}
#wrapper {
height: 400px;
width: 600px;
background: #2a2c31;
border: solid #5865f2 4px;
border-radius: 16px;
display: grid;
grid-template-areas: "header nav" "main nav";
grid-template-columns: 1fr 64px;
grid-template-rows: 64px 1fr;
overflow: hidden;
}
header {
border-bottom: solid #131416 2px;
grid-area: header;
display: flex;
padding: 8px 16px;
}
header > img {
border-radius: 16px;
}
header > .info {
flex: 1;
margin: auto 8px;
}
header > .menu {
background: #131416;
height: 48px;
width: 48px;
border-radius: 50%;
border: solid #4c4c4e 2px;
}
main > div[data-item="map"] {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 8px;
gap: 4px;
}
main > div[data-item="map"] > .item {
background: #131416;
padding: 8px;
border-radius: 8px;
}
nav {
background: #131416;
grid-area: nav;
display: flex;
flex-direction: column;
gap: 4px;
padding: 8px;
}
nav > .item {
background: #2a2c31;
height: 48px;
width: 48px;
border-radius: 50%;
}
.icon {
height: 12px;
width: 12px;
margin-right: 6px;
display: inline-block;
border-radius: 50%;
background: #aaaaaa;
}
.icon.green {
background: #23a559;
}
.space {
display: inline-block;
width: 12px;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<div id="wrapper">
<header>
<img src="/guhsunsbud.png" />
<div class="info">
<div style="font-weight: bold">guhsunsbud</div>
<div><div class="icon"></div>20 members<div class="space"></div><div class="icon green"></div>10 online</div>
</div>
<div class="menu"></div>
</header>
<main>
<div data-item="info" class="hidden"></div>
<div data-item="map" class="hidden">
<div class="item"><div class="icon"></div> Train Station</div>
<div class="item"><div class="icon"></div> Beach</div>
<div class="item"><div class="icon"></div> House</div>
<div class="item"><div class="icon"></div> House</div>
<div class="item"><div class="icon"></div> House</div>
<div class="item"><div class="icon"></div> House</div>
</div>
<div data-item="members"></div>
<div data-item="chat" class="hidden"></div>
</main>
<nav>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</nav>
</div>
</body>
</html>

3
math.html Normal file
View file

@ -0,0 +1,3 @@
<body>
<p>sqrt(3^2 + 4*2)</p>
</body>

68
matrix.html Normal file
View file

@ -0,0 +1,68 @@
<!DOCTYPE html>
<html>
<head>
<meta name="charset" content="utf8" />
<meta name="initial-device-width" content="1" />
<title>matrix</title>
<style>
body {
background: #f8f8f8;
color: #222222;
max-width: 600px;
margin: 0 auto;
padding: 2em;
font: 1em/1.3 serif;
}
a {
color: #3b74c9;
}
a:hover {
text-decoration: underline wavy;
}
</style>
</head>
<body>
<h1>matrix</h1>
<p><a href="https://matrix.org/">Matrix</a> is a <font color="#c8324e">decentralized</font> <font color="#c732c3">open</font> <font color="#32c767">secure</font> and otherwise (mostly) <font color="#c78d32">bullshit-free</font> <font color="#3282c7">protocol</font> you can use for instant messaging</p>
<h2>what</h2>
<p>Let's break it down a bit, in order of importance:</p>
<ul>
<li>
<p><font color="#3282c7">protocol</font>: matrix is not an app, it's a protocol (much like email or http). You know how can use any web browser to use http, like chrome or <a href="https://www.mozilla.org/en-US/firefox/new/">firefox</a>? Or any email client to use an email server? The same applies here!</p>
<p>You can choose any client, like <a href="https://app.element.io/">element (web, ios, android)</a>, <a href="https://cinny.in/">cinny (web)</a>, <a href="https://fluffychat.im/">fluffychat (ios, android)</a> or any of the <a href="https://matrix.org/ecosystem/clients/">many other clients</a> to use matrix. Anything that can <a href="https://spec.matrix.org/latest/">speak matrix</a> (warning: technical jargon) can interact with the entire ecosystem!</p>
</li>
<li>
<p><font color="#c8324e">decentralized</font>: You can host your own <a href="https://matrix.org/ecosystem/servers/">homeserver</a> (if you're technically inclined), or join an <a href="https://servers.joinmatrix.org/">existing one</a>. There's no one owner of matrix like there is with reddit.com, <s>twitter</s> x.com, or discord.com.</p>
<p>Every homeserver can talk to each other - think of it like email, where a gmail user can email a outlook user. This was how the internet is meant to work, despite companies wanting walled gardens.</p>
</li>
<li><p><font color="#32c767">open</font>: The protocol, along with pretty much all servers and clients, are all open source. Not only that, you can <a href="https://github.com/matrix-org/matrix-spec-proposals/">propose changes</a> to the protocol yourself if you really wanted to. Programmers can develop their own applications on matrix - in a nutshell, 3rd party apps are not only allowed, they're encouraged!</p></li>
<li>
<p><font color="#c732c3">secure (and private)</font>: <a href="https://www.un.org/en/about-us/universal-declaration-of-human-rights#:~:text=No%20one%20shall%20be%20subjected%20to%20arbitrary%20interference%20with%20his%20privacy">Privacy is a human right</a>, so matrix can and does end to encrypt private conversations with strong, auditable encryption. (For nerds: matrix uses <a href="https://gitlab.matrix.org/matrix-org/olm/-/blob/master/docs/olm.md">olm</a>, which is in incarnation of <a href="https://signal.org/">signal</a>'s double-ratchet algorithm).</a>
<p>Some applications such as iMessage are closed source, so when apple touts e2ee you need to take their word for it. Other platforms, like discord, don't have e2ee at all!</p>
<p>Plus, clients have dignity and will ask you before sending telemetry, which is nice considering the sheer number of applications trying to shovel tons of data to their servers without warning.</p>
</li>
<li><p><font color="#c78d32">bullshit-free</font>: All of these points combine into a pretty potent cocktail. There's no ceo that can ruin anything. You can own your own data.</p></li>
</ul>
<h2>why</h2>
<p>In case the overview/philisophical-ish reasons didn't mean much to you, here are more, concrete, reasons</p>
<ul>
<li><b>searching</b> and <b>unread markers</b>: iMessage neither lets you search past messages or jump to the last unread message in 2023?</li>
<li><b>finer permissions</b>: You can control who can do what in each group</li>
<li><b>larger uploads</b>: Most homeservers let you upload files larger than 8mb for free. And you host your own homeserver, you can set the limit arbitrarily high.</li>
<li><b>spaces</b>: <a href="https://element.io/blog/spaces-the-next-frontier/">Spaces</a> are collections of chatrooms and other spaces, where each room can be in multiple spaces. Use them as a folder, or as to create communities. Once they "clicked", I firmly believe this is the best method of organization. (And yes, you can create a space that contains itself if you mess around enough.)</li>
<li><b>invite only rooms</b>: Discord only lets you invite people with invite links. Matrix lets you send people invites directly. (There are other neat things, like aliases, if you have a public room)</li>
<li><b>no phone number requirement</b>: You don't need a phone number to use matrix.</li>
<li><b>no ads</b>: Telegram users will understand.</li>
</ul>
<h2>why not</h2>
<p>Matrix is great, but it's not perfect.</p>
<ul>
<li><b>beta quality clients</b>: a lot of clients (including flagship element) behave a little janky or bad <a href="https://en.wikipedia.org/wiki/Computer_accessibility">a11y</a>. This will be fixed in due time, but for now it won't be entirely smooth.</li>
<li><b>sketchy notification support</b>: notifications behave a bit funkily - they're overengineered yet to rigid to support that many use cases</li>
<li><b>no rbac</b>: permissions exist, but without the granularity <a href="https://support.discord.com/hc/en-us/articles/214836687-Role-Management-101">discord has</a> with roles and overrides. Don't get me wrong though, <a href="https://matrix.org/docs/communities/moderation/">power levels</a> are enough for the vast majority of communities.</li>
<li><b>mediocre multi-user calls</b>: The tl;dr is element currently embeds a different voice call website <a href="https://jitsi.org/">jitsi</a></li>
</ul>
</body>
</html>

301
matrix.md Normal file
View file

@ -0,0 +1,301 @@
::: header
# thoughts on matrix
:::
::: section
I've used matrix for a while now. While the core idea is excellent and
there's so many good ideas, there's so many bad parts and annoyances
with it. Parts of the protocol feel like they were patched together by
someone until they went "eh looks about right", while other parts are
incoherent or give off strong design-by-comittee vibes. I'm going to
keep using matrix, but because of these problems I won't suggest it to
any other people.
This critique looks at matrix from an end user's perspecive as well as
from a more technical perspective and is mostly a thought dump, so it
may be hard to follow.
## threads
Threads are implemented as fancy replies. This makes it easy for people
using clients without threads to accidentally reply to a threaded message
from outside of a thread, causing things to break. It also causes
per-thread typing notifications and read receipts to be chronically
broken. Once you send a message in a thread it's permanently added to
"my threads" with no way of removing it later. There's also pretty much
no qol features, like thread titles/names or being able to archive old
threads. There's no way to lock threads (though this is fairly niche and
to my knowledge would be extremely difficult to implement). On top of all
that, there's no way disable threads in a room. Thread only rooms would
be nice and technically only need special ui, but don't currently exist.
Making threads their own rooms (threads as rooms) would solve some of
these problems, but would cause problems elsewhere. Searching messages
across the main room and threads would be harder to implement. Access
control would need to be synced, and "rogue threads" which don't set
power levels for the parent room's moderators could be created. There's
no way to add other people to threads (ie. in the case of "reply in
thread"). Letting people peek in threads without joining would rely on
features that don't exist currently, like federated peeking as well as
a version of history_visibility for peeking. This could also lead to
amplification: currently, creating a thread is as expensive as sending
a message, wheras each thread as room would need its own set of state
(m.room.create, m.room.member, m.room.join_rules, etc)
(Aside: it looks like having a "main thread/chat" and "threads" are
fundementally incompatible. Most people would like messages would be
properly threaded, but there's an easier to use main thread and ui
encouraging its use. There's a fundemental tension and neither option
is quite correct.)
## push rules
Push rules are how a matrix client and server decides whether a message
sends a push notification, makes a sound, and so forth.
All push rules go in one giant blob in global account data, which I
think some of which should have been split out into per-room account
data. Push rules have seemingly arbitrary groupings: muting
a room goes in the `overrides` group, but receiving notifications for
all messages goes in the `rooms` group.
When changing a lot of room-specific push rules, the rules can overwrite
each other in flight, causing some room-specific push rules to reset/be
dropped. This is technically an issue with all push rules, but most of the
time it isn't noticable to end users. Push rules get around this by having
an entire separate set of apis for changing fine-grained account data.
The rules are written in a json <abbr title="domain specific
language">dsl</abbr>-like thing that is needlessly flexible. This causes
performance issues. Simultaneously, they're somehow extremely rigid. It
is only possible to use one of the 6 predefined conditions and the only
counters that exist are `notify_count` and `highlight_count`. Notably,
there's no `unread_count`. My workaround for now is to patch clients
to not notify unless the highlight tweak is set, and use `notify_count`
as an unread count.
Mentions are currently implemented as searching the message body for a
display name/username, which can cause accidental notifications. Saying
people's names without notifying them needs workarounds like
1337speek. This is slated to be fixed with intentional mentions,
where mentions are extracted to their own json field. Unfortunately,
it looks like encrypted messages will put the mentions in encrypted
content, breaking rules (todo: heard this from somewhere, but need a
source). Ironically, the one time metadata is made less leaky, it also
happens to be the one time where it makes sense and is needed for good ux.
The `/notifications` endpoint paginates through a list of pings/mentions,
though due to the above paragraph won't show any mentions in encrypted
rooms. There's no way to filter mentions per room/space or if it's @room.
Although "list of mentions" makes sense naively, it would be much better
to have an inbox where messages be added and removed.
No client supports marking rooms, threads, or events as unread.
There's no way to temporarily mute rooms (or all notifications). Since a
room can be in multiple spaces, there's no easy way to mute all rooms in
a space. There's no way to only mute @room notifications while allowing
user mentions.
## e2ee
Matrix's implementation of end to end encryption leaks a lot of metadata,
including but not limited to room name/topic/avatar, member per-room
displaynames/avatars, and reactions.
Newly joined members can't view old e2ee messages. This is fixable,
but not yet fixed.
It's also remarkably easy to get undecryptable messages by accident,
and is the **single biggest reason** why I'm not recommending matrix to
anyone else for now. It needs to be more robust and have a better ux.
## apis
Syncing is slow and sends tons of extra data, though sliding sync is
aiming to fix it. No comment will be made on sliding sync, as its apis
are currently in flux. EDIT: Sliding sync is shaping up quite nicely,
but I think there are some mistakes, like `room_name_like` and sorting.
Similarily, the authentication mess is slated to be replaced with OIDC,
so no comment there until it's fleshed out more properly. The current
system isn't terrible, but isn't great either. Getting a seamless ux,
both for users and server admins, looks like it will be pretty difficult
to achieve.
A lot of apis are unergonomic or difficult to use. For example, every
event/message needs to be sent with a random transaction id, which is
annoying when trying to use webhooks. The api doesn't use one event model:
there are events, events without room_id, stripped state events, and
stripped state events with `origin_server_ts`. The application service
api doesn't support e2ee without workarounds *yet*.
The media repository (media repo) lets users store blobs, but it feels
tacked on instead of part of the protocol. Each piece of media is stored
on a single canonicical and trusted server (aka point of failure), unlike
rooms. There is no way to delete uploaded blobs from the media repo.
The apis are trying to be generic while geared towards instant messaging:
`/search` is only indexes blessed keys and even types, which are
different per server. This could be fixed by having a blessed `body`
property that is always indexed, regardless of event type. Events are
able to form graphs but can't be recursively queried. Rooms didn't
have types until relatively recently, and most clients will display
all rooms regardless of type anyway. There also isn't any subtyping
(mutable types, ie. to convert a room between a normal room and dm).
I know instant messaging is the main puropse of matrix,
but for medium-large communities I *really* wish there
was some form of forum system. Something similar to
tildes.net would be ideal, especially the [hierarchical
tagging](https://docs.tildes.net/instructions/hierarchical-tags)
and [comment
labelling](https://docs.tildes.net/instructions/commenting-on-tildes#labelling-comments),
though the extra sorting/filtering is probably too much to ask.
## bots
Bots are hard to get right, as there's no way to use structured commands
(ie. discord and telegram slash commands). Bots need to parse the
message's body. This has problems, since reply fallbacks exist. Parsing
mentions and other things from the body is also difficult, requiring
parsing html.
There's no way to specify interactions, like buttons, menus, canned
responses, preset reactions, etc. Reaction-based uis are the best to
currently exist, but it takes n + 1 events where n is the number of
"buttons".
Matrix seems to be heading towards a widget-based ui system, where
widgets are embedded webpages/webapps. Clients that want to support
widgets would need to embed an entire web browser. Even though it could
be more flexible, it would be much more annoying for bot developers to
learn an entirely separate widget api as well as well as use html/css/js
instead of matrix events and json. Since widgets seem to be able to do
interactions on behalf of the user(?), clients need to take extra care
in implementing sandboxing and access control. Widget ui would also
wouldn't fit in as well with the rest of the client. Widgets might
have issues with privacy and tracking because they can use arbitrary
html/js/css.
Bots can use the full set of html, including tables and
details/summary. However, different clients may only support certain
subsets of html.
## potpourri
Matrix can be generalized as logs of arbitrary json events combined
with a crdt of map<(type, state), event>. Although this could be led
to *so many* use cases, the official client-server api isn't flexible
enough as mentioned above. However, it's entirely possible to use the
core matrix protocol with a custom client-server api + custom client,
activitypub style.
Messages can either be text or a single file, but not both (like a file
with a comment) or multiple attachments.
Clients are missing features or are buggy. A lot of spec is dictated by
synapse and element, even when spec.matrix.org says otherwise. Old and
buggy room versions exist in the wild, with no incentive to upgrade.
Federation is excellent in theory, but in practice servers tend to drop
events.
Power levels are pretty rudimentary. There's no way allow/deny specific
rel_types, only event types. There is no role based access control.
There's no way to peek into dms. (Or federated rooms, for that matter.)
There are many msc (matrix spec change) proposals that seem to have
gotten stuck, like custom emoji/stickers.
Room-specific user displaynames/avatars can be overwritten when the
global displayname/avatar is changed.
Anything added to spec can't be removed later, which is to be expected
for a protocol. But when mscs are opened, events are sent with unstable
identifiers. Clients later will need to support both the official type
and unstable identifier to support past events.
Moderation is lacking, and it's pretty much required to use a bot
([mjolnir](https://github.com/matrix-org/mjolnir)) (not that bad,
but a bit annoying for smaller rooms). When cleaning up spam, a
redaction event must be sent for each message/event - bulk redactions
([msc2244](https://github.com/matrix-org/matrix-spec-proposals/pull/2244))
have been merged but isn't in spec and doesn't seem to be implemented
by any server.
`GET /state` returns the content of a state event, not the full event
itself.
## conclusion
7.8/10 too much water
## wishlist
In no particular order. These requests shouldn't be too difficult
to implement, but would improve usability by *so* much. These aren't
nearly fleshed out to be full mscs.
- Cleanup threads and improve usability
- ~~`DELETE /rooms/{roomId}/threads/{eventId}` to stop participating in
a thread~~
- `PUT /rooms/{roomId}/threads/{eventId}/participation` to change
whether you're participating in or aren't participating in a thread.
- Thread-only rooms.
- Redo power levels
- Base them on `(from_event_type, rel_type, to_event_type)` tuples rather
than `(event_type)` alone.
- Implement rbac (roles). Ideally, it would use explicit deny as the
permission model. May be blocked on "give every member a role" use cases.
- Add a way to make spaces sync subsets of state with the child
rooms. msc3216 and msc2962 exist for power levels, which may be enough
for most use cases
- Add a way to mute rooms temporarily. Maybe add a push rule condition
for this, or better yet redo push rules entirely. (I know the whole
"don't rewrite what works", but seriously...)
- Make aliases and visibility less confusing. There's room visibility,
history visibility, local/published/main alias(es), and the
room directory. In ui, room directory could be merged into room
visibility. I'm not sure how to simplify aliases without reducing
functionality.
- Improve /notifications to be more like a proper inbox
- Use intentional mentions (even in encrypeted rooms) to populate the list
- `DELETE /notifications` + `DELETE /notifications/{eventId}` along
with automatically removing old notifications to enhance usability
- `PUT /notifications/{eventId}` to bookmark an event for later (though,
this may be better served with "starred/bookmarked messages")
- Some way to reorder notifications? Maybe the `PUT` endpoint could
take an "order" key.
- Add a `m.preset_reactions` or `m.interactions` key for bots.
- Bot supplied edits or annotations?
- `unread_count` to view the number of unread messages in a room, see msc2654
- This might only be something I want, but another presence/status type
different from online for when you're explicitly available to talk to
woul be nice. I really want to be able to have a clear split between
"being on the internet" and "willing to have my attention taken"
<!--
## the far future?
Some random ideas on how matrix could look in the far future...
Memberships could be made ephemeral. A user's membership could be
`allow` (invite, join) or `deny` (kick, leave, ban). In private rooms,
the default membership would be `deny` and in public rooms it would
be `allow`. When a member's membership is explicitly set to `allow`,
they are invited to the room. A member can send a special ephemeral
(or timeline) event to tell other servers they have acknowledged the
membership change and are now joined. Of course in practice, more
memberships/states would need to be added, like `null`/`default` or
`knock`. The main problem would be making restricted rooms work.
No matter how many apis you try to add, some use case will need something
special. I wonder how feasable it would be to use wasm instead of
room versions for permissions, custom sorting/filtering/indexing,
and deriving custom unsigned/state. It could even do state resolution,
although this is extremely difficult, may have security issues, and is
probably impractical. The main problem is wasm would need to be embedded
in the event or be placed in the media repo.
-->
:::

13
meta.html Normal file
View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<title>ayo</title>
<meta charset="utf8">
<meta content="metatesting" property="og:site_name" />
<meta content="title4" property="og:title" />
<meta content="description4" property="og:description" />
<meta content="image" property="og:type" />
<meta content="https://celery.eu.org/media/ketchup.jpg" property="og:image" />
</head>
</html>

29
mindus.html Normal file
View file

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<title>ayo</title>
<meta charset="utf8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<h1>hello</h1>
<pre id="output"></pre>
<form id="form"><input id="input" /></form>
<script>
const form = document.getElementById("form");
const input = document.getElementById("input");
const output = document.getElementById("output");
const ws = new WebSocket(`wss://${location.host}/mindus/live`);
ws.onmessage = ({ data }) => output.innerText += data + "\n";
form.addEventListener("submit", (e) => {
e.preventDefault();
output.innerText += `=> ${input.value}\n`;
ws.send(input.value + "\n");
input.value = "";
});
</script>
</body>
</html>

18
ml.html Normal file
View file

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8" />
<title>machine learning</title>
<link rel="stylesheet" href="/assets/style2.css" />
</head>
<body>
<header>
<h1>machine learning</h1>
</header>
<section>
<p>
todo: write stuff here. start with gradiant descent, then perceptrons, networks, rnns, transformers
</p>
</section>
</body>
</html>

34
nix.html Normal file
View file

@ -0,0 +1,34 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf8" />
<title>nix</title>
<link rel="stylesheet" href="/assets/style2.css" />
</head>
<body>
<header>
<h1>nix</h1>
</header>
<section>
<h2>the language</h2>
<p>Nix is a language. It has numbers. You can add them.</p>
<pre><code><span class="num">1</span> <span class="op">+</span> <span class="num">2</span></code></pre>
<div class="eval">= 3</div>
<p>The above expression evaluates to <code><span class="num">3</span></code>. If you have nix installed, try running <code>nix repl</code> and pasting that in.</p>
<pre><code><span class="str">"hello nix!"</span></code></pre>
<div class="eval">= "hello nix!"</div>
<p>Here you can see a string.</p>
<pre><code><span class="str">"escapes\nand\nnewlines"</span> <span class="op">==</span> <span class="str">"escapes
and
newlines"</span></code></pre>
<div class="eval">= true</div>
<p>Nix has booleans.</p>
<pre><code><span class="op">!(</span><span class="key">true</span> <span class="op">&&</span> <span class="key">false</span><span class="op">) || </span><span class="key">false</span></code></pre>
<div class="eval">= true</div>
<p>Nix has sets, key value pairs known as records, maps, or objects in other lanugages. They can be nested.</p>
<pre><code><span class="op">{ </span><span class="id">foo</span> <span class="op">=</span> <span class="num">123</span><span class="op">; }.</span><span class="id">foo</span></code></pre>
<div class="eval">= 123</div>
</section>
</body>
</html>

233
nix.md Normal file
View file

@ -0,0 +1,233 @@
::: header
# nix
:::
::: section
## nix, the language
Nix is a language. It has numbers. You can add them.
```nix
1 + 2
```
<div class="eval">= 3</div>
The above expression evaluates to `3`. If you have nix installed, try
running `nix repl` and pasting that in. Nix also has strings.
```nix
"hello nix!"
```
<div class="eval">= "hello nix!"</div>
```nix
"escapes\nand\nnewlines" == "escapes
and
newlines"
```
<div class="eval">= true</div>
Nix has booleans.
```nix
!(true && false) || false
```
<div class="eval">= true</div>
Nix has sets, or key value pairs. These are known as records, maps,
or objects in other lanugages.
```nix
{ foo = 123; }.foo
```
<div class="eval">= 123</div>
Sets can be nested.
```nix
# There isn't any hard rule on which style to use
{ foo = { bar = "baz"; }; } == { foo.bar = "baz"; }
```
<div class="eval">= true</div>
The `let` and `in` keyword defines a variable for a given scope.
```nix
let
foo = 3;
bar = foo * 3;
in
bar
```
<div class="eval">= 9</div>
Nix has pure functions that transform inputs to outputs without side
effects.
```nix
let
incr = n: n + 1;
in
incr 5
```
<div class="eval">= 6</div>
To use multiple parameters, either pass a set or use currying (create
a function that returns another function).
```nix
let
addSet = input: input.a + input.b;
addDestructure = { a, b }: a + b;
addCurry = a: b: a + b;
in {
foo = addSet { a = 10; b = 20; };
bar = addDestructure { a = 10; b = 20; };
baz = addCurry 30 40;
}
```
<div class="eval">= { bar = 30; baz = 70; foo = 30; }</div>
Destructuring optional fields.
```nix
let
# this will use b = 5 if b is not defined
addOptional = { a, b ? 5 }: a + b;
in {
foo = addOptional { a = 1; };
bar = addOptional { a = 1; b = 1; };
}
```
<div class="eval">= { bar = 2; foo = 6; }</div>
The `inherit` keyword.
```nix
let
key1 = "something here";
key2 = "something else";
in {
inherit key1 key2;
}
```
<div class="eval">= { key1 = "something here"; key2 = "something else"; }</div>
Nix provides many builtin functions in the `builtins` set. If you're
using the repl, press <kbd>tab</kbd> to get a list of them.
```nix
{
system = builtins.currentSystem;
}
```
<div class="eval">= { system = "x86_64-linux"; }</div>
Finally, nix has a path type. When
```nix
{
sourceCode = ./path/to/sources;
}
```
<div class="eval">= { system = "x86_64-linux"; }</div>
:::
::: section
## nix, the build tool
Nix provides a builtin function to create *derivations*. These are special
descriptions of how to derive build outputs from source code. Build
outputs can be anything, such as binaries, shared libraries, or a
docker tarball.
```nix
derivation {
name = "foobar";
# here is where you'd
# src = ./path/to/source
# the $out variable has the location of where the build outputs should go
# the build outputs can be a file or a folder of any structure
# the $src variable has the location of the sources
builder = "/bin/sh";
args = ["-c" "echo 'Hello, derivation!' > $out"];
system = builtins.currentSystem;
}
```
<div class="eval">= derivation «/nix/store/ha5hof1nput-foobar.drv»</div>
To build this, use `:b (copy-pasted code)` in the repl. It should print
a path to the build outputs.
[NixOS/nixpkgs](https://github.com/NixOS/nixpkgs) is a combination package
repository and standard library, containing thousands of derivations and
functions. Using the `derivation` function is almost always unnecessary,
since nixpkgs probably has a helper for whatever language or build system
you want to use. Even if you need to manually make a derivation, there is
`mkDerivation` which is a bit higher level than `derivation`.
[Nix flakes](https://nixos.wiki/wiki/Flakes) are how derivations and
packages are managed, and is what you probably want to be using.
You've probably heard it before, but it's worth repeating: although
more difficult to set up, using nix over other build systems gives you
reproducability. This means that the same nix expression and source code
will *always* produce the same outputs. If it works on one nix user's
machine, it will work every nix user's machine. If a build fails, it
fails for everyone.
Flakes work by taking in an explicit set of inputs along with the build
steps. Anything that isn't explicitly defined as an input, whether
it's binaries, paths, or environment variables, is not given to the
derivation's builder.
Here's an example flake:
```nix
{
description = "any useful description here";
inputs = {
# this is a flake identifier
nixpkgs.url = "github:NixOS/nixpkgs";
};
outputs = { self, nixpkgs }: {
packages.x86_64-linux.default = inputs.nixpkgs.legacyPackages.x86_64-linux.hello;
};
}
```
This code should be put inside `flake.nix` at the root of a git
repository. Running `nix flake new hello-world` would create a directory
called `hello-world` pre-initialized with a flake like this. From there,
run `nix build` to build (the binary will be in `result/bin/hello`), or
`nix run` to build and run the binary.
Maybe you've noticed already, but the flake isn't really building anything
new - it's exporting an already made derivation from nixpkgs. Here is
another flake:
```nix
{
description = "any useful description here";
inputs.nixpkgs.url = "github:NixOS/nixpkgs";
outputs = { self, nixpkgs }: let
pkgs = import nixpkgs { system = "x86_64-linux"; };
in {
packages.x86_64-linux.default = pkgs.stdenv.mkDerivation {
name = "hello";
src = self;
buildPhase = "echo '#!/bin/sh\necho hello world' > bin; chmod +x bin";
installPhase = "mkdir -p $out/bin; mv bin $out/bin/hello";
};
};
}
```
:::
<div style="min-height:500px"></div>

25
no.html Normal file
View file

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html>
<head>
<title>ayo</title>
<meta charset="utf8">
<meta content="no." property="og:title" />
<meta content="no." property="og:description" />
<meta content="https://i.redd.it/o0gjdu4ivlx51.jpg" property="og:image" />
<meta content="#ff0000" data-react-helmet="true" name="theme-color" />
<link rel="stylesheet" href="/assets/style.css"></link>
</head>
<body>
<h1>no.</h1>
<ul>
<li>no</li>
<li>no.</li>
<li><a href="https://en.uncyclopedia.co/wiki/Nooooooooooooooooooo!">no</a></li>
<li><a href="https://www.reddit.com/r/no/top/?t=all">no</a></li>
<li>No</li>
<li><a href="https://www.merriam-webster.com/dictionary/no">no</a></li>
<li>no!</li>
</ul>
</body>
</html>

15
pnpm-lock.yaml Normal file
View file

@ -0,0 +1,15 @@
lockfileVersion: 5.3
specifiers:
xterm-addon-fit: ^0.5.0
dependencies:
xterm-addon-fit: 0.5.0
packages:
/xterm-addon-fit/0.5.0:
resolution: {integrity: sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==}
peerDependencies:
xterm: ^4.0.0
dev: false

8
public/FFFB-dendrite.md Normal file
View file

@ -0,0 +1,8 @@
# dendrite
I've been running Dendrite for over a week now, and there are signifigant performance improvements.
If I knew how Dendrite currently was, though, I probably wouldn't switch yet. It's currently missing a few features.
For now, it works. Hopefully it will get better over time.

4
public/FFFC-synapse.md Normal file
View file

@ -0,0 +1,4 @@
# synapse
synapse is a literal resource management game on a small vps change my mind

22
public/FFFD-todo.md Normal file
View file

@ -0,0 +1,22 @@
# todo list
## done
- get a server
- get a domain
- get a ssl certificate
- make a file server
- make a [server stats](/stats) page
- set up synapse
- set up [cinny](/cinny/)
## todo
- move to dendrite, when it works
- set up a git server
- file uploading
- gemini capsule
- improve stats page
- get my own domain? (current one from [sky](https://skybldev.eu.org), but it will be hard to switch because of the matrix server)
- temporary pastebin

16
public/FFFE-symbols.md Normal file
View file

@ -0,0 +1,16 @@
# symbols
for copying and pasting
- `°` degrees
- `™` tm
- `½` half
- `¼` quarter
- `²` square
- `³` cube
- `√` sqrt
- `‰` perthousanth
- `§` section
- `¶` paragraph
- `•` bullet point

4
public/FFFF-first.md Normal file
View file

@ -0,0 +1,4 @@
# first page
the first page on my site!

BIN
public/altdrag.zip Normal file

Binary file not shown.

BIN
public/amine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

177
public/blender-violet.xml Normal file
View file

@ -0,0 +1,177 @@
<!-- stolen from https://github.com/kame404/Blender-Themes/ -->
<bpy>
<Theme>
<user_interface>
<ThemeUserInterface
>
<wcol_regular>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_regular>
<wcol_tool>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_tool>
<wcol_toolbar_item>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_toolbar_item>
<wcol_radio>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_radio>
<wcol_text>
<ThemeWidgetColors
item="#9333eaff"
>
</ThemeWidgetColors>
</wcol_text>
<wcol_option>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_option>
<wcol_toggle>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_toggle>
<wcol_num>
<ThemeWidgetColors
item="#9333eaff"
>
</ThemeWidgetColors>
</wcol_num>
<wcol_numslider>
<ThemeWidgetColors
item="#9333eaff"
>
</ThemeWidgetColors>
</wcol_numslider>
<wcol_menu>
<ThemeWidgetColors
inner_sel="#9333eab3"
>
</ThemeWidgetColors>
</wcol_menu>
<wcol_pulldown>
<ThemeWidgetColors
inner_sel="#9333eab3"
>
</ThemeWidgetColors>
</wcol_pulldown>
<wcol_menu_back>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_menu_back>
<wcol_pie_menu>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_pie_menu>
<wcol_tooltip>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_tooltip>
<wcol_menu_item>
<ThemeWidgetColors
inner_sel="#9333eaff"
>
</ThemeWidgetColors>
</wcol_menu_item>
<wcol_progress>
<ThemeWidgetColors
inner_sel="#9333eaff"
item="#9333eaff"
>
</ThemeWidgetColors>
</wcol_progress>
<wcol_list_item>
<ThemeWidgetColors
item="#9333eaff"
>
</ThemeWidgetColors>
</wcol_list_item>
</ThemeUserInterface>
</user_interface>
<view_3d>
<ThemeView3D
frame_current="#9333ea"
>
</ThemeView3D>
</view_3d>
<graph_editor>
<ThemeGraphEditor
frame_current="#9333ea"
>
</ThemeGraphEditor>
</graph_editor>
<file_browser>
<ThemeFileBrowser
selected_file="#9333ea"
>
</ThemeFileBrowser>
</file_browser>
<nla_editor>
<ThemeNLAEditor
frame_current="#9333ea"
>
</ThemeNLAEditor>
</nla_editor>
<dopesheet_editor>
<ThemeDopeSheet
frame_current="#9333ea"
>
</ThemeDopeSheet>
</dopesheet_editor>
<image_editor>
<ThemeImageEditor
frame_current="#9333ea"
>
</ThemeImageEditor>
</image_editor>
<sequence_editor>
<ThemeSequenceEditor
frame_current="#9333ea"
>
</ThemeSequenceEditor>
</sequence_editor>
<properties>
<ThemeProperties
match="#9333ea"
active_modifier="#9333eaff"
>
</ThemeProperties>
</properties>
<outliner>
<ThemeOutliner
selected_highlight="#3b145e"
active="#581f8c"
>
</ThemeOutliner>
</outliner>
<clip_editor>
<ThemeClipEditor
frame_current="#9333ea"
>
</ThemeClipEditor>
</clip_editor>
</Theme>
<ThemeStyle>
</ThemeStyle>
</bpy>

BIN
public/corpus.txt.bz2 Normal file

Binary file not shown.

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>dog search</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="style.css" />
<script src="script.js" defer></script>
</head>
<body>
<h1>dog search</h1>
<main>
<h2 id="count"></h2>
<pre id="grid"></pre>
</main>
</body>
</html>

View file

@ -0,0 +1,50 @@
const rnd = (arr) => arr[Math.floor(Math.random() * arr.length)];
const grid = [];
const size = 1000;
let count = 0;
for (let i = 0; i < size; i++) {
grid.push("");
for (let j = 0; j < size; j++) {
grid[i] += rnd(["d", "o", "g"]);
if (check(i, j)) count++;
}
}
document.getElementById("grid").innerText = grid.join("\n");
document.getElementById("count").innerText = "There are " + count + " dogs";
function check(i, j) {
switch (grid[i][j]) {
case "d":
if (!grid[i - 1]) break;
if (grid[i - 1] == "d") break;
if (grid[i - 2]) {
if (grid[i - 1][j] == "o" && grid[i - 2][j] == "g") return true;
if (grid[i - 1][j - 1] == "o" && grid[i - 2][j - 2] == "g")
return true;
if (grid[i - 1][j + 1] == "o" && grid[i - 2][j + 2] == "g")
return true;
}
if (grid[i][j + 1] == "o" && grid[i][j + 2] == "g") return true;
if (grid[i][j - 1] == "o" && grid[i][j - 2] == "g") return true;
break;
case "g":
if (!grid[i - 1]) break;
if (grid[i - 1][j] == "g") break;
if (grid[i - 2]) {
if (grid[i - 1][j] == "o" && grid[i - 2][j] == "d") return true;
if (grid[i - 1][j - 1] == "o" && grid[i - 2][j - 2] == "d")
return true;
if (grid[i - 1][j + 1] == "o" && grid[i - 2][j + 2] == "d")
return true;
}
if (grid[i][j + 1] == "o" && grid[i][j + 2] == "d") return true;
if (grid[i][j - 1] == "o" && grid[i][j - 2] == "d") return true;
break;
default:
break;
}
return false;
}

View file

@ -0,0 +1,10 @@
body {
font-family: helvetica, arial, sans-serif;
margin: 2em;
}
pre {
padding: 1em;
display: block;
}

View file

@ -0,0 +1,14 @@
colors:
primary:
background: '#1A1D2B'
key_bindings:
- { key: "N", mods: "control|shift", action: SpawnNewInstance }
font:
normal:
family: Iosevka Zesty
size: 8
window:
opacity: 0.9

1
public/dots/.config/bspwm Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/bspwm

1
public/dots/.config/helix Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/helix/

1
public/dots/.config/nvim Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/nvim

1
public/dots/.config/polybar Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/polybar

1
public/dots/.config/rofi Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/rofi

1
public/dots/.config/sxhkd Symbolic link
View file

@ -0,0 +1 @@
/home/zestylemonade/.config/sxhkd

View file

@ -0,0 +1 @@
/home/zestylemonade/.config/touchegg

267
public/dots/.z.sh Normal file
View file

@ -0,0 +1,267 @@
# Copyright (c) 2009 rupa deadwyler. Licensed under the WTFPL license, Version 2
# maintains a jump-list of the directories you actually use
#
# INSTALL:
# * put something like this in your .bashrc/.zshrc:
# . /path/to/z.sh
# * cd around for a while to build up the db
# * PROFIT!!
# * optionally:
# set $_Z_CMD in .bashrc/.zshrc to change the command (default z).
# set $_Z_DATA in .bashrc/.zshrc to change the datafile (default ~/.z).
# set $_Z_MAX_SCORE lower to age entries out faster (default 9000).
# set $_Z_NO_RESOLVE_SYMLINKS to prevent symlink resolution.
# set $_Z_NO_PROMPT_COMMAND if you're handling PROMPT_COMMAND yourself.
# set $_Z_EXCLUDE_DIRS to an array of directories to exclude.
# set $_Z_OWNER to your username if you want use z while sudo with $HOME kept
#
# USE:
# * z foo # cd to most frecent dir matching foo
# * z foo bar # cd to most frecent dir matching foo and bar
# * z -r foo # cd to highest ranked dir matching foo
# * z -t foo # cd to most recently accessed dir matching foo
# * z -l foo # list matches instead of cd
# * z -e foo # echo the best match, don't cd
# * z -c foo # restrict matches to subdirs of $PWD
# * z -x # remove the current directory from the datafile
# * z -h # show a brief help message
[ -d "${_Z_DATA:-$HOME/.z}" ] && {
echo "ERROR: z.sh's datafile (${_Z_DATA:-$HOME/.z}) is a directory."
}
_z() {
local datafile="${_Z_DATA:-$HOME/.z}"
# if symlink, dereference
[ -h "$datafile" ] && datafile=$(readlink "$datafile")
# bail if we don't own ~/.z and $_Z_OWNER not set
[ -z "$_Z_OWNER" -a -f "$datafile" -a ! -O "$datafile" ] && return
_z_dirs () {
[ -f "$datafile" ] || return
local line
while read line; do
# only count directories
[ -d "${line%%\|*}" ] && echo "$line"
done < "$datafile"
return 0
}
# add entries
if [ "$1" = "--add" ]; then
shift
# $HOME and / aren't worth matching
[ "$*" = "$HOME" -o "$*" = '/' ] && return
# don't track excluded directory trees
if [ ${#_Z_EXCLUDE_DIRS[@]} -gt 0 ]; then
local exclude
for exclude in "${_Z_EXCLUDE_DIRS[@]}"; do
case "$*" in "$exclude"*) return;; esac
done
fi
# maintain the data file
local tempfile="$datafile.$RANDOM"
local score=${_Z_MAX_SCORE:-9000}
_z_dirs | awk -v path="$*" -v now="$(date +%s)" -v score=$score -F"|" '
BEGIN {
rank[path] = 1
time[path] = now
}
$2 >= 1 {
# drop ranks below 1
if( $1 == path ) {
rank[$1] = $2 + 1
time[$1] = now
} else {
rank[$1] = $2
time[$1] = $3
}
count += $2
}
END {
if( count > score ) {
# aging
for( x in rank ) print x "|" 0.99*rank[x] "|" time[x]
} else for( x in rank ) print x "|" rank[x] "|" time[x]
}
' 2>/dev/null >| "$tempfile"
# do our best to avoid clobbering the datafile in a race condition.
if [ $? -ne 0 -a -f "$datafile" ]; then
env rm -f "$tempfile"
else
[ "$_Z_OWNER" ] && chown $_Z_OWNER:"$(id -ng $_Z_OWNER)" "$tempfile"
env mv -f "$tempfile" "$datafile" || env rm -f "$tempfile"
fi
# tab completion
elif [ "$1" = "--complete" -a -s "$datafile" ]; then
_z_dirs | awk -v q="$2" -F"|" '
BEGIN {
q = substr(q, 3)
if( q == tolower(q) ) imatch = 1
gsub(/ /, ".*", q)
}
{
if( imatch ) {
if( tolower($1) ~ q ) print $1
} else if( $1 ~ q ) print $1
}
' 2>/dev/null
else
# list/go
local echo fnd last list opt typ
while [ "$1" ]; do case "$1" in
--) while [ "$1" ]; do shift; fnd="$fnd${fnd:+ }$1";done;;
-*) opt=${1:1}; while [ "$opt" ]; do case ${opt:0:1} in
c) fnd="^$PWD $fnd";;
e) echo=1;;
h) echo "${_Z_CMD:-z} [-cehlrtx] args" >&2; return;;
l) list=1;;
r) typ="rank";;
t) typ="recent";;
x) sed -i -e "\:^${PWD}|.*:d" "$datafile";;
esac; opt=${opt:1}; done;;
*) fnd="$fnd${fnd:+ }$1";;
esac; last=$1; [ "$#" -gt 0 ] && shift; done
[ "$fnd" -a "$fnd" != "^$PWD " ] || list=1
# if we hit enter on a completion just go there
case "$last" in
# completions will always start with /
/*) [ -z "$list" -a -d "$last" ] && builtin cd "$last" && return;;
esac
# no file yet
[ -f "$datafile" ] || return
local cd
cd="$( < <( _z_dirs ) awk -v t="$(date +%s)" -v list="$list" -v typ="$typ" -v q="$fnd" -F"|" '
function frecent(rank, time) {
# relate frequency and time
dx = t - time
return int(10000 * rank * (3.75/((0.0001 * dx + 1) + 0.25)))
}
function output(matches, best_match, common) {
# list or return the desired directory
if( list ) {
if( common ) {
printf "%-10s %s\n", "common:", common > "/dev/stderr"
}
cmd = "sort -n >&2"
for( x in matches ) {
if( matches[x] ) {
printf "%-10s %s\n", matches[x], x | cmd
}
}
} else {
if( common && !typ ) best_match = common
print best_match
}
}
function common(matches) {
# find the common root of a list of matches, if it exists
for( x in matches ) {
if( matches[x] && (!short || length(x) < length(short)) ) {
short = x
}
}
if( short == "/" ) return
for( x in matches ) if( matches[x] && index(x, short) != 1 ) {
return
}
return short
}
BEGIN {
gsub(" ", ".*", q)
hi_rank = ihi_rank = -9999999999
}
{
if( typ == "rank" ) {
rank = $2
} else if( typ == "recent" ) {
rank = $3 - t
} else rank = frecent($2, $3)
if( $1 ~ q ) {
matches[$1] = rank
} else if( tolower($1) ~ tolower(q) ) imatches[$1] = rank
if( matches[$1] && matches[$1] > hi_rank ) {
best_match = $1
hi_rank = matches[$1]
} else if( imatches[$1] && imatches[$1] > ihi_rank ) {
ibest_match = $1
ihi_rank = imatches[$1]
}
}
END {
# prefer case sensitive
if( best_match ) {
output(matches, best_match, common(matches))
exit
} else if( ibest_match ) {
output(imatches, ibest_match, common(imatches))
exit
}
exit(1)
}
')"
if [ "$?" -eq 0 ]; then
if [ "$cd" ]; then
if [ "$echo" ]; then echo "$cd"; else builtin cd "$cd"; fi
fi
else
return $?
fi
fi
}
alias ${_Z_CMD:-z}='_z 2>&1'
[ "$_Z_NO_RESOLVE_SYMLINKS" ] || _Z_RESOLVE_SYMLINKS="-P"
if type compctl >/dev/null 2>&1; then
# zsh
[ "$_Z_NO_PROMPT_COMMAND" ] || {
# populate directory list, avoid clobbering any other precmds.
if [ "$_Z_NO_RESOLVE_SYMLINKS" ]; then
_z_precmd() {
(_z --add "${PWD:a}" &)
: $RANDOM
}
else
_z_precmd() {
(_z --add "${PWD:A}" &)
: $RANDOM
}
fi
[[ -n "${precmd_functions[(r)_z_precmd]}" ]] || {
precmd_functions[$(($#precmd_functions+1))]=_z_precmd
}
}
_z_zsh_tab_completion() {
# tab completion
local compl
read -l compl
reply=(${(f)"$(_z --complete "$compl")"})
}
compctl -U -K _z_zsh_tab_completion _z
elif type complete >/dev/null 2>&1; then
# bash
# tab completion
complete -o filenames -C '_z --complete "$COMP_LINE"' ${_Z_CMD:-z}
[ "$_Z_NO_PROMPT_COMMAND" ] || {
# populate directory list. avoid clobbering other PROMPT_COMMANDs.
grep "_z --add" <<< "$PROMPT_COMMAND" >/dev/null || {
PROMPT_COMMAND="$PROMPT_COMMAND"$'\n''(_z --add "$(command pwd '$_Z_RESOLVE_SYMLINKS' 2>/dev/null)" 2>/dev/null &);'
}
}
fi

34
public/dots/.zshrc Normal file
View file

@ -0,0 +1,34 @@
# history
HISTFILE=~/.histfile
HISTSIZE=1000
SAVEHIST=1000
setopt histignoredups histignorespace incappendhistory
# completion
zstyle ':completion:*' completer _complete _ignored
zstyle ':completion:*' matcher-list '' 'r:|[._-/]=* r:|=*'
zstyle :compinstall filename '/home/zestylemonade/.zshrc'
autoload -Uz compinit && compinit
# aliases
alias ls="lsd --color=auto --icon=never"
alias ll="ls -lh"
alias cat="bat"
alias vim="vim -p"
alias ..="cd .."
# exports
export EDITOR="nvim"
export GOPATH="$HOME/.go"
export PATH="$PATH:$HOME/.local/bin:$GOPATH/bin"
# misc
. ~/.z.sh
bindkey -e
unset _Z_RESOLVE_SYMLINKS
export _Z_NO_RESOLVE_SYMLINKS=1
# sugar
echo -e "\e[90mlogged in as \e[36m`whoami`\e[0m@\e[34m`hostname`\e[90m!\e[0m"
export PS1='%(!.%1F.%8F)%~%f%(0?.. %1F[%B%?%b]%f)%(!.#.>) '

270
public/dots/nnn.h Normal file
View file

@ -0,0 +1,270 @@
/*
* BSD 2-Clause License
*
* Copyright (C) 2014-2016, Lazaros Koromilas <lostd@2f30.org>
* Copyright (C) 2014-2016, Dimitris Papastamos <sin@2f30.org>
* Copyright (C) 2016-2022, Arun Prakash Jana <engineerarun@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <curses.h>
#define CONTROL(c) ((c) & 0x1f)
#ifndef ESC
#define ESC (27)
#endif
#ifndef DEL
#define DEL (127)
#endif
/* Supported actions */
enum action {
SEL_BACK = 1,
SEL_OPEN,
SEL_NAV_IN,
SEL_NEXT,
SEL_PREV,
SEL_PGDN,
SEL_PGUP,
SEL_CTRL_D,
SEL_CTRL_U,
SEL_HOME,
SEL_END,
SEL_FIRST,
SEL_CDHOME,
SEL_CDBEGIN,
SEL_CDLAST,
SEL_CDROOT,
SEL_BMOPEN,
SEL_REMOTE,
SEL_CYCLE,
SEL_CYCLER,
SEL_CTX1,
SEL_CTX2,
SEL_CTX3,
SEL_CTX4,
#ifdef CTX8
SEL_CTX5,
SEL_CTX6,
SEL_CTX7,
SEL_CTX8,
#endif
SEL_MARK,
SEL_BMARK,
SEL_FLTR,
SEL_MFLTR,
SEL_HIDDEN,
SEL_DETAIL,
SEL_STATS,
SEL_CHMODX,
SEL_ARCHIVE,
SEL_SORT,
SEL_REDRAW,
SEL_SEL,
SEL_SELMUL,
SEL_SELALL,
SEL_SELINV,
SEL_SELEDIT,
SEL_CP,
SEL_MV,
SEL_CPMVAS,
SEL_RM,
SEL_OPENWITH,
SEL_NEW,
SEL_RENAME,
SEL_RENAMEMUL,
SEL_UMOUNT,
SEL_HELP,
SEL_AUTONEXT,
SEL_EDIT,
SEL_PLUGIN,
SEL_SHELL,
SEL_LAUNCH,
SEL_PROMPT,
SEL_LOCK,
SEL_SESSIONS,
SEL_EXPORT,
SEL_TIMETYPE,
SEL_QUITCTX,
SEL_QUITCD,
SEL_QUIT,
SEL_QUITERR,
#ifndef NOMOUSE
SEL_CLICK,
#endif
};
/* Associate a pressed key to an action */
struct key {
int sym; /* Key pressed */
enum action act; /* Action */
};
static struct key bindings[] = {
/* Back */
{ KEY_LEFT, SEL_BACK },
{ 'n', SEL_BACK },
/* Inside or select */
{ KEY_ENTER, SEL_OPEN },
{ '\r', SEL_OPEN },
/* Pure navigate inside */
{ KEY_RIGHT, SEL_NAV_IN },
{ 'i', SEL_NAV_IN },
/* Next */
{ 'e', SEL_NEXT },
{ KEY_DOWN, SEL_NEXT },
/* Previous */
{ 'u', SEL_PREV },
{ KEY_UP, SEL_PREV },
/* Page down */
{ KEY_NPAGE, SEL_PGDN },
/* Page up */
{ KEY_PPAGE, SEL_PGUP },
/* Ctrl+D */
{ 'E', SEL_CTRL_D },
/* Ctrl+U */
{ 'U', SEL_CTRL_U },
/* First entry */
{ KEY_HOME, SEL_HOME },
{ 'g', SEL_HOME },
/* Last entry */
{ KEY_END, SEL_END },
{ 'G', SEL_END },
/* Go to first file */
{ '\'', SEL_FIRST },
/* HOME */
{ '~', SEL_CDHOME },
/* Initial directory */
{ '@', SEL_CDBEGIN },
/* Last visited dir */
{ '-', SEL_CDLAST },
/* Go to / */
{ '`', SEL_CDROOT },
/* Leader key */
{ '_', SEL_BMOPEN },
/* Connect to server over SSHFS */
{ 'c', SEL_REMOTE },
/* Cycle contexts in forward direction */
{ '\t', SEL_CYCLE },
/* Cycle contexts in reverse direction */
{ KEY_BTAB, SEL_CYCLER },
/* Go to/create context N */
{ '1', SEL_CTX1 },
{ '2', SEL_CTX2 },
{ '3', SEL_CTX3 },
{ '4', SEL_CTX4 },
#ifdef CTX8
{ '5', SEL_CTX5 },
{ '6', SEL_CTX6 },
{ '7', SEL_CTX7 },
{ '8', SEL_CTX8 },
#endif
/* Mark a path to visit later */
{ ',', SEL_MARK },
/* Create a bookmark */
{ 'b', SEL_BMARK },
/* Filter */
{ '/', SEL_FLTR },
/* Toggle filter mode */
{ CONTROL('N'), SEL_MFLTR },
/* Toggle hide .dot files */
{ '.', SEL_HIDDEN },
/* Detailed listing */
{ 'd', SEL_DETAIL },
/* File details */
{ 'f', SEL_STATS },
{ CONTROL('F'), SEL_STATS },
/* Toggle executable status */
{ '*', SEL_CHMODX },
/* Create archive */
{ 'z', SEL_ARCHIVE },
/* Sort toggles */
{ 't', SEL_SORT },
{ CONTROL('T'), SEL_SORT },
/* Redraw window */
{ CONTROL('L'), SEL_REDRAW },
/* Select current file path */
{ CONTROL('J'), SEL_SEL },
{ ' ', SEL_SEL },
/* Toggle select multiple files */
{ 'm', SEL_SELMUL },
/* Select all files in current dir */
{ 'a', SEL_SELALL },
/* Invert selection in current dir */
{ 'A', SEL_SELINV },
/* Copy from selection buffer */
{ 'p', SEL_CP },
/* Move from selection buffer */
{ 'v', SEL_MV },
/* Copy/move from selection buffer and rename */
{ 'w', SEL_CPMVAS },
/* Delete from selection buffer */
{ 'x', SEL_RM },
/* Open in a custom application */
{ 'o', SEL_OPENWITH },
/* Create a new file */
{ 'l', SEL_NEW },
/* Show rename prompt */
{ CONTROL('R'), SEL_RENAME },
/* Rename contents of current dir */
{ 'r', SEL_RENAMEMUL },
/* Disconnect a SSHFS mount point */
{ 'C', SEL_UMOUNT },
/* Show help */
{ '?', SEL_HELP },
/* Quit a context */
{ '+', SEL_AUTONEXT },
/* Edit in EDITOR */
{ 'y', SEL_EDIT },
/* Run a plugin */
{ ';', SEL_PLUGIN },
/* Run command */
{ '!', SEL_SHELL },
{ CONTROL(']'), SEL_SHELL },
/* Launcher */
{ '=', SEL_LAUNCH },
/* Show command prompt */
{ ']', SEL_PROMPT },
/* Manage sessions */
{ 's', SEL_SESSIONS },
/* Export list */
{ '>', SEL_EXPORT },
/* Set time type */
{ 'T', SEL_TIMETYPE },
/* Quit a context */
{ 'q', SEL_QUITCTX },
/* Change dir on quit */
{ CONTROL('G'), SEL_QUITCD },
/* Quit */
{ CONTROL('Q'), SEL_QUIT },
/* Quit with an error code */
{ 'Q', SEL_QUITERR },
#ifndef NOMOUSE
{ KEY_MOUSE, SEL_CLICK },
#endif
};

Binary file not shown.

View file

@ -0,0 +1 @@
ca645177-1508-4e84-8259-9017e79e6c91

View file

@ -0,0 +1,110 @@
Copyright (c) 2015-2022, Renzhi Li (aka. Belleve Invis, belleve@typeof.net)
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
--------------------------
SIL Open Font License v1.1
====================================================
Preamble
----------
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
Definitions
-------------
`"Font Software"` refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
`"Reserved Font Name"` refers to any names specified as such after the
copyright statement(s).
`"Original Version"` refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
`"Modified Version"` refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
`"Author"` refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
Permission & Conditions
------------------------
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1. Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2. Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3. No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4. The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5. The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
Termination
-----------
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,39 @@
[buildPlans.iosevka-zesty]
family = "Iosevka Zesty"
spacing = "normal"
serifs = "sans"
no-cv-ss = true
no-ligation = true
[buildPlans.iosevka-zesty.variants.design]
two = "straight-neck"
eight = "two-circles"
nine = "straight-bar"
brace = "straight"
number-sign = "slanted"
dollar = "open"
cent = "open"
percent = "rings-continuous-slash"
[buildPlans.iosevka-zesty.weights.regular]
shape = 400
menu = 400
css = 400
[buildPlans.iosevka-zesty.weights.bold]
shape = 700
menu = 700
css = 700
[buildPlans.iosevka-zesty.slopes.upright]
angle = 0
shape = "upright"
menu = "upright"
css = "normal"
[buildPlans.iosevka-zesty.slopes.italic]
angle = 9.4
shape = "italic"
menu = "italic"
css = "italic"

View file

@ -0,0 +1,6 @@
this is my custom build of iosevka, see plans.toml for the exact config
if you want, you can download them (why else would i put them in /public/?)
the iosevka license is attached if you want to read it

@ -0,0 +1 @@
Subproject commit d0a72669c9e0d1bbbae2f3d832d291592d1a4f22

BIN
public/pfp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
public/pkl.zip Normal file

Binary file not shown.

92
public/platformer/data.js Normal file
View file

@ -0,0 +1,92 @@
// the game data
export default {
// the platforms
parts: [
// x, y, width, height, type
[100, 100, 200, 50],
[400, 50, 200, 50],
[700, 0, 50, 50],
[900, -50, 50, 50],
[1100, -100, 50, 100],
[1200, -200, 50, 50],
[1300, -300, 50, 50],
[1150, -400, 100, 50],
[800, -450, 100, 50],
[450, -500, 100, 50],
[300, -600, 50, 50],
[400, -700, 50, 50],
[300, -800, 50, 50],
[400, -900, 150, 50],
[450, -1000, 50, 50],
[450, -1100, 50, 50],
[450, -1200, 100, 50],
[700, -1300, 50, 50, "checkpoint"],
[850, -1400, 50, 50],
[1000, -1500, 50, 50],
[1400, -1400, 50, 50],
[1800, -1350, 50, 50],
[2150, -1350, 50, 50],
[2150, -1450, 50, 50],
[2150, -1550, 50, 50],
[2150, -1650, 50, 50],
[2150, -1750, 50, 50, "checkpoint"],
[2125, -1850, 100, 50],
[2100, -1950, 150, 50],
[2075, -2050, 200, 50],
[2050, -2150, 100, 50],
[2200, -2150, 100, 50],
[2150, -2250, 50, 50, "checkpoint"],
[2000, -2350, 50, 50],
[1850, -2450, 50, 50],
[1600, -2500, 50, 50],
[1350, -2550, 50, 50],
[1050, -2600, 50, 50],
[775, -2650, 50, 50],
[400, -2650, 50, 50],
[25, -2650, 50, 50],
[-350, -2650, 50, 50, "checkpoint"],
[-750, -2650, 50, 50],
[-1200, -2500, 50, 50],
[-1500, -2200, 50, 50],
[-1900, -1900, 50, 50],
[-2100, -2000, 50, 50, "final"],
],
// the player
player: {
x: 200,
y: 0,
velx: 0,
vely: 0,
savex: 200,
savey: 85,
size: 15,
canJump: false,
},
// inputs - done this way so you can press multiple keys at once
input: {
up: false,
down: false,
left: false,
right: false,
},
// colors for each thing
color: {
player: "#f92a38",
background: "#ffffff",
dots: "#f6f6f6",
platforms: "#222222",
shadow: "#dddddd",
checkpoint: "#4feab4",
active: "#52e5a5",
final: "#52e5cd",
win: "#6befd9",
},
// rendering stuff
camera: [0, 0], // camera position
size: [0, 0], // window/canvas size
anim: [0, 0, 1], // checkpoint animation details
};

View file

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>canvas testing</title>
<link rel="stylesheet" href="style.css" />
<script src="script.js" type="module" defer></script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>

213
public/platformer/script.js Normal file
View file

@ -0,0 +1,213 @@
import game from "./data.js"; // import the game data
// import elements from html
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
// resize the canvas to full screen
function resize() {
const w = window.innerWidth;
const h = window.innerHeight;
canvas.width = w;
canvas.height = h;
ctx.width = w;
ctx.height = h;
game.size = [w, h];
}
// reset the player to the last checkpoint (or start)
function die() {
game.player.x = game.player.savex;
game.player.y = game.player.savey;
game.player.velx = 0;
game.player.vely = 0;
}
function draw() {
requestAnimationFrame(draw); // to continuously animate
const offx = game.camera[0] - game.size[0] / 2;
const offy = game.camera[1] - game.size[1] / 2;
const c = game.color;
const point = (x, y) => [x - offx, y - offy];
const color = (which) => (ctx.fillStyle = game.color[which]);
const rect = (x, y, w, h) => ctx.fillRect(...point(x, y), w, h);
// draw background
color("background");
ctx.fillRect(0, 0, game.size[0], game.size[1]);
color("dots");
for (let i = 0; i < 40; i++) {
for (let j = 0; j < 30; j++) {
const spacing = 60;
const depth = 0.5;
ctx.beginPath();
ctx.arc(
i * spacing - (offx % (spacing / depth)) * depth,
j * spacing - (offy % (spacing / depth)) * depth,
5,
0,
2 * Math.PI
);
ctx.fill();
}
}
// draw checkpoint animation (if there is one)
if (game.anim[2] < 1) {
color("shadow");
ctx.globalAlpha = 1 - game.anim[2];
ctx.beginPath();
ctx.arc(
...point(game.anim[0], game.anim[1]),
game.anim[2] * 100 + 25,
0,
2 * Math.PI
);
ctx.fill();
ctx.globalAlpha = 1;
game.anim[2] += 0.04;
}
// draw platforms
for (let part of game.parts) {
color("shadow");
for (let i = 6; i > 0; i--) {
rect(part[0] + i, part[1] + i, part[2], part[3]);
}
color(part[4] || "platforms");
rect(part[0], part[1], part[2], part[3]);
}
// draw player
color("player");
rect(game.player.x, game.player.y, game.player.size, game.player.size);
}
function update() {
const p = game.player;
const c = game.camera;
// handle input
const i = game.input;
const speed = 2;
if (i.up && p.canJump) p.vely = -14;
if (i.down) p.vely += 0.8;
if (i.left) p.velx -= speed;
if (i.right) p.velx += speed;
// update x position
if (move("x", p.velx, p.velx < 0 ? -1 : 1)) {
p.velx = 0;
}
// reset jump if they're falling or already jumping (there's a small grace period though)
if (Math.abs(p.vely) > 3) p.canJump = false;
// update y position
const collided = move("y", p.vely, p.vely < 0 ? -1 : 1);
if (collided) {
if (p.vely >= 0) {
// if they fell onto a platform then let them jump
p.canJump = true;
// if they hit a checkpoint
if (collided[4] === "checkpoint" || collided[4] === "final") {
// unset the other checkpoints
for (let part of game.parts.filter((i) => i[4] === "active")) {
part[4] = "checkpoint";
}
const x = collided[0] + collided[2] / 2;
const y = collided[1] + collided[3] / 2;
// play the checkpoint animation
game.anim = [x, y, 0];
game.player.savex = x - game.player.size / 2;
game.player.savey = y - collided[3] / 2 - game.player.size;
// they won!
if (collided[4] === "final") {
alert("ayo you win");
// reset the inputs, `alert()` does weird things
input.up = false;
input.down = false;
input.left = false;
input.right = false;
}
// don't spam animation; change platform color
collided[4] = collided[4] === "final" ? "win" : "active";
}
}
p.vely = 0;
}
// they fell out of the world
if (p.y > 1000) die();
// update velocity
p.velx *= 0.8;
p.vely = Math.min(30, p.vely + 0.8);
// update camera
c[0] = (c[0] * 9 + p.x) / 10;
c[1] = (c[1] * 9 + p.y) / 10;
// move, and return the platform the player collided with if any
function move(key, amt, speed) {
for (let i = 0; i < Math.abs(amt) - 1; i++) {
p[key] += speed;
const c = collision();
if (c) {
p[key] -= speed;
return c;
}
}
return null;
}
// check if there was a collision
function collision() {
const s = game.player.size;
for (let part of game.parts) {
const inside =
p.x + s > part[0] &&
p.y + s > part[1] &&
p.x < part[0] + part[2] &&
p.y < part[1] + part[3];
if (inside) return part;
}
return false;
}
}
// handle input
function input(e) {
const i = game.input;
const down = e.type === "keydown";
switch (e.key) {
case "ArrowUp":
return (i.up = down);
case "ArrowDown":
return (i.down = down);
case "ArrowLeft":
return (i.left = down);
case "ArrowRight":
return (i.right = down);
case "r":
return die();
}
}
// run the game!
resize();
draw();
setInterval(update, 1000 / 60);
window.addEventListener("resize", resize);
window.addEventListener("keydown", input);
window.addEventListener("keyup", input);

View file

@ -0,0 +1,7 @@
/* mmmm css */
body {
margin: 0;
padding: 0;
overflow: hidden;
}

2103
public/pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load diff

BIN
public/reminder.mbp Normal file

Binary file not shown.

1
public/snek Submodule

@ -0,0 +1 @@
Subproject commit bf62d20fe90755e089a59c4bc4dff8d00525887b

3201
public/test.txt Normal file

File diff suppressed because it is too large Load diff

22
raid.md Normal file
View file

@ -0,0 +1,22 @@
# how to use the raid (shadow legends) farm
1. get bad omen from any pillager outpost (there's one directly accessible from the nether)
2. go to the raid farm
3. immediately go into the water elevator (or you lose bad omen)
4. if you're not on your first raid, skip to step 9
5. a raid will start. ignore it for now
6. stand below the chest
7. put all your items into the chest except some food and a sword
8. organize your inventory in a way that it's filled with the items you want to collect (see first image) (if you want totems, leave some empty space in your inventory)
9. do the same thing with the hopper (second image)
10. wait for the horns to stop (with subtitles, wait for "ominous horn blaring" to disappear)
11. flip the lever (fence gate will be closed)
12. attack through the gap between the hopper and the chest until everything is dead
13. if there's too many items on top of the hopper, take the lava bucket from the chest and place it on top of the hopper so the items burn
14. make sure to put back the lava bucket
15. if you're done, take your items
16. flip the lever (fence gate open)
17. on the ladders, go as far forwards as you can, then stop pressing w and you will drop right into the water
18. if you're done, just leave, otherwise repeat from step 3
![screenshot of inventory setup](https://celery.eu.org/_matrix/media/r0/download/celery.eu.org/bb2ad5b01f62d9fc566bbc3e3946694d5c26adf91725949427471876096)

105
rfc/index.html Normal file
View file

@ -0,0 +1,105 @@
<!DOCTYPE html>
<html>
<head>
<title>List of failed RFCs</title>
<link rel="stylesheet" href="rfc.css"></link>
<link rel="stylesheet" href="normal.css"></link>
<link rel="stylesheet" href="wikihow.css"></link>
</head>
<body>
<article class="normal">
<table class="info">
<tr><td>Stream:</td><td>Independent Submission</td></tr>
<tr><td>RFC:</td><td><a href="#no">12383</a></td></tr>
<tr><td>Category:</td><td>Euclid</td></tr>
<tr><td>Published:</td><td>Tomorrow</td></tr>
<tr><td>Hotel:</td><td>Trivago</td></tr>
</table>
<h1>RFC 12383<br>Folder limits</h1>
<h2>Status of this Memo</h2>
<p> This memo provides absolutely no information to the Internet community. This memo does not specify an Internet standard of any kind. Distribution of this memo is unlimited, assuming nobody mints this as a NFT.</p>
<h2>Introduction</h2>
<p>This RFC is attempts to fix inconsistencies found on many servers. Folders are commonly used as a form of organizing files. However, many admins store hundreds or thousands of files inside these folders. In the physical world, this would be impossible. To remedy this, this RFC defines an upper limit on the number of files per folder. Although this is not an internet standard, it is advised to note that there is no limit to our power, and that we may lower the limit at any time.</p>
<h2>Requirements Language</h2>
<p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHOULD", "WOULD BE A GOOD IDEA TO", "PLEASE DON'T", "IF YOU WANT TO", and "ABSOLUTELY NOT" in this document are to be interpreted as described in <a href="https://www.rfc-editor.org/info/bcp14">BCP 14</a> when, and only when, they appear in SQL case.</p>
<h2>Implementation</h2>
<p>The number of files per folder are to be limited to 493 because it is a very nice number<sup>1</sup>. Any attempt to shove more than the maximum number of files into a single folder MUST result in an out of space error.</p>
<p>An additional data structure, "pile", MUST be implemented for mass file storage. A pile must have no upper limit to the number of files, however listing files MUST take an additional <code>2^ni</code> milliseconds of time, where n = number of files and i = impatience of user.</p>
<h2>Footnotes</h2>
<ol>
<li>An easy way to remember this number is that it is your mother's weight in kilograms.</li>
</ol>
<h2>Comments</h2>
<textarea disabled>Comments are disabled for this RFC.</textarea>
</article>
<div class="sep"></div>
<article class="wikihow">
<div class="how">
<div class="block">
<div class="content">
<div style="height: 4px;"></div>
<h1>How to Communicate Effectively</h1>
<p>Even with nothing to send besides shitposts, communication can be a rewarding process. TCP is an important part of the internet, and is evolving to this day! Make sure to have a stable internet connection to increase speed by minimizing packet loss.</p>
</div>
</div>
<div class="block">
<div class="title">
<div>Part <div>1</div></div>
<h2>Get a friend</h2>
</div>
<a href="https://www.reddit.com/r/disneyvacation/comments/9otz7t/how_to_browse_rfunny/"><img src="wiki1.png"></a>
<div class="content">
<p><span class="num">1</span><b>Make sure to have a friend to communicate with.</b> Without a target to send your shitposts to, it can be very difficult to get anywhere while communicating.</p>
</div>
</div>
<div class="block">
<div class="title">
<div>Part <div>2</div></div>
<h2>SYN</h2>
</div>
<a href="https://www.wikihow.com/Yell-Like-Tarzan"><img src="wiki2.png"></a>
<div class="content">
<p><span class="num">2</span><b>Initiate the connection by sending a SYN packet.</b> This is the first packet you send when initiating a connection.</p>
</div>
</div>
<div class="block">
<div class="title">
<div>Part <div>3</div></div>
<h2>SYN/ACK</h2>
</div>
<a href="https://www.wikihow.com/Yell-Like-Tarzan"><img src="wiki3.png"></a>
<div class="content">
<p><span class="num">3</span><b>Acknowledge the connection by sending an ACK+SYN packet.</b> This is done by your friend to accept the connection. They will need to set both the ACK and SYN flag.</p>
</div>
</div>
<div class="block">
<div class="title">
<div>Part <div>4</div></div>
<h2>ACK</h2>
</div>
<a href="https://www.wikihow.com/Deal-With-Someone-Yelling-at-You"><img src="wiki4.png"></a>
<div class="content">
<p><span class="num">4</span><b>Complete connection establishment with an ACK packet.</b> This is the final step in connecting.</p>
</div>
</div>
<div class="block">
<div class="title">
<div>Part <div>5</div></div>
<h2>(optional) Secure your communications with TLS</h2>
</div>
<a href="https://media.istockphoto.com/photos/calculator-in-hands-picture-id172781076"><img src="wiki5.png"></a>
<div class="content">
<p><span class="num">5</span><b>It is a good idea to secure your communications with transport layer security.</b> How to perform TLS is out of scope for this tutorial, but remember that TLS is a good idea.</p>
</div>
</div>
</div>
</article>
</body>
</html>

31
rfc/normal.css Normal file
View file

@ -0,0 +1,31 @@
.normal {
font: 14px/1.2 sans-serif;
max-width: 550px;
margin: 0 auto;
padding: 2em;
}
.normal h1 {
padding-bottom: 1em;
border-bottom: solid #ddd 1px;
}
.normal a { text-decoration: none }
.normal a:hover { background: #eeeeee }
.normal .info {
font-size: 0.9em;
color: #333333;
}
.normal img {
width: 100%;
}
.normal textarea {
width: 100%;
height: 10em;
background: #eee;
border: solid #aaa 1px;
}

10
rfc/rfc.css Normal file
View file

@ -0,0 +1,10 @@
body {
padding: 0;
margin: 0;
}
.sep {
height: 1em;
background: #222222;
}

Some files were not shown because too many files have changed in this diff Show more