1
0
Fork 0

Handle live federation

This commit is contained in:
Chocobozzz 2020-09-17 13:59:02 +02:00 committed by Chocobozzz
parent 1ef65f4c03
commit de6310b2fc
10 changed files with 30 additions and 26 deletions

View file

@ -55,7 +55,6 @@ import {
videosUpdateValidator videosUpdateValidator
} from '../../../middlewares' } from '../../../middlewares'
import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update' import { ScheduleVideoUpdateModel } from '../../../models/video/schedule-video-update'
import { TagModel } from '../../../models/video/tag'
import { VideoModel } from '../../../models/video/video' import { VideoModel } from '../../../models/video/video'
import { VideoFileModel } from '../../../models/video/video-file' import { VideoFileModel } from '../../../models/video/video-file'
import { abuseVideoRouter } from './abuse' import { abuseVideoRouter } from './abuse'

View file

@ -62,6 +62,7 @@ function sanitizeAndCheckVideoTorrentObject (video: any) {
if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false if (!isBooleanValid(video.waitTranscoding)) video.waitTranscoding = false
if (!isBooleanValid(video.downloadEnabled)) video.downloadEnabled = true if (!isBooleanValid(video.downloadEnabled)) video.downloadEnabled = true
if (!isBooleanValid(video.commentsEnabled)) video.commentsEnabled = false if (!isBooleanValid(video.commentsEnabled)) video.commentsEnabled = false
if (!isBooleanValid(video.isLiveBroadcast)) video.isLiveBroadcast = false
return isActivityPubUrlValid(video.id) && return isActivityPubUrlValid(video.id) &&
isVideoNameValid(video.name) && isVideoNameValid(video.name) &&

View file

@ -1,5 +1,5 @@
import { isRedundancyAccepted } from '@server/lib/redundancy' import { isRedundancyAccepted } from '@server/lib/redundancy'
import { ActivityCreate, CacheFileObject, VideoTorrentObject } from '../../../../shared' import { ActivityCreate, CacheFileObject, VideoObject } from '../../../../shared'
import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object' import { PlaylistObject } from '../../../../shared/models/activitypub/objects/playlist-object'
import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object' import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
import { retryTransactionWrapper } from '../../../helpers/database-utils' import { retryTransactionWrapper } from '../../../helpers/database-utils'
@ -52,7 +52,7 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function processCreateVideo (activity: ActivityCreate, notify: boolean) { async function processCreateVideo (activity: ActivityCreate, notify: boolean) {
const videoToCreateData = activity.object as VideoTorrentObject const videoToCreateData = activity.object as VideoObject
const syncParam = { likes: false, dislikes: false, shares: false, comments: false, thumbnail: true, refreshVideo: false } const syncParam = { likes: false, dislikes: false, shares: false, comments: false, thumbnail: true, refreshVideo: false }
const { video, created } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoToCreateData, syncParam }) const { video, created } = await getOrCreateVideoAndAccountAndChannel({ videoObject: videoToCreateData, syncParam })

View file

@ -1,4 +1,4 @@
import { ActivityUpdate, CacheFileObject, VideoTorrentObject } from '../../../../shared/models/activitypub' import { ActivityUpdate, CacheFileObject, VideoObject } from '../../../../shared/models/activitypub'
import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor' import { ActivityPubActor } from '../../../../shared/models/activitypub/activitypub-actor'
import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils' import { resetSequelizeInstance, retryTransactionWrapper } from '../../../helpers/database-utils'
import { logger } from '../../../helpers/logger' import { logger } from '../../../helpers/logger'
@ -55,7 +55,7 @@ export {
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
async function processUpdateVideo (actor: MActorSignature, activity: ActivityUpdate) { async function processUpdateVideo (actor: MActorSignature, activity: ActivityUpdate) {
const videoObject = activity.object as VideoTorrentObject const videoObject = activity.object as VideoObject
if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) { if (sanitizeAndCheckVideoTorrentObject(videoObject) === false) {
logger.debug('Video sent by update is not valid.', { videoObject }) logger.debug('Video sent by update is not valid.', { videoObject })

View file

@ -15,7 +15,7 @@ import {
ActivityVideoUrlObject, ActivityVideoUrlObject,
VideoState VideoState
} from '../../../shared/index' } from '../../../shared/index'
import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' import { VideoObject } from '../../../shared/models/activitypub/objects'
import { VideoPrivacy } from '../../../shared/models/videos' import { VideoPrivacy } from '../../../shared/models/videos'
import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type'
@ -38,7 +38,6 @@ import {
} from '../../initializers/constants' } from '../../initializers/constants'
import { sequelizeTypescript } from '../../initializers/database' import { sequelizeTypescript } from '../../initializers/database'
import { AccountVideoRateModel } from '../../models/account/account-video-rate' import { AccountVideoRateModel } from '../../models/account/account-video-rate'
import { TagModel } from '../../models/video/tag'
import { VideoModel } from '../../models/video/video' import { VideoModel } from '../../models/video/video'
import { VideoCaptionModel } from '../../models/video/video-caption' import { VideoCaptionModel } from '../../models/video/video-caption'
import { VideoCommentModel } from '../../models/video/video-comment' import { VideoCommentModel } from '../../models/video/video-comment'
@ -104,7 +103,7 @@ async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVid
} }
} }
async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.RequestResponse, videoObject: VideoTorrentObject }> { async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.RequestResponse, videoObject: VideoObject }> {
const options = { const options = {
uri: videoUrl, uri: videoUrl,
method: 'GET', method: 'GET',
@ -136,7 +135,7 @@ async function fetchRemoteVideoDescription (video: MVideoAccountLight) {
return body.description ? body.description : '' return body.description ? body.description : ''
} }
function getOrCreateVideoChannelFromVideoObject (videoObject: VideoTorrentObject) { function getOrCreateVideoChannelFromVideoObject (videoObject: VideoObject) {
const channel = videoObject.attributedTo.find(a => a.type === 'Group') const channel = videoObject.attributedTo.find(a => a.type === 'Group')
if (!channel) throw new Error('Cannot find associated video channel to video ' + videoObject.url) if (!channel) throw new Error('Cannot find associated video channel to video ' + videoObject.url)
@ -155,7 +154,7 @@ type SyncParam = {
thumbnail: boolean thumbnail: boolean
refreshVideo?: boolean refreshVideo?: boolean
} }
async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoTorrentObject, syncParam: SyncParam) { async function syncVideoExternalAttributes (video: MVideo, fetchedVideo: VideoObject, syncParam: SyncParam) {
logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid) logger.info('Adding likes/dislikes/shares/comments of video %s.', video.uuid)
const jobPayloads: ActivitypubHttpFetcherPayload[] = [] const jobPayloads: ActivitypubHttpFetcherPayload[] = []
@ -294,7 +293,7 @@ async function getOrCreateVideoAndAccountAndChannel (
async function updateVideoFromAP (options: { async function updateVideoFromAP (options: {
video: MVideoAccountLightBlacklistAllFiles video: MVideoAccountLightBlacklistAllFiles
videoObject: VideoTorrentObject videoObject: VideoObject
account: MAccountIdActor account: MAccountIdActor
channel: MChannelDefault channel: MChannelDefault
overrideTo?: string[] overrideTo?: string[]
@ -538,7 +537,7 @@ function isAPHashTagObject (url: any): url is ActivityHashTagObject {
return url && url.type === 'Hashtag' return url && url.type === 'Hashtag'
} }
async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAccountLight, waitThumbnail = false) { async function createVideo (videoObject: VideoObject, channel: MChannelAccountLight, waitThumbnail = false) {
logger.debug('Adding remote video %s.', videoObject.id) logger.debug('Adding remote video %s.', videoObject.id)
const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to) const videoData = await videoActivityObjectToDBAttributes(channel, videoObject, videoObject.to)
@ -632,7 +631,7 @@ async function createVideo (videoObject: VideoTorrentObject, channel: MChannelAc
return { autoBlacklisted, videoCreated } return { autoBlacklisted, videoCreated }
} }
function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoTorrentObject, to: string[] = []) { function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObject: VideoObject, to: string[] = []) {
const privacy = to.includes(ACTIVITY_PUB.PUBLIC) const privacy = to.includes(ACTIVITY_PUB.PUBLIC)
? VideoPrivacy.PUBLIC ? VideoPrivacy.PUBLIC
: VideoPrivacy.UNLISTED : VideoPrivacy.UNLISTED
@ -664,6 +663,7 @@ function videoActivityObjectToDBAttributes (videoChannel: MChannelId, videoObjec
commentsEnabled: videoObject.commentsEnabled, commentsEnabled: videoObject.commentsEnabled,
downloadEnabled: videoObject.downloadEnabled, downloadEnabled: videoObject.downloadEnabled,
waitTranscoding: videoObject.waitTranscoding, waitTranscoding: videoObject.waitTranscoding,
isLive: videoObject.isLiveBroadcast,
state: videoObject.state, state: videoObject.state,
channelId: videoChannel.id, channelId: videoChannel.id,
duration: parseInt(duration, 10), duration: parseInt(duration, 10),
@ -732,7 +732,7 @@ function videoFileActivityUrlToDBAttributes (
return attributes return attributes
} }
function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObject: VideoTorrentObject, videoFiles: MVideoFile[]) { function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObject: VideoObject, videoFiles: MVideoFile[]) {
const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[] const playlistUrls = videoObject.url.filter(u => isAPStreamingPlaylistUrlObject(u)) as ActivityPlaylistUrlObject[]
if (playlistUrls.length === 0) return [] if (playlistUrls.length === 0) return []
@ -766,7 +766,7 @@ function streamingPlaylistActivityUrlToDBAttributes (video: MVideoId, videoObjec
return attributes return attributes
} }
function getThumbnailFromIcons (videoObject: VideoTorrentObject) { function getThumbnailFromIcons (videoObject: VideoObject) {
let validIcons = videoObject.icon.filter(i => i.width > THUMBNAILS_SIZE.minWidth) let validIcons = videoObject.icon.filter(i => i.width > THUMBNAILS_SIZE.minWidth)
// Fallback if there are not valid icons // Fallback if there are not valid icons
if (validIcons.length === 0) validIcons = videoObject.icon if (validIcons.length === 0) validIcons = videoObject.icon
@ -774,7 +774,7 @@ function getThumbnailFromIcons (videoObject: VideoTorrentObject) {
return minBy(validIcons, 'width') return minBy(validIcons, 'width')
} }
function getPreviewFromIcons (videoObject: VideoTorrentObject) { function getPreviewFromIcons (videoObject: VideoObject) {
const validIcons = videoObject.icon.filter(i => i.width > PREVIEWS_SIZE.minWidth) const validIcons = videoObject.icon.filter(i => i.width > PREVIEWS_SIZE.minWidth)
// FIXME: don't put a fallback here for compatibility with PeerTube <2.2 // FIXME: don't put a fallback here for compatibility with PeerTube <2.2

View file

@ -18,7 +18,7 @@ import {
MVideoAccountLightBlacklistAllFiles MVideoAccountLightBlacklistAllFiles
} from '@server/types/models' } from '@server/types/models'
import { ActivityCreate } from '../../shared/models/activitypub' import { ActivityCreate } from '../../shared/models/activitypub'
import { VideoTorrentObject } from '../../shared/models/activitypub/objects' import { VideoObject } from '../../shared/models/activitypub/objects'
import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object' import { VideoCommentObject } from '../../shared/models/activitypub/objects/video-comment-object'
import { VideoCreate, VideoImportCreate } from '../../shared/models/videos' import { VideoCreate, VideoImportCreate } from '../../shared/models/videos'
import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model' import { VideoCommentCreate } from '../../shared/models/videos/video-comment.model'
@ -62,7 +62,7 @@ function isLocalVideoCommentReplyAccepted (_object: {
function isRemoteVideoAccepted (_object: { function isRemoteVideoAccepted (_object: {
activity: ActivityCreate activity: ActivityCreate
videoAP: VideoTorrentObject videoAP: VideoObject
byActor: ActorModel byActor: ActorModel
}): AcceptResult { }): AcceptResult {
return { accepted: true } return { accepted: true }

View file

@ -1,6 +1,6 @@
import { Video, VideoDetails } from '../../../shared/models/videos' import { Video, VideoDetails } from '../../../shared/models/videos'
import { VideoModel } from './video' import { VideoModel } from './video'
import { ActivityTagObject, ActivityUrlObject, VideoTorrentObject } from '../../../shared/models/activitypub/objects' import { ActivityTagObject, ActivityUrlObject, VideoObject } from '../../../shared/models/activitypub/objects'
import { MIMETYPES, WEBSERVER } from '../../initializers/constants' import { MIMETYPES, WEBSERVER } from '../../initializers/constants'
import { VideoCaptionModel } from './video-caption' import { VideoCaptionModel } from './video-caption'
import { import {
@ -262,7 +262,7 @@ function addVideoFilesInAPAcc (
} }
} }
function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject { function videoModelToActivityPubObject (video: MVideoAP): VideoObject {
const { baseUrlHttp, baseUrlWs } = video.getBaseUrls() const { baseUrlHttp, baseUrlWs } = video.getBaseUrls()
if (!video.Tags) video.Tags = [] if (!video.Tags) video.Tags = []
@ -351,6 +351,7 @@ function videoModelToActivityPubObject (video: MVideoAP): VideoTorrentObject {
views: video.views, views: video.views,
sensitive: video.nsfw, sensitive: video.nsfw,
waitTranscoding: video.waitTranscoding, waitTranscoding: video.waitTranscoding,
isLiveBroadcast: video.isLive,
state: video.state, state: video.state,
commentsEnabled: video.commentsEnabled, commentsEnabled: video.commentsEnabled,
downloadEnabled: video.downloadEnabled, downloadEnabled: video.downloadEnabled,

View file

@ -31,7 +31,7 @@ import { getServerActor } from '@server/models/application/application'
import { ModelCache } from '@server/models/model-cache' import { ModelCache } from '@server/models/model-cache'
import { VideoFile } from '@shared/models/videos/video-file.model' import { VideoFile } from '@shared/models/videos/video-file.model'
import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared' import { ResultList, UserRight, VideoPrivacy, VideoState } from '../../../shared'
import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' import { VideoObject } from '../../../shared/models/activitypub/objects'
import { Video, VideoDetails } from '../../../shared/models/videos' import { Video, VideoDetails } from '../../../shared/models/videos'
import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type'
import { VideoFilter } from '../../../shared/models/videos/video-query.type' import { VideoFilter } from '../../../shared/models/videos/video-query.type'
@ -1763,7 +1763,7 @@ export class VideoModel extends Model<VideoModel> {
return videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, files) return videoFilesModelToFormattedJSON(this, baseUrlHttp, baseUrlWs, files)
} }
toActivityPubObject (this: MVideoAP): VideoTorrentObject { toActivityPubObject (this: MVideoAP): VideoObject {
return videoModelToActivityPubObject(this) return videoModelToActivityPubObject(this)
} }

View file

@ -1,6 +1,6 @@
import { ActivityPubActor } from './activitypub-actor' import { ActivityPubActor } from './activitypub-actor'
import { ActivityPubSignature } from './activitypub-signature' import { ActivityPubSignature } from './activitypub-signature'
import { ActivityFlagReasonObject, CacheFileObject, VideoTorrentObject } from './objects' import { ActivityFlagReasonObject, CacheFileObject, VideoObject } from './objects'
import { AbuseObject } from './objects/abuse-object' import { AbuseObject } from './objects/abuse-object'
import { DislikeObject } from './objects/dislike-object' import { DislikeObject } from './objects/dislike-object'
import { APObject } from './objects/object.model' import { APObject } from './objects/object.model'
@ -53,12 +53,12 @@ export interface BaseActivity {
export interface ActivityCreate extends BaseActivity { export interface ActivityCreate extends BaseActivity {
type: 'Create' type: 'Create'
object: VideoTorrentObject | AbuseObject | ViewObject | DislikeObject | VideoCommentObject | CacheFileObject | PlaylistObject object: VideoObject | AbuseObject | ViewObject | DislikeObject | VideoCommentObject | CacheFileObject | PlaylistObject
} }
export interface ActivityUpdate extends BaseActivity { export interface ActivityUpdate extends BaseActivity {
type: 'Update' type: 'Update'
object: VideoTorrentObject | ActivityPubActor | CacheFileObject | PlaylistObject object: VideoObject | ActivityPubActor | CacheFileObject | PlaylistObject
} }
export interface ActivityDelete extends BaseActivity { export interface ActivityDelete extends BaseActivity {

View file

@ -7,7 +7,7 @@ import {
} from './common-objects' } from './common-objects'
import { VideoState } from '../../videos' import { VideoState } from '../../videos'
export interface VideoTorrentObject { export interface VideoObject {
type: 'Video' type: 'Video'
id: string id: string
name: string name: string
@ -19,7 +19,10 @@ export interface VideoTorrentObject {
language: ActivityIdentifierObject language: ActivityIdentifierObject
subtitleLanguage: ActivityIdentifierObject[] subtitleLanguage: ActivityIdentifierObject[]
views: number views: number
sensitive: boolean sensitive: boolean
isLiveBroadcast: boolean
commentsEnabled: boolean commentsEnabled: boolean
downloadEnabled: boolean downloadEnabled: boolean
waitTranscoding: boolean waitTranscoding: boolean