summaryrefslogtreecommitdiff
path: root/src/common/remote/activitypub/create.ts
blob: 4aaaeb306093284e22cf6a7afe2cbd5c7d7b811d (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
import { JSDOM } from 'jsdom';
import config from '../../../conf';
import Post from '../../../models/post';
import RemoteUserObject, { IRemoteUserObject } from '../../../models/remote-user-object';
import uploadFromUrl from '../../drive/upload_from_url';
const createDOMPurify = require('dompurify');

function createRemoteUserObject($ref, $id, { id }) {
	const object = { $ref, $id };

	if (!id) {
		return { object };
	}

	return RemoteUserObject.insert({ uri: id, object });
}

async function createImage(actor, object) {
	if ('attributedTo' in object && actor.account.uri !== object.attributedTo) {
		throw new Error;
	}

	const { _id } = await uploadFromUrl(object.url, actor);
	return createRemoteUserObject('driveFiles.files', _id, object);
}

async function createNote(resolver, actor, object) {
	if ('attributedTo' in object && actor.account.uri !== object.attributedTo) {
		throw new Error;
	}

	const mediaIds = 'attachment' in object &&
		(await Promise.all(await create(resolver, actor, object.attachment)))
			.filter(media => media !== null && media.object.$ref === 'driveFiles.files')
			.map(({ object }) => object.$id);

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

	const { _id } = await Post.insert({
		channelId: undefined,
		index: undefined,
		createdAt: new Date(object.published),
		mediaIds,
		replyId: undefined,
		repostId: undefined,
		poll: undefined,
		text: window.document.body.textContent,
		textHtml: object.content && createDOMPurify(window).sanitize(object.content),
		userId: actor._id,
		appId: null,
		viaMobile: false,
		geo: undefined
	});

	// Register to search database
	if (object.content && config.elasticsearch.enable) {
		const es = require('../../db/elasticsearch');

		es.index({
			index: 'misskey',
			type: 'post',
			id: _id.toString(),
			body: {
				text: window.document.body.textContent
			}
		});
	}

	return createRemoteUserObject('posts', _id, object);
}

export default async function create(parentResolver, actor, value): Promise<Promise<IRemoteUserObject>[]> {
	const results = await parentResolver.resolveRemoteUserObjects(value);

	return results.map(asyncResult => asyncResult.then(({ resolver, object }) => {
		switch (object.type) {
		case 'Image':
			return createImage(actor, object);

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

		return null;
	}));
};