const path = require("path"); const bodyParser = require("koa-body")({multipart: true}); const fetch = require("node-fetch"); const Koa = require("koa"); const koaPug = require("koa-pug"); const koaRouter = require("koa-router"); const { MysqlError } = require("mysql"); const config = require("./config"); const guestbook = require("./guestbook"); const mindflow = require("./mindflow"); const util = require("../shared/util"); const articles_meta = { "rpi_root_on_external_drive": { title: "How to move a root from SD card to external drive on Raspberry Pi", description: "Article on moving a root partition to an ext. drive on Raspberry Pi." }, "setting_up_a_tor_proxy_relay_hiddenserv": { title: "Setting up a Tor proxy, relay and hidden service", description: "Article on setting up a Tor proxy, relay and hidden service." }, "setting_up_a_mail_server": { title: "Setting up a mail server", description: "Article on creating your own mail server using Postfix and Dovecot." }, "nginx_recipes_and_tips": { title: "NGiNX's recipes & tips", description: "Article on tips and recipes for NGiNX webserver." }, }; async function getProcesses() { let reimu = await fetch("http://reimu.arav.home:14882/processes").then(r => r.json()); let sakuya = await fetch("http://sakuya.arav.home:14882/processes").then(r => r.json()); return Object.fromEntries(Object.entries(reimu).concat(Object.entries(sakuya))); } function setRoutes() { return koaRouter().get('/', async ctx => { await ctx.render('index', { description: "A homepage of a russian guy Arav. Not just homepage, but FTP, radio, and smth more as well." }); }) .get('/rss.xml', async ctx => { ctx.type = 'xml'; await ctx.render('rss', { doctype: 'xml', protocol: ctx.protocol, host: ctx.header.host, author: "me@arav.top (Alexander \"Arav\" Andreev)", items: await mindflow.getPostsForRSS() }) }) .get('/stuff', async ctx => { await ctx.render('stuff', { title: "/ Stuff", description: "Here I share my programs, scripts, articles, may be other stuff." }) }) .get('/mindflow', async ctx => { await ctx.render('mindflow', { title: "/ Mindflow", description: "Here I will post updates on my infrastructure, my very important opinions and thoughts.", files_site: util.getServiceByHost(ctx.request.host, "files"), tz: util.getClientTimezone(ctx), diary: await mindflow.getPosts("Diary"), updates: await mindflow.getPosts("Update") }) }) .get('/stuff/article/:article', async ctx => { if (ctx.params.article) { return await ctx.render("articles/" + ctx.params.article, { title: "/ Article / " + articles_meta[ctx.params.article].title, description: articles_meta[ctx.params.article].description }); } else { return ctx.throw(404); } }) .get('/about', async ctx => { await ctx.render('about', { title: "/ About", description: "This is a page where I'm telling about me and my home server.", files_site: util.getServiceByHost(ctx.request.host, "files"), services: await getProcesses() }) }) .get('/guestbook', async ctx => { const page = ctx.request.query.p !== undefined ? ctx.request.query.p : 1; const page_size = ctx.request.query.ps !== undefined ? ctx.request.query.ps : guestbook.pageSize; let posts; try { posts = await guestbook.getPosts(page, page_size); } catch(err) { posts = null; } return await ctx.render('guestbook', { title: "/ Guestbook", description: "This is my guestbook. Welcome.", tz: util.getClientTimezone(ctx), owner: config.guestbook.owner, posts: posts, pages_count: Math.ceil(await guestbook.getPostsCount() / page_size) }); }) .post('/guestbook', bodyParser, async ctx => { const post = ctx.request.body; post.hide_email = post.hide_email !== undefined; post.hide_website = post.hide_website !== undefined; try { if (await guestbook.addPost(post)) ctx.redirect("/guestbook"); } catch(err) { ctx.type = "text/plain"; if (err instanceof MysqlError) ctx.body = `Database failed so your post wasn't added. So your time wasn't wasted here's your message:\n${post.message}`; else ctx.body = `Your post was rejected because of "${err}". So your time wasn't wasted here's your message:\n${post.message}`; } }); } const app = new Koa(); const pug = new koaPug({ viewPath: path.join(__dirname, "views"), locals: { date_: (date, tz) => util.datetime(date, util.formats.post_date, tz), mindflowDateToId: (date, tz) => util.datetime(date, util.formats.id_date, tz), rssLink: util.rssLink }, app: app }); app.proxy = true; app .use(async (ctx, next) => { try { await next(); if (ctx.status === 404) ctx.throw(404); } catch (err) { ctx.status = err.status || 500; if (ctx.status === 404) await ctx.render('404'); else await ctx.render('500'); } }) .use(setRoutes().routes()) .listen(config.port, config.host); console.log("Arav's dwelling / Homepage is up.");