1// Originally written for https://lol.zip on May 16, 2023
2// Now hosted on https://paperclover.net/lol.zip
3// See https://paperclover.net/q+a/2512200208
4import { Hono } from "hono";
5import sourceText from "./lines.txt?text";
6
7const encoder = new TextEncoder();
8
9const SPACE = 32;
10const NEWLINE = 10;
11
12let stats_total = 0;
13let stats_currentlySending = 0;
14
15let start: Uint8Array | null = null;
16let chunks: Uint8Array[] = [];
17let last = 0;
18
19const buffer = encoder.encode(sourceText);
20for (let i = 0; i < buffer.length; i++) {
21 if (buffer[i] === NEWLINE) {
22 if (start === null) {
23 start = buffer.subarray(last, i + 1);
24 } else {
25 chunks.push(buffer.subarray(last, i + 1));
26 }
27 buffer[i] = SPACE;
28 last = i + 1;
29 }
30}
31const length = chunks.length;
32
33function shuffle<T>(array: T[]): T[] {
34 let currentIndex = array.length,
35 randomIndex;
36 let val;
37 while (currentIndex != 0) {
38 randomIndex = Math.floor(Math.random() * currentIndex);
39 currentIndex--;
40 val = array[currentIndex]!;
41 array[currentIndex] = array[randomIndex]!;
42 array[randomIndex] = val;
43 }
44 return array;
45}
46
47export const app = new Hono();
48
49app.get("/lol.zip", (c) => {
50 const userAgent = c.req.header("User-Agent") ?? "";
51
52 // if known search engine, return a 404
53 if (
54 userAgent.includes("Googlebot")
55 || userAgent.includes("bingbot")
56 || userAgent.includes("Discordbot")
57 ) {
58 return c.text("Not Found", 404);
59 }
60
61 let cleanup: VoidFunction | null = null;
62 const stream = new ReadableStream({
63 async start(controller) {
64 const array = chunks.slice();
65 shuffle(array);
66 let i = 0;
67
68 controller.enqueue(start);
69
70 const interval = setInterval(() => {
71 if (i >= length) {
72 shuffle(array);
73 i = 0;
74 }
75 controller.enqueue(array[i]);
76 i++;
77 }, 100);
78
79 const timeout = setTimeout(() => {
80 clearInterval(interval);
81 controller.enqueue(
82 encoder.encode(
83 "\n\ndamn, you got to the end. congrats. you win nothing. this site closes the connection after 24 hours, since i think the joke wears off at that point.",
84 ),
85 );
86 controller.close();
87 stats_currentlySending--;
88 }, 86400000);
89
90 // cleanup on abort
91 cleanup = () => {
92 clearInterval(interval);
93 clearTimeout(timeout);
94 stats_currentlySending--;
95 };
96 },
97 cancel() {
98 cleanup?.();
99 },
100 });
101
102 stats_currentlySending++;
103 stats_total++;
104
105 return new Response(stream, {
106 headers: {
107 "Content-Type": "application/zip",
108 "Content-Length": "77700420420420420",
109 "Content-Disposition": "attachment; filename=lol.zip",
110 "Server": "by clover caruso <paperclover.net>",
111 "X-Source-Code": "https://git.paperclover.net/clo/sitegen/src/branch/master/src/q+a/lol.zip/",
112 },
113 });
114});
115
116app.get("/lol.stats", (c) => {
117 return c.json({
118 currentlySending: stats_currentlySending,
119 total: stats_total,
120 });
121});