diff options
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r-- | server/lib/activitypub/videos.ts | 59 |
1 files changed, 53 insertions, 6 deletions
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index a5f6537eb..66330a964 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -3,7 +3,8 @@ import { maxBy, minBy } from 'lodash' | |||
3 | import * as magnetUtil from 'magnet-uri' | 3 | import * as magnetUtil from 'magnet-uri' |
4 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import * as request from 'request' | 5 | import * as request from 'request' |
6 | import * as sequelize from 'sequelize' | 6 | import { Transaction } from 'sequelize/types' |
7 | import { TrackerModel } from '@server/models/server/tracker' | ||
7 | import { VideoLiveModel } from '@server/models/video/video-live' | 8 | import { VideoLiveModel } from '@server/models/video/video-live' |
8 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | 9 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' |
9 | import { | 10 | import { |
@@ -16,12 +17,16 @@ import { | |||
16 | ActivityUrlObject, | 17 | ActivityUrlObject, |
17 | ActivityVideoUrlObject | 18 | ActivityVideoUrlObject |
18 | } from '../../../shared/index' | 19 | } from '../../../shared/index' |
19 | import { ActivityIconObject, VideoObject } from '../../../shared/models/activitypub/objects' | 20 | import { ActivityIconObject, ActivityTrackerUrlObject, VideoObject } from '../../../shared/models/activitypub/objects' |
20 | import { VideoPrivacy } from '../../../shared/models/videos' | 21 | import { VideoPrivacy } from '../../../shared/models/videos' |
21 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' | 22 | import { ThumbnailType } from '../../../shared/models/videos/thumbnail.type' |
22 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' | 23 | import { VideoStreamingPlaylistType } from '../../../shared/models/videos/video-streaming-playlist.type' |
23 | import { buildRemoteVideoBaseUrl, checkUrlsSameHost, getAPId } from '../../helpers/activitypub' | 24 | import { buildRemoteVideoBaseUrl, checkUrlsSameHost, getAPId } from '../../helpers/activitypub' |
24 | import { isAPVideoFileMetadataObject, sanitizeAndCheckVideoTorrentObject } from '../../helpers/custom-validators/activitypub/videos' | 25 | import { |
26 | isAPVideoFileUrlMetadataObject, | ||
27 | isAPVideoTrackerUrlObject, | ||
28 | sanitizeAndCheckVideoTorrentObject | ||
29 | } from '../../helpers/custom-validators/activitypub/videos' | ||
25 | import { isArray } from '../../helpers/custom-validators/misc' | 30 | import { isArray } from '../../helpers/custom-validators/misc' |
26 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' | 31 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' |
27 | import { deleteNonExistingModels, resetSequelizeInstance, retryTransactionWrapper } from '../../helpers/database-utils' | 32 | import { deleteNonExistingModels, resetSequelizeInstance, retryTransactionWrapper } from '../../helpers/database-utils' |
@@ -83,7 +88,7 @@ import { addVideoShares, shareVideoByServerAndChannel } from './share' | |||
83 | import { addVideoComments } from './video-comments' | 88 | import { addVideoComments } from './video-comments' |
84 | import { createRates } from './video-rates' | 89 | import { createRates } from './video-rates' |
85 | 90 | ||
86 | async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: sequelize.Transaction) { | 91 | async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVideo: boolean, transaction?: Transaction) { |
87 | const video = videoArg as MVideoAP | 92 | const video = videoArg as MVideoAP |
88 | 93 | ||
89 | if ( | 94 | if ( |
@@ -433,6 +438,12 @@ async function updateVideoFromAP (options: { | |||
433 | await setVideoTags({ video: videoUpdated, tags, transaction: t, defaultValue: videoUpdated.Tags }) | 438 | await setVideoTags({ video: videoUpdated, tags, transaction: t, defaultValue: videoUpdated.Tags }) |
434 | } | 439 | } |
435 | 440 | ||
441 | // Update trackers | ||
442 | { | ||
443 | const trackers = getTrackerUrls(videoObject, videoUpdated) | ||
444 | await setVideoTrackers({ video: videoUpdated, trackers, transaction: t }) | ||
445 | } | ||
446 | |||
436 | { | 447 | { |
437 | // Update captions | 448 | // Update captions |
438 | await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(videoUpdated.id, t) | 449 | await VideoCaptionModel.deleteAllCaptionsOfRemoteVideo(videoUpdated.id, t) |
@@ -577,7 +588,7 @@ function isAPVideoUrlObject (url: any): url is ActivityVideoUrlObject { | |||
577 | return MIMETYPES.VIDEO.MIMETYPE_EXT[urlMediaType] && urlMediaType.startsWith('video/') | 588 | return MIMETYPES.VIDEO.MIMETYPE_EXT[urlMediaType] && urlMediaType.startsWith('video/') |
578 | } | 589 | } |
579 | 590 | ||
580 | function isAPStreamingPlaylistUrlObject (url: ActivityUrlObject): url is ActivityPlaylistUrlObject { | 591 | function isAPStreamingPlaylistUrlObject (url: any): url is ActivityPlaylistUrlObject { |
581 | return url && url.mediaType === 'application/x-mpegURL' | 592 | return url && url.mediaType === 'application/x-mpegURL' |
582 | } | 593 | } |
583 | 594 | ||
@@ -671,6 +682,12 @@ async function createVideo (videoObject: VideoObject, channel: MChannelAccountLi | |||
671 | }) | 682 | }) |
672 | await Promise.all(videoCaptionsPromises) | 683 | await Promise.all(videoCaptionsPromises) |
673 | 684 | ||
685 | // Process trackers | ||
686 | { | ||
687 | const trackers = getTrackerUrls(videoObject, videoCreated) | ||
688 | await setVideoTrackers({ video: videoCreated, trackers, transaction: t }) | ||
689 | } | ||
690 | |||
674 | videoCreated.VideoFiles = videoFiles | 691 | videoCreated.VideoFiles = videoFiles |
675 | 692 | ||
676 | if (videoCreated.isLive) { | 693 | if (videoCreated.isLive) { |
@@ -797,7 +814,7 @@ function videoFileActivityUrlToDBAttributes ( | |||
797 | : parsed.xs | 814 | : parsed.xs |
798 | 815 | ||
799 | // Fetch associated metadata url, if any | 816 | // Fetch associated metadata url, if any |
800 | const metadata = urls.filter(isAPVideoFileMetadataObject) | 817 | const metadata = urls.filter(isAPVideoFileUrlMetadataObject) |
801 | .find(u => { | 818 | .find(u => { |
802 | return u.height === fileUrl.height && | 819 | return u.height === fileUrl.height && |
803 | u.fps === fileUrl.fps && | 820 | u.fps === fileUrl.fps && |
@@ -889,3 +906,33 @@ function getPreviewUrl (previewIcon: ActivityIconObject, video: MVideoWithHost) | |||
889 | ? previewIcon.url | 906 | ? previewIcon.url |
890 | : buildRemoteVideoBaseUrl(video, join(LAZY_STATIC_PATHS.PREVIEWS, video.generatePreviewName())) | 907 | : buildRemoteVideoBaseUrl(video, join(LAZY_STATIC_PATHS.PREVIEWS, video.generatePreviewName())) |
891 | } | 908 | } |
909 | |||
910 | function getTrackerUrls (object: VideoObject, video: MVideoWithHost) { | ||
911 | let wsFound = false | ||
912 | |||
913 | const trackers = object.url.filter(u => isAPVideoTrackerUrlObject(u)) | ||
914 | .map((u: ActivityTrackerUrlObject) => { | ||
915 | if (u.rel.includes('websocket')) wsFound = true | ||
916 | |||
917 | return u.href | ||
918 | }) | ||
919 | |||
920 | if (wsFound) return trackers | ||
921 | |||
922 | return [ | ||
923 | buildRemoteVideoBaseUrl(video, '/tracker/socket', REMOTE_SCHEME.WS), | ||
924 | buildRemoteVideoBaseUrl(video, '/tracker/announce') | ||
925 | ] | ||
926 | } | ||
927 | |||
928 | async function setVideoTrackers (options: { | ||
929 | video: MVideo | ||
930 | trackers: string[] | ||
931 | transaction?: Transaction | ||
932 | }) { | ||
933 | const { video, trackers, transaction } = options | ||
934 | |||
935 | const trackerInstances = await TrackerModel.findOrCreateTrackers(trackers, transaction) | ||
936 | |||
937 | await video.$set('Trackers', trackerInstances, { transaction }) | ||
938 | } | ||