aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/activitypub/videos.ts
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2018-06-12 20:04:58 +0200
committerChocobozzz <me@florianbigard.com>2018-06-12 20:37:51 +0200
commit2186386cca113506791583cb07d6ccacba7af4e0 (patch)
tree3c214c0b5fbd64332624267fa6e51fd4a9cf6474 /server/lib/activitypub/videos.ts
parent6ccdf3a23ecec5ba2eeaf487fd1fafdc7606b4bf (diff)
downloadPeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.gz
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.tar.zst
PeerTube-2186386cca113506791583cb07d6ccacba7af4e0.zip
Add concept of video state, and add ability to wait transcoding before
publishing a video
Diffstat (limited to 'server/lib/activitypub/videos.ts')
-rw-r--r--server/lib/activitypub/videos.ts80
1 files changed, 49 insertions, 31 deletions
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts
index 907f7e11e..7ec8ca193 100644
--- a/server/lib/activitypub/videos.ts
+++ b/server/lib/activitypub/videos.ts
@@ -1,8 +1,9 @@
1import * as Bluebird from 'bluebird' 1import * as Bluebird from 'bluebird'
2import * as sequelize from 'sequelize'
2import * as magnetUtil from 'magnet-uri' 3import * as magnetUtil from 'magnet-uri'
3import { join } from 'path' 4import { join } from 'path'
4import * as request from 'request' 5import * as request from 'request'
5import { ActivityIconObject } from '../../../shared/index' 6import { ActivityIconObject, VideoState } from '../../../shared/index'
6import { VideoTorrentObject } from '../../../shared/models/activitypub/objects' 7import { VideoTorrentObject } from '../../../shared/models/activitypub/objects'
7import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos' 8import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
8import { sanitizeAndCheckVideoTorrentObject } from '../../helpers/custom-validators/activitypub/videos' 9import { sanitizeAndCheckVideoTorrentObject } from '../../helpers/custom-validators/activitypub/videos'
@@ -21,6 +22,21 @@ import { VideoShareModel } from '../../models/video/video-share'
21import { getOrCreateActorAndServerAndModel } from './actor' 22import { getOrCreateActorAndServerAndModel } from './actor'
22import { addVideoComments } from './video-comments' 23import { addVideoComments } from './video-comments'
23import { crawlCollectionPage } from './crawl' 24import { crawlCollectionPage } from './crawl'
25import { sendCreateVideo, sendUpdateVideo } from './send'
26import { shareVideoByServerAndChannel } from './index'
27
28async function federateVideoIfNeeded (video: VideoModel, isNewVideo: boolean, transaction?: sequelize.Transaction) {
29 // If the video is not private and published, we federate it
30 if (video.privacy !== VideoPrivacy.PRIVATE && video.state === VideoState.PUBLISHED) {
31 if (isNewVideo === true) {
32 // Now we'll add the video's meta data to our followers
33 await sendCreateVideo(video, transaction)
34 await shareVideoByServerAndChannel(video, transaction)
35 } else {
36 await sendUpdateVideo(video, transaction)
37 }
38 }
39}
24 40
25function fetchRemoteVideoPreview (video: VideoModel, reject: Function) { 41function fetchRemoteVideoPreview (video: VideoModel, reject: Function) {
26 const host = video.VideoChannel.Account.Actor.Server.host 42 const host = video.VideoChannel.Account.Actor.Server.host
@@ -55,9 +71,11 @@ function generateThumbnailFromUrl (video: VideoModel, icon: ActivityIconObject)
55 return doRequestAndSaveToFile(options, thumbnailPath) 71 return doRequestAndSaveToFile(options, thumbnailPath)
56} 72}
57 73
58async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelModel, 74async function videoActivityObjectToDBAttributes (
59 videoObject: VideoTorrentObject, 75 videoChannel: VideoChannelModel,
60 to: string[] = []) { 76 videoObject: VideoTorrentObject,
77 to: string[] = []
78) {
61 const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED 79 const privacy = to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1 ? VideoPrivacy.PUBLIC : VideoPrivacy.UNLISTED
62 const duration = videoObject.duration.replace(/[^\d]+/, '') 80 const duration = videoObject.duration.replace(/[^\d]+/, '')
63 81
@@ -90,6 +108,8 @@ async function videoActivityObjectToDBAttributes (videoChannel: VideoChannelMode
90 support, 108 support,
91 nsfw: videoObject.sensitive, 109 nsfw: videoObject.sensitive,
92 commentsEnabled: videoObject.commentsEnabled, 110 commentsEnabled: videoObject.commentsEnabled,
111 waitTranscoding: videoObject.waitTranscoding,
112 state: videoObject.state,
93 channelId: videoChannel.id, 113 channelId: videoChannel.id,
94 duration: parseInt(duration, 10), 114 duration: parseInt(duration, 10),
95 createdAt: new Date(videoObject.published), 115 createdAt: new Date(videoObject.published),
@@ -185,22 +205,20 @@ async function getOrCreateVideo (videoObject: VideoTorrentObject, channelActor:
185} 205}
186 206
187async function getOrCreateAccountAndVideoAndChannel (videoObject: VideoTorrentObject | string, actor?: ActorModel) { 207async function getOrCreateAccountAndVideoAndChannel (videoObject: VideoTorrentObject | string, actor?: ActorModel) {
188 if (typeof videoObject === 'string') { 208 const videoUrl = typeof videoObject === 'string' ? videoObject : videoObject.id
189 const videoUrl = videoObject 209
190 210 const videoFromDatabase = await VideoModel.loadByUrlAndPopulateAccount(videoUrl)
191 const videoFromDatabase = await VideoModel.loadByUrlAndPopulateAccount(videoUrl) 211 if (videoFromDatabase) {
192 if (videoFromDatabase) { 212 return {
193 return { 213 video: videoFromDatabase,
194 video: videoFromDatabase, 214 actor: videoFromDatabase.VideoChannel.Account.Actor,
195 actor: videoFromDatabase.VideoChannel.Account.Actor, 215 channelActor: videoFromDatabase.VideoChannel.Actor
196 channelActor: videoFromDatabase.VideoChannel.Actor
197 }
198 } 216 }
199
200 videoObject = await fetchRemoteVideo(videoUrl)
201 if (!videoObject) throw new Error('Cannot fetch remote video with url: ' + videoUrl)
202 } 217 }
203 218
219 videoObject = await fetchRemoteVideo(videoUrl)
220 if (!videoObject) throw new Error('Cannot fetch remote video with url: ' + videoUrl)
221
204 if (!actor) { 222 if (!actor) {
205 const actorObj = videoObject.attributedTo.find(a => a.type === 'Person') 223 const actorObj = videoObject.attributedTo.find(a => a.type === 'Person')
206 if (!actorObj) throw new Error('Cannot find associated actor to video ' + videoObject.url) 224 if (!actorObj) throw new Error('Cannot find associated actor to video ' + videoObject.url)
@@ -291,20 +309,6 @@ async function addVideoShares (shareUrls: string[], instance: VideoModel) {
291 } 309 }
292} 310}
293 311
294export {
295 getOrCreateAccountAndVideoAndChannel,
296 fetchRemoteVideoPreview,
297 fetchRemoteVideoDescription,
298 generateThumbnailFromUrl,
299 videoActivityObjectToDBAttributes,
300 videoFileActivityUrlToDBAttributes,
301 getOrCreateVideo,
302 getOrCreateVideoChannel,
303 addVideoShares
304}
305
306// ---------------------------------------------------------------------------
307
308async function fetchRemoteVideo (videoUrl: string): Promise<VideoTorrentObject> { 312async function fetchRemoteVideo (videoUrl: string): Promise<VideoTorrentObject> {
309 const options = { 313 const options = {
310 uri: videoUrl, 314 uri: videoUrl,
@@ -324,3 +328,17 @@ async function fetchRemoteVideo (videoUrl: string): Promise<VideoTorrentObject>
324 328
325 return body 329 return body
326} 330}
331
332export {
333 federateVideoIfNeeded,
334 fetchRemoteVideo,
335 getOrCreateAccountAndVideoAndChannel,
336 fetchRemoteVideoPreview,
337 fetchRemoteVideoDescription,
338 generateThumbnailFromUrl,
339 videoActivityObjectToDBAttributes,
340 videoFileActivityUrlToDBAttributes,
341 getOrCreateVideo,
342 getOrCreateVideoChannel,
343 addVideoShares
344}