refactor(server/utils): create reusable utilities for various story-related functions

`bodyHandler` takes a request body and returns the chapter content as a string
`formChapterTransform` serializes a chapter-like object supplied in a request body to an actual
	proper chapter object
`getBucket` retrieves the story content gridfs bucket
`replaceGridFS` either creates or updates (deletes + reuploads) a gridfs file
This commit is contained in:
☙◦ The Tablet ❀ GamerGirlandCo ◦❧ 2023-10-03 00:37:46 -04:00
parent 1338e87238
commit c8bdcc0ec3
Signed by: tablet
GPG Key ID: 924A5F6AF051E87C
4 changed files with 88 additions and 86 deletions

View File

@ -1,38 +1,38 @@
import { extname, resolve } from "path"; import { extname, resolve } from "path";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import { marked } from "marked"; import { marked } from "marked";
import * as mammoth from "mammoth"; import * as mammoth from "mammoth";
import * as san from "sanitize-html"; import * as san from "sanitize-html";
import { sanitizeConf } from "../constants"; import { sanitizeConf } from "../constants";
import { FormChapter } from "~/lib/client/types/FormStory"; import { FormChapter } from "~/lib/client/types/form/story";
export default async function (bodyObj: FormChapter): Promise<string> { export default async function (bodyObj: FormChapter): Promise<string> {
let str: string = ""; let str: string = "";
if (bodyObj.content) { if (bodyObj.content) {
str = bodyObj.content; str = bodyObj.content;
} else if (bodyObj.file) { } else if (bodyObj.file) {
let ext = extname(bodyObj.file).toLowerCase(); let ext = extname(bodyObj.file).toLowerCase();
if (ext === "md" || ext === "markdown") if (ext === "md" || ext === "markdown")
str = marked.parse( str = marked.parse(
readFileSync(resolve(`tmp/${bodyObj.file}`)).toString(), readFileSync(resolve(`tmp/${bodyObj.file}`)).toString(),
); );
else if (ext === "doc" || ext === "docx") else if (ext === "doc" || ext === "docx")
str = ( str = (
await mammoth.convertToHtml( await mammoth.convertToHtml(
{ path: resolve(`tmp/${bodyObj.file}`) }, { path: resolve(`tmp/${bodyObj.file}`) },
{ styleMap: ["b => b", "i => i", "u => u"] }, { styleMap: ["b => b", "i => i", "u => u"] },
) )
).value; ).value;
else else
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: "bad file type", message: "bad file type",
}); });
} else { } else {
throw createError({ throw createError({
statusCode: 400, statusCode: 400,
message: "no content", message: "no content",
}); });
} }
return san(str, sanitizeConf); return san(str, sanitizeConf);
} }

View File

@ -1,23 +1,22 @@
import san from "sanitize-html"; import san from "sanitize-html";
import { FormChapter } from "~/lib/client/types/FormStory"; import { FormChapter } from "~/lib/client/types/form/story";
import { countWords } from "~/lib/functions"; import { countWords } from "~/lib/functions";
import { IChapter } from "~/models/stories/chapter"; import { IChapter } from "~/models/stories/chapter";
import { sanitizeConf } from "../constants"; import { sanitizeConf } from "../constants";
import bodyHandler from "./bodyHandler"; import bodyHandler from "./bodyHandler";
export default function (c: FormChapter): IChapter {
export default function(c: FormChapter): IChapter { let t: IChapter = {
let t: IChapter = { title: c.chapterTitle,
title: c.chapterTitle, summary: san(c.summary, sanitizeConf),
summary: san(c.summary, sanitizeConf), notes: san(c.notes, sanitizeConf),
notes: san(c.notes, sanitizeConf), bands: c.bands,
bands: c.bands, characters: c.characters,
characters: c.characters, relationships: c.relationships,
relationships: c.relationships, nsfw: c.nsfw,
nsfw: c.nsfw, genre: c.genre,
genre: c.genre, loggedInOnly: c.loggedInOnly,
loggedInOnly: c.loggedInOnly, hidden: c.hidden,
hidden: c.hidden };
} return t;
return t; }
}

View File

@ -1,9 +1,9 @@
import { GridFSBucket } from "mongodb"; import { GridFSBucket } from "mongodb";
import mongoose from "mongoose"; import mongoose from "mongoose";
export default function () { export default function () {
// @ts-ignore SHUT UP MEG // @ts-ignore SHUT UP MEG
return new GridFSBucket(mongoose.connection.db, { return new GridFSBucket(mongoose.connection.db, {
bucketName: "story_text", bucketName: "story_text",
}); });
} }

View File

@ -1,16 +1,19 @@
import getBucket from "./getBucket"; import getBucket from "./getBucket";
import {Readable} from "stream" import { Readable } from "stream";
export default async function replaceGridFS(chapterID: number | undefined, content: string) { export default async function replaceGridFS(
let filename = `/stories/${chapterID}.txt`; chapterID: number | undefined,
const bucket = getBucket() content: string,
if(chapterID) { ) {
const curs = bucket.find({filename}).limit(1) let filename = `/stories/${chapterID}.txt`;
for await(const d of curs) { const bucket = getBucket();
await bucket.delete(d._id); if (chapterID) {
} const curs = bucket.find({ filename }).limit(1);
} for await (const d of curs) {
const readable = new Readable(); await bucket.delete(d._id);
readable.push(content); }
readable.push(null); }
readable.pipe(bucket.openUploadStream(filename)); const readable = new Readable();
} readable.push(content);
readable.push(null);
readable.pipe(bucket.openUploadStream(filename));
}