]>
Commit | Line | Data |
---|---|---|
54141398 | 1 | import { Transaction } from 'sequelize' |
57e4e1c1 C |
2 | import { getServerActor } from '@server/models/application/application' |
3 | import { ActivityAudience, ActivityCreate, ContextType, VideoPlaylistPrivacy, VideoPrivacy } from '@shared/models' | |
452b3bea | 4 | import { logger, loggerTagsFactory } from '../../../helpers/logger' |
57e4e1c1 | 5 | import { VideoCommentModel } from '../../../models/video/video-comment' |
453e83ea C |
6 | import { |
7 | MActorLight, | |
8 | MCommentOwnerVideo, | |
9 | MVideoAccountLight, | |
10 | MVideoAP, | |
11 | MVideoPlaylistFull, | |
12 | MVideoRedundancyFileVideo, | |
13 | MVideoRedundancyStreamingPlaylistVideo | |
26d6bf65 | 14 | } from '../../../types/models' |
57e4e1c1 C |
15 | import { audiencify, getAudience } from '../audience' |
16 | import { | |
17 | broadcastToActors, | |
18 | broadcastToFollowers, | |
19 | getActorsInvolvedInVideo, | |
20 | getAudienceFromFollowersOf, | |
21 | getVideoCommentAudience, | |
22 | sendVideoRelatedActivity, | |
23 | unicastTo | |
24 | } from './shared' | |
453e83ea | 25 | |
452b3bea C |
26 | const lTags = loggerTagsFactory('ap', 'create') |
27 | ||
a219c910 | 28 | async function sendCreateVideo (video: MVideoAP, transaction: Transaction) { |
22a73cb8 | 29 | if (!video.hasPrivacyForFederation()) return undefined |
54141398 | 30 | |
452b3bea | 31 | logger.info('Creating job to send video creation of %s.', video.url, lTags(video.uuid)) |
8e0fd45e | 32 | |
e12a0092 | 33 | const byActor = video.VideoChannel.Account.Actor |
50d6de9c | 34 | const videoObject = video.toActivityPubObject() |
e12a0092 | 35 | |
2186386c | 36 | const audience = getAudience(byActor, video.privacy === VideoPrivacy.PUBLIC) |
c48e82b5 | 37 | const createActivity = buildCreateActivity(video.url, byActor, videoObject, audience) |
54141398 | 38 | |
a219c910 C |
39 | return broadcastToFollowers({ |
40 | data: createActivity, | |
41 | byActor, | |
42 | toFollowersOf: [ byActor ], | |
43 | transaction, | |
44 | contextType: 'Video' | |
45 | }) | |
54141398 C |
46 | } |
47 | ||
453e83ea C |
48 | async function sendCreateCacheFile ( |
49 | byActor: MActorLight, | |
50 | video: MVideoAccountLight, | |
51 | fileRedundancy: MVideoRedundancyStreamingPlaylistVideo | MVideoRedundancyFileVideo | |
52 | ) { | |
452b3bea | 53 | logger.info('Creating job to send file cache of %s.', fileRedundancy.url, lTags(video.uuid)) |
c48e82b5 | 54 | |
a2377d15 C |
55 | return sendVideoRelatedCreateActivity({ |
56 | byActor, | |
57 | video, | |
58 | url: fileRedundancy.url, | |
084a2cd0 C |
59 | object: fileRedundancy.toActivityPubObject(), |
60 | contextType: 'CacheFile' | |
a2377d15 | 61 | }) |
40ff5707 C |
62 | } |
63 | ||
a219c910 | 64 | async function sendCreateVideoPlaylist (playlist: MVideoPlaylistFull, transaction: Transaction) { |
418d092a C |
65 | if (playlist.privacy === VideoPlaylistPrivacy.PRIVATE) return undefined |
66 | ||
452b3bea | 67 | logger.info('Creating job to send create video playlist of %s.', playlist.url, lTags(playlist.uuid)) |
418d092a C |
68 | |
69 | const byActor = playlist.OwnerAccount.Actor | |
70 | const audience = getAudience(byActor, playlist.privacy === VideoPlaylistPrivacy.PUBLIC) | |
71 | ||
a219c910 | 72 | const object = await playlist.toActivityPubObject(null, transaction) |
418d092a C |
73 | const createActivity = buildCreateActivity(playlist.url, byActor, object, audience) |
74 | ||
75 | const serverActor = await getServerActor() | |
76 | const toFollowersOf = [ byActor, serverActor ] | |
77 | ||
78 | if (playlist.VideoChannel) toFollowersOf.push(playlist.VideoChannel.Actor) | |
79 | ||
a219c910 C |
80 | return broadcastToFollowers({ |
81 | data: createActivity, | |
82 | byActor, | |
83 | toFollowersOf, | |
84 | transaction, | |
85 | contextType: 'Playlist' | |
86 | }) | |
418d092a C |
87 | } |
88 | ||
a219c910 | 89 | async function sendCreateVideoComment (comment: MCommentOwnerVideo, transaction: Transaction) { |
8e0fd45e C |
90 | logger.info('Creating job to send comment %s.', comment.url) |
91 | ||
07197db4 C |
92 | const isOrigin = comment.Video.isOwned() |
93 | ||
ea44f375 | 94 | const byActor = comment.Account.Actor |
a219c910 | 95 | const threadParentComments = await VideoCommentModel.listThreadParentComments(comment, transaction) |
d7e70384 | 96 | const commentObject = comment.toActivityPubObject(threadParentComments) |
ea44f375 | 97 | |
a219c910 | 98 | const actorsInvolvedInComment = await getActorsInvolvedInVideo(comment.Video, transaction) |
a2377d15 | 99 | // Add the actor that commented too |
93ef8a9d | 100 | actorsInvolvedInComment.push(byActor) |
93ef8a9d | 101 | |
6cb55644 C |
102 | const parentsCommentActors = threadParentComments.filter(c => !c.isDeleted()) |
103 | .map(c => c.Account.Actor) | |
ea44f375 | 104 | |
07197db4 C |
105 | let audience: ActivityAudience |
106 | if (isOrigin) { | |
107 | audience = getVideoCommentAudience(comment, threadParentComments, actorsInvolvedInComment, isOrigin) | |
108 | } else { | |
a2377d15 | 109 | audience = getAudienceFromFollowersOf(actorsInvolvedInComment.concat(parentsCommentActors)) |
07197db4 | 110 | } |
93ef8a9d | 111 | |
c48e82b5 | 112 | const createActivity = buildCreateActivity(comment.url, byActor, commentObject, audience) |
ea44f375 | 113 | |
93ef8a9d C |
114 | // This was a reply, send it to the parent actors |
115 | const actorsException = [ byActor ] | |
a219c910 C |
116 | await broadcastToActors({ |
117 | data: createActivity, | |
118 | byActor, | |
119 | toActors: parentsCommentActors, | |
120 | transaction, | |
121 | actorsException, | |
122 | contextType: 'Comment' | |
123 | }) | |
93ef8a9d C |
124 | |
125 | // Broadcast to our followers | |
a219c910 C |
126 | await broadcastToFollowers({ |
127 | data: createActivity, | |
128 | byActor, | |
129 | toFollowersOf: [ byActor ], | |
130 | transaction, | |
131 | contextType: 'Comment' | |
132 | }) | |
93ef8a9d C |
133 | |
134 | // Send to actors involved in the comment | |
a219c910 C |
135 | if (isOrigin) { |
136 | return broadcastToFollowers({ | |
137 | data: createActivity, | |
138 | byActor, | |
139 | toFollowersOf: actorsInvolvedInComment, | |
140 | transaction, | |
141 | actorsException, | |
142 | contextType: 'Comment' | |
143 | }) | |
144 | } | |
07197db4 C |
145 | |
146 | // Send to origin | |
a219c910 C |
147 | return transaction.afterCommit(() => { |
148 | return unicastTo({ | |
149 | data: createActivity, | |
150 | byActor, | |
151 | toActorUrl: comment.Video.VideoChannel.Account.Actor.getSharedInbox(), | |
152 | contextType: 'Comment' | |
153 | }) | |
154 | }) | |
ea44f375 C |
155 | } |
156 | ||
453e83ea | 157 | function buildCreateActivity (url: string, byActor: MActorLight, object: any, audience?: ActivityAudience): ActivityCreate { |
2186386c C |
158 | if (!audience) audience = getAudience(byActor) |
159 | ||
160 | return audiencify( | |
161 | { | |
162 | type: 'Create' as 'Create', | |
163 | id: url + '/activity', | |
164 | actor: byActor.url, | |
ab18fadf | 165 | object: audiencify(object, audience) |
2186386c C |
166 | }, |
167 | audience | |
168 | ) | |
54141398 C |
169 | } |
170 | ||
171 | // --------------------------------------------------------------------------- | |
172 | ||
173 | export { | |
50d6de9c | 174 | sendCreateVideo, |
c48e82b5 | 175 | buildCreateActivity, |
c48e82b5 | 176 | sendCreateVideoComment, |
418d092a | 177 | sendCreateVideoPlaylist, |
c48e82b5 | 178 | sendCreateCacheFile |
54141398 | 179 | } |
a2377d15 C |
180 | |
181 | // --------------------------------------------------------------------------- | |
182 | ||
183 | async function sendVideoRelatedCreateActivity (options: { | |
a1587156 C |
184 | byActor: MActorLight |
185 | video: MVideoAccountLight | |
186 | url: string | |
187 | object: any | |
a219c910 | 188 | contextType: ContextType |
a2377d15 C |
189 | transaction?: Transaction |
190 | }) { | |
191 | const activityBuilder = (audience: ActivityAudience) => { | |
192 | return buildCreateActivity(options.url, options.byActor, options.object, audience) | |
193 | } | |
194 | ||
195 | return sendVideoRelatedActivity(activityBuilder, options) | |
196 | } |