diff options
Diffstat (limited to 'server/lib/activitypub/process/process-undo.ts')
-rw-r--r-- | server/lib/activitypub/process/process-undo.ts | 183 |
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 @@ | |||
1 | import { VideoModel } from '@server/models/video/video' | ||
2 | import { | ||
3 | ActivityAnnounce, | ||
4 | ActivityCreate, | ||
5 | ActivityDislike, | ||
6 | ActivityFollow, | ||
7 | ActivityLike, | ||
8 | ActivityUndo, | ||
9 | ActivityUndoObject, | ||
10 | CacheFileObject | ||
11 | } from '../../../../shared/models/activitypub' | ||
12 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | ||
13 | import { logger } from '../../../helpers/logger' | ||
14 | import { sequelizeTypescript } from '../../../initializers/database' | ||
15 | import { AccountVideoRateModel } from '../../../models/account/account-video-rate' | ||
16 | import { ActorModel } from '../../../models/actor/actor' | ||
17 | import { ActorFollowModel } from '../../../models/actor/actor-follow' | ||
18 | import { VideoRedundancyModel } from '../../../models/redundancy/video-redundancy' | ||
19 | import { VideoShareModel } from '../../../models/video/video-share' | ||
20 | import { APProcessorOptions } from '../../../types/activitypub-processor.model' | ||
21 | import { MActorSignature } from '../../../types/models' | ||
22 | import { fetchAPObjectIfNeeded } from '../activity' | ||
23 | import { forwardVideoRelatedActivity } from '../send/shared/send-utils' | ||
24 | import { federateVideoIfNeeded, getOrCreateAPVideo } from '../videos' | ||
25 | |||
26 | async 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 | |||
61 | export { | ||
62 | processUndoActivity | ||
63 | } | ||
64 | |||
65 | // --------------------------------------------------------------------------- | ||
66 | |||
67 | async 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 | |||
92 | async 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 | |||
119 | async 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 | |||
146 | function 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 | |||
169 | function 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 | } | ||