### BREAKING CHANGES
* Hide by default NSFW videos. Update the `instance.default_nsfw_policy` configuration to `blur` to keep the old behaviour
+ * Move video channels routes:
+ * `/videos/channels` routes to `/accounts/{accountId}/video-channels`
+ * `/videos/accounts/{accountId}/channels` route to `/accounts/{accountId}/video-channels`
* PeerTube now listen on 127.0.0.1 by default
* Use ISO 639 for language (*en*, *es*, *fr*...)
* Tools (`import-videos`...) need the language ISO639 code instead of a number
import * as express from 'express'
-import { getFormattedObjects } from '../../helpers/utils'
-import { asyncMiddleware, optionalAuthenticate, paginationValidator, setDefaultPagination, setDefaultSort } from '../../middlewares'
+import { getFormattedObjects, resetSequelizeInstance } from '../../helpers/utils'
+import {
+ asyncMiddleware,
+ authenticate,
+ listVideoAccountChannelsValidator,
+ optionalAuthenticate,
+ paginationValidator,
+ setDefaultPagination,
+ setDefaultSort,
+ videoChannelsAddValidator,
+ videoChannelsGetValidator,
+ videoChannelsRemoveValidator,
+ videoChannelsUpdateValidator
+} from '../../middlewares'
import { accountsGetValidator, accountsSortValidator, videosSortValidator } from '../../middlewares/validators'
import { AccountModel } from '../../models/account/account'
import { VideoModel } from '../../models/video/video'
-import { VideoSortField } from '../../../client/src/app/shared/video/sort-field.type'
import { isNSFWHidden } from '../../helpers/express-utils'
+import { VideoChannelModel } from '../../models/video/video-channel'
+import { VideoChannelCreate, VideoChannelUpdate } from '../../../shared'
+import { sendUpdateActor } from '../../lib/activitypub/send'
+import { createVideoChannel } from '../../lib/video-channel'
+import { setAsyncActorKeys } from '../../lib/activitypub'
+import { sequelizeTypescript } from '../../initializers'
+import { logger } from '../../helpers/logger'
+import { retryTransactionWrapper } from '../../helpers/database-utils'
const accountsRouter = express.Router()
setDefaultSort,
setDefaultPagination,
optionalAuthenticate,
- asyncMiddleware(getAccountVideos)
+ asyncMiddleware(listAccountVideos)
+)
+
+accountsRouter.get('/:accountId/video-channels',
+ asyncMiddleware(listVideoAccountChannelsValidator),
+ asyncMiddleware(listVideoAccountChannels)
+)
+
+accountsRouter.post('/:accountId/video-channels',
+ authenticate,
+ videoChannelsAddValidator,
+ asyncMiddleware(addVideoChannelRetryWrapper)
+)
+
+accountsRouter.put('/:accountId/video-channels/:id',
+ authenticate,
+ asyncMiddleware(videoChannelsUpdateValidator),
+ updateVideoChannelRetryWrapper
+)
+
+accountsRouter.delete('/:accountId/video-channels/:id',
+ authenticate,
+ asyncMiddleware(videoChannelsRemoveValidator),
+ asyncMiddleware(removeVideoChannelRetryWrapper)
+)
+
+accountsRouter.get('/:accountId/video-channels/:id',
+ asyncMiddleware(videoChannelsGetValidator),
+ asyncMiddleware(getVideoChannel)
+)
+
+accountsRouter.get('/:accountId/video-channels/:id/videos',
+ asyncMiddleware(videoChannelsGetValidator),
+ paginationValidator,
+ videosSortValidator,
+ setDefaultSort,
+ setDefaultPagination,
+ optionalAuthenticate,
+ asyncMiddleware(listVideoChannelVideos)
)
// ---------------------------------------------------------------------------
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
-async function getAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
+async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const resultList = await VideoChannelModel.listByAccount(res.locals.account.id)
+
+ return res.json(getFormattedObjects(resultList.data, resultList.total))
+}
+
+// Wrapper to video channel add that retry the async function if there is a database error
+// We need this because we run the transaction in SERIALIZABLE isolation that can fail
+async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const options = {
+ arguments: [ req, res ],
+ errorMessage: 'Cannot insert the video video channel with many retries.'
+ }
+
+ const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
+ return res.json({
+ videoChannel: {
+ id: videoChannel.id
+ }
+ }).end()
+}
+
+async function addVideoChannel (req: express.Request, res: express.Response) {
+ const videoChannelInfo: VideoChannelCreate = req.body
+ const account: AccountModel = res.locals.oauth.token.User.Account
+
+ const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
+ return createVideoChannel(videoChannelInfo, account, t)
+ })
+
+ setAsyncActorKeys(videoChannelCreated.Actor)
+ .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
+
+ logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
+
+ return videoChannelCreated
+}
+
+async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const options = {
+ arguments: [ req, res ],
+ errorMessage: 'Cannot update the video with many retries.'
+ }
+
+ await retryTransactionWrapper(updateVideoChannel, options)
+
+ return res.type('json').status(204).end()
+}
+
+async function updateVideoChannel (req: express.Request, res: express.Response) {
+ const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
+ const videoChannelFieldsSave = videoChannelInstance.toJSON()
+ const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
+
+ try {
+ await sequelizeTypescript.transaction(async t => {
+ const sequelizeOptions = {
+ transaction: t
+ }
+
+ if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
+ if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
+ if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
+
+ const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
+ await sendUpdateActor(videoChannelInstanceUpdated, t)
+ })
+
+ logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
+ } catch (err) {
+ logger.debug('Cannot update the video channel.', { err })
+
+ // Force fields we want to update
+ // If the transaction is retried, sequelize will think the object has not changed
+ // So it will skip the SQL request, even if the last one was ROLLBACKed!
+ resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
+
+ throw err
+ }
+}
+
+async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const options = {
+ arguments: [ req, res ],
+ errorMessage: 'Cannot remove the video channel with many retries.'
+ }
+
+ await retryTransactionWrapper(removeVideoChannel, options)
+
+ return res.type('json').status(204).end()
+}
+
+async function removeVideoChannel (req: express.Request, res: express.Response) {
+ const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
+
+ return sequelizeTypescript.transaction(async t => {
+ await videoChannelInstance.destroy({ transaction: t })
+
+ logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
+ })
+
+}
+
+async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
+
+ return res.json(videoChannelWithVideos.toFormattedJSON())
+}
+
+async function listVideoChannelVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
+
+ const resultList = await VideoModel.listForApi({
+ start: req.query.start,
+ count: req.query.count,
+ sort: req.query.sort,
+ hideNSFW: isNSFWHidden(res),
+ withFiles: false,
+ videoChannelId: videoChannelInstance.id
+ })
+
+ return res.json(getFormattedObjects(resultList.data, resultList.total))
+}
+
+
+async function listAccountVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
const account: AccountModel = res.locals.account
- const resultList = await VideoModel.listForApi(
- req.query.start as number,
- req.query.count as number,
- req.query.sort as VideoSortField,
- isNSFWHidden(res),
- null,
- false,
- account.id
- )
+ const resultList = await VideoModel.listForApi({
+ start: req.query.start,
+ count: req.query.count,
+ sort: req.query.sort,
+ hideNSFW: isNSFWHidden(res),
+ withFiles: false,
+ accountId: account.id
+ })
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
import { accountsRouter } from './accounts'
import { videosRouter } from './videos'
import { badRequest } from '../../helpers/express-utils'
+import { videoChannelRouter } from './video-channel'
const apiRouter = express.Router()
apiRouter.use('/config', configRouter)
apiRouter.use('/users', usersRouter)
apiRouter.use('/accounts', accountsRouter)
+apiRouter.use('/video-channels', videoChannelRouter)
apiRouter.use('/videos', videosRouter)
apiRouter.use('/jobs', jobsRouter)
apiRouter.use('/ping', pong)
--- /dev/null
+import * as express from 'express'
+import { getFormattedObjects } from '../../helpers/utils'
+import {
+ asyncMiddleware,
+ paginationValidator,
+ setDefaultPagination,
+ setDefaultSort,
+ videoChannelsSortValidator
+} from '../../middlewares'
+import { VideoChannelModel } from '../../models/video/video-channel'
+
+const videoChannelRouter = express.Router()
+
+videoChannelRouter.get('/',
+ paginationValidator,
+ videoChannelsSortValidator,
+ setDefaultSort,
+ setDefaultPagination,
+ asyncMiddleware(listVideoChannels)
+)
+
+// ---------------------------------------------------------------------------
+
+export {
+ videoChannelRouter
+}
+
+// ---------------------------------------------------------------------------
+
+async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
+ const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort)
+
+ return res.json(getFormattedObjects(resultList.data, resultList.total))
+}
+++ /dev/null
-import * as express from 'express'
-import { VideoChannelCreate, VideoChannelUpdate } from '../../../../shared'
-import { retryTransactionWrapper } from '../../../helpers/database-utils'
-import { logger } from '../../../helpers/logger'
-import { getFormattedObjects, resetSequelizeInstance } from '../../../helpers/utils'
-import { sequelizeTypescript } from '../../../initializers'
-import { setAsyncActorKeys } from '../../../lib/activitypub'
-import { sendUpdateActor } from '../../../lib/activitypub/send'
-import { createVideoChannel } from '../../../lib/video-channel'
-import {
- asyncMiddleware, authenticate, listVideoAccountChannelsValidator, paginationValidator, setDefaultSort, setDefaultPagination,
- videoChannelsAddValidator, videoChannelsGetValidator, videoChannelsRemoveValidator, videoChannelsSortValidator,
- videoChannelsUpdateValidator
-} from '../../../middlewares'
-import { AccountModel } from '../../../models/account/account'
-import { VideoChannelModel } from '../../../models/video/video-channel'
-
-const videoChannelRouter = express.Router()
-
-videoChannelRouter.get('/channels',
- paginationValidator,
- videoChannelsSortValidator,
- setDefaultSort,
- setDefaultPagination,
- asyncMiddleware(listVideoChannels)
-)
-
-videoChannelRouter.get('/accounts/:accountId/channels',
- asyncMiddleware(listVideoAccountChannelsValidator),
- asyncMiddleware(listVideoAccountChannels)
-)
-
-videoChannelRouter.post('/channels',
- authenticate,
- videoChannelsAddValidator,
- asyncMiddleware(addVideoChannelRetryWrapper)
-)
-
-videoChannelRouter.put('/channels/:id',
- authenticate,
- asyncMiddleware(videoChannelsUpdateValidator),
- updateVideoChannelRetryWrapper
-)
-
-videoChannelRouter.delete('/channels/:id',
- authenticate,
- asyncMiddleware(videoChannelsRemoveValidator),
- asyncMiddleware(removeVideoChannelRetryWrapper)
-)
-
-videoChannelRouter.get('/channels/:id',
- asyncMiddleware(videoChannelsGetValidator),
- asyncMiddleware(getVideoChannel)
-)
-
-// ---------------------------------------------------------------------------
-
-export {
- videoChannelRouter
-}
-
-// ---------------------------------------------------------------------------
-
-async function listVideoChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
- const resultList = await VideoChannelModel.listForApi(req.query.start, req.query.count, req.query.sort)
-
- return res.json(getFormattedObjects(resultList.data, resultList.total))
-}
-
-async function listVideoAccountChannels (req: express.Request, res: express.Response, next: express.NextFunction) {
- const resultList = await VideoChannelModel.listByAccount(res.locals.account.id)
-
- return res.json(getFormattedObjects(resultList.data, resultList.total))
-}
-
-// Wrapper to video channel add that retry the async function if there is a database error
-// We need this because we run the transaction in SERIALIZABLE isolation that can fail
-async function addVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
- const options = {
- arguments: [ req, res ],
- errorMessage: 'Cannot insert the video video channel with many retries.'
- }
-
- const videoChannel = await retryTransactionWrapper(addVideoChannel, options)
- return res.json({
- videoChannel: {
- id: videoChannel.id
- }
- }).end()
-}
-
-async function addVideoChannel (req: express.Request, res: express.Response) {
- const videoChannelInfo: VideoChannelCreate = req.body
- const account: AccountModel = res.locals.oauth.token.User.Account
-
- const videoChannelCreated: VideoChannelModel = await sequelizeTypescript.transaction(async t => {
- return createVideoChannel(videoChannelInfo, account, t)
- })
-
- setAsyncActorKeys(videoChannelCreated.Actor)
- .catch(err => logger.error('Cannot set async actor keys for account %s.', videoChannelCreated.Actor.uuid, { err }))
-
- logger.info('Video channel with uuid %s created.', videoChannelCreated.Actor.uuid)
-
- return videoChannelCreated
-}
-
-async function updateVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
- const options = {
- arguments: [ req, res ],
- errorMessage: 'Cannot update the video with many retries.'
- }
-
- await retryTransactionWrapper(updateVideoChannel, options)
-
- return res.type('json').status(204).end()
-}
-
-async function updateVideoChannel (req: express.Request, res: express.Response) {
- const videoChannelInstance = res.locals.videoChannel as VideoChannelModel
- const videoChannelFieldsSave = videoChannelInstance.toJSON()
- const videoChannelInfoToUpdate = req.body as VideoChannelUpdate
-
- try {
- await sequelizeTypescript.transaction(async t => {
- const sequelizeOptions = {
- transaction: t
- }
-
- if (videoChannelInfoToUpdate.name !== undefined) videoChannelInstance.set('name', videoChannelInfoToUpdate.name)
- if (videoChannelInfoToUpdate.description !== undefined) videoChannelInstance.set('description', videoChannelInfoToUpdate.description)
- if (videoChannelInfoToUpdate.support !== undefined) videoChannelInstance.set('support', videoChannelInfoToUpdate.support)
-
- const videoChannelInstanceUpdated = await videoChannelInstance.save(sequelizeOptions)
- await sendUpdateActor(videoChannelInstanceUpdated, t)
- })
-
- logger.info('Video channel with name %s and uuid %s updated.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
- } catch (err) {
- logger.debug('Cannot update the video channel.', { err })
-
- // Force fields we want to update
- // If the transaction is retried, sequelize will think the object has not changed
- // So it will skip the SQL request, even if the last one was ROLLBACKed!
- resetSequelizeInstance(videoChannelInstance, videoChannelFieldsSave)
-
- throw err
- }
-}
-
-async function removeVideoChannelRetryWrapper (req: express.Request, res: express.Response, next: express.NextFunction) {
- const options = {
- arguments: [ req, res ],
- errorMessage: 'Cannot remove the video channel with many retries.'
- }
-
- await retryTransactionWrapper(removeVideoChannel, options)
-
- return res.type('json').status(204).end()
-}
-
-async function removeVideoChannel (req: express.Request, res: express.Response) {
- const videoChannelInstance: VideoChannelModel = res.locals.videoChannel
-
- return sequelizeTypescript.transaction(async t => {
- await videoChannelInstance.destroy({ transaction: t })
-
- logger.info('Video channel with name %s and uuid %s deleted.', videoChannelInstance.name, videoChannelInstance.Actor.uuid)
- })
-
-}
-
-async function getVideoChannel (req: express.Request, res: express.Response, next: express.NextFunction) {
- const videoChannelWithVideos = await VideoChannelModel.loadAndPopulateAccountAndVideos(res.locals.videoChannel.id)
-
- return res.json(videoChannelWithVideos.toFormattedJSON())
-}
import { VideoFileModel } from '../../../models/video/video-file'
import { abuseVideoRouter } from './abuse'
import { blacklistRouter } from './blacklist'
-import { videoChannelRouter } from './channel'
import { videoCommentRouter } from './comment'
import { rateVideoRouter } from './rate'
import { VideoFilter } from '../../../../shared/models/videos/video-query.type'
videosRouter.use('/', abuseVideoRouter)
videosRouter.use('/', blacklistRouter)
videosRouter.use('/', rateVideoRouter)
-videosRouter.use('/', videoChannelRouter)
videosRouter.use('/', videoCommentRouter)
videosRouter.get('/categories', listVideoCategories)
}
async function listVideos (req: express.Request, res: express.Response, next: express.NextFunction) {
- const resultList = await VideoModel.listForApi(
- req.query.start as number,
- req.query.count as number,
- req.query.sort as VideoSortField,
- isNSFWHidden(res),
- req.query.filter as VideoFilter
- )
+ const resultList = await VideoModel.listForApi({
+ start: req.query.start,
+ count: req.query.count,
+ sort: req.query.sort,
+ hideNSFW: isNSFWHidden(res),
+ filter: req.query.filter as VideoFilter,
+ withFiles: false
+ })
return res.json(getFormattedObjects(resultList.data, resultList.total))
}
const account: AccountModel = res.locals.account
const hideNSFW = CONFIG.INSTANCE.DEFAULT_NSFW_POLICY === 'do_not_list'
- const resultList = await VideoModel.listForApi(
+ const resultList = await VideoModel.listForApi({
start,
- FEEDS.COUNT,
- req.query.sort as VideoSortField,
+ count: FEEDS.COUNT,
+ sort: req.query.sort,
hideNSFW,
- req.query.filter,
- true,
- account ? account.id : null
- )
+ filter: req.query.filter,
+ withFiles: true,
+ accountId: account ? account.id : null
+ })
// Adding video items to the feed, one at a time
resultList.data.forEach(video => {
if (isTestInstance() === false && CONFIG.WEBSERVER.SCHEME === 'http') {
return res.status(400)
.json({
- error: 'Cannot follow non HTTPS web server.'
+ error: 'Cannot follow on a non HTTPS web server.'
})
.end()
}
]
const videoChannelsAddValidator = [
+ param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
body('name').custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
const videoChannelsUpdateValidator = [
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
+ param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
body('name').optional().custom(isVideoChannelNameValid).withMessage('Should have a valid name'),
body('description').optional().custom(isVideoChannelDescriptionValid).withMessage('Should have a valid description'),
body('support').optional().custom(isVideoChannelSupportValid).withMessage('Should have a valid support text'),
logger.debug('Checking videoChannelsUpdate parameters', { parameters: req.body })
if (areValidationErrors(req, res)) return
+ if (!await isAccountIdExist(req.params.accountId, res)) return
if (!await isVideoChannelExist(req.params.id, res)) return
// We need to make additional checks
const videoChannelsRemoveValidator = [
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
+ param('accountId').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoChannelsRemove parameters', { parameters: req.params })
if (areValidationErrors(req, res)) return
+ if (!await isAccountIdExist(req.params.accountId, res)) return
if (!await isVideoChannelExist(req.params.id, res)) return
// Check if the user who did the request is able to delete the video
const videoChannelsGetValidator = [
param('id').custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid id'),
+ param('accountId').optional().custom(isIdOrUUIDValid).not().isEmpty().withMessage('Should have a valid account id'),
async (req: express.Request, res: express.Response, next: express.NextFunction) => {
logger.debug('Checking videoChannelsGet parameters', { parameters: req.params })
if (areValidationErrors(req, res)) return
+ // On some routes, accountId is optional (for example in the ActivityPub route)
+ if (req.params.accountId && !await isAccountIdExist(req.params.accountId, res)) return
if (!await isVideoChannelExist(req.params.id, res)) return
return next()
}
@Scopes({
- [ScopeNames.AVAILABLE_FOR_LIST]: (actorId: number, hideNSFW: boolean, filter?: VideoFilter, withFiles?: boolean, accountId?: number) => {
+ [ScopeNames.AVAILABLE_FOR_LIST]: (options: {
+ actorId: number,
+ hideNSFW: boolean,
+ filter?: VideoFilter,
+ withFiles?: boolean,
+ accountId?: number,
+ videoChannelId?: number
+ }) => {
const accountInclude = {
attributes: [ 'name' ],
model: AccountModel.unscoped(),
attributes: [ 'preferredUsername', 'url', 'serverId', 'avatarId' ],
model: ActorModel.unscoped(),
required: true,
- where: VideoModel.buildActorWhereWithFilter(filter),
+ where: VideoModel.buildActorWhereWithFilter(options.filter),
include: [
{
attributes: [ 'host' ],
]
}
+ const videoChannelInclude = {
+ attributes: [ 'name', 'description' ],
+ model: VideoChannelModel.unscoped(),
+ required: true,
+ where: {},
+ include: [
+ accountInclude
+ ]
+ }
+
+ // Force actorId to be a number to avoid SQL injections
+ const actorIdNumber = parseInt(options.actorId.toString(), 10)
const query: IFindOptions<VideoModel> = {
where: {
id: {
'(' +
'SELECT "videoShare"."videoId" AS "id" FROM "videoShare" ' +
'INNER JOIN "actorFollow" ON "actorFollow"."targetActorId" = "videoShare"."actorId" ' +
- 'WHERE "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) +
+ 'WHERE "actorFollow"."actorId" = ' + actorIdNumber +
' UNION ' +
'SELECT "video"."id" AS "id" FROM "video" ' +
'INNER JOIN "videoChannel" ON "videoChannel"."id" = "video"."channelId" ' +
'INNER JOIN "account" ON "account"."id" = "videoChannel"."accountId" ' +
'INNER JOIN "actor" ON "account"."actorId" = "actor"."id" ' +
'LEFT JOIN "actorFollow" ON "actorFollow"."targetActorId" = "actor"."id" ' +
- 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + parseInt(actorId.toString(), 10) +
+ 'WHERE "actor"."serverId" IS NULL OR "actorFollow"."actorId" = ' + actorIdNumber +
')'
)
},
privacy: VideoPrivacy.PUBLIC
},
- include: [
- {
- attributes: [ 'name', 'description' ],
- model: VideoChannelModel.unscoped(),
- required: true,
- include: [
- accountInclude
- ]
- }
- ]
+ include: [ videoChannelInclude ]
}
- if (withFiles === true) {
+ if (options.withFiles === true) {
query.include.push({
model: VideoFileModel.unscoped(),
required: true
}
// Hide nsfw videos?
- if (hideNSFW === true) {
+ if (options.hideNSFW === true) {
query.where['nsfw'] = false
}
- if (accountId) {
+ if (options.accountId) {
accountInclude.where = {
- id: accountId
+ id: options.accountId
+ }
+ }
+
+ if (options.videoChannelId) {
+ videoChannelInclude.where = {
+ id: options.videoChannelId
}
}
})
}
- static async listForApi (
+ static async listForApi (options: {
start: number,
count: number,
sort: string,
hideNSFW: boolean,
+ withFiles: boolean,
filter?: VideoFilter,
- withFiles = false,
- accountId?: number
- ) {
+ accountId?: number,
+ videoChannelId?: number
+ }) {
const query = {
- offset: start,
- limit: count,
- order: getSort(sort)
+ offset: options.start,
+ limit: options.count,
+ order: getSort(options.sort)
}
const serverActor = await getServerActor()
- return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW, filter, withFiles, accountId ] })
+ const scopes = {
+ method: [
+ ScopeNames.AVAILABLE_FOR_LIST, {
+ actorId: serverActor.id,
+ hideNSFW: options.hideNSFW,
+ filter: options.filter,
+ withFiles: options.withFiles,
+ accountId: options.accountId,
+ videoChannelId: options.videoChannelId
+ }
+ ]
+ }
+
+ return VideoModel.scope(scopes)
.findAndCountAll(query)
.then(({ rows, count }) => {
return {
}
const serverActor = await getServerActor()
+ const scopes = {
+ method: [
+ ScopeNames.AVAILABLE_FOR_LIST, {
+ actorId: serverActor.id,
+ hideNSFW
+ }
+ ]
+ }
- return VideoModel.scope({ method: [ ScopeNames.AVAILABLE_FOR_LIST, serverActor.id, hideNSFW ] })
+ return VideoModel.scope(scopes)
.findAndCountAll(query)
.then(({ rows, count }) => {
return {
import { omit } from 'lodash'
import 'mocha'
import {
- createUser, deleteVideoChannel, flushTests, getAccountVideoChannelsList, getVideoChannelsList, immutableAssign, killallServers,
- makeGetRequest, makePostBodyRequest, makePutBodyRequest, runServer, ServerInfo, setAccessTokensToServers, userLogin
+ createUser,
+ deleteVideoChannel,
+ flushTests,
+ getAccountVideoChannelsList,
+ getVideoChannelsList,
+ immutableAssign,
+ killallServers,
+ makeGetRequest,
+ makePostBodyRequest,
+ makePutBodyRequest,
+ runServer,
+ ServerInfo,
+ setAccessTokensToServers,
+ userLogin
} from '../../utils'
import { checkBadCountPagination, checkBadSortPagination, checkBadStartPagination } from '../../utils/requests/check-api-params'
+import { getAccountsList } from '../../utils/users/accounts'
const expect = chai.expect
describe('Test videos API validator', function () {
- const path = '/api/v1/videos/channels'
+ const videoChannelPath = '/api/v1/video-channels'
+ const accountPath = '/api/v1/accounts/'
let server: ServerInfo
let accessTokenUser: string
describe('When listing a video channels', function () {
it('Should fail with a bad start pagination', async function () {
- await checkBadStartPagination(server.url, path, server.accessToken)
+ await checkBadStartPagination(server.url, videoChannelPath, server.accessToken)
})
it('Should fail with a bad count pagination', async function () {
- await checkBadCountPagination(server.url, path, server.accessToken)
+ await checkBadCountPagination(server.url, videoChannelPath, server.accessToken)
})
it('Should fail with an incorrect sort', async function () {
- await checkBadSortPagination(server.url, path, server.accessToken)
+ await checkBadSortPagination(server.url, videoChannelPath, server.accessToken)
})
})
})
describe('When adding a video channel', function () {
+ let path: string
+
const baseCorrectParams = {
name: 'hello',
description: 'super description',
support: 'super support text'
}
+ before(async function () {
+ const res = await getAccountsList(server.url)
+ const accountId = res.body.data[0].id
+ path = accountPath + accountId + '/video-channels'
+ })
+
it('Should fail with a non authenticated user', async function () {
await makePostBodyRequest({ url: server.url, path, token: 'none', fields: baseCorrectParams, statusCodeExpected: 401 })
})
})
describe('When updating a video channel', function () {
+ let path: string
+
const baseCorrectParams = {
name: 'hello',
description: 'super description'
}
- let videoChannelId
-
before(async function () {
- const res = await getVideoChannelsList(server.url, 0, 1)
- videoChannelId = res.body.data[0].id
+ const res1 = await getVideoChannelsList(server.url, 0, 1)
+ const videoChannelId = res1.body.data[0].id
+
+ const res2 = await getAccountsList(server.url)
+ const accountId = res2.body.data[0].id
+
+ path = accountPath + accountId + '/video-channels/' + videoChannelId
})
it('Should fail with a non authenticated user', async function () {
await makePutBodyRequest({
url: server.url,
- path: path + '/' + videoChannelId,
+ path,
token: 'hi',
fields: baseCorrectParams,
statusCodeExpected: 401
it('Should fail with another authenticated user', async function () {
await makePutBodyRequest({
url: server.url,
- path: path + '/' + videoChannelId,
+ path,
token: accessTokenUser,
fields: baseCorrectParams,
statusCodeExpected: 403
it('Should fail with a long name', async function () {
const fields = immutableAssign(baseCorrectParams, { name: 'super'.repeat(25) })
- await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
+ await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long description', async function () {
const fields = immutableAssign(baseCorrectParams, { description: 'super'.repeat(60) })
- await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
+ await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should fail with a long support text', async function () {
const fields = immutableAssign(baseCorrectParams, { support: 'super'.repeat(70) })
- await makePutBodyRequest({ url: server.url, path: path + '/' + videoChannelId, token: server.accessToken, fields })
+ await makePutBodyRequest({ url: server.url, path, token: server.accessToken, fields })
})
it('Should succeed with the correct parameters', async function () {
await makePutBodyRequest({
url: server.url,
- path: path + '/' + videoChannelId,
+ path,
token: server.accessToken,
fields: baseCorrectParams,
statusCodeExpected: 204
})
describe('When getting a video channel', function () {
+ let basePath: string
let videoChannelId: number
before(async function () {
- const res = await getVideoChannelsList(server.url, 0, 1)
- videoChannelId = res.body.data[0].id
+ const res1 = await getVideoChannelsList(server.url, 0, 1)
+ videoChannelId = res1.body.data[0].id
+
+ const res2 = await getAccountsList(server.url)
+ const accountId = res2.body.data[0].id
+
+ basePath = accountPath + accountId + '/video-channels'
})
it('Should return the list of the video channels with nothing', async function () {
const res = await makeGetRequest({
url: server.url,
- path,
+ path: basePath,
statusCodeExpected: 200
})
it('Should fail without a correct uuid', async function () {
await makeGetRequest({
url: server.url,
- path: path + '/coucou',
+ path: basePath + '/coucou',
statusCodeExpected: 400
})
})
it('Should return 404 with an incorrect video channel', async function () {
await makeGetRequest({
url: server.url,
- path: path + '/4da6fde3-88f7-4d16-b119-108df5630b06',
+ path: basePath + '/4da6fde3-88f7-4d16-b119-108df5630b06',
statusCodeExpected: 404
})
})
it('Should succeed with the correct parameters', async function () {
await makeGetRequest({
url: server.url,
- path: path + '/' + videoChannelId,
+ path: basePath + '/' + videoChannelId,
statusCodeExpected: 200
})
})
describe('When deleting a video channel', function () {
let videoChannelId: number
+ let accountId: number
before(async function () {
- const res = await getVideoChannelsList(server.url, 0, 1)
- videoChannelId = res.body.data[0].id
+ const res1 = await getVideoChannelsList(server.url, 0, 1)
+ videoChannelId = res1.body.data[0].id
+
+ const res2 = await getAccountsList(server.url)
+ accountId = res2.body.data[0].id
})
it('Should fail with a non authenticated user', async function () {
- await deleteVideoChannel(server.url, 'coucou', videoChannelId, 401)
+ await deleteVideoChannel(server.url, 'coucou', accountId, videoChannelId, 401)
})
it('Should fail with another authenticated user', async function () {
- await deleteVideoChannel(server.url, accessTokenUser, videoChannelId, 403)
+ await deleteVideoChannel(server.url, accessTokenUser, accountId, videoChannelId, 403)
+ })
+
+ it('Should fail with an unknown account id', async function () {
+ await deleteVideoChannel(server.url, server.accessToken, 454554,videoChannelId, 404)
})
- it('Should fail with an unknown id', async function () {
- await deleteVideoChannel(server.url, server.accessToken, 454554, 404)
+ it('Should fail with an unknown video channel id', async function () {
+ await deleteVideoChannel(server.url, server.accessToken, accountId,454554, 404)
})
it('Should succeed with the correct parameters', async function () {
- await deleteVideoChannel(server.url, server.accessToken, videoChannelId)
+ await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId)
})
it('Should fail to delete the last user video channel', async function () {
const res = await getVideoChannelsList(server.url, 0, 1)
videoChannelId = res.body.data[0].id
- await deleteVideoChannel(server.url, server.accessToken, videoChannelId, 409)
+ await deleteVideoChannel(server.url, server.accessToken, accountId, videoChannelId, 409)
})
})
getVideoCommentThreads,
getVideoThreadComments
} from '../../utils/videos/video-comments'
+import { getAccountsList } from '../../utils/users/accounts'
const expect = chai.expect
let servers: ServerInfo[] = []
const toRemove = []
let videoUUID = ''
+ let accountId: number
let videoChannelId: number
before(async function () {
// Get the access tokens
await setAccessTokensToServers(servers)
- const videoChannel = {
- name: 'my channel',
- description: 'super channel'
+ {
+ const res = await getAccountsList(servers[0].url)
+ accountId = res.body.data[0].id
+ }
+
+ {
+ const videoChannel = {
+ name: 'my channel',
+ description: 'super channel'
+ }
+ await addVideoChannel(servers[ 0 ].url, servers[ 0 ].accessToken, accountId, videoChannel)
+ const channelRes = await getVideoChannelsList(servers[ 0 ].url, 0, 1)
+ videoChannelId = channelRes.body.data[ 0 ].id
}
- await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
- const channelRes = await getVideoChannelsList(servers[0].url, 0, 1)
- videoChannelId = channelRes.body.data[0].id
// Server 1 and server 2 follow each other
await doubleFollow(servers[0], servers[1])
setAccessTokensToServers,
updateVideoChannel
} from '../../utils/index'
+import { getAccountsList } from '../../utils/users/accounts'
const expect = chai.expect
describe('Test video channels', function () {
let servers: ServerInfo[]
let userInfo: User
+ let accountId: number
let videoChannelId: number
before(async function () {
await setAccessTokensToServers(servers)
await doubleFollow(servers[0], servers[1])
+ {
+ const res = await getAccountsList(servers[0].url)
+ accountId = res.body.data[0].id
+ }
+
await wait(5000)
})
description: 'super video channel description',
support: 'super video channel support text'
}
- const res = await addVideoChannel(servers[0].url, servers[0].accessToken, videoChannel)
+ const res = await addVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannel)
videoChannelId = res.body.videoChannel.id
// The channel is 1 is propagated to servers 2
support: 'video channel support text updated'
}
- await updateVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId, videoChannelAttributes)
+ await updateVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId, videoChannelAttributes)
await wait(3000)
})
})
it('Should get video channel', async function () {
- const res = await getVideoChannel(servers[0].url, videoChannelId)
+ const res = await getVideoChannel(servers[0].url, accountId, videoChannelId)
const videoChannel = res.body
expect(videoChannel.displayName).to.equal('video channel updated')
})
it('Should delete video channel', async function () {
- await deleteVideoChannel(servers[0].url, servers[0].accessToken, videoChannelId)
+ await deleteVideoChannel(servers[0].url, servers[0].accessToken, accountId, videoChannelId)
})
it('Should have video channel deleted', async function () {
}
function getVideoChannelsList (url: string, start: number, count: number, sort?: string) {
- const path = '/api/v1/videos/channels'
+ const path = '/api/v1/video-channels'
const req = request(url)
.get(path)
}
function getAccountVideoChannelsList (url: string, accountId: number | string, specialStatus = 200) {
- const path = '/api/v1/videos/accounts/' + accountId + '/channels'
+ const path = '/api/v1/accounts/' + accountId + '/video-channels'
return request(url)
.get(path)
.expect('Content-Type', /json/)
}
-function addVideoChannel (url: string, token: string, videoChannelAttributesArg: VideoChannelAttributes, expectedStatus = 200) {
- const path = '/api/v1/videos/channels'
+function addVideoChannel (
+ url: string,
+ token: string,
+ accountId: number,
+ videoChannelAttributesArg: VideoChannelAttributes,
+ expectedStatus = 200
+) {
+ const path = '/api/v1/accounts/' + accountId + '/video-channels/'
// Default attributes
let attributes = {
.expect(expectedStatus)
}
-function updateVideoChannel (url: string, token: string, channelId: number, attributes: VideoChannelAttributes, expectedStatus = 204) {
+function updateVideoChannel (
+ url: string,
+ token: string,
+ accountId: number,
+ channelId: number,
+ attributes: VideoChannelAttributes,
+ expectedStatus = 204
+) {
const body = {}
- const path = '/api/v1/videos/channels/' + channelId
+ const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
if (attributes.name) body['name'] = attributes.name
if (attributes.description) body['description'] = attributes.description
.expect(expectedStatus)
}
-function deleteVideoChannel (url: string, token: string, channelId: number, expectedStatus = 204) {
- const path = '/api/v1/videos/channels/'
+function deleteVideoChannel (url: string, token: string, accountId: number, channelId: number, expectedStatus = 204) {
+ const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
return request(url)
- .delete(path + channelId)
+ .delete(path)
.set('Accept', 'application/json')
.set('Authorization', 'Bearer ' + token)
.expect(expectedStatus)
}
-function getVideoChannel (url: string, channelId: number) {
- const path = '/api/v1/videos/channels/' + channelId
+function getVideoChannel (url: string, accountId: number, channelId: number) {
+ const path = '/api/v1/accounts/' + accountId + '/video-channels/' + channelId
return request(url)
.get(path)
</li>
</ul>
</section>
+ <section>
+ <a href="#tag-Feeds">Feeds</a>
+ <ul>
+ <li>
+ <a href="#operation--feeds-videos.-format--get"> GET /feeds/videos.{format} </a>
+ </li>
+ </ul>
+ </section>
<section>
<a href="#tag-Job">Job</a>
<ul>
<a href="#tag-VideoChannel">VideoChannel</a>
<ul>
<li>
- <a href="#operation--videos-channels-get"> GET /videos/channels </a>
+ <a href="#operation--video-channels-get"> GET /video-channels </a>
</li>
<li>
- <a href="#operation--videos-channels-post"> POST /videos/channels </a>
+ <a href="#operation--accounts--accountId--video-channels-get"> GET /accounts/{accountId}/video-channels </a>
</li>
<li>
- <a href="#operation--videos-channels--id--get"> GET /videos/channels/{id} </a>
+ <a href="#operation--accounts--accountId--video-channels-post"> POST /accounts/{accountId}/video-channels </a>
</li>
<li>
- <a href="#operation--videos-channels--id--put"> PUT /videos/channels/{id} </a>
+ <a href="#operation--account--accountId--video-channels--id--get"> GET /account/{accountId}/video-channels/{id} </a>
</li>
<li>
- <a href="#operation--videos-channels--id--delete"> DELETE /videos/channels/{id} </a>
+ <a href="#operation--account--accountId--video-channels--id--put"> PUT /account/{accountId}/video-channels/{id} </a>
</li>
<li>
- <a href="#operation--videos-accounts--accountId--channels-get"> GET /videos/accounts/{accountId}/channels </a>
+ <a href="#operation--account--accountId--video-channels--id--delete"> DELETE /account/{accountId}/video-channels/{id} </a>
</li>
</ul>
</section>
</ul>
</section>
<h5>Schema Definitions</h5>
- <a href="#definition-VideoConstant"> VideoConstant </a>
+ <a href="#definition-VideoConstantNumber"> VideoConstantNumber </a>
+ <a href="#definition-VideoConstantString"> VideoConstantString </a>
<a href="#definition-VideoPrivacy"> VideoPrivacy </a>
<a href="#definition-Video"> Video </a>
<a href="#definition-VideoAbuse"> VideoAbuse </a>
</div>
</div>
</div>
+ <h1 id="tag-Feeds" class="swagger-summary-tag" data-traverse-target="tag-Feeds">Feeds</h1>
+ <div id="operation--feeds-videos.-format--get" class="operation panel" data-traverse-target="operation--feeds-videos.-format--get">
+ <!-- <section class="operation-tags row"> -->
+ <!-- <div class="doc-copy"> -->
+ <div class="operation-tags">
+ <a class="label" href="#tag-Feeds">Feeds</a>
+ <!---->
+ </div>
+ <!-- </div> -->
+ <!-- </section> -->
+ <h2 class="operation-title">
+ <span class="operation-name">
+ <span class="operation-name">GET</span>
+ <span class="operation-path">/feeds/videos.{format}</span>
+ </span>
+ </h2>
+ <div class="doc-row">
+ <div class="doc-copy">
+ <section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">format</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-enum" title="Possible values">
+ <span class="json-property-enum-item json-property-enum-default-value">xml</span>,
+ <span class="json-property-enum-item">atom</span>,
+ <span class="json-property-enum-item">json</span>
+ </span>
+ <span class="json-property-range" title="Value limits"></span>
+ <span class="json-property-default-value" title="Default value">xml</span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0</p>
+ </div>
+ </div>
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <div class="prop-subtitle"> in query </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">number</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The id of the local account to filter to (beware, users IDs and not actors IDs which will return empty feeds</p>
+ </div>
+ </div>
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountName</div>
+ <div class="prop-subtitle"> in query </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The name of the local account to filter to</p>
+ </div>
+ </div>
+ </section>
+ </div>
+ <div class="doc-examples"></div>
+ </div>
+ <div class="doc-row">
+ <div class="doc-copy">
+ <section class="swagger-responses">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">200 OK</div>
+ </div>
+ <div class="prop-value">
+ <p>successful operation</p>
+ </div>
+ </div>
+ </section>
+ </div>
+ <div class="doc-examples">
+ <h5>Response Content-Types:
+ <span>application/atom+xml, application/rss+xml, application/json</span>
+ </h5>
+ </div>
+ </div>
+ </div>
<h1 id="tag-Job" class="swagger-summary-tag" data-traverse-target="tag-Job">Job</h1>
<div id="operation--jobs-get" class="operation panel" data-traverse-target="operation--jobs-get">
<!-- <section class="operation-tags row"> -->
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<div class="prop-title">language</div>
<div class="prop-subtitle"> in formData </div>
<div class="prop-subtitle">
- <span class="json-property-type">number</span>
+ <span class="json-property-type">string</span>
<span class="json-property-range" title="Value limits"></span>
</div>
</div>
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<div class="prop-title">language</div>
<div class="prop-subtitle"> in formData </div>
<div class="prop-subtitle">
- <span class="json-property-type">number</span>
+ <span class="json-property-type">string</span>
<span class="json-property-range" title="Value limits"></span>
</div>
</div>
</div>
</div>
<h1 id="tag-VideoChannel" class="swagger-summary-tag" data-traverse-target="tag-VideoChannel">VideoChannel</h1>
- <div id="operation--videos-channels-get" class="operation panel" data-traverse-target="operation--videos-channels-get">
+ <div id="operation--video-channels-get" class="operation panel" data-traverse-target="operation--video-channels-get">
<!-- <section class="operation-tags row"> -->
<!-- <div class="doc-copy"> -->
<div class="operation-tags">
<h2 class="operation-title">
<span class="operation-name">
<span class="operation-name">GET</span>
- <span class="operation-path">/videos/channels</span>
+ <span class="operation-path">/video-channels</span>
</span>
</h2>
<div class="doc-row">
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
+ },
+ <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>,
+ <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"thumbnailPath"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"previewPath"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"embedPath"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"views"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"likes"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"dislikes"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"nsfw"</span>: <span class="hljs-string">"boolean"</span>,
+ <span class="hljs-attr">"account"</span>: {
+ <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"url"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"host"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"avatar"</span>: {
+ <span class="hljs-attr">"path"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>
+ }
+ }
+ }
+ ]
+ }
+]
+</code></pre>
+ <!-- </div> -->
+ </section>
+ </div>
+ </div>
+ </div>
+ <div id="operation--accounts--accountId--video-channels-get" class="operation panel" data-traverse-target="operation--accounts--accountId--video-channels-get">
+ <!-- <section class="operation-tags row"> -->
+ <!-- <div class="doc-copy"> -->
+ <div class="operation-tags">
+ <a class="label" href="#tag-VideoChannel">VideoChannel</a>
+ <!---->
+ </div>
+ <!-- </div> -->
+ <!-- </section> -->
+ <h2 class="operation-title">
+ <span class="operation-name">
+ <span class="operation-name">GET</span>
+ <span class="operation-path">/accounts/{accountId}/video-channels</span>
+ </span>
+ </h2>
+ <div class="doc-row">
+ <div class="doc-copy">
+ <section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The account id </p>
+ </div>
+ </div>
+ </section>
+ </div>
+ <div class="doc-examples"></div>
+ </div>
+ <div class="doc-row">
+ <div class="doc-copy">
+ <section class="swagger-responses">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">200 OK</div>
+ <div class="prop-ref">
+ <span class="json-schema-ref-array">
+ <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a>
+ </span>
+ </div>
+ <!-- <span class="swagger-global"></span> <span class="json-schema-reference"><a href=""></a></span> -->
+ </div>
+ <div class="prop-value">
+ <p>successful operation</p>
+ </div>
+ </div>
+ <div class="prop-row prop-inner">
+ <div class="prop-name">type</div>
+ <div class="prop-value">
+ <span class="json-property-type">
+ <span class="json-schema-ref-array">
+ <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a>
+ </span>
+ </span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ </section>
+ </div>
+ <div class="doc-examples">
+ <h5>Response Content-Types:
+ <span>application/json</span>
+ </h5>
+ <section>
+ <h5>Response Example
+ <span>(200 OK)</span>
+ </h5>
+ <!-- <div class="hljs"> --><pre><code class="hljs lang-json">[
+ {
+ <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>,
+ <span class="hljs-attr">"owner"</span>: {
+ <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>
+ },
+ <span class="hljs-attr">"videos"</span>: [
+ {
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"publishedAt"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"category"</span>: {
<span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
+ <span class="hljs-attr">"licence"</span>: {
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
+ },
+ <span class="hljs-attr">"language"</span>: {
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
+ },
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>,
</div>
</div>
</div>
- <div id="operation--videos-channels-post" class="operation panel" data-traverse-target="operation--videos-channels-post">
+ <div id="operation--accounts--accountId--video-channels-post" class="operation panel" data-traverse-target="operation--accounts--accountId--video-channels-post">
<!-- <section class="operation-tags row"> -->
<!-- <div class="doc-copy"> -->
<div class="operation-tags">
<h2 class="operation-title">
<span class="operation-name">
<span class="operation-name">POST</span>
- <span class="operation-path">/videos/channels</span>
+ <span class="operation-path">/accounts/{accountId}/video-channels</span>
</span>
</h2>
<div class="doc-row">
</div>
</div>
</section>
+ <section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The account id </p>
+ </div>
+ </div>
+ </section>
</div>
<div class="doc-examples">
<section>
</div>
</div>
</div>
- <div id="operation--videos-channels--id--get" class="operation panel" data-traverse-target="operation--videos-channels--id--get">
+ <div id="operation--account--accountId--video-channels--id--get" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--get">
<!-- <section class="operation-tags row"> -->
<!-- <div class="doc-copy"> -->
<div class="operation-tags">
<h2 class="operation-title">
<span class="operation-name">
<span class="operation-name">GET</span>
- <span class="operation-path">/videos/channels/{id}</span>
+ <span class="operation-path">/account/{accountId}/video-channels/{id}</span>
</span>
</h2>
<div class="doc-row">
<div class="doc-copy">
<section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The account id </p>
+ </div>
+ </div>
<div class="prop-row prop-group">
<div class="prop-name">
<div class="prop-title">id</div>
</div>
</div>
<div class="prop-value">
- <p>The video id </p>
+ <p>The video channel id </p>
</div>
</div>
</section>
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
</div>
</div>
</div>
- <div id="operation--videos-channels--id--put" class="operation panel" data-traverse-target="operation--videos-channels--id--put">
+ <div id="operation--account--accountId--video-channels--id--put" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--put">
<!-- <section class="operation-tags row"> -->
<!-- <div class="doc-copy"> -->
<div class="operation-tags">
<h2 class="operation-title">
<span class="operation-name">
<span class="operation-name">PUT</span>
- <span class="operation-path">/videos/channels/{id}</span>
+ <span class="operation-path">/account/{accountId}/video-channels/{id}</span>
</span>
</h2>
<div class="doc-row">
</div>
</section>
<section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The account id </p>
+ </div>
+ </div>
<div class="prop-row prop-group">
<div class="prop-name">
<div class="prop-title">id</div>
</div>
</div>
<div class="prop-value">
- <p>The video id </p>
+ <p>The video channel id </p>
</div>
</div>
</section>
</div>
</div>
</div>
- <div id="operation--videos-channels--id--delete" class="operation panel" data-traverse-target="operation--videos-channels--id--delete">
+ <div id="operation--account--accountId--video-channels--id--delete" class="operation panel" data-traverse-target="operation--account--accountId--video-channels--id--delete">
<!-- <section class="operation-tags row"> -->
<!-- <div class="doc-copy"> -->
<div class="operation-tags">
<h2 class="operation-title">
<span class="operation-name">
<span class="operation-name">DELETE</span>
- <span class="operation-path">/videos/channels/{id}</span>
+ <span class="operation-path">/account/{accountId}/video-channels/{id}</span>
</span>
</h2>
<div class="doc-row">
<div class="doc-copy">
<section class="swagger-request-params">
+ <div class="prop-row prop-group">
+ <div class="prop-name">
+ <div class="prop-title">accountId</div>
+ <span class="json-property-required"></span>
+ <div class="prop-subtitle"> in path </div>
+ <div class="prop-subtitle">
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </div>
+ </div>
+ <div class="prop-value">
+ <p>The account id </p>
+ </div>
+ </div>
<div class="prop-row prop-group">
<div class="prop-name">
<div class="prop-title">id</div>
</div>
</div>
<div class="prop-value">
- <p>The video id </p>
+ <p>The video channel id </p>
</div>
</div>
</section>
</div>
</div>
</div>
- <div id="operation--videos-accounts--accountId--channels-get" class="operation panel" data-traverse-target="operation--videos-accounts--accountId--channels-get">
- <!-- <section class="operation-tags row"> -->
- <!-- <div class="doc-copy"> -->
- <div class="operation-tags">
- <a class="label" href="#tag-VideoChannel">VideoChannel</a>
- <!---->
- </div>
- <!-- </div> -->
- <!-- </section> -->
- <h2 class="operation-title">
- <span class="operation-name">
- <span class="operation-name">GET</span>
- <span class="operation-path">/videos/accounts/{accountId}/channels</span>
- </span>
- </h2>
- <div class="doc-row">
- <div class="doc-copy">
- <section class="swagger-request-params">
- <div class="prop-row prop-group">
- <div class="prop-name">
- <div class="prop-title">accountId</div>
- <span class="json-property-required"></span>
- <div class="prop-subtitle"> in path </div>
- <div class="prop-subtitle">
- <span class="json-property-type">string</span>
- <span class="json-property-range" title="Value limits"></span>
- </div>
- </div>
- <div class="prop-value">
- <p>The account id </p>
- </div>
- </div>
- </section>
- </div>
- <div class="doc-examples"></div>
- </div>
- <div class="doc-row">
- <div class="doc-copy">
- <section class="swagger-responses">
- <div class="prop-row prop-group">
- <div class="prop-name">
- <div class="prop-title">200 OK</div>
- <div class="prop-ref">
- <span class="json-schema-ref-array">
- <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a>
- </span>
- </div>
- <!-- <span class="swagger-global"></span> <span class="json-schema-reference"><a href=""></a></span> -->
- </div>
- <div class="prop-value">
- <p>successful operation</p>
- </div>
- </div>
- <div class="prop-row prop-inner">
- <div class="prop-name">type</div>
- <div class="prop-value">
- <span class="json-property-type">
- <span class="json-schema-ref-array">
- <a class="json-schema-ref" href="#/definitions/VideoChannel">VideoChannel</a>
- </span>
- </span>
- <span class="json-property-range" title="Value limits"></span>
- </div>
- </div>
- </section>
- </div>
- <div class="doc-examples">
- <h5>Response Content-Types:
- <span>application/json</span>
- </h5>
- <section>
- <h5>Response Example
- <span>(200 OK)</span>
- </h5>
- <!-- <div class="hljs"> --><pre><code class="hljs lang-json">[
- {
- <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>,
- <span class="hljs-attr">"owner"</span>: {
- <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>
- },
- <span class="hljs-attr">"videos"</span>: [
- {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"uuid"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"publishedAt"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"category"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
- },
- <span class="hljs-attr">"licence"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
- },
- <span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
- },
- <span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"description"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"duration"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"isLocal"</span>: <span class="hljs-string">"boolean"</span>,
- <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"thumbnailPath"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"previewPath"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"embedPath"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"views"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"likes"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"dislikes"</span>: <span class="hljs-string">"number"</span>,
- <span class="hljs-attr">"nsfw"</span>: <span class="hljs-string">"boolean"</span>,
- <span class="hljs-attr">"account"</span>: {
- <span class="hljs-attr">"name"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"displayName"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"url"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"host"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"avatar"</span>: {
- <span class="hljs-attr">"path"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"createdAt"</span>: <span class="hljs-string">"string"</span>,
- <span class="hljs-attr">"updatedAt"</span>: <span class="hljs-string">"string"</span>
- }
- }
- }
- ]
- }
-]
-</code></pre>
- <!-- </div> -->
- </section>
- </div>
- </div>
- </div>
<h1 id="tag-VideoComment" class="swagger-summary-tag" data-traverse-target="tag-VideoComment">VideoComment</h1>
<div id="operation--videos--videoId--comment-threads-get" class="operation panel" data-traverse-target="operation--videos--videoId--comment-threads-get">
<!-- <section class="operation-tags row"> -->
</div>
</div>
<h1>Schema Definitions</h1>
- <div id="definition-VideoConstant" class="definition panel" data-traverse-target="definition-VideoConstant">
+ <div id="definition-VideoConstantNumber" class="definition panel" data-traverse-target="definition-VideoConstantNumber">
<h2 class="panel-title">
- <a name="/definitions/VideoConstant"></a>VideoConstant:
+ <a name="/definitions/VideoConstantNumber"></a>VideoConstantNumber:
<!-- <span class="json-property-type"><span class="json-property-type">object</span>
<span class="json-property-range" title="Value limits"></span>
<span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
}
+</code></pre>
+ <!-- </div> -->
+ </section>
+ </div>
+ </div>
+ </div>
+ <div id="definition-VideoConstantString" class="definition panel" data-traverse-target="definition-VideoConstantString">
+ <h2 class="panel-title">
+ <a name="/definitions/VideoConstantString"></a>VideoConstantString:
+ <!-- <span class="json-property-type"><span class="json-property-type">object</span>
+ <span class="json-property-range" title="Value limits"></span>
+
+
+ </span> -->
+ </h2>
+ <div class="doc-row">
+ <div class="doc-copy">
+ <section class="json-schema-properties">
+ <dl>
+ <dt data-property-name="id">
+ <span class="json-property-name">id:</span>
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </dt>
+ <dt data-property-name="label">
+ <span class="json-property-name">label:</span>
+ <span class="json-property-type">string</span>
+ <span class="json-property-range" title="Value limits"></span>
+ </dt>
+ </dl>
+ </section>
+ </div>
+ <div class="doc-examples">
+ <section>
+ <h5>Example</h5>
+ <!-- <div class="hljs"> --><pre><code class="hljs lang-json">{
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
+ <span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
+}
</code></pre>
<!-- </div> -->
</section>
<span class="json-property-name">category:</span>
<span class="json-property-type">
<span class="">
- <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a>
+ <a class="json-schema-ref" href="#/definitions/VideoConstantNumber">VideoConstantNumber</a>
</span>
</span>
<span class="json-property-range" title="Value limits"></span>
<span class="json-property-name">licence:</span>
<span class="json-property-type">
<span class="">
- <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a>
+ <a class="json-schema-ref" href="#/definitions/VideoConstantNumber">VideoConstantNumber</a>
</span>
</span>
<span class="json-property-range" title="Value limits"></span>
<span class="json-property-name">language:</span>
<span class="json-property-type">
<span class="">
- <a class="json-schema-ref" href="#/definitions/VideoConstant">VideoConstant</a>
+ <a class="json-schema-ref" href="#/definitions/VideoConstantString">VideoConstantString</a>
</span>
</span>
<span class="json-property-range" title="Value limits"></span>
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"language"</span>: {
- <span class="hljs-attr">"id"</span>: <span class="hljs-string">"number"</span>,
+ <span class="hljs-attr">"id"</span>: <span class="hljs-string">"string"</span>,
<span class="hljs-attr">"label"</span>: <span class="hljs-string">"string"</span>
},
<span class="hljs-attr">"privacy"</span>: <span class="hljs-string">"string"</span>,
in: path
required: true
type: string
- enum: ['xml', 'atom' 'json']
+ enum: [ 'xml', 'atom', 'json']
default: 'xml'
description: 'The format expected (xml defaults to RSS 2.0, atom to ATOM 1.0 and json to JSON FEED 1.0'
- name: accountId
type: array
items:
$ref: '#/definitions/VideoBlacklist'
- /videos/channels:
+ /video-channels:
get:
tags:
- VideoChannel
type: array
items:
$ref: '#/definitions/VideoChannel'
+ /accounts/{accountId}/video-channels:
+ get:
+ tags:
+ - VideoChannel
+ consumes:
+ - application/json
+ produces:
+ - application/json
+ parameters:
+ - name: accountId
+ in: path
+ required: true
+ type: string
+ description: 'The account id '
+ responses:
+ '200':
+ description: successful operation
+ schema:
+ type: array
+ items:
+ $ref: '#/definitions/VideoChannel'
post:
security:
- OAuth2: [ ]
produces:
- application/json
parameters:
+ - name: accountId
+ in: path
+ required: true
+ type: string
+ description: 'The account id '
- in: body
name: body
schema:
responses:
'204':
description: successful operation
- "/videos/channels/{id}":
+ "/account/{accountId}/video-channels/{id}":
get:
tags:
- VideoChannel
produces:
- application/json
parameters:
+ - name: accountId
+ in: path
+ required: true
+ type: string
+ description: 'The account id '
- name: id
in: path
required: true
type: string
- description: 'The video id '
+ description: 'The video channel id '
responses:
'200':
description: successful operation
produces:
- application/json
parameters:
+ - name: accountId
+ in: path
+ required: true
+ type: string
+ description: 'The account id '
- name: id
in: path
required: true
type: string
- description: 'The video id '
+ description: 'The video channel id '
- in: body
name: body
schema:
produces:
- application/json
parameters:
- - name: id
+ - name: accountId
in: path
required: true
type: string
- description: 'The video id '
- responses:
- '204':
- description: successful operation
- /videos/accounts/{accountId}/channels:
- get:
- tags:
- - VideoChannel
- consumes:
- - application/json
- produces:
- - application/json
- parameters:
- - name: accountId
+ description: 'The account id '
+ - name: id
in: path
required: true
type: string
- description: 'The account id '
+ description: 'The video channel id '
responses:
- '200':
+ '204':
description: successful operation
- schema:
- type: array
- items:
- $ref: '#/definitions/VideoChannel'
"/videos/{videoId}/comment-threads":
get:
tags: