accounts.ts 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import express from 'express'
  2. import { pickCommonVideoQuery } from '@server/helpers/query.js'
  3. import { ActorFollowModel } from '@server/models/actor/actor-follow.js'
  4. import { getServerActor } from '@server/models/application/application.js'
  5. import { VideoChannelSyncModel } from '@server/models/video/video-channel-sync.js'
  6. import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils.js'
  7. import { getFormattedObjects } from '../../helpers/utils.js'
  8. import { JobQueue } from '../../lib/job-queue/index.js'
  9. import { Hooks } from '../../lib/plugins/hooks.js'
  10. import {
  11. apiRateLimiter,
  12. asyncMiddleware,
  13. authenticate,
  14. commonVideosFiltersValidator,
  15. optionalAuthenticate,
  16. paginationValidator,
  17. setDefaultPagination,
  18. setDefaultSort,
  19. setDefaultVideosSort,
  20. videoPlaylistsSortValidator,
  21. videoRatesSortValidator,
  22. videoRatingValidator
  23. } from '../../middlewares/index.js'
  24. import {
  25. accountNameWithHostGetValidator,
  26. accountsFollowersSortValidator,
  27. accountsSortValidator,
  28. ensureAuthUserOwnsAccountValidator,
  29. ensureCanManageChannelOrAccount,
  30. videoChannelsSortValidator,
  31. videoChannelStatsValidator,
  32. videoChannelSyncsSortValidator,
  33. videosSortValidator
  34. } from '../../middlewares/validators/index.js'
  35. import { commonVideoPlaylistFiltersValidator, videoPlaylistsSearchValidator } from '../../middlewares/validators/videos/video-playlists.js'
  36. import { AccountModel } from '../../models/account/account.js'
  37. import { AccountVideoRateModel } from '../../models/account/account-video-rate.js'
  38. import { guessAdditionalAttributesFromQuery } from '../../models/video/formatter/index.js'
  39. import { VideoModel } from '../../models/video/video.js'
  40. import { VideoChannelModel } from '../../models/video/video-channel.js'
  41. import { VideoPlaylistModel } from '../../models/video/video-playlist.js'
  42. const accountsRouter = express.Router()
  43. accountsRouter.use(apiRateLimiter)
  44. accountsRouter.get('/',
  45. paginationValidator,
  46. accountsSortValidator,
  47. setDefaultSort,
  48. setDefaultPagination,
  49. asyncMiddleware(listAccounts)
  50. )
  51. accountsRouter.get('/:accountName',
  52. asyncMiddleware(accountNameWithHostGetValidator),
  53. getAccount
  54. )
  55. accountsRouter.get('/:accountName/videos',
  56. asyncMiddleware(accountNameWithHostGetValidator),
  57. paginationValidator,
  58. videosSortValidator,
  59. setDefaultVideosSort,
  60. setDefaultPagination,
  61. optionalAuthenticate,
  62. commonVideosFiltersValidator,
  63. asyncMiddleware(listAccountVideos)
  64. )
  65. accountsRouter.get('/:accountName/video-channels',
  66. asyncMiddleware(accountNameWithHostGetValidator),
  67. videoChannelStatsValidator,
  68. paginationValidator,
  69. videoChannelsSortValidator,
  70. setDefaultSort,
  71. setDefaultPagination,
  72. asyncMiddleware(listAccountChannels)
  73. )
  74. accountsRouter.get('/:accountName/video-channel-syncs',
  75. authenticate,
  76. asyncMiddleware(accountNameWithHostGetValidator),
  77. ensureCanManageChannelOrAccount,
  78. paginationValidator,
  79. videoChannelSyncsSortValidator,
  80. setDefaultSort,
  81. setDefaultPagination,
  82. asyncMiddleware(listAccountChannelsSync)
  83. )
  84. accountsRouter.get('/:accountName/video-playlists',
  85. optionalAuthenticate,
  86. asyncMiddleware(accountNameWithHostGetValidator),
  87. paginationValidator,
  88. videoPlaylistsSortValidator,
  89. setDefaultSort,
  90. setDefaultPagination,
  91. commonVideoPlaylistFiltersValidator,
  92. videoPlaylistsSearchValidator,
  93. asyncMiddleware(listAccountPlaylists)
  94. )
  95. accountsRouter.get('/:accountName/ratings',
  96. authenticate,
  97. asyncMiddleware(accountNameWithHostGetValidator),
  98. ensureAuthUserOwnsAccountValidator,
  99. paginationValidator,
  100. videoRatesSortValidator,
  101. setDefaultSort,
  102. setDefaultPagination,
  103. videoRatingValidator,
  104. asyncMiddleware(listAccountRatings)
  105. )
  106. accountsRouter.get('/:accountName/followers',
  107. authenticate,
  108. asyncMiddleware(accountNameWithHostGetValidator),
  109. ensureAuthUserOwnsAccountValidator,
  110. paginationValidator,
  111. accountsFollowersSortValidator,
  112. setDefaultSort,
  113. setDefaultPagination,
  114. asyncMiddleware(listAccountFollowers)
  115. )
  116. // ---------------------------------------------------------------------------
  117. export {
  118. accountsRouter
  119. }
  120. // ---------------------------------------------------------------------------
  121. function getAccount (req: express.Request, res: express.Response) {
  122. const account = res.locals.account
  123. if (account.isOutdated()) {
  124. JobQueue.Instance.createJobAsync({ type: 'activitypub-refresher', payload: { type: 'actor', url: account.Actor.url } })
  125. }
  126. return res.json(account.toFormattedJSON())
  127. }
  128. async function listAccounts (req: express.Request, res: express.Response) {
  129. const resultList = await AccountModel.listForApi(req.query.start, req.query.count, req.query.sort)
  130. return res.json(getFormattedObjects(resultList.data, resultList.total))
  131. }
  132. async function listAccountChannels (req: express.Request, res: express.Response) {
  133. const options = {
  134. accountId: res.locals.account.id,
  135. start: req.query.start,
  136. count: req.query.count,
  137. sort: req.query.sort,
  138. withStats: req.query.withStats,
  139. search: req.query.search
  140. }
  141. const resultList = await VideoChannelModel.listByAccountForAPI(options)
  142. return res.json(getFormattedObjects(resultList.data, resultList.total))
  143. }
  144. async function listAccountChannelsSync (req: express.Request, res: express.Response) {
  145. const options = {
  146. accountId: res.locals.account.id,
  147. start: req.query.start,
  148. count: req.query.count,
  149. sort: req.query.sort,
  150. search: req.query.search
  151. }
  152. const resultList = await VideoChannelSyncModel.listByAccountForAPI(options)
  153. return res.json(getFormattedObjects(resultList.data, resultList.total))
  154. }
  155. async function listAccountPlaylists (req: express.Request, res: express.Response) {
  156. const serverActor = await getServerActor()
  157. // Allow users to see their private/unlisted video playlists
  158. let listMyPlaylists = false
  159. if (res.locals.oauth && res.locals.oauth.token.User.Account.id === res.locals.account.id) {
  160. listMyPlaylists = true
  161. }
  162. const resultList = await VideoPlaylistModel.listForApi({
  163. search: req.query.search,
  164. followerActorId: isUserAbleToSearchRemoteURI(res)
  165. ? null
  166. : serverActor.id,
  167. start: req.query.start,
  168. count: req.query.count,
  169. sort: req.query.sort,
  170. accountId: res.locals.account.id,
  171. listMyPlaylists,
  172. type: req.query.playlistType
  173. })
  174. return res.json(getFormattedObjects(resultList.data, resultList.total))
  175. }
  176. async function listAccountVideos (req: express.Request, res: express.Response) {
  177. const serverActor = await getServerActor()
  178. const account = res.locals.account
  179. const displayOnlyForFollower = isUserAbleToSearchRemoteURI(res)
  180. ? null
  181. : {
  182. actorId: serverActor.id,
  183. orLocalVideos: true
  184. }
  185. const countVideos = getCountVideos(req)
  186. const query = pickCommonVideoQuery(req.query)
  187. const apiOptions = await Hooks.wrapObject({
  188. ...query,
  189. displayOnlyForFollower,
  190. nsfw: buildNSFWFilter(res, query.nsfw),
  191. accountId: account.id,
  192. user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
  193. countVideos
  194. }, 'filter:api.accounts.videos.list.params')
  195. const resultList = await Hooks.wrapPromiseFun(
  196. VideoModel.listForApi.bind(VideoModel),
  197. apiOptions,
  198. 'filter:api.accounts.videos.list.result'
  199. )
  200. return res.json(getFormattedObjects(resultList.data, resultList.total, guessAdditionalAttributesFromQuery(query)))
  201. }
  202. async function listAccountRatings (req: express.Request, res: express.Response) {
  203. const account = res.locals.account
  204. const resultList = await AccountVideoRateModel.listByAccountForApi({
  205. accountId: account.id,
  206. start: req.query.start,
  207. count: req.query.count,
  208. sort: req.query.sort,
  209. type: req.query.rating
  210. })
  211. return res.json(getFormattedObjects(resultList.data, resultList.total))
  212. }
  213. async function listAccountFollowers (req: express.Request, res: express.Response) {
  214. const account = res.locals.account
  215. const channels = await VideoChannelModel.listAllByAccount(account.id)
  216. const actorIds = [ account.actorId ].concat(channels.map(c => c.actorId))
  217. const resultList = await ActorFollowModel.listFollowersForApi({
  218. actorIds,
  219. start: req.query.start,
  220. count: req.query.count,
  221. sort: req.query.sort,
  222. search: req.query.search,
  223. state: 'accepted'
  224. })
  225. return res.json(getFormattedObjects(resultList.data, resultList.total))
  226. }