diff options
feat: cutely wrap console logging functions, etc
Diffstat (limited to 'src')
-rw-r--r-- | src/lib/console.ts | 191 | ||||
-rw-r--r-- | src/routes/+layout.svelte | 1 | ||||
-rw-r--r-- | src/routes/anim-gen.ts | 84 | ||||
-rw-r--r-- | src/routes/canaries/keystore.ts | 36 |
4 files changed, 256 insertions, 56 deletions
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; |