forked from nm3clol/nm3clol-express-app
290 lines
11 KiB
JavaScript
290 lines
11 KiB
JavaScript
console.log(`Starting up nm3clol-express-app...`);
|
|
|
|
const express = require('express');
|
|
const axios = require('axios');
|
|
const app = express();
|
|
const serve = require('./vercel-serve');
|
|
const path = require('path');
|
|
const glob = require('glob');
|
|
const matter = require('gray-matter');
|
|
const ejs = require('ejs');
|
|
const { config } = require('./config');
|
|
const helpers = require('../views/helpers/functions');
|
|
const search = require('./routes/search');
|
|
const fs = require('fs');
|
|
// const advancedSearch = require('../routes/advanced-search');
|
|
|
|
console.log(`Running app configuration:`, config);
|
|
|
|
// Set EJS as the view engine
|
|
app.set('view engine', 'ejs');
|
|
|
|
// Specify the views directory
|
|
app.set('views', path.join(__dirname, '..', 'views'));
|
|
|
|
// Middleware to parse JSON request body
|
|
app.use(express.json());
|
|
|
|
// Middleware to rewrite requests
|
|
//app.use(rewriter);
|
|
|
|
// // Serve static files (CSS, JavaScript, images, etc.)
|
|
// app.use(serve('../public', {
|
|
// dotfiles: 'ignore',
|
|
// index: false,
|
|
// }));
|
|
|
|
// app.get('/', (req, res) => {
|
|
// res.send('Hello World!');
|
|
// })
|
|
|
|
// console.log("Setting route for /ads.txt");
|
|
// app.get('/ads.txt', (req, res) => {
|
|
// res.setHeader("Content-Type", "text/plain");
|
|
// res.setHeader("Cache-Control", "no-cache");
|
|
// res.send(`google.com, pub-8937572456576531, DIRECT, f08c47fec0942fa0`);
|
|
// });
|
|
|
|
console.log(`Serving /robots.txt from memory.`);
|
|
app.get('/robots.txt', (req, res) => {
|
|
res.setHeader("Content-Type", "text/plain");
|
|
res.setHeader("Cache-Control", "no-cache");
|
|
// TODO: Implement Site Map feature and provide sitemap url in robots.txt
|
|
res.send(
|
|
`User-agent: *
|
|
Allow: /
|
|
|
|
# TODO: Implement Site Map feature and provide sitemap url in robots.txt
|
|
#sitemap: https://no-moss-3-carbo-landfill-library.online/sitemap.xml`
|
|
);//end of res.send() for robots.txt
|
|
});
|
|
|
|
// Search endpoints
|
|
console.log(`Serving /search using search router.`);
|
|
app.use('/search', search.router);
|
|
// app.use('/advanced-search', advancedSearch.router);
|
|
|
|
// Endpoints for all the site's pages.
|
|
console.log(`Scanning for pages in ${config.pagesPath} to create routes.`);
|
|
glob.globSync('**/*.md', {
|
|
cwd: config.pagesPath,
|
|
matchBase: true,
|
|
follow: true,
|
|
}).forEach((filePath) => {
|
|
const expressRoutePathFromFilePath = (filePath) => {
|
|
filePath = filePath.substring(0, filePath.length - path.extname(filePath).length).replaceAll(path.sep, path.posix.sep);
|
|
if (!filePath.startsWith('/') && filePath.length > 0) {
|
|
filePath = `/${filePath}`;
|
|
}
|
|
return filePath;
|
|
};
|
|
const route = expressRoutePathFromFilePath(filePath);
|
|
const fullFilePath = path.join(config.pagesPath, filePath);
|
|
let paths = route.split(path.posix.sep);
|
|
paths[0] = 'public';
|
|
console.log(`Serving ${route} route as a page at ${fullFilePath}.`);
|
|
app.get(route, async (req, res) => {
|
|
const fm = matter.read(fullFilePath);
|
|
const fmData = { fm: fm.data, excerpt: fm.excerpt };
|
|
const content = helpers.md.render(fm.content, fmData );
|
|
const renderData = { content, route, filePath, fullFilePath, req, paths, ...fmData };
|
|
res.render("page", { h: helpers, require, ...renderData });
|
|
});
|
|
});
|
|
|
|
// console.log("Scanning for documents to create routes.");
|
|
// glob.globSync('**/*{.pdf,.docx,.xlsx,.pptx,.doc,.xls,.ppt}', {
|
|
// cwd: path.join(__dirname, '..', 'public'),
|
|
// matchBase: true,
|
|
// follow: true,
|
|
// }).forEach((filePath) => {
|
|
// const expressRoutePathFromFilePath = (filePath) => {
|
|
// return filePath.substring(0, filePath.length - path.extname(filePath).length).replaceAll(path.sep, path.posix.sep);
|
|
// };
|
|
// const route = expressRoutePathFromFilePath(filePath);
|
|
// const fullFilePath = path.join(__dirname, '..', 'public', filePath);
|
|
// let paths = route.split(path.posix.sep);
|
|
// paths[0] = 'public';
|
|
// console.log(`Setting route for ${route}`);
|
|
// app.get(route, async (req, res) => {
|
|
// const fm = matter.read(fullFilePath);
|
|
// const fmData = { fm: fm.data, excerpt: fm.excerpt };
|
|
// const content = helpers.md.render(fm.content, fmData );
|
|
// const renderData = { content, route, filePath, fullFilePath, req, paths, ...fmData };
|
|
// res.render("page", { h: helpers, ...renderData });
|
|
// });
|
|
// });
|
|
|
|
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
|
|
console.log("Scanning for web archive HTML documents to create routes.");
|
|
glob.globSync('Web_Site_Archives/**/*{.htm,.html}', {
|
|
cwd: path.join(__dirname, '..', 'public'),
|
|
matchBase: true,
|
|
follow: true,
|
|
}).forEach((filePath) => {
|
|
const expressRoutePathFromFilePath = (filePath) => {
|
|
return '/' + filePath.replaceAll(path.sep, path.posix.sep);
|
|
};
|
|
const route = expressRoutePathFromFilePath(filePath);
|
|
const fullFilePath = path.join(__dirname, '..', 'public', filePath);
|
|
let paths = route.split(path.posix.sep);
|
|
paths[0] = 'public';
|
|
console.log(`Setting route for ${route}`);
|
|
app.get(route, async (req, res) => {
|
|
const html = fs.readFileSync(fullFilePath).toString();
|
|
const renderData = { route, filePath, fullFilePath, req, paths, html };
|
|
res.render("archive", { h: helpers, ...renderData });
|
|
});
|
|
});
|
|
|
|
|
|
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
|
|
console.log("Scanning for archived videos to create routes.");
|
|
glob.globSync(['Russell_County/Board_of_Supervisors/YouTube_Archive/**/*.info.json', 'Virginia_Energy/YouTube_Archive/**/*.info.json', 'Virginia_Governor/**/*.info.json'], {
|
|
cwd: path.join(__dirname, '..', 'public'),
|
|
matchBase: true,
|
|
follow: true,
|
|
}).forEach((filePath) => {
|
|
const expressRoutePathFromFilePath = (filePath) => {
|
|
return path.posix.sep+filePath.substring(0, filePath.lastIndexOf(path.sep)).replaceAll(path.sep, path.posix.sep);
|
|
};
|
|
const dirFromFilePath = (filePath) => {
|
|
return filePath.substring(0, filePath.lastIndexOf(path.sep));
|
|
}
|
|
const directory = dirFromFilePath(filePath);
|
|
let videoURL = ""+glob.globSync("*.{mpg,mpeg,mp4,mkv,webm}", {
|
|
cwd: path.join(__dirname, '..', 'public', directory),
|
|
matchBase: true,
|
|
follow: true,
|
|
}).pop();
|
|
let subtitleURL = ""+glob.globSync("*.en.vtt", {
|
|
cwd: path.join(__dirname, '..', 'public', directory),
|
|
matchBase: true,
|
|
follow: true,
|
|
}).pop();
|
|
let subtitleFile = path.join(__dirname, '..', 'public', directory, subtitleURL);
|
|
const route = encodeURI(expressRoutePathFromFilePath(filePath));
|
|
let paths = filePath.substring(0, filePath.lastIndexOf(path.sep) > 0 ? filePath.lastIndexOf(path.sep) : filePath.length-1).split(path.sep);
|
|
paths = paths.map((name, idx, aPaths) => {
|
|
let url = aPaths.slice(0, idx+1).join(path.posix.sep);
|
|
return {
|
|
name,
|
|
url,
|
|
};
|
|
});
|
|
const fullFilePath = path.join(__dirname, '..', 'public', filePath);
|
|
console.log(`Setting route for ${route}`);
|
|
app.get(route, async (req, res) => {
|
|
if (!req.path.endsWith('/')) {
|
|
res.redirect(req.path + '/');
|
|
}
|
|
else {
|
|
let info = require(fullFilePath);
|
|
let subtitleVTT = fs.existsSync(subtitleFile)?fs.readFileSync(subtitleFile, 'utf8'):undefined;
|
|
const renderData = { route, filePath, fullFilePath, req, paths, directory: path.join('public', directory), videoURL, subtitleURL, subtitleVTT, info };
|
|
res.render("video-player", { h: helpers, require, ...renderData });
|
|
}
|
|
});
|
|
});
|
|
|
|
//app.get('/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding**', rewriter.rewrite('/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding/$1'));
|
|
|
|
console.log(`Serving /vendor/**/* route for all files in ${path.join(config.staticPath, 'vendor')}`);;
|
|
app.get('/vendor/**/*', async (req, res) => {
|
|
await serve(req, res, {
|
|
public: config.staticPath,
|
|
symlinks: true,
|
|
trailingSlash: true,
|
|
cleanUrls: false,
|
|
renderSingle: false,
|
|
unlisted: [
|
|
".DS_Store",
|
|
".git",
|
|
"Thumbs.db",
|
|
"README*",
|
|
],
|
|
});
|
|
});
|
|
|
|
console.log(`Serving /css/*.css route for all files in ${path.join(config.staticPath, 'css')}`);;
|
|
app.get('/css/*.css', async (req, res) => {
|
|
await serve(req, res, {
|
|
public: config.staticPath,
|
|
symlinks: true,
|
|
trailingSlash: true,
|
|
cleanUrls: false,
|
|
renderSingle: false,
|
|
unlisted: [
|
|
".DS_Store",
|
|
".git",
|
|
"Thumbs.db",
|
|
"README*",
|
|
],
|
|
});
|
|
});
|
|
|
|
console.log(`Serving /svg/*.svg route for all files in ${path.join(config.staticPath, 'svg')}`);;
|
|
app.get('/svg/*.svg', async (req, res) => {
|
|
await serve(req, res, {
|
|
public: config.staticPath,
|
|
symlinks: true,
|
|
trailingSlash: true,
|
|
cleanUrls: false,
|
|
renderSingle: false,
|
|
unlisted: [
|
|
".DS_Store",
|
|
".git",
|
|
"Thumbs.db",
|
|
"README*",
|
|
],
|
|
});
|
|
});
|
|
|
|
//TODO: Rewrite this facility so that it utilizes Git index as a filesystem.
|
|
console.log(`Serving * default route for all files in ${config.publicPath}`);;
|
|
app.get('*', async (req, res) => {
|
|
await serve(req, res, {
|
|
public: config.publicPath,
|
|
symlinks: true,
|
|
trailingSlash: true,
|
|
cleanUrls: false,
|
|
renderSingle: false,
|
|
unlisted: [
|
|
".*", //dot files/folders
|
|
"Thumbs.db"
|
|
],
|
|
redirects: [
|
|
{
|
|
source: "/:year(\d{4})-:mo(\d{2})-:dd(\d{2})_:hh(\d{2})_:mm(\d{2})/",
|
|
destination: "/Web_Site_Archives/Russell_County_Web_Site-:year-:mo-:dd_:hh_:mm/"
|
|
},
|
|
{
|
|
source: "/OCR-Encoded-PDFs",
|
|
destination: "/Web_Site_Archives"
|
|
},
|
|
{
|
|
source: "/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding.zip",
|
|
destination: "/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding.zip"
|
|
},
|
|
{
|
|
source: "/OCR-Encoded-PDFs/Russell-County-Web-Site_2024-02-13_19_50_Modified-With-OCR-Encoding/:u(.*)",
|
|
destination: "/Web_Site_Archives/Russell_County_Web_Site-2024-02-13_19_50_Modified_With_OCR_Encoding:u"
|
|
},
|
|
{ source: '/YouTube Channel', destination: '/Russell_County/Board_of_Supervisors/YouTube_Archive/@russellcountyvirginia8228' },
|
|
// { source: '/YouTube Channel.zip', destination: '/Russell_County_BOS/YouTube_Channel.zip' },
|
|
// { source: '/YouTube Channel/:u?', destination: '/Russell_County_BOS/YouTube_Channel/:u' },
|
|
{ source: '/Project Reclaim [WI19KR9Ogwg].mkv', destination: '/YouTube_Archives/@VADMME/Project Reclaim [WI19KR9Ogwg].mkv' },
|
|
]
|
|
});
|
|
});
|
|
|
|
// Start server
|
|
app.listen(config.appHttpPort, () => {
|
|
console.log(`nm3clol-express-app HTTP server listening on port ${config.appHttpPort}.`)
|
|
console.log(`To access your app, you can use the localhost URL, http://localhost:${config.appHttpPort}.`);
|
|
console.log(`To access your app, you can use the 127.0.0.1 host, http://127.0.0.1:${config.appHttpPort}.`);
|
|
console.log(`To access your app, you can use the ::1 host, http://[::1]:${config.appHttpPort}.`);
|
|
console.log(`To access your app, you might can use the app host name, ${config.appHttpUrl}.`);
|
|
console.log(`This app is configured to use the web site URL, ${config.siteUrl}.`);
|
|
});
|