aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers/activitypub/client.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers/activitypub/client.ts')
-rw-r--r--server/controllers/activitypub/client.ts86
1 files changed, 63 insertions, 23 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts
index 433186179..31c0a5fbd 100644
--- a/server/controllers/activitypub/client.ts
+++ b/server/controllers/activitypub/client.ts
@@ -3,7 +3,7 @@ import * as express from 'express'
3import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos' 3import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
4import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub' 4import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub'
5import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers' 5import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
6import { buildAnnounceWithVideoAudience } from '../../lib/activitypub/send' 6import { buildAnnounceWithVideoAudience, buildLikeActivity } from '../../lib/activitypub/send'
7import { audiencify, getAudience } from '../../lib/activitypub/audience' 7import { audiencify, getAudience } from '../../lib/activitypub/audience'
8import { buildCreateActivity } from '../../lib/activitypub/send/send-create' 8import { buildCreateActivity } from '../../lib/activitypub/send/send-create'
9import { 9import {
@@ -11,9 +11,10 @@ import {
11 executeIfActivityPub, 11 executeIfActivityPub,
12 localAccountValidator, 12 localAccountValidator,
13 localVideoChannelValidator, 13 localVideoChannelValidator,
14 videosCustomGetValidator 14 videosCustomGetValidator,
15 videosShareValidator
15} from '../../middlewares' 16} from '../../middlewares'
16import { videoCommentGetValidator, videosGetValidator, videosShareValidator } from '../../middlewares/validators' 17import { getAccountVideoRateValidator, videoCommentGetValidator, videosGetValidator } from '../../middlewares/validators'
17import { AccountModel } from '../../models/account/account' 18import { AccountModel } from '../../models/account/account'
18import { ActorModel } from '../../models/activitypub/actor' 19import { ActorModel } from '../../models/activitypub/actor'
19import { ActorFollowModel } from '../../models/activitypub/actor-follow' 20import { ActorFollowModel } from '../../models/activitypub/actor-follow'
@@ -25,14 +26,17 @@ import { cacheRoute } from '../../middlewares/cache'
25import { activityPubResponse } from './utils' 26import { activityPubResponse } from './utils'
26import { AccountVideoRateModel } from '../../models/account/account-video-rate' 27import { AccountVideoRateModel } from '../../models/account/account-video-rate'
27import { 28import {
29 getRateUrl,
28 getVideoCommentsActivityPubUrl, 30 getVideoCommentsActivityPubUrl,
29 getVideoDislikesActivityPubUrl, 31 getVideoDislikesActivityPubUrl,
30 getVideoLikesActivityPubUrl, 32 getVideoLikesActivityPubUrl,
31 getVideoSharesActivityPubUrl 33 getVideoSharesActivityPubUrl
32} from '../../lib/activitypub' 34} from '../../lib/activitypub'
33import { VideoCaptionModel } from '../../models/video/video-caption' 35import { VideoCaptionModel } from '../../models/video/video-caption'
34import { videoRedundancyGetValidator } from '../../middlewares/validators/redundancy' 36import { videoFileRedundancyGetValidator, videoPlaylistRedundancyGetValidator } from '../../middlewares/validators/redundancy'
35import { getServerActor } from '../../helpers/utils' 37import { getServerActor } from '../../helpers/utils'
38import { VideoRedundancyModel } from '../../models/redundancy/video-redundancy'
39import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike'
36 40
37const activityPubClientRouter = express.Router() 41const activityPubClientRouter = express.Router()
38 42
@@ -48,21 +52,29 @@ activityPubClientRouter.get('/accounts?/:name/following',
48 executeIfActivityPub(asyncMiddleware(localAccountValidator)), 52 executeIfActivityPub(asyncMiddleware(localAccountValidator)),
49 executeIfActivityPub(asyncMiddleware(accountFollowingController)) 53 executeIfActivityPub(asyncMiddleware(accountFollowingController))
50) 54)
55activityPubClientRouter.get('/accounts?/:name/likes/:videoId',
56 executeIfActivityPub(asyncMiddleware(getAccountVideoRateValidator('like'))),
57 executeIfActivityPub(getAccountVideoRate('like'))
58)
59activityPubClientRouter.get('/accounts?/:name/dislikes/:videoId',
60 executeIfActivityPub(asyncMiddleware(getAccountVideoRateValidator('dislike'))),
61 executeIfActivityPub(getAccountVideoRate('dislike'))
62)
51 63
52activityPubClientRouter.get('/videos/watch/:id', 64activityPubClientRouter.get('/videos/watch/:id',
53 executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))), 65 executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))),
54 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 66 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video-with-rights'))),
55 executeIfActivityPub(asyncMiddleware(videoController)) 67 executeIfActivityPub(asyncMiddleware(videoController))
56) 68)
57activityPubClientRouter.get('/videos/watch/:id/activity', 69activityPubClientRouter.get('/videos/watch/:id/activity',
58 executeIfActivityPub(asyncMiddleware(videosGetValidator)), 70 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video-with-rights'))),
59 executeIfActivityPub(asyncMiddleware(videoController)) 71 executeIfActivityPub(asyncMiddleware(videoController))
60) 72)
61activityPubClientRouter.get('/videos/watch/:id/announces', 73activityPubClientRouter.get('/videos/watch/:id/announces',
62 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))), 74 executeIfActivityPub(asyncMiddleware(videosCustomGetValidator('only-video'))),
63 executeIfActivityPub(asyncMiddleware(videoAnnouncesController)) 75 executeIfActivityPub(asyncMiddleware(videoAnnouncesController))
64) 76)
65activityPubClientRouter.get('/videos/watch/:id/announces/:accountId', 77activityPubClientRouter.get('/videos/watch/:id/announces/:actorId',
66 executeIfActivityPub(asyncMiddleware(videosShareValidator)), 78 executeIfActivityPub(asyncMiddleware(videosShareValidator)),
67 executeIfActivityPub(asyncMiddleware(videoAnnounceController)) 79 executeIfActivityPub(asyncMiddleware(videoAnnounceController))
68) 80)
@@ -101,7 +113,11 @@ activityPubClientRouter.get('/video-channels/:name/following',
101) 113)
102 114
103activityPubClientRouter.get('/redundancy/videos/:videoId/:resolution([0-9]+)(-:fps([0-9]+))?', 115activityPubClientRouter.get('/redundancy/videos/:videoId/:resolution([0-9]+)(-:fps([0-9]+))?',
104 executeIfActivityPub(asyncMiddleware(videoRedundancyGetValidator)), 116 executeIfActivityPub(asyncMiddleware(videoFileRedundancyGetValidator)),
117 executeIfActivityPub(asyncMiddleware(videoRedundancyController))
118)
119activityPubClientRouter.get('/redundancy/video-playlists/:streamingPlaylistType/:videoId',
120 executeIfActivityPub(asyncMiddleware(videoPlaylistRedundancyGetValidator)),
105 executeIfActivityPub(asyncMiddleware(videoRedundancyController)) 121 executeIfActivityPub(asyncMiddleware(videoRedundancyController))
106) 122)
107 123
@@ -133,8 +149,25 @@ async function accountFollowingController (req: express.Request, res: express.Re
133 return activityPubResponse(activityPubContextify(activityPubResult), res) 149 return activityPubResponse(activityPubContextify(activityPubResult), res)
134} 150}
135 151
136async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) { 152function getAccountVideoRate (rateType: VideoRateType) {
137 const video: VideoModel = res.locals.video 153 return (req: express.Request, res: express.Response) => {
154 const accountVideoRate: AccountVideoRateModel = res.locals.accountVideoRate
155
156 const byActor = accountVideoRate.Account.Actor
157 const url = getRateUrl(rateType, byActor, accountVideoRate.Video)
158 const APObject = rateType === 'like'
159 ? buildLikeActivity(url, byActor, accountVideoRate.Video)
160 : buildDislikeActivity(url, byActor, accountVideoRate.Video)
161
162 return activityPubResponse(activityPubContextify(APObject), res)
163 }
164}
165
166async function videoController (req: express.Request, res: express.Response) {
167 // We need more attributes
168 const video: VideoModel = await VideoModel.loadForGetAPI(res.locals.video.id)
169
170 if (video.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(video.url)
138 171
139 // We need captions to render AP object 172 // We need captions to render AP object
140 video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id) 173 video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id)
@@ -150,14 +183,17 @@ async function videoController (req: express.Request, res: express.Response, nex
150 return activityPubResponse(activityPubContextify(videoObject), res) 183 return activityPubResponse(activityPubContextify(videoObject), res)
151} 184}
152 185
153async function videoAnnounceController (req: express.Request, res: express.Response, next: express.NextFunction) { 186async function videoAnnounceController (req: express.Request, res: express.Response) {
154 const share = res.locals.videoShare as VideoShareModel 187 const share = res.locals.videoShare as VideoShareModel
188
189 if (share.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(share.url)
190
155 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined) 191 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined)
156 192
157 return activityPubResponse(activityPubContextify(activity), res) 193 return activityPubResponse(activityPubContextify(activity), res)
158} 194}
159 195
160async function videoAnnouncesController (req: express.Request, res: express.Response, next: express.NextFunction) { 196async function videoAnnouncesController (req: express.Request, res: express.Response) {
161 const video: VideoModel = res.locals.video 197 const video: VideoModel = res.locals.video
162 198
163 const handler = async (start: number, count: number) => { 199 const handler = async (start: number, count: number) => {
@@ -172,21 +208,21 @@ async function videoAnnouncesController (req: express.Request, res: express.Resp
172 return activityPubResponse(activityPubContextify(json), res) 208 return activityPubResponse(activityPubContextify(json), res)
173} 209}
174 210
175async function videoLikesController (req: express.Request, res: express.Response, next: express.NextFunction) { 211async function videoLikesController (req: express.Request, res: express.Response) {
176 const video: VideoModel = res.locals.video 212 const video: VideoModel = res.locals.video
177 const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video)) 213 const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video))
178 214
179 return activityPubResponse(activityPubContextify(json), res) 215 return activityPubResponse(activityPubContextify(json), res)
180} 216}
181 217
182async function videoDislikesController (req: express.Request, res: express.Response, next: express.NextFunction) { 218async function videoDislikesController (req: express.Request, res: express.Response) {
183 const video: VideoModel = res.locals.video 219 const video: VideoModel = res.locals.video
184 const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video)) 220 const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video))
185 221
186 return activityPubResponse(activityPubContextify(json), res) 222 return activityPubResponse(activityPubContextify(json), res)
187} 223}
188 224
189async function videoCommentsController (req: express.Request, res: express.Response, next: express.NextFunction) { 225async function videoCommentsController (req: express.Request, res: express.Response) {
190 const video: VideoModel = res.locals.video 226 const video: VideoModel = res.locals.video
191 227
192 const handler = async (start: number, count: number) => { 228 const handler = async (start: number, count: number) => {
@@ -201,29 +237,31 @@ async function videoCommentsController (req: express.Request, res: express.Respo
201 return activityPubResponse(activityPubContextify(json), res) 237 return activityPubResponse(activityPubContextify(json), res)
202} 238}
203 239
204async function videoChannelController (req: express.Request, res: express.Response, next: express.NextFunction) { 240async function videoChannelController (req: express.Request, res: express.Response) {
205 const videoChannel: VideoChannelModel = res.locals.videoChannel 241 const videoChannel: VideoChannelModel = res.locals.videoChannel
206 242
207 return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res) 243 return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res)
208} 244}
209 245
210async function videoChannelFollowersController (req: express.Request, res: express.Response, next: express.NextFunction) { 246async function videoChannelFollowersController (req: express.Request, res: express.Response) {
211 const videoChannel: VideoChannelModel = res.locals.videoChannel 247 const videoChannel: VideoChannelModel = res.locals.videoChannel
212 const activityPubResult = await actorFollowers(req, videoChannel.Actor) 248 const activityPubResult = await actorFollowers(req, videoChannel.Actor)
213 249
214 return activityPubResponse(activityPubContextify(activityPubResult), res) 250 return activityPubResponse(activityPubContextify(activityPubResult), res)
215} 251}
216 252
217async function videoChannelFollowingController (req: express.Request, res: express.Response, next: express.NextFunction) { 253async function videoChannelFollowingController (req: express.Request, res: express.Response) {
218 const videoChannel: VideoChannelModel = res.locals.videoChannel 254 const videoChannel: VideoChannelModel = res.locals.videoChannel
219 const activityPubResult = await actorFollowing(req, videoChannel.Actor) 255 const activityPubResult = await actorFollowing(req, videoChannel.Actor)
220 256
221 return activityPubResponse(activityPubContextify(activityPubResult), res) 257 return activityPubResponse(activityPubContextify(activityPubResult), res)
222} 258}
223 259
224async function videoCommentController (req: express.Request, res: express.Response, next: express.NextFunction) { 260async function videoCommentController (req: express.Request, res: express.Response) {
225 const videoComment: VideoCommentModel = res.locals.videoComment 261 const videoComment: VideoCommentModel = res.locals.videoComment
226 262
263 if (videoComment.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoComment.url)
264
227 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) 265 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined)
228 const isPublic = true // Comments are always public 266 const isPublic = true // Comments are always public
229 const audience = getAudience(videoComment.Account.Actor, isPublic) 267 const audience = getAudience(videoComment.Account.Actor, isPublic)
@@ -239,7 +277,9 @@ async function videoCommentController (req: express.Request, res: express.Respon
239} 277}
240 278
241async function videoRedundancyController (req: express.Request, res: express.Response) { 279async function videoRedundancyController (req: express.Request, res: express.Response) {
242 const videoRedundancy = res.locals.videoRedundancy 280 const videoRedundancy: VideoRedundancyModel = res.locals.videoRedundancy
281 if (videoRedundancy.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoRedundancy.url)
282
243 const serverActor = await getServerActor() 283 const serverActor = await getServerActor()
244 284
245 const audience = getAudience(serverActor) 285 const audience = getAudience(serverActor)
@@ -260,7 +300,7 @@ async function actorFollowing (req: express.Request, actor: ActorModel) {
260 return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count) 300 return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count)
261 } 301 }
262 302
263 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.url, handler, req.query.page) 303 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
264} 304}
265 305
266async function actorFollowers (req: express.Request, actor: ActorModel) { 306async function actorFollowers (req: express.Request, actor: ActorModel) {
@@ -268,7 +308,7 @@ async function actorFollowers (req: express.Request, actor: ActorModel) {
268 return ActorFollowModel.listAcceptedFollowerUrlsForApi([ actor.id ], undefined, start, count) 308 return ActorFollowModel.listAcceptedFollowerUrlsForApi([ actor.id ], undefined, start, count)
269 } 309 }
270 310
271 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.url, handler, req.query.page) 311 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.path, handler, req.query.page)
272} 312}
273 313
274function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) { 314function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) {
@@ -276,7 +316,7 @@ function videoRates (req: express.Request, rateType: VideoRateType, video: Video
276 const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count) 316 const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count)
277 return { 317 return {
278 total: result.count, 318 total: result.count,
279 data: result.rows.map(r => r.Account.Actor.url) 319 data: result.rows.map(r => r.url)
280 } 320 }
281 } 321 }
282 return activityPubCollectionPagination(url, handler, req.query.page) 322 return activityPubCollectionPagination(url, handler, req.query.page)