]>
Commit | Line | Data |
---|---|---|
94831479 | 1 | import * as Bull from 'bull' |
5350fd8e | 2 | import { logger } from '../../../helpers/logger' |
74dc3bca | 3 | import { REMOTE_SCHEME, WEBSERVER } from '../../../initializers/constants' |
5350fd8e C |
4 | import { sendFollow } from '../../activitypub/send' |
5 | import { sanitizeHost } from '../../../helpers/core-utils' | |
6 | import { loadActorUrlOrGetFromWebfinger } from '../../../helpers/webfinger' | |
7 | import { getOrCreateActorAndServerAndModel } from '../../activitypub/actor' | |
8 | import { retryTransactionWrapper } from '../../../helpers/database-utils' | |
9 | import { ActorFollowModel } from '../../../models/activitypub/actor-follow' | |
10 | import { ActorModel } from '../../../models/activitypub/actor' | |
f7cc67b4 | 11 | import { Notifier } from '../../notifier' |
74dc3bca | 12 | import { sequelizeTypescript } from '../../../initializers/database' |
8424c402 | 13 | import { MActor, MActorFollowActors, MActorFull } from '../../../typings/models' |
5350fd8e C |
14 | |
15 | export type ActivitypubFollowPayload = { | |
06a05d5f C |
16 | followerActorId: number |
17 | name: string | |
5350fd8e | 18 | host: string |
8424c402 | 19 | isAutoFollow?: boolean |
2c0ccd4b | 20 | assertIsChannel?: boolean |
5350fd8e C |
21 | } |
22 | ||
94831479 | 23 | async function processActivityPubFollow (job: Bull.Job) { |
5350fd8e C |
24 | const payload = job.data as ActivitypubFollowPayload |
25 | const host = payload.host | |
26 | ||
27 | logger.info('Processing ActivityPub follow in job %d.', job.id) | |
28 | ||
453e83ea | 29 | let targetActor: MActorFull |
6dd9de95 | 30 | if (!host || host === WEBSERVER.HOST) { |
22a16e36 C |
31 | targetActor = await ActorModel.loadLocalByName(payload.name) |
32 | } else { | |
33 | const sanitizedHost = sanitizeHost(host, REMOTE_SCHEME.HTTP) | |
34 | const actorUrl = await loadActorUrlOrGetFromWebfinger(payload.name + '@' + sanitizedHost) | |
453e83ea | 35 | targetActor = await getOrCreateActorAndServerAndModel(actorUrl, 'all') |
22a16e36 | 36 | } |
5350fd8e | 37 | |
2c0ccd4b C |
38 | if (payload.assertIsChannel && !targetActor.VideoChannel) { |
39 | logger.warn('Do not follow %s@%s because it is not a channel.', name, host) | |
40 | return | |
41 | } | |
42 | ||
06a05d5f | 43 | const fromActor = await ActorModel.load(payload.followerActorId) |
5350fd8e | 44 | |
8424c402 | 45 | return retryTransactionWrapper(follow, fromActor, targetActor, payload.isAutoFollow) |
5350fd8e C |
46 | } |
47 | // --------------------------------------------------------------------------- | |
48 | ||
49 | export { | |
50 | processActivityPubFollow | |
51 | } | |
52 | ||
53 | // --------------------------------------------------------------------------- | |
54 | ||
8424c402 | 55 | async function follow (fromActor: MActor, targetActor: MActorFull, isAutoFollow = false) { |
5350fd8e | 56 | if (fromActor.id === targetActor.id) { |
32d7f2b7 | 57 | throw new Error('Follower is the same as target actor.') |
5350fd8e C |
58 | } |
59 | ||
06a05d5f C |
60 | // Same server, direct accept |
61 | const state = !fromActor.serverId && !targetActor.serverId ? 'accepted' : 'pending' | |
62 | ||
f7cc67b4 | 63 | const actorFollow = await sequelizeTypescript.transaction(async t => { |
0283eaac | 64 | const [ actorFollow ] = await ActorFollowModel.findOrCreate<MActorFollowActors>({ |
5350fd8e C |
65 | where: { |
66 | actorId: fromActor.id, | |
67 | targetActorId: targetActor.id | |
68 | }, | |
69 | defaults: { | |
06a05d5f | 70 | state, |
5350fd8e C |
71 | actorId: fromActor.id, |
72 | targetActorId: targetActor.id | |
73 | }, | |
74 | transaction: t | |
75 | }) | |
76 | actorFollow.ActorFollowing = targetActor | |
77 | actorFollow.ActorFollower = fromActor | |
78 | ||
6104adc3 | 79 | // Send a notification to remote server if our follow is not already accepted |
2284f202 | 80 | if (actorFollow.state !== 'accepted') sendFollow(actorFollow, t) |
f7cc67b4 C |
81 | |
82 | return actorFollow | |
5350fd8e | 83 | }) |
f7cc67b4 | 84 | |
8424c402 | 85 | const followerFull = await ActorModel.loadFull(fromActor.id) |
0283eaac | 86 | |
8424c402 C |
87 | const actorFollowFull = Object.assign(actorFollow, { |
88 | ActorFollowing: targetActor, | |
89 | ActorFollower: followerFull | |
90 | }) | |
0283eaac | 91 | |
8424c402 C |
92 | if (actorFollow.state === 'accepted') Notifier.Instance.notifyOfNewUserFollow(actorFollowFull) |
93 | if (isAutoFollow === true) Notifier.Instance.notifyOfAutoInstanceFollowing(actorFollowFull) | |
94 | ||
95 | return actorFollow | |
5350fd8e | 96 | } |