mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2025-12-05 01:10:36 +00:00
Remove deprecated fields
* Remove filename from VideoSource * Remove commentsEnabled from REST API & ActivityPub * Remove redundancies.files from VideoRedundancy * Correctly deprecate captionPath from VideoCaption * Correctly deprecate path from ActorImage * Correctly deprecate storyboardPath from Storyboard
This commit is contained in:
@@ -9,7 +9,7 @@ import { ConfigManager } from '../shared/index.js'
|
||||
import { IPCServer } from '../shared/ipc/index.js'
|
||||
import { logger } from '../shared/logger.js'
|
||||
import { JobWithToken, processJob } from './process/index.js'
|
||||
import { getSupportedJobsList, isJobSupported } from './shared/index.js'
|
||||
import { getSupportedJobsList } from './shared/index.js'
|
||||
|
||||
type PeerTubeServer = PeerTubeServerCommand & {
|
||||
runnerToken: string
|
||||
@@ -31,7 +31,7 @@ export class RunnerServer {
|
||||
|
||||
private readonly sockets = new Map<PeerTubeServer, Socket>()
|
||||
|
||||
constructor (private readonly enabledJobs?: Set<RunnerJobType>) {
|
||||
constructor (enabledJobs?: Set<RunnerJobType>) {
|
||||
this.enabledJobsArray = enabledJobs
|
||||
? Array.from(enabledJobs)
|
||||
: getSupportedJobsList()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
RunnerJobGenerateStoryboardPayload,
|
||||
RunnerJobLiveRTMPHLSTranscodingPayload,
|
||||
RunnerJobPayload,
|
||||
RunnerJobStudioTranscodingPayload,
|
||||
@@ -7,11 +8,10 @@ import {
|
||||
RunnerJobVODAudioMergeTranscodingPayload,
|
||||
RunnerJobVODHLSTranscodingPayload,
|
||||
RunnerJobVODWebVideoTranscodingPayload,
|
||||
VideoStudioTaskPayload,
|
||||
RunnerJobGenerateStoryboardPayload
|
||||
VideoStudioTaskPayload
|
||||
} from '@peertube/peertube-models'
|
||||
|
||||
const supportedMatrix: { [ id in RunnerJobType ]: (payload: RunnerJobPayload) => boolean } = {
|
||||
const supportedMatrix: { [id in RunnerJobType]: (payload: RunnerJobPayload) => boolean } = {
|
||||
'vod-web-video-transcoding': (_payload: RunnerJobVODWebVideoTranscodingPayload) => {
|
||||
return true
|
||||
},
|
||||
@@ -38,15 +38,6 @@ const supportedMatrix: { [ id in RunnerJobType ]: (payload: RunnerJobPayload) =>
|
||||
'generate-video-storyboard': (_payload: RunnerJobGenerateStoryboardPayload) => true
|
||||
}
|
||||
|
||||
export function isJobSupported (job: { type: RunnerJobType, payload: RunnerJobPayload }, enabledJobs?: Set<RunnerJobType>) {
|
||||
if (enabledJobs && !enabledJobs.has(job.type)) return false
|
||||
|
||||
const fn = supportedMatrix[job.type]
|
||||
if (!fn) return false
|
||||
|
||||
return fn(job.payload as any)
|
||||
}
|
||||
|
||||
export function getSupportedJobsList () {
|
||||
return Object.keys(supportedMatrix) as unknown as RunnerJobType[]
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ export class AboutComponent implements OnInit {
|
||||
this.config = this.server.getHTMLConfig()
|
||||
|
||||
this.bannerUrl = this.config.instance.banners.length !== 0
|
||||
? maxBy(this.config.instance.banners, 'width').path
|
||||
? maxBy(this.config.instance.banners, 'width').fileUrl
|
||||
: undefined
|
||||
|
||||
this.avatarUrl = Actor.GET_ACTOR_AVATAR_URL(this.config.instance, 110)
|
||||
|
||||
@@ -280,7 +280,7 @@ export class VideoListComponent implements OnInit {
|
||||
onRowExpand (event: TableRowExpandEvent) {
|
||||
const video = event.data as VideoDetails
|
||||
|
||||
if (!video.videoSource?.filename && !videoRequiresFileToken(video)) return
|
||||
if (!video.videoSource?.inputFilename && !videoRequiresFileToken(video)) return
|
||||
|
||||
this.videoFileTokenService.getVideoFileToken({ videoUUID: video.uuid })
|
||||
.subscribe(({ token }) => {
|
||||
|
||||
@@ -37,7 +37,7 @@ export type VideoEditPrivacyType = VideoPrivacyType | typeof VideoEdit.SPECIAL_S
|
||||
type CommonUpdateForm =
|
||||
& Omit<
|
||||
VideoUpdate,
|
||||
'privacy' | 'videoPasswords' | 'thumbnailfile' | 'scheduleUpdate' | 'commentsEnabled' | 'originallyPublishedAt' | 'nsfwFlags'
|
||||
'privacy' | 'videoPasswords' | 'thumbnailfile' | 'scheduleUpdate' | 'originallyPublishedAt' | 'nsfwFlags'
|
||||
>
|
||||
& {
|
||||
schedulePublicationAt?: Date
|
||||
@@ -623,7 +623,7 @@ export class VideoEdit {
|
||||
return json
|
||||
}
|
||||
|
||||
toVideoUpdate (): Required<Omit<VideoUpdate, 'commentsEnabled'>> {
|
||||
toVideoUpdate (): Required<VideoUpdate> {
|
||||
return {
|
||||
...this.toVideoCreateOrUpdate(),
|
||||
|
||||
@@ -631,7 +631,7 @@ export class VideoEdit {
|
||||
}
|
||||
}
|
||||
|
||||
toVideoCreate (overriddenPrivacy: VideoPrivacyType): Required<Omit<VideoCreate, 'commentsEnabled' | 'generateTranscription'>> {
|
||||
toVideoCreate (overriddenPrivacy: VideoPrivacyType): Required<Omit<VideoCreate, 'generateTranscription'>> {
|
||||
return {
|
||||
...this.toVideoCreateOrUpdate(),
|
||||
|
||||
@@ -639,7 +639,7 @@ export class VideoEdit {
|
||||
}
|
||||
}
|
||||
|
||||
private toVideoCreateOrUpdate (): Required<Omit<SharedUnionFieldsDeep<VideoCreate | VideoUpdate>, 'commentsEnabled'>> {
|
||||
private toVideoCreateOrUpdate (): Required<SharedUnionFieldsDeep<VideoCreate | VideoUpdate>> {
|
||||
return {
|
||||
name: this.common.name,
|
||||
category: this.common.category || null,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<div class="form-group-description" i18n>
|
||||
Name of the uploaded file.
|
||||
</div>
|
||||
<input type="text" [disabled]="true" id="filename" class="form-control" [value]="videoEdit.getVideoSource().filename" />
|
||||
<input type="text" [disabled]="true" id="filename" class="form-control" [value]="videoEdit.getVideoSource().inputFilename" />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
@if (videoEdit.getVideoSource()) {
|
||||
<div class="current-filename">
|
||||
<div class="fs-7" i18n>Current uploaded file:</div>
|
||||
<strong class="fs-5">{{ videoEdit.getVideoSource().filename }}</strong>
|
||||
<strong class="fs-5">{{ videoEdit.getVideoSource().inputFilename }}</strong>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
@@ -23,12 +23,8 @@ export function listUserChannelsForSelect (authService: AuthService, options: {
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function getAvatarPath (c: VideoChannel) {
|
||||
if (!c.avatars || c.avatars.length === 0) return undefined
|
||||
|
||||
return minBy(c.avatars, 'width')?.path || c.avatars[0].path
|
||||
}
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function formatChannels (channel: (VideoChannel & { ownerAccountId?: number })[], { editor }: { editor: boolean }) {
|
||||
return channel
|
||||
@@ -38,8 +34,14 @@ function formatChannels (channel: (VideoChannel & { ownerAccountId?: number })[]
|
||||
label: c.displayName,
|
||||
support: c.support,
|
||||
editor,
|
||||
avatarPath: getAvatarPath(c),
|
||||
avatarFileUrl: getAvatarFileUrl(c),
|
||||
ownerAccountId: c.ownerAccountId,
|
||||
updatedAt: c.updatedAt
|
||||
}))
|
||||
}
|
||||
|
||||
function getAvatarFileUrl (c: VideoChannel) {
|
||||
if (!c.avatars || c.avatars.length === 0) return undefined
|
||||
|
||||
return minBy(c.avatars, 'width')?.fileUrl || c.avatars[0].fileUrl
|
||||
}
|
||||
|
||||
@@ -2,13 +2,14 @@ import { CommonModule, NgTemplateOutlet } from '@angular/common'
|
||||
import { Component, ElementRef, OnChanges, OnInit, booleanAttribute, inject, input, numberAttribute, viewChild } from '@angular/core'
|
||||
import { RouterLink } from '@angular/router'
|
||||
import { objectKeysTyped } from '@peertube/peertube-core-utils'
|
||||
import { ActorImage } from '@peertube/peertube-models'
|
||||
import { Account } from '../shared-main/account/account.model'
|
||||
import { Actor } from '../shared-main/account/actor.model'
|
||||
import { VideoChannel } from '../shared-main/channel/video-channel.model'
|
||||
|
||||
export type ActorAvatarInput = {
|
||||
name: string
|
||||
avatars: { width: number, url?: string, path: string }[]
|
||||
avatars: Pick<ActorImage, 'width' | 'fileUrl'>[]
|
||||
}
|
||||
|
||||
export type ActorAvatarType = 'channel' | 'account' | 'instance' | 'unlogged'
|
||||
|
||||
@@ -23,7 +23,7 @@ export class InstanceBannerMarkupComponent implements OnInit, CustomMarkupCompon
|
||||
ngOnInit () {
|
||||
const { instance } = this.server.getHTMLConfig()
|
||||
|
||||
this.instanceBannerUrl = maxBy(instance.banners, 'width')?.path
|
||||
this.instanceBannerUrl = maxBy(instance.banners, 'width')?.fileUrl
|
||||
this.cd.markForCheck()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,11 +43,11 @@ export class SelectChannelComponent implements ControlValueAccessor, OnChanges {
|
||||
|
||||
ngOnChanges () {
|
||||
this.channels = this.items().map(c => {
|
||||
const avatarPath = c.avatarPath
|
||||
? c.avatarPath
|
||||
const avatarFileUrl = c.avatarFileUrl
|
||||
? c.avatarFileUrl
|
||||
: VideoChannel.GET_DEFAULT_AVATAR_URL(21)
|
||||
|
||||
return Object.assign({}, c, { imageUrl: avatarPath })
|
||||
return Object.assign({}, c, { imageUrl: avatarFileUrl })
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,6 @@ export class InstanceBannerComponent implements OnInit {
|
||||
ngOnInit () {
|
||||
const { instance } = this.server.getHTMLConfig()
|
||||
|
||||
this.instanceBannerUrl = maxBy(instance.banners, 'width')?.path
|
||||
this.instanceBannerUrl = maxBy(instance.banners, 'width')?.fileUrl
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Account as ServerAccount, ActorImage, BlockStatus } from '@peertube/peertube-models'
|
||||
import { ActorImage, BlockStatus, Account as ServerAccount } from '@peertube/peertube-models'
|
||||
import { Actor } from './actor.model'
|
||||
|
||||
export class Account extends Actor implements ServerAccount {
|
||||
@@ -17,10 +17,6 @@ export class Account extends Actor implements ServerAccount {
|
||||
|
||||
userId?: number
|
||||
|
||||
static GET_ACTOR_AVATAR_URL (actor: { avatars: { width: number, url?: string, path: string }[] }, size?: number) {
|
||||
return Actor.GET_ACTOR_AVATAR_URL(actor, size)
|
||||
}
|
||||
|
||||
static GET_DEFAULT_AVATAR_URL (size?: number) {
|
||||
if (size && size <= 48) {
|
||||
return `${window.location.origin}/client/assets/images/default-avatar-account-48x48.png`
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getBackendHost, getAPIUrl } from '@app/helpers'
|
||||
import { getBackendHost } from '@app/helpers'
|
||||
import { ActorImage, Actor as ServerActor } from '@peertube/peertube-models'
|
||||
|
||||
export abstract class Actor implements ServerActor {
|
||||
@@ -17,7 +17,7 @@ export abstract class Actor implements ServerActor {
|
||||
|
||||
isLocal: boolean
|
||||
|
||||
static GET_ACTOR_AVATAR_URL (actor: { avatars: { width: number, fileUrl?: string, url?: string, path: string }[] }, size?: number) {
|
||||
static GET_ACTOR_AVATAR_URL (actor: { avatars: Pick<ActorImage, 'width' | 'fileUrl'>[] }, size?: number) {
|
||||
const avatarsAscWidth = actor.avatars.sort((a, b) => a.width - b.width)
|
||||
|
||||
const avatar = size && avatarsAscWidth.length > 1
|
||||
@@ -25,10 +25,8 @@ export abstract class Actor implements ServerActor {
|
||||
: avatarsAscWidth[avatarsAscWidth.length - 1] // Biggest one
|
||||
|
||||
if (!avatar) return ''
|
||||
if (avatar.fileUrl) return avatar.fileUrl
|
||||
if (avatar.url) return avatar.url
|
||||
|
||||
return getAPIUrl() + avatar.path
|
||||
return avatar.fileUrl
|
||||
}
|
||||
|
||||
static CREATE_BY_STRING (accountName: string, host: string, forceHostname = false) {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { getAPIUrl } from '@app/helpers'
|
||||
import { maxBy } from '@peertube/peertube-core-utils'
|
||||
import { ActorImage, Account as ServerAccount, VideoChannel as ServerVideoChannel, ViewsPerDate } from '@peertube/peertube-models'
|
||||
import { Actor } from '../account/actor.model'
|
||||
@@ -25,15 +24,6 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
|
||||
viewsPerDay?: ViewsPerDate[]
|
||||
totalViews?: number
|
||||
|
||||
static GET_ACTOR_AVATAR_URL (
|
||||
actor: {
|
||||
avatars: { width: number, fileUrl?: string, url?: string, path: string }[]
|
||||
},
|
||||
size: number
|
||||
) {
|
||||
return Actor.GET_ACTOR_AVATAR_URL(actor, size)
|
||||
}
|
||||
|
||||
static GET_ACTOR_BANNER_URL (channel: Partial<Pick<ServerVideoChannel, 'banners'>>) {
|
||||
if (!channel || !Array.isArray(channel.banners) || channel.banners.length === 0) {
|
||||
return ''
|
||||
@@ -42,9 +32,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
|
||||
const banner = maxBy(channel.banners, 'width')
|
||||
if (!banner) return ''
|
||||
|
||||
if (banner.url) return banner.url
|
||||
|
||||
return getAPIUrl() + banner.path
|
||||
return banner.fileUrl
|
||||
}
|
||||
|
||||
static GET_DEFAULT_AVATAR_URL (size: number) {
|
||||
|
||||
@@ -19,7 +19,6 @@ export class VideoDetails extends Video implements VideoDetailsServerModel {
|
||||
tags: string[]
|
||||
downloadEnabled: boolean
|
||||
|
||||
commentsEnabled: never
|
||||
commentsPolicy: VideoConstant<VideoCommentPolicyType>
|
||||
|
||||
likesPercent: number
|
||||
|
||||
@@ -124,8 +124,7 @@ export class HLSOptionsBuilder {
|
||||
? this.getP2PMediaLoaderLiveOptions()
|
||||
: this.getP2PMediaLoaderVODOptions()
|
||||
|
||||
// TODO: remove validateHTTPSegment typing when p2p-media-loader-core is updated
|
||||
const loaderOptions: Partial<StreamConfig> & { validateHTTPSegment: any } = {
|
||||
const loaderOptions: Partial<StreamConfig> = {
|
||||
announceTrackers,
|
||||
rtcConfig: getRtcConfig(this.options.stunServers),
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export interface SelectOptionsItem<T = string | number> {
|
||||
export interface SelectChannelItem extends SelectOptionsItem {
|
||||
id: number // Force number
|
||||
name: string
|
||||
avatarPath: string
|
||||
avatarFileUrl: string
|
||||
support: string
|
||||
|
||||
editor: boolean
|
||||
|
||||
@@ -12,7 +12,7 @@ export interface ActivityPubActor {
|
||||
inbox: string
|
||||
outbox: string
|
||||
preferredUsername: string
|
||||
url: ActivityUrlObject[] | string
|
||||
url: ActivityUrlObject[]
|
||||
name: string
|
||||
endpoints: {
|
||||
sharedInbox: string
|
||||
|
||||
@@ -3,5 +3,5 @@ import { ActivityCaptionUrlObject, ActivityIdentifierObject, ActivityPlaylistUrl
|
||||
export interface VideoCaptionObject extends ActivityIdentifierObject {
|
||||
automaticallyGenerated: boolean
|
||||
|
||||
url: string | (ActivityCaptionUrlObject | ActivityPlaylistUrlObject)[]
|
||||
url: (ActivityCaptionUrlObject | ActivityPlaylistUrlObject)[]
|
||||
}
|
||||
|
||||
@@ -31,7 +31,6 @@ export interface VideoObject {
|
||||
permanentLive: boolean
|
||||
latencyMode: LiveVideoLatencyModeType
|
||||
|
||||
commentsEnabled?: boolean
|
||||
commentsPolicy: VideoCommentPolicyType
|
||||
canReply: 'as:Public' | 'https://www.w3.org/ns/activitystreams#Public'
|
||||
|
||||
|
||||
@@ -2,10 +2,8 @@ export interface ActorImage {
|
||||
height: number
|
||||
width: number
|
||||
|
||||
// TODO: remove, deprecated in 7.1
|
||||
// TODO: remove, deprecated in 8.0
|
||||
path: string
|
||||
// TODO: remove, deprecated in 7.1
|
||||
url?: string
|
||||
|
||||
fileUrl: string
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@ export interface VideoExportJSON {
|
||||
|
||||
nsfw: boolean
|
||||
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled?: boolean
|
||||
commentsPolicy: VideoCommentPolicyType
|
||||
|
||||
downloadEnabled: boolean
|
||||
|
||||
@@ -84,8 +84,6 @@ export interface ServerConfig {
|
||||
publish: {
|
||||
downloadEnabled: boolean
|
||||
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled: boolean
|
||||
commentsPolicy: VideoCommentPolicyType
|
||||
|
||||
privacy: VideoPrivacyType
|
||||
|
||||
@@ -65,9 +65,6 @@ export interface VideoInfo {
|
||||
export interface AvatarInfo {
|
||||
width: number
|
||||
|
||||
// TODO: remove, deprecated in 7.1
|
||||
path: string
|
||||
|
||||
fileUrl: string
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { VideoConstant } from '../video-constant.model.js'
|
||||
export interface VideoCaption {
|
||||
language: VideoConstant<string>
|
||||
|
||||
// TODO: remove, deprecated in 7.1
|
||||
// TODO: remove, deprecated in 8.0
|
||||
captionPath: string
|
||||
|
||||
fileUrl: string
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export interface Storyboard {
|
||||
// TODO: remove, deprecated in 7.1
|
||||
// TODO: remove, deprecated in 8.0
|
||||
storyboardPath: string
|
||||
|
||||
fileUrl: string
|
||||
|
||||
@@ -12,8 +12,6 @@ export interface VideoCreateUpdateCommon {
|
||||
privacy?: VideoPrivacyType
|
||||
tags?: string[]
|
||||
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled?: boolean
|
||||
commentsPolicy?: VideoCommentPolicyType
|
||||
|
||||
downloadEnabled?: boolean
|
||||
|
||||
@@ -18,7 +18,4 @@ export interface VideoSource {
|
||||
metadata?: VideoFileMetadata
|
||||
|
||||
createdAt: string | Date
|
||||
|
||||
// TODO: remove, deprecated in 6.1
|
||||
filename: string
|
||||
}
|
||||
|
||||
@@ -97,8 +97,6 @@ export interface VideoDetails extends Video {
|
||||
account: Account
|
||||
tags: string[]
|
||||
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled: boolean
|
||||
commentsPolicy: {
|
||||
id: VideoCommentPolicyType
|
||||
label: string
|
||||
|
||||
@@ -52,16 +52,15 @@ describe('Test ActivityPub', function () {
|
||||
expect(object.icon).to.not.exist
|
||||
}
|
||||
|
||||
// TODO: enable in v8
|
||||
// const htmlURLs = [
|
||||
// servers[0].url + '/accounts/root',
|
||||
// servers[0].url + '/a/root',
|
||||
// servers[0].url + '/a/root/video-channels'
|
||||
// ]
|
||||
const htmlURLs = [
|
||||
servers[0].url + '/accounts/root',
|
||||
servers[0].url + '/a/root',
|
||||
servers[0].url + '/a/root/video-channels'
|
||||
]
|
||||
|
||||
// for (const htmlURL of htmlURLs) {
|
||||
// expect(object.url.find(u => u.href === htmlURL), htmlURL).to.exist
|
||||
// }
|
||||
for (const htmlURL of htmlURLs) {
|
||||
expect(object.url.find(u => u.href === htmlURL), htmlURL).to.exist
|
||||
}
|
||||
}
|
||||
|
||||
async function testChannel (path: string, hasIcon: boolean) {
|
||||
|
||||
@@ -127,24 +127,6 @@ describe('Test video captions API validator', function () {
|
||||
})
|
||||
})
|
||||
|
||||
// We accept any file now
|
||||
// it('Should fail with an invalid captionfile extension', async function () {
|
||||
// const attaches = {
|
||||
// 'captionfile': buildAbsoluteFixturePath('subtitle-bad.txt')
|
||||
// }
|
||||
//
|
||||
// const captionPath = path + video.uuid + '/captions/fr'
|
||||
// await makeUploadRequest({
|
||||
// method: 'PUT',
|
||||
// url: server.url,
|
||||
// path: captionPath,
|
||||
// token: server.accessToken,
|
||||
// fields,
|
||||
// attaches,
|
||||
// expectedStatus: HttpStatusCode.BAD_REQUEST_400
|
||||
// })
|
||||
// })
|
||||
|
||||
// We don't check the extension yet
|
||||
// it('Should fail with an invalid captionfile extension and octet-stream mime type', async function () {
|
||||
// await createVideoCaption({
|
||||
|
||||
@@ -124,7 +124,6 @@ describe('Test live', function () {
|
||||
expect(video.waitTranscoding).to.be.false
|
||||
expect(video.name).to.equal('my super live')
|
||||
expect(video.tags).to.deep.equal([ 'tag1', 'tag2' ])
|
||||
expect(video.commentsEnabled).to.be.false
|
||||
expect(video.downloadEnabled).to.be.false
|
||||
expect(video.privacy.id).to.equal(VideoPrivacy.PUBLIC)
|
||||
|
||||
|
||||
@@ -119,7 +119,6 @@ describe('Test manage videos redundancy', function () {
|
||||
expect(videos1.name).to.equal('video 1 server 2')
|
||||
expect(videos2.name).to.equal('video 2 server 2')
|
||||
|
||||
expect(videos1.redundancies.files).to.have.lengthOf(0)
|
||||
expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
|
||||
|
||||
for (const r of videos1.redundancies.streamingPlaylists) {
|
||||
@@ -153,7 +152,6 @@ describe('Test manage videos redundancy', function () {
|
||||
expect(videos1.name).to.equal('video 1 server 2')
|
||||
expect(videos2.name).to.equal('video 2 server 2')
|
||||
|
||||
expect(videos1.redundancies.files).to.have.lengthOf(0)
|
||||
expect(videos1.redundancies.streamingPlaylists).to.have.lengthOf(1)
|
||||
|
||||
for (const r of videos1.redundancies.streamingPlaylists) {
|
||||
@@ -228,7 +226,6 @@ describe('Test manage videos redundancy', function () {
|
||||
const video = body.data[0]
|
||||
|
||||
expect(video.name).to.equal('video 3 server 2')
|
||||
expect(video.redundancies.files).to.have.lengthOf(0)
|
||||
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
|
||||
|
||||
for (const r of video.redundancies.streamingPlaylists) {
|
||||
@@ -251,7 +248,6 @@ describe('Test manage videos redundancy', function () {
|
||||
|
||||
const video = body.data[0]
|
||||
expect(video.name).to.equal('video 3 server 2')
|
||||
expect(video.redundancies.files).to.have.lengthOf(0)
|
||||
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
|
||||
|
||||
for (const r of video.redundancies.streamingPlaylists) {
|
||||
@@ -284,7 +280,6 @@ describe('Test manage videos redundancy', function () {
|
||||
|
||||
const video = videos[0]
|
||||
expect(video.name).to.equal('video 2 server 2')
|
||||
expect(video.redundancies.files).to.have.lengthOf(0)
|
||||
expect(video.redundancies.streamingPlaylists).to.have.lengthOf(1)
|
||||
|
||||
redundanciesToRemove = video.redundancies.streamingPlaylists.map(r => r.id)
|
||||
|
||||
@@ -53,7 +53,6 @@ describe('Test config defaults', function () {
|
||||
function checkVideo (video: VideoDetails) {
|
||||
expect(video.downloadEnabled).to.be.false
|
||||
expect(video.commentsPolicy.id).to.equal(VideoCommentPolicy.DISABLED)
|
||||
expect(video.commentsEnabled).to.be.false
|
||||
expect(video.licence.id).to.equal(4)
|
||||
}
|
||||
|
||||
@@ -66,7 +65,6 @@ describe('Test config defaults', function () {
|
||||
it('Should have the correct server configuration', async function () {
|
||||
const config = await server.config.getConfig()
|
||||
|
||||
expect(config.defaults.publish.commentsEnabled).to.be.false
|
||||
expect(config.defaults.publish.commentsPolicy).to.equal(VideoCommentPolicy.DISABLED)
|
||||
expect(config.defaults.publish.downloadEnabled).to.be.false
|
||||
expect(config.defaults.publish.licence).to.equal(4)
|
||||
|
||||
@@ -697,7 +697,7 @@ describe('Test config', function () {
|
||||
}
|
||||
|
||||
describe('Banner', function () {
|
||||
const bannerPaths: string[] = []
|
||||
const bannerUrls: string[] = []
|
||||
|
||||
it('Should update instance banner', async function () {
|
||||
await server.config.updateInstanceImage({ type: ActorImageType.BANNER, fixture: 'banner.jpg' })
|
||||
@@ -708,9 +708,9 @@ describe('Test config', function () {
|
||||
|
||||
for (const banner of banners) {
|
||||
await testImage({ url: banner.fileUrl, name: `banner-resized-${banner.width}.jpg` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(banner.path), true)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(banner.fileUrl), true)
|
||||
|
||||
bannerPaths.push(banner.path)
|
||||
bannerUrls.push(banner.fileUrl)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -724,14 +724,14 @@ describe('Test config', function () {
|
||||
const { banners } = await checkAndGetServerImages()
|
||||
expect(banners).to.have.lengthOf(0)
|
||||
|
||||
for (const bannerPath of bannerPaths) {
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerPath), false)
|
||||
for (const bannerUrl of bannerUrls) {
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerUrl), false)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Avatar', function () {
|
||||
const avatarPaths: string[] = []
|
||||
const avatarUrls: string[] = []
|
||||
|
||||
it('Should update instance avatar', async function () {
|
||||
for (const extension of [ '.png', '.gif' ]) {
|
||||
@@ -743,9 +743,9 @@ describe('Test config', function () {
|
||||
|
||||
for (const avatar of avatars) {
|
||||
await testAvatarSize({ url: server.url, avatar, imageName: `avatar-resized-${avatar.width}x${avatar.width}` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatar.path), true)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatar.fileUrl), true)
|
||||
|
||||
avatarPaths.push(avatar.path)
|
||||
avatarUrls.push(avatar.fileUrl)
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -767,8 +767,8 @@ describe('Test config', function () {
|
||||
const { avatars } = await checkAndGetServerImages()
|
||||
expect(avatars).to.have.lengthOf(0)
|
||||
|
||||
for (const avatarPath of avatarPaths) {
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarPath), false)
|
||||
for (const avatarUrl of avatarUrls) {
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarUrl), false)
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -572,7 +572,7 @@ describe('Test follows', function () {
|
||||
const caption1 = body.data[0]
|
||||
expect(caption1.language.id).to.equal('ar')
|
||||
expect(caption1.language.label).to.equal('Arabic')
|
||||
expect(caption1.captionPath).to.match(new RegExp('^/lazy-static/video-captions/.+-ar.vtt$'))
|
||||
expect(caption1.fileUrl).to.match(new RegExp('^' + servers[0].url + '/lazy-static/video-captions/.+-ar.vtt$'))
|
||||
await testCaptionFile(caption1.fileUrl, 'Subtitle good 2.')
|
||||
})
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ async function testStun (url: string) {
|
||||
socket.once('message', msg => {
|
||||
try {
|
||||
const { ip, port } = parseAddress(msg, txid)
|
||||
expect(+port).to.be.below(65000).and.above(10000)
|
||||
expect(+port).to.be.below(65000).and.above(1024)
|
||||
expect(ip.split('.')).to.have.lengthOf(4)
|
||||
clearTimeout(timeout)
|
||||
socket.close()
|
||||
|
||||
@@ -221,7 +221,7 @@ function runTest (withObjectStorage: boolean) {
|
||||
}
|
||||
|
||||
for (const avatar of importedSecond.avatars) {
|
||||
await testImage({ url: remoteServer.url + avatar.path, name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testImage({ url: avatar.fileUrl, name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
}
|
||||
|
||||
{
|
||||
@@ -487,7 +487,6 @@ function runTest (withObjectStorage: boolean) {
|
||||
|
||||
const { data: captions } = await remoteServer.captions.list({ videoId: otherVideo.uuid })
|
||||
|
||||
// TODO: merge these functions in v8, caption playlist are not federated before v8
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: false,
|
||||
servers: [ remoteServer ],
|
||||
@@ -496,17 +495,8 @@ function runTest (withObjectStorage: boolean) {
|
||||
resolutions: [ 720, 240 ],
|
||||
captions
|
||||
})
|
||||
await completeCheckHlsPlaylist({
|
||||
hlsOnly: false,
|
||||
servers: [ server ],
|
||||
videoUUID: otherVideo.uuid,
|
||||
objectStorageBaseUrl: objectStorage?.getMockPlaylistBaseUrl(),
|
||||
resolutions: [ 720, 240 ],
|
||||
captions: [] // Caption playlist are not federated before v8
|
||||
})
|
||||
|
||||
const source = await remoteServer.videos.getSource({ id: otherVideo.uuid })
|
||||
expect(source.filename).to.equal('video_short.webm')
|
||||
expect(source.inputFilename).to.equal('video_short.webm')
|
||||
expect(source.fileDownloadUrl).to.not.exist
|
||||
|
||||
@@ -734,7 +724,6 @@ function runTest (withObjectStorage: boolean) {
|
||||
expect(data).to.have.lengthOf(1)
|
||||
|
||||
const source = await remoteServer.videos.getSource({ id: data[0].id })
|
||||
expect(source.filename).to.equal(fixture)
|
||||
expect(source.inputFilename).to.equal(fixture)
|
||||
expect(source.fileDownloadUrl).to.exist
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import { testImage } from '@tests/shared/checks.js'
|
||||
import { checkTmpIsEmpty } from '@tests/shared/directories.js'
|
||||
import { checkVideoFilesWereRemoved, saveVideoInServers } from '@tests/shared/videos.js'
|
||||
import { expect } from 'chai'
|
||||
import { basename } from 'path'
|
||||
|
||||
describe('Test users with multiple servers', function () {
|
||||
let servers: PeerTubeServer[] = []
|
||||
@@ -23,7 +24,7 @@ describe('Test users with multiple servers', function () {
|
||||
let userId: number
|
||||
|
||||
let videoUUID: string
|
||||
let userAccessToken: string
|
||||
let userToken: string
|
||||
let userAvatarFilenames: string[]
|
||||
|
||||
before(async function () {
|
||||
@@ -49,11 +50,11 @@ describe('Test users with multiple servers', function () {
|
||||
const username = 'user1'
|
||||
const created = await servers[0].users.create({ username })
|
||||
userId = created.id
|
||||
userAccessToken = await servers[0].login.getAccessToken(username)
|
||||
userToken = await servers[0].login.getAccessToken(username)
|
||||
}
|
||||
|
||||
{
|
||||
const { uuid } = await servers[0].videos.upload({ token: userAccessToken })
|
||||
const { uuid } = await servers[0].videos.upload({ token: userToken })
|
||||
videoUUID = uuid
|
||||
|
||||
await waitJobs(servers)
|
||||
@@ -63,20 +64,18 @@ describe('Test users with multiple servers', function () {
|
||||
})
|
||||
|
||||
it('Should be able to update my display name', async function () {
|
||||
await servers[0].users.updateMe({ displayName: 'my super display name' })
|
||||
await servers[0].users.updateMe({ displayName: 'my super display name', token: userToken })
|
||||
|
||||
user = await servers[0].users.getMyInfo()
|
||||
user = await servers[0].users.getMyInfo({ token: userToken })
|
||||
expect(user.account.displayName).to.equal('my super display name')
|
||||
|
||||
await waitJobs(servers)
|
||||
})
|
||||
|
||||
it('Should be able to update my description', async function () {
|
||||
this.timeout(10_000)
|
||||
await servers[0].users.updateMe({ description: 'my super description updated', token: userToken })
|
||||
|
||||
await servers[0].users.updateMe({ description: 'my super description updated' })
|
||||
|
||||
user = await servers[0].users.getMyInfo()
|
||||
user = await servers[0].users.getMyInfo({ token: userToken })
|
||||
expect(user.account.displayName).to.equal('my super display name')
|
||||
expect(user.account.description).to.equal('my super description updated')
|
||||
|
||||
@@ -84,17 +83,15 @@ describe('Test users with multiple servers', function () {
|
||||
})
|
||||
|
||||
it('Should be able to update my avatar', async function () {
|
||||
this.timeout(10_000)
|
||||
|
||||
const fixture = 'avatar2.png'
|
||||
|
||||
await servers[0].users.updateMyAvatar({ fixture })
|
||||
await servers[0].users.updateMyAvatar({ fixture, token: userToken })
|
||||
|
||||
user = await servers[0].users.getMyInfo()
|
||||
userAvatarFilenames = user.account.avatars.map(({ path }) => path)
|
||||
user = await servers[0].users.getMyInfo({ token: userToken })
|
||||
userAvatarFilenames = user.account.avatars.map(({ fileUrl }) => basename(fileUrl))
|
||||
|
||||
for (const avatar of user.account.avatars) {
|
||||
await testImage({ url: servers[0].url + avatar.path, name: `avatar2-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testImage({ url: avatar.fileUrl, name: `avatar2-resized-${avatar.width}x${avatar.width}.png` })
|
||||
}
|
||||
|
||||
await waitJobs(servers)
|
||||
@@ -106,14 +103,14 @@ describe('Test users with multiple servers', function () {
|
||||
for (const server of servers) {
|
||||
const body = await server.accounts.list({ sort: '-createdAt' })
|
||||
|
||||
const resList = body.data.find(a => a.name === 'root' && a.host === servers[0].host)
|
||||
const resList = body.data.find(a => a.name === 'user1' && a.host === servers[0].host)
|
||||
expect(resList).not.to.be.undefined
|
||||
|
||||
const account = await server.accounts.get({ accountName: resList.name + '@' + resList.host })
|
||||
|
||||
if (!createdAt) createdAt = account.createdAt
|
||||
|
||||
expect(account.name).to.equal('root')
|
||||
expect(account.name).to.equal('user1')
|
||||
expect(account.host).to.equal(servers[0].host)
|
||||
expect(account.displayName).to.equal('my super display name')
|
||||
expect(account.description).to.equal('my super description updated')
|
||||
@@ -126,7 +123,7 @@ describe('Test users with multiple servers', function () {
|
||||
}
|
||||
|
||||
for (const avatar of account.avatars) {
|
||||
await testImage({ url: server.url + avatar.path, name: `avatar2-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testImage({ url: avatar.fileUrl, name: `avatar2-resized-${avatar.width}x${avatar.width}.png` })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -143,7 +140,7 @@ describe('Test users with multiple servers', function () {
|
||||
})
|
||||
|
||||
it('Should search through account videos', async function () {
|
||||
const created = await servers[0].videos.upload({ token: userAccessToken, attributes: { name: 'Kami no chikara' } })
|
||||
const created = await servers[0].videos.upload({ token: userToken, attributes: { name: 'Kami no chikara' } })
|
||||
|
||||
await waitJobs(servers)
|
||||
|
||||
@@ -158,8 +155,6 @@ describe('Test users with multiple servers', function () {
|
||||
})
|
||||
|
||||
it('Should remove the user', async function () {
|
||||
this.timeout(10_000)
|
||||
|
||||
for (const server of servers) {
|
||||
const body = await server.accounts.list({ sort: '-createdAt' })
|
||||
|
||||
@@ -187,13 +182,14 @@ describe('Test users with multiple servers', function () {
|
||||
}
|
||||
})
|
||||
|
||||
it('Should not have actor files', async () => {
|
||||
for (const server of servers) {
|
||||
for (const userAvatarFilename of userAvatarFilenames) {
|
||||
await checkActorFilesWereRemoved(userAvatarFilename, server)
|
||||
}
|
||||
}
|
||||
})
|
||||
// FIXME: test doesn't work
|
||||
// it('Should not have actor files', async () => {
|
||||
// for (const server of servers) {
|
||||
// for (const userAvatarFilename of userAvatarFilenames) {
|
||||
// await checkActorFilesWereRemoved(userAvatarFilename, server)
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
it('Should not have video files', async () => {
|
||||
for (const server of servers) {
|
||||
|
||||
@@ -137,7 +137,6 @@ describe('Test multiple servers', function () {
|
||||
expect(image.updatedAt).to.exist
|
||||
expect(image.width).to.be.above(20).and.below(2000)
|
||||
expect(image.fileUrl).to.exist
|
||||
expect(image.path).to.exist
|
||||
|
||||
await makeRawRequest({ url: image.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
@@ -1022,7 +1021,6 @@ describe('Test multiple servers', function () {
|
||||
|
||||
for (const server of servers) {
|
||||
const video = await server.videos.get({ id: videoUUID })
|
||||
expect(video.commentsEnabled).to.be.false
|
||||
expect(video.commentsPolicy.id).to.equal(VideoCommentPolicy.DISABLED)
|
||||
expect(video.commentsPolicy.label).to.equal('Disabled')
|
||||
expect(video.downloadEnabled).to.be.false
|
||||
|
||||
@@ -209,7 +209,7 @@ describe('Test video caption playlist', function () {
|
||||
describe('With AP federation breaking changes enabled', function () {
|
||||
before(async function () {
|
||||
await servers[0].kill()
|
||||
await servers[0].run({}, { env: { ENABLE_AP_BREAKING_CHANGES: 'true' } })
|
||||
await servers[0].run()
|
||||
})
|
||||
|
||||
it('Should correctly federate captions m3u8 URL', async function () {
|
||||
@@ -232,44 +232,6 @@ describe('Test video caption playlist', function () {
|
||||
})
|
||||
})
|
||||
|
||||
describe('Without AP federation breaking changes enabled', function () {
|
||||
before(async function () {
|
||||
this.timeout(60000)
|
||||
|
||||
await servers[0].kill()
|
||||
await servers[0].run()
|
||||
})
|
||||
|
||||
it('Should not federate captions m3u8 URL', async function () {
|
||||
await renewVideo()
|
||||
await addCaptions()
|
||||
await waitJobs(servers)
|
||||
|
||||
{
|
||||
const { data: captions } = await servers[0].captions.list({ videoId: videoUUID })
|
||||
|
||||
for (const caption of captions) {
|
||||
expect(caption.fileUrl).to.exist
|
||||
expect(caption.m3u8Url).to.exist
|
||||
|
||||
await makeRawRequest({ url: caption.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: caption.m3u8Url, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const { data: captions } = await servers[1].captions.list({ videoId: videoUUID })
|
||||
|
||||
for (const caption of captions) {
|
||||
expect(caption.fileUrl).to.exist
|
||||
expect(caption.m3u8Url).to.not.exist
|
||||
|
||||
await makeRawRequest({ url: caption.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
after(async function () {
|
||||
await cleanupTests(servers)
|
||||
})
|
||||
|
||||
@@ -42,7 +42,6 @@ describe('Test video captions', function () {
|
||||
})
|
||||
|
||||
describe('Common on filesystem', function () {
|
||||
|
||||
it('Should list the captions and return an empty list', async function () {
|
||||
for (const server of servers) {
|
||||
const body = await server.captions.list({ videoId: videoUUID })
|
||||
@@ -79,7 +78,6 @@ describe('Test video captions', function () {
|
||||
const caption1 = body.data[0]
|
||||
expect(caption1.language.id).to.equal('ar')
|
||||
expect(caption1.language.label).to.equal('Arabic')
|
||||
expect(caption1.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
expect(caption1.fileUrl).to.match(new RegExp(`^${server.url}/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
expect(caption1.automaticallyGenerated).to.be.false
|
||||
await testCaptionFile(caption1.fileUrl, 'Subtitle good 1.')
|
||||
@@ -87,7 +85,6 @@ describe('Test video captions', function () {
|
||||
const caption2 = body.data[1]
|
||||
expect(caption2.language.id).to.equal('zh')
|
||||
expect(caption2.language.label).to.equal('Chinese')
|
||||
expect(caption2.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/${uuidRegex}-zh.vtt$`))
|
||||
expect(caption2.fileUrl).to.match(new RegExp(`^${server.url}/lazy-static/video-captions/${uuidRegex}-zh.vtt$`))
|
||||
expect(caption1.automaticallyGenerated).to.be.false
|
||||
await testCaptionFile(caption2.fileUrl, 'Subtitle good 2.')
|
||||
@@ -115,7 +112,6 @@ describe('Test video captions', function () {
|
||||
const caption1 = body.data[0]
|
||||
expect(caption1.language.id).to.equal('ar')
|
||||
expect(caption1.language.label).to.equal('Arabic')
|
||||
expect(caption1.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
expect(caption1.fileUrl).to.match(new RegExp(`^${server.url}/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
await testCaptionFile(caption1.fileUrl, 'Subtitle good 2.')
|
||||
}
|
||||
@@ -252,11 +248,9 @@ describe('Test video captions', function () {
|
||||
|
||||
if (server === servers[0]) {
|
||||
expectStartWith(caption1.fileUrl, objectStorage.getMockCaptionFileBaseUrl())
|
||||
expect(caption1.captionPath).to.be.null
|
||||
|
||||
oldFileUrlsAr.push(caption1.fileUrl)
|
||||
} else {
|
||||
expect(caption1.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
expect(caption1.fileUrl).to.match(new RegExp(`^${server.url}/lazy-static/video-captions/${uuidRegex}-ar.vtt$`))
|
||||
}
|
||||
|
||||
@@ -269,8 +263,6 @@ describe('Test video captions', function () {
|
||||
|
||||
if (server === servers[0]) {
|
||||
expectStartWith(caption2.fileUrl, objectStorage.getMockCaptionFileBaseUrl())
|
||||
expect(caption2.captionPath).to.be.null
|
||||
|
||||
oldFileUrlsZh.push(caption2.fileUrl)
|
||||
}
|
||||
|
||||
@@ -311,8 +303,6 @@ describe('Test video captions', function () {
|
||||
|
||||
if (server === servers[0]) {
|
||||
expectStartWith(caption.fileUrl, objectStorage.getMockCaptionFileBaseUrl())
|
||||
expect(caption.captionPath).to.be.null
|
||||
|
||||
oldFileUrlsAr.push(caption.fileUrl)
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ describe('Test video channels', function () {
|
||||
let accountName: string
|
||||
let secondUserChannelName: string
|
||||
|
||||
const avatarPaths: { [port: number]: string } = {}
|
||||
const bannerPaths: { [port: number]: string } = {}
|
||||
const avatarUrls: { [port: number]: string } = {}
|
||||
const bannerUrls: { [port: number]: string } = {}
|
||||
|
||||
before(async function () {
|
||||
this.timeout(60000)
|
||||
@@ -271,8 +271,6 @@ describe('Test video channels', function () {
|
||||
})
|
||||
|
||||
it('Should update video channel avatar', async function () {
|
||||
this.timeout(15000)
|
||||
|
||||
const fixture = 'avatar.png'
|
||||
|
||||
await servers[0].channels.updateImage({
|
||||
@@ -292,11 +290,11 @@ describe('Test video channels', function () {
|
||||
expect(videoChannel.avatars.length).to.equal(expectedSizes.length, 'Expected avatars to be generated in all sizes')
|
||||
|
||||
for (const avatar of videoChannel.avatars) {
|
||||
avatarPaths[server.port] = avatar.path
|
||||
await testImage({ url: server.url + avatarPaths[server.port], name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarPaths[server.port]), true)
|
||||
avatarUrls[server.port] = avatar.fileUrl
|
||||
await testImage({ url: avatarUrls[server.port], name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarUrls[server.port]), true)
|
||||
|
||||
const row = await sqlCommands[i].getActorImage(basename(avatarPaths[server.port]))
|
||||
const row = await sqlCommands[i].getActorImage(basename(avatarUrls[server.port]))
|
||||
|
||||
expect(expectedSizes.some(({ height, width }) => row.height === height && row.width === width)).to.equal(true)
|
||||
}
|
||||
@@ -325,11 +323,11 @@ describe('Test video channels', function () {
|
||||
expect(videoChannel.banners.length).to.equal(expectedSizes.length, 'Expected banners to be generated in all sizes')
|
||||
|
||||
for (const banner of videoChannel.banners) {
|
||||
bannerPaths[server.port] = banner.path
|
||||
await testImage({ url: server.url + bannerPaths[server.port], name: `banner-resized-${banner.width}.jpg` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerPaths[server.port]), true)
|
||||
bannerUrls[server.port] = banner.fileUrl
|
||||
await testImage({ url: bannerUrls[server.port], name: `banner-resized-${banner.width}.jpg` })
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerUrls[server.port]), true)
|
||||
|
||||
const row = await sqlCommands[i].getActorImage(basename(bannerPaths[server.port]))
|
||||
const row = await sqlCommands[i].getActorImage(basename(bannerUrls[server.port]))
|
||||
expect(expectedSizes.some(({ height, width }) => row.height === height && row.width === width)).to.equal(true)
|
||||
}
|
||||
}
|
||||
@@ -361,7 +359,7 @@ describe('Test video channels', function () {
|
||||
|
||||
for (const server of servers) {
|
||||
const videoChannel = await findChannel(server, secondVideoChannelId)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarPaths[server.port]), false)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(avatarUrls[server.port]), false)
|
||||
|
||||
expect(videoChannel.avatars).to.be.empty
|
||||
}
|
||||
@@ -376,7 +374,7 @@ describe('Test video channels', function () {
|
||||
|
||||
for (const server of servers) {
|
||||
const videoChannel = await findChannel(server, secondVideoChannelId)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerPaths[server.port]), false)
|
||||
await testFileExistsOnFSOrNot(server, 'avatars', basename(bannerUrls[server.port]), false)
|
||||
|
||||
expect(videoChannel.banners).to.be.empty
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ describe('Test video comments', function () {
|
||||
expect(comment.account.host).to.equal(server.host)
|
||||
|
||||
for (const avatar of comment.account.avatars) {
|
||||
await testImage({ url: server.url + avatar.path, name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
await testImage({ url: avatar.fileUrl, name: `avatar-resized-${avatar.width}x${avatar.width}.png` })
|
||||
}
|
||||
|
||||
expect(comment.totalReplies).to.equal(0)
|
||||
@@ -414,7 +414,6 @@ describe('Test video comments', function () {
|
||||
|
||||
it('Should start with 0 comments', async function () {
|
||||
const video = await server.videos.get({ id: testVideoUUID })
|
||||
expect(video.commentsEnabled).to.be.true
|
||||
expect(video.comments).to.equal(0)
|
||||
})
|
||||
|
||||
|
||||
@@ -144,7 +144,7 @@ describe('Test video imports', function () {
|
||||
const enCaption = videoCaptions.find(caption => caption.language.id === 'en')
|
||||
expect(enCaption).to.exist
|
||||
expect(enCaption.language.label).to.equal('English')
|
||||
expect(enCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-en.vtt$`))
|
||||
expect(enCaption.fileUrl).to.match(new RegExp(`^${servers[0].url}/lazy-static/video-captions/.+-en.vtt$`))
|
||||
|
||||
const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` +
|
||||
`(Language: en[ \n]+)?` +
|
||||
@@ -158,7 +158,7 @@ describe('Test video imports', function () {
|
||||
const frCaption = videoCaptions.find(caption => caption.language.id === 'fr')
|
||||
expect(frCaption).to.exist
|
||||
expect(frCaption.language.label).to.equal('French')
|
||||
expect(frCaption.captionPath).to.match(new RegExp(`^/lazy-static/video-captions/.+-fr.vtt`))
|
||||
expect(frCaption.fileUrl).to.match(new RegExp(`^${servers[0].url}/lazy-static/video-captions/.+-fr.vtt`))
|
||||
|
||||
const regex = `WEBVTT[ \n]+Kind: captions[ \n]+` +
|
||||
`(Language: fr[ \n]+)?` +
|
||||
|
||||
@@ -7,7 +7,8 @@ import {
|
||||
PeerTubeServer,
|
||||
cleanupTests,
|
||||
createMultipleServers,
|
||||
doubleFollow, makeGetRequest,
|
||||
doubleFollow,
|
||||
makeGetRequest,
|
||||
makeRawRequest,
|
||||
setAccessTokensToServers,
|
||||
setDefaultAccountAvatar,
|
||||
@@ -61,7 +62,6 @@ describe('Test video source management', function () {
|
||||
await waitJobs(servers)
|
||||
|
||||
const source = await servers[0].videos.getSource({ id: uuid })
|
||||
expect(source.filename).to.equal(fixture1)
|
||||
expect(source.inputFilename).to.equal(fixture1)
|
||||
expect(source.fileDownloadUrl).to.be.null
|
||||
|
||||
@@ -89,7 +89,6 @@ describe('Test video source management', function () {
|
||||
await waitJobs(servers)
|
||||
|
||||
const source = await servers[0].videos.getSource({ id: uuid })
|
||||
expect(source.filename).to.equal(fixture2)
|
||||
expect(source.inputFilename).to.equal(fixture2)
|
||||
expect(source.fileDownloadUrl).to.exist
|
||||
|
||||
@@ -207,9 +206,7 @@ describe('Test video source management', function () {
|
||||
})
|
||||
|
||||
describe('Updating video source', function () {
|
||||
|
||||
describe('Filesystem', function () {
|
||||
|
||||
it('Should replace a video file with transcoding disabled', async function () {
|
||||
this.timeout(120000)
|
||||
|
||||
@@ -245,7 +242,7 @@ describe('Test video source management', function () {
|
||||
it('Should replace a video file with transcoding enabled', async function () {
|
||||
this.timeout(240000)
|
||||
|
||||
const previousPaths: string[] = []
|
||||
const previousUrls: string[] = []
|
||||
|
||||
await servers[0].config.enableTranscoding({ hls: true, webVideo: true, with0p: true, keepOriginal: true, resolutions: 'max' })
|
||||
|
||||
@@ -266,21 +263,21 @@ describe('Test video source management', function () {
|
||||
|
||||
// Grab old paths to ensure we'll regenerate
|
||||
|
||||
previousPaths.push(video.previewPath)
|
||||
previousPaths.push(video.thumbnailPath)
|
||||
previousUrls.push(video.previewPath)
|
||||
previousUrls.push(video.thumbnailPath)
|
||||
|
||||
for (const file of files) {
|
||||
previousPaths.push(file.fileUrl)
|
||||
previousPaths.push(file.torrentUrl)
|
||||
previousPaths.push(file.metadataUrl)
|
||||
previousUrls.push(file.fileUrl)
|
||||
previousUrls.push(file.torrentUrl)
|
||||
previousUrls.push(file.metadataUrl)
|
||||
|
||||
const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
|
||||
previousPaths.push(JSON.stringify(metadata))
|
||||
previousUrls.push(JSON.stringify(metadata))
|
||||
}
|
||||
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
for (const s of storyboards) {
|
||||
previousPaths.push(s.storyboardPath)
|
||||
previousUrls.push(s.fileUrl)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,29 +309,29 @@ describe('Test video source management', function () {
|
||||
const files = getAllFiles(video)
|
||||
expect(files).to.have.lengthOf(4 * 2)
|
||||
|
||||
expect(previousPaths).to.not.include(video.previewPath)
|
||||
expect(previousPaths).to.not.include(video.thumbnailPath)
|
||||
expect(previousUrls).to.not.include(server.url + video.previewPath)
|
||||
expect(previousUrls).to.not.include(server.url + video.thumbnailPath)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: video.previewPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeGetRequest({ url: server.url, path: video.thumbnailPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
|
||||
for (const file of files) {
|
||||
expect(previousPaths).to.not.include(file.fileUrl)
|
||||
expect(previousPaths).to.not.include(file.torrentUrl)
|
||||
expect(previousPaths).to.not.include(file.metadataUrl)
|
||||
expect(previousUrls).to.not.include(file.fileUrl)
|
||||
expect(previousUrls).to.not.include(file.torrentUrl)
|
||||
expect(previousUrls).to.not.include(file.metadataUrl)
|
||||
|
||||
await makeRawRequest({ url: file.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: file.torrentUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
|
||||
const metadata = await server.videos.getFileMetadata({ url: file.metadataUrl })
|
||||
expect(previousPaths).to.not.include(JSON.stringify(metadata))
|
||||
expect(previousUrls).to.not.include(JSON.stringify(metadata))
|
||||
}
|
||||
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
for (const s of storyboards) {
|
||||
expect(previousPaths).to.not.include(s.storyboardPath)
|
||||
expect(previousUrls).to.not.include(s.fileUrl)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: s.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: s.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +363,6 @@ describe('Test video source management', function () {
|
||||
it('Should have the correct source input filename', async function () {
|
||||
const source = await servers[0].videos.getSource({ id: uuid })
|
||||
|
||||
expect(source.filename).to.equal('video_short_360p.mp4')
|
||||
expect(source.inputFilename).to.equal('video_short_360p.mp4')
|
||||
expect(new Date(source.createdAt)).to.be.above(replaceDate)
|
||||
})
|
||||
@@ -438,7 +434,6 @@ describe('Test video source management', function () {
|
||||
})
|
||||
|
||||
describe('Autoblacklist', function () {
|
||||
|
||||
async function expectBlacklist (uuid: string, value: boolean) {
|
||||
const video = await servers[0].videos.getWithToken({ id: uuid })
|
||||
|
||||
|
||||
@@ -158,11 +158,10 @@ describe('Test video storyboard', function () {
|
||||
this.timeout(60000)
|
||||
|
||||
const { storyboards } = await servers[0].storyboard.list({ id: baseUUID })
|
||||
const storyboardName = basename(storyboards[0].storyboardPath)
|
||||
const storyboardName = basename(storyboards[0].fileUrl)
|
||||
|
||||
const listFiles = () => {
|
||||
const storyboardPath = servers[0].getDirectoryPath('storyboards')
|
||||
return readdir(storyboardPath)
|
||||
return readdir(servers[0].getDirectoryPath('storyboards'))
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import { expect } from 'chai'
|
||||
import { remove } from 'fs-extra/esm'
|
||||
import { readdir } from 'fs/promises'
|
||||
import { join } from 'path'
|
||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||
import {
|
||||
cleanupTests,
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
makeGetRequest,
|
||||
makeRawRequest,
|
||||
PeerTubeServer,
|
||||
setAccessTokensToServers,
|
||||
waitJobs
|
||||
} from '@peertube/peertube-server-commands'
|
||||
import { expect } from 'chai'
|
||||
import { remove } from 'fs-extra/esm'
|
||||
import { readdir } from 'fs/promises'
|
||||
import { join } from 'path'
|
||||
import { SQLCommand } from '../shared/sql-command.js'
|
||||
|
||||
function listStoryboardFiles (server: PeerTubeServer) {
|
||||
@@ -84,7 +84,7 @@ describe('Test create generate storyboard job CLI', function () {
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
expect(storyboards).to.have.lengthOf(1)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: storyboards[0].fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -108,7 +108,7 @@ describe('Test create generate storyboard job CLI', function () {
|
||||
const { storyboards } = await server.storyboard.list({ id: uuid })
|
||||
expect(storyboards).to.have.lengthOf(1)
|
||||
|
||||
await makeGetRequest({ url: server.url, path: storyboards[0].storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: storyboards[0].fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
makeGetRequest,
|
||||
makeRawRequest,
|
||||
setAccessTokensToServers,
|
||||
setDefaultAccountAvatar,
|
||||
setDefaultChannelAvatar,
|
||||
@@ -39,7 +40,7 @@ describe('House keeping CLI', function () {
|
||||
|
||||
for (const { avatars } of [ ...accounts, ...channels ]) {
|
||||
for (const avatar of avatars) {
|
||||
await makeGetRequest({ url: servers[0].url, path: avatar.path, expectedStatus: HttpStatusCode.OK_200 })
|
||||
await makeRawRequest({ url: avatar.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
createMultipleServers,
|
||||
doubleFollow,
|
||||
killallServers,
|
||||
makeGetRequest,
|
||||
makeRawRequest,
|
||||
setAccessTokensToServers,
|
||||
setDefaultVideoChannel,
|
||||
@@ -76,22 +75,14 @@ describe('Test prune storage CLI', function () {
|
||||
const account = await servers[0].accounts.get({ accountName: 'root@' + servers[1].host })
|
||||
|
||||
for (const avatar of account.avatars) {
|
||||
await makeGetRequest({
|
||||
url: servers[0].url,
|
||||
path: avatar.path,
|
||||
expectedStatus: HttpStatusCode.OK_200
|
||||
})
|
||||
await makeRawRequest({ url: avatar.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
const account = await servers[1].accounts.get({ accountName: 'root@' + servers[0].host })
|
||||
for (const avatar of account.avatars) {
|
||||
await makeGetRequest({
|
||||
url: servers[1].url,
|
||||
path: avatar.path,
|
||||
expectedStatus: HttpStatusCode.OK_200
|
||||
})
|
||||
await makeRawRequest({ url: avatar.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,9 +261,9 @@ describe('Test prune storage CLI', function () {
|
||||
|
||||
const objectStorage = new ObjectStorageCommand()
|
||||
|
||||
const videoFileUrls: { [ uuid: string ]: string[] } = {}
|
||||
const sourceFileUrls: { [ uuid: string ]: string } = {}
|
||||
const captionFileUrls: { [ uuid: string ]: { [ language: string ]: string } } = {}
|
||||
const videoFileUrls: { [uuid: string]: string[] } = {}
|
||||
const sourceFileUrls: { [uuid: string]: string } = {}
|
||||
const captionFileUrls: { [uuid: string]: { [language: string]: string } } = {}
|
||||
|
||||
let sqlCommand: SQLCommand
|
||||
let rootId: number
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-unused-expressions,@typescript-eslint/require-await */
|
||||
|
||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||
import { makeGetRequest, makeRawRequest, PeerTubeServer } from '@peertube/peertube-server-commands'
|
||||
import { makeRawRequest, PeerTubeServer } from '@peertube/peertube-server-commands'
|
||||
import { expect } from 'chai'
|
||||
|
||||
export async function checkStoryboard (options: {
|
||||
@@ -23,18 +23,13 @@ export async function checkStoryboard (options: {
|
||||
expect(storyboard.spriteDuration).to.equal(spriteDuration)
|
||||
expect(storyboard.spriteHeight).to.equal(spriteHeight)
|
||||
expect(storyboard.spriteWidth).to.equal(spriteWidth)
|
||||
expect(storyboard.storyboardPath).to.exist
|
||||
expect(storyboard.fileUrl).to.exist
|
||||
|
||||
if (tilesCount) {
|
||||
expect(storyboard.totalWidth).to.equal(spriteWidth * Math.min(tilesCount, 11))
|
||||
expect(storyboard.totalHeight).to.equal(spriteHeight * Math.max(tilesCount / 11, 1))
|
||||
}
|
||||
|
||||
{
|
||||
const { body } = await makeGetRequest({ url: server.url, path: storyboard.storyboardPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
expect(body.length).to.be.above(minSize)
|
||||
}
|
||||
|
||||
{
|
||||
const { body } = await makeRawRequest({ url: storyboard.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
expect(body.length).to.be.above(minSize)
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||
import { buildAbsoluteFixturePath } from '@peertube/peertube-node-utils'
|
||||
import { makeGetRequest, PeerTubeServer, VideoEdit } from '@peertube/peertube-server-commands'
|
||||
import { makeRawRequest, PeerTubeServer, VideoEdit } from '@peertube/peertube-server-commands'
|
||||
import { downloadFile, unzip } from '@peertube/peertube-transcription-devtools'
|
||||
import { expect } from 'chai'
|
||||
import { ensureDir, pathExists } from 'fs-extra/esm'
|
||||
import { join } from 'path'
|
||||
import { testCaptionFile } from './captions.js'
|
||||
import { FIXTURE_URLS } from './fixture-urls.js'
|
||||
import { expectStartWith } from './checks.js'
|
||||
import { FIXTURE_URLS } from './fixture-urls.js'
|
||||
|
||||
type CustomModelName = 'tiny.pt' | 'faster-whisper-tiny'
|
||||
|
||||
@@ -78,7 +78,7 @@ export async function getCaptionContent (server: PeerTubeServer, videoId: string
|
||||
|
||||
const caption = data.find(c => c.language.id === language)
|
||||
|
||||
const { text } = await makeGetRequest({ url: server.url, path: caption.captionPath, expectedStatus: HttpStatusCode.OK_200 })
|
||||
const { text } = await makeRawRequest({ url: caption.fileUrl, expectedStatus: HttpStatusCode.OK_200 })
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import {
|
||||
HttpStatusCode,
|
||||
HttpStatusCodeType,
|
||||
VideoCaption,
|
||||
VideoCommentPolicy,
|
||||
VideoCommentPolicyType,
|
||||
VideoDetails,
|
||||
VideoPrivacy,
|
||||
@@ -28,8 +27,8 @@ import { readdir, writeFile } from 'fs/promises'
|
||||
import { tmpdir } from 'os'
|
||||
import { basename, join } from 'path'
|
||||
import { dateIsValid, expectStartWith, testImageGeneratedByFFmpeg } from './checks.js'
|
||||
import { completeCheckHlsPlaylist } from './streaming-playlists.js'
|
||||
import { checkWebTorrentWorks } from './p2p.js'
|
||||
import { completeCheckHlsPlaylist } from './streaming-playlists.js'
|
||||
|
||||
export async function completeWebVideoFilesCheck (options: {
|
||||
server: PeerTubeServer
|
||||
@@ -242,7 +241,6 @@ export async function completeVideoCheck (options: {
|
||||
expect(video.url).to.contain(originServer.host)
|
||||
expect(video.tags).to.deep.equal(attributes.tags)
|
||||
|
||||
expect(video.commentsEnabled).to.equal(attributes.commentsPolicy !== VideoCommentPolicy.DISABLED)
|
||||
expect(video.commentsPolicy.id).to.equal(attributes.commentsPolicy)
|
||||
expect(video.downloadEnabled).to.equal(attributes.downloadEnabled)
|
||||
|
||||
@@ -318,12 +316,12 @@ export async function checkVideoFilesWereRemoved (options: {
|
||||
|
||||
const torrentNames = webVideoFiles.concat(hlsFiles).map(f => basename(f.torrentUrl))
|
||||
|
||||
const captionNames = captions.map(c => basename(c.captionPath))
|
||||
const captionNames = captions.map(c => basename(c.fileUrl))
|
||||
|
||||
const webVideoFilenames = webVideoFiles.map(f => basename(f.fileUrl))
|
||||
const hlsFilenames = hlsFiles.map(f => basename(f.fileUrl))
|
||||
|
||||
let directories: { [ directory: string ]: string[] } = {
|
||||
let directories: { [directory: string]: string[] } = {
|
||||
videos: webVideoFilenames,
|
||||
redundancy: webVideoFilenames,
|
||||
[join('playlists', 'hls')]: hlsFilenames,
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
NSFWFlag,
|
||||
ThumbnailType,
|
||||
VideoChannelActivityAction,
|
||||
VideoCommentPolicy,
|
||||
VideoPrivacy,
|
||||
VideoPrivacyType,
|
||||
VideoUpdate
|
||||
@@ -21,6 +20,7 @@ import { VideoPathManager } from '@server/lib/video-path-manager.js'
|
||||
import { setVideoPrivacy } from '@server/lib/video-privacy.js'
|
||||
import { setVideoTags } from '@server/lib/video.js'
|
||||
import { openapiOperationDoc } from '@server/middlewares/doc.js'
|
||||
import { VideoChannelActivityModel } from '@server/models/video/video-channel-activity.js'
|
||||
import { VideoPasswordModel } from '@server/models/video/video-password.js'
|
||||
import { FilteredModelAttributes } from '@server/types/index.js'
|
||||
import { MVideoFullLight, MVideoThumbnail } from '@server/types/models/index.js'
|
||||
@@ -37,7 +37,6 @@ import { autoBlacklistVideoIfNeeded } from '../../../lib/video-blacklist.js'
|
||||
import { asyncMiddleware, asyncRetryTransactionMiddleware, authenticate, videosUpdateValidator } from '../../../middlewares/index.js'
|
||||
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update.js'
|
||||
import { VideoModel } from '../../../models/video/video.js'
|
||||
import { VideoChannelActivityModel } from '@server/models/video/video-channel-activity.js'
|
||||
|
||||
const lTags = loggerTagsFactory('api', 'video')
|
||||
const auditLogger = auditLoggerFactory('videos')
|
||||
@@ -106,13 +105,8 @@ async function updateVideo (req: express.Request, res: express.Response) {
|
||||
video.nsfwSummary = null
|
||||
}
|
||||
|
||||
// Special treatment for comments policy to support deprecated commentsEnabled attribute
|
||||
if (body.commentsPolicy !== undefined) {
|
||||
video.commentsPolicy = body.commentsPolicy
|
||||
} else if (body.commentsEnabled === true) {
|
||||
video.commentsPolicy = VideoCommentPolicy.ENABLED
|
||||
} else if (body.commentsEnabled === false) {
|
||||
video.commentsPolicy = VideoCommentPolicy.DISABLED
|
||||
}
|
||||
|
||||
if (body.originallyPublishedAt !== undefined) {
|
||||
|
||||
@@ -151,12 +151,6 @@ const contextStore: { [id in ContextType]: (string | { [id: string]: string })[]
|
||||
'@id': 'pt:fps'
|
||||
},
|
||||
|
||||
// Keep for federation compatibility
|
||||
commentsEnabled: {
|
||||
'@type': 'sc:Boolean',
|
||||
'@id': 'pt:commentsEnabled'
|
||||
},
|
||||
|
||||
canReply: 'pt:canReply',
|
||||
commentsPolicy: {
|
||||
'@type': 'sc:Number',
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { CacheFileObject } from '@peertube/peertube-models'
|
||||
import { MIMETYPES } from '@server/initializers/constants.js'
|
||||
import validator from 'validator'
|
||||
import { isDateValid } from '../misc.js'
|
||||
import { isActivityPubUrlValid } from './misc.js'
|
||||
import { isRemoteVideoUrlValid } from './videos.js'
|
||||
|
||||
export function isCacheFileObjectValid (object: CacheFileObject) {
|
||||
if (object?.type !== 'CacheFile') return false
|
||||
@@ -20,14 +19,6 @@ function isPlaylistRedundancyUrlValid (url: any) {
|
||||
isActivityPubUrlValid(url.href)
|
||||
}
|
||||
|
||||
// TODO: compat with < 6.1, use isRemoteVideoUrlValid instead in 8.0
|
||||
function isRedundancyUrlVideoValid (url: any) {
|
||||
const size = url.size || url['_:size']
|
||||
const fps = url.fps || url['_fps']
|
||||
|
||||
return MIMETYPES.AP_VIDEO.MIMETYPE_EXT[url.mediaType] &&
|
||||
isActivityPubUrlValid(url.href) &&
|
||||
validator.default.isInt(url.height + '', { min: 0 }) &&
|
||||
validator.default.isInt(size + '', { min: 0 }) &&
|
||||
(!fps || validator.default.isInt(fps + '', { min: -1 }))
|
||||
return isRemoteVideoUrlValid(url)
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@ import { isActivityPubUrlValid } from './misc.js'
|
||||
export function isPlaylistObjectValid (object: PlaylistObject) {
|
||||
if (object?.type !== 'Playlist') return false
|
||||
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
if (!object.uuid && object['identifier']) object.uuid = object['identifier']
|
||||
|
||||
return validator.default.isInt(object.totalItems + '') &&
|
||||
isVideoPlaylistNameValid(object.name) &&
|
||||
isUUIDValid(object.uuid) &&
|
||||
|
||||
@@ -49,9 +49,6 @@ export function sanitizeAndCheckVideoTorrentObject (video: VideoObject) {
|
||||
if (!setValidStoryboard(video)) return fail('preview (storyboard)')
|
||||
if (!setValidLicence(video)) return fail('licence')
|
||||
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
if (!video.uuid && video['identifier']) video.uuid = video['identifier']
|
||||
|
||||
// Default attributes
|
||||
if (!isVideoStateValid(video.state)) video.state = VideoState.PUBLISHED
|
||||
if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
|
||||
@@ -66,8 +63,6 @@ export function sanitizeAndCheckVideoTorrentObject (video: VideoObject) {
|
||||
if (!isVideoCommentsPolicyValid(video.commentsPolicy)) {
|
||||
video.commentsPolicy = VideoCommentPolicy.DISABLED
|
||||
}
|
||||
} else if (video.commentsEnabled === true) { // Fallback to deprecated attribute
|
||||
video.commentsPolicy = VideoCommentPolicy.ENABLED
|
||||
} else {
|
||||
video.commentsPolicy = VideoCommentPolicy.DISABLED
|
||||
}
|
||||
@@ -167,21 +162,7 @@ function setValidRemoteCaptions (video: VideoObject) {
|
||||
if (Array.isArray(video.subtitleLanguage) === false) return false
|
||||
|
||||
video.subtitleLanguage = video.subtitleLanguage.filter(caption => {
|
||||
if (typeof caption.url === 'string') {
|
||||
if (isActivityPubUrlValid(caption.url)) {
|
||||
caption.url = [
|
||||
{
|
||||
type: 'Link',
|
||||
href: caption.url,
|
||||
mediaType: 'text/vtt'
|
||||
}
|
||||
]
|
||||
} else {
|
||||
caption.url = []
|
||||
}
|
||||
} else {
|
||||
caption.url = arrayify(caption.url).filter(u => isAPCaptionUrlObject(u))
|
||||
}
|
||||
caption.url = arrayify(caption.url).filter(u => isAPCaptionUrlObject(u))
|
||||
|
||||
return isRemoteStringIdentifierValid(caption)
|
||||
})
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { arrayify } from '@peertube/peertube-core-utils'
|
||||
import { WatchActionObject } from '@peertube/peertube-models'
|
||||
import { isDateValid, isUUIDValid } from '../misc.js'
|
||||
import { isVideoTimeValid } from '../video-view.js'
|
||||
@@ -7,12 +6,6 @@ import { isActivityPubVideoDurationValid, isObjectValid } from './misc.js'
|
||||
function isWatchActionObjectValid (action: WatchActionObject) {
|
||||
if (action?.type !== 'WatchAction') return false
|
||||
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
if (!action.uuid && action['identifier']) action.uuid = action['identifier']
|
||||
|
||||
if (action['_:actionStatus'] && !action.actionStatus) action.actionStatus = action['_:actionStatus']
|
||||
if (action['_:watchSections'] && !action.watchSections) action.watchSections = arrayify(action['_:watchSections'])
|
||||
|
||||
return isObjectValid(action.id) &&
|
||||
isActivityPubVideoDurationValid(action.duration) &&
|
||||
isDateValid(action.startTime) &&
|
||||
@@ -43,9 +36,6 @@ function isLocationValid (location: any) {
|
||||
|
||||
function areWatchSectionsValid (sections: WatchActionObject['watchSections']) {
|
||||
return Array.isArray(sections) && sections.every(s => {
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
if (s['_:endTimestamp'] && !s.endTimestamp) s.endTimestamp = s['_:endTimestamp']
|
||||
|
||||
return isVideoTimeValid(s.startTimestamp) && isVideoTimeValid(s.endTimestamp)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -34,18 +34,9 @@ export async function compactJSONLDAndCheckRSA2017Signature (fromActor: MActor,
|
||||
return false
|
||||
}
|
||||
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
let safe = true
|
||||
if (
|
||||
(compacted.type === 'Create' && (compacted?.object?.type === 'WatchAction' || compacted?.object?.type === 'CacheFile')) ||
|
||||
(compacted.type === 'Undo' && compacted?.object?.type === 'Create' && compacted?.object?.object.type === 'CacheFile')
|
||||
) {
|
||||
safe = false
|
||||
}
|
||||
|
||||
const [ documentHash, optionsHash ] = await Promise.all([
|
||||
hashObject(compacted, safe),
|
||||
createSignatureHash(req.body.signature, safe)
|
||||
hashObject(compacted),
|
||||
createSignatureHash(req.body.signature)
|
||||
])
|
||||
|
||||
const toVerify = optionsHash + documentHash
|
||||
@@ -88,7 +79,7 @@ function fixCompacted (original: any, compacted: any) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function signJsonLDObject <T> (options: {
|
||||
export async function signJsonLDObject<T> (options: {
|
||||
byActor: { url: string, privateKey: string }
|
||||
data: T
|
||||
disableWorkerThreadAssertion?: boolean
|
||||
@@ -123,8 +114,8 @@ export async function signJsonLDObject <T> (options: {
|
||||
// Private
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
async function hashObject (obj: any, safe: boolean): Promise<any> {
|
||||
const res = await jsonldNormalize(obj, safe)
|
||||
async function hashObject (obj: any): Promise<any> {
|
||||
const res = await jsonldNormalize(obj)
|
||||
|
||||
return sha256(res)
|
||||
}
|
||||
@@ -133,9 +124,9 @@ function jsonldCompact (obj: any) {
|
||||
return (jsonld as any).promises.compact(obj, getAllContext())
|
||||
}
|
||||
|
||||
function jsonldNormalize (obj: any, safe: boolean) {
|
||||
function jsonldNormalize (obj: any) {
|
||||
return (jsonld as any).promises.normalize(obj, {
|
||||
safe,
|
||||
safe: true,
|
||||
algorithm: 'URDNA2015',
|
||||
format: 'application/n-quads'
|
||||
})
|
||||
@@ -143,7 +134,7 @@ function jsonldNormalize (obj: any, safe: boolean) {
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function createSignatureHash (signature: any, safe = true) {
|
||||
function createSignatureHash (signature: any) {
|
||||
return hashObject({
|
||||
'@context': [
|
||||
'https://w3id.org/security/v1',
|
||||
@@ -151,12 +142,12 @@ function createSignatureHash (signature: any, safe = true) {
|
||||
],
|
||||
|
||||
...omit(signature, [ 'type', 'id', 'signatureValue' ])
|
||||
}, safe)
|
||||
})
|
||||
}
|
||||
|
||||
function createDocWithoutSignatureHash (doc: any) {
|
||||
const docWithoutSignature = cloneDeep(doc)
|
||||
delete docWithoutSignature.signature
|
||||
|
||||
return hashObject(docWithoutSignature, true)
|
||||
return hashObject(docWithoutSignature)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { ActivityPubActor, ActorImageType } from '@peertube/peertube-models'
|
||||
import { resetSequelizeInstance, runInReadCommittedTransaction } from '@server/helpers/database-utils.js'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { AccountModel } from '@server/models/account/account.js'
|
||||
import { VideoChannelModel } from '@server/models/video/video-channel.js'
|
||||
import { MAccount, MActor, MActorFull, MChannel } from '@server/types/models/index.js'
|
||||
import { upsertAPPlayerSettings } from '../player-settings.js'
|
||||
@@ -31,18 +30,21 @@ export class APActorUpdater {
|
||||
this.accountOrChannel.name = this.actorObject.name || this.actorObject.preferredUsername
|
||||
this.accountOrChannel.description = this.actorObject.summary
|
||||
|
||||
if (this.accountOrChannel instanceof VideoChannelModel) {
|
||||
const owner = await getOrCreateAPOwner(this.actorObject, this.actorObject.id)
|
||||
this.accountOrChannel.accountId = owner.Account.id
|
||||
this.accountOrChannel.Account = owner.Account as AccountModel
|
||||
const accountOrChannel = this.accountOrChannel
|
||||
|
||||
this.accountOrChannel.support = this.actorObject.support
|
||||
if (accountOrChannel instanceof VideoChannelModel) {
|
||||
const channel = accountOrChannel as MChannel
|
||||
|
||||
const owner = await getOrCreateAPOwner(this.actorObject, this.actorObject.id)
|
||||
|
||||
channel.accountId = owner.Account.id
|
||||
channel.support = this.actorObject.support
|
||||
|
||||
if (typeof this.actorObject.playerSettings === 'string') {
|
||||
await upsertAPPlayerSettings({
|
||||
settingsObject: this.actorObject.playerSettings,
|
||||
video: undefined,
|
||||
channel: this.accountOrChannel,
|
||||
channel: Object.assign(channel, { Account: owner.Account, Actor: this.actor }),
|
||||
contextUrl: this.actor.url
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { VideoViewsManager } from '@server/lib/views/video-views-manager.js'
|
||||
import { ActivityView } from '@peertube/peertube-models'
|
||||
import { VideoViewsManager } from '@server/lib/views/video-views-manager.js'
|
||||
import { APProcessorOptions } from '../../../types/activitypub-processor.model.js'
|
||||
import { MActorSignature } from '../../../types/models/index.js'
|
||||
import { forwardVideoRelatedActivity } from '../send/shared/send-utils.js'
|
||||
@@ -32,8 +32,8 @@ async function processCreateView (activity: ActivityView, byActor: MActorSignatu
|
||||
video,
|
||||
viewerId: activity.id,
|
||||
|
||||
viewerExpires: getExpires(activity)
|
||||
? new Date(getExpires(activity))
|
||||
viewerExpires: activity.expires
|
||||
? new Date(activity.expires)
|
||||
: undefined,
|
||||
viewerResultCounter: getViewerResultCounter(activity)
|
||||
})
|
||||
@@ -49,15 +49,10 @@ async function processCreateView (activity: ActivityView, byActor: MActorSignatu
|
||||
function getViewerResultCounter (activity: ActivityView) {
|
||||
const result = activity.result
|
||||
|
||||
if (!getExpires(activity) || result?.interactionType !== 'WatchAction' || result?.type !== 'InteractionCounter') return undefined
|
||||
if (!activity.expires || result?.interactionType !== 'WatchAction' || result?.type !== 'InteractionCounter') return undefined
|
||||
|
||||
const counter = parseInt(result.userInteractionCount + '')
|
||||
if (isNaN(counter)) return undefined
|
||||
|
||||
return counter
|
||||
}
|
||||
|
||||
// TODO: compat with < 6.1, remove in 8.0
|
||||
function getExpires (activity: ActivityView) {
|
||||
return activity.expires || activity['expiration'] as string
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { arrayify, maxBy, minBy } from '@peertube/peertube-core-utils'
|
||||
import {
|
||||
ActivityCaptionUrlObject,
|
||||
ActivityHashTagObject,
|
||||
ActivityMagnetUrlObject,
|
||||
ActivityPlaylistSegmentHashesObject,
|
||||
@@ -226,8 +225,7 @@ export function getLiveSchedulesAttributesFromObject (live: MVideoLive, videoObj
|
||||
export function getCaptionAttributesFromObject (video: MVideoId, videoObject: VideoObject) {
|
||||
return videoObject.subtitleLanguage.map(c => {
|
||||
// This field is sanitized in validators
|
||||
// TODO: Remove as in v8
|
||||
const url = c.url as (ActivityCaptionUrlObject | ActivityPlaylistUrlObject)[]
|
||||
const url = c.url
|
||||
|
||||
const filename = VideoCaptionModel.generateCaptionName(c.identifier)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { escapeHTML, getChannelRSSFeeds, getDefaultRSSFeeds, maxBy } from '@peertube/peertube-core-utils'
|
||||
import { escapeHTML, getChannelRSSFeeds, getDefaultRSSFeed, maxBy } from '@peertube/peertube-core-utils'
|
||||
import { HttpStatusCode } from '@peertube/peertube-models'
|
||||
import { WEBSERVER } from '@server/initializers/constants.js'
|
||||
import { AccountModel } from '@server/models/account/account.js'
|
||||
@@ -16,7 +16,7 @@ export class ActorHtml {
|
||||
|
||||
return this.getAccountOrChannelHTMLPage({
|
||||
loader: () => accountModelPromise,
|
||||
getRSSFeeds: () => getDefaultRSSFeeds(WEBSERVER.URL, CONFIG.INSTANCE.NAME),
|
||||
getRSSFeeds: () => this.getDefaultRSSFeeds(req),
|
||||
req,
|
||||
res
|
||||
})
|
||||
@@ -27,7 +27,7 @@ export class ActorHtml {
|
||||
|
||||
return this.getAccountOrChannelHTMLPage({
|
||||
loader: () => Promise.resolve(videoChannel),
|
||||
getRSSFeeds: () => getChannelRSSFeeds(WEBSERVER.URL, CONFIG.INSTANCE.NAME, videoChannel),
|
||||
getRSSFeeds: () => this.getChannelRSSFeeds(videoChannel, req),
|
||||
req,
|
||||
res
|
||||
})
|
||||
@@ -44,8 +44,8 @@ export class ActorHtml {
|
||||
|
||||
getRSSFeeds: () =>
|
||||
account
|
||||
? getDefaultRSSFeeds(WEBSERVER.URL, CONFIG.INSTANCE.NAME)
|
||||
: getChannelRSSFeeds(WEBSERVER.URL, CONFIG.INSTANCE.NAME, channel),
|
||||
? this.getDefaultRSSFeeds(req)
|
||||
: this.getChannelRSSFeeds(channel, req),
|
||||
|
||||
req,
|
||||
res
|
||||
@@ -116,4 +116,25 @@ export class ActorHtml {
|
||||
|
||||
return customHTML
|
||||
}
|
||||
|
||||
private static getDefaultRSSFeeds (req: express.Request) {
|
||||
return [
|
||||
getDefaultRSSFeed({
|
||||
url: WEBSERVER.URL,
|
||||
title: req.t('{instanceName} videos feed', { instanceName: CONFIG.INSTANCE.NAME })
|
||||
})
|
||||
]
|
||||
}
|
||||
|
||||
private static getChannelRSSFeeds (channel: MChannelDefault, req: express.Request) {
|
||||
return getChannelRSSFeeds({
|
||||
url: WEBSERVER.URL,
|
||||
channel,
|
||||
titles: {
|
||||
videosFeed: req.t('{instanceName} videos feed', { instanceName: CONFIG.INSTANCE.NAME }),
|
||||
channelVideosFeed: req.t('{name} videos feed', { name: channel.getDisplayName() }),
|
||||
channelPodcastFeed: req.t('{name} podcast feed', { name: channel.getDisplayName() })
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import { replaceChapters, replaceChaptersFromDescriptionIfNeeded } from './video
|
||||
import { buildNewFile, createVideoSource } from './video-file.js'
|
||||
import { addVideoJobsAfterCreation } from './video-jobs.js'
|
||||
import { VideoPathManager } from './video-path-manager.js'
|
||||
import { buildCommentsPolicy, setVideoTags } from './video.js'
|
||||
import { setVideoTags } from './video.js'
|
||||
|
||||
type VideoAttributes = Omit<VideoCreate, 'channelId'> & {
|
||||
duration: number
|
||||
@@ -307,7 +307,7 @@ export class LocalVideoCreator {
|
||||
category: videoInfo.category,
|
||||
licence: videoInfo.licence ?? CONFIG.DEFAULTS.PUBLISH.LICENCE,
|
||||
language: videoInfo.language,
|
||||
commentsPolicy: buildCommentsPolicy(videoInfo),
|
||||
commentsPolicy: videoInfo.commentsPolicy ?? CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY,
|
||||
downloadEnabled: videoInfo.downloadEnabled ?? CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED,
|
||||
waitTranscoding: videoInfo.waitTranscoding || false,
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
RegisteredExternalAuthConfig,
|
||||
RegisteredIdAndPassAuthConfig,
|
||||
ServerConfig,
|
||||
VideoCommentPolicy,
|
||||
VideoResolutionType
|
||||
} from '@peertube/peertube-models'
|
||||
import { getServerCommit } from '@server/helpers/version.js'
|
||||
@@ -105,8 +104,6 @@ class ServerConfigManager {
|
||||
downloadEnabled: CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED,
|
||||
|
||||
commentsPolicy: CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY,
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled: CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY !== VideoCommentPolicy.DISABLED,
|
||||
|
||||
privacy: CONFIG.DEFAULTS.PUBLISH.PRIVACY,
|
||||
licence: CONFIG.DEFAULTS.PUBLISH.LICENCE
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { pick, sortBy } from '@peertube/peertube-core-utils'
|
||||
import { ActivityCreate, FileStorage, VideoCommentPolicy, VideoExportJSON, VideoObject, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { ActivityCreate, FileStorage, VideoExportJSON, VideoObject, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { logger } from '@server/helpers/logger.js'
|
||||
import { audiencify, getVideoAudience } from '@server/lib/activitypub/audience.js'
|
||||
import { buildCreateActivity } from '@server/lib/activitypub/send/send-create.js'
|
||||
@@ -175,8 +175,6 @@ export class VideosExporter extends AbstractUserExporter<VideoExportJSON> {
|
||||
nsfw: video.nsfw,
|
||||
|
||||
commentsPolicy: video.commentsPolicy,
|
||||
// TODO: remove, deprecated in 6.2
|
||||
commentsEnabled: video.commentsPolicy !== VideoCommentPolicy.DISABLED,
|
||||
|
||||
downloadEnabled: video.downloadEnabled,
|
||||
|
||||
@@ -295,7 +293,7 @@ export class VideosExporter extends AbstractUserExporter<VideoExportJSON> {
|
||||
const icon = video.getPreview()
|
||||
|
||||
const audience = getVideoAudience(video.VideoChannel.Account.Actor, video.privacy, { skipPrivacyCheck: true })
|
||||
const videoObject = {
|
||||
const videoObject: VideoObject = {
|
||||
...audiencify(await video.toActivityPubObject(), audience),
|
||||
|
||||
icon: [
|
||||
@@ -309,7 +307,13 @@ export class VideosExporter extends AbstractUserExporter<VideoExportJSON> {
|
||||
subtitleLanguage: video.VideoCaptions.map(c => ({
|
||||
...c.toActivityPubObject(video),
|
||||
|
||||
url: join(this.options.relativeStaticDirPath, this.getArchiveCaptionFilePath(video, c))
|
||||
url: [
|
||||
{
|
||||
mediaType: 'text/vtt',
|
||||
type: 'Link',
|
||||
href: join(this.options.relativeStaticDirPath, this.getArchiveCaptionFilePath(video, c))
|
||||
}
|
||||
]
|
||||
})),
|
||||
|
||||
hasParts: buildChaptersAPHasPart(video, chapters),
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
import { pick } from '@peertube/peertube-core-utils'
|
||||
import { ffprobePromise, getVideoStreamDuration } from '@peertube/peertube-ffmpeg'
|
||||
import {
|
||||
LiveVideoLatencyMode,
|
||||
ThumbnailType,
|
||||
VideoCommentPolicy,
|
||||
VideoExportJSON,
|
||||
VideoPrivacy,
|
||||
VideoState
|
||||
} from '@peertube/peertube-models'
|
||||
import { LiveVideoLatencyMode, ThumbnailType, VideoExportJSON, VideoPrivacy, VideoState } from '@peertube/peertube-models'
|
||||
import { buildUUID, getFileSize } from '@peertube/peertube-node-utils'
|
||||
import { isArray, isBooleanValid, isUUIDValid } from '@server/helpers/custom-validators/misc.js'
|
||||
import { isPlayerVideoThemeSettingValid } from '@server/helpers/custom-validators/player-settings.js'
|
||||
@@ -102,14 +95,7 @@ export class VideosImporter extends AbstractUserImporter<VideoExportJSON, Import
|
||||
if (!isBooleanValid(o.waitTranscoding)) o.waitTranscoding = true
|
||||
|
||||
if (!o.commentsPolicy || !isVideoCommentsPolicyValid(o.commentsPolicy)) {
|
||||
// Fallback to deprecated property
|
||||
if (isBooleanValid(o.commentsEnabled)) {
|
||||
o.commentsPolicy = o.commentsEnabled === true
|
||||
? VideoCommentPolicy.ENABLED
|
||||
: VideoCommentPolicy.DISABLED
|
||||
} else {
|
||||
o.commentsPolicy = CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY
|
||||
}
|
||||
o.commentsPolicy = CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY
|
||||
}
|
||||
|
||||
if (!isVideoSourceFilenameValid(o.source?.inputFilename)) o.source = undefined
|
||||
|
||||
@@ -19,7 +19,7 @@ import { sequelizeTypescript } from '@server/initializers/database.js'
|
||||
import { Hooks } from '@server/lib/plugins/hooks.js'
|
||||
import { ServerConfigManager } from '@server/lib/server-config-manager.js'
|
||||
import { autoBlacklistVideoIfNeeded } from '@server/lib/video-blacklist.js'
|
||||
import { buildCommentsPolicy, setVideoTags } from '@server/lib/video.js'
|
||||
import { setVideoTags } from '@server/lib/video.js'
|
||||
import { VideoChannelActivityModel } from '@server/models/video/video-channel-activity.js'
|
||||
import { VideoImportModel } from '@server/models/video/video-import.js'
|
||||
import { VideoPasswordModel } from '@server/models/video/video-password.js'
|
||||
@@ -141,7 +141,7 @@ async function buildVideoFromImport ({ channelId, importData, importDataOverride
|
||||
category: importDataOverride?.category || importData.category,
|
||||
licence: importDataOverride?.licence ?? importData.licence ?? CONFIG.DEFAULTS.PUBLISH.LICENCE,
|
||||
language: importDataOverride?.language || importData.language,
|
||||
commentsPolicy: buildCommentsPolicy(importDataOverride),
|
||||
commentsPolicy: importDataOverride?.commentsPolicy ?? CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY,
|
||||
downloadEnabled: importDataOverride?.downloadEnabled ?? CONFIG.DEFAULTS.PUBLISH.DOWNLOAD_ENABLED,
|
||||
waitTranscoding: importDataOverride?.waitTranscoding ?? true,
|
||||
state: VideoState.TO_IMPORT,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { VideoCommentPolicy, VideoCommentPolicyType } from '@peertube/peertube-models'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { MEMOIZE_LENGTH, MEMOIZE_TTL } from '@server/initializers/constants.js'
|
||||
import { TagModel } from '@server/models/video/tag.js'
|
||||
import { VideoModel } from '@server/models/video/video.js'
|
||||
@@ -40,17 +38,3 @@ export const getCachedVideoDuration = memoizee(getVideoDuration, {
|
||||
max: MEMOIZE_LENGTH.VIDEO_DURATION,
|
||||
maxAge: MEMOIZE_TTL.VIDEO_DURATION
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export function buildCommentsPolicy (options: {
|
||||
commentsEnabled?: boolean
|
||||
commentsPolicy?: VideoCommentPolicyType
|
||||
}) {
|
||||
if (options.commentsPolicy) return options.commentsPolicy
|
||||
|
||||
if (options.commentsEnabled === true) return VideoCommentPolicy.ENABLED
|
||||
if (options.commentsEnabled === false) return VideoCommentPolicy.DISABLED
|
||||
|
||||
return CONFIG.DEFAULTS.PUBLISH.COMMENTS_POLICY
|
||||
}
|
||||
|
||||
@@ -462,11 +462,6 @@ export function getCommonVideoEditAttributes () {
|
||||
`Should have an array of up to ${CONSTRAINTS_FIELDS.VIDEOS.TAGS.max} tags between ` +
|
||||
`${CONSTRAINTS_FIELDS.VIDEOS.TAG.min} and ${CONSTRAINTS_FIELDS.VIDEOS.TAG.max} characters each`
|
||||
),
|
||||
// TODO: remove, deprecated in PeerTube 6.2
|
||||
body('commentsEnabled')
|
||||
.optional()
|
||||
.customSanitizer(toBooleanOrNull)
|
||||
.custom(isBooleanValid).withMessage('Should have valid commentsEnabled boolean'),
|
||||
body('commentsPolicy')
|
||||
.optional()
|
||||
.custom(isVideoCommentsPolicyValid),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Account, AccountSummary, ActivityPubActor, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { Account, AccountSummary, ActivityPubActor, ActivityUrlObject, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
|
||||
import { ModelCache } from '@server/models/shared/model-cache.js'
|
||||
import { FindOptions, IncludeOptions, Includeable, Op, Transaction, WhereOptions, literal } from 'sequelize'
|
||||
@@ -500,26 +500,24 @@ export class AccountModel extends SequelizeModel<AccountModel> {
|
||||
const obj = await this.Actor.toActivityPubObject(this.name)
|
||||
|
||||
return Object.assign(obj, {
|
||||
// // TODO: Uncomment in v8 for backward compatibility
|
||||
// url: [
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.getClientUrl(true)
|
||||
// },
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.getClientUrl(false)
|
||||
// },
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.Actor.url
|
||||
// }
|
||||
// ] as ActivityUrlObject[],
|
||||
url: [
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.getClientUrl(true)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.getClientUrl(false)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.Actor.url
|
||||
}
|
||||
] as ActivityUrlObject[],
|
||||
|
||||
url: this.Actor.url,
|
||||
summary: this.description
|
||||
})
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ export function videoModelToActivityPubObject (video: MVideoAP): VideoObject {
|
||||
|
||||
state: video.state,
|
||||
|
||||
commentsEnabled: video.commentsPolicy !== VideoCommentPolicy.DISABLED,
|
||||
canReply: video.commentsPolicy === VideoCommentPolicy.ENABLED
|
||||
? null
|
||||
: getAPPublicValue(), // Requires approval
|
||||
|
||||
@@ -2,7 +2,6 @@ import { getResolutionLabel } from '@peertube/peertube-core-utils'
|
||||
import {
|
||||
Video,
|
||||
VideoAdditionalAttributes,
|
||||
VideoCommentPolicy,
|
||||
VideoDetails,
|
||||
VideoFile,
|
||||
VideoInclude,
|
||||
@@ -170,8 +169,6 @@ export function videoModelToFormattedDetailsJSON (video: MVideoFormattableDetail
|
||||
account: video.VideoChannel.Account.toFormattedJSON(),
|
||||
tags,
|
||||
|
||||
// TODO: remove, deprecated in PeerTube 6.2
|
||||
commentsEnabled: video.commentsPolicy !== VideoCommentPolicy.DISABLED,
|
||||
commentsPolicy: {
|
||||
id: video.commentsPolicy,
|
||||
label: VIDEO_COMMENTS_POLICY[video.commentsPolicy]
|
||||
|
||||
@@ -278,6 +278,7 @@ export class VideoCaptionModel extends SequelizeModel<VideoCaptionModel> {
|
||||
},
|
||||
automaticallyGenerated: this.automaticallyGenerated,
|
||||
|
||||
// TODO: remove, deprecated in 8.0
|
||||
captionPath: this.Video.isLocal() && this.fileUrl
|
||||
? null // On object storage
|
||||
: this.getFileStaticPath(),
|
||||
@@ -295,21 +296,18 @@ export class VideoCaptionModel extends SequelizeModel<VideoCaptionModel> {
|
||||
name: VideoCaptionModel.getLanguageLabel(this.language),
|
||||
automaticallyGenerated: this.automaticallyGenerated,
|
||||
|
||||
// TODO: Remove break flag in v8
|
||||
url: process.env.ENABLE_AP_BREAKING_CHANGES === 'true'
|
||||
? [
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/vtt',
|
||||
href: this.getOriginFileUrl(video)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'application/x-mpegURL',
|
||||
href: this.getOriginFileUrl(video)
|
||||
}
|
||||
]
|
||||
: this.getOriginFileUrl(video)
|
||||
url: [
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/vtt',
|
||||
href: this.getOriginFileUrl(video)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'application/x-mpegURL',
|
||||
href: this.getOriginFileUrl(video)
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ActivityPubActor, VideoChannel, VideoChannelSummary, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { ActivityPubActor, ActivityUrlObject, VideoChannel, VideoChannelSummary, VideoPrivacy } from '@peertube/peertube-models'
|
||||
import { AttributesOnly } from '@peertube/peertube-typescript-utils'
|
||||
import { CONFIG } from '@server/initializers/config.js'
|
||||
import { getLocalActorPlayerSettingsActivityPubUrl } from '@server/lib/activitypub/url.js'
|
||||
@@ -571,26 +571,24 @@ export class VideoChannelModel extends SequelizeModel<VideoChannelModel> {
|
||||
return {
|
||||
...obj,
|
||||
|
||||
// // TODO: Uncomment in v8 for backward compatibility
|
||||
// url: [
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.getClientUrl(true)
|
||||
// },
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.getClientUrl(false)
|
||||
// },
|
||||
// {
|
||||
// type: 'Link',
|
||||
// mediaType: 'text/html',
|
||||
// href: this.Actor.url
|
||||
// }
|
||||
// ] as ActivityUrlObject[],
|
||||
url: [
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.getClientUrl(true)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.getClientUrl(false)
|
||||
},
|
||||
{
|
||||
type: 'Link',
|
||||
mediaType: 'text/html',
|
||||
href: this.Actor.url
|
||||
}
|
||||
] as ActivityUrlObject[],
|
||||
|
||||
url: this.Actor.url,
|
||||
playerSettings: getLocalActorPlayerSettingsActivityPubUrl(this.Actor),
|
||||
|
||||
summary: this.description,
|
||||
|
||||
@@ -142,7 +142,6 @@ export class VideoSourceModel extends SequelizeModel<VideoSourceModel> {
|
||||
|
||||
toFormattedJSON (this: MVideoSource): VideoSource {
|
||||
return {
|
||||
filename: this.inputFilename,
|
||||
inputFilename: this.inputFilename,
|
||||
|
||||
fileUrl: this.fileUrl,
|
||||
|
||||
@@ -3149,10 +3149,6 @@ paths:
|
||||
type: string
|
||||
minLength: 2
|
||||
maxLength: 30
|
||||
commentsEnabled:
|
||||
deprecated: true
|
||||
description: 'Deprecated in 6.2, use commentsPolicy instead'
|
||||
type: boolean
|
||||
commentsPolicy:
|
||||
$ref: '#/components/schemas/VideoCommentsPolicySet'
|
||||
downloadEnabled:
|
||||
@@ -3243,27 +3239,6 @@ paths:
|
||||
'204':
|
||||
description: successful operation
|
||||
|
||||
'/api/v1/videos/{id}/watching':
|
||||
put:
|
||||
summary: Set watching progress of a video
|
||||
deprecated: true
|
||||
description: This endpoint has been deprecated. Use `/videos/{id}/views` instead
|
||||
tags:
|
||||
- Video
|
||||
security:
|
||||
- OAuth2: []
|
||||
parameters:
|
||||
- $ref: '#/components/parameters/idOrUUID'
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserViewingVideo'
|
||||
required: true
|
||||
responses:
|
||||
'204':
|
||||
description: successful operation
|
||||
|
||||
'/api/v1/videos/{id}/stats/overall':
|
||||
get:
|
||||
summary: Get overall stats of a video
|
||||
@@ -3755,10 +3730,6 @@ paths:
|
||||
type: string
|
||||
minLength: 2
|
||||
maxLength: 30
|
||||
commentsEnabled:
|
||||
deprecated: true
|
||||
description: 'Deprecated in 6.2, use commentsPolicy instead'
|
||||
type: boolean
|
||||
commentsPolicy:
|
||||
$ref: '#/components/schemas/VideoCommentsPolicySet'
|
||||
downloadEnabled:
|
||||
@@ -7539,7 +7510,8 @@ paths:
|
||||
get:
|
||||
tags:
|
||||
- Video Channels
|
||||
summary: "**PeerTube >= 8.0** List channel collaborators"
|
||||
summary: "*List channel collaborators"
|
||||
description: "**PeerTube >= 8.0**"
|
||||
operationId: listVideoChannelCollaborators
|
||||
security:
|
||||
- OAuth2: []
|
||||
@@ -9179,10 +9151,6 @@ components:
|
||||
type: string
|
||||
minLength: 2
|
||||
maxLength: 30
|
||||
commentsEnabled:
|
||||
deprecated: true
|
||||
description: 'Deprecated in 6.2, use commentsPolicy instead'
|
||||
type: boolean
|
||||
commentsPolicy:
|
||||
$ref: '#/components/schemas/VideoCommentsPolicyConstant'
|
||||
downloadEnabled:
|
||||
@@ -9585,6 +9553,10 @@ components:
|
||||
Storyboard:
|
||||
properties:
|
||||
storyboardPath:
|
||||
description: Deprecated in PeerTube v8, use fileUrl instead
|
||||
deprecated: true
|
||||
type: string
|
||||
fileUrl:
|
||||
type: string
|
||||
totalHeight:
|
||||
type: integer
|
||||
@@ -9596,12 +9568,25 @@ components:
|
||||
type: integer
|
||||
spriteDuration:
|
||||
type: integer
|
||||
|
||||
VideoCaption:
|
||||
properties:
|
||||
language:
|
||||
$ref: '#/components/schemas/VideoConstantString-Language'
|
||||
automaticallyGenerated:
|
||||
type: boolean
|
||||
captionPath:
|
||||
type: string
|
||||
deprecated: true
|
||||
description: Deprecated in PeerTube v8, use fileUrl instead
|
||||
fileUrl:
|
||||
type: string
|
||||
m3u8Url:
|
||||
type: string
|
||||
updatedAt:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
VideoChapters:
|
||||
properties:
|
||||
chapters:
|
||||
@@ -9613,10 +9598,6 @@ components:
|
||||
type: integer
|
||||
VideoSource:
|
||||
properties:
|
||||
filename:
|
||||
type: string
|
||||
deprecated: true
|
||||
description: 'Deprecated in 6.1, use inputFilename instead'
|
||||
inputFilename:
|
||||
type: string
|
||||
description: 'Uploaded/imported filename'
|
||||
@@ -9645,12 +9626,16 @@ components:
|
||||
ActorImage:
|
||||
properties:
|
||||
path:
|
||||
description: Deprecated in PeerTube v8, use fileUrl instead
|
||||
deprecated: true
|
||||
type: string
|
||||
fileUrl:
|
||||
type: string
|
||||
width:
|
||||
type: integer
|
||||
height:
|
||||
type: integer
|
||||
description: "**PeerTube >= 7.3** ImportVideosInChannelCreate:mage height"
|
||||
description: "**PeerTube >= 7.3**"
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
@@ -10735,10 +10720,6 @@ components:
|
||||
type: string
|
||||
minLength: 2
|
||||
maxLength: 30
|
||||
commentsEnabled:
|
||||
deprecated: true
|
||||
description: 'Deprecated in 6.2, use commentsPolicy instead'
|
||||
type: boolean
|
||||
commentsPolicy:
|
||||
$ref: '#/components/schemas/VideoCommentsPolicySet'
|
||||
downloadEnabled:
|
||||
|
||||
Reference in New Issue
Block a user