1 import express from 'express'
2 import { pickCommonVideoQuery } from '@server/helpers/query'
3 import { ActorFollowModel } from '@server/models/actor/actor-follow'
4 import { getServerActor } from '@server/models/application/application'
5 import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils'
6 import { buildNSFWFilter, getCountVideos, isUserAbleToSearchRemoteURI } from '../../helpers/express-utils'
7 import { getFormattedObjects } from '../../helpers/utils'
8 import { JobQueue } from '../../lib/job-queue'
9 import { Hooks } from '../../lib/plugins/hooks'
13 commonVideosFiltersValidator,
19 videoPlaylistsSortValidator,
20 videoRatesSortValidator,
22 } from '../../middlewares'
24 accountNameWithHostGetValidator,
25 accountsFollowersSortValidator,
26 accountsSortValidator,
27 ensureAuthUserOwnsAccountValidator,
28 videoChannelsSortValidator,
29 videoChannelStatsValidator,
31 } from '../../middlewares/validators'
32 import { commonVideoPlaylistFiltersValidator, videoPlaylistsSearchValidator } from '../../middlewares/validators/videos/video-playlists'
33 import { AccountModel } from '../../models/account/account'
34 import { AccountVideoRateModel } from '../../models/account/account-video-rate'
35 import { VideoModel } from '../../models/video/video'
36 import { VideoChannelModel } from '../../models/video/video-channel'
37 import { VideoPlaylistModel } from '../../models/video/video-playlist'
39 const accountsRouter = express.Router()
41 accountsRouter.get('/',
43 accountsSortValidator,
46 asyncMiddleware(listAccounts)
49 accountsRouter.get('/:accountName',
50 asyncMiddleware(accountNameWithHostGetValidator),
54 accountsRouter.get('/:accountName/videos',
55 asyncMiddleware(accountNameWithHostGetValidator),
61 commonVideosFiltersValidator,
62 asyncMiddleware(listAccountVideos)
65 accountsRouter.get('/:accountName/video-channels',
66 asyncMiddleware(accountNameWithHostGetValidator),
67 videoChannelStatsValidator,
69 videoChannelsSortValidator,
72 asyncMiddleware(listAccountChannels)
75 accountsRouter.get('/:accountName/video-playlists',
77 asyncMiddleware(accountNameWithHostGetValidator),
79 videoPlaylistsSortValidator,
82 commonVideoPlaylistFiltersValidator,
83 videoPlaylistsSearchValidator,
84 asyncMiddleware(listAccountPlaylists)
87 accountsRouter.get('/:accountName/ratings',
89 asyncMiddleware(accountNameWithHostGetValidator),
90 ensureAuthUserOwnsAccountValidator,
92 videoRatesSortValidator,
96 asyncMiddleware(listAccountRatings)
99 accountsRouter.get('/:accountName/followers',
101 asyncMiddleware(accountNameWithHostGetValidator),
102 ensureAuthUserOwnsAccountValidator,
104 accountsFollowersSortValidator,
106 setDefaultPagination,
107 asyncMiddleware(listAccountFollowers)
110 // ---------------------------------------------------------------------------
116 // ---------------------------------------------------------------------------
118 function getAccount (req: express.Request, res: express.Response) {
119 const account = res.locals.account
121 if (account.isOutdated()) {
122 JobQueue.Instance.createJob({ type: 'activitypub-refresher', payload: { type: 'actor', url: account.Actor.url } })
125 return res.json(account.toFormattedJSON())
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)
131 return res.json(getFormattedObjects(resultList.data, resultList.total))
134 async function listAccountChannels (req: express.Request, res: express.Response) {
136 accountId: res.locals.account.id,
137 start: req.query.start,
138 count: req.query.count,
139 sort: req.query.sort,
140 withStats: req.query.withStats,
141 search: req.query.search
144 const resultList = await VideoChannelModel.listByAccountForAPI(options)
146 return res.json(getFormattedObjects(resultList.data, resultList.total))
149 async function listAccountPlaylists (req: express.Request, res: express.Response) {
150 const serverActor = await getServerActor()
152 // Allow users to see their private/unlisted video playlists
153 let listMyPlaylists = false
154 if (res.locals.oauth && res.locals.oauth.token.User.Account.id === res.locals.account.id) {
155 listMyPlaylists = true
158 const resultList = await VideoPlaylistModel.listForApi({
159 search: req.query.search,
160 followerActorId: serverActor.id,
161 start: req.query.start,
162 count: req.query.count,
163 sort: req.query.sort,
164 accountId: res.locals.account.id,
166 type: req.query.playlistType
169 return res.json(getFormattedObjects(resultList.data, resultList.total))
172 async function listAccountVideos (req: express.Request, res: express.Response) {
173 const serverActor = await getServerActor()
175 const account = res.locals.account
177 const displayOnlyForFollower = isUserAbleToSearchRemoteURI(res)
180 actorId: serverActor.id,
184 const countVideos = getCountVideos(req)
185 const query = pickCommonVideoQuery(req.query)
187 const apiOptions = await Hooks.wrapObject({
190 displayOnlyForFollower,
191 nsfw: buildNSFWFilter(res, query.nsfw),
192 accountId: account.id,
193 user: res.locals.oauth ? res.locals.oauth.token.User : undefined,
195 }, 'filter:api.accounts.videos.list.params')
197 const resultList = await Hooks.wrapPromiseFun(
198 VideoModel.listForApi,
200 'filter:api.accounts.videos.list.result'
203 return res.json(getFormattedObjects(resultList.data, resultList.total, guessAdditionalAttributesFromQuery(query)))
206 async function listAccountRatings (req: express.Request, res: express.Response) {
207 const account = res.locals.account
209 const resultList = await AccountVideoRateModel.listByAccountForApi({
210 accountId: account.id,
211 start: req.query.start,
212 count: req.query.count,
213 sort: req.query.sort,
214 type: req.query.rating
216 return res.json(getFormattedObjects(resultList.data, resultList.total))
219 async function listAccountFollowers (req: express.Request, res: express.Response) {
220 const account = res.locals.account
222 const channels = await VideoChannelModel.listAllByAccount(account.id)
223 const actorIds = [ account.actorId ].concat(channels.map(c => c.actorId))
225 const resultList = await ActorFollowModel.listFollowersForApi({
227 start: req.query.start,
228 count: req.query.count,
229 sort: req.query.sort,
230 search: req.query.search,
234 return res.json(getFormattedObjects(resultList.data, resultList.total))