]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blob - server/helpers/activitypub.ts
ecb509b66c81dd9edea35d7466717493ff77b422
[github/Chocobozzz/PeerTube.git] / server / helpers / activitypub.ts
1 import * as url from 'url'
2
3 import { database as db } from '../initializers'
4 import { logger } from './logger'
5 import { doRequest } from './requests'
6 import { isRemoteAccountValid } from './custom-validators'
7 import { ActivityPubActor } from '../../shared/models/activitypub/activitypub-actor'
8 import { ResultList } from '../../shared/models/result-list.model'
9
10 async 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
59 function 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
78 function 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
100 export {
101 fetchRemoteAccountAndCreatePod,
102 activityPubContextify,
103 activityPubCollectionPagination
104 }
105
106 // ---------------------------------------------------------------------------
107
108 async 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 }