diff options
author | Chocobozzz <florian.bigard@gmail.com> | 2017-05-15 22:22:03 +0200 |
---|---|---|
committer | Chocobozzz <florian.bigard@gmail.com> | 2017-05-20 09:57:40 +0200 |
commit | 65fcc3119c334b75dd13bcfdebf186afdc580a8f (patch) | |
tree | 4f2158c61a9b7c3f47cfa233d01413b946ee53c0 /server/controllers/client.ts | |
parent | d5f345ed4cfac4e1fa84dcb4fce1cda4d32f9c73 (diff) | |
download | PeerTube-65fcc3119c334b75dd13bcfdebf186afdc580a8f.tar.gz PeerTube-65fcc3119c334b75dd13bcfdebf186afdc580a8f.tar.zst PeerTube-65fcc3119c334b75dd13bcfdebf186afdc580a8f.zip |
First typescript iteration
Diffstat (limited to 'server/controllers/client.ts')
-rw-r--r-- | server/controllers/client.ts | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/server/controllers/client.ts b/server/controllers/client.ts new file mode 100644 index 000000000..aaa04889a --- /dev/null +++ b/server/controllers/client.ts | |||
@@ -0,0 +1,118 @@ | |||
1 | import { parallel } from 'async' | ||
2 | import express = require('express') | ||
3 | import fs = require('fs') | ||
4 | import { join } from 'path' | ||
5 | import expressValidator = require('express-validator') | ||
6 | // TODO: use .validator when express-validator typing will have validator field | ||
7 | const validator = expressValidator['validator'] | ||
8 | |||
9 | const db = require('../initializers/database') | ||
10 | import { | ||
11 | CONFIG, | ||
12 | REMOTE_SCHEME, | ||
13 | STATIC_PATHS, | ||
14 | STATIC_MAX_AGE | ||
15 | } from '../initializers' | ||
16 | |||
17 | const clientsRouter = express.Router() | ||
18 | |||
19 | // TODO: move to constants | ||
20 | const opengraphComment = '<!-- opengraph tags -->' | ||
21 | const distPath = join(__dirname, '..', '..', 'client/dist') | ||
22 | const embedPath = join(distPath, 'standalone/videos/embed.html') | ||
23 | const indexPath = join(distPath, 'index.html') | ||
24 | |||
25 | // Special route that add OpenGraph tags | ||
26 | // Do not use a template engine for a so little thing | ||
27 | clientsRouter.use('/videos/watch/:id', generateWatchHtmlPage) | ||
28 | |||
29 | clientsRouter.use('/videos/embed', function (req, res, next) { | ||
30 | res.sendFile(embedPath) | ||
31 | }) | ||
32 | |||
33 | // Static HTML/CSS/JS client files | ||
34 | clientsRouter.use('/client', express.static(distPath, { maxAge: STATIC_MAX_AGE })) | ||
35 | |||
36 | // 404 for static files not found | ||
37 | clientsRouter.use('/client/*', function (req, res, next) { | ||
38 | res.sendStatus(404) | ||
39 | }) | ||
40 | |||
41 | // --------------------------------------------------------------------------- | ||
42 | |||
43 | export { | ||
44 | clientsRouter | ||
45 | } | ||
46 | |||
47 | // --------------------------------------------------------------------------- | ||
48 | |||
49 | function addOpenGraphTags (htmlStringPage, video) { | ||
50 | let basePreviewUrlHttp | ||
51 | |||
52 | if (video.isOwned()) { | ||
53 | basePreviewUrlHttp = CONFIG.WEBSERVER.URL | ||
54 | } else { | ||
55 | basePreviewUrlHttp = REMOTE_SCHEME.HTTP + '://' + video.Author.Pod.host | ||
56 | } | ||
57 | |||
58 | // We fetch the remote preview (bigger than the thumbnail) | ||
59 | // This should not overhead the remote server since social websites put in a cache the OpenGraph tags | ||
60 | // We can't use the thumbnail because these social websites want bigger images (> 200x200 for Facebook for example) | ||
61 | const previewUrl = basePreviewUrlHttp + STATIC_PATHS.PREVIEWS + video.getPreviewName() | ||
62 | const videoUrl = CONFIG.WEBSERVER.URL + '/videos/watch/' + video.id | ||
63 | |||
64 | const metaTags = { | ||
65 | 'og:type': 'video', | ||
66 | 'og:title': video.name, | ||
67 | 'og:image': previewUrl, | ||
68 | 'og:url': videoUrl, | ||
69 | 'og:description': video.description, | ||
70 | |||
71 | 'name': video.name, | ||
72 | 'description': video.description, | ||
73 | 'image': previewUrl, | ||
74 | |||
75 | 'twitter:card': 'summary_large_image', | ||
76 | 'twitter:site': '@Chocobozzz', | ||
77 | 'twitter:title': video.name, | ||
78 | 'twitter:description': video.description, | ||
79 | 'twitter:image': previewUrl | ||
80 | } | ||
81 | |||
82 | let tagsString = '' | ||
83 | Object.keys(metaTags).forEach(function (tagName) { | ||
84 | const tagValue = metaTags[tagName] | ||
85 | |||
86 | tagsString += '<meta property="' + tagName + '" content="' + tagValue + '" />' | ||
87 | }) | ||
88 | |||
89 | return htmlStringPage.replace(opengraphComment, tagsString) | ||
90 | } | ||
91 | |||
92 | function generateWatchHtmlPage (req, res, next) { | ||
93 | const videoId = req.params.id | ||
94 | |||
95 | // Let Angular application handle errors | ||
96 | if (!validator.isUUID(videoId, 4)) return res.sendFile(indexPath) | ||
97 | |||
98 | parallel({ | ||
99 | file: function (callback) { | ||
100 | fs.readFile(indexPath, callback) | ||
101 | }, | ||
102 | |||
103 | video: function (callback) { | ||
104 | db.Video.loadAndPopulateAuthorAndPodAndTags(videoId, callback) | ||
105 | } | ||
106 | }, function (err, result: any) { | ||
107 | if (err) return next(err) | ||
108 | |||
109 | const html = result.file.toString() | ||
110 | const video = result.video | ||
111 | |||
112 | // Let Angular application handle errors | ||
113 | if (!video) return res.sendFile(indexPath) | ||
114 | |||
115 | const htmlStringPageWithTags = addOpenGraphTags(html, video) | ||
116 | res.set('Content-Type', 'text/html; charset=UTF-8').send(htmlStringPageWithTags) | ||
117 | }) | ||
118 | } | ||