redacted my info, into my database #1

Merged
botalex merged 21 commits from dev into main 2025-10-09 06:42:05 +02:00
5 changed files with 53 additions and 44 deletions
Showing only changes of commit 4205712d32 - Show all commits

View file

@ -4,7 +4,7 @@
import fly from "@e/fly"; import fly from "@e/fly";
import MediaQuery from "svelte-media-queries"; import MediaQuery from "svelte-media-queries";
import Dices from "@lucide/svelte/icons/dices"; import Dices from "@lucide/svelte/icons/dices";
import { re } from "@ts/Redaction/Redactor"; import re from "@ts/Redaction/Redactor";
let hideOnPrint: boolean = $state(false); let hideOnPrint: boolean = $state(false);
let { children } = $props(); let { children } = $props();
@ -115,16 +115,14 @@
</a> </a>
<div class="nav-spacer" /> <div class="nav-spacer" />
<!-- <a href="/">Home</a> -->
<!-- <a href="/zhen/notes/physics/1?hideOnPrint=1" target="_blank" style="width: 7.5rem;">Notes</a> -->
{@render SwitchThemeButton()} {@render SwitchThemeButton()}
<a <a
href="/cv?hideOnPrint=1" href="/cv?hideOnPrint=1"
target="_blank" target="_blank"
style="width: 7.5rem;" style="width: 7.5rem;"
class="text-center justify-center">Zhen CV</a class="text-center justify-center text-md"
>{$re?.nick ?? "Alex"}'s CV</a
> >
<!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> --> <!-- <a href="/tools" style="width: 7.5rem;" class="text-center">Tools</a> -->
<a href="https://botalex.itch.io/" target="_blank">Games</a> <a href="https://botalex.itch.io/" target="_blank">Games</a>

View file

@ -28,8 +28,9 @@
// import NameAndTag from "./comps/NameAndTag.svelte"; // import NameAndTag from "./comps/NameAndTag.svelte";
import Profile from "./comps/Profile.svelte"; import Profile from "./comps/Profile.svelte";
import DeprivedTrackerSection from "./comps/DeprivedTrackerSection.svelte"; import DeprivedTrackerSection from "./comps/DeprivedTrackerSection.svelte";
import re from "@src/ts/Redaction/Redactor";
const mobileThreshold: string = "600px"; // was 1000px. zhen testing const mobileThreshold: string = "600px"; // was 1000px.
let mobile: boolean; let mobile: boolean;
let debug = false; let debug = false;
@ -102,14 +103,15 @@
class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full" class="grid max-lg:grid-cols-1 sm:grid-cols-2 gap-4 p-4 max-lg:px-0 w-full"
> >
<Profile <Profile
name="Zhen / Alex" name={$re?.nick ? $re?.nick + "/Alex" : "Alex"}
tags={["Programmer", "3D artist", "UX Designer"]} tags={["Programmer", "3D artist", "UX Designer"]}
isMobile={mobile} isMobile={mobile}
> >
<span> <span>
<p> <p>
Hi, I am Alex/Zhen, {@html !mobile ? "" : "<br/>"} I'm that chinese Hi, I am {$re?.nick ? $re?.nick + "/Alex" : "Alex"}, {@html !mobile
guy. ? ""
: "<br/>"} I'm that chinese guy.
</p> </p>
<p> <p>
Here's my CV: <a href="/cv?hideOnPrint=1" style="color:lightblue;" Here's my CV: <a href="/cv?hideOnPrint=1" style="color:lightblue;"
@ -203,7 +205,6 @@
</div> </div>
<div class="py-4"></div> <div class="py-4"></div>
<div <div
class="grid place-content-center place-items-center pointer-events-auto font-mono" class="grid place-content-center place-items-center pointer-events-auto font-mono"
> >

View file

@ -4,6 +4,7 @@
import onDestroy from "@e/onDestroy"; import onDestroy from "@e/onDestroy";
import ArrowBigDown from "lucide-svelte/icons/arrow-big-down"; import ArrowBigDown from "lucide-svelte/icons/arrow-big-down";
import fly from "@e/fly"; import fly from "@e/fly";
import re from "@ts/Redaction/Redactor";
const buildTime = __BUILD_TIME__; const buildTime = __BUILD_TIME__;
let scrollY = 0; let scrollY = 0;
@ -156,16 +157,16 @@
/> />
<div class="{hideOnPrint ? 'hide-on-print' : ''} w-full"> <div class="{hideOnPrint ? 'hide-on-print' : ''} w-full">
<!-- Keep scrolling thing --> <!-- <!-- Keep scrolling thing --> -->
<div class="hidden h-64 w-full flex flex-col justify-center items-center"> <!-- <div class="hidden h-64 w-full flex flex-col justify-center items-center"> -->
<div>Keep scrolling to veiw Zhen's portfolio site!</div> <!-- <div>Keep scrolling to veiw [Redacted]'s portfolio site!</div> -->
<div class="flex justify-center"> <!-- <div class="flex justify-center"> -->
<ArrowBigDown /> <!-- <ArrowBigDown /> -->
<ArrowBigDown /> <!-- <ArrowBigDown /> -->
<ArrowBigDown /> <!-- <ArrowBigDown /> -->
<ArrowBigDown /> <!-- <ArrowBigDown /> -->
</div> <!-- </div> -->
</div> <!-- </div> -->
<div <div
class="hidden h-64 w-full flex flex-col justify-end items-center" class="hidden h-64 w-full flex flex-col justify-end items-center"
@ -193,7 +194,7 @@
<br /> <br />
<span>Snorre Ettrup Altschul</span> <span>Snorre Ettrup Altschul</span>
<br /> <br />
<span>Zhentao Wei</span> <span>{$re?.name ?? "BOT Alex"}</span>
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<h3><b>About this website</b></h3> <h3><b>About this website</b></h3>
@ -221,7 +222,9 @@
</div> </div>
<div class="flex flex-col items-center"> <div class="flex flex-col items-center">
<h3><b>Contact</b></h3> <h3><b>Contact</b></h3>
<a href="mailto:zhen@deprived.dev">zhen@deprived.dev</a> <a href="mailto:{$re?.email ?? 'Alex@deprived.dev'}"
>{$re?.email ?? "alex@deprived.dev"}</a
>
<div class="mt-2"></div> <div class="mt-2"></div>
<a <a
href="https://discord.gg/awatEEqc3M" href="https://discord.gg/awatEEqc3M"

View file

@ -19,6 +19,7 @@ const EducationLoose = z.object({
const ProfileSchema = z.object({ const ProfileSchema = z.object({
name: z.string().min(1), name: z.string().min(1),
nick: z.string().min(1),
shortProfileHiddenContent: z.array(z.string()), shortProfileHiddenContent: z.array(z.string()),
email: z.string().email(), email: z.string().email(),
phone: z.string().min(1), phone: z.string().min(1),

View file

@ -1,56 +1,62 @@
// redactor.ts
import { parseProfile, type Profile } from "./Profile"; import { parseProfile, type Profile } from "./Profile";
import env from "@ts/EnvHandler"; import env, { initEnv } from "@ts/EnvHandler";
import { initEnv } from "@ts/EnvHandler"; import type { Readable, Subscriber, Unsubscriber } from "svelte/store";
class Redactor { class Redactor implements Readable<Profile | undefined> {
public unredactedProfile: Profile | undefined = undefined; public unredactedProfile: Profile | undefined = undefined;
private subs = new Set<Subscriber<Profile | undefined>>();
subscribe(run: Subscriber<Profile | undefined>): Unsubscriber {
this.subs.add(run);
run(this.unredactedProfile);
return () => this.subs.delete(run);
}
private notify() {
this.subs.forEach((s) => s(this.unredactedProfile));
}
async TryGetUnredacter(): Promise<Profile> { async TryGetUnredacter(): Promise<Profile> {
if (!!this.unredactedProfile) return this.unredactedProfile; if (this.unredactedProfile) return this.unredactedProfile;
const storedKey = localStorage.getItem("key"); const storedKey = localStorage.getItem("key");
if (!storedKey) throw new Error("Missing key"); if (!storedKey) throw new Error("Missing key");
let jsonKey = JSON.stringify({ key: storedKey });
console.log("Requesting unredactor.json with: " + jsonKey);
const hashResJson = await ( const hashResJson = await (
await fetch("https://api.deprived.dev/unredact", { await fetch("https://api.deprived.dev/unredact", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: jsonKey, body: JSON.stringify({ key: storedKey }),
}) })
).json(); ).json();
const unredactHash = hashResJson.response; const unredactHash = hashResJson.response;
console.log('Trying unredact hash: "' + unredactHash + '"');
initEnv(); initEnv();
const url = `${env.POCKETBASE_URL}/api/files/redacted_content/${unredactHash}/redacted_cv_info_ha08bbn520.json`; const url = `${env.POCKETBASE_URL}/api/files/redacted_content/${unredactHash}/redacted_cv_info_amhz90nhr7.json`;
const res = await fetch(url, { const res = await fetch(url, {
method: "GET", method: "GET",
headers: { Accept: "application/json" }, headers: { Accept: "application/json" },
}); });
if (!res.ok) throw new Error(`HTTP ${res.status}`); if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json(); const data = await res.json();
return parseProfile(data); this.unredactedProfile = parseProfile(data);
this.notify(); // <-- tell Svelte to update
return this.unredactedProfile;
} }
async t(unredactPath: string, fallback: string): Promise<string> { t(path: string, fallback: string): string {
try { try {
if (!this.unredactedProfile) await this.TryGetUnredacter(); const src = this.unredactedProfile as Record<string, unknown> | undefined;
const src = this.unredactedProfile ?? {}; if (!src) return fallback;
const v = path.split(".").reduce<any>((o, k) => (o as any)?.[k], src);
// safe dot-path lookup return (v ?? "") !== "" ? String(v) : fallback;
const value = unredactPath.split(".").reduce<any>((o, k) => o?.[k], src);
return (value ?? "") !== "" ? String(value) : fallback;
} catch { } catch {
return fallback; return fallback;
} }
} }
} }
export let re = new Redactor(); export const re = new Redactor();
export default re;