Migrate to Astro 5
This commit is contained in:
parent
5d701069e9
commit
bb1e533a00
129 changed files with 1408 additions and 1448 deletions
|
|
@ -1,167 +0,0 @@
|
|||
import type { APIRoute, GetStaticPaths } from "astro";
|
||||
import { getCollection, type CollectionEntry, getEntries } from "astro:content";
|
||||
import type { PostWebsite } from "@content/config";
|
||||
import { t } from "@i18n";
|
||||
import { formatCopyrightedCharacters } from "@utils/format_copyrighted_characters";
|
||||
import { markdownToBbcode } from "@utils/markdown_to_bbcode";
|
||||
import { getUsernameForLang } from "@utils/get_username_for_lang";
|
||||
import { isAnonymousUser } from "@utils/is_anonymous_user";
|
||||
import { qualifyLocalURLsInMarkdown } from "@utils/qualify_local_urls_in_markdown";
|
||||
import { getWebsiteLinkForUser } from "@utils/get_website_link_for_user";
|
||||
import { toPlainMarkdown } from "@utils/to_plain_markdown";
|
||||
|
||||
interface ExportWebsiteInfo {
|
||||
website: PostWebsite;
|
||||
exportFormat: "bbcode" | "markdown";
|
||||
}
|
||||
|
||||
const WEBSITE_LIST = [
|
||||
{ website: "eka", exportFormat: "bbcode" },
|
||||
{ website: "furaffinity", exportFormat: "bbcode" },
|
||||
{ website: "inkbunny", exportFormat: "bbcode" },
|
||||
{ website: "sofurry", exportFormat: "bbcode" },
|
||||
{ website: "weasyl", exportFormat: "markdown" },
|
||||
] as const satisfies ExportWebsiteInfo[];
|
||||
|
||||
type ExportWebsiteName = typeof WEBSITE_LIST extends ReadonlyArray<{ website: infer K }> ? K : never;
|
||||
|
||||
export type ExportStoryResponse = {
|
||||
story: string;
|
||||
description: Record<string, string>;
|
||||
thumbnail: string | null;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
story: CollectionEntry<"stories">;
|
||||
};
|
||||
|
||||
type Params = {
|
||||
slug: CollectionEntry<"stories">["slug"];
|
||||
};
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
if (import.meta.env.PROD) {
|
||||
return [];
|
||||
}
|
||||
return (await getCollection("stories")).map((story) => ({
|
||||
params: { slug: story.slug } satisfies Params,
|
||||
props: { story } satisfies Props,
|
||||
}));
|
||||
};
|
||||
|
||||
export const GET: APIRoute<Props, Params> = async ({ props: { story }, site }) => {
|
||||
try {
|
||||
const { lang } = story.data;
|
||||
const copyrightedCharacters = await formatCopyrightedCharacters(story.data.copyrightedCharacters);
|
||||
const authorsList = await getEntries(story.data.authors);
|
||||
const commissionersList = story.data.commissioners && (await getEntries(story.data.commissioners));
|
||||
const requestersList = story.data.requesters && (await getEntries(story.data.requesters));
|
||||
|
||||
const description = await Promise.all(
|
||||
WEBSITE_LIST.map(async ({ website, exportFormat }) => {
|
||||
const exportWebsite: ExportWebsiteName = website;
|
||||
const u = (user: CollectionEntry<"users">) =>
|
||||
isAnonymousUser(user)
|
||||
? getUsernameForLang(user, lang)
|
||||
: getWebsiteLinkForUser(user, exportWebsite, (user) => getUsernameForLang(user, lang));
|
||||
const storyDescription = await [
|
||||
story.data.description,
|
||||
`*${t(lang, "story/warnings", story.data.wordCount, story.data.contentWarning)}*`,
|
||||
t(
|
||||
lang,
|
||||
"export_story/authors",
|
||||
authorsList.map((author) => u(author)),
|
||||
),
|
||||
requestersList &&
|
||||
t(
|
||||
lang,
|
||||
"export_story/request_for",
|
||||
requestersList.map((requester) => u(requester)),
|
||||
),
|
||||
commissionersList &&
|
||||
t(
|
||||
lang,
|
||||
"export_story/commissioned_by",
|
||||
commissionersList.map((commissioner) => u(commissioner)),
|
||||
),
|
||||
...copyrightedCharacters.map(({ user, characters }) =>
|
||||
t(lang, "characters/characters_are_copyrighted_by", u(user), characters[0] === "" ? [] : characters),
|
||||
),
|
||||
].reduce(async (promise, data) => {
|
||||
if (!data) {
|
||||
return promise;
|
||||
}
|
||||
const acc = await promise;
|
||||
const newData = await qualifyLocalURLsInMarkdown(data, lang, site, exportWebsite);
|
||||
return `${acc}\n\n${newData}`;
|
||||
}, Promise.resolve(""));
|
||||
switch (exportFormat) {
|
||||
case "bbcode":
|
||||
return {
|
||||
descriptionFilename: `description_${exportWebsite}.txt`,
|
||||
descriptionText: markdownToBbcode(storyDescription).replaceAll(/\n\n\n+/g, "\n\n"),
|
||||
};
|
||||
case "markdown":
|
||||
return {
|
||||
descriptionFilename: `description_${exportWebsite}.md`,
|
||||
descriptionText: toPlainMarkdown(storyDescription)
|
||||
.replaceAll(/\n\n\n+/g, "\n\n")
|
||||
.trim(),
|
||||
};
|
||||
default:
|
||||
const unknown: never = exportFormat;
|
||||
throw new Error(`Unknown export format "${unknown}"`);
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
const storyHeader =
|
||||
`${story.data.title}\n` +
|
||||
`${t(
|
||||
lang,
|
||||
"story/authors",
|
||||
authorsList.map((author) => getUsernameForLang(author, lang)),
|
||||
)}\n` +
|
||||
(requestersList
|
||||
? `${t(
|
||||
lang,
|
||||
"story/requested_by",
|
||||
requestersList.map((requester) => getUsernameForLang(requester, lang)),
|
||||
)}\n`
|
||||
: "") +
|
||||
(commissionersList
|
||||
? `${t(
|
||||
lang,
|
||||
"story/commissioned_by",
|
||||
commissionersList.map((commissioner) => getUsernameForLang(commissioner, lang)),
|
||||
)}\n`
|
||||
: "");
|
||||
|
||||
const storyText = `${storyHeader}\n===\n\n${story.body.replaceAll(/\\([=*])/g, "$1")}`
|
||||
.replaceAll(/\n\n\n+/g, "\n\n")
|
||||
.trim();
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
story: storyText,
|
||||
description: description.reduce(
|
||||
(acc, item) => {
|
||||
acc[item.descriptionFilename] = item.descriptionText;
|
||||
return acc;
|
||||
},
|
||||
{} as Record<string, string>,
|
||||
),
|
||||
thumbnail: story.data.thumbnail ? story.data.thumbnail.src : null,
|
||||
} satisfies ExportStoryResponse),
|
||||
{ headers: { "Content-Type": "application/json; charset=utf-8" } },
|
||||
);
|
||||
} catch (e) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
message: (e as Error).message ?? null,
|
||||
stack: (e as Error).stack ?? null,
|
||||
}),
|
||||
{ status: 500, headers: { "Content-Type": "application/json; charset=utf-8" } },
|
||||
);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue