diff options
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/activitypub/client.ts | 28 | ||||
-rw-r--r-- | server/controllers/api/accounts.ts | 4 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 12 | ||||
-rw-r--r-- | server/controllers/api/users/index.ts | 1 | ||||
-rw-r--r-- | server/controllers/api/users/me.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/video-channel.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/videos/import.ts | 6 | ||||
-rw-r--r-- | server/controllers/api/videos/index.ts | 24 | ||||
-rw-r--r-- | server/controllers/bots.ts | 101 | ||||
-rw-r--r-- | server/controllers/index.ts | 1 | ||||
-rw-r--r-- | server/controllers/static.ts | 15 |
11 files changed, 161 insertions, 43 deletions
diff --git a/server/controllers/activitypub/client.ts b/server/controllers/activitypub/client.ts index d9d385460..1a4e28dc8 100644 --- a/server/controllers/activitypub/client.ts +++ b/server/controllers/activitypub/client.ts | |||
@@ -162,10 +162,10 @@ function getAccountVideoRate (rateType: VideoRateType) { | |||
162 | } | 162 | } |
163 | } | 163 | } |
164 | 164 | ||
165 | async function videoController (req: express.Request, res: express.Response, next: express.NextFunction) { | 165 | async function videoController (req: express.Request, res: express.Response) { |
166 | const video: VideoModel = res.locals.video | 166 | const video: VideoModel = res.locals.video |
167 | 167 | ||
168 | if (video.isOwned() === false) return res.redirect(video.url) | 168 | if (video.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(video.url) |
169 | 169 | ||
170 | // We need captions to render AP object | 170 | // We need captions to render AP object |
171 | video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id) | 171 | video.VideoCaptions = await VideoCaptionModel.listVideoCaptions(video.id) |
@@ -181,17 +181,17 @@ async function videoController (req: express.Request, res: express.Response, nex | |||
181 | return activityPubResponse(activityPubContextify(videoObject), res) | 181 | return activityPubResponse(activityPubContextify(videoObject), res) |
182 | } | 182 | } |
183 | 183 | ||
184 | async function videoAnnounceController (req: express.Request, res: express.Response, next: express.NextFunction) { | 184 | async function videoAnnounceController (req: express.Request, res: express.Response) { |
185 | const share = res.locals.videoShare as VideoShareModel | 185 | const share = res.locals.videoShare as VideoShareModel |
186 | 186 | ||
187 | if (share.Actor.isOwned() === false) return res.redirect(share.url) | 187 | if (share.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(share.url) |
188 | 188 | ||
189 | const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined) | 189 | const { activity } = await buildAnnounceWithVideoAudience(share.Actor, share, res.locals.video, undefined) |
190 | 190 | ||
191 | return activityPubResponse(activityPubContextify(activity), res) | 191 | return activityPubResponse(activityPubContextify(activity), res) |
192 | } | 192 | } |
193 | 193 | ||
194 | async function videoAnnouncesController (req: express.Request, res: express.Response, next: express.NextFunction) { | 194 | async function videoAnnouncesController (req: express.Request, res: express.Response) { |
195 | const video: VideoModel = res.locals.video | 195 | const video: VideoModel = res.locals.video |
196 | 196 | ||
197 | const handler = async (start: number, count: number) => { | 197 | const handler = async (start: number, count: number) => { |
@@ -206,21 +206,21 @@ async function videoAnnouncesController (req: express.Request, res: express.Resp | |||
206 | return activityPubResponse(activityPubContextify(json), res) | 206 | return activityPubResponse(activityPubContextify(json), res) |
207 | } | 207 | } |
208 | 208 | ||
209 | async function videoLikesController (req: express.Request, res: express.Response, next: express.NextFunction) { | 209 | async function videoLikesController (req: express.Request, res: express.Response) { |
210 | const video: VideoModel = res.locals.video | 210 | const video: VideoModel = res.locals.video |
211 | const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video)) | 211 | const json = await videoRates(req, 'like', video, getVideoLikesActivityPubUrl(video)) |
212 | 212 | ||
213 | return activityPubResponse(activityPubContextify(json), res) | 213 | return activityPubResponse(activityPubContextify(json), res) |
214 | } | 214 | } |
215 | 215 | ||
216 | async function videoDislikesController (req: express.Request, res: express.Response, next: express.NextFunction) { | 216 | async function videoDislikesController (req: express.Request, res: express.Response) { |
217 | const video: VideoModel = res.locals.video | 217 | const video: VideoModel = res.locals.video |
218 | const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video)) | 218 | const json = await videoRates(req, 'dislike', video, getVideoDislikesActivityPubUrl(video)) |
219 | 219 | ||
220 | return activityPubResponse(activityPubContextify(json), res) | 220 | return activityPubResponse(activityPubContextify(json), res) |
221 | } | 221 | } |
222 | 222 | ||
223 | async function videoCommentsController (req: express.Request, res: express.Response, next: express.NextFunction) { | 223 | async function videoCommentsController (req: express.Request, res: express.Response) { |
224 | const video: VideoModel = res.locals.video | 224 | const video: VideoModel = res.locals.video |
225 | 225 | ||
226 | const handler = async (start: number, count: number) => { | 226 | const handler = async (start: number, count: number) => { |
@@ -235,30 +235,30 @@ async function videoCommentsController (req: express.Request, res: express.Respo | |||
235 | return activityPubResponse(activityPubContextify(json), res) | 235 | return activityPubResponse(activityPubContextify(json), res) |
236 | } | 236 | } |
237 | 237 | ||
238 | async function videoChannelController (req: express.Request, res: express.Response, next: express.NextFunction) { | 238 | async function videoChannelController (req: express.Request, res: express.Response) { |
239 | const videoChannel: VideoChannelModel = res.locals.videoChannel | 239 | const videoChannel: VideoChannelModel = res.locals.videoChannel |
240 | 240 | ||
241 | return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res) | 241 | return activityPubResponse(activityPubContextify(videoChannel.toActivityPubObject()), res) |
242 | } | 242 | } |
243 | 243 | ||
244 | async function videoChannelFollowersController (req: express.Request, res: express.Response, next: express.NextFunction) { | 244 | async function videoChannelFollowersController (req: express.Request, res: express.Response) { |
245 | const videoChannel: VideoChannelModel = res.locals.videoChannel | 245 | const videoChannel: VideoChannelModel = res.locals.videoChannel |
246 | const activityPubResult = await actorFollowers(req, videoChannel.Actor) | 246 | const activityPubResult = await actorFollowers(req, videoChannel.Actor) |
247 | 247 | ||
248 | return activityPubResponse(activityPubContextify(activityPubResult), res) | 248 | return activityPubResponse(activityPubContextify(activityPubResult), res) |
249 | } | 249 | } |
250 | 250 | ||
251 | async function videoChannelFollowingController (req: express.Request, res: express.Response, next: express.NextFunction) { | 251 | async function videoChannelFollowingController (req: express.Request, res: express.Response) { |
252 | const videoChannel: VideoChannelModel = res.locals.videoChannel | 252 | const videoChannel: VideoChannelModel = res.locals.videoChannel |
253 | const activityPubResult = await actorFollowing(req, videoChannel.Actor) | 253 | const activityPubResult = await actorFollowing(req, videoChannel.Actor) |
254 | 254 | ||
255 | return activityPubResponse(activityPubContextify(activityPubResult), res) | 255 | return activityPubResponse(activityPubContextify(activityPubResult), res) |
256 | } | 256 | } |
257 | 257 | ||
258 | async function videoCommentController (req: express.Request, res: express.Response, next: express.NextFunction) { | 258 | async function videoCommentController (req: express.Request, res: express.Response) { |
259 | const videoComment: VideoCommentModel = res.locals.videoComment | 259 | const videoComment: VideoCommentModel = res.locals.videoComment |
260 | 260 | ||
261 | if (videoComment.isOwned() === false) return res.redirect(videoComment.url) | 261 | if (videoComment.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoComment.url) |
262 | 262 | ||
263 | const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) | 263 | const threadParentComments = await VideoCommentModel.listThreadParentComments(videoComment, undefined) |
264 | const isPublic = true // Comments are always public | 264 | const isPublic = true // Comments are always public |
@@ -276,7 +276,7 @@ async function videoCommentController (req: express.Request, res: express.Respon | |||
276 | 276 | ||
277 | async function videoRedundancyController (req: express.Request, res: express.Response) { | 277 | async function videoRedundancyController (req: express.Request, res: express.Response) { |
278 | const videoRedundancy: VideoRedundancyModel = res.locals.videoRedundancy | 278 | const videoRedundancy: VideoRedundancyModel = res.locals.videoRedundancy |
279 | if (videoRedundancy.isOwned() === false) return res.redirect(videoRedundancy.url) | 279 | if (videoRedundancy.url.startsWith(CONFIG.WEBSERVER.URL) === false) return res.redirect(videoRedundancy.url) |
280 | 280 | ||
281 | const serverActor = await getServerActor() | 281 | const serverActor = await getServerActor() |
282 | 282 | ||
diff --git a/server/controllers/api/accounts.ts b/server/controllers/api/accounts.ts index 86ef2aed1..a69a83acf 100644 --- a/server/controllers/api/accounts.ts +++ b/server/controllers/api/accounts.ts | |||
@@ -74,10 +74,10 @@ async function listVideoAccountChannels (req: express.Request, res: express.Resp | |||
74 | 74 | ||
75 | async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 75 | async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
76 | const account: AccountModel = res.locals.account | 76 | const account: AccountModel = res.locals.account |
77 | const actorId = isUserAbleToSearchRemoteURI(res) ? null : undefined | 77 | const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined |
78 | 78 | ||
79 | const resultList = await VideoModel.listForApi({ | 79 | const resultList = await VideoModel.listForApi({ |
80 | actorId, | 80 | followerActorId, |
81 | start: req.query.start, | 81 | start: req.query.start, |
82 | count: req.query.count, | 82 | count: req.query.count, |
83 | sort: req.query.sort, | 83 | sort: req.query.sort, |
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts index 03c1cec7b..d65e321e9 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -10,7 +10,8 @@ import { customConfigUpdateValidator } from '../../middlewares/validators/config | |||
10 | import { ClientHtml } from '../../lib/client-html' | 10 | import { ClientHtml } from '../../lib/client-html' |
11 | import { auditLoggerFactory, CustomConfigAuditView, getAuditIdFromRes } from '../../helpers/audit-logger' | 11 | import { auditLoggerFactory, CustomConfigAuditView, getAuditIdFromRes } from '../../helpers/audit-logger' |
12 | import { remove, writeJSON } from 'fs-extra' | 12 | import { remove, writeJSON } from 'fs-extra' |
13 | import { getVersion } from '../../helpers/utils' | 13 | import { getServerCommit } from '../../helpers/utils' |
14 | import { Emailer } from '../../lib/emailer' | ||
14 | 15 | ||
15 | const packageJSON = require('../../../../package.json') | 16 | const packageJSON = require('../../../../package.json') |
16 | const configRouter = express.Router() | 17 | const configRouter = express.Router() |
@@ -40,11 +41,11 @@ configRouter.delete('/custom', | |||
40 | ) | 41 | ) |
41 | 42 | ||
42 | let serverCommit: string | 43 | let serverCommit: string |
43 | async function getConfig (req: express.Request, res: express.Response, next: express.NextFunction) { | 44 | async function getConfig (req: express.Request, res: express.Response) { |
44 | const allowed = await isSignupAllowed() | 45 | const allowed = await isSignupAllowed() |
45 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) | 46 | const allowedForCurrentIP = isSignupAllowedForCurrentIP(req.ip) |
46 | serverCommit = (serverCommit) ? serverCommit : await getVersion() | 47 | |
47 | if (serverCommit === packageJSON.version) serverCommit = '' | 48 | if (serverCommit === undefined) serverCommit = await getServerCommit() |
48 | 49 | ||
49 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) | 50 | const enabledResolutions = Object.keys(CONFIG.TRANSCODING.RESOLUTIONS) |
50 | .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true) | 51 | .filter(key => CONFIG.TRANSCODING.ENABLED === CONFIG.TRANSCODING.RESOLUTIONS[key] === true) |
@@ -61,6 +62,9 @@ async function getConfig (req: express.Request, res: express.Response, next: exp | |||
61 | css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS | 62 | css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS |
62 | } | 63 | } |
63 | }, | 64 | }, |
65 | email: { | ||
66 | enabled: Emailer.Instance.isEnabled() | ||
67 | }, | ||
64 | serverVersion: packageJSON.version, | 68 | serverVersion: packageJSON.version, |
65 | serverCommit, | 69 | serverCommit, |
66 | signup: { | 70 | signup: { |
diff --git a/server/controllers/api/users/index.ts b/server/controllers/api/users/index.ts index 9fcb8077f..87fab4a40 100644 --- a/server/controllers/api/users/index.ts +++ b/server/controllers/api/users/index.ts | |||
@@ -262,6 +262,7 @@ async function updateUser (req: express.Request, res: express.Response, next: ex | |||
262 | const roleChanged = body.role !== undefined && body.role !== userToUpdate.role | 262 | const roleChanged = body.role !== undefined && body.role !== userToUpdate.role |
263 | 263 | ||
264 | if (body.email !== undefined) userToUpdate.email = body.email | 264 | if (body.email !== undefined) userToUpdate.email = body.email |
265 | if (body.emailVerified !== undefined) userToUpdate.emailVerified = body.emailVerified | ||
265 | if (body.videoQuota !== undefined) userToUpdate.videoQuota = body.videoQuota | 266 | if (body.videoQuota !== undefined) userToUpdate.videoQuota = body.videoQuota |
266 | if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily | 267 | if (body.videoQuotaDaily !== undefined) userToUpdate.videoQuotaDaily = body.videoQuotaDaily |
267 | if (body.role !== undefined) userToUpdate.role = body.role | 268 | if (body.role !== undefined) userToUpdate.role = body.role |
diff --git a/server/controllers/api/users/me.ts b/server/controllers/api/users/me.ts index 82299747d..d2456346b 100644 --- a/server/controllers/api/users/me.ts +++ b/server/controllers/api/users/me.ts | |||
@@ -42,7 +42,7 @@ import { AccountModel } from '../../../models/account/account' | |||
42 | 42 | ||
43 | const auditLogger = auditLoggerFactory('users-me') | 43 | const auditLogger = auditLoggerFactory('users-me') |
44 | 44 | ||
45 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) | 45 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) |
46 | 46 | ||
47 | const meRouter = express.Router() | 47 | const meRouter = express.Router() |
48 | 48 | ||
@@ -238,7 +238,7 @@ async function getUserSubscriptionVideos (req: express.Request, res: express.Res | |||
238 | nsfw: buildNSFWFilter(res, req.query.nsfw), | 238 | nsfw: buildNSFWFilter(res, req.query.nsfw), |
239 | filter: req.query.filter as VideoFilter, | 239 | filter: req.query.filter as VideoFilter, |
240 | withFiles: false, | 240 | withFiles: false, |
241 | actorId: user.Account.Actor.id, | 241 | followerActorId: user.Account.Actor.id, |
242 | user | 242 | user |
243 | }) | 243 | }) |
244 | 244 | ||
@@ -348,7 +348,7 @@ async function updateMe (req: express.Request, res: express.Response, next: expr | |||
348 | return res.sendStatus(204) | 348 | return res.sendStatus(204) |
349 | } | 349 | } |
350 | 350 | ||
351 | async function updateMyAvatar (req: express.Request, res: express.Response, next: express.NextFunction) { | 351 | async function updateMyAvatar (req: express.Request, res: express.Response) { |
352 | const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] | 352 | const avatarPhysicalFile = req.files[ 'avatarfile' ][ 0 ] |
353 | const user: UserModel = res.locals.oauth.token.user | 353 | const user: UserModel = res.locals.oauth.token.user |
354 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) | 354 | const oldUserAuditView = new UserAuditView(user.toFormattedJSON()) |
diff --git a/server/controllers/api/video-channel.ts b/server/controllers/api/video-channel.ts index 9bf3c5fd8..fd143a139 100644 --- a/server/controllers/api/video-channel.ts +++ b/server/controllers/api/video-channel.ts | |||
@@ -32,7 +32,7 @@ import { resetSequelizeInstance } from '../../helpers/database-utils' | |||
32 | import { UserModel } from '../../models/account/user' | 32 | import { UserModel } from '../../models/account/user' |
33 | 33 | ||
34 | const auditLogger = auditLoggerFactory('channels') | 34 | const auditLogger = auditLoggerFactory('channels') |
35 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.AVATARS_DIR }) | 35 | const reqAvatarFile = createReqFiles([ 'avatarfile' ], IMAGE_MIMETYPE_EXT, { avatarfile: CONFIG.STORAGE.TMP_DIR }) |
36 | 36 | ||
37 | const videoChannelRouter = express.Router() | 37 | const videoChannelRouter = express.Router() |
38 | 38 | ||
@@ -202,10 +202,10 @@ async function getVideoChannel (req: express.Request, res: express.Response, nex | |||
202 | 202 | ||
203 | async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 203 | async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) { |
204 | const videoChannelInstance: VideoChannelModel = res.locals.videoChannel | 204 | const videoChannelInstance: VideoChannelModel = res.locals.videoChannel |
205 | const actorId = isUserAbleToSearchRemoteURI(res) ? null : undefined | 205 | const followerActorId = isUserAbleToSearchRemoteURI(res) ? null : undefined |
206 | 206 | ||
207 | const resultList = await VideoModel.listForApi({ | 207 | const resultList = await VideoModel.listForApi({ |
208 | actorId, | 208 | followerActorId, |
209 | start: req.query.start, | 209 | start: req.query.start, |
210 | count: req.query.count, | 210 | count: req.query.count, |
211 | sort: req.query.sort, | 211 | sort: req.query.sort, |
diff --git a/server/controllers/api/videos/import.ts b/server/controllers/api/videos/import.ts index 398fd5a7f..f27d648c7 100644 --- a/server/controllers/api/videos/import.ts +++ b/server/controllers/api/videos/import.ts | |||
@@ -37,9 +37,9 @@ const reqVideoFileImport = createReqFiles( | |||
37 | [ 'thumbnailfile', 'previewfile', 'torrentfile' ], | 37 | [ 'thumbnailfile', 'previewfile', 'torrentfile' ], |
38 | Object.assign({}, TORRENT_MIMETYPE_EXT, IMAGE_MIMETYPE_EXT), | 38 | Object.assign({}, TORRENT_MIMETYPE_EXT, IMAGE_MIMETYPE_EXT), |
39 | { | 39 | { |
40 | thumbnailfile: CONFIG.STORAGE.THUMBNAILS_DIR, | 40 | thumbnailfile: CONFIG.STORAGE.TMP_DIR, |
41 | previewfile: CONFIG.STORAGE.PREVIEWS_DIR, | 41 | previewfile: CONFIG.STORAGE.TMP_DIR, |
42 | torrentfile: CONFIG.STORAGE.TORRENTS_DIR | 42 | torrentfile: CONFIG.STORAGE.TMP_DIR |
43 | } | 43 | } |
44 | ) | 44 | ) |
45 | 45 | ||
diff --git a/server/controllers/api/videos/index.ts b/server/controllers/api/videos/index.ts index 89fd0432f..4e4697ef4 100644 --- a/server/controllers/api/videos/index.ts +++ b/server/controllers/api/videos/index.ts | |||
@@ -67,17 +67,17 @@ const reqVideoFileAdd = createReqFiles( | |||
67 | [ 'videofile', 'thumbnailfile', 'previewfile' ], | 67 | [ 'videofile', 'thumbnailfile', 'previewfile' ], |
68 | Object.assign({}, VIDEO_MIMETYPE_EXT, IMAGE_MIMETYPE_EXT), | 68 | Object.assign({}, VIDEO_MIMETYPE_EXT, IMAGE_MIMETYPE_EXT), |
69 | { | 69 | { |
70 | videofile: CONFIG.STORAGE.VIDEOS_DIR, | 70 | videofile: CONFIG.STORAGE.TMP_DIR, |
71 | thumbnailfile: CONFIG.STORAGE.THUMBNAILS_DIR, | 71 | thumbnailfile: CONFIG.STORAGE.TMP_DIR, |
72 | previewfile: CONFIG.STORAGE.PREVIEWS_DIR | 72 | previewfile: CONFIG.STORAGE.TMP_DIR |
73 | } | 73 | } |
74 | ) | 74 | ) |
75 | const reqVideoFileUpdate = createReqFiles( | 75 | const reqVideoFileUpdate = createReqFiles( |
76 | [ 'thumbnailfile', 'previewfile' ], | 76 | [ 'thumbnailfile', 'previewfile' ], |
77 | IMAGE_MIMETYPE_EXT, | 77 | IMAGE_MIMETYPE_EXT, |
78 | { | 78 | { |
79 | thumbnailfile: CONFIG.STORAGE.THUMBNAILS_DIR, | 79 | thumbnailfile: CONFIG.STORAGE.TMP_DIR, |
80 | previewfile: CONFIG.STORAGE.PREVIEWS_DIR | 80 | previewfile: CONFIG.STORAGE.TMP_DIR |
81 | } | 81 | } |
82 | ) | 82 | ) |
83 | 83 | ||
@@ -387,6 +387,11 @@ async function updateVideo (req: express.Request, res: express.Response) { | |||
387 | function getVideo (req: express.Request, res: express.Response) { | 387 | function getVideo (req: express.Request, res: express.Response) { |
388 | const videoInstance = res.locals.video | 388 | const videoInstance = res.locals.video |
389 | 389 | ||
390 | if (videoInstance.isOutdated()) { | ||
391 | JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'video', videoUrl: videoInstance.url } }) | ||
392 | .catch(err => logger.error('Cannot create AP refresher job for video %s.', videoInstance.url, { err })) | ||
393 | } | ||
394 | |||
390 | return res.json(videoInstance.toFormattedDetailsJSON()) | 395 | return res.json(videoInstance.toFormattedDetailsJSON()) |
391 | } | 396 | } |
392 | 397 | ||
@@ -406,12 +411,7 @@ async function viewVideo (req: express.Request, res: express.Response) { | |||
406 | ]) | 411 | ]) |
407 | 412 | ||
408 | const serverActor = await getServerActor() | 413 | const serverActor = await getServerActor() |
409 | 414 | await sendCreateView(serverActor, videoInstance, undefined) | |
410 | // Send the event to the origin server | ||
411 | // If we own the video, we'll send an update event when we'll process the views (in our job queue) | ||
412 | if (videoInstance.isOwned() === false) { | ||
413 | await sendCreateView(serverActor, videoInstance, undefined) | ||
414 | } | ||
415 | 415 | ||
416 | return res.status(204).end() | 416 | return res.status(204).end() |
417 | } | 417 | } |
@@ -429,7 +429,7 @@ async function getVideoDescription (req: express.Request, res: express.Response) | |||
429 | return res.json({ description }) | 429 | return res.json({ description }) |
430 | } | 430 | } |
431 | 431 | ||
432 | async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) { | 432 | async function listVideos (req: express.Request, res: express.Response) { |
433 | const resultList = await VideoModel.listForApi({ | 433 | const resultList = await VideoModel.listForApi({ |
434 | start: req.query.start, | 434 | start: req.query.start, |
435 | count: req.query.count, | 435 | count: req.query.count, |
diff --git a/server/controllers/bots.ts b/server/controllers/bots.ts new file mode 100644 index 000000000..2db86a2d8 --- /dev/null +++ b/server/controllers/bots.ts | |||
@@ -0,0 +1,101 @@ | |||
1 | import * as express from 'express' | ||
2 | import { asyncMiddleware } from '../middlewares' | ||
3 | import { CONFIG, ROUTE_CACHE_LIFETIME } from '../initializers' | ||
4 | import * as sitemapModule from 'sitemap' | ||
5 | import { logger } from '../helpers/logger' | ||
6 | import { VideoModel } from '../models/video/video' | ||
7 | import { VideoChannelModel } from '../models/video/video-channel' | ||
8 | import { AccountModel } from '../models/account/account' | ||
9 | import { cacheRoute } from '../middlewares/cache' | ||
10 | import { buildNSFWFilter } from '../helpers/express-utils' | ||
11 | import { truncate } from 'lodash' | ||
12 | |||
13 | const botsRouter = express.Router() | ||
14 | |||
15 | // Special route that add OpenGraph and oEmbed tags | ||
16 | // Do not use a template engine for a so little thing | ||
17 | botsRouter.use('/sitemap.xml', | ||
18 | asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.SITEMAP)), | ||
19 | asyncMiddleware(getSitemap) | ||
20 | ) | ||
21 | |||
22 | // --------------------------------------------------------------------------- | ||
23 | |||
24 | export { | ||
25 | botsRouter | ||
26 | } | ||
27 | |||
28 | // --------------------------------------------------------------------------- | ||
29 | |||
30 | async function getSitemap (req: express.Request, res: express.Response) { | ||
31 | let urls = getSitemapBasicUrls() | ||
32 | |||
33 | urls = urls.concat(await getSitemapLocalVideoUrls()) | ||
34 | urls = urls.concat(await getSitemapVideoChannelUrls()) | ||
35 | urls = urls.concat(await getSitemapAccountUrls()) | ||
36 | |||
37 | const sitemap = sitemapModule.createSitemap({ | ||
38 | hostname: CONFIG.WEBSERVER.URL, | ||
39 | urls: urls | ||
40 | }) | ||
41 | |||
42 | sitemap.toXML((err, xml) => { | ||
43 | if (err) { | ||
44 | logger.error('Cannot generate sitemap.', { err }) | ||
45 | return res.sendStatus(500) | ||
46 | } | ||
47 | |||
48 | res.header('Content-Type', 'application/xml') | ||
49 | res.send(xml) | ||
50 | }) | ||
51 | } | ||
52 | |||
53 | async function getSitemapVideoChannelUrls () { | ||
54 | const rows = await VideoChannelModel.listLocalsForSitemap('createdAt') | ||
55 | |||
56 | return rows.map(channel => ({ | ||
57 | url: CONFIG.WEBSERVER.URL + '/video-channels/' + channel.Actor.preferredUsername | ||
58 | })) | ||
59 | } | ||
60 | |||
61 | async function getSitemapAccountUrls () { | ||
62 | const rows = await AccountModel.listLocalsForSitemap('createdAt') | ||
63 | |||
64 | return rows.map(channel => ({ | ||
65 | url: CONFIG.WEBSERVER.URL + '/accounts/' + channel.Actor.preferredUsername | ||
66 | })) | ||
67 | } | ||
68 | |||
69 | async function getSitemapLocalVideoUrls () { | ||
70 | const resultList = await VideoModel.listForApi({ | ||
71 | start: 0, | ||
72 | count: undefined, | ||
73 | sort: 'createdAt', | ||
74 | includeLocalVideos: true, | ||
75 | nsfw: buildNSFWFilter(), | ||
76 | filter: 'local', | ||
77 | withFiles: false | ||
78 | }) | ||
79 | |||
80 | return resultList.data.map(v => ({ | ||
81 | url: CONFIG.WEBSERVER.URL + '/videos/watch/' + v.uuid, | ||
82 | video: [ | ||
83 | { | ||
84 | title: v.name, | ||
85 | // Sitemap description should be < 2000 characters | ||
86 | description: truncate(v.description || v.name, { length: 2000, omission: '...' }), | ||
87 | player_loc: CONFIG.WEBSERVER.URL + '/videos/embed/' + v.uuid, | ||
88 | thumbnail_loc: CONFIG.WEBSERVER.URL + v.getThumbnailStaticPath() | ||
89 | } | ||
90 | ] | ||
91 | })) | ||
92 | } | ||
93 | |||
94 | function getSitemapBasicUrls () { | ||
95 | const paths = [ | ||
96 | '/about/instance', | ||
97 | '/videos/local' | ||
98 | ] | ||
99 | |||
100 | return paths.map(p => ({ url: CONFIG.WEBSERVER.URL + p })) | ||
101 | } | ||
diff --git a/server/controllers/index.ts b/server/controllers/index.ts index 197fa897a..a88a03c79 100644 --- a/server/controllers/index.ts +++ b/server/controllers/index.ts | |||
@@ -6,3 +6,4 @@ export * from './services' | |||
6 | export * from './static' | 6 | export * from './static' |
7 | export * from './webfinger' | 7 | export * from './webfinger' |
8 | export * from './tracker' | 8 | export * from './tracker' |
9 | export * from './bots' | ||
diff --git a/server/controllers/static.ts b/server/controllers/static.ts index 75e30353c..4fd58f70c 100644 --- a/server/controllers/static.ts +++ b/server/controllers/static.ts | |||
@@ -34,13 +34,18 @@ staticRouter.use( | |||
34 | ) | 34 | ) |
35 | 35 | ||
36 | // Videos path for webseeding | 36 | // Videos path for webseeding |
37 | const videosPhysicalPath = CONFIG.STORAGE.VIDEOS_DIR | ||
38 | staticRouter.use( | 37 | staticRouter.use( |
39 | STATIC_PATHS.WEBSEED, | 38 | STATIC_PATHS.WEBSEED, |
40 | cors(), | 39 | cors(), |
41 | express.static(videosPhysicalPath) | 40 | express.static(CONFIG.STORAGE.VIDEOS_DIR, { fallthrough: false }) // 404 because we don't have this video |
42 | ) | 41 | ) |
43 | staticRouter.use( | 42 | staticRouter.use( |
43 | STATIC_PATHS.REDUNDANCY, | ||
44 | cors(), | ||
45 | express.static(CONFIG.STORAGE.REDUNDANCY_DIR, { fallthrough: false }) // 404 because we don't have this video | ||
46 | ) | ||
47 | |||
48 | staticRouter.use( | ||
44 | STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension', | 49 | STATIC_DOWNLOAD_PATHS.VIDEOS + ':id-:resolution([0-9]+).:extension', |
45 | asyncMiddleware(videosGetValidator), | 50 | asyncMiddleware(videosGetValidator), |
46 | asyncMiddleware(downloadVideoFile) | 51 | asyncMiddleware(downloadVideoFile) |
@@ -131,6 +136,12 @@ staticRouter.use('/.well-known/dnt/', | |||
131 | } | 136 | } |
132 | ) | 137 | ) |
133 | 138 | ||
139 | staticRouter.use('/.well-known/change-password', | ||
140 | (_, res: express.Response) => { | ||
141 | res.redirect('/my-account/settings') | ||
142 | } | ||
143 | ) | ||
144 | |||
134 | // --------------------------------------------------------------------------- | 145 | // --------------------------------------------------------------------------- |
135 | 146 | ||
136 | export { | 147 | export { |