From a3bd4ba42693b1dc99ef586ef35f61dc53cdf9e9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 13 Apr 2018 00:51:55 +0900 Subject: wip --- src/server/activitypub.ts | 142 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 src/server/activitypub.ts (limited to 'src/server/activitypub.ts') diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts new file mode 100644 index 0000000000..ed0311af9d --- /dev/null +++ b/src/server/activitypub.ts @@ -0,0 +1,142 @@ +import * as Router from 'koa-router'; +import { parseRequest } from 'http-signature'; + +import { createHttp } from '../queue'; +import context from '../remote/activitypub/renderer/context'; +import render from '../remote/activitypub/renderer/note'; +import Note from '../models/note'; +import User, { isLocalUser } from '../models/user'; +import renderNote from '../remote/activitypub/renderer/note'; +import renderKey from '../remote/activitypub/renderer/key'; +import renderPerson from '../remote/activitypub/renderer/person'; +import renderOrderedCollection from '../remote/activitypub/renderer/ordered-collection'; +//import parseAcct from '../acct/parse'; +import config from '../config'; + +// Init router +const router = new Router(); + +//#region Routing + +// inbox +router.post('/users/:user/inbox', ctx => { + let signature; + + ctx.req.headers.authorization = 'Signature ' + ctx.req.headers.signature; + + try { + signature = parseRequest(ctx.req); + } catch (e) { + ctx.status = 401; + return; + } + + createHttp({ + type: 'processInbox', + activity: ctx.request.body, + signature + }).save(); + + ctx.status = 202; +}); + +// note +router.get('/notes/:note', async (ctx, next) => { + const accepted = ctx.accepts('html', 'application/activity+json', 'application/ld+json'); + if (!['application/activity+json', 'application/ld+json'].includes(accepted as string)) { + next(); + return; + } + + const note = await Note.findOne({ + _id: ctx.params.note + }); + + if (note === null) { + ctx.status = 404; + return; + } + + const rendered = await render(note); + rendered['@context'] = context; + + ctx.body = rendered; +}); + +// outbot +router.get('/users/:user/outbox', async ctx => { + const userId = ctx.params.user; + + const user = await User.findOne({ _id: userId }); + + if (user === null) { + ctx.status = 404; + return; + } + + const notes = await Note.find({ userId: user._id }, { + limit: 10, + sort: { _id: -1 } + }); + + const renderedNotes = await Promise.all(notes.map(note => renderNote(note))); + const rendered = renderOrderedCollection(`${config.url}/users/${userId}/inbox`, user.notesCount, renderedNotes); + rendered['@context'] = context; + + ctx.body = rendered; +}); + +// publickey +router.get('/users/:user/publickey', async ctx => { + const userId = ctx.params.user; + + const user = await User.findOne({ _id: userId }); + + if (user === null) { + ctx.status = 404; + return; + } + + if (isLocalUser(user)) { + const rendered = renderKey(user); + rendered['@context'] = context; + + ctx.body = rendered; + } else { + ctx.status = 400; + } +}); + +// user +router.get('/users/:user', async ctx => { + const userId = ctx.params.user; + + const user = await User.findOne({ _id: userId }); + + if (user === null) { + ctx.status = 404; + return; + } + + const rendered = renderPerson(user); + rendered['@context'] = context; + + ctx.body = rendered; +}); + +// follow form +router.get('/authorize-follow', async ctx => { + /* TODO + const { username, host } = parseAcct(ctx.query.acct); + if (host === null) { + res.sendStatus(422); + return; + } + + const finger = await request(`https://${host}`) + */ +}); + +//#endregion + +export default router; -- cgit v1.2.3-freya