]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/activitypub/process/process-create.ts
Fix dependency errors between modules
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / process / process-create.ts
1 import { ActivityCreate, CacheFileObject, VideoAbuseState, VideoTorrentObject } from '../../../../shared'
2 import { DislikeObject, VideoAbuseObject, ViewObject } from '../../../../shared/models/activitypub/objects'
3 import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
4 import { retryTransactionWrapper } from '../../../helpers/database-utils'
5 import { logger } from '../../../helpers/logger'
6 import { sequelizeTypescript } from '../../../initializers'
7 import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
8 import { ActorModel } from '../../../models/activitypub/actor'
9 import { VideoAbuseModel } from '../../../models/video/video-abuse'
10 import { addVideoComment, resolveThread } from '../video-comments'
11 import { getOrCreateVideoAndAccountAndChannel } from '../videos'
12 import { forwardVideoRelatedActivity } from '../send/utils'
13 import { Redis } from '../../redis'
14 import { createOrUpdateCacheFile } from '../cache-file'
15 import { immutableAssign } from '../../../../shared/utils'
16 import { getVideoDislikeActivityPubUrl } from '../url'
17 import { VideoModel } from '../../../models/video/video'
18
19 async function processCreateActivity (activity: ActivityCreate, byActor: ActorModel) {
20 const activityObject = activity.object
21 const activityType = activityObject.type
22
23 if (activityType === 'View') {
24 return processCreateView(byActor, activity)
25 } else if (activityType === 'Dislike') {
26 return retryTransactionWrapper(processCreateDislike, byActor, activity)
27 } else if (activityType === 'Video') {
28 return processCreateVideo(activity)
29 } else if (activityType === 'Flag') {
30 return retryTransactionWrapper(processCreateVideoAbuse, byActor, activityObject as VideoAbuseObject)
31 } else if (activityType === 'Note') {
32 return retryTransactionWrapper(processCreateVideoComment, byActor, activity)
33 } else if (activityType === 'CacheFile') {
34 return retryTransactionWrapper(processCacheFile, byActor, activity)
35 }
36
37 logger.warn('Unknown activity object type %s when creating activity.', activityType, { activity: activity.id })
38 return Promise.resolve(undefined)
39 }
40
41 // ---------------------------------------------------------------------------
42
43 export {
44 processCreateActivity
45 }
46
47 // ---------------------------------------------------------------------------
48
49 async function processCreateVideo (activity: ActivityCreate) {
50 const videoToCreateData = activity.object as VideoTorrentObject
51
52 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoToCreateData })
53
54 return video
55 }
56
57 async function processCreateDislike (byActor: ActorModel, activity: ActivityCreate) {
58 const dislike = activity.object as DislikeObject
59 const byAccount = byActor.Account
60
61 if (!byAccount) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
62
63 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: dislike.object })
64
65 return sequelizeTypescript.transaction(async t => {
66 const rate = {
67 type: 'dislike' as 'dislike',
68 videoId: video.id,
69 accountId: byAccount.id
70 }
71
72 const [ , created ] = await AccountVideoRateModel.findOrCreate({
73 where: rate,
74 defaults: immutableAssign(rate, { url: getVideoDislikeActivityPubUrl(byActor, video) }),
75 transaction: t
76 })
77 if (created === true) await video.increment('dislikes', { transaction: t })
78
79 if (video.isOwned() && created === true) {
80 // Don't resend the activity to the sender
81 const exceptions = [ byActor ]
82
83 await forwardVideoRelatedActivity(activity, t, exceptions, video)
84 }
85 })
86 }
87
88 async function processCreateView (byActor: ActorModel, activity: ActivityCreate) {
89 const view = activity.object as ViewObject
90
91 const video = await VideoModel.loadByUrl(view.object)
92 if (!video || video.isOwned() === false) return
93
94 await Redis.Instance.addVideoView(video.id)
95 }
96
97 async function processCacheFile (byActor: ActorModel, activity: ActivityCreate) {
98 const cacheFile = activity.object as CacheFileObject
99
100 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: cacheFile.object })
101
102 await sequelizeTypescript.transaction(async t => {
103 return createOrUpdateCacheFile(cacheFile, video, byActor, t)
104 })
105
106 if (video.isOwned()) {
107 // Don't resend the activity to the sender
108 const exceptions = [ byActor ]
109 await forwardVideoRelatedActivity(activity, undefined, exceptions, video)
110 }
111 }
112
113 async function processCreateVideoAbuse (byActor: ActorModel, videoAbuseToCreateData: VideoAbuseObject) {
114 logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object)
115
116 const account = byActor.Account
117 if (!account) throw new Error('Cannot create dislike with the non account actor ' + byActor.url)
118
119 const { video } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoAbuseToCreateData.object })
120
121 return sequelizeTypescript.transaction(async t => {
122 const videoAbuseData = {
123 reporterAccountId: account.id,
124 reason: videoAbuseToCreateData.content,
125 videoId: video.id,
126 state: VideoAbuseState.PENDING
127 }
128
129 await VideoAbuseModel.create(videoAbuseData, { transaction: t })
130
131 logger.info('Remote abuse for video uuid %s created', videoAbuseToCreateData.object)
132 })
133 }
134
135 async function processCreateVideoComment (byActor: ActorModel, activity: ActivityCreate) {
136 const commentObject = activity.object as VideoCommentObject
137 const byAccount = byActor.Account
138
139 if (!byAccount) throw new Error('Cannot create video comment with the non account actor ' + byActor.url)
140
141 const { video } = await resolveThread(commentObject.inReplyTo)
142
143 const { created } = await addVideoComment(video, commentObject.id)
144
145 if (video.isOwned() && created === true) {
146 // Don't resend the activity to the sender
147 const exceptions = [ byActor ]
148
149 await forwardVideoRelatedActivity(activity, undefined, exceptions, video)
150 }
151 }