summaryrefslogtreecommitdiff
path: root/src/processor/http/deliver-post.ts
blob: c00ab912c9a57448c5f79dc9cbb6e3f9eff063e8 (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
93
import Channel from '../../models/channel';
import Following from '../../models/following';
import ChannelWatching from '../../models/channel-watching';
import Post, { pack } from '../../models/post';
import User, { isLocalUser } from '../../models/user';
import stream, { publishChannelStream } from '../../publishers/stream';
import context from '../../remote/activitypub/renderer/context';
import renderCreate from '../../remote/activitypub/renderer/create';
import renderNote from '../../remote/activitypub/renderer/note';
import request from '../../remote/request';

export default ({ data }) => Post.findOne({ _id: data.id }).then(post => {
	const promisedPostObj = pack(post);
	const promises = [];

	// タイムラインへの投稿
	if (!post.channelId) {
		promises.push(
			// Publish event to myself's stream
			promisedPostObj.then(postObj => {
				stream(post.userId, 'post', postObj);
			}),

			Promise.all([
				User.findOne({ _id: post.userId }),

				// Fetch all followers
				Following.aggregate([{
					$lookup: {
						from: 'users',
						localField: 'followerId',
						foreignField: '_id',
						as: 'follower'
					}
				}, {
					$match: {
						followeeId: post.userId
					}
				}], {
					_id: false
				})
			]).then(([user, followers]) => Promise.all(followers.map(following => {
				if (isLocalUser(following.follower)) {
					// Publish event to followers stream
					return promisedPostObj.then(postObj => {
						stream(following.followerId, 'post', postObj);
					});
				}

				return renderNote(user, post).then(note => {
					const create = renderCreate(note);
					create['@context'] = context;
					return request(user, following.follower[0].account.inbox, create);
				});
			})))
		);
	}

	// チャンネルへの投稿
	if (post.channelId) {
		promises.push(
			// Increment channel index(posts count)
			Channel.update({ _id: post.channelId }, {
				$inc: {
					index: 1
				}
			}),

			// Publish event to channel
			promisedPostObj.then(postObj => {
				publishChannelStream(post.channelId, 'post', postObj);
			}),

			Promise.all([
				promisedPostObj,

				// Get channel watchers
				ChannelWatching.find({
					channelId: post.channelId,
					// 削除されたドキュメントは除く
					deletedAt: { $exists: false }
				})
			]).then(([postObj, watches]) => {
				// チャンネルの視聴者(のタイムライン)に配信
				watches.forEach(w => {
					stream(w.userId, 'post', postObj);
				});
			})
		);
	}

	return Promise.all(promises);
});