aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/helpers/activitypub.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/helpers/activitypub.ts')
-rw-r--r--server/helpers/activitypub.ts123
1 files changed, 123 insertions, 0 deletions
diff --git a/server/helpers/activitypub.ts b/server/helpers/activitypub.ts
new file mode 100644
index 000000000..ecb509b66
--- /dev/null
+++ b/server/helpers/activitypub.ts
@@ -0,0 +1,123 @@
1import * as url from 'url'
2
3import { database as db } from '../initializers'
4import { logger } from './logger'
5import { doRequest } from './requests'
6import { isRemoteAccountValid } from './custom-validators'
7import { ActivityPubActor } from '../../shared/models/activitypub/activitypub-actor'
8import { ResultList } from '../../shared/models/result-list.model'
9
10async function fetchRemoteAccountAndCreatePod (accountUrl: string) {
11 const options = {
12 uri: accountUrl,
13 method: 'GET'
14 }
15
16 let requestResult
17 try {
18 requestResult = await doRequest(options)
19 } catch (err) {
20 logger.warning('Cannot fetch remote account %s.', accountUrl, err)
21 return undefined
22 }
23
24 const accountJSON: ActivityPubActor = requestResult.body
25 if (isRemoteAccountValid(accountJSON) === false) return undefined
26
27 const followersCount = await fetchAccountCount(accountJSON.followers)
28 const followingCount = await fetchAccountCount(accountJSON.following)
29
30 const account = db.Account.build({
31 uuid: accountJSON.uuid,
32 name: accountJSON.preferredUsername,
33 url: accountJSON.url,
34 publicKey: accountJSON.publicKey.publicKeyPem,
35 privateKey: null,
36 followersCount: followersCount,
37 followingCount: followingCount,
38 inboxUrl: accountJSON.inbox,
39 outboxUrl: accountJSON.outbox,
40 sharedInboxUrl: accountJSON.endpoints.sharedInbox,
41 followersUrl: accountJSON.followers,
42 followingUrl: accountJSON.following
43 })
44
45 const accountHost = url.parse(account.url).host
46 const podOptions = {
47 where: {
48 host: accountHost
49 },
50 defaults: {
51 host: accountHost
52 }
53 }
54 const pod = await db.Pod.findOrCreate(podOptions)
55
56 return { account, pod }
57}
58
59function activityPubContextify (data: object) {
60 return Object.assign(data,{
61 '@context': [
62 'https://www.w3.org/ns/activitystreams',
63 'https://w3id.org/security/v1',
64 {
65 'Hashtag': 'as:Hashtag',
66 'uuid': 'http://schema.org/identifier',
67 'category': 'http://schema.org/category',
68 'licence': 'http://schema.org/license',
69 'nsfw': 'as:sensitive',
70 'language': 'http://schema.org/inLanguage',
71 'views': 'http://schema.org/Number',
72 'size': 'http://schema.org/Number'
73 }
74 ]
75 })
76}
77
78function activityPubCollectionPagination (url: string, page: number, result: ResultList<any>) {
79 const baseUrl = url.split('?').shift
80
81 const obj = {
82 id: baseUrl,
83 type: 'Collection',
84 totalItems: result.total,
85 first: {
86 id: baseUrl + '?page=' + page,
87 type: 'CollectionPage',
88 totalItems: result.total,
89 next: baseUrl + '?page=' + (page + 1),
90 partOf: baseUrl,
91 items: result.data
92 }
93 }
94
95 return activityPubContextify(obj)
96}
97
98// ---------------------------------------------------------------------------
99
100export {
101 fetchRemoteAccountAndCreatePod,
102 activityPubContextify,
103 activityPubCollectionPagination
104}
105
106// ---------------------------------------------------------------------------
107
108async function fetchAccountCount (url: string) {
109 const options = {
110 uri: url,
111 method: 'GET'
112 }
113
114 let requestResult
115 try {
116 requestResult = await doRequest(options)
117 } catch (err) {
118 logger.warning('Cannot fetch remote account count %s.', url, err)
119 return undefined
120 }
121
122 return requestResult.totalItems ? requestResult.totalItems : 0
123}