diff options
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/api/accounts.ts | 4 | ||||
-rw-r--r-- | server/controllers/api/config.ts | 4 | ||||
-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 | 10 | ||||
-rw-r--r-- | server/controllers/bots.ts | 101 | ||||
-rw-r--r-- | server/controllers/index.ts | 1 | ||||
-rw-r--r-- | server/controllers/static.ts | 9 |
9 files changed, 129 insertions, 18 deletions
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 5233e9f68..d65e321e9 100644 --- a/server/controllers/api/config.ts +++ b/server/controllers/api/config.ts | |||
@@ -11,6 +11,7 @@ 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 { getServerCommit } 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() |
@@ -61,6 +62,9 @@ async function getConfig (req: express.Request, res: express.Response) { | |||
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/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 3d1b2e1a2..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 | ||
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..55e7392a1 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) |