diff options
Diffstat (limited to 'server/controllers/misc.ts')
-rw-r--r-- | server/controllers/misc.ts | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/server/controllers/misc.ts b/server/controllers/misc.ts new file mode 100644 index 000000000..4c8af2adc --- /dev/null +++ b/server/controllers/misc.ts | |||
@@ -0,0 +1,206 @@ | |||
1 | import cors from 'cors' | ||
2 | import express from 'express' | ||
3 | import { CONFIG, isEmailEnabled } from '@server/initializers/config' | ||
4 | import { serveIndexHTML } from '@server/lib/client-html' | ||
5 | import { ServerConfigManager } from '@server/lib/server-config-manager' | ||
6 | import { HttpStatusCode } from '@shared/models' | ||
7 | import { HttpNodeinfoDiasporaSoftwareNsSchema20 } from '../../shared/models/nodeinfo/nodeinfo.model' | ||
8 | import { CONSTRAINTS_FIELDS, DEFAULT_THEME_NAME, PEERTUBE_VERSION, ROUTE_CACHE_LIFETIME } from '../initializers/constants' | ||
9 | import { getThemeOrDefault } from '../lib/plugins/theme-utils' | ||
10 | import { asyncMiddleware } from '../middlewares' | ||
11 | import { cacheRoute } from '../middlewares/cache/cache' | ||
12 | import { UserModel } from '../models/user/user' | ||
13 | import { VideoModel } from '../models/video/video' | ||
14 | import { VideoCommentModel } from '../models/video/video-comment' | ||
15 | |||
16 | const miscRouter = express.Router() | ||
17 | |||
18 | miscRouter.use(cors()) | ||
19 | |||
20 | miscRouter.use('/nodeinfo/:version.json', | ||
21 | cacheRoute(ROUTE_CACHE_LIFETIME.NODEINFO), | ||
22 | asyncMiddleware(generateNodeinfo) | ||
23 | ) | ||
24 | |||
25 | // robots.txt service | ||
26 | miscRouter.get('/robots.txt', | ||
27 | cacheRoute(ROUTE_CACHE_LIFETIME.ROBOTS), | ||
28 | (_, res: express.Response) => { | ||
29 | res.type('text/plain') | ||
30 | |||
31 | return res.send(CONFIG.INSTANCE.ROBOTS) | ||
32 | } | ||
33 | ) | ||
34 | |||
35 | miscRouter.all('/teapot', | ||
36 | getCup, | ||
37 | asyncMiddleware(serveIndexHTML) | ||
38 | ) | ||
39 | |||
40 | // security.txt service | ||
41 | miscRouter.get('/security.txt', | ||
42 | (_, res: express.Response) => { | ||
43 | return res.redirect(HttpStatusCode.MOVED_PERMANENTLY_301, '/.well-known/security.txt') | ||
44 | } | ||
45 | ) | ||
46 | |||
47 | // --------------------------------------------------------------------------- | ||
48 | |||
49 | export { | ||
50 | miscRouter | ||
51 | } | ||
52 | |||
53 | // --------------------------------------------------------------------------- | ||
54 | |||
55 | async function generateNodeinfo (req: express.Request, res: express.Response) { | ||
56 | const { totalVideos } = await VideoModel.getStats() | ||
57 | const { totalLocalVideoComments } = await VideoCommentModel.getStats() | ||
58 | const { totalUsers, totalMonthlyActiveUsers, totalHalfYearActiveUsers } = await UserModel.getStats() | ||
59 | |||
60 | if (!req.params.version || req.params.version !== '2.0') { | ||
61 | return res.fail({ | ||
62 | status: HttpStatusCode.NOT_FOUND_404, | ||
63 | message: 'Nodeinfo schema version not handled' | ||
64 | }) | ||
65 | } | ||
66 | |||
67 | const json = { | ||
68 | version: '2.0', | ||
69 | software: { | ||
70 | name: 'peertube', | ||
71 | version: PEERTUBE_VERSION | ||
72 | }, | ||
73 | protocols: [ | ||
74 | 'activitypub' | ||
75 | ], | ||
76 | services: { | ||
77 | inbound: [], | ||
78 | outbound: [ | ||
79 | 'atom1.0', | ||
80 | 'rss2.0' | ||
81 | ] | ||
82 | }, | ||
83 | openRegistrations: CONFIG.SIGNUP.ENABLED, | ||
84 | usage: { | ||
85 | users: { | ||
86 | total: totalUsers, | ||
87 | activeMonth: totalMonthlyActiveUsers, | ||
88 | activeHalfyear: totalHalfYearActiveUsers | ||
89 | }, | ||
90 | localPosts: totalVideos, | ||
91 | localComments: totalLocalVideoComments | ||
92 | }, | ||
93 | metadata: { | ||
94 | taxonomy: { | ||
95 | postsName: 'Videos' | ||
96 | }, | ||
97 | nodeName: CONFIG.INSTANCE.NAME, | ||
98 | nodeDescription: CONFIG.INSTANCE.SHORT_DESCRIPTION, | ||
99 | nodeConfig: { | ||
100 | search: { | ||
101 | remoteUri: { | ||
102 | users: CONFIG.SEARCH.REMOTE_URI.USERS, | ||
103 | anonymous: CONFIG.SEARCH.REMOTE_URI.ANONYMOUS | ||
104 | } | ||
105 | }, | ||
106 | plugin: { | ||
107 | registered: ServerConfigManager.Instance.getRegisteredPlugins() | ||
108 | }, | ||
109 | theme: { | ||
110 | registered: ServerConfigManager.Instance.getRegisteredThemes(), | ||
111 | default: getThemeOrDefault(CONFIG.THEME.DEFAULT, DEFAULT_THEME_NAME) | ||
112 | }, | ||
113 | email: { | ||
114 | enabled: isEmailEnabled() | ||
115 | }, | ||
116 | contactForm: { | ||
117 | enabled: CONFIG.CONTACT_FORM.ENABLED | ||
118 | }, | ||
119 | transcoding: { | ||
120 | hls: { | ||
121 | enabled: CONFIG.TRANSCODING.HLS.ENABLED | ||
122 | }, | ||
123 | webtorrent: { | ||
124 | enabled: CONFIG.TRANSCODING.WEBTORRENT.ENABLED | ||
125 | }, | ||
126 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('vod') | ||
127 | }, | ||
128 | live: { | ||
129 | enabled: CONFIG.LIVE.ENABLED, | ||
130 | transcoding: { | ||
131 | enabled: CONFIG.LIVE.TRANSCODING.ENABLED, | ||
132 | enabledResolutions: ServerConfigManager.Instance.getEnabledResolutions('live') | ||
133 | } | ||
134 | }, | ||
135 | import: { | ||
136 | videos: { | ||
137 | http: { | ||
138 | enabled: CONFIG.IMPORT.VIDEOS.HTTP.ENABLED | ||
139 | }, | ||
140 | torrent: { | ||
141 | enabled: CONFIG.IMPORT.VIDEOS.TORRENT.ENABLED | ||
142 | } | ||
143 | } | ||
144 | }, | ||
145 | autoBlacklist: { | ||
146 | videos: { | ||
147 | ofUsers: { | ||
148 | enabled: CONFIG.AUTO_BLACKLIST.VIDEOS.OF_USERS.ENABLED | ||
149 | } | ||
150 | } | ||
151 | }, | ||
152 | avatar: { | ||
153 | file: { | ||
154 | size: { | ||
155 | max: CONSTRAINTS_FIELDS.ACTORS.IMAGE.FILE_SIZE.max | ||
156 | }, | ||
157 | extensions: CONSTRAINTS_FIELDS.ACTORS.IMAGE.EXTNAME | ||
158 | } | ||
159 | }, | ||
160 | video: { | ||
161 | image: { | ||
162 | extensions: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.EXTNAME, | ||
163 | size: { | ||
164 | max: CONSTRAINTS_FIELDS.VIDEOS.IMAGE.FILE_SIZE.max | ||
165 | } | ||
166 | }, | ||
167 | file: { | ||
168 | extensions: CONSTRAINTS_FIELDS.VIDEOS.EXTNAME | ||
169 | } | ||
170 | }, | ||
171 | videoCaption: { | ||
172 | file: { | ||
173 | size: { | ||
174 | max: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.FILE_SIZE.max | ||
175 | }, | ||
176 | extensions: CONSTRAINTS_FIELDS.VIDEO_CAPTIONS.CAPTION_FILE.EXTNAME | ||
177 | } | ||
178 | }, | ||
179 | user: { | ||
180 | videoQuota: CONFIG.USER.VIDEO_QUOTA, | ||
181 | videoQuotaDaily: CONFIG.USER.VIDEO_QUOTA_DAILY | ||
182 | }, | ||
183 | trending: { | ||
184 | videos: { | ||
185 | intervalDays: CONFIG.TRENDING.VIDEOS.INTERVAL_DAYS | ||
186 | } | ||
187 | }, | ||
188 | tracker: { | ||
189 | enabled: CONFIG.TRACKER.ENABLED | ||
190 | } | ||
191 | } | ||
192 | } | ||
193 | } as HttpNodeinfoDiasporaSoftwareNsSchema20 | ||
194 | |||
195 | res.contentType('application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"') | ||
196 | .send(json) | ||
197 | .end() | ||
198 | } | ||
199 | |||
200 | function getCup (req: express.Request, res: express.Response, next: express.NextFunction) { | ||
201 | res.status(HttpStatusCode.I_AM_A_TEAPOT_418) | ||
202 | res.setHeader('Accept-Additions', 'Non-Dairy;1,Sugar;1') | ||
203 | res.setHeader('Safe', 'if-sepia-awake') | ||
204 | |||
205 | return next() | ||
206 | } | ||