Optimize video view AP processing
[oweals/peertube.git] / server / lib / activitypub / process / process-follow.ts
1 import { ActivityFollow } from '../../../../shared/models/activitypub'
2 import { retryTransactionWrapper } from '../../../helpers/database-utils'
3 import { logger } from '../../../helpers/logger'
4 import { sequelizeTypescript } from '../../../initializers'
5 import { ActorModel } from '../../../models/activitypub/actor'
6 import { ActorFollowModel } from '../../../models/activitypub/actor-follow'
7 import { getOrCreateActorAndServerAndModel } from '../actor'
8 import { sendAccept } from '../send'
9
10 async function processFollowActivity (activity: ActivityFollow) {
11   const activityObject = activity.object
12   const actor = await getOrCreateActorAndServerAndModel(activity.actor)
13
14   return retryTransactionWrapper(processFollow, actor, activityObject)
15 }
16
17 // ---------------------------------------------------------------------------
18
19 export {
20   processFollowActivity
21 }
22
23 // ---------------------------------------------------------------------------
24
25 async function processFollow (actor: ActorModel, targetActorURL: string) {
26   await sequelizeTypescript.transaction(async t => {
27     const targetActor = await ActorModel.loadByUrl(targetActorURL, t)
28
29     if (!targetActor) throw new Error('Unknown actor')
30     if (targetActor.isOwned() === false) throw new Error('This is not a local actor.')
31
32     const [ actorFollow ] = await ActorFollowModel.findOrCreate({
33       where: {
34         actorId: actor.id,
35         targetActorId: targetActor.id
36       },
37       defaults: {
38         actorId: actor.id,
39         targetActorId: targetActor.id,
40         state: 'accepted'
41       },
42       transaction: t
43     })
44
45     actorFollow.ActorFollower = actor
46     actorFollow.ActorFollowing = targetActor
47
48     if (actorFollow.state !== 'accepted') {
49       actorFollow.state = 'accepted'
50       await actorFollow.save({ transaction: t })
51     }
52
53     actorFollow.ActorFollower = actor
54     actorFollow.ActorFollowing = targetActor
55
56     // Target sends to actor he accepted the follow request
57     return sendAccept(actorFollow)
58   })
59
60   logger.info('Actor %s is followed by actor %s.', targetActorURL, actor.url)
61 }