diff options
Diffstat (limited to 'server/server/controllers/activitypub/client.ts')
-rw-r--r-- | server/server/controllers/activitypub/client.ts | 65 |
1 files changed, 63 insertions, 2 deletions
diff --git a/server/server/controllers/activitypub/client.ts b/server/server/controllers/activitypub/client.ts index 5d5e43bf5..1d5d269a9 100644 --- a/server/server/controllers/activitypub/client.ts +++ b/server/server/controllers/activitypub/client.ts | |||
@@ -1,6 +1,13 @@ | |||
1 | import cors from 'cors' | 1 | import cors from 'cors' |
2 | import express from 'express' | 2 | import express from 'express' |
3 | import { VideoCommentObject, VideoPlaylistPrivacy, VideoPrivacy, VideoRateType } from '@peertube/peertube-models' | 3 | import { |
4 | VideoChapterObject, | ||
5 | VideoChaptersObject, | ||
6 | VideoCommentObject, | ||
7 | VideoPlaylistPrivacy, | ||
8 | VideoPrivacy, | ||
9 | VideoRateType | ||
10 | } from '@peertube/peertube-models' | ||
4 | import { activityPubCollectionPagination } from '@server/lib/activitypub/collection.js' | 11 | import { activityPubCollectionPagination } from '@server/lib/activitypub/collection.js' |
5 | import { getContextFilter } from '@server/lib/activitypub/context.js' | 12 | import { getContextFilter } from '@server/lib/activitypub/context.js' |
6 | import { getServerActor } from '@server/models/application/application.js' | 13 | import { getServerActor } from '@server/models/application/application.js' |
@@ -12,12 +19,18 @@ import { buildAnnounceWithVideoAudience, buildLikeActivity } from '../../lib/act | |||
12 | import { buildCreateActivity } from '../../lib/activitypub/send/send-create.js' | 19 | import { buildCreateActivity } from '../../lib/activitypub/send/send-create.js' |
13 | import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike.js' | 20 | import { buildDislikeActivity } from '../../lib/activitypub/send/send-dislike.js' |
14 | import { | 21 | import { |
22 | getLocalVideoChaptersActivityPubUrl, | ||
15 | getLocalVideoCommentsActivityPubUrl, | 23 | getLocalVideoCommentsActivityPubUrl, |
16 | getLocalVideoDislikesActivityPubUrl, | 24 | getLocalVideoDislikesActivityPubUrl, |
17 | getLocalVideoLikesActivityPubUrl, | 25 | getLocalVideoLikesActivityPubUrl, |
18 | getLocalVideoSharesActivityPubUrl | 26 | getLocalVideoSharesActivityPubUrl |
19 | } from '../../lib/activitypub/url.js' | 27 | } from '../../lib/activitypub/url.js' |
20 | import { cacheRoute } from '../../middlewares/cache/cache.js' | 28 | import { |
29 | apVideoChaptersSetCacheKey, | ||
30 | buildAPVideoChaptersGroupsCache, | ||
31 | cacheRoute, | ||
32 | cacheRouteFactory | ||
33 | } from '../../middlewares/cache/cache.js' | ||
21 | import { | 34 | import { |
22 | activityPubRateLimiter, | 35 | activityPubRateLimiter, |
23 | asyncMiddleware, | 36 | asyncMiddleware, |
@@ -42,6 +55,8 @@ import { VideoCommentModel } from '../../models/video/video-comment.js' | |||
42 | import { VideoPlaylistModel } from '../../models/video/video-playlist.js' | 55 | import { VideoPlaylistModel } from '../../models/video/video-playlist.js' |
43 | import { VideoShareModel } from '../../models/video/video-share.js' | 56 | import { VideoShareModel } from '../../models/video/video-share.js' |
44 | import { activityPubResponse } from './utils.js' | 57 | import { activityPubResponse } from './utils.js' |
58 | import { VideoChapterModel } from '@server/models/video/video-chapter.js' | ||
59 | import { InternalEventEmitter } from '@server/lib/internal-event-emitter.js' | ||
45 | 60 | ||
46 | const activityPubClientRouter = express.Router() | 61 | const activityPubClientRouter = express.Router() |
47 | activityPubClientRouter.use(cors()) | 62 | activityPubClientRouter.use(cors()) |
@@ -145,6 +160,27 @@ activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId/activity | |||
145 | asyncMiddleware(videoCommentController) | 160 | asyncMiddleware(videoCommentController) |
146 | ) | 161 | ) |
147 | 162 | ||
163 | // --------------------------------------------------------------------------- | ||
164 | |||
165 | const { middleware: chaptersCacheRouteMiddleware, instance: chaptersApiCache } = cacheRouteFactory() | ||
166 | |||
167 | InternalEventEmitter.Instance.on('chapters-updated', ({ video }) => { | ||
168 | if (video.remote) return | ||
169 | |||
170 | chaptersApiCache.clearGroupSafe(buildAPVideoChaptersGroupsCache({ videoId: video.uuid })) | ||
171 | }) | ||
172 | |||
173 | activityPubClientRouter.get('/videos/watch/:id/chapters', | ||
174 | executeIfActivityPub, | ||
175 | activityPubRateLimiter, | ||
176 | apVideoChaptersSetCacheKey, | ||
177 | chaptersCacheRouteMiddleware(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS), | ||
178 | asyncMiddleware(videosCustomGetValidator('only-video')), | ||
179 | asyncMiddleware(videoChaptersController) | ||
180 | ) | ||
181 | |||
182 | // --------------------------------------------------------------------------- | ||
183 | |||
148 | activityPubClientRouter.get( | 184 | activityPubClientRouter.get( |
149 | [ '/video-channels/:nameWithHost', '/video-channels/:nameWithHost/videos', '/c/:nameWithHost', '/c/:nameWithHost/videos' ], | 185 | [ '/video-channels/:nameWithHost', '/video-channels/:nameWithHost/videos', '/c/:nameWithHost', '/c/:nameWithHost/videos' ], |
150 | executeIfActivityPub, | 186 | executeIfActivityPub, |
@@ -390,6 +426,31 @@ async function videoCommentController (req: express.Request, res: express.Respon | |||
390 | return activityPubResponse(activityPubContextify(videoCommentObject, 'Comment', getContextFilter()), res) | 426 | return activityPubResponse(activityPubContextify(videoCommentObject, 'Comment', getContextFilter()), res) |
391 | } | 427 | } |
392 | 428 | ||
429 | async function videoChaptersController (req: express.Request, res: express.Response) { | ||
430 | const video = res.locals.onlyVideo | ||
431 | |||
432 | if (redirectIfNotOwned(video.url, res)) return | ||
433 | |||
434 | const chapters = await VideoChapterModel.listChaptersOfVideo(video.id) | ||
435 | |||
436 | const hasPart: VideoChapterObject[] = [] | ||
437 | |||
438 | if (chapters.length !== 0) { | ||
439 | for (let i = 0; i < chapters.length - 1; i++) { | ||
440 | hasPart.push(chapters[i].toActivityPubJSON({ video, nextChapter: chapters[i + 1] })) | ||
441 | } | ||
442 | |||
443 | hasPart.push(chapters[chapters.length - 1].toActivityPubJSON({ video: res.locals.onlyVideo, nextChapter: null })) | ||
444 | } | ||
445 | |||
446 | const chaptersObject: VideoChaptersObject = { | ||
447 | id: getLocalVideoChaptersActivityPubUrl(video), | ||
448 | hasPart | ||
449 | } | ||
450 | |||
451 | return activityPubResponse(activityPubContextify(chaptersObject, 'Chapters', getContextFilter()), res) | ||
452 | } | ||
453 | |||
393 | async function videoRedundancyController (req: express.Request, res: express.Response) { | 454 | async function videoRedundancyController (req: express.Request, res: express.Response) { |
394 | const videoRedundancy = res.locals.videoRedundancy | 455 | const videoRedundancy = res.locals.videoRedundancy |
395 | 456 | ||