]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blame - server/controllers/activitypub/client.ts
Raw query to get video ids
[github/Chocobozzz/PeerTube.git] / server / controllers / activitypub / client.ts
CommitLineData
e4f97bab
C
1// Intercept ActivityPub client requests
2import * as express from 'express'
8fffe21a 3import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
d6e99e53 4import { activityPubCollectionPagination, activityPubContextify } from '../../helpers/activitypub'
8fffe21a 5import { CONFIG, ROUTE_CACHE_LIFETIME } from '../../initializers'
c48e82b5 6import { buildAnnounceWithVideoAudience } from '../../lib/activitypub/send'
e251f170 7import { audiencify, getAudience } from '../../lib/activitypub/audience'
c48e82b5 8import { buildCreateActivity } from '../../lib/activitypub/send/send-create'
8a19bee1
C
9import { asyncMiddleware, executeIfActivityPub, localAccountValidator, localVideoChannelValidator } from '../../middlewares'
10import { videosGetValidator, videosShareValidator } from '../../middlewares/validators'
da854ddd 11import { videoCommentGetValidator } from '../../middlewares/validators/video-comments'
3fd3ab2d 12import { AccountModel } from '../../models/account/account'
7006bc63 13import { ActorModel } from '../../models/activitypub/actor'
50d6de9c 14import { ActorFollowModel } from '../../models/activitypub/actor-follow'
3fd3ab2d
C
15import { VideoModel } from '../../models/video/video'
16import { VideoChannelModel } from '../../models/video/video-channel'
da854ddd 17import { VideoCommentModel } from '../../models/video/video-comment'
3fd3ab2d 18import { VideoShareModel } from '../../models/video/video-share'
98d3324d 19import { cacheRoute } from '../../middlewares/cache'
8fffe21a
C
20import { activityPubResponse } from './utils'
21import { AccountVideoRateModel } from '../../models/account/account-video-rate'
22import {
23 getVideoCommentsActivityPubUrl,
24 getVideoDislikesActivityPubUrl,
25 getVideoLikesActivityPubUrl,
26 getVideoSharesActivityPubUrl
27} from '../../lib/activitypub'
40e87e9e 28import { VideoCaptionModel } from '../../models/video/video-caption'
c48e82b5
C
29import { videoRedundancyGetValidator } from '../../middlewares/validators/redundancy'
30import { getServerActor } from '../../helpers/utils'
e4f97bab
C
31
32const activityPubClientRouter = express.Router()
33
108af661 34activityPubClientRouter.get('/accounts?/:name',
a2431b7d 35 executeIfActivityPub(asyncMiddleware(localAccountValidator)),
4e50b6a1 36 executeIfActivityPub(accountController)
e4f97bab 37)
7006bc63 38activityPubClientRouter.get('/accounts?/:name/followers',
a2431b7d 39 executeIfActivityPub(asyncMiddleware(localAccountValidator)),
e4f97bab
C
40 executeIfActivityPub(asyncMiddleware(accountFollowersController))
41)
7006bc63 42activityPubClientRouter.get('/accounts?/:name/following',
a2431b7d 43 executeIfActivityPub(asyncMiddleware(localAccountValidator)),
e4f97bab
C
44 executeIfActivityPub(asyncMiddleware(accountFollowingController))
45)
46
20494f12 47activityPubClientRouter.get('/videos/watch/:id',
98d3324d 48 executeIfActivityPub(asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.ACTIVITY_PUB.VIDEOS))),
a2431b7d 49 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
da854ddd 50 executeIfActivityPub(asyncMiddleware(videoController))
4e50b6a1 51)
296c0905
C
52activityPubClientRouter.get('/videos/watch/:id/activity',
53 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
54 executeIfActivityPub(asyncMiddleware(videoController))
55)
46531a0a
C
56activityPubClientRouter.get('/videos/watch/:id/announces',
57 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
58 executeIfActivityPub(asyncMiddleware(videoAnnouncesController))
59)
4e50b6a1
C
60activityPubClientRouter.get('/videos/watch/:id/announces/:accountId',
61 executeIfActivityPub(asyncMiddleware(videosShareValidator)),
62 executeIfActivityPub(asyncMiddleware(videoAnnounceController))
20494f12 63)
46531a0a
C
64activityPubClientRouter.get('/videos/watch/:id/likes',
65 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
66 executeIfActivityPub(asyncMiddleware(videoLikesController))
67)
68activityPubClientRouter.get('/videos/watch/:id/dislikes',
69 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
70 executeIfActivityPub(asyncMiddleware(videoDislikesController))
71)
72activityPubClientRouter.get('/videos/watch/:id/comments',
73 executeIfActivityPub(asyncMiddleware(videosGetValidator)),
74 executeIfActivityPub(asyncMiddleware(videoCommentsController))
75)
da854ddd
C
76activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId',
77 executeIfActivityPub(asyncMiddleware(videoCommentGetValidator)),
78 executeIfActivityPub(asyncMiddleware(videoCommentController))
79)
296c0905
C
80activityPubClientRouter.get('/videos/watch/:videoId/comments/:commentId/activity',
81 executeIfActivityPub(asyncMiddleware(videoCommentGetValidator)),
82 executeIfActivityPub(asyncMiddleware(videoCommentController))
83)
da854ddd 84
8a19bee1
C
85activityPubClientRouter.get('/video-channels/:name',
86 executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)),
20494f12
C
87 executeIfActivityPub(asyncMiddleware(videoChannelController))
88)
8a19bee1
C
89activityPubClientRouter.get('/video-channels/:name/followers',
90 executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)),
7006bc63
C
91 executeIfActivityPub(asyncMiddleware(videoChannelFollowersController))
92)
8a19bee1
C
93activityPubClientRouter.get('/video-channels/:name/following',
94 executeIfActivityPub(asyncMiddleware(localVideoChannelValidator)),
7006bc63
C
95 executeIfActivityPub(asyncMiddleware(videoChannelFollowingController))
96)
20494f12 97
c48e82b5
C
98activityPubClientRouter.get('/redundancy/videos/:videoId/:resolution([0-9]+)(-:fps([0-9]+))?',
99 executeIfActivityPub(asyncMiddleware(videoRedundancyGetValidator)),
100 executeIfActivityPub(asyncMiddleware(videoRedundancyController))
101)
102
e4f97bab
C
103// ---------------------------------------------------------------------------
104
105export {
106 activityPubClientRouter
107}
108
109// ---------------------------------------------------------------------------
110
4e50b6a1 111function accountController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 112 const account: AccountModel = res.locals.account
e4f97bab 113
4b8f09fa 114 return activityPubResponse(activityPubContextify(account.toActivityPubObject()), res)
e4f97bab
C
115}
116
117async function accountFollowersController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 118 const account: AccountModel = res.locals.account
7006bc63 119 const activityPubResult = await actorFollowers(req, account.Actor)
e4f97bab 120
4b8f09fa 121 return activityPubResponse(activityPubContextify(activityPubResult), res)
e4f97bab
C
122}
123
124async function accountFollowingController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 125 const account: AccountModel = res.locals.account
7006bc63 126 const activityPubResult = await actorFollowing(req, account.Actor)
e4f97bab 127
4b8f09fa 128 return activityPubResponse(activityPubContextify(activityPubResult), res)
e4f97bab 129}
20494f12 130
da854ddd 131async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 132 const video: VideoModel = res.locals.video
20494f12 133
40e87e9e
C
134 // We need captions to render AP object
135 video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id)
136
2186386c 137 const audience = getAudience(video.VideoChannel.Account.Actor, video.privacy === VideoPrivacy.PUBLIC)
8fffe21a 138 const videoObject = audiencify(video.toActivityPubObject(), audience)
2ccaeeb3 139
296c0905 140 if (req.path.endsWith('/activity')) {
c48e82b5 141 const data = buildCreateActivity(video.url, video.VideoChannel.Account.Actor, videoObject, audience)
4b8f09fa 142 return activityPubResponse(activityPubContextify(data), res)
296c0905
C
143 }
144
4b8f09fa 145 return activityPubResponse(activityPubContextify(videoObject), res)
20494f12
C
146}
147
4e50b6a1 148async function videoAnnounceController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 149 const share = res.locals.videoShare as VideoShareModel
c48e82b5 150 const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined)
4e50b6a1 151
c48e82b5 152 return activityPubResponse(activityPubContextify(activity), res)
4e50b6a1
C
153}
154
46531a0a
C
155async function videoAnnouncesController (req: express.Request, res: express.Response, next: express.NextFunction) {
156 const video: VideoModel = res.locals.video
157
8fffe21a
C
158 const handler = async (start: number, count: number) => {
159 const result = await VideoShareModel.listAndCountByVideoId(video.id, start, count)
160 return {
161 total: result.count,
162 data: result.rows.map(r => r.url)
163 }
164 }
165 const json = await activityPubCollectionPagination(getVideoSharesActivityPubUrl(video), handler, req.query.page)
46531a0a 166
8fffe21a 167 return activityPubResponse(activityPubContextify(json), res)
46531a0a
C
168}
169
170async function videoLikesController (req: express.Request, res: express.Response, next: express.NextFunction) {
171 const video: VideoModel = res.locals.video
8fffe21a 172 const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video))
46531a0a 173
8fffe21a 174 return activityPubResponse(activityPubContextify(json), res)
46531a0a
C
175}
176
177async function videoDislikesController (req: express.Request, res: express.Response, next: express.NextFunction) {
178 const video: VideoModel = res.locals.video
8fffe21a 179 const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video))
46531a0a 180
8fffe21a 181 return activityPubResponse(activityPubContextify(json), res)
46531a0a
C
182}
183
184async function videoCommentsController (req: express.Request, res: express.Response, next: express.NextFunction) {
185 const video: VideoModel = res.locals.video
186
8fffe21a
C
187 const handler = async (start: number, count: number) => {
188 const result = await VideoCommentModel.listAndCountByVideoId(video.id, start, count)
189 return {
190 total: result.count,
191 data: result.rows.map(r => r.url)
192 }
193 }
194 const json = await activityPubCollectionPagination(getVideoCommentsActivityPubUrl(video), handler, req.query.page)
46531a0a 195
8fffe21a 196 return activityPubResponse(activityPubContextify(json), res)
46531a0a
C
197}
198
20494f12 199async function videoChannelController (req: express.Request, res: express.Response, next: express.NextFunction) {
3fd3ab2d 200 const videoChannel: VideoChannelModel = res.locals.videoChannel
20494f12 201
4b8f09fa 202 return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res)
20494f12 203}
da854ddd 204
7006bc63
C
205async function videoChannelFollowersController (req: express.Request, res: express.Response, next: express.NextFunction) {
206 const videoChannel: VideoChannelModel = res.locals.videoChannel
207 const activityPubResult = await actorFollowers(req, videoChannel.Actor)
208
4b8f09fa 209 return activityPubResponse(activityPubContextify(activityPubResult), res)
7006bc63
C
210}
211
212async function videoChannelFollowingController (req: express.Request, res: express.Response, next: express.NextFunction) {
213 const videoChannel: VideoChannelModel = res.locals.videoChannel
214 const activityPubResult = await actorFollowing(req, videoChannel.Actor)
215
4b8f09fa 216 return activityPubResponse(activityPubContextify(activityPubResult), res)
7006bc63
C
217}
218
da854ddd
C
219async function videoCommentController (req: express.Request, res: express.Response, next: express.NextFunction) {
220 const videoComment: VideoCommentModel = res.locals.videoComment
221
d7e70384 222 const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined)
d6e99e53 223 const isPublic = true // Comments are always public
2186386c 224 const audience = getAudience(videoComment.Account.Actor, isPublic)
d6e99e53
C
225
226 const videoCommentObject = audiencify(videoComment.toActivityPubObject(threadParentComments), audience)
227
296c0905 228 if (req.path.endsWith('/activity')) {
c48e82b5 229 const data = buildCreateActivity(videoComment.url, videoComment.Account.Actor, videoCommentObject, audience)
4b8f09fa 230 return activityPubResponse(activityPubContextify(data), res)
296c0905
C
231 }
232
4b8f09fa 233 return activityPubResponse(activityPubContextify(videoCommentObject), res)
da854ddd 234}
7006bc63 235
c48e82b5
C
236async function videoRedundancyController (req: express.Request, res: express.Response) {
237 const videoRedundancy = res.locals.videoRedundancy
238 const serverActor = await getServerActor()
239
240 const audience = getAudience(serverActor)
241 const object = audiencify(videoRedundancy.toActivityPubObject(), audience)
242
243 if (req.path.endsWith('/activity')) {
244 const data = buildCreateActivity(videoRedundancy.url, serverActor, object, audience)
245 return activityPubResponse(activityPubContextify(data), res)
246 }
247
248 return activityPubResponse(activityPubContextify(object), res)
249}
250
7006bc63
C
251// ---------------------------------------------------------------------------
252
253async function actorFollowing (req: express.Request, actor: ActorModel) {
8fffe21a
C
254 const handler = (start: number, count: number) => {
255 return ActorFollowModel.listAcceptedFollowingUrlsForApi([ actor.id ], undefined, start, count)
256 }
7006bc63 257
8fffe21a 258 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.url, handler, req.query.page)
7006bc63
C
259}
260
261async function actorFollowers (req: express.Request, actor: ActorModel) {
8fffe21a
C
262 const handler = (start: number, count: number) => {
263 return ActorFollowModel.listAcceptedFollowerUrlsForApi([ actor.id ], undefined, start, count)
264 }
7006bc63 265
8fffe21a 266 return activityPubCollectionPagination(CONFIG.WEBSERVER.URL + req.url, handler, req.query.page)
7006bc63 267}
4b8f09fa 268
8fffe21a
C
269function videoRates (req: express.Request, rateType: VideoRateType, video: VideoModel, url: string) {
270 const handler = async (start: number, count: number) => {
271 const result = await AccountVideoRateModel.listAndCountAccountUrlsByVideoId(rateType, video.id, start, count)
272 return {
273 total: result.count,
274 data: result.rows.map(r => r.Account.Actor.url)
275 }
276 }
277 return activityPubCollectionPagination(url, handler, req.query.page)
4b8f09fa 278}