From b052f741d935abd2f51423abf3fcda9157844b5c Mon Sep 17 00:00:00 2001 From: "netop://ウィビ" Date: Sat, 11 Apr 2026 14:42:43 -0700 Subject: initial commit --- src/routes/api/blog.json/+server.ts | 51 ++++++++++++++++++++++ src/routes/api/cv.json/+server.ts | 75 +++++++++++++++++++++++++++++++++ src/routes/api/mastodon.json/+server.ts | 55 ++++++++++++++++++++++++ src/routes/api/remarks.json/+server.ts | 51 ++++++++++++++++++++++ 4 files changed, 232 insertions(+) create mode 100644 src/routes/api/blog.json/+server.ts create mode 100644 src/routes/api/cv.json/+server.ts create mode 100644 src/routes/api/mastodon.json/+server.ts create mode 100644 src/routes/api/remarks.json/+server.ts (limited to 'src/routes/api') diff --git a/src/routes/api/blog.json/+server.ts b/src/routes/api/blog.json/+server.ts new file mode 100644 index 0000000..f416647 --- /dev/null +++ b/src/routes/api/blog.json/+server.ts @@ -0,0 +1,51 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { error, json } from "@sveltejs/kit"; + +/*** EXPORT ------------------------------------------- ***/ + +export const POST = async({ fetch, request }) => { + try { + const { filename } = await request.json(); + + const response = await fetch(`https://blog.webb.page/${String(filename)}`, { + headers: { "Content-Type": "text/plain" }, + method: "GET" + }); + + const memo = parseMemo(await response.text()); + memo.push(` [READ]`, "\n"); + + return json({ content: memo.join("\n") }); + } catch(welp) { + console.error(`Error fetching memo: ${String(welp)}`); + return error(500); + } +}; + +/*** HELPER ------------------------------------------- ***/ + +function parseMemo(text: string): string { + const intro = text.split(/^Body$/m)[0]; + const lines = intro.split("\n").filter(Boolean); + const format = [""]; + let firstLine = ""; + + lines.map((line, index) => { + if (index === 1) + firstLine = " " + line.split(/\s+\B/)[1].trim(); + + if (index === 2) { + firstLine += ` • ${line.trim()}`; + format.push(firstLine); + } + + if (index === 4) + format.push(" " + line.trim()); + }); + + return format; +} diff --git a/src/routes/api/cv.json/+server.ts b/src/routes/api/cv.json/+server.ts new file mode 100644 index 0000000..956525f --- /dev/null +++ b/src/routes/api/cv.json/+server.ts @@ -0,0 +1,75 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { error, json } from "@sveltejs/kit"; + +/*** EXPORT ------------------------------------------- ***/ + +export const POST = async({ fetch, request }) => { + try { + const response = await fetch("https://cv.webb.page", { + headers: { "Content-Type": "text/plain" }, + method: "GET" + }); + + const content = await response.text(); + return json({ content: processCV(content) }); + } catch(welp) { + console.error(`Error fetching CV: ${String(welp)}`); + return error(500); + } +}; + +/*** HELPER ------------------------------------------- ***/ + +function processCV(text) { + const sections = text.split(/(^░▒▓[\s\S]*?^---$)/m); + const intro = sections[1]; + const body = sections[2]; + const lines = body.split(/\n{2,}/); + const table = processTable(body); + + const processedLines = lines.map(line => { + if (line.includes("Proficiency") && line.includes("Notes")) + return table.join("").trim(); + + return line.replace(/\s+/g, " "); + }); + + return intro + processedLines.join("\n\n") + "\n\n\n"; +} + +function processTable(text) { + const lines = text.split(/\r?\n/); + const tableStartIndex = lines.findIndex(line => line.includes("|")); + + if (tableStartIndex === -1) + return null; + + const separatorLineIndex = lines.findIndex((line, index) => index > tableStartIndex && line.includes("|-") || line.includes("| -")); + + if (separatorLineIndex === -1) + return null; + + let tableEndIndex = separatorLineIndex + 1; + + while (tableEndIndex < lines.length && lines[tableEndIndex].includes("|")) { + tableEndIndex++; + } + + const contentRows = lines.slice(separatorLineIndex + 1, tableEndIndex); + + return contentRows.map(row => { + let cells = row.split("|").map(cell => cell.trim()); + + if (cells[0] === "") + cells.shift(); + + if (cells[cells.length - 1] === "") + cells.pop(); + + return cells.join(" / ") + "\n"; + }); +} diff --git a/src/routes/api/mastodon.json/+server.ts b/src/routes/api/mastodon.json/+server.ts new file mode 100644 index 0000000..72cbd38 --- /dev/null +++ b/src/routes/api/mastodon.json/+server.ts @@ -0,0 +1,55 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { error, json } from "@sveltejs/kit"; + +/*** EXPORT ------------------------------------------- ***/ + +export const POST = async({ fetch }) => { + try { + const response = await fetch("https://social.coop/users/netopwibby/outbox?page=true", { + headers: { "Content-Type": "application/json" }, + method: "GET" + }); + + const { orderedItems } = await response.json(); + const { object } = findCreateType(orderedItems); + + return json({ + created: object.published, + content: object.content, + link: object.url, + media: processAttachments(object.attachment) + }); + } catch(welp) { + console.error(`Error fetching latest Mastodon post: ${String(welp)}`); + return error(500); + } +}; + +/*** HELPER ------------------------------------------- ***/ + +function findCreateType(arr: Array<{ [key: string]: any }>): { [key: string]: any } | undefined { + return arr.find(obj => obj.type === "Create"); +} + +function processAttachments(attachments: Array<{ [key: string]: any }>): Array { + const media = []; + + if (attachments) { + for (const attachment of attachments) { + // TODO + // : use blurhash given to us by mastodon + // : https://github.com/woltapp/blurhash/tree/master/TypeScript#example + // : `attachment` comes with blurhash, height, mediaType, width + // if (attachment && attachment.url) + + // @ts-ignore | Argument of type "any" is not assignable to parameter of type "never". + media.push(attachment.url); + } + } + + return media; +} diff --git a/src/routes/api/remarks.json/+server.ts b/src/routes/api/remarks.json/+server.ts new file mode 100644 index 0000000..c708207 --- /dev/null +++ b/src/routes/api/remarks.json/+server.ts @@ -0,0 +1,51 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + +import { error, json } from "@sveltejs/kit"; + +/*** EXPORT ------------------------------------------- ***/ + +export const POST = async({ fetch, request }) => { + try { + const { filename } = await request.json(); + + const response = await fetch("https://blog.webb.page/remarks/" + String(filename), { + headers: { "Content-Type": "text/plain" }, + method: "GET" + }); + + const remark = parseRemark(await response.text()); + remark.push(` [READ]`, "\n"); + + return json({ content: remark.join("\n") }); + } catch(welp) { + console.error(`Error fetching remark: ${String(welp)}`); + return error(500); + } +}; + +/*** HELPER ------------------------------------------- ***/ + +function parseRemark(text: string): string { + const intro = text.split(/^Body$/m)[0]; + const lines = intro.split("\n").filter(Boolean); + const format = [""]; + let firstLine = ""; + + lines.map((line, index) => { + if (index === 1) + firstLine = " " + line.split(/\s+\B/)[1].trim(); + + if (index === 2) { + firstLine += ` • ${line.trim()}`; + format.push(firstLine); + } + + if (index === 4) + format.push(" " + line.trim()); + }); + + return format; +} -- cgit v1.2.3