import { parseDocument } from "@lib/documents.ts"; import { parse, stringify } from "yaml"; import { createCrud } from "@lib/crud.ts"; import { extractHashTags, formatDate } from "@lib/string.ts"; import { fixRenderedMarkdown } from "@lib/helpers.ts"; export type Movie = { id: string; name: string; description: string; type: "movie"; tags: string[]; meta: { date: Date; tmdbId?: number; keywords?: string[]; image: string; thumbnail?: string; average?: string; author: string; rating: number; }; }; export function renderMovie(movie: Movie) { const meta = movie.meta; if ("date" in meta && typeof meta.date !== "string") { meta.date = formatDate(meta.date) as unknown as Date; } delete meta.thumbnail; delete meta.average; const movieImage = `![](${movie.meta.image})`; return fixRenderedMarkdown(`${ meta ? `--- ${stringify(meta)} ---` : `--- ---` } # ${movie.name} ${ // So we do not add a new image to the description everytime we render (movie.meta.image && !movie.description.includes(movieImage)) ? movieImage : ""} ${movie.tags.map((t) => `#${t}`).join(" ")} ${movie.description} `); } export function parseMovie(original: string, id: string): Movie { const doc = parseDocument(original); let meta = {} as Movie["meta"]; let name = ""; const range = [Infinity, -Infinity]; for (const child of doc.children) { if (child.type === "yaml") { try { meta = (parse(child.value) || {}) as Movie["meta"]; } catch (_) { // ignore here } if (meta["rating"] && typeof meta["rating"] === "string") { meta.rating = [...meta.rating?.matchAll("⭐")].length; } continue; } if ( child.type === "heading" && child.depth === 1 && !name && child.children.length === 1 && child.children[0].type === "text" ) { name = child.children[0].value; continue; } if (name) { const start = child.position?.start.offset || Infinity; const end = child.position?.end.offset || -Infinity; if (start < range[0]) range[0] = start; if (end > range[1]) range[1] = end; } } let description = original.slice(range[0], range[1]); const tags = extractHashTags(description); for (const tag of tags) { description = description.replace("#" + tag, ""); } return { type: "movie", id, name, tags, description, meta, }; } const crud = createCrud({ prefix: "Media/movies/", parse: parseMovie, render: renderMovie, hasThumbnails: true, }); export const getMovie = async (id: string) => { const movie = await crud.read(id); return movie; }; export const getAllMovies = crud.readAll; export const createMovie = crud.create;