summaryrefslogtreecommitdiff
path: root/src/processor/http/deliver-post.ts
blob: 83ac8281f483410d0a91c97f4d5beb102a6cff77 (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
94
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 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(rendered => {
					rendered['@context'] = context;
					return request(user, following.follower[0].account.inbox, rendered);
				});
			})))
		);
	}

	// チャンネルへの投稿
	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);
});