nsfw: video.nsfw,
waitTranscoding: video.waitTranscoding,
commentsEnabled: video.commentsEnabled,
+ downloadingEnabled: video.downloadingEnabled,
thumbnailfile: video.thumbnailfile,
previewfile: video.previewfile,
scheduleUpdate
files: VideoFile[]
account: Account
commentsEnabled: boolean
+ downloadingEnabled: boolean
waitTranscoding: boolean
state: VideoConstant<VideoState>
this.tags = hash.tags
this.support = hash.support
this.commentsEnabled = hash.commentsEnabled
+ this.downloadingEnabled = hash.downloadingEnabled
this.buildLikeAndDislikePercents()
}
tags: string[]
nsfw: boolean
commentsEnabled: boolean
+ downloadingEnabled: boolean
waitTranscoding: boolean
channelId: number
privacy: VideoPrivacy
id?: number
scheduleUpdate?: VideoScheduleUpdate
- constructor (video?: Video & { tags: string[], commentsEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) {
+ constructor (video?: Video & { tags: string[], commentsEnabled: boolean, downloadingEnabled: boolean, support: string, thumbnailUrl: string, previewUrl: string }) {
if (video) {
this.id = video.id
this.uuid = video.uuid
this.tags = video.tags
this.nsfw = video.nsfw
this.commentsEnabled = video.commentsEnabled
+ this.downloadingEnabled = video.downloadingEnabled
this.waitTranscoding = video.waitTranscoding
this.channelId = video.channel.id
this.privacy = video.privacy.id
tags: this.tags,
nsfw: this.nsfw,
commentsEnabled: this.commentsEnabled,
+ downloadingEnabled: this.downloadingEnabled,
waitTranscoding: this.waitTranscoding,
channelId: this.channelId,
privacy: this.privacy
nsfw: video.nsfw,
waitTranscoding: video.waitTranscoding,
commentsEnabled: video.commentsEnabled,
+ downloadingEnabled: video.downloadingEnabled,
thumbnailfile: video.thumbnailfile,
previewfile: video.previewfile,
scheduleUpdate
privacy: this.firstStepPrivacyId,
waitTranscoding: false,
commentsEnabled: true,
+ downloadingEnabled: true,
channelId: this.firstStepChannelId
}
this.video = new VideoEdit(Object.assign(res.video, {
commentsEnabled: videoUpdate.commentsEnabled,
+ downloadingEnabled: videoUpdate.downloadingEnabled,
support: null,
thumbnailUrl: null,
previewUrl: null
privacy: this.firstStepPrivacyId,
waitTranscoding: false,
commentsEnabled: true,
+ downloadingEnabled: true,
channelId: this.firstStepChannelId
}
this.video = new VideoEdit(Object.assign(res.video, {
commentsEnabled: videoUpdate.commentsEnabled,
+ downloadingEnabled: videoUpdate.downloadingEnabled,
support: null,
thumbnailUrl: null,
previewUrl: null
const nsfw = false
const waitTranscoding = true
const commentsEnabled = true
+ const downloadingEnabled = true
const channelId = this.firstStepChannelId.toString()
const formData = new FormData()
formData.append('privacy', VideoPrivacy.PRIVATE.toString())
formData.append('nsfw', '' + nsfw)
formData.append('commentsEnabled', '' + commentsEnabled)
+ formData.append('downloadingEnabled', '' + downloadingEnabled)
formData.append('waitTranscoding', '' + waitTranscoding)
formData.append('channelId', '' + channelId)
formData.append('videofile', videofile)
</div>
<div ngbDropdownMenu>
- <a class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
+ <a *ngIf="isVideoDownloadable()" class="dropdown-item" i18n-title title="Download the video" href="#" (click)="showDownloadModal($event)">
<span class="icon icon-download"></span> <ng-container i18n>Download</ng-container>
</a>
return this.video && this.video.state.id === VideoState.TO_TRANSCODE
}
+ isVideoDownloadable () {
+ return this.video && this.video.downloadingEnabled
+ }
+
isVideoToImport () {
return this.video && this.video.state.id === VideoState.TO_IMPORT
}
licence: body.licence || importData.licence,
language: body.language || undefined,
commentsEnabled: body.commentsEnabled || true,
+ downloadingEnabled: body.downloadingEnabled || true,
waitTranscoding: body.waitTranscoding || false,
state: VideoState.TO_IMPORT,
nsfw: body.nsfw || importData.nsfw || false,
licence: videoInfo.licence,
language: videoInfo.language,
commentsEnabled: videoInfo.commentsEnabled || false,
+ downloadingEnabled: videoInfo.downloadingEnabled || false,
waitTranscoding: videoInfo.waitTranscoding || false,
state: CONFIG.TRANSCODING.ENABLED ? VideoState.TO_TRANSCODE : VideoState.PUBLISHED,
nsfw: videoInfo.nsfw || false,
if (videoInfoToUpdate.support !== undefined) videoInstance.set('support', videoInfoToUpdate.support)
if (videoInfoToUpdate.description !== undefined) videoInstance.set('description', videoInfoToUpdate.description)
if (videoInfoToUpdate.commentsEnabled !== undefined) videoInstance.set('commentsEnabled', videoInfoToUpdate.commentsEnabled)
+ if (videoInfoToUpdate.downloadingEnabled !== undefined) videoInstance.set('downloadingEnabled', videoInfoToUpdate.downloadingEnabled)
if (videoInfoToUpdate.privacy !== undefined) {
const newPrivacy = parseInt(videoInfoToUpdate.privacy.toString(), 10)
videoInstance.set('privacy', newPrivacy)
size: 'schema:Number',
fps: 'schema:Number',
commentsEnabled: 'schema:Boolean',
+ downloadingEnabled: 'schema:Boolean',
waitTranscoding: 'schema:Boolean',
expires: 'schema:expires',
support: 'schema:Text',
'channel-uuid',
'channel-name',
'support',
- 'commentsEnabled'
+ 'commentsEnabled',
+ 'downloadingEnabled'
]
class VideoAuditView extends EntityAuditView {
constructor (private video: VideoDetails) {
isVideoViewsValid(video.views) &&
isBooleanValid(video.sensitive) &&
isBooleanValid(video.commentsEnabled) &&
+ isBooleanValid(video.downloadingEnabled) &&
isDateValid(video.published) &&
isDateValid(video.updated) &&
(!video.content || isRemoteVideoContentValid(video.mediaType, video.content)) &&
--- /dev/null
+import * as Sequelize from 'sequelize'
+import { Migration } from '../../models/migrations'
+
+async function up (utils: {
+ transaction: Sequelize.Transaction,
+ queryInterface: Sequelize.QueryInterface,
+ sequelize: Sequelize.Sequelize
+}): Promise<void> {
+ const data = {
+ type: Sequelize.BOOLEAN,
+ allowNull: false,
+ defaultValue: true
+ } as Migration.Boolean
+ await utils.queryInterface.addColumn('video', 'downloadingEnabled', data)
+
+ data.defaultValue = null
+ return utils.queryInterface.changeColumn('video', 'downloadingEnabled', data)
+}
+
+function down (options) {
+ throw new Error('Not implemented.')
+}
+
+export {
+ up,
+ down
+}
options.video.set('support', videoData.support)
options.video.set('nsfw', videoData.nsfw)
options.video.set('commentsEnabled', videoData.commentsEnabled)
+ options.video.set('downloadingEnabled', videoData.downloadingEnabled)
options.video.set('waitTranscoding', videoData.waitTranscoding)
options.video.set('state', videoData.state)
options.video.set('duration', videoData.duration)
support,
nsfw: videoObject.sensitive,
commentsEnabled: videoObject.commentsEnabled,
+ downloadingEnabled: videoObject.downloadingEnabled,
waitTranscoding: videoObject.waitTranscoding,
state: videoObject.state,
channelId: videoChannel.id,
.optional()
.toBoolean()
.custom(isBooleanValid).withMessage('Should have comments enabled boolean'),
+ body('downloadingEnabled')
+ .optional()
+ .toBoolean()
+ .custom(isBooleanValid).withMessage('Should have downloading enabled boolean'),
body('scheduleUpdate')
.optional()
account: video.VideoChannel.Account.toFormattedJSON(),
tags,
commentsEnabled: video.commentsEnabled,
+ downloadingEnabled: video.downloadingEnabled,
waitTranscoding: video.waitTranscoding,
state: {
id: video.state,
waitTranscoding: video.waitTranscoding,
state: video.state,
commentsEnabled: video.commentsEnabled,
+ downloadingEnabled: video.downloadingEnabled,
published: video.publishedAt.toISOString(),
updated: video.updatedAt.toISOString(),
mediaType: 'text/markdown',
@Column
commentsEnabled: boolean
+ @AllowNull(false)
+ @Column
+ downloadingEnabled: boolean
+
@AllowNull(false)
@Column
waitTranscoding: boolean
language: 'pt',
nsfw: false,
commentsEnabled: true,
+ downloadingEnabled: true,
waitTranscoding: true,
description: 'my super description',
support: 'my super support text',
language: 'pt',
nsfw: false,
commentsEnabled: true,
+ downloadingEnabled: true,
waitTranscoding: true,
description: 'my super description',
support: 'my super support text',
language: 'pt',
nsfw: false,
commentsEnabled: false,
+ downloadingEnabled: false,
description: 'my super description',
privacy: VideoPrivacy.PUBLIC,
tags: [ 'tag1', 'tag2' ]
},
isLocal,
commentsEnabled: true,
+ downloadingEnabled: true,
duration: 5,
tags: [ 'tag1', 'tag2', 'tag3' ],
privacy: VideoPrivacy.PUBLIC,
tags: [ 'tag1p1', 'tag2p1' ],
privacy: VideoPrivacy.PUBLIC,
commentsEnabled: true,
+ downloadingEnabled: true,
channel: {
name: 'root_channel',
displayName: 'Main root channel',
tags: [ 'tag1p1', 'tag2p1' ],
privacy: VideoPrivacy.PUBLIC,
commentsEnabled: true,
+ downloadingEnabled: true,
channel: {
displayName: 'my channel',
name: 'super_channel_name',
},
isLocal,
commentsEnabled: true,
+ downloadingEnabled: true,
duration: 5,
tags: [ 'tag1p2', 'tag2p2', 'tag3p2' ],
privacy: VideoPrivacy.PUBLIC,
isLocal,
duration: 5,
commentsEnabled: true,
+ downloadingEnabled: true,
tags: [ 'tag1p3' ],
privacy: VideoPrivacy.PUBLIC,
channel: {
host: 'localhost:9003'
},
commentsEnabled: true,
+ downloadingEnabled: true,
isLocal,
duration: 5,
tags: [ 'tag2p3', 'tag3p3', 'tag4p3' ],
isLocal,
duration: 5,
commentsEnabled: true,
+ downloadingEnabled: true,
tags: [ 'tag_up_1', 'tag_up_2' ],
privacy: VideoPrivacy.PUBLIC,
channel: {
isLocal,
duration: 5,
commentsEnabled: false,
+ downloadingEnabled: false,
tags: [ ],
privacy: VideoPrivacy.PUBLIC,
channel: {
tags: [ 'tag1', 'tag2', 'tag3' ],
privacy: VideoPrivacy.PUBLIC,
commentsEnabled: true,
+ downloadingEnabled: true,
channel: {
displayName: 'Main root channel',
name: 'root_channel',
privacy: VideoPrivacy.PUBLIC,
duration: 5,
commentsEnabled: false,
+ downloadingEnabled: false,
channel: {
name: 'root_channel',
displayName: 'Main root channel',
nsfw: false,
description: 'my super description updated',
commentsEnabled: false,
+ downloadingEnabled: false,
tags: [ 'tagup1', 'tagup2' ]
}
await updateVideo(server.url, server.accessToken, videoId, attributes)
language?: string
nsfw?: boolean
commentsEnabled?: boolean
+ downloadingEnabled?: boolean
waitTranscoding?: boolean
description?: string
tags?: string[]
tags: [ 'tag' ],
privacy: VideoPrivacy.PUBLIC,
commentsEnabled: true,
+ downloadingEnabled: true,
fixture: 'video_short.webm'
}, videoAttributesArg)
.field('name', attributes.name)
.field('nsfw', JSON.stringify(attributes.nsfw))
.field('commentsEnabled', JSON.stringify(attributes.commentsEnabled))
+ .field('downloadingEnabled', JSON.stringify(attributes.downloadingEnabled))
.field('waitTranscoding', JSON.stringify(attributes.waitTranscoding))
.field('privacy', attributes.privacy.toString())
.field('channelId', attributes.channelId)
if (attributes.language) body['language'] = attributes.language
if (attributes.nsfw !== undefined) body['nsfw'] = JSON.stringify(attributes.nsfw)
if (attributes.commentsEnabled !== undefined) body['commentsEnabled'] = JSON.stringify(attributes.commentsEnabled)
+ if (attributes.downloadingEnabled !== undefined) body['downloadingEnabled'] = JSON.stringify(attributes.downloadingEnabled)
if (attributes.description) body['description'] = attributes.description
if (attributes.tags) body['tags'] = attributes.tags
if (attributes.privacy) body['privacy'] = attributes.privacy
language: string
nsfw: boolean
commentsEnabled: boolean
+ downloadingEnabled: boolean
description: string
publishedAt?: string
support: string
expect(dateIsValid(videoDetails.channel.createdAt.toString())).to.be.true
expect(dateIsValid(videoDetails.channel.updatedAt.toString())).to.be.true
expect(videoDetails.commentsEnabled).to.equal(attributes.commentsEnabled)
+ expect(videoDetails.downloadingEnabled).to.equal(attributes.downloadingEnabled)
for (const attributeFile of attributes.files) {
const file = videoDetails.files.find(f => f.resolution.id === attributeFile.resolution)
nsfw: isNSFW(videoInfo),
waitTranscoding: true,
commentsEnabled: true,
+ downloadingEnabled: true,
description: videoInfo.description || undefined,
support: undefined,
tags,
if (!program['nsfw']) program['nsfw'] = false
if (!program['privacy']) program['privacy'] = VideoPrivacy.PUBLIC
if (!program['commentsEnabled']) program['commentsEnabled'] = false
+if (!program['downloadingEnabled']) program['downloadingEnabled'] = false
getSettings()
.then(settings => {
description: program['videoDescription'],
tags: program['tags'],
commentsEnabled: program['commentsEnabled'],
+ downloadingEnabled: program['downloadingEnabled'],
fixture: program['file'],
thumbnailfile: program['thumbnail'],
previewfile: program['preview'],
subtitleLanguage: ActivityIdentifierObject[]
views: number
sensitive: boolean
- commentsEnabled: boolean
+ commentsEnabled: boolean,
+ downloadingEnabled: boolean,
waitTranscoding: boolean
state: VideoState
published: string
name: string
tags?: string[]
commentsEnabled?: boolean
+ downloadingEnabled?: boolean
privacy: VideoPrivacy
scheduleUpdate?: VideoScheduleUpdate
}
privacy?: VideoPrivacy
tags?: string[]
commentsEnabled?: boolean
+ downloadingEnabled?: boolean
nsfw?: boolean
waitTranscoding?: boolean
channelId?: number
files: VideoFile[]
account: Account
commentsEnabled: boolean
+ downloadingEnabled: boolean
// Not optional in details (unlike in Video)
waitTranscoding: boolean
- $ref: "videos.yaml#/parameters/name"
- $ref: "videos.yaml#/parameters/tags"
- $ref: "videos.yaml#/parameters/commentsEnabled"
+ - $ref: "videos.yaml#/parameters/downloadingEnabled"
- $ref: "videos.yaml#/parameters/privacy"
- $ref: "videos.yaml#/parameters/scheduleUpdate"
responses:
- $ref: "videos.yaml#/parameters/name"
- $ref: "videos.yaml#/parameters/tags"
- $ref: "videos.yaml#/parameters/commentsEnabled"
+ - $ref: "videos.yaml#/parameters/downloadingEnabled"
- $ref: "videos.yaml#/parameters/privacy"
- $ref: "videos.yaml#/parameters/scheduleUpdate"
responses:
in: formData
type: boolean
description: 'Enable or disable comments for this video'
+ downloadingEnabled:
+ name: downloadingEnabled
+ in: formData
+ type: boolean
+ description: 'Enable or disable downloading for this video'
privacy:
name: privacy
in: formData