Benjamin Atkin 5 years ago
parent
commit
aabdb3391f
  1. 143
      app.js
  2. 1
      package-lock.json
  3. 1
      package.json

143
app.js

@ -1,24 +1,25 @@
const Koa = require('koa');
const Router = require('@koa/router');
const serve = require('koa-static');
const bodyParser = require('koa-bodyparser');
const fetch = require('isomorphic-unfetch');
const randomBytes = require('crypto').randomBytes;
import Koa from 'koa'
import Router from '@koa/router'
import serve from 'koa-static'
import bodyParser from 'koa-bodyparser'
import fetch from 'isomorphic-unfetch'
import { randomBytes } from 'crypto'
import parse from "mdast-util-from-markdown"
const app = new Koa();
const router = new Router();
const app = new Koa()
const router = new Router()
const gitea = { const gitea = {
apiBase: process.env.GITEA_API_BASE, apiBase: process.env.GITEA_API_BASE,
user: process.env.GITEA_USER, user: process.env.GITEA_USER,
repo: process.env.GITEA_REPO, repo: process.env.GITEA_REPO,
token: process.env.GITEA_TOKEN, token: process.env.GITEA_TOKEN,
};
}
async function createNote(name, contentPlain) { async function createNote(name, contentPlain) {
const content = Buffer.from(contentPlain).toString('base64');
const body = JSON.stringify({content});
const url = `${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/${name}.txt`;
const content = Buffer.from(contentPlain).toString('base64')
const body = JSON.stringify({ content })
const url = `${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/${name}.md`
const resp = await fetch(url, { const resp = await fetch(url, {
method: 'POST', method: 'POST',
headers: { headers: {
@ -27,31 +28,7 @@ async function createNote(name, contentPlain) {
Authorization: `token ${gitea.token}`, Authorization: `token ${gitea.token}`,
}, },
body, body,
});
console.log({url, resp});
}
async function appendNote(content) {
const originalResp = await fetch(`${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/notes.txt`, {
headers: {
Accept: 'application/json',
Authorization: `token ${gitea.token}`,
},
});
const originalData = await originalResp.json();
const originalContentPlain = Buffer.from(originalData.content, 'base64').toString('utf8');
const newContentPlain = originalContentPlain + "\n\n" + content;
const newContent = Buffer.from(newContentPlain).toString('base64');
const body = JSON.stringify({content: newContent, sha: originalData.sha});
const resp = await fetch(`${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/notes.txt`, {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: `token ${gitea.token}`,
},
body,
});
})
} }
router.post('/micropub', async (ctx, next) => { router.post('/micropub', async (ctx, next) => {
@ -61,58 +38,84 @@ router.post('/micropub', async (ctx, next) => {
Accept: 'application/json', Accept: 'application/json',
Authorization: ctx.headers['authorization'] Authorization: ctx.headers['authorization']
} }
});
const data = await resp.json();
})
const data = await resp.json()
if (!resp.ok) { if (!resp.ok) {
next();
return;
next()
return
}
const name = randomBytes(12).toString('hex')
await createNote(name, ctx.request.body.content)
ctx.set('Location', `https://${name}.benatkin.com/`)
ctx.status = 201
ctx.body = {}
})
function readMarkdown(md) {
const parsed = parse(value);
const codeBlocks = parsed.children.filter((block) => block.type === "code");
const blocks = {
html: codeBlocks.filter((block) => block.lang === "html"),
js: codeBlocks.filter((block) => ["js", "javascript"].includes(block.lang)),
css: codeBlocks.filter((block) => block.lang === "css"),
}
const code = {
html: blocks.html.length === 1 ? blocks.html[0].value,
js: blocks.html.length === 1 ? blocks.js[0].value,
css: blocks.html.length === 1 ? blocks.css[0].value,
}
}
function renderSandbox({html, css, js}) {
return `<html>
<head>
<title>Sandbox</title>
${css ? `<style type="text/css">
${css}
</style>` : ''}
</head>
<body>
${html || ''}
${js ? `<script>
${js}
</script>` : ''}
</body>
</html>`
} }
const name = randomBytes(12).toString('hex');
await createNote(name, ctx.request.body.content);
ctx.set('Location', `https://${name}.benatkin.com/`);
ctx.status = 201;
ctx.body = {};
});
router.get('/', async (ctx, next) => { router.get('/', async (ctx, next) => {
const host = (ctx.headers['host'] || '').replace(/\.[^.]+\.[^.*]+$/, '') const host = (ctx.headers['host'] || '').replace(/\.[^.]+\.[^.*]+$/, '')
if (host === 'notes') { if (host === 'notes') {
return await next();
return await next()
} }
const url = `${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/${encodeURIComponent(host)}.txt`;
const url = `${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/${encodeURIComponent(host)}.txt`
const resp = await fetch(url, { const resp = await fetch(url, {
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
Authorization: `token ${gitea.token}`, Authorization: `token ${gitea.token}`,
}, },
});
console.log({url, resp});
})
if (resp.ok) { if (resp.ok) {
const { content } = await resp.json();
const contentPlain = Buffer.from(content, 'base64').toString('utf8');
ctx.body = contentPlain;
const { content } = await resp.json()
const contentPlain = Buffer.from(content, 'base64').toString('utf8')
const markdownContent = readMarkdown(contentPlain)
if (markdownContent) {
ctx.body = renderSandbox(markdownContent)
ctx.set('Content-Security-Policy', "default-src 'self'")
ctx.set('Content-Type', 'text/html')
} else { } else {
ctx.status = 404;
ctx.body = `${host} not found`;
ctx.body = contentPlain
}
} else {
ctx.status = 404
ctx.body = `${host} not found`
} }
}) })
router.get('/api/notes', async (ctx, next) => {
const resp = await fetch(`${gitea.apiBase}/repos/${gitea.user}/${gitea.repo}/contents/notes.txt`, {
headers: {
Accept: 'application/json',
Authorization: `token ${gitea.token}`,
},
});
const { content } = await resp.json();
const contentPlain = Buffer.from(content, 'base64').toString('utf8');
ctx.body = { content: contentPlain };
});
app app
.use(bodyParser()) .use(bodyParser())
.use(router.routes()) .use(router.routes())
.use(router.allowedMethods()) .use(router.allowedMethods())
.use(serve('static'));
.use(serve('static'))
app.listen(3000);
app.listen(3000)

1
package-lock.json

@ -5,6 +5,7 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "notes",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {

1
package.json

@ -1,5 +1,6 @@
{ {
"name": "notes", "name": "notes",
"type": "module",
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",

Loading…
Cancel
Save