aboutsummaryrefslogtreecommitdiffhomepage
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/controllers/api/config.ts18
-rw-r--r--server/helpers/audit-logger.ts1
-rw-r--r--server/initializers/config.ts10
-rw-r--r--server/middlewares/validators/config.ts3
-rw-r--r--server/models/video/video-query-builder.ts95
-rw-r--r--server/tests/api/check-params/config.ts10
-rw-r--r--server/tests/api/server/config.ts10
-rw-r--r--server/tests/client.ts2
8 files changed, 87 insertions, 62 deletions
diff --git a/server/controllers/api/config.ts b/server/controllers/api/config.ts
index 44f3d3ef7..24e7601ec 100644
--- a/server/controllers/api/config.ts
+++ b/server/controllers/api/config.ts
@@ -65,9 +65,15 @@ async function getConfig (req: express.Request, res: express.Response) {
65 instance: { 65 instance: {
66 name: CONFIG.INSTANCE.NAME, 66 name: CONFIG.INSTANCE.NAME,
67 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, 67 shortDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION,
68 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
69 isNSFW: CONFIG.INSTANCE.IS_NSFW, 68 isNSFW: CONFIG.INSTANCE.IS_NSFW,
70 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, 69 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
70 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
71 defaultTrendingRoute: CONFIG.INSTANCE.DEFAULT_TRENDING_ROUTE,
72 pages: {
73 hot: {
74 enabled: CONFIG.INSTANCE.PAGES.HOT.ENABLED
75 }
76 },
71 customizations: { 77 customizations: {
72 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT, 78 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT,
73 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS 79 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS
@@ -362,8 +368,16 @@ function customConfig (): CustomConfig {
362 categories: CONFIG.INSTANCE.CATEGORIES, 368 categories: CONFIG.INSTANCE.CATEGORIES,
363 369
364 isNSFW: CONFIG.INSTANCE.IS_NSFW, 370 isNSFW: CONFIG.INSTANCE.IS_NSFW,
365 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
366 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY, 371 defaultNSFWPolicy: CONFIG.INSTANCE.DEFAULT_NSFW_POLICY,
372
373 defaultClientRoute: CONFIG.INSTANCE.DEFAULT_CLIENT_ROUTE,
374 defaultTrendingRoute: CONFIG.INSTANCE.DEFAULT_TRENDING_ROUTE,
375 pages: {
376 hot: {
377 enabled: CONFIG.INSTANCE.PAGES.HOT.ENABLED
378 }
379 },
380
367 customizations: { 381 customizations: {
368 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS, 382 css: CONFIG.INSTANCE.CUSTOMIZATIONS.CSS,
369 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT 383 javascript: CONFIG.INSTANCE.CUSTOMIZATIONS.JAVASCRIPT
diff --git a/server/helpers/audit-logger.ts b/server/helpers/audit-logger.ts
index 6aae5e821..e474959b2 100644
--- a/server/helpers/audit-logger.ts
+++ b/server/helpers/audit-logger.ts
@@ -230,6 +230,7 @@ const customConfigKeysToKeep = [
230 'instance-description', 230 'instance-description',
231 'instance-terms', 231 'instance-terms',
232 'instance-defaultClientRoute', 232 'instance-defaultClientRoute',
233 'instance-defaultTrendingRoute',
233 'instance-defaultNSFWPolicy', 234 'instance-defaultNSFWPolicy',
234 'instance-customizations-javascript', 235 'instance-customizations-javascript',
235 'instance-customizations-css', 236 'instance-customizations-css',
diff --git a/server/initializers/config.ts b/server/initializers/config.ts
index c7ef9b497..e1f807752 100644
--- a/server/initializers/config.ts
+++ b/server/initializers/config.ts
@@ -278,8 +278,16 @@ const CONFIG = {
278 get CATEGORIES () { return config.get<number[]>('instance.categories') || [] }, 278 get CATEGORIES () { return config.get<number[]>('instance.categories') || [] },
279 279
280 get IS_NSFW () { return config.get<boolean>('instance.is_nsfw') }, 280 get IS_NSFW () { return config.get<boolean>('instance.is_nsfw') },
281 get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
282 get DEFAULT_NSFW_POLICY () { return config.get<NSFWPolicyType>('instance.default_nsfw_policy') }, 281 get DEFAULT_NSFW_POLICY () { return config.get<NSFWPolicyType>('instance.default_nsfw_policy') },
282
283 get DEFAULT_CLIENT_ROUTE () { return config.get<string>('instance.default_client_route') },
284 get DEFAULT_TRENDING_ROUTE () { return config.get<string>('instance.default_trending_route') },
285 PAGES: {
286 HOT: {
287 get ENABLED () { return config.get<boolean>('instance.pages.hot.enabled') }
288 }
289 },
290
283 CUSTOMIZATIONS: { 291 CUSTOMIZATIONS: {
284 get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') }, 292 get JAVASCRIPT () { return config.get<string>('instance.customizations.javascript') },
285 get CSS () { return config.get<string>('instance.customizations.css') } 293 get CSS () { return config.get<string>('instance.customizations.css') }
diff --git a/server/middlewares/validators/config.ts b/server/middlewares/validators/config.ts
index faabf17d7..0efe1157f 100644
--- a/server/middlewares/validators/config.ts
+++ b/server/middlewares/validators/config.ts
@@ -15,8 +15,9 @@ const customConfigUpdateValidator = [
15 body('instance.shortDescription').exists().withMessage('Should have a valid instance short description'), 15 body('instance.shortDescription').exists().withMessage('Should have a valid instance short description'),
16 body('instance.description').exists().withMessage('Should have a valid instance description'), 16 body('instance.description').exists().withMessage('Should have a valid instance description'),
17 body('instance.terms').exists().withMessage('Should have a valid instance terms'), 17 body('instance.terms').exists().withMessage('Should have a valid instance terms'),
18 body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'),
19 body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid).withMessage('Should have a valid NSFW policy'), 18 body('instance.defaultNSFWPolicy').custom(isUserNSFWPolicyValid).withMessage('Should have a valid NSFW policy'),
19 body('instance.defaultClientRoute').exists().withMessage('Should have a valid instance default client route'),
20 body('instance.defaultTrendingRoute').exists().withMessage('Should have a valid instance default trending route'),
20 body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'), 21 body('instance.customizations.css').exists().withMessage('Should have a valid instance CSS customization'),
21 body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'), 22 body('instance.customizations.javascript').exists().withMessage('Should have a valid instance JavaScript customization'),
22 23
diff --git a/server/models/video/video-query-builder.ts b/server/models/video/video-query-builder.ts
index 8e0965244..3f31ac862 100644
--- a/server/models/video/video-query-builder.ts
+++ b/server/models/video/video-query-builder.ts
@@ -242,64 +242,49 @@ function buildListQuery (model: typeof Model, options: BuildVideosQueryOptions)
242 } 242 }
243 243
244 // We don't exclude results in this so if we do a count we don't need to add this complex clause 244 // We don't exclude results in this so if we do a count we don't need to add this complex clause
245 if (options.trendingDays && options.isCount !== true) { 245 if (options.isCount !== true) {
246 const viewsGteDate = new Date(new Date().getTime() - (24 * 3600 * 1000) * options.trendingDays) 246 if (options.trendingDays) {
247 247 const viewsGteDate = new Date(new Date().getTime() - (24 * 3600 * 1000) * options.trendingDays)
248 joins.push('LEFT JOIN "videoView" ON "video"."id" = "videoView"."videoId" AND "videoView"."startDate" >= :viewsGteDate') 248
249 replacements.viewsGteDate = viewsGteDate 249 joins.push('LEFT JOIN "videoView" ON "video"."id" = "videoView"."videoId" AND "videoView"."startDate" >= :viewsGteDate')
250 250 replacements.viewsGteDate = viewsGteDate
251 attributes.push('COALESCE(SUM("videoView"."views"), 0) AS "score"') 251
252 252 attributes.push('COALESCE(SUM("videoView"."views"), 0) AS "score"')
253 group = 'GROUP BY "video"."id"' 253
254 } else if (options.hot && options.isCount !== true) { 254 group = 'GROUP BY "video"."id"'
255 /** 255 } else if (options.hot) {
256 * "Hotness" is a measure based on absolute view/comment/like/dislike numbers, 256 /**
257 * with fixed weights only applied to their log values. 257 * "Hotness" is a measure based on absolute view/comment/like/dislike numbers,
258 * 258 * with fixed weights only applied to their log values.
259 * This algorithm gives little chance for an old video to have a good score, 259 *
260 * for which recent spikes in interactions could be a sign of "hotness" and 260 * This algorithm gives little chance for an old video to have a good score,
261 * justify a better score. However there are multiple ways to achieve that 261 * for which recent spikes in interactions could be a sign of "hotness" and
262 * goal, which is left for later. Yes, this is a TODO :) 262 * justify a better score. However there are multiple ways to achieve that
263 * 263 * goal, which is left for later. Yes, this is a TODO :)
264 * note: weights and base score are in number of half-days. 264 *
265 * see https://github.com/reddit-archive/reddit/blob/master/r2/r2/lib/db/_sorts.pyx#L47-L58 265 * note: weights and base score are in number of half-days.
266 */ 266 * see https://github.com/reddit-archive/reddit/blob/master/r2/r2/lib/db/_sorts.pyx#L47-L58
267 const weights = { 267 */
268 like: 3, 268 const weights = {
269 dislike: 3, 269 like: 3,
270 view: 1 / 12, 270 dislike: 3,
271 comment: 2 // a comment takes more time than a like to do, but can be done multiple times 271 view: 1 / 12,
272 } 272 comment: 2 // a comment takes more time than a like to do, but can be done multiple times
273 273 }
274 cte.push( // TODO: exclude blocklisted comments
275 '"totalCommentsWithoutVideoAuthor" AS (' +
276 'SELECT "video"."id", ' +
277 'COUNT("replies"."id") - (' +
278 'SELECT COUNT("authorReplies"."id") ' +
279 'FROM "videoComment" AS "authorReplies" ' +
280 'LEFT JOIN "account" ON "account"."id" = "authorReplies"."accountId" ' +
281 'LEFT JOIN "videoChannel" ON "videoChannel"."accountId" = "account"."id" ' +
282 'WHERE "video"."channelId" = "videoChannel"."id" ' +
283 ') as "value" ' +
284 'FROM "videoComment" AS "replies" ' +
285 'LEFT JOIN "video" ON "video"."id" = "replies"."videoId" ' +
286 'WHERE "replies"."videoId" = "video"."id" ' +
287 'GROUP BY "video"."id"' +
288 ')'
289 )
290 274
291 joins.push('LEFT JOIN "totalCommentsWithoutVideoAuthor" ON "video"."id" = "totalCommentsWithoutVideoAuthor"."id"') 275 joins.push('LEFT JOIN "videoComment" ON "video"."id" = "videoComment"."videoId"')
292 276
293 attributes.push( 277 attributes.push(
294 `LOG(GREATEST(1, "video"."likes" - 1)) * ${weights.like} ` + // likes (+) 278 `LOG(GREATEST(1, "video"."likes" - 1)) * ${weights.like} ` + // likes (+)
295 `- LOG(GREATEST(1, "video"."dislikes" - 1)) * ${weights.dislike} ` + // dislikes (-) 279 `- LOG(GREATEST(1, "video"."dislikes" - 1)) * ${weights.dislike} ` + // dislikes (-)
296 `+ LOG("video"."views" + 1) * ${weights.view} ` + // views (+) 280 `+ LOG("video"."views" + 1) * ${weights.view} ` + // views (+)
297 `+ LOG(GREATEST(1, "totalCommentsWithoutVideoAuthor"."value")) * ${weights.comment} ` + // comments (+) 281 `+ LOG(GREATEST(1, COUNT(DISTINCT "videoComment"."id"))) * ${weights.comment} ` + // comments (+)
298 '+ (SELECT EXTRACT(epoch FROM "video"."publishedAt") / 47000) ' + // base score (in number of half-days) 282 '+ (SELECT EXTRACT(epoch FROM "video"."publishedAt") / 47000) ' + // base score (in number of half-days)
299 'AS "score"' 283 'AS "score"'
300 ) 284 )
301 285
302 group = 'GROUP BY "video"."id", "totalCommentsWithoutVideoAuthor"."value"' 286 group = 'GROUP BY "video"."id"'
287 }
303 } 288 }
304 289
305 if (options.historyOfUser) { 290 if (options.historyOfUser) {
diff --git a/server/tests/api/check-params/config.ts b/server/tests/api/check-params/config.ts
index e36cdeab2..e58e0cd9f 100644
--- a/server/tests/api/check-params/config.ts
+++ b/server/tests/api/check-params/config.ts
@@ -41,8 +41,16 @@ describe('Test config API validators', function () {
41 categories: [ 1, 2 ], 41 categories: [ 1, 2 ],
42 42
43 isNSFW: true, 43 isNSFW: true,
44 defaultClientRoute: '/videos/recently-added',
45 defaultNSFWPolicy: 'blur', 44 defaultNSFWPolicy: 'blur',
45
46 defaultClientRoute: '/videos/recently-added',
47 defaultTrendingRoute: '/videos/trending',
48 pages: {
49 hot: {
50 enabled: true
51 }
52 },
53
46 customizations: { 54 customizations: {
47 javascript: 'alert("coucou")', 55 javascript: 'alert("coucou")',
48 css: 'body { background-color: red; }' 56 css: 'body { background-color: red; }'
diff --git a/server/tests/api/server/config.ts b/server/tests/api/server/config.ts
index af25f4800..328f4852a 100644
--- a/server/tests/api/server/config.ts
+++ b/server/tests/api/server/config.ts
@@ -272,9 +272,17 @@ describe('Test config', function () {
272 languages: [ 'en', 'es' ], 272 languages: [ 'en', 'es' ],
273 categories: [ 1, 2 ], 273 categories: [ 1, 2 ],
274 274
275 defaultClientRoute: '/videos/recently-added',
276 isNSFW: true, 275 isNSFW: true,
277 defaultNSFWPolicy: 'blur' as 'blur', 276 defaultNSFWPolicy: 'blur' as 'blur',
277
278 defaultClientRoute: '/videos/recently-added',
279 defaultTrendingRoute: '/videos/trending',
280 pages: {
281 hot: {
282 enabled: true
283 }
284 },
285
278 customizations: { 286 customizations: {
279 javascript: 'alert("coucou")', 287 javascript: 'alert("coucou")',
280 css: 'body { background-color: red; }' 288 css: 'body { background-color: red; }'
diff --git a/server/tests/client.ts b/server/tests/client.ts
index 7572fd34a..d608764ee 100644
--- a/server/tests/client.ts
+++ b/server/tests/client.ts
@@ -308,8 +308,8 @@ describe('Test a client controllers', function () {
308 shortDescription: 'my short description', 308 shortDescription: 'my short description',
309 description: 'my super description', 309 description: 'my super description',
310 terms: 'my super terms', 310 terms: 'my super terms',
311 defaultClientRoute: '/videos/recently-added',
312 defaultNSFWPolicy: 'blur', 311 defaultNSFWPolicy: 'blur',
312 defaultClientRoute: '/videos/recently-added',
313 customizations: { 313 customizations: {
314 javascript: 'alert("coucou")', 314 javascript: 'alert("coucou")',
315 css: 'body { background-color: red; }' 315 css: 'body { background-color: red; }'