aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'server/controllers')
-rw-r--r--server/controllers/feeds.ts155
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'
18import { VideoModel } from '../models/video/video' 18import { VideoModel } from '../models/video/video'
19import { VideoCommentModel } from '../models/video/video-comment' 19import { VideoCommentModel } from '../models/video/video-comment'
20import { VideoFilter } from '../../shared/models/videos/video-query.type' 20import { VideoFilter } from '../../shared/models/videos/video-query.type'
21import { logger } from '../helpers/logger'
22 21
23const feedsRouter = express.Router() 22const 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
52feedsRouter.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
56export { 69export {
@@ -61,7 +74,6 @@ export {
61 74
62async function generateVideoCommentsFeed (req: express.Request, res: express.Response) { 75async 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
126async function generateVideoFeed (req: express.Request, res: express.Response) { 138async 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
187async 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
223function 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
256function 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
261function 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
294function sendFeed (feed, req: express.Request, res: express.Response) { 333function sendFeed (feed, req: express.Request, res: express.Response) {