Federate video update
This commit is contained in:
parent
20494f1221
commit
d7d5611c8a
|
@ -25,12 +25,8 @@ function videoChannelActivityObjectToDBAttributes (videoChannelObject: VideoChan
|
|||
|
||||
async function videoActivityObjectToDBAttributes (
|
||||
videoChannel: VideoChannelInstance,
|
||||
videoObject: VideoTorrentObject,
|
||||
t: Sequelize.Transaction
|
||||
videoObject: VideoTorrentObject
|
||||
) {
|
||||
const videoFromDatabase = await db.Video.loadByUUIDOrURL(videoObject.uuid, videoObject.id, t)
|
||||
if (videoFromDatabase) throw new Error('Video with this UUID/Url already exists.')
|
||||
|
||||
const duration = videoObject.duration.replace(/[^\d]+/, '')
|
||||
const videoData: VideoAttributes = {
|
||||
name: videoObject.name,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import * as Bluebird from 'bluebird'
|
||||
import { VideoTorrentObject } from '../../../shared'
|
||||
import { ActivityAdd } from '../../../shared/models/activitypub/activity'
|
||||
import { generateThumbnailFromUrl, logger, retryTransactionWrapper, getOrCreateAccount } from '../../helpers'
|
||||
import { generateThumbnailFromUrl, getOrCreateAccount, logger, retryTransactionWrapper } from '../../helpers'
|
||||
import { getOrCreateVideoChannel } from '../../helpers/activitypub'
|
||||
import { database as db } from '../../initializers'
|
||||
import { AccountInstance } from '../../models/account/account-interface'
|
||||
import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
|
||||
import Bluebird = require('bluebird')
|
||||
import { getOrCreateVideoChannel } from '../../helpers/activitypub'
|
||||
import { VideoChannelInstance } from '../../models/video/video-channel-interface'
|
||||
import { videoActivityObjectToDBAttributes, videoFileActivityUrlToDBAttributes } from './misc'
|
||||
|
||||
async function processAddActivity (activity: ActivityAdd) {
|
||||
const activityObject = activity.object
|
||||
|
@ -51,7 +51,10 @@ function addRemoteVideo (account: AccountInstance, videoChannel: VideoChannelIns
|
|||
|
||||
if (videoChannel.Account.id !== account.id) throw new Error('Video channel is not owned by this account.')
|
||||
|
||||
const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoToCreateData, t)
|
||||
const videoFromDatabase = await db.Video.loadByUUIDOrURL(videoToCreateData.uuid, videoToCreateData.id, t)
|
||||
if (videoFromDatabase) throw new Error('Video with this UUID/Url already exists.')
|
||||
|
||||
const videoData = await videoActivityObjectToDBAttributes(videoChannel, videoToCreateData)
|
||||
const video = db.Video.build(videoData)
|
||||
|
||||
// Don't block on request
|
||||
|
|
|
@ -69,7 +69,7 @@ function addRemoteVideoAbuse (account: AccountInstance, videoAbuseToCreateData:
|
|||
logger.debug('Reporting remote abuse for video %s.', videoAbuseToCreateData.object)
|
||||
|
||||
return db.sequelize.transaction(async t => {
|
||||
const video = await db.Video.loadByUrl(videoAbuseToCreateData.object, t)
|
||||
const video = await db.Video.loadByUrlAndPopulateAccount(videoAbuseToCreateData.object, t)
|
||||
if (!video) {
|
||||
logger.warn('Unknown video %s for remote video abuse.', videoAbuseToCreateData.object)
|
||||
return
|
||||
|
|
|
@ -15,7 +15,7 @@ async function processDeleteActivity (activity: ActivityDelete) {
|
|||
}
|
||||
|
||||
{
|
||||
let videoObject = await db.Video.loadByUrl(activity.id)
|
||||
let videoObject = await db.Video.loadByUrlAndPopulateAccount(activity.id)
|
||||
if (videoObject !== undefined) {
|
||||
return processDeleteVideo(account, videoObject)
|
||||
}
|
||||
|
|
|
@ -50,14 +50,14 @@ async function updateRemoteVideo (account: AccountInstance, videoAttributesToUpd
|
|||
transaction: t
|
||||
}
|
||||
|
||||
const videoInstance = await db.Video.loadByUrl(videoAttributesToUpdate.id, t)
|
||||
const videoInstance = await db.Video.loadByUrlAndPopulateAccount(videoAttributesToUpdate.id, t)
|
||||
if (!videoInstance) throw new Error('Video ' + videoAttributesToUpdate.id + ' not found.')
|
||||
|
||||
if (videoInstance.VideoChannel.Account.id !== account.id) {
|
||||
throw new Error('Account ' + account.url + ' does not own video channel ' + videoInstance.VideoChannel.url)
|
||||
}
|
||||
|
||||
const videoData = await videoActivityObjectToDBAttributes(videoInstance.VideoChannel, videoAttributesToUpdate, t)
|
||||
const videoData = await videoActivityObjectToDBAttributes(videoInstance.VideoChannel, videoAttributesToUpdate)
|
||||
videoInstance.set('name', videoData.name)
|
||||
videoInstance.set('category', videoData.category)
|
||||
videoInstance.set('licence', videoData.licence)
|
||||
|
|
|
@ -24,13 +24,19 @@ async function sendUpdateVideoChannel (videoChannel: VideoChannelInstance, t: Se
|
|||
const videoChannelObject = videoChannel.toActivityPubObject()
|
||||
const data = await updateActivityData(videoChannel.url, videoChannel.Account, videoChannelObject)
|
||||
|
||||
return broadcastToFollowers(data, [ videoChannel.Account ], t)
|
||||
const accountsInvolved = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id)
|
||||
accountsInvolved.push(videoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, accountsInvolved, t)
|
||||
}
|
||||
|
||||
async function sendDeleteVideoChannel (videoChannel: VideoChannelInstance, t: Sequelize.Transaction) {
|
||||
const data = await deleteActivityData(videoChannel.url, videoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, [ videoChannel.Account ], t)
|
||||
const accountsInvolved = await db.VideoChannelShare.loadAccountsByShare(videoChannel.id)
|
||||
accountsInvolved.push(videoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, accountsInvolved, t)
|
||||
}
|
||||
|
||||
async function sendAddVideo (video: VideoInstance, t: Sequelize.Transaction) {
|
||||
|
@ -44,13 +50,19 @@ async function sendUpdateVideo (video: VideoInstance, t: Sequelize.Transaction)
|
|||
const videoObject = video.toActivityPubObject()
|
||||
const data = await updateActivityData(video.url, video.VideoChannel.Account, videoObject)
|
||||
|
||||
return broadcastToFollowers(data, [ video.VideoChannel.Account ], t)
|
||||
const accountsInvolved = await db.VideoShare.loadAccountsByShare(video.id)
|
||||
accountsInvolved.push(video.VideoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, accountsInvolved, t)
|
||||
}
|
||||
|
||||
async function sendDeleteVideo (video: VideoInstance, t: Sequelize.Transaction) {
|
||||
const data = await deleteActivityData(video.url, video.VideoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, [ video.VideoChannel.Account ], t)
|
||||
const accountsInvolved = await db.VideoShare.loadAccountsByShare(video.id)
|
||||
accountsInvolved.push(video.VideoChannel.Account)
|
||||
|
||||
return broadcastToFollowers(data, accountsInvolved, t)
|
||||
}
|
||||
|
||||
async function sendDeleteAccount (account: AccountInstance, t: Sequelize.Transaction) {
|
||||
|
|
|
@ -187,13 +187,13 @@ async function createListAcceptedFollowForApiQuery (
|
|||
let query = 'SELECT ' + selection + ' FROM "Accounts" ' +
|
||||
'INNER JOIN "AccountFollows" ON "AccountFollows"."' + firstJoin + '" = "Accounts"."id" ' +
|
||||
'INNER JOIN "Accounts" AS "Follows" ON "AccountFollows"."' + secondJoin + '" = "Follows"."id" ' +
|
||||
'WHERE "Accounts"."id" IN ($accountIds) AND "AccountFollows"."state" = \'accepted\' '
|
||||
'WHERE "Accounts"."id" = ANY ($accountIds) AND "AccountFollows"."state" = \'accepted\' '
|
||||
|
||||
if (start !== undefined) query += 'LIMIT ' + start
|
||||
if (count !== undefined) query += ', ' + count
|
||||
|
||||
const options = {
|
||||
bind: { accountIds: accountIds.join(',') },
|
||||
bind: { accountIds },
|
||||
type: Sequelize.QueryTypes.SELECT
|
||||
}
|
||||
tasks.push(AccountFollow['sequelize'].query(query, options))
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import * as Bluebird from 'bluebird'
|
||||
import * as Sequelize from 'sequelize'
|
||||
import { AccountInstance } from '../account/account-interface'
|
||||
import { VideoChannelInstance } from './video-channel-interface'
|
||||
|
||||
export namespace VideoChannelShareMethods {
|
||||
export type LoadAccountsByShare = (videoChannelId: number) => Bluebird<AccountInstance[]>
|
||||
}
|
||||
|
||||
export interface VideoChannelShareClass {
|
||||
loadAccountsByShare: VideoChannelShareMethods.LoadAccountsByShare
|
||||
}
|
||||
|
||||
export interface VideoChannelShareAttributes {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from '../utils'
|
||||
import { VideoChannelShareAttributes, VideoChannelShareInstance } from './video-channel-share-interface'
|
||||
import { VideoChannelShareAttributes, VideoChannelShareInstance, VideoChannelShareMethods } from './video-channel-share-interface'
|
||||
|
||||
let VideoChannelShare: Sequelize.Model<VideoChannelShareInstance, VideoChannelShareAttributes>
|
||||
let loadAccountsByShare: VideoChannelShareMethods.LoadAccountsByShare
|
||||
|
||||
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||
VideoChannelShare = sequelize.define<VideoChannelShareInstance, VideoChannelShareAttributes>('VideoChannelShare',
|
||||
|
@ -21,7 +22,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
)
|
||||
|
||||
const classMethods = [
|
||||
associate
|
||||
associate,
|
||||
loadAccountsByShare
|
||||
]
|
||||
addMethodsToModel(VideoChannelShare, classMethods)
|
||||
|
||||
|
@ -47,3 +49,20 @@ function associate (models) {
|
|||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
loadAccountsByShare = function (videoChannelId: number) {
|
||||
const query = {
|
||||
where: {
|
||||
videoChannelId
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: VideoChannelShare['sequelize'].models.Account,
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return VideoChannelShare.findAll(query)
|
||||
.then(res => res.map(r => r.Account))
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ export namespace VideoMethods {
|
|||
|
||||
export type Load = (id: number) => Bluebird<VideoInstance>
|
||||
export type LoadByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||
export type LoadByUrl = (url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||
export type LoadByUrlAndPopulateAccount = (url: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||
export type LoadLocalVideoByUUID = (uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||
export type LoadByHostAndUUID = (fromHost: string, uuid: string, t?: Sequelize.Transaction) => Bluebird<VideoInstance>
|
||||
export type LoadAndPopulateAccount = (id: number) => Bluebird<VideoInstance>
|
||||
|
@ -82,7 +82,7 @@ export interface VideoClass {
|
|||
loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
|
||||
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
||||
loadByUUID: VideoMethods.LoadByUUID
|
||||
loadByUrl: VideoMethods.LoadByUrl
|
||||
loadByUrlAndPopulateAccount: VideoMethods.LoadByUrlAndPopulateAccount
|
||||
loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
||||
loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
||||
loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
import { AccountInstance } from '../account/account-interface'
|
||||
import { VideoInstance } from './video-interface'
|
||||
import * as Bluebird from 'bluebird'
|
||||
|
||||
export namespace VideoShareMethods {
|
||||
export type LoadAccountsByShare = (videoChannelId: number) => Bluebird<AccountInstance[]>
|
||||
}
|
||||
|
||||
export interface VideoShareClass {
|
||||
loadAccountsByShare: VideoShareMethods.LoadAccountsByShare
|
||||
}
|
||||
|
||||
export interface VideoShareAttributes {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as Sequelize from 'sequelize'
|
||||
|
||||
import { addMethodsToModel } from '../utils'
|
||||
import { VideoShareAttributes, VideoShareInstance } from './video-share-interface'
|
||||
import { VideoShareAttributes, VideoShareInstance, VideoShareMethods } from './video-share-interface'
|
||||
|
||||
let VideoShare: Sequelize.Model<VideoShareInstance, VideoShareAttributes>
|
||||
let loadAccountsByShare: VideoShareMethods.LoadAccountsByShare
|
||||
|
||||
export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.DataTypes) {
|
||||
VideoShare = sequelize.define<VideoShareInstance, VideoShareAttributes>('VideoShare',
|
||||
|
@ -21,7 +22,8 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
)
|
||||
|
||||
const classMethods = [
|
||||
associate
|
||||
associate,
|
||||
loadAccountsByShare
|
||||
]
|
||||
addMethodsToModel(VideoShare, classMethods)
|
||||
|
||||
|
@ -47,3 +49,20 @@ function associate (models) {
|
|||
onDelete: 'cascade'
|
||||
})
|
||||
}
|
||||
|
||||
loadAccountsByShare = function (videoId: number) {
|
||||
const query = {
|
||||
where: {
|
||||
videoId
|
||||
},
|
||||
include: [
|
||||
{
|
||||
model: VideoShare['sequelize'].models.Account,
|
||||
required: true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return VideoShare.findAll(query)
|
||||
.then(res => res.map(r => r.Account))
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ let loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
|
|||
let listOwnedAndPopulateAccountAndTags: VideoMethods.ListOwnedAndPopulateAccountAndTags
|
||||
let listOwnedByAccount: VideoMethods.ListOwnedByAccount
|
||||
let load: VideoMethods.Load
|
||||
let loadByUrlAndPopulateAccount: VideoMethods.LoadByUrlAndPopulateAccount
|
||||
let loadByUUID: VideoMethods.LoadByUUID
|
||||
let loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
|
||||
let loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
|
||||
|
@ -271,6 +272,7 @@ export default function (sequelize: Sequelize.Sequelize, DataTypes: Sequelize.Da
|
|||
listOwnedAndPopulateAccountAndTags,
|
||||
listOwnedByAccount,
|
||||
load,
|
||||
loadByUrlAndPopulateAccount,
|
||||
loadAndPopulateAccount,
|
||||
loadAndPopulateAccountAndServerAndTags,
|
||||
loadByHostAndUUID,
|
||||
|
@ -936,6 +938,25 @@ loadByUUID = function (uuid: string, t?: Sequelize.Transaction) {
|
|||
return Video.findOne(query)
|
||||
}
|
||||
|
||||
loadByUrlAndPopulateAccount = function (url: string, t?: Sequelize.Transaction) {
|
||||
const query: Sequelize.FindOptions<VideoAttributes> = {
|
||||
where: {
|
||||
url
|
||||
},
|
||||
include: [
|
||||
Video['sequelize'].models.VideoFile,
|
||||
{
|
||||
model: Video['sequelize'].models.VideoChannel,
|
||||
include: [ Video['sequelize'].models.Account ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
if (t !== undefined) query.transaction = t
|
||||
|
||||
return Video.findOne(query)
|
||||
}
|
||||
|
||||
loadByUUIDOrURL = function (uuid: string, url: string, t?: Sequelize.Transaction) {
|
||||
const query: Sequelize.FindOptions<VideoAttributes> = {
|
||||
where: {
|
||||
|
|
Loading…
Reference in New Issue