1 import * as magnetUtil from 'magnet-uri'
2 import { VideoTorrentObject } from '../../../../shared'
3 import { VideoChannelObject } from '../../../../shared/models/activitypub/objects'
4 import { VideoPrivacy } from '../../../../shared/models/videos'
5 import { doRequest } from '../../../helpers'
6 import { isVideoFileInfoHashValid } from '../../../helpers/custom-validators/videos'
7 import { ACTIVITY_PUB, VIDEO_MIMETYPE_EXT } from '../../../initializers'
8 import { AccountModel } from '../../../models/account/account'
9 import { VideoModel } from '../../../models/video/video'
10 import { VideoChannelModel } from '../../../models/video/video-channel'
11 import { VideoChannelShareModel } from '../../../models/video/video-channel-share'
12 import { VideoShareModel } from '../../../models/video/video-share'
13 import { getOrCreateAccountAndServer } from '../account'
15 function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChannelObject, account: AccountModel) {
17 name: videoChannelObject.name,
18 description: videoChannelObject.content,
19 uuid: videoChannelObject.uuid,
20 url: videoChannelObject.id,
21 createdAt: new Date(videoChannelObject.published),
22 updatedAt: new Date(videoChannelObject.updated),
28 async function videoActivityObjectToDBAttributes (
29 videoChannel: VideoChannelModel,
30 videoObject: VideoTorrentObject,
34 let privacy = VideoPrivacy.PRIVATE
35 if (to.indexOf(ACTIVITY_PUB.PUBLIC) !== -1) privacy = VideoPrivacy.PUBLIC
36 else if (cc.indexOf(ACTIVITY_PUB.PUBLIC) !== -1) privacy = VideoPrivacy.UNLISTED
38 const duration = videoObject.duration.replace(/[^\d]+/, '')
40 if (videoObject.language) {
41 language = parseInt(videoObject.language.identifier, 10)
45 if (videoObject.category) {
46 category = parseInt(videoObject.category.identifier, 10)
50 if (videoObject.licence) {
51 licence = parseInt(videoObject.licence.identifier, 10)
54 let description = null
55 if (videoObject.content) {
56 description = videoObject.content
60 name: videoObject.name,
61 uuid: videoObject.uuid,
67 nsfw: videoObject.nsfw,
68 channelId: videoChannel.id,
69 duration: parseInt(duration, 10),
70 createdAt: new Date(videoObject.published),
71 // FIXME: updatedAt does not seems to be considered by Sequelize
72 updatedAt: new Date(videoObject.updated),
73 views: videoObject.views,
81 function videoFileActivityUrlToDBAttributes (videoCreated: VideoModel, videoObject: VideoTorrentObject) {
82 const mimeTypes = Object.keys(VIDEO_MIMETYPE_EXT)
83 const fileUrls = videoObject.url.filter(u => {
84 return mimeTypes.indexOf(u.mimeType) !== -1 && u.mimeType.startsWith('video/')
87 if (fileUrls.length === 0) {
88 throw new Error('Cannot find video files for ' + videoCreated.url)
92 for (const fileUrl of fileUrls) {
93 // Fetch associated magnet uri
94 const magnet = videoObject.url.find(u => {
95 return u.mimeType === 'application/x-bittorrent;x-scheme-handler/magnet' && u.width === fileUrl.width
98 if (!magnet) throw new Error('Cannot find associated magnet uri for file ' + fileUrl.url)
100 const parsed = magnetUtil.decode(magnet.url)
101 if (!parsed || isVideoFileInfoHashValid(parsed.infoHash) === false) throw new Error('Cannot parse magnet URI ' + magnet.url)
104 extname: VIDEO_MIMETYPE_EXT[fileUrl.mimeType],
105 infoHash: parsed.infoHash,
106 resolution: fileUrl.width,
108 videoId: videoCreated.id
110 attributes.push(attribute)
116 async function addVideoShares (instance: VideoModel, shares: string[]) {
117 for (const share of shares) {
119 const json = await doRequest({
123 const actor = json['actor']
126 const account = await getOrCreateAccountAndServer(actor)
129 accountId: account.id,
133 await VideoShareModel.findOrCreate({
140 async function addVideoChannelShares (instance: VideoChannelModel, shares: string[]) {
141 for (const share of shares) {
143 const json = await doRequest({
147 const actor = json['actor']
150 const account = await getOrCreateAccountAndServer(actor)
153 accountId: account.id,
154 videoChannelId: instance.id
157 await VideoChannelShareModel.findOrCreate({
164 // ---------------------------------------------------------------------------
167 videoFileActivityUrlToDBAttributes,
168 videoActivityObjectToDBAttributes,
169 videoChannelActivityObjectToDBAttributes,
170 addVideoChannelShares,