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,
+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
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
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
}
{
- let videoObject = await db.Video.loadByUrl(activity.id)
+ let videoObject = await db.Video.loadByUrlAndPopulateAccount(activity.id)
if (videoObject !== undefined) {
return processDeleteVideo(account, videoObject)
}
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)
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) {
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) {
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))
+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 {
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',
)
const classMethods = [
- associate
+ associate,
+ loadAccountsByShare
]
addMethodsToModel(VideoChannelShare, classMethods)
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))
+}
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>
loadAndPopulateAccountAndServerAndTags: VideoMethods.LoadAndPopulateAccountAndServerAndTags
loadByHostAndUUID: VideoMethods.LoadByHostAndUUID
loadByUUID: VideoMethods.LoadByUUID
- loadByUrl: VideoMethods.LoadByUrl
+ loadByUrlAndPopulateAccount: VideoMethods.LoadByUrlAndPopulateAccount
loadByUUIDOrURL: VideoMethods.LoadByUUIDOrURL
loadLocalVideoByUUID: VideoMethods.LoadLocalVideoByUUID
loadByUUIDAndPopulateAccountAndServerAndTags: VideoMethods.LoadByUUIDAndPopulateAccountAndServerAndTags
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 {
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',
)
const classMethods = [
- associate
+ associate,
+ loadAccountsByShare
]
addMethodsToModel(VideoShare, classMethods)
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))
+}
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
listOwnedAndPopulateAccountAndTags,
listOwnedByAccount,
load,
+ loadByUrlAndPopulateAccount,
loadAndPopulateAccount,
loadAndPopulateAccountAndServerAndTags,
loadByHostAndUUID,
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: {