import path from 'path' import striptags from 'striptags' import Parent from '../base/serve.mjs' import fs from 'fs/promises' import config from '../base/config.mjs' export default class ServeHandler extends Parent { traverseTree(set, tree) { for (let branch of tree) { if (branch.children && branch.children.length) { set.add(branch.id) this.traverseTree(set, branch.children) } } } getDescriptionFromBlocks(blocks) { return encodeURI(blocks .filter(x => x.type === 'header' || x.type === 'paragraph' || x.type === 'quote' || x.type === 'list' || x.type === 'code' || x.type === 'htmlraw') .map(x => { if (x.type === 'htmlraw') { return striptags(x.data.html) } if (x.type === 'quote') { return `"${x.data.text}"` + (x.data.caption ? ` - ${x.data.caption}` : '') } if (x.type === 'list') { return x.data.items.join('. ') } return x.data.code ? `"${x.data.code}"` : x.data.text }) .map(x => striptags(x)) .map(x => { console.log(x) return x }) .filter(x => x) .join('. ') .replace('/\.+/g', '.') ) } async serveIndex(ctx) { if (config.get('NODE_ENV') === 'development') { let indexFile = await fs.readFile(path.join(this.root, 'index.html')) this.loadTemplate(indexFile) } let payload = { headerDescription: 'A small fansubbing and scanlation group translating and encoding our favourite shows from Japan.', headerImage: this.frontend + '/assets/img/heart.png', headerTitle: 'NFP Moe - Anime/Manga translation group', headerUrl: this.frontend + ctx.url, payloadData: null, payloadTree: null, version: this.version, nonce: ctx.state.nonce, type: 'page', banner: false, media: false, in_debug: config.get('NODE_ENV') === 'development' && false, } try { let tree = await this.pageRoutes.getPageTree(ctx, true) let setOfBranches = new Set() this.traverseTree(setOfBranches, tree.tree) payload.payloadTree = JSON.stringify(tree) if (ctx.url === '/' || (ctx.url.startsWith('/page/') && ctx.url.lastIndexOf('/') === 5)) { ctx.params.path = null if (ctx.url.lastIndexOf('/') === 5) { ctx.params.path = ctx.url.slice(ctx.url.lastIndexOf('/') + 1) } let data = await this.pageRoutes.getPage(ctx, true) if (!data.page) { payload.type = 'frontpage' } else if (setOfBranches.has(data.page.id)) { payload.type = 'page_with_children' } if (data.page) { payload.headerTitle = data.page.name + ' - NFP Moe' payload.headerDescription = 'Page ' + data.page.name + ' over at NFP Moe. ' + payload.headerDescription if (data.page.content.blocks?.length) { payload.headerDescription = this.getDescriptionFromBlocks(data.page.content.blocks) || payload.headerDescription } if (data.page.media_alt_prefix) { payload.headerImage = data.page.media_alt_prefix + '_small.jpg' } } payload.media = data.page?.media_avif_preview || false payload.banner = data.featured?.banner_avif_preview || data.page?.banner_avif_preview || false payload.payloadData = JSON.stringify(data) } else if (ctx.url.startsWith('/article/') && ctx.url.lastIndexOf('/') === 8) { ctx.params.path = ctx.url.slice(ctx.url.lastIndexOf('/') + 1) let data = await this.articleRoutes.getArticle(ctx, true) if (data.article) { payload.headerTitle = data.article.name + ' - NFP Moe' if (data.article.content.blocks.length) { payload.headerDescription = this.getDescriptionFromBlocks(data.article.content.blocks) || payload.headerDescription } if (data.article.media_alt_prefix) { payload.headerImage = data.article.media_alt_prefix + '_small.jpg' } } payload.media = data.article?.media_avif_preview || false payload.payloadData = JSON.stringify(data) payload.type = 'article' } else if (ctx.url !== '/login' && !ctx.url.startsWith('/admin/')) { ctx.status = 404 } } catch (e) { ctx.log.error(e) } ctx.body = this.template(payload) ctx.type = 'text/html; charset=utf-8' } }