summaryrefslogtreecommitdiff
path: root/src/remote/activitypub/act/create.ts
blob: c1a30ce7d042b0ef6b0ee50356b4904933e50e4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import { JSDOM } from 'jsdom';
const createDOMPurify = require('dompurify');

import Resolver from '../resolver';
import DriveFile from '../../../models/drive-file';
import Post from '../../../models/post';
import uploadFromUrl from '../../../drive/upload-from-url';
import createPost from '../../../post/create';

export default async (resolver: Resolver, actor, activity): Promise<void> => {
	if ('actor' in activity && actor.account.uri !== activity.actor) {
		throw new Error('invalid actor');
	}

	const uri = activity.id || activity;

	try {
		await Promise.all([
			DriveFile.findOne({ 'metadata.uri': uri }).then(file => {
				if (file !== null) {
					throw new Error();
				}
			}, () => {}),
			Post.findOne({ uri }).then(post => {
				if (post !== null) {
					throw new Error();
				}
			}, () => {})
		]);
	} catch (object) {
		throw new Error(`already registered: ${uri}`);
	}

	const object = await resolver.resolve(activity);

	switch (object.type) {
	case 'Image':
		createImage(resolver, object);
		break;

	case 'Note':
		createNote(resolver, object);
		break;
	}

	///

	async function createImage(resolver: Resolver, image) {
		if ('attributedTo' in image && actor.account.uri !== image.attributedTo) {
			throw new Error('invalid image');
		}

		return await uploadFromUrl(image.url, actor);
	}

	async function createNote(resolver: Resolver, note) {
		if (
			('attributedTo' in note && actor.account.uri !== note.attributedTo) ||
			typeof note.id !== 'string'
		) {
			throw new Error('invalid note');
		}

		const mediaIds = [];

		if ('attachment' in note) {
			note.attachment.forEach(async media => {
				const created = await createImage(resolver, media);
				mediaIds.push(created._id);
			});
		}

		const { window } = new JSDOM(note.content);

		await createPost(actor, {
			channelId: undefined,
			index: undefined,
			createdAt: new Date(note.published),
			mediaIds,
			replyId: undefined,
			repostId: undefined,
			poll: undefined,
			text: window.document.body.textContent,
			textHtml: note.content && createDOMPurify(window).sanitize(note.content),
			userId: actor._id,
			appId: null,
			viaMobile: false,
			geo: undefined,
			uri: note.id
		}, null, null, []);
	}
};