X-Git-Url: https://git.immae.eu/?a=blobdiff_plain;f=server%2Fcontrollers%2Fapi%2Fusers%2Fmy-subscriptions.ts;h=6e2aa371108a9b97b11db69f49b29b0fefb4f2a0;hb=85c20aaeb90ef0e0f44c377e62c323fde275cdde;hp=accca6d520f0c02ba8e810aca108f966c624a1d1;hpb=88108880bbdba473cfe36ecbebc1c3c4f972e102;p=github%2FChocobozzz%2FPeerTube.git diff --git a/server/controllers/api/users/my-subscriptions.ts b/server/controllers/api/users/my-subscriptions.ts index accca6d52..6e2aa3711 100644 --- a/server/controllers/api/users/my-subscriptions.ts +++ b/server/controllers/api/users/my-subscriptions.ts @@ -1,7 +1,15 @@ -import * as express from 'express' import 'multer' +import express from 'express' +import { handlesToNameAndHost } from '@server/helpers/actors' +import { pickCommonVideoQuery } from '@server/helpers/query' +import { sendUndoFollow } from '@server/lib/activitypub/send' +import { guessAdditionalAttributesFromQuery } from '@server/models/video/formatter/video-format-utils' +import { VideoChannelModel } from '@server/models/video/video-channel' +import { HttpStatusCode } from '../../../../shared/models/http/http-error-codes' +import { buildNSFWFilter, getCountVideos } from '../../../helpers/express-utils' import { getFormattedObjects } from '../../../helpers/utils' -import { CONFIG, sequelizeTypescript } from '../../../initializers' +import { sequelizeTypescript } from '../../../initializers/database' +import { JobQueue } from '../../../lib/job-queue' import { asyncMiddleware, asyncRetryTransactionMiddleware, @@ -10,17 +18,19 @@ import { paginationValidator, setDefaultPagination, setDefaultSort, + setDefaultVideosSort, userSubscriptionAddValidator, userSubscriptionGetValidator } from '../../../middlewares' -import { areSubscriptionsExistValidator, userSubscriptionsSortValidator, videosSortValidator } from '../../../middlewares/validators' -import { UserModel } from '../../../models/account/user' +import { + areSubscriptionsExistValidator, + userSubscriptionListValidator, + userSubscriptionsSortValidator, + videosSortValidator +} from '../../../middlewares/validators' +import { ActorFollowModel } from '../../../models/actor/actor-follow' import { VideoModel } from '../../../models/video/video' -import { buildNSFWFilter } from '../../../helpers/express-utils' -import { VideoFilter } from '../../../../shared/models/videos/video-query.type' -import { ActorFollowModel } from '../../../models/activitypub/actor-follow' -import { JobQueue } from '../../../lib/job-queue' -import { logger } from '../../../helpers/logger' +import { Hooks } from '@server/lib/plugins/hooks' const mySubscriptionsRouter = express.Router() @@ -28,7 +38,7 @@ mySubscriptionsRouter.get('/me/subscriptions/videos', authenticate, paginationValidator, videosSortValidator, - setDefaultSort, + setDefaultVideosSort, setDefaultPagination, commonVideosFiltersValidator, asyncMiddleware(getUserSubscriptionVideos) @@ -46,19 +56,20 @@ mySubscriptionsRouter.get('/me/subscriptions', userSubscriptionsSortValidator, setDefaultSort, setDefaultPagination, + userSubscriptionListValidator, asyncMiddleware(getUserSubscriptions) ) mySubscriptionsRouter.post('/me/subscriptions', authenticate, userSubscriptionAddValidator, - asyncMiddleware(addUserSubscription) + addUserSubscription ) mySubscriptionsRouter.get('/me/subscriptions/:uri', authenticate, userSubscriptionGetValidator, - getUserSubscription + asyncMiddleware(getUserSubscription) ) mySubscriptionsRouter.delete('/me/subscriptions/:uri', @@ -77,94 +88,106 @@ export { async function areSubscriptionsExist (req: express.Request, res: express.Response) { const uris = req.query.uris as string[] - const user = res.locals.oauth.token.User as UserModel + const user = res.locals.oauth.token.User - const handles = uris.map(u => { - let [ name, host ] = u.split('@') - if (host === CONFIG.WEBSERVER.HOST) host = null - - return { name, host, uri: u } - }) + const sanitizedHandles = handlesToNameAndHost(uris) - const results = await ActorFollowModel.listSubscribedIn(user.Account.Actor.id, handles) + const results = await ActorFollowModel.listSubscriptionsOf(user.Account.Actor.id, sanitizedHandles) const existObject: { [id: string ]: boolean } = {} - for (const handle of handles) { + for (const sanitizedHandle of sanitizedHandles) { const obj = results.find(r => { const server = r.ActorFollowing.Server - return r.ActorFollowing.preferredUsername === handle.name && + return r.ActorFollowing.preferredUsername.toLowerCase() === sanitizedHandle.name.toLowerCase() && ( - (!server && !handle.host) || - (server.host === handle.host) + (!server && !sanitizedHandle.host) || + (server.host === sanitizedHandle.host) ) }) - existObject[handle.uri] = obj !== undefined + existObject[sanitizedHandle.handle] = obj !== undefined } return res.json(existObject) } -async function addUserSubscription (req: express.Request, res: express.Response) { - const user = res.locals.oauth.token.User as UserModel +function addUserSubscription (req: express.Request, res: express.Response) { + const user = res.locals.oauth.token.User const [ name, host ] = req.body.uri.split('@') const payload = { name, host, + assertIsChannel: true, followerActorId: user.Account.Actor.id } - JobQueue.Instance.createJob({ type: 'activitypub-follow', payload }) - .catch(err => logger.error('Cannot create follow job for subscription %s.', req.body.uri, err)) + JobQueue.Instance.createJobAsync({ type: 'activitypub-follow', payload }) - return res.status(204).end() + return res.status(HttpStatusCode.NO_CONTENT_204).end() } -function getUserSubscription (req: express.Request, res: express.Response) { - const subscription: ActorFollowModel = res.locals.subscription +async function getUserSubscription (req: express.Request, res: express.Response) { + const subscription = res.locals.subscription + const videoChannel = await VideoChannelModel.loadAndPopulateAccount(subscription.ActorFollowing.VideoChannel.id) - return res.json(subscription.ActorFollowing.VideoChannel.toFormattedJSON()) + return res.json(videoChannel.toFormattedJSON()) } async function deleteUserSubscription (req: express.Request, res: express.Response) { - const subscription: ActorFollowModel = res.locals.subscription + const subscription = res.locals.subscription await sequelizeTypescript.transaction(async t => { + if (subscription.state === 'accepted') { + sendUndoFollow(subscription, t) + } + return subscription.destroy({ transaction: t }) }) - return res.type('json').status(204).end() + return res.type('json') + .status(HttpStatusCode.NO_CONTENT_204) + .end() } async function getUserSubscriptions (req: express.Request, res: express.Response) { - const user = res.locals.oauth.token.User as UserModel + const user = res.locals.oauth.token.User const actorId = user.Account.Actor.id - const resultList = await ActorFollowModel.listSubscriptionsForApi(actorId, req.query.start, req.query.count, req.query.sort) - - return res.json(getFormattedObjects(resultList.data, resultList.total)) -} - -async function getUserSubscriptionVideos (req: express.Request, res: express.Response, next: express.NextFunction) { - const user = res.locals.oauth.token.User as UserModel - const resultList = await VideoModel.listForApi({ + const resultList = await ActorFollowModel.listSubscriptionsForApi({ + actorId, start: req.query.start, count: req.query.count, sort: req.query.sort, - includeLocalVideos: false, - categoryOneOf: req.query.categoryOneOf, - licenceOneOf: req.query.licenceOneOf, - languageOneOf: req.query.languageOneOf, - tagsOneOf: req.query.tagsOneOf, - tagsAllOf: req.query.tagsAllOf, - nsfw: buildNSFWFilter(res, req.query.nsfw), - filter: req.query.filter as VideoFilter, - withFiles: false, - followerActorId: user.Account.Actor.id, - user + search: req.query.search }) return res.json(getFormattedObjects(resultList.data, resultList.total)) } + +async function getUserSubscriptionVideos (req: express.Request, res: express.Response) { + const user = res.locals.oauth.token.User + const countVideos = getCountVideos(req) + const query = pickCommonVideoQuery(req.query) + + const apiOptions = await Hooks.wrapObject({ + ...query, + + displayOnlyForFollower: { + actorId: user.Account.Actor.id, + orLocalVideos: false + }, + nsfw: buildNSFWFilter(res, query.nsfw), + user, + countVideos + }, 'filter:api.user.me.subscription-videos.list.params') + + const resultList = await Hooks.wrapPromiseFun( + VideoModel.listForApi, + apiOptions, + 'filter:api.user.me.subscription-videos.list.result' + ) + + return res.json(getFormattedObjects(resultList.data, resultList.total, guessAdditionalAttributesFromQuery(query))) +}