const followersMatrix = await ActorModel.getActorsFollowerSharedInboxUrls(actors, undefined)
for (const video of data.data) {
- const videoObject = video.toActivityPubObject()
-
const byActor = video.VideoChannel.Account.Actor
const createActivityAudience = buildAudience(followersMatrix[byActor.id])
// This is a shared video
if (video.VideoShares !== undefined && video.VideoShares.length !== 0) {
- const createActivity = await createActivityData(video.url, byActor, videoObject, undefined, createActivityAudience)
-
const announceAudience = buildAudience(followersMatrix[actor.id])
const url = getAnnounceActivityPubUrl(video.url, actor)
- const announceActivity = await announceActivityData(url, actor, createActivity, undefined, announceAudience)
+ const announceActivity = await announceActivityData(url, actor, video.url, undefined, announceAudience)
activities.push(announceActivity)
} else {
+ const videoObject = video.toActivityPubObject()
const createActivity = await createActivityData(video.url, byActor, videoObject, undefined, createActivityAudience)
activities.push(createActivity)
import { isActivityPubUrlValid, isBaseActivityValid } from './misc'
-import { isVideoTorrentCreateActivityValid } from './videos'
function isAnnounceActivityValid (activity: any) {
return isBaseActivityValid(activity, 'Announce') &&
(
- isVideoTorrentCreateActivityValid(activity.object) ||
- isActivityPubUrlValid(activity.object)
+ isActivityPubUrlValid(activity.object) ||
+ (activity.object && isActivityPubUrlValid(activity.object.id))
)
}
import { ActivityAnnounce } from '../../../../shared/models/activitypub'
import { retryTransactionWrapper } from '../../../helpers/database-utils'
-import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers'
import { ActorModel } from '../../../models/activitypub/actor'
import { VideoModel } from '../../../models/video/video'
import { getOrCreateActorAndServerAndModel } from '../actor'
import { forwardActivity } from '../send/misc'
import { getOrCreateAccountAndVideoAndChannel } from '../videos'
-import { processCreateActivity } from './process-create'
async function processAnnounceActivity (activity: ActivityAnnounce) {
- const announcedActivity = activity.object
const actorAnnouncer = await getOrCreateActorAndServerAndModel(activity.actor)
- if (typeof announcedActivity === 'string') {
- return processVideoShare(actorAnnouncer, activity)
- } else if (announcedActivity.type === 'Create' && announcedActivity.object.type === 'Video') {
- return processVideoShare(actorAnnouncer, activity)
- }
-
- logger.warn(
- 'Unknown activity object type %s -> %s when announcing activity.', announcedActivity.type, announcedActivity.object.type,
- { activity: activity.id }
- )
-
- return undefined
+ return processVideoShare(actorAnnouncer, activity)
}
// ---------------------------------------------------------------------------
}
async function shareVideo (actorAnnouncer: ActorModel, activity: ActivityAnnounce) {
- const announced = activity.object
+ const objectUri = typeof activity.object === 'string' ? activity.object : activity.object.id
let video: VideoModel
- if (typeof announced === 'string') {
- const res = await getOrCreateAccountAndVideoAndChannel(announced)
- video = res.video
- } else {
- video = await processCreateActivity(announced)
- }
+ const res = await getOrCreateAccountAndVideoAndChannel(objectUri)
+ video = res.video
return sequelizeTypescript.transaction(async t => {
// Add share entry
-import * as Bluebird from 'bluebird'
import { ActivityCreate, VideoTorrentObject } from '../../../../shared'
import { DislikeObject, VideoAbuseObject, ViewObject } from '../../../../shared/models/activitypub/objects'
import { VideoCommentObject } from '../../../../shared/models/activitypub/objects/video-comment-object'
-import { VideoRateType } from '../../../../shared/models/videos'
import { retryTransactionWrapper } from '../../../helpers/database-utils'
import { logger } from '../../../helpers/logger'
import { sequelizeTypescript } from '../../../initializers'
import { AccountVideoRateModel } from '../../../models/account/account-video-rate'
import { ActorModel } from '../../../models/activitypub/actor'
-import { VideoModel } from '../../../models/video/video'
import { VideoAbuseModel } from '../../../models/video/video-abuse'
import { VideoCommentModel } from '../../../models/video/video-comment'
import { getOrCreateActorAndServerAndModel } from '../actor'
import { forwardActivity, getActorsInvolvedInVideo } from '../send/misc'
-import { addVideoComments, resolveThread } from '../video-comments'
-import { addVideoShares, getOrCreateAccountAndVideoAndChannel } from '../videos'
+import { resolveThread } from '../video-comments'
+import { getOrCreateAccountAndVideoAndChannel } from '../videos'
async function processCreateActivity (activity: ActivityCreate) {
const activityObject = activity.object
const { video } = await getOrCreateAccountAndVideoAndChannel(videoToCreateData, actor)
- // Process outside the transaction because we could fetch remote data
- if (videoToCreateData.likes && Array.isArray(videoToCreateData.likes.orderedItems)) {
- logger.info('Adding likes of video %s.', video.uuid)
- await createRates(videoToCreateData.likes.orderedItems, video, 'like')
- }
-
- if (videoToCreateData.dislikes && Array.isArray(videoToCreateData.dislikes.orderedItems)) {
- logger.info('Adding dislikes of video %s.', video.uuid)
- await createRates(videoToCreateData.dislikes.orderedItems, video, 'dislike')
- }
-
- if (videoToCreateData.shares && Array.isArray(videoToCreateData.shares.orderedItems)) {
- logger.info('Adding shares of video %s.', video.uuid)
- await addVideoShares(video, videoToCreateData.shares.orderedItems)
- }
-
- if (videoToCreateData.comments && Array.isArray(videoToCreateData.comments.orderedItems)) {
- logger.info('Adding comments of video %s.', video.uuid)
- await addVideoComments(video, videoToCreateData.comments.orderedItems)
- }
-
return video
}
-async function createRates (actorUrls: string[], video: VideoModel, rate: VideoRateType) {
- let rateCounts = 0
- const tasks: Bluebird<number>[] = []
-
- for (const actorUrl of actorUrls) {
- const actor = await getOrCreateActorAndServerAndModel(actorUrl)
- const p = AccountVideoRateModel
- .create({
- videoId: video.id,
- accountId: actor.Account.id,
- type: rate
- })
- .then(() => rateCounts += 1)
-
- tasks.push(p)
- }
-
- await Promise.all(tasks)
-
- logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid)
-
- // This is "likes" and "dislikes"
- await video.increment(rate + 's', { by: rateCounts })
-
- return
-}
-
async function processCreateDislike (byActor: ActorModel, activity: ActivityCreate) {
const options = {
arguments: [ byActor, activity ],
import { Transaction } from 'sequelize'
-import { ActivityAnnounce, ActivityAudience, ActivityCreate } from '../../../../shared/models/activitypub'
-import { VideoPrivacy } from '../../../../shared/models/videos'
+import { ActivityAnnounce, ActivityAudience } from '../../../../shared/models/activitypub'
import { ActorModel } from '../../../models/activitypub/actor'
import { VideoModel } from '../../../models/video/video'
import { getAnnounceActivityPubUrl } from '../url'
async function buildVideoAnnounceToFollowers (byActor: ActorModel, video: VideoModel, t: Transaction) {
const url = getAnnounceActivityPubUrl(video.url, byActor)
- const videoObject = video.toActivityPubObject()
-
- const announcedAudience = await getAudience(byActor, t, video.privacy === VideoPrivacy.PUBLIC)
- const announcedActivity = await createActivityData(url, video.VideoChannel.Account.Actor, videoObject, t, announcedAudience)
+ const announcedObject = video.url
const accountsToForwardView = await getActorsInvolvedInVideo(video, t)
const audience = getObjectFollowersAudience(accountsToForwardView)
- return announceActivityData(url, byActor, announcedActivity, t, audience)
+ return announceActivityData(url, byActor, announcedObject, t, audience)
}
async function sendVideoAnnounceToFollowers (byActor: ActorModel, video: VideoModel, t: Transaction) {
async function announceActivityData (
url: string,
byActor: ActorModel,
- object: ActivityCreate,
+ object: string,
t: Transaction,
audience?: ActivityAudience
): Promise<ActivityAnnounce> {
+import * as Bluebird from 'bluebird'
import * as magnetUtil from 'magnet-uri'
import { join } from 'path'
import * as request from 'request'
import { ActivityIconObject } from '../../../shared/index'
import { VideoTorrentObject } from '../../../shared/models/activitypub/objects'
-import { VideoPrivacy } from '../../../shared/models/videos'
+import { VideoPrivacy, VideoRateType } from '../../../shared/models/videos'
import { isVideoTorrentObjectValid } from '../../helpers/custom-validators/activitypub/videos'
import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos'
import { retryTransactionWrapper } from '../../helpers/database-utils'
import { logger } from '../../helpers/logger'
import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests'
import { ACTIVITY_PUB, CONFIG, REMOTE_SCHEME, sequelizeTypescript, STATIC_PATHS, VIDEO_MIMETYPE_EXT } from '../../initializers'
+import { AccountVideoRateModel } from '../../models/account/account-video-rate'
import { ActorModel } from '../../models/activitypub/actor'
import { TagModel } from '../../models/video/tag'
import { VideoModel } from '../../models/video/video'
import { VideoFileModel } from '../../models/video/video-file'
import { VideoShareModel } from '../../models/video/video-share'
import { getOrCreateActorAndServerAndModel } from './actor'
+import { addVideoComments } from './video-comments'
function fetchRemoteVideoPreview (video: VideoModel, reject: Function) {
const host = video.VideoChannel.Account.Actor.Server.host
const video = await retryTransactionWrapper(getOrCreateVideo, options)
+ // Process outside the transaction because we could fetch remote data
+ if (videoObject.likes && Array.isArray(videoObject.likes.orderedItems)) {
+ logger.info('Adding likes of video %s.', video.uuid)
+ await createRates(videoObject.likes.orderedItems, video, 'like')
+ }
+
+ if (videoObject.dislikes && Array.isArray(videoObject.dislikes.orderedItems)) {
+ logger.info('Adding dislikes of video %s.', video.uuid)
+ await createRates(videoObject.dislikes.orderedItems, video, 'dislike')
+ }
+
+ if (videoObject.shares && Array.isArray(videoObject.shares.orderedItems)) {
+ logger.info('Adding shares of video %s.', video.uuid)
+ await addVideoShares(video, videoObject.shares.orderedItems)
+ }
+
+ if (videoObject.comments && Array.isArray(videoObject.comments.orderedItems)) {
+ logger.info('Adding comments of video %s.', video.uuid)
+ await addVideoComments(video, videoObject.comments.orderedItems)
+ }
+
return { actor, channelActor, video }
}
+async function createRates (actorUrls: string[], video: VideoModel, rate: VideoRateType) {
+ let rateCounts = 0
+ const tasks: Bluebird<number>[] = []
+
+ for (const actorUrl of actorUrls) {
+ const actor = await getOrCreateActorAndServerAndModel(actorUrl)
+ const p = AccountVideoRateModel
+ .create({
+ videoId: video.id,
+ accountId: actor.Account.id,
+ type: rate
+ })
+ .then(() => rateCounts += 1)
+
+ tasks.push(p)
+ }
+
+ await Promise.all(tasks)
+
+ logger.info('Adding %d %s to video %s.', rateCounts, rate, video.uuid)
+
+ // This is "likes" and "dislikes"
+ await video.increment(rate + 's', { by: rateCounts })
+
+ return
+}
+
async function addVideoShares (instance: VideoModel, shareUrls: string[]) {
for (const shareUrl of shareUrls) {
// Fetch url
export interface ActivityAnnounce extends BaseActivity {
type: 'Announce'
- object: ActivityCreate | string
+ object: string | { id: string }
}
export interface ActivityUndo extends BaseActivity {