From 2d2e1f52afaf1eb142e391c00450bc379c745f2f Mon Sep 17 00:00:00 2001
From: memdmp <memdmp@estrogen.zone>
Date: Thu, 23 Jan 2025 02:11:44 +0100
Subject: feat: cutely wrap console logging functions, etc

---
 src/lib/console.ts              | 191 ++++++++++++++++++++++++++++++++++++++++
 src/routes/+layout.svelte       |   1 +
 src/routes/anim-gen.ts          |  84 +++++++++---------
 src/routes/canaries/keystore.ts |  36 +++++---
 tailwind.config.js              |   6 +-
 5 files changed, 260 insertions(+), 58 deletions(-)
 create mode 100644 src/lib/console.ts

diff --git a/src/lib/console.ts b/src/lib/console.ts
new file mode 100644
index 0000000..313fd0a
--- /dev/null
+++ b/src/lib/console.ts
@@ -0,0 +1,191 @@
+import { browser } from "$app/environment";
+import { dev } from "$app/environment";
+
+if (browser) {
+  for (const v of [
+    "debug",
+    "log",
+    "info",
+    "warn",
+    "error",
+    "trace",
+  ] satisfies (keyof typeof console)[]) {
+    const old = ((globalThis as any)['_oldconsole_' + v] ?? console[v]) as typeof console[typeof v];
+    (globalThis as any)['_oldconsole_' + v] = old;
+    console[v] = (a, ...b) => {
+      if (typeof a === "string") {
+        const tags_unparsed = a.match(/^(\s*\[[\w\s]+\])*/mu)?.[0];
+        const pre: string[] = [];
+        const styles: string[] = [];
+        if (tags_unparsed) {
+          let tag_unparsed = null as null | string;
+          while ((tag_unparsed = a.match(/^(\s*\[[^\]\r\n]+\])/mu)?.[0])) {
+            a = a.substring(tag_unparsed.length);
+            tag_unparsed = tag_unparsed.trim();
+            let tag = tag_unparsed.substring(1, tag_unparsed.length - 1);
+            let colour = "#aa99ffcc";
+            switch (tag) {
+              case "vite":
+                colour =
+                  "linear-gradient(-45deg, #41D1FF -50%, #BD34FE 150%)";
+                break;
+              case "w":
+              case "warn":
+                colour = "#FFEA83";
+                break;
+              case "i":
+              case "inf":
+              case "info":
+                colour = "#99AAFF";
+                break;
+              case "e":
+              case "err":
+              case "error":
+                colour = "#FF99AA";
+                break;
+              case "success":
+              case "succ":
+                colour = "#AAFF99";
+                break;
+              case "motd":
+              case "devmotd":
+                colour =
+                  "linear-gradient(-75deg, #99AAFF -90%, #BD34FE 150%)";
+                break;
+              case "uwu":
+                colour = "#BBAAFF";
+                break;
+              case 'keystore':
+                colour = '#CC99FF';
+                break;
+              case 'globalState':
+                colour = '#E699FF';
+                break;
+            }
+            let baseMainStyles = `
+background: ${colour};
+color: #1a1a1a;
+font-width: bold;
+font-family: Inter, sans-serif;
+padding-top: 4px;
+padding-bottom: 4px;
+`
+            if (tag.includes('=')) {
+              const v = tag.split('=');
+              pre.push(`%c${v.shift() ?? ''}: %c${v.join('=')}%c`)
+              baseMainStyles += `background: #667;
+`
+              styles.push(`${baseMainStyles}
+border-top-left-radius: 4px;
+border-bottom-left-radius: 4px;
+padding-left: 4px;
+color: #3a3a3a;
+`, `${baseMainStyles}
+border-top-right-radius: 4px;
+border-bottom-right-radius: 4px;
+padding-right: 4px;
+margin-right: 4px;
+`, '')
+            } else {
+              pre.push(`%c${tag}%c`);
+              styles.push(
+                `
+${baseMainStyles}
+padding-left: 4px;
+padding-right: 4px;
+border-radius: 4px;
+margin-right: 4px;
+`,
+                "",
+              );
+            }
+          }
+        }
+        a = `​\n${pre.join("")}${(a as string).trimStart()}`;
+        if (b.length) b.push("\n​");
+        else a += "\n​";
+        return old(a, ...styles, ...b);
+      } else return old(a, ...b);
+    };
+  }
+
+  const s = [
+    [`CALL THE FIRE DEPARTMENT, WE JUST NUKED THE BUILDING`],
+    [`RIP Terry`],
+    [`WARNING, NUKING IS NOW LEGAL... WORLDWIDE!!! >~<`],
+    [`Welcome back, Anon`],
+    [`when you suckin on her nuts`],
+    [`wait.. nuking's actually kinda hot......`],
+    [`you know what happens after a nuke? smoke %c#3`, "color: #ff0000;"],
+    [`Fucking the industry's transfems since 20xx`],
+    [
+      `%c"How many Bitcoin?"%c I prefer my coin count in bytes.`,
+      "color: #99aaff;",
+      "color: undo;",
+    ],
+    [`Lesbians are hot %c<3`, "color: #ff99aa;"],
+    [
+      `Astolfo didn't kill %chim%c- herself`,
+      "text-decoration: line-through;",
+      "text-decoration: none;",
+    ],
+  ] as [string, ...string[]][];
+  const strs = s.map(([v0, ...vn]) => [
+    `[${dev ? "dev" : ""}motd]%c${v0}`,
+    ...[
+      // Base Styles
+      `
+color: #12488B;
+font-family: "Courier New", Courier, monospace;
+`,
+      // Additional Styles
+      ...vn,
+    ]
+      // Parse Declarations
+      .map((_, i, a) =>
+        a[i]
+          .split(";")
+          .filter((v) => v.trim().length !== 0)
+          .map((v) => v.split(":"))
+          .map(
+            ([k, ...v]) =>
+              [k.trim(), v.join(":").trim()] as [key: string, value: string],
+          ),
+      )
+      // Inherit from previous values
+      .map((_, i, a) => {
+        const props = {} as Record<string, string[]>;
+        for (let i2 = 0; i2 <= i; i2++) {
+          for (const [k, v] of a[i2]) {
+            if (v === "undo") (props[k] ?? []).pop();
+            else (props[k] = props[k] ?? []).push(v);
+          }
+        }
+        return Object.fromEntries(
+          Object.entries(props).map(([k, v]) => [k, v[v.length - 1]]),
+        );
+      })
+      // Join into strings
+      .map((v) => {
+        return Object.entries(v)
+          .map((v) => v.join(": ") + ";")
+          .join("\n");
+      }),
+  ]);
+  console.debug(
+    ...strs[
+    dev
+      ? Math.floor(Math.random() * strs.length)
+      : (Date.now() /
+        // millis in a second
+        1000 /
+        // secs in a min
+        60 /
+        // mins in an hour
+        60 /
+        // hours in a day
+        24) %
+      strs.length
+    ],
+  );
+}
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index 53bd941..80bd58c 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -1,4 +1,5 @@
 <script lang="ts">
+  import "$/lib/console";
   import "../app.css";
   import "$lib/fonts/all-local-after-woff2.css";
   const { children } = $props();
diff --git a/src/routes/anim-gen.ts b/src/routes/anim-gen.ts
index 382237e..550efb7 100644
--- a/src/routes/anim-gen.ts
+++ b/src/routes/anim-gen.ts
@@ -113,17 +113,17 @@ const biosStepHandlers: Step[] = [
     biosSteps,
   ).fill(
     (quantity: number, lastQuantity: number, index: number) =>
-    (next: () => void) => {
-      const s = anim.selector(
-        `#bios .bar`,
-      );
-      s.style(`${index === 0 ? hiddenStyles : visibleStyles}
+      (next: () => void) => {
+        const s = anim.selector(
+          `#bios .bar`,
+        );
+        s.style(`${index === 0 ? hiddenStyles : visibleStyles}
 width: ${lastQuantity * 100}vw;`);
-      anim._internal_timeline.now += 1;
-      s.style(`${visibleStyles}
+        anim._internal_timeline.now += 1;
+        s.style(`${visibleStyles}
 width: ${quantity * 100}vw;`);
-      anim.in(quantity === 1 ? 50 : biosStepInterval, next);
-    },
+        anim.in(quantity === 1 ? 50 : biosStepInterval, next);
+      },
   ).map((v, i, a) => v((i + 1) / a.length, i / a.length, i)),
   // Show bdsdxe
   (next) => {
@@ -378,8 +378,7 @@ const ttyStepHandlers: Step[] = [
       switch (step.kind) {
         case 'text': {
           const s = anim.selector(
-            `${isBeforeFirstClear ? '#openrc' : '#tty-' + (ttyIdx - 1)} ${
-              step.classes.map((v) => `.${v}`).join('')
+            `${isBeforeFirstClear ? '#openrc' : '#tty-' + (ttyIdx - 1)} ${step.classes.map((v) => `.${v}`).join('')
             }`,
           );
           s.style(altHiddenStyles);
@@ -391,8 +390,7 @@ const ttyStepHandlers: Step[] = [
         }
         case 'removeNode': {
           const s = anim.selector(
-            `${isBeforeFirstClear ? '#openrc' : '#tty-' + (ttyIdx - 1)} ${
-              step.removedItemClassList.map((v) => `.${v}`).join('')
+            `${isBeforeFirstClear ? '#openrc' : '#tty-' + (ttyIdx - 1)} ${step.removedItemClassList.map((v) => `.${v}`).join('')
             }`,
           );
           s.style(altVisibleStyles);
@@ -460,9 +458,8 @@ const output = `/**
  * You should have received a copy of the GNU Affero General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 ${anim.exportToCSS()}
-${
-  stages.filter((_, i, a) => i !== a.length - 1).map((v) =>
-    `${v.selector} {
+${stages.filter((_, i, a) => i !== a.length - 1).map((v) =>
+  `${v.selector} {
 ${hiddenStageStyles}
 }
 .ttytext-removed-after-done {
@@ -473,35 +470,34 @@ ${hiddenStageStyles}
   margin-left: -100vw;
   margin-right: 100vw;
 }
-${
-      (ttyLines.flatMap((v) =>
-        v.kind === 'text'
-          ? [
-            ...v.value.map((v) => ({
-              kind: 'text' as const,
-              ...v,
-            })),
-          ]
-          : []
-      ).flatMap((v) => [
-        ...(
-          v.kind === 'text'
-            ? [
-              v.colour
-                ? `.ttytext-block.text-\\[\\${v.colour}\\]{color:${v.colour};}`
-                : '',
-              v.bg
-                ? `.ttytext-block.bg-\\[\\${v.bg}\\]{background:${v.bg};}`
-                : '',
-            ]
-            : []
-        ),
-      ]).filter((v, i, a) => v.length !== 0 && a.indexOf(v) === i)).join('\n')
-    }
+${(ttyLines.flatMap((v) =>
+    v.kind === 'text'
+      ? [
+        ...v.value.map((v) => ({
+          kind: 'text' as const,
+          ...v,
+        })),
+      ]
+      : []
+  ).flatMap((v) => [
+    ...(
+      v.kind === 'text'
+        ? [
+          v.colour
+            ? `.ttytext-block.text-\\[\\${v.colour}\\]{color:${v.colour};}`
+            : '',
+          v.bg
+            ? `.ttytext-block.bg-\\[\\${v.bg}\\]{background:${v.bg};}`
+            : '',
+        ]
+        : []
+    ),
+  ]).filter((v, i, a) => v.length !== 0 && a.indexOf(v) === i)).join('\n')
+  }
 `
-  ).join('')
-}
-${[...anim.exportToObject().values()].map(v=>`#app.skip-animation ${v.selector} {
+).join('')
+  }
+${[...anim.exportToObject().values()].map(v => `#app.skip-animation ${v.selector} {
   animation-duration: 0.01ms;
 }`).join('\n')}
 `;
diff --git a/src/routes/canaries/keystore.ts b/src/routes/canaries/keystore.ts
index 1d2aefb..5b85201 100644
--- a/src/routes/canaries/keystore.ts
+++ b/src/routes/canaries/keystore.ts
@@ -2,23 +2,31 @@ import { dev } from "$app/environment";
 import { PublicKey, readCleartextMessage, readKey, verify } from "openpgp";
 import { fallbackKeys } from "./fallback-keys";
 export const keyStore = new Map<string, PublicKey>();
-const will_debug = false;
-const debug = dev && will_debug ? console.debug : () => void 0;
+const will_debug = true;
+const debug = dev && will_debug ? (z: any, ...a: any[]) => console.debug(...[
+  ...(typeof z === 'string' ? [`[keystore] ${z}`] : ['[keystore]', z]),
+  ...a
+]) : () => void 0;
 const _validateSignature = async (message: string, id: string) => {
   id = id.toUpperCase();
+  debug(`[validateSignature][status=lookup] looking up key by ID ${JSON.stringify(id)}`)
   const key = keyStore.get(id) ?? keyStore.get(id.replace(/ /g, ""));
   if (!key) throw new Error("Could not find key from keystore");
+  debug(`[validateSignature][status=parse] parsing message`)
   const signedMessage = await readCleartextMessage({
     cleartextMessage: message,
   });
+  debug(`[validateSignature][status=verify] verifying message signature`)
   const verificationResult = await verify({
     message: signedMessage,
     verificationKeys: key,
     expectSigned: true,
   });
+  debug(`[validateSignature][success] successfully validated message signature`)
   return verificationResult.data;
 }
 export const validateSignature: typeof _validateSignature = async (message, id) => {
+  debug(`[validateSignature][globalState] waiting on initKeystore`)
   await initKeystore;
   return _validateSignature(message, id)
 };
@@ -40,22 +48,22 @@ const pushKey = async ({
   ids = ids ?? [];
   if (is_url) {
     const url = new URL(key, "https://keys.openpgp.org/vks/v1/by-fingerprint/");
-    debug('getting key with url', url)
+    debug('[pushKey][info] Getting key with url\n\n', url)
     key = await fetch(
       url,
     ).then((v) => v.text()).catch(e => {
       if (fallbackKeys.has(key)) {
-        debug('failed with error', e, 'but found fallback key')
+        debug('[pushKey][warn] Failed with error', e, 'but found fallback key')
         return fallbackKeys.get(key)!
       }
       else {
-        debug('failed to fetch key, cannot find fallback')
+        debug('[pushKey][error] Failed to fetch key, cannot find fallback')
         throw e
       }
     });
-    debug('fetched key', key)
+    debug('[pushKey][success] Fetched key\n\n', JSON.stringify(key))
   } else {
-    debug('found key', key)
+    debug('[pushKey][success] Found key\n\n', JSON.stringify(key))
   }
   if (key === null)
     throw new Error('Key is null.')
@@ -64,9 +72,9 @@ const pushKey = async ({
   if (typeof key !== 'string')
     throw new Error(`Expected key with type string, got key of type ${key}`)
   if (signed_by) {
-    debug('key must be signed by', signed_by)
+    debug('[pushKey][validation][info] Key must be signed by', signed_by)
     key = await _validateSignature(key, signed_by);
-    debug('validated signature')
+    debug('[pushKey][success] Validated signature')
   }
   const parsedKey = await readKey({
     armoredKey: key,
@@ -88,9 +96,9 @@ const pushKey = async ({
       `Key ${parsedKey.getFingerprint()} is not ${expect_fingerprint}`,
     );
   else if (expect_fingerprint)
-    debug('fingerprint matches expected fingerprint')
+    debug('[success] Fingerprint matches expected fingerprint')
   else
-    debug('no expected fingerprint passed')
+    debug('[warn] No expected fingerprint passed')
   ids.push(
     parsedKey.getKeyID().toHex().replace(/ /g, ""),
     parsedKey.getFingerprint().replace(/ /g, ""),
@@ -100,7 +108,10 @@ const pushKey = async ({
   for (const id of ids) {
     keyStore.set(id, parsedKey);
   }
-  debug('added key', parsedKey, 'with ids', ids, 'to keystore')
+  debug('[success] Added key\n\n', {
+    key: parsedKey,
+    ids,
+  })
 };
 export const initKeystore = (async () => {
   await pushKey({
@@ -158,6 +169,7 @@ ZQ4KTbprMz8J4AD/bG33f9Kqg3AqehEyU2TldJs9U9Oni5AXGSGfKLJhmQc=
     is_url: true,
     signed_by: "canary-sigkey-signing",
   });
+  debug('[success] keystore initialization completed')
 })();
 
 export default keyStore;
diff --git a/tailwind.config.js b/tailwind.config.js
index f5a256c..da87acc 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -4,7 +4,7 @@ export default {
   theme: {
     extend: {
       fontFamily: {
-        bios: ['Ac437 IBM EGA 8x14', 'Hack', 'monospace'].map((v) =>
+        bios: ['Ac437 IBM EGA 8x14', 'Hack', "Courier New", 'Courier', 'monospace'].map((v) =>
           JSON.stringify(v)
         ),
         // TODO: Find more accurate grub2 default font!
@@ -12,9 +12,11 @@ export default {
           'Px437 DOS/V re. JPN12',
           'Ac437 IBM EGA 8x14',
           'Hack',
+          "Courier New",
+          'Courier',
           'monospace',
         ].map((v) => JSON.stringify(v)),
-        mono: ['PxPlus IBM EGA 8x14', 'Hack', 'monospace'].map((v) =>
+        mono: ['PxPlus IBM EGA 8x14', 'Hack', "Courier New", 'Courier', 'monospace'].map((v) =>
           JSON.stringify(v)
         ),
       },
-- 
cgit v1.2.3