Added everything.

This commit is contained in:
flash 2025-03-29 04:58:01 +01:00
parent 9e2277b172
commit 9014b9dbdd
10 changed files with 524 additions and 3 deletions

8
.editorconfig Normal file
View file

@ -0,0 +1,8 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
indent_style = space
indent_size = 4

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
* text=auto

17
.gitignore vendored Normal file
View file

@ -0,0 +1,17 @@
.dub
docs.json
__dummy.html
docs/
/april-fools-2025
april-fools-2025.so
april-fools-2025.dylib
april-fools-2025.dll
april-fools-2025.a
april-fools-2025.lib
april-fools-2025-test-*
*.exe
*.pdb
*.o
*.obj
*.lst
*.dll

13
LICENSE
View file

@ -1,5 +1,12 @@
Copyright (C) 2025 by flashii
Copyright (c) 2025 flashwave
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View file

@ -1,2 +1,5 @@
# april-fools-2025
stinky server thats probably really easy to break that shows peoples cursors in places this will surely not get annoying
just running `dub` should do the trick

6
dub.sdl Normal file
View file

@ -0,0 +1,6 @@
name "april-fools-2025"
description "april foole"
authors "flashwave"
copyright "2025 flashwave"
license "0BSD"
dependency "vibe-d" version="~>0.10.2"

19
dub.selections.json Normal file
View file

@ -0,0 +1,19 @@
{
"fileVersion": 1,
"versions": {
"diet-ng": "1.8.3",
"eventcore": "0.9.35",
"mir-linux-kernel": "1.2.1",
"openssl": "3.3.4",
"openssl-static": "1.0.5+3.0.8",
"stdx-allocator": "2.77.5",
"taggedalgebraic": "0.11.23",
"vibe-container": "1.5.0",
"vibe-core": "2.10.1",
"vibe-d": "0.10.2",
"vibe-http": "1.2.2",
"vibe-inet": "1.1.1",
"vibe-serialization": "1.0.7",
"vibe-stream": "1.1.1"
}
}

317
public/script.js Normal file
View file

@ -0,0 +1,317 @@
const BeansAPI = Object.freeze((() => {
const pointerNuke = pointer => {
if(pointer.element instanceof Element)
document.body.removeChild(pointer.element);
pointer.element = undefined;
pointer.elementHand = undefined;
pointer.elementGlow = undefined;
pointer.elementNumber = undefined;
};
const pointerDraw = pointer => {
pointer.fadeOutStart = false;
if(!pointer.visible) {
pointerNuke(pointer);
return;
}
if(!pointer.element) {
pointer.element = document.createElement('div');
pointer.element.style.width = '64px';
pointer.element.style.height = '64px';
pointer.element.style.pointerEvents = 'none';
pointer.element.style.borderWidth = '0';
pointer.element.style.boxStyle = 'border-box';
pointer.element.style.position = 'fixed';
pointer.element.style.zIndex = pointer.self ? '2147483647' : (10000000 + (pointer.connId ?? 0)).toString();
pointer.element.style.transform = 'scale(.5) rotate(-20deg)';
pointer.element.style.transformOrigin = '-18px 10px';
pointer.elementNumber = document.createElement('div');
pointer.elementNumber.style.position = 'absolute';
pointer.elementNumber.style.top = '28px';
pointer.elementNumber.style.left = '0';
pointer.elementNumber.style.zIndex = '30';
pointer.elementNumber.style.color = 'var(--pointer-colour, #00f)';
pointer.elementNumber.style.fontFamily = 'sans-serif';
pointer.elementNumber.style.fontSize = '24px';
pointer.elementNumber.style.fontWeight = '700';
pointer.elementNumber.style.letterSpacing = '-1px';
pointer.elementNumber.style.textAlign = 'center';
pointer.elementNumber.style.width = pointer.element.style.width;
pointer.elementNumber.style.height = pointer.element.style.height;
pointer.element.appendChild(pointer.elementNumber);
pointer.elementGlow = document.createElement('div');
pointer.elementGlow.style.position = 'absolute';
pointer.elementGlow.style.top = '0';
pointer.elementGlow.style.left = '0';
pointer.elementGlow.style.zIndex = '20';
pointer.elementGlow.style.backgroundColor = 'var(--pointer-colour, #00f)';
pointer.elementGlow.style.width = pointer.element.style.width;
pointer.elementGlow.style.height = pointer.element.style.height;
pointer.elementGlow.style.maskImage = 'url(//static.flash.moe/images/pointer.png)';
pointer.elementGlow.style.webkitMaskImage = 'url(//static.flash.moe/images/pointer.png)';
pointer.elementGlow.style.maskType = 'alpha';
pointer.elementGlow.style.webkitMaskType = 'alpha';
pointer.element.appendChild(pointer.elementGlow);
pointer.elementHand = document.createElement('div');
pointer.elementHand.style.position = 'absolute';
pointer.elementHand.style.top = '0';
pointer.elementHand.style.left = '0';
pointer.elementHand.style.zIndex = '10';
pointer.elementHand.style.width = pointer.element.style.width;
pointer.elementHand.style.height = pointer.element.style.height;
pointer.elementHand.style.backgroundColor = '#fff';
pointer.elementHand.style.maskImage = 'url(//static.flash.moe/images/pointer.png)';
pointer.elementHand.style.webkitMaskImage = 'url(//static.flash.moe/images/pointer.png)';
pointer.elementHand.style.maskType = 'alpha';
pointer.elementHand.style.webkitMaskType = 'alpha';
pointer.element.appendChild(pointer.elementHand);
document.body.appendChild(pointer.element);
}
const opacity = pointer.self ? .5 : 1;
pointer.elementNumber.textContent = pointer.userId ?? pointer.connId ?? 0;
pointer.element.style.setProperty('--pointer-colour', '#' + (pointer.colour ?? 0).toString(16).padStart(6, '0'));
pointer.element.style.opacity = opacity.toString();
pointer.element.style.left = Math.round(window.innerWidth * ((pointer.xPos ?? 0) / 0xFFFF)).toString() + 'px';
pointer.element.style.top = Math.round(window.innerHeight * ((pointer.yPos ?? 0) / 0xFFFF)).toString() + 'px';
if(pointer.click) {
pointer.elementHand.style.maskPosition = '-64px 0';
pointer.elementHand.style.webkitMaskPosition = '-64px 0';
pointer.elementGlow.style.maskPosition = '-64px -64px';
pointer.elementGlow.style.webkitMaskPosition = '-64px -64px';
} else {
pointer.elementHand.style.maskPosition = '0 0';
pointer.elementHand.style.webkitMaskPosition = '0 0';
pointer.elementGlow.style.maskPosition = '0 -64px';
pointer.elementGlow.style.webkitMaskPosition = '0 -64px';
}
pointer.fadeOutStart = undefined;
const fadeOut = time => {
if(pointer.fadeOutStart === false || !pointer.element) {
pointer.fadeOutStart = undefined;
return;
}
if(pointer.fadeOutStart === undefined)
pointer.fadeOutStart = time;
const elapsed = time - pointer.fadeOutStart;
const completion = Math.min(1, Math.max(0, elapsed / 60000));
const eased = completion === 0 ? 0 : Math.pow(2, 10 * completion - 10);
pointer.element.style.opacity = (opacity - (opacity * eased)).toString();
if(completion < 1)
requestAnimationFrame(fadeOut);
else
pointerNuke(pointer);
};
requestAnimationFrame(fadeOut);
};
const pointers = new Map;
let selfPointer;
let sock;
const pub = {};
let connected = false;
const runWhenConnected = [];
const connect = () => {
sock = new WebSocket('ws://localhost:9091');
sock.binaryType = 'arraybuffer';
sock.addEventListener('close', ev => {
connected = false;
sock = undefined;
setTimeout(() => { connect(); }, 1000);
});
sock.addEventListener('message', ev => {
if(!(ev.data instanceof ArrayBuffer))
return;
const view = new DataView(ev.data);
let offset = 0;
let connId = offset < view.byteLength ? view.getUint8(offset++) : 0;
connId <<= 8;
connId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
connId <<= 8;
connId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
connId <<= 8;
connId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
const isSelf = !!(connId & 0x80000000);
connId &= 0x7FFFFFFF;
let pointer;
if(pointers.has(connId))
pointer = pointers.get(connId);
else
pointers.set(connId, pointer = { connId, visible: false, xPos: -1000, yPos: -1000, });
if(isSelf) {
console.log(pointer);
if(selfPointer)
selfPointer.self = false;
selfPointer = pointer;
selfPointer.self = true;
connected = true;
for(const callback of runWhenConnected)
callback(pub);
}
const oflags = offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.visible = !!(oflags & 0x10);
pointer.click = !!(oflags & 0x20);
if(oflags & 0x01) {
pointer.userId = offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.userId <<= 8;
pointer.userId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.userId <<= 8;
pointer.userId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.userId <<= 8;
pointer.userId |= offset < view.byteLength ? view.getUint8(offset++) : 0;
}
if(oflags & 0x02) {
pointer.xPos = offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.xPos <<= 8;
pointer.xPos |= offset < view.byteLength ? view.getUint8(offset++) : 0;
}
if(oflags & 0x04) {
pointer.yPos = offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.yPos <<= 8;
pointer.yPos |= offset < view.byteLength ? view.getUint8(offset++) : 0;
}
if(oflags & 0x08) {
pointer.colour = offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.colour <<= 8;
pointer.colour |= offset < view.byteLength ? view.getUint8(offset++) : 0;
pointer.colour <<= 8;
pointer.colour |= offset < view.byteLength ? view.getUint8(offset++) : 0;
}
pointerDraw(pointer);
});
};
const pointerUpdate = ev => {
if(!connected)
return;
let iflags = 0;
let oflags = 0;
const buffer = [];
const xPos = Math.round((ev.clientX / window.innerWidth) * 0xFFFF);
const yPos = Math.round((ev.clientY / window.innerHeight) * 0xFFFF);
const click = !!(ev.buttons & 1);
if(!click !== !selfPointer.click) {
selfPointer.click = click;
iflags |= 0x20;
if(click) oflags |= 0x20;
buffer.push(click ? 0x78 : 0x58);
}
if(xPos !== selfPointer.xPos) {
selfPointer.xPos = xPos;
iflags |= 0x02;
buffer.push((xPos & 0xFF00) >> 8);
buffer.push(xPos & 0xFF);
}
if(yPos !== selfPointer.yPos) {
selfPointer.yPos = yPos;
iflags |= 0x04;
buffer.push((yPos & 0xFF00) >> 8);
buffer.push(yPos & 0xFF);
}
if(iflags) {
if(iflags & 0x01)
buffer.unshift(oflags);
buffer.unshift(iflags);
}
if(buffer.length > 0) {
sock.send(new Uint8Array(buffer));
pointerDraw(selfPointer);
}
};
window.addEventListener('pointermove', pointerUpdate);
window.addEventListener('pointerup', pointerUpdate);
window.addEventListener('pointerdown', pointerUpdate);
connect();
pub.runWhenConnected = callback => {
if(typeof callback !== 'function')
return;
runWhenConnected.push(callback);
if(connected)
callback(pub);
};
pub.setUserInfo = (id, colour) => {
if(!connected)
return;
if(typeof id === 'string')
id = parseInt(id);
if(typeof id !== 'number' || !Number.isInteger(id))
id = undefined;
if(typeof colour === 'string')
colour = colour.startsWith('#') ? parseInt(colour.substring(1), 16) : parseInt(colour);
if(typeof colour !== 'number' || !Number.isInteger(colour))
colour = undefined;
let iflags = 0x10;
const buffer = [0x10];
selfPointer.visible = true;
if(id !== undefined && id !== selfPointer.userId) {
selfPointer.userId = id;
iflags |= 0x01;
buffer.push((id & 0xFF000000) >> 24);
buffer.push((id & 0xFF0000) >> 16);
buffer.push((id & 0xFF00) >> 8);
buffer.push(id & 0xFF);
}
if(colour !== undefined && colour !== selfPointer.colour) {
selfPointer.colour = colour;
iflags |= 0x08;
buffer.push((colour & 0xFF0000) >> 16);
buffer.push((colour & 0xFF00) >> 8);
buffer.push(colour & 0xFF);
}
if(iflags)
buffer.unshift(iflags);
if(buffer.length > 0) {
sock.send(new Uint8Array(buffer));
pointerDraw(selfPointer);
}
};
return pub;
})());

5
public/test.html Normal file
View file

@ -0,0 +1,5 @@
<!doctype html>
<meta charset="utf-8">
<title>soup</title>
<h1>soup</h1>
<script src="/script.js"></script>

138
source/app.d Normal file
View file

@ -0,0 +1,138 @@
import vibe.d;
import std.container : DList;
import std.random : Mt19937;
import core.stdc.time;
private DList!WebSocket socks;
private Mt19937 rng;
private uint counter = 0;
int main(string[] args) {
rng.seed(core.stdc.time.time(null));
auto router = new URLRouter;
router.get("/", handleWebSockets(&handleWebSocketConnection));
router.get("*", serveStaticFiles("public/"));
auto settings = new HTTPServerSettings;
settings.port = 9091;
settings.bindAddresses = ["::1", "127.1"];
auto listener = listenHTTP(settings, router);
return runApplication(&args);
}
void broadcast(scope WebSocket sender, ubyte[] buffer) {
foreach(sock; socks)
if(sender != sock && sock.connected)
sock.send(buffer);
}
void handleWebSocketConnection(scope WebSocket sock) {
logInfo("[+] %s", sock.request.peer);
socks.insert(sock);
// ioflags
// 0x01 -> set user id
// 0x02 -> set x position
// 0x04 -> set y position
// 0x08 -> set colour
// iflags
// 0xF0 -> mask for oflags
// oflags
// 0x10 -> visible
// 0x20 -> pressed
uint connId = (++counter & 0x7FFFFFFF);
uint userId = connId;
ushort xPos = 0;
ushort yPos = 0;
ubyte oflags = 0x09;
uint colour = 0;
colour |= rng.front & 0xFF0000;
rng.popFront;
colour |= rng.front & 0xFF00;
rng.popFront;
colour |= rng.front & 0xFF;
rng.popFront;
ubyte[] buffer = [
(0x80 | ((connId & 0x7F000000) >> 24)), ((connId & 0xFF0000) >> 16), ((connId & 0xFF00) >> 8), (connId & 0xFF),
oflags,
((userId & 0xFF000000) >> 24), ((userId & 0xFF0000) >> 16), ((userId & 0xFF00) >> 8), (userId & 0xFF),
((colour & 0xFF0000) >> 16), ((colour & 0xFF00) >> 8), (colour & 0xFF)
];
sock.send(buffer);
buffer[0] &= ~0x80;
broadcast(sock, buffer);
oflags |= 0x06;
while(sock.waitForData) {
if(!sock.connected)
break;
int offset = 0;
ubyte[] data = sock.receiveBinary;
ubyte iflags = (offset < data.length ? data[offset++] : 0);
if(iflags & 0xF0) {
oflags &= ~(iflags & 0xF0);
oflags |= (offset < data.length ? data[offset++] : 0) & (iflags & 0xF0);
}
if(iflags & 0x01) {
userId = (offset < data.length ? data[offset++] : 0);
userId <<= 8;
userId |= (offset < data.length ? data[offset++] : 0);
userId <<= 8;
userId |= (offset < data.length ? data[offset++] : 0);
userId <<= 8;
userId |= (offset < data.length ? data[offset++] : 0);
}
if(iflags & 0x02) {
xPos = (offset < data.length ? data[offset++] : 0);
xPos <<= 8;
xPos |= offset < data.length ? data[offset++] : 0;
}
if(iflags & 0x04) {
yPos = (offset < data.length ? data[offset++] : 0);
yPos <<= 8;
yPos |= offset < data.length ? data[offset++] : 0;
}
if(iflags & 0x08) {
colour = (offset < data.length ? data[offset++] : 0);
colour <<= 8;
colour |= (offset < data.length ? data[offset++] : 0);
colour <<= 8;
colour |= (offset < data.length ? data[offset++] : 0);
}
buffer = [
((connId & 0x7F000000) >> 24), ((connId & 0xFF0000) >> 16), ((connId & 0xFF00) >> 8), (connId & 0xFF),
oflags,
((userId & 0xFF000000) >> 24), ((userId & 0xFF0000) >> 16), ((userId & 0xFF00) >> 8), (userId & 0xFF),
((xPos & 0xFF00) >> 8), (xPos & 0xFF),
((yPos & 0xFF00) >> 8), (yPos & 0xFF),
((colour & 0xFF0000) >> 16), ((colour & 0xFF00) >> 8), (colour & 0xFF),
];
broadcast(sock, buffer);
}
oflags &= ~0x0F;
socks.linearRemoveElement(sock);
sock.close;
buffer = [
((connId & 0x7F000000) >> 24), ((connId & 0xFF0000) >> 16), ((connId & 0xFF00) >> 8), (connId & 0xFF),
oflags,
];
broadcast(sock, buffer);
logInfo("[-] %s", sock.request.peer);
}