my-subscriptions.ts 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import * as express from 'express'
  2. import 'multer'
  3. import { getFormattedObjects } from '../../../helpers/utils'
  4. import { WEBSERVER } from '../../../initializers/constants'
  5. import {
  6. asyncMiddleware,
  7. asyncRetryTransactionMiddleware,
  8. authenticate,
  9. commonVideosFiltersValidator,
  10. paginationValidator,
  11. setDefaultPagination,
  12. setDefaultSort,
  13. userSubscriptionAddValidator,
  14. userSubscriptionGetValidator
  15. } from '../../../middlewares'
  16. import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators'
  17. import { VideoModel } from '../../../models/video/video'
  18. import { buildNSFWFilter } from '../../../helpers/express-utils'
  19. import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
  20. import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
  21. import { JobQueue } from '../../../lib/job-queue'
  22. import { logger } from '../../../helpers/logger'
  23. import { sequelizeTypescript } from '../../../initializers/database'
  24. const mySubscriptionsRouter = express.Router()
  25. mySubscriptionsRouter.get('/me/subscriptions/videos',
  26. authenticate,
  27. paginationValidator,
  28. videosSortValidator,
  29. setDefaultSort,
  30. setDefaultPagination,
  31. commonVideosFiltersValidator,
  32. asyncMiddleware(getUserSubscriptionVideos)
  33. )
  34. mySubscriptionsRouter.get('/me/subscriptions/exist',
  35. authenticate,
  36. areSubscriptionsExistValidator,
  37. asyncMiddleware(areSubscriptionsExist)
  38. )
  39. mySubscriptionsRouter.get('/me/subscriptions',
  40. authenticate,
  41. paginationValidator,
  42. userSubscriptionsSortValidator,
  43. setDefaultSort,
  44. setDefaultPagination,
  45. asyncMiddleware(getUserSubscriptions)
  46. )
  47. mySubscriptionsRouter.post('/me/subscriptions',
  48. authenticate,
  49. userSubscriptionAddValidator,
  50. asyncMiddleware(addUserSubscription)
  51. )
  52. mySubscriptionsRouter.get('/me/subscriptions/:uri',
  53. authenticate,
  54. userSubscriptionGetValidator,
  55. getUserSubscription
  56. )
  57. mySubscriptionsRouter.delete('/me/subscriptions/:uri',
  58. authenticate,
  59. userSubscriptionGetValidator,
  60. asyncRetryTransactionMiddleware(deleteUserSubscription)
  61. )
  62. // ---------------------------------------------------------------------------
  63. export {
  64. mySubscriptionsRouter
  65. }
  66. // ---------------------------------------------------------------------------
  67. async function areSubscriptionsExist (req: express.Request, res: express.Response) {
  68. const uris = req.query.uris as string[]
  69. const user = res.locals.oauth.token.User
  70. const handles = uris.map(u => {
  71. let [ name, host ] = u.split('@')
  72. if (host === WEBSERVER.HOST) host = null
  73. return { name, host, uri: u }
  74. })
  75. const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles)
  76. const existObject: { [id: string ]: boolean } = {}
  77. for (const handle of handles) {
  78. const obj = results.find(r => {
  79. const server = r.ActorFollowing.Server
  80. return r.ActorFollowing.preferredUsername === handle.name &&
  81. (
  82. (!server && !handle.host) ||
  83. (server.host === handle.host)
  84. )
  85. })
  86. existObject[handle.uri] = obj !== undefined
  87. }
  88. return res.json(existObject)
  89. }
  90. async function addUserSubscription (req: express.Request, res: express.Response) {
  91. const user = res.locals.oauth.token.User
  92. const [ name, host ] = req.body.uri.split('@')
  93. const payload = {
  94. name,
  95. host,
  96. followerActorId: user.Account.Actor.id
  97. }
  98. JobQueue.Instance.createJob({ type: 'activitypub-follow', payload })
  99. .catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err))
  100. return res.status(204).end()
  101. }
  102. function getUserSubscription (req: express.Request, res: express.Response) {
  103. const subscription = res.locals.subscription
  104. return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON())
  105. }
  106. async function deleteUserSubscription (req: express.Request, res: express.Response) {
  107. const subscription = res.locals.subscription
  108. await sequelizeTypescript.transaction(async t => {
  109. return subscription.destroy({ transaction: t })
  110. })
  111. return res.type('json').status(204).end()
  112. }
  113. async function getUserSubscriptions (req: express.Request, res: express.Response) {
  114. const user = res.locals.oauth.token.User
  115. const actorId = user.Account.Actor.id
  116. const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort)
  117. return res.json(getFormattedObjects(resultList.data, resultList.total))
  118. }
  119. async function getUserSubscriptionVideos (req: express.Request, res: express.Response) {
  120. const user = res.locals.oauth.token.User
  121. const resultList = await VideoModel.listForApi({
  122. start: req.query.start,
  123. count: req.query.count,
  124. sort: req.query.sort,
  125. includeLocalVideos: false,
  126. categoryOneOf: req.query.categoryOneOf,
  127. licenceOneOf: req.query.licenceOneOf,
  128. languageOneOf: req.query.languageOneOf,
  129. tagsOneOf: req.query.tagsOneOf,
  130. tagsAllOf: req.query.tagsAllOf,
  131. nsfw: buildNSFWFilter(res, req.query.nsfw),
  132. filter: req.query.filter as VideoFilter,
  133. withFiles: false,
  134. followerActorId: user.Account.Actor.id,
  135. user
  136. })
  137. return res.json(getFormattedObjects(resultList.data, resultList.total))
  138. }