]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/lib/activitypub/send/send-undo.ts
36d7ef99199e58a68b095f16da6331193343245c
[github/Chocobozzz/PeerTube.git] / server / lib / activitypub / send / send-undo.ts
1 import { Transaction } from 'sequelize'
2 import {
3 ActivityAnnounce,
4 ActivityAudience,
5 ActivityCreate,
6 ActivityDislike,
7 ActivityFollow,
8 ActivityLike,
9 ActivityUndo,
10 ContextType
11 } from '@shared/models'
12 import { logger } from '../../../helpers/logger'
13 import { VideoModel } from '../../../models/video/video'
14 import {
15 MActor,
16 MActorAudience,
17 MActorFollowActors,
18 MActorLight,
19 MVideo,
20 MVideoAccountLight,
21 MVideoRedundancyVideo,
22 MVideoShare
23 } from '../../../types/models'
24 import { audiencify, getAudience } from '../audience'
25 import { getUndoActivityPubUrl, getVideoDislikeActivityPubUrlByLocalActor, getVideoLikeActivityPubUrlByLocalActor } from '../url'
26 import { buildAnnounceWithVideoAudience } from './send-announce'
27 import { buildCreateActivity } from './send-create'
28 import { buildDislikeActivity } from './send-dislike'
29 import { buildFollowActivity } from './send-follow'
30 import { buildLikeActivity } from './send-like'
31 import { broadcastToFollowers, sendVideoActivityToOrigin, sendVideoRelatedActivity, unicastTo } from './shared/send-utils'
32
33 function sendUndoFollow (actorFollow: MActorFollowActors, t: Transaction) {
34 const me = actorFollow.ActorFollower
35 const following = actorFollow.ActorFollowing
36
37 // Same server as ours
38 if (!following.serverId) return
39
40 logger.info('Creating job to send an unfollow request to %s.', following.url)
41
42 const undoUrl = getUndoActivityPubUrl(actorFollow.url)
43
44 const followActivity = buildFollowActivity(actorFollow.url, me, following)
45 const undoActivity = undoActivityData(undoUrl, me, followActivity)
46
47 return t.afterCommit(() => {
48 return unicastTo({
49 data: undoActivity,
50 byActor: me,
51 toActorUrl: following.inboxUrl,
52 contextType: 'Follow'
53 })
54 })
55 }
56
57 // ---------------------------------------------------------------------------
58
59 async function sendUndoAnnounce (byActor: MActorLight, videoShare: MVideoShare, video: MVideo, transaction: Transaction) {
60 logger.info('Creating job to undo announce %s.', videoShare.url)
61
62 const undoUrl = getUndoActivityPubUrl(videoShare.url)
63
64 const { activity: announce, actorsInvolvedInVideo } = await buildAnnounceWithVideoAudience(byActor, videoShare, video, transaction)
65 const undoActivity = undoActivityData(undoUrl, byActor, announce)
66
67 return broadcastToFollowers({
68 data: undoActivity,
69 byActor,
70 toFollowersOf: actorsInvolvedInVideo,
71 transaction,
72 actorsException: [ byActor ],
73 contextType: 'Announce'
74 })
75 }
76
77 async function sendUndoCacheFile (byActor: MActor, redundancyModel: MVideoRedundancyVideo, transaction: Transaction) {
78 logger.info('Creating job to undo cache file %s.', redundancyModel.url)
79
80 const associatedVideo = redundancyModel.getVideo()
81 if (!associatedVideo) {
82 logger.warn('Cannot send undo activity for redundancy %s: no video files associated.', redundancyModel.url)
83 return
84 }
85
86 const video = await VideoModel.loadAndPopulateAccountAndServerAndTags(associatedVideo.id)
87 const createActivity = buildCreateActivity(redundancyModel.url, byActor, redundancyModel.toActivityPubObject())
88
89 return sendUndoVideoRelatedActivity({
90 byActor,
91 video,
92 url: redundancyModel.url,
93 activity: createActivity,
94 contextType: 'CacheFile',
95 transaction
96 })
97 }
98
99 // ---------------------------------------------------------------------------
100
101 async function sendUndoLike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
102 logger.info('Creating job to undo a like of video %s.', video.url)
103
104 const likeUrl = getVideoLikeActivityPubUrlByLocalActor(byActor, video)
105 const likeActivity = buildLikeActivity(likeUrl, byActor, video)
106
107 return sendUndoVideoRateToOriginActivity({ byActor, video, url: likeUrl, activity: likeActivity, transaction: t })
108 }
109
110 async function sendUndoDislike (byActor: MActor, video: MVideoAccountLight, t: Transaction) {
111 logger.info('Creating job to undo a dislike of video %s.', video.url)
112
113 const dislikeUrl = getVideoDislikeActivityPubUrlByLocalActor(byActor, video)
114 const dislikeActivity = buildDislikeActivity(dislikeUrl, byActor, video)
115
116 return sendUndoVideoRateToOriginActivity({ byActor, video, url: dislikeUrl, activity: dislikeActivity, transaction: t })
117 }
118
119 // ---------------------------------------------------------------------------
120
121 export {
122 sendUndoFollow,
123 sendUndoLike,
124 sendUndoDislike,
125 sendUndoAnnounce,
126 sendUndoCacheFile
127 }
128
129 // ---------------------------------------------------------------------------
130
131 function undoActivityData (
132 url: string,
133 byActor: MActorAudience,
134 object: ActivityFollow | ActivityLike | ActivityDislike | ActivityCreate | ActivityAnnounce,
135 audience?: ActivityAudience
136 ): ActivityUndo {
137 if (!audience) audience = getAudience(byActor)
138
139 return audiencify(
140 {
141 type: 'Undo' as 'Undo',
142 id: url,
143 actor: byActor.url,
144 object
145 },
146 audience
147 )
148 }
149
150 async function sendUndoVideoRelatedActivity (options: {
151 byActor: MActor
152 video: MVideoAccountLight
153 url: string
154 activity: ActivityFollow | ActivityCreate | ActivityAnnounce
155 contextType: ContextType
156 transaction: Transaction
157 }) {
158 const activityBuilder = (audience: ActivityAudience) => {
159 const undoUrl = getUndoActivityPubUrl(options.url)
160
161 return undoActivityData(undoUrl, options.byActor, options.activity, audience)
162 }
163
164 return sendVideoRelatedActivity(activityBuilder, options)
165 }
166
167 async function sendUndoVideoRateToOriginActivity (options: {
168 byActor: MActor
169 video: MVideoAccountLight
170 url: string
171 activity: ActivityLike | ActivityDislike
172 transaction: Transaction
173 }) {
174 const activityBuilder = (audience: ActivityAudience) => {
175 const undoUrl = getUndoActivityPubUrl(options.url)
176
177 return undoActivityData(undoUrl, options.byActor, options.activity, audience)
178 }
179
180 return sendVideoActivityToOrigin(activityBuilder, { ...options, contextType: 'Rate' })
181 }