diff options
Diffstat (limited to 'server/lib/activitypub/account.ts')
-rw-r--r-- | server/lib/activitypub/account.ts | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/server/lib/activitypub/account.ts b/server/lib/activitypub/account.ts new file mode 100644 index 000000000..704a92e13 --- /dev/null +++ b/server/lib/activitypub/account.ts | |||
@@ -0,0 +1,104 @@ | |||
1 | import * as url from 'url' | ||
2 | import { ActivityPubActor } from '../../../shared/models/activitypub/activitypub-actor' | ||
3 | import { isRemoteAccountValid } from '../../helpers/custom-validators/activitypub/account' | ||
4 | import { logger } from '../../helpers/logger' | ||
5 | import { doRequest } from '../../helpers/requests' | ||
6 | import { ACTIVITY_PUB } from '../../initializers/constants' | ||
7 | import { database as db } from '../../initializers/database' | ||
8 | |||
9 | async function getOrCreateAccount (accountUrl: string) { | ||
10 | let account = await db.Account.loadByUrl(accountUrl) | ||
11 | |||
12 | // We don't have this account in our database, fetch it on remote | ||
13 | if (!account) { | ||
14 | const res = await fetchRemoteAccountAndCreateServer(accountUrl) | ||
15 | if (res === undefined) throw new Error('Cannot fetch remote account.') | ||
16 | |||
17 | // Save our new account in database | ||
18 | account = await res.account.save() | ||
19 | } | ||
20 | |||
21 | return account | ||
22 | } | ||
23 | |||
24 | async function fetchRemoteAccountAndCreateServer (accountUrl: string) { | ||
25 | const options = { | ||
26 | uri: accountUrl, | ||
27 | method: 'GET', | ||
28 | headers: { | ||
29 | 'Accept': ACTIVITY_PUB.ACCEPT_HEADER | ||
30 | } | ||
31 | } | ||
32 | |||
33 | logger.info('Fetching remote account %s.', accountUrl) | ||
34 | |||
35 | let requestResult | ||
36 | try { | ||
37 | requestResult = await doRequest(options) | ||
38 | } catch (err) { | ||
39 | logger.warn('Cannot fetch remote account %s.', accountUrl, err) | ||
40 | return undefined | ||
41 | } | ||
42 | |||
43 | const accountJSON: ActivityPubActor = JSON.parse(requestResult.body) | ||
44 | if (isRemoteAccountValid(accountJSON) === false) { | ||
45 | logger.debug('Remote account JSON is not valid.', { accountJSON }) | ||
46 | return undefined | ||
47 | } | ||
48 | |||
49 | const followersCount = await fetchAccountCount(accountJSON.followers) | ||
50 | const followingCount = await fetchAccountCount(accountJSON.following) | ||
51 | |||
52 | const account = db.Account.build({ | ||
53 | uuid: accountJSON.uuid, | ||
54 | name: accountJSON.preferredUsername, | ||
55 | url: accountJSON.url, | ||
56 | publicKey: accountJSON.publicKey.publicKeyPem, | ||
57 | privateKey: null, | ||
58 | followersCount: followersCount, | ||
59 | followingCount: followingCount, | ||
60 | inboxUrl: accountJSON.inbox, | ||
61 | outboxUrl: accountJSON.outbox, | ||
62 | sharedInboxUrl: accountJSON.endpoints.sharedInbox, | ||
63 | followersUrl: accountJSON.followers, | ||
64 | followingUrl: accountJSON.following | ||
65 | }) | ||
66 | |||
67 | const accountHost = url.parse(account.url).host | ||
68 | const serverOptions = { | ||
69 | where: { | ||
70 | host: accountHost | ||
71 | }, | ||
72 | defaults: { | ||
73 | host: accountHost | ||
74 | } | ||
75 | } | ||
76 | const [ server ] = await db.Server.findOrCreate(serverOptions) | ||
77 | account.set('serverId', server.id) | ||
78 | |||
79 | return { account, server } | ||
80 | } | ||
81 | |||
82 | export { | ||
83 | getOrCreateAccount, | ||
84 | fetchRemoteAccountAndCreateServer | ||
85 | } | ||
86 | |||
87 | // --------------------------------------------------------------------------- | ||
88 | |||
89 | async function fetchAccountCount (url: string) { | ||
90 | const options = { | ||
91 | uri: url, | ||
92 | method: 'GET' | ||
93 | } | ||
94 | |||
95 | let requestResult | ||
96 | try { | ||
97 | requestResult = await doRequest(options) | ||
98 | } catch (err) { | ||
99 | logger.warn('Cannot fetch remote account count %s.', url, err) | ||
100 | return undefined | ||
101 | } | ||
102 | |||
103 | return requestResult.totalItems ? requestResult.totalItems : 0 | ||
104 | } | ||