bots.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. import * as express from 'express'
  2. import { asyncMiddleware } from '../middlewares'
  3. import { ROUTE_CACHE_LIFETIME, WEBSERVER } from '../initializers/constants'
  4. import * as sitemapModule from 'sitemap'
  5. import { VideoModel } from '../models/video/video'
  6. import { VideoChannelModel } from '../models/video/video-channel'
  7. import { AccountModel } from '../models/account/account'
  8. import { cacheRoute } from '../middlewares/cache'
  9. import { buildNSFWFilter } from '../helpers/express-utils'
  10. import { truncate } from 'lodash'
  11. const botsRouter = express.Router()
  12. // Special route that add OpenGraph and oEmbed tags
  13. // Do not use a template engine for a so little thing
  14. botsRouter.use('/sitemap.xml',
  15. asyncMiddleware(cacheRoute(ROUTE_CACHE_LIFETIME.SITEMAP)),
  16. asyncMiddleware(getSitemap)
  17. )
  18. // ---------------------------------------------------------------------------
  19. export {
  20. botsRouter
  21. }
  22. // ---------------------------------------------------------------------------
  23. async function getSitemap (req: express.Request, res: express.Response) {
  24. let urls = getSitemapBasicUrls()
  25. urls = urls.concat(await getSitemapLocalVideoUrls())
  26. urls = urls.concat(await getSitemapVideoChannelUrls())
  27. urls = urls.concat(await getSitemapAccountUrls())
  28. const sitemap = sitemapModule.createSitemap({
  29. hostname: WEBSERVER.URL,
  30. urls: urls
  31. })
  32. const xml = sitemap.toXML()
  33. res.header('Content-Type', 'application/xml')
  34. res.send(xml)
  35. }
  36. async function getSitemapVideoChannelUrls () {
  37. const rows = await VideoChannelModel.listLocalsForSitemap('createdAt')
  38. return rows.map(channel => ({
  39. url: WEBSERVER.URL + '/video-channels/' + channel.Actor.preferredUsername
  40. }))
  41. }
  42. async function getSitemapAccountUrls () {
  43. const rows = await AccountModel.listLocalsForSitemap('createdAt')
  44. return rows.map(channel => ({
  45. url: WEBSERVER.URL + '/accounts/' + channel.Actor.preferredUsername
  46. }))
  47. }
  48. async function getSitemapLocalVideoUrls () {
  49. const { data } = await VideoModel.listForApi({
  50. start: 0,
  51. count: undefined,
  52. sort: 'createdAt',
  53. includeLocalVideos: true,
  54. nsfw: buildNSFWFilter(),
  55. filter: 'local',
  56. withFiles: false,
  57. countVideos: false
  58. })
  59. return data.map(v => ({
  60. url: WEBSERVER.URL + '/videos/watch/' + v.uuid,
  61. video: [
  62. {
  63. title: v.name,
  64. // Sitemap description should be < 2000 characters
  65. description: truncate(v.description || v.name, { length: 2000, omission: '...' }),
  66. player_loc: WEBSERVER.URL + '/videos/embed/' + v.uuid,
  67. thumbnail_loc: WEBSERVER.URL + v.getMiniatureStaticPath()
  68. }
  69. ]
  70. }))
  71. }
  72. function getSitemapBasicUrls () {
  73. const paths = [
  74. '/about/instance',
  75. '/videos/local'
  76. ]
  77. return paths.map(p => ({ url: WEBSERVER.URL + p }))
  78. }