Fix lint
[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 processFollow(actor, activityObject)
15 }
16
17 // ---------------------------------------------------------------------------
18
19 export {
20   processFollowActivity
21 }
22
23 // ---------------------------------------------------------------------------
24
25 function processFollow (actor: ActorModel, targetActorURL: string) {
26   const options = {
27     arguments: [ actor, targetActorURL ],
28     errorMessage: 'Cannot follow with many retries.'
29   }
30
31   return retryTransactionWrapper(follow, options)
32 }
33
34 async function follow (actor: ActorModel, targetActorURL: string) {
35   await sequelizeTypescript.transaction(async t => {
36     const targetActor = await ActorModel.loadByUrl(targetActorURL, t)
37
38     if (!targetActor) throw new Error('Unknown actor')
39     if (targetActor.isOwned() === false) throw new Error('This is not a local actor.')
40
41     const [ actorFollow ] = await ActorFollowModel.findOrCreate({
42       where: {
43         actorId: actor.id,
44         targetActorId: targetActor.id
45       },
46       defaults: {
47         actorId: actor.id,
48         targetActorId: targetActor.id,
49         state: 'accepted'
50       },
51       transaction: t
52     })
53
54     actorFollow.ActorFollower = actor
55     actorFollow.ActorFollowing = targetActor
56
57     if (actorFollow.state !== 'accepted') {
58       actorFollow.state = 'accepted'
59       await actorFollow.save({ transaction: t })
60     }
61
62     actorFollow.ActorFollower = actor
63     actorFollow.ActorFollowing = targetActor
64
65     // Target sends to actor he accepted the follow request
66     return sendAccept(actorFollow, t)
67   })
68
69   logger.info('Actor %s is followed by actor %s.', targetActorURL, actor.url)
70 }