aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/process/process-undo.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/activitypub/process/process-undo.ts')
-rw-r--r--server/lib/activitypub/process/process-undo.ts183
1 files changed, 0 insertions, 183 deletions
diff --git a/server/lib/activitypub/process/process-undo.ts b/server/lib/activitypub/process/process-undo.ts
deleted file mode 100644
index a9d8199de..000000000
--- a/server/lib/activitypub/process/process-undo.ts
+++ /dev/null
@@ -1,183 +0,0 @@
1import { VideoModel } from '@server/models/video/video'
2import {
3 ActivityAnnounce,
4 ActivityCreate,
5 ActivityDislike,
6 ActivityFollow,
7 ActivityLike,
8 ActivityUndo,
9 ActivityUndoObject,
10 CacheFileObject
11} from '../../../../shared/models/activitypub'
12import { retryTransactionWrapper } from '../../../helpers/database-utils'
13import { logger } from '../../../helpers/logger'
14import { sequelizeTypescript } from '../../../initializers/database'
15import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
16import { ActorModel } from '../../../models/actor/actor'
17import { ActorFollowModel } from '../../../models/actor/actor-follow'
18import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy'
19import { VideoShareModel } from '../../../models/video/video-share'
20import { APProcessorOptions } from '../../../types/activitypub-processor.model'
21import { MActorSignature } from '../../../types/models'
22import { fetchAPObjectIfNeeded } from '../activity'
23import { forwardVideoRelatedActivity } from '../send/shared/send-utils'
24import { federateVideoIfNeeded, getOrCreateAPVideo } from '../videos'
25
26async function processUndoActivity (options: APProcessorOptions<ActivityUndo<ActivityUndoObject>>) {
27 const { activity, byActor } = options
28 const activityToUndo = activity.object
29
30 if (activityToUndo.type === 'Like') {
31 return retryTransactionWrapper(processUndoLike, byActor, activity)
32 }
33
34 if (activityToUndo.type === 'Create') {
35 const objectToUndo = await fetchAPObjectIfNeeded<CacheFileObject>(activityToUndo.object)
36
37 if (objectToUndo.type === 'CacheFile') {
38 return retryTransactionWrapper(processUndoCacheFile, byActor, activity, objectToUndo)
39 }
40 }
41
42 if (activityToUndo.type === 'Dislike') {
43 return retryTransactionWrapper(processUndoDislike, byActor, activity)
44 }
45
46 if (activityToUndo.type === 'Follow') {
47 return retryTransactionWrapper(processUndoFollow, byActor, activityToUndo)
48 }
49
50 if (activityToUndo.type === 'Announce') {
51 return retryTransactionWrapper(processUndoAnnounce, byActor, activityToUndo)
52 }
53
54 logger.warn('Unknown activity object type %s -> %s when undo activity.', activityToUndo.type, { activity: activity.id })
55
56 return undefined
57}
58
59// ---------------------------------------------------------------------------
60
61export {
62 processUndoActivity
63}
64
65// ---------------------------------------------------------------------------
66
67async function processUndoLike (byActor: MActorSignature, activity: ActivityUndo<ActivityLike>) {
68 const likeActivity = activity.object
69
70 const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: likeActivity.object })
71 // We don't care about likes of remote videos
72 if (!onlyVideo.isOwned()) return
73
74 return sequelizeTypescript.transaction(async t => {
75 if (!byActor.Account) throw new Error('Unknown account ' + byActor.url)
76
77 const video = await VideoModel.loadFull(onlyVideo.id, t)
78 const rate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byActor.Account.id, video.id, likeActivity.id, t)
79 if (!rate || rate.type !== 'like') {
80 logger.warn('Unknown like by account %d for video %d.', byActor.Account.id, video.id)
81 return
82 }
83
84 await rate.destroy({ transaction: t })
85 await video.decrement('likes', { transaction: t })
86
87 video.likes--
88 await federateVideoIfNeeded(video, false, t)
89 })
90}
91
92async function processUndoDislike (byActor: MActorSignature, activity: ActivityUndo<ActivityDislike>) {
93 const dislikeActivity = activity.object
94
95 const { video: onlyVideo } = await getOrCreateAPVideo({ videoObject: dislikeActivity.object })
96 // We don't care about likes of remote videos
97 if (!onlyVideo.isOwned()) return
98
99 return sequelizeTypescript.transaction(async t => {
100 if (!byActor.Account) throw new Error('Unknown account ' + byActor.url)
101
102 const video = await VideoModel.loadFull(onlyVideo.id, t)
103 const rate = await AccountVideoRateModel.loadByAccountAndVideoOrUrl(byActor.Account.id, video.id, dislikeActivity.id, t)
104 if (!rate || rate.type !== 'dislike') {
105 logger.warn(`Unknown dislike by account %d for video %d.`, byActor.Account.id, video.id)
106 return
107 }
108
109 await rate.destroy({ transaction: t })
110 await video.decrement('dislikes', { transaction: t })
111 video.dislikes--
112
113 await federateVideoIfNeeded(video, false, t)
114 })
115}
116
117// ---------------------------------------------------------------------------
118
119async function processUndoCacheFile (
120 byActor: MActorSignature,
121 activity: ActivityUndo<ActivityCreate<CacheFileObject>>,
122 cacheFileObject: CacheFileObject
123) {
124 const { video } = await getOrCreateAPVideo({ videoObject: cacheFileObject.object })
125
126 return sequelizeTypescript.transaction(async t => {
127 const cacheFile = await VideoRedundancyModel.loadByUrl(cacheFileObject.id, t)
128 if (!cacheFile) {
129 logger.debug('Cannot undo unknown video cache %s.', cacheFileObject.id)
130 return
131 }
132
133 if (cacheFile.actorId !== byActor.id) throw new Error('Cannot delete redundancy ' + cacheFile.url + ' of another actor.')
134
135 await cacheFile.destroy({ transaction: t })
136
137 if (video.isOwned()) {
138 // Don't resend the activity to the sender
139 const exceptions = [ byActor ]
140
141 await forwardVideoRelatedActivity(activity, t, exceptions, video)
142 }
143 })
144}
145
146function processUndoAnnounce (byActor: MActorSignature, announceActivity: ActivityAnnounce) {
147 return sequelizeTypescript.transaction(async t => {
148 const share = await VideoShareModel.loadByUrl(announceActivity.id, t)
149 if (!share) {
150 logger.warn('Unknown video share %d', announceActivity.id)
151 return
152 }
153
154 if (share.actorId !== byActor.id) throw new Error(`${share.url} is not shared by ${byActor.url}.`)
155
156 await share.destroy({ transaction: t })
157
158 if (share.Video.isOwned()) {
159 // Don't resend the activity to the sender
160 const exceptions = [ byActor ]
161
162 await forwardVideoRelatedActivity(announceActivity, t, exceptions, share.Video)
163 }
164 })
165}
166
167// ---------------------------------------------------------------------------
168
169function processUndoFollow (follower: MActorSignature, followActivity: ActivityFollow) {
170 return sequelizeTypescript.transaction(async t => {
171 const following = await ActorModel.loadByUrlAndPopulateAccountAndChannel(followActivity.object, t)
172 const actorFollow = await ActorFollowModel.loadByActorAndTarget(follower.id, following.id, t)
173
174 if (!actorFollow) {
175 logger.warn('Unknown actor follow %d -> %d.', follower.id, following.id)
176 return
177 }
178
179 await actorFollow.destroy({ transaction: t })
180
181 return undefined
182 })
183}