diff options
Diffstat (limited to 'server/controllers')
-rw-r--r-- | server/controllers/feeds.ts | 155 |
1 files changed, 97 insertions, 58 deletions
diff --git a/server/controllers/feeds.ts b/server/controllers/feeds.ts index 6e9f7e60c..5c95069fc 100644 --- a/server/controllers/feeds.ts +++ b/server/controllers/feeds.ts | |||
@@ -18,7 +18,6 @@ import { cacheRoute } from '../middlewares/cache' | |||
18 | import { VideoModel } from '../models/video/video' | 18 | import { VideoModel } from '../models/video/video' |
19 | import { VideoCommentModel } from '../models/video/video-comment' | 19 | import { VideoCommentModel } from '../models/video/video-comment' |
20 | import { VideoFilter } from '../../shared/models/videos/video-query.type' | 20 | import { VideoFilter } from '../../shared/models/videos/video-query.type' |
21 | import { logger } from '../helpers/logger' | ||
22 | 21 | ||
23 | const feedsRouter = express.Router() | 22 | const feedsRouter = express.Router() |
24 | 23 | ||
@@ -47,10 +46,24 @@ feedsRouter.get('/feeds/videos.:format', | |||
47 | })(ROUTE_CACHE_LIFETIME.FEEDS)), | 46 | })(ROUTE_CACHE_LIFETIME.FEEDS)), |
48 | commonVideosFiltersValidator, | 47 | commonVideosFiltersValidator, |
49 | asyncMiddleware(videoFeedsValidator), | 48 | asyncMiddleware(videoFeedsValidator), |
50 | asyncMiddleware(videoSubscriptonFeedsValidator), | ||
51 | asyncMiddleware(generateVideoFeed) | 49 | asyncMiddleware(generateVideoFeed) |
52 | ) | 50 | ) |
53 | 51 | ||
52 | feedsRouter.get('/feeds/subscriptions.:format', | ||
53 | videosSortValidator, | ||
54 | setDefaultVideosSort, | ||
55 | feedsFormatValidator, | ||
56 | setFeedFormatContentType, | ||
57 | asyncMiddleware(cacheRoute({ | ||
58 | headerBlacklist: [ | ||
59 | 'Content-Type' | ||
60 | ] | ||
61 | })(ROUTE_CACHE_LIFETIME.FEEDS)), | ||
62 | commonVideosFiltersValidator, | ||
63 | asyncMiddleware(videoSubscriptonFeedsValidator), | ||
64 | asyncMiddleware(generateVideoFeedForSubscriptions) | ||
65 | ) | ||
66 | |||
54 | // --------------------------------------------------------------------------- | 67 | // --------------------------------------------------------------------------- |
55 | 68 | ||
56 | export { | 69 | export { |
@@ -61,7 +74,6 @@ export { | |||
61 | 74 | ||
62 | async function generateVideoCommentsFeed (req: express.Request, res: express.Response) { | 75 | async function generateVideoCommentsFeed (req: express.Request, res: express.Response) { |
63 | const start = 0 | 76 | const start = 0 |
64 | |||
65 | const video = res.locals.videoAll | 77 | const video = res.locals.videoAll |
66 | const account = res.locals.account | 78 | const account = res.locals.account |
67 | const videoChannel = res.locals.videoChannel | 79 | const videoChannel = res.locals.videoChannel |
@@ -125,10 +137,8 @@ async function generateVideoCommentsFeed (req: express.Request, res: express.Res | |||
125 | 137 | ||
126 | async function generateVideoFeed (req: express.Request, res: express.Response) { | 138 | async function generateVideoFeed (req: express.Request, res: express.Response) { |
127 | const start = 0 | 139 | const start = 0 |
128 | |||
129 | const account = res.locals.account | 140 | const account = res.locals.account |
130 | const videoChannel = res.locals.videoChannel | 141 | const videoChannel = res.locals.videoChannel |
131 | const token = req.query.token | ||
132 | const nsfw = buildNSFWFilter(res, req.query.nsfw) | 142 | const nsfw = buildNSFWFilter(res, req.query.nsfw) |
133 | 143 | ||
134 | let name: string | 144 | let name: string |
@@ -152,21 +162,10 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { | |||
152 | queryString: new URL(WEBSERVER.URL + req.url).search | 162 | queryString: new URL(WEBSERVER.URL + req.url).search |
153 | }) | 163 | }) |
154 | 164 | ||
155 | /** | 165 | const options = { |
156 | * We have two ways to query video results: | 166 | accountId: account ? account.id : null, |
157 | * - one with account and token -> get subscription videos | 167 | videoChannelId: videoChannel ? videoChannel.id : null |
158 | * - one with either account, channel, or nothing: just videos with these filters | 168 | } |
159 | */ | ||
160 | const options = token && token !== '' && res.locals.user | ||
161 | ? { | ||
162 | followerActorId: res.locals.user.Account.Actor.id, | ||
163 | user: res.locals.user, | ||
164 | includeLocalVideos: false | ||
165 | } | ||
166 | : { | ||
167 | accountId: account ? account.id : null, | ||
168 | videoChannelId: videoChannel ? videoChannel.id : null | ||
169 | } | ||
170 | 169 | ||
171 | const resultList = await VideoModel.listForApi({ | 170 | const resultList = await VideoModel.listForApi({ |
172 | start, | 171 | start, |
@@ -179,10 +178,86 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { | |||
179 | ...options | 178 | ...options |
180 | }) | 179 | }) |
181 | 180 | ||
181 | addVideosToFeed(feed, resultList.data) | ||
182 | |||
183 | // Now the feed generation is done, let's send it! | ||
184 | return sendFeed(feed, req, res) | ||
185 | } | ||
186 | |||
187 | async function generateVideoFeedForSubscriptions (req: express.Request, res: express.Response) { | ||
188 | const start = 0 | ||
189 | const account = res.locals.account | ||
190 | const nsfw = buildNSFWFilter(res, req.query.nsfw) | ||
191 | const name = account.getDisplayName() | ||
192 | const description = account.description | ||
193 | |||
194 | const feed = initFeed({ | ||
195 | name, | ||
196 | description, | ||
197 | resourceType: 'videos', | ||
198 | queryString: new URL(WEBSERVER.URL + req.url).search | ||
199 | }) | ||
200 | |||
201 | const options = { | ||
202 | followerActorId: res.locals.user.Account.Actor.id, | ||
203 | user: res.locals.user | ||
204 | } | ||
205 | |||
206 | const resultList = await VideoModel.listForApi({ | ||
207 | start, | ||
208 | count: FEEDS.COUNT, | ||
209 | sort: req.query.sort, | ||
210 | includeLocalVideos: true, | ||
211 | nsfw, | ||
212 | filter: req.query.filter as VideoFilter, | ||
213 | withFiles: true, | ||
214 | ...options | ||
215 | }) | ||
216 | |||
217 | addVideosToFeed(feed, resultList.data) | ||
218 | |||
219 | // Now the feed generation is done, let's send it! | ||
220 | return sendFeed(feed, req, res) | ||
221 | } | ||
222 | |||
223 | function initFeed (parameters: { | ||
224 | name: string | ||
225 | description: string | ||
226 | resourceType?: 'videos' | 'video-comments' | ||
227 | queryString?: string | ||
228 | }) { | ||
229 | const webserverUrl = WEBSERVER.URL | ||
230 | const { name, description, resourceType, queryString } = parameters | ||
231 | |||
232 | return new Feed({ | ||
233 | title: name, | ||
234 | description, | ||
235 | // updated: TODO: somehowGetLatestUpdate, // optional, default = today | ||
236 | id: webserverUrl, | ||
237 | link: webserverUrl, | ||
238 | image: webserverUrl + '/client/assets/images/icons/icon-96x96.png', | ||
239 | favicon: webserverUrl + '/client/assets/images/favicon.png', | ||
240 | copyright: `All rights reserved, unless otherwise specified in the terms specified at ${webserverUrl}/about` + | ||
241 | ` and potential licenses granted by each content's rightholder.`, | ||
242 | generator: `Toraifōsu`, // ^.~ | ||
243 | feedLinks: { | ||
244 | json: `${webserverUrl}/feeds/${resourceType}.json${queryString}`, | ||
245 | atom: `${webserverUrl}/feeds/${resourceType}.atom${queryString}`, | ||
246 | rss: `${webserverUrl}/feeds/${resourceType}.xml${queryString}` | ||
247 | }, | ||
248 | author: { | ||
249 | name: 'Instance admin of ' + CONFIG.INSTANCE.NAME, | ||
250 | email: CONFIG.ADMIN.EMAIL, | ||
251 | link: `${webserverUrl}/about` | ||
252 | } | ||
253 | }) | ||
254 | } | ||
255 | |||
256 | function addVideosToFeed (feed, videos: VideoModel[]) { | ||
182 | /** | 257 | /** |
183 | * Adding video items to the feed object, one at a time | 258 | * Adding video items to the feed object, one at a time |
184 | */ | 259 | */ |
185 | resultList.data.forEach(video => { | 260 | for (const video of videos) { |
186 | const formattedVideoFiles = video.getFormattedVideoFilesJSON() | 261 | const formattedVideoFiles = video.getFormattedVideoFilesJSON() |
187 | 262 | ||
188 | const torrents = formattedVideoFiles.map(videoFile => ({ | 263 | const torrents = formattedVideoFiles.map(videoFile => ({ |
@@ -252,43 +327,7 @@ async function generateVideoFeed (req: express.Request, res: express.Response) { | |||
252 | } | 327 | } |
253 | ] | 328 | ] |
254 | }) | 329 | }) |
255 | }) | 330 | } |
256 | |||
257 | // Now the feed generation is done, let's send it! | ||
258 | return sendFeed(feed, req, res) | ||
259 | } | ||
260 | |||
261 | function initFeed (parameters: { | ||
262 | name: string | ||
263 | description: string | ||
264 | resourceType?: 'videos' | 'video-comments' | ||
265 | queryString?: string | ||
266 | }) { | ||
267 | const webserverUrl = WEBSERVER.URL | ||
268 | const { name, description, resourceType, queryString } = parameters | ||
269 | |||
270 | return new Feed({ | ||
271 | title: name, | ||
272 | description, | ||
273 | // updated: TODO: somehowGetLatestUpdate, // optional, default = today | ||
274 | id: webserverUrl, | ||
275 | link: webserverUrl, | ||
276 | image: webserverUrl + '/client/assets/images/icons/icon-96x96.png', | ||
277 | favicon: webserverUrl + '/client/assets/images/favicon.png', | ||
278 | copyright: `All rights reserved, unless otherwise specified in the terms specified at ${webserverUrl}/about` + | ||
279 | ` and potential licenses granted by each content's rightholder.`, | ||
280 | generator: `Toraifōsu`, // ^.~ | ||
281 | feedLinks: { | ||
282 | json: `${webserverUrl}/feeds/${resourceType}.json${queryString}`, | ||
283 | atom: `${webserverUrl}/feeds/${resourceType}.atom${queryString}`, | ||
284 | rss: `${webserverUrl}/feeds/${resourceType}.xml${queryString}` | ||
285 | }, | ||
286 | author: { | ||
287 | name: 'Instance admin of ' + CONFIG.INSTANCE.NAME, | ||
288 | email: CONFIG.ADMIN.EMAIL, | ||
289 | link: `${webserverUrl}/about` | ||
290 | } | ||
291 | }) | ||
292 | } | 331 | } |
293 | 332 | ||
294 | function sendFeed (feed, req: express.Request, res: express.Response) { | 333 | function sendFeed (feed, req: express.Request, res: express.Response) { |