aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/process/process-create.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/activitypub/process/process-create.ts')
-rw-r--r--server/lib/activitypub/process/process-create.ts127
1 files changed, 29 insertions, 98 deletions
diff --git a/server/lib/activitypub/process/process-create.ts b/server/lib/activitypub/process/process-create.ts
index e65b257c0..08d61996a 100644
--- a/server/lib/activitypub/process/process-create.ts
+++ b/server/lib/activitypub/process/process-create.ts
@@ -8,15 +8,13 @@ import { logger } from '../../../helpers/logger'
8import { sequelizeTypescript } from '../../../initializers' 8import { sequelizeTypescript } from '../../../initializers'
9import { AccountVideoRateModel } from '../../../models/account/account-video-rate' 9import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
10import { ActorModel } from '../../../models/activitypub/actor' 10import { ActorModel } from '../../../models/activitypub/actor'
11import { TagModel } from '../../../models/video/tag'
12import { VideoModel } from '../../../models/video/video' 11import { VideoModel } from '../../../models/video/video'
13import { VideoAbuseModel } from '../../../models/video/video-abuse' 12import { VideoAbuseModel } from '../../../models/video/video-abuse'
14import { VideoCommentModel } from '../../../models/video/video-comment' 13import { VideoCommentModel } from '../../../models/video/video-comment'
15import { VideoFileModel } from '../../../models/video/video-file'
16import { getOrCreateActorAndServerAndModel } from '../actor' 14import { getOrCreateActorAndServerAndModel } from '../actor'
17import { forwardActivity, getActorsInvolvedInVideo } from '../send/misc' 15import { forwardActivity, getActorsInvolvedInVideo } from '../send/misc'
18import { generateThumbnailFromUrl } from '../videos' 16import { addVideoComments, resolveThread } from '../video-comments'
19import { addVideoComments, addVideoShares, videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc' 17import { addVideoShares, getOrCreateAccountAndVideoAndChannel } from '../videos'
20 18
21async function processCreateActivity (activity: ActivityCreate) { 19async function processCreateActivity (activity: ActivityCreate) {
22 const activityObject = activity.object 20 const activityObject = activity.object
@@ -53,17 +51,7 @@ async function processCreateVideo (
53) { 51) {
54 const videoToCreateData = activity.object as VideoTorrentObject 52 const videoToCreateData = activity.object as VideoTorrentObject
55 53
56 const channel = videoToCreateData.attributedTo.find(a => a.type === 'Group') 54 const { video } = await getOrCreateAccountAndVideoAndChannel(videoToCreateData, actor)
57 if (!channel) throw new Error('Cannot find associated video channel to video ' + videoToCreateData.url)
58
59 const channelActor = await getOrCreateActorAndServerAndModel(channel.id)
60
61 const options = {
62 arguments: [ actor, activity, videoToCreateData, channelActor ],
63 errorMessage: 'Cannot insert the remote video with many retries.'
64 }
65
66 const video = await retryTransactionWrapper(createRemoteVideo, options)
67 55
68 // Process outside the transaction because we could fetch remote data 56 // Process outside the transaction because we could fetch remote data
69 if (videoToCreateData.likes && Array.isArray(videoToCreateData.likes.orderedItems)) { 57 if (videoToCreateData.likes && Array.isArray(videoToCreateData.likes.orderedItems)) {
@@ -89,48 +77,6 @@ async function processCreateVideo (
89 return video 77 return video
90} 78}
91 79
92function createRemoteVideo (
93 account: ActorModel,
94 activity: ActivityCreate,
95 videoToCreateData: VideoTorrentObject,
96 channelActor: ActorModel
97) {
98 logger.debug('Adding remote video %s.', videoToCreateData.id)
99
100 return sequelizeTypescript.transaction(async t => {
101 const sequelizeOptions = {
102 transaction: t
103 }
104 const videoFromDatabase = await VideoModel.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t)
105 if (videoFromDatabase) return videoFromDatabase
106
107 const videoData = await videoActivityObjectToDBAttributes(channelActor.VideoChannel, videoToCreateData, activity.to, activity.cc)
108 const video = VideoModel.build(videoData)
109
110 // Don't block on request
111 generateThumbnailFromUrl(video, videoToCreateData.icon)
112 .catch(err => logger.warn('Cannot generate thumbnail of %s.', videoToCreateData.id, err))
113
114 const videoCreated = await video.save(sequelizeOptions)
115
116 const videoFileAttributes = videoFileActivityUrlToDBAttributes(videoCreated, videoToCreateData)
117 if (videoFileAttributes.length === 0) {
118 throw new Error('Cannot find valid files for video %s ' + videoToCreateData.url)
119 }
120
121 const tasks: Bluebird<any>[] = videoFileAttributes.map(f => VideoFileModel.create(f, { transaction: t }))
122 await Promise.all(tasks)
123
124 const tags = videoToCreateData.tag.map(t => t.name)
125 const tagInstances = await TagModel.findOrCreateTags(tags, t)
126 await videoCreated.$set('Tags', tagInstances, sequelizeOptions)
127
128 logger.info('Remote video with uuid %s inserted.', videoToCreateData.uuid)
129
130 return videoCreated
131 })
132}
133
134async function createRates (actorUrls: string[], video: VideoModel, rate: VideoRateType) { 80async function createRates (actorUrls: string[], video: VideoModel, rate: VideoRateType) {
135 let rateCounts = 0 81 let rateCounts = 0
136 const tasks: Bluebird<any>[] = [] 82 const tasks: Bluebird<any>[] = []
@@ -167,16 +113,15 @@ async function processCreateDislike (byActor: ActorModel, activity: ActivityCrea
167 return retryTransactionWrapper(createVideoDislike, options) 113 return retryTransactionWrapper(createVideoDislike, options)
168} 114}
169 115
170function createVideoDislike (byActor: ActorModel, activity: ActivityCreate) { 116async function createVideoDislike (byActor: ActorModel, activity: ActivityCreate) {
171 const dislike = activity.object as DislikeObject 117 const dislike = activity.object as DislikeObject
172 const byAccount = byActor.Account 118 const byAccount = byActor.Account
173 119
174 if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url) 120 if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
175 121
176 return sequelizeTypescript.transaction(async t => { 122 const { video } = await getOrCreateAccountAndVideoAndChannel(dislike.object)
177 const video = await VideoModel.loadByUrlAndPopulateAccount(dislike.object, t)
178 if (!video) throw new Error('Unknown video ' + dislike.object)
179 123
124 return sequelizeTypescript.transaction(async t => {
180 const rate = { 125 const rate = {
181 type: 'dislike' as 'dislike', 126 type: 'dislike' as 'dislike',
182 videoId: video.id, 127 videoId: video.id,
@@ -200,9 +145,7 @@ function createVideoDislike (byActor: ActorModel, activity: ActivityCreate) {
200async function processCreateView (byActor: ActorModel, activity: ActivityCreate) { 145async function processCreateView (byActor: ActorModel, activity: ActivityCreate) {
201 const view = activity.object as ViewObject 146 const view = activity.object as ViewObject
202 147
203 const video = await VideoModel.loadByUrlAndPopulateAccount(view.object) 148 const { video } = await getOrCreateAccountAndVideoAndChannel(view.object)
204
205 if (!video) throw new Error('Unknown video ' + view.object)
206 149
207 const account = await ActorModel.loadByUrl(view.actor) 150 const account = await ActorModel.loadByUrl(view.actor)
208 if (!account) throw new Error('Unknown account ' + view.actor) 151 if (!account) throw new Error('Unknown account ' + view.actor)
@@ -225,19 +168,15 @@ function processCreateVideoAbuse (actor: ActorModel, videoAbuseToCreateData: Vid
225 return retryTransactionWrapper(addRemoteVideoAbuse, options) 168 return retryTransactionWrapper(addRemoteVideoAbuse, options)
226} 169}
227 170
228function addRemoteVideoAbuse (actor: ActorModel, videoAbuseToCreateData: VideoAbuseObject) { 171async function addRemoteVideoAbuse (actor: ActorModel, videoAbuseToCreateData: VideoAbuseObject) {
229 logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object) 172 logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object)
230 173
231 const account = actor.Account 174 const account = actor.Account
232 if (!account) throw new Error('Cannot create dislike with the non account actor ' + actor.url) 175 if (!account) throw new Error('Cannot create dislike with the non account actor ' + actor.url)
233 176
234 return sequelizeTypescript.transaction(async t => { 177 const { video } = await getOrCreateAccountAndVideoAndChannel(videoAbuseToCreateData.object)
235 const video = await VideoModel.loadByUrlAndPopulateAccount(videoAbuseToCreateData.object, t)
236 if (!video) {
237 logger.warn('Unknown video %s for remote video abuse.', videoAbuseToCreateData.object)
238 return undefined
239 }
240 178
179 return sequelizeTypescript.transaction(async t => {
241 const videoAbuseData = { 180 const videoAbuseData = {
242 reporterAccountId: account.id, 181 reporterAccountId: account.id,
243 reason: videoAbuseToCreateData.content, 182 reason: videoAbuseToCreateData.content,
@@ -259,41 +198,33 @@ function processCreateVideoComment (byActor: ActorModel, activity: ActivityCreat
259 return retryTransactionWrapper(createVideoComment, options) 198 return retryTransactionWrapper(createVideoComment, options)
260} 199}
261 200
262function createVideoComment (byActor: ActorModel, activity: ActivityCreate) { 201async function createVideoComment (byActor: ActorModel, activity: ActivityCreate) {
263 const comment = activity.object as VideoCommentObject 202 const comment = activity.object as VideoCommentObject
264 const byAccount = byActor.Account 203 const byAccount = byActor.Account
265 204
266 if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url) 205 if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
267 206
207 const { video, parents } = await resolveThread(comment.inReplyTo)
208
268 return sequelizeTypescript.transaction(async t => { 209 return sequelizeTypescript.transaction(async t => {
269 let video = await VideoModel.loadByUrlAndPopulateAccount(comment.inReplyTo, t) 210 let originCommentId = null
270 let objectToCreate 211 let inReplyToCommentId = null
212
213 if (parents.length !== 0) {
214 const parent = parents[0]
215
216 originCommentId = parent.getThreadId()
217 inReplyToCommentId = parent.id
218 }
271 219
272 // This is a new thread 220 // This is a new thread
273 if (video) { 221 const objectToCreate = {
274 objectToCreate = { 222 url: comment.id,
275 url: comment.id, 223 text: comment.content,
276 text: comment.content, 224 originCommentId,
277 originCommentId: null, 225 inReplyToCommentId,
278 inReplyToComment: null, 226 videoId: video.id,
279 videoId: video.id, 227 accountId: byAccount.id
280 accountId: byAccount.id
281 }
282 } else {
283 const inReplyToComment = await VideoCommentModel.loadByUrl(comment.inReplyTo, t)
284 if (!inReplyToComment) throw new Error('Unknown replied comment ' + comment.inReplyTo)
285
286 video = await VideoModel.loadAndPopulateAccount(inReplyToComment.videoId)
287
288 const originCommentId = inReplyToComment.originCommentId || inReplyToComment.id
289 objectToCreate = {
290 url: comment.id,
291 text: comment.content,
292 originCommentId,
293 inReplyToCommentId: inReplyToComment.id,
294 videoId: video.id,
295 accountId: byAccount.id
296 }
297 } 228 }
298 229
299 const options = { 230 const options = {