diff options
Diffstat (limited to 'server/lib/activitypub/actor.ts')
-rw-r--r-- | server/lib/activitypub/actor.ts | 86 |
1 files changed, 47 insertions, 39 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index e557896e8..b6ba2cc22 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -5,13 +5,13 @@ import * as url from 'url' | |||
5 | import * as uuidv4 from 'uuid/v4' | 5 | import * as uuidv4 from 'uuid/v4' |
6 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' | 6 | import { ActivityPubActor, ActivityPubActorType } from '../../../shared/models/activitypub' |
7 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' | 7 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' |
8 | import { isRemoteActorValid } from '../../helpers/custom-validators/activitypub/actor' | 8 | import { isActorObjectValid } from '../../helpers/custom-validators/activitypub/actor' |
9 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 9 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
10 | import { retryTransactionWrapper } from '../../helpers/database-utils' | 10 | import { retryTransactionWrapper } from '../../helpers/database-utils' |
11 | import { logger } from '../../helpers/logger' | 11 | import { logger } from '../../helpers/logger' |
12 | import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' | 12 | import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' |
13 | import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' | 13 | import { doRequest, doRequestAndSaveToFile } from '../../helpers/requests' |
14 | import { CONFIG, sequelizeTypescript } from '../../initializers' | 14 | import { AVATAR_MIMETYPE_EXT, CONFIG, sequelizeTypescript } from '../../initializers' |
15 | import { AccountModel } from '../../models/account/account' | 15 | import { AccountModel } from '../../models/account/account' |
16 | import { ActorModel } from '../../models/activitypub/actor' | 16 | import { ActorModel } from '../../models/activitypub/actor' |
17 | import { AvatarModel } from '../../models/avatar/avatar' | 17 | import { AvatarModel } from '../../models/avatar/avatar' |
@@ -84,10 +84,52 @@ function buildActorInstance (type: ActivityPubActorType, url: string, preferredU | |||
84 | }) | 84 | }) |
85 | } | 85 | } |
86 | 86 | ||
87 | async function fetchActorTotalItems (url: string) { | ||
88 | const options = { | ||
89 | uri: url, | ||
90 | method: 'GET', | ||
91 | json: true, | ||
92 | activityPub: true | ||
93 | } | ||
94 | |||
95 | let requestResult | ||
96 | try { | ||
97 | requestResult = await doRequest(options) | ||
98 | } catch (err) { | ||
99 | logger.warn('Cannot fetch remote actor count %s.', url, err) | ||
100 | return undefined | ||
101 | } | ||
102 | |||
103 | return requestResult.totalItems ? requestResult.totalItems : 0 | ||
104 | } | ||
105 | |||
106 | async function fetchAvatarIfExists (actorJSON: ActivityPubActor) { | ||
107 | if ( | ||
108 | actorJSON.icon && actorJSON.icon.type === 'Image' && AVATAR_MIMETYPE_EXT[actorJSON.icon.mediaType] !== undefined && | ||
109 | isActivityPubUrlValid(actorJSON.icon.url) | ||
110 | ) { | ||
111 | const extension = AVATAR_MIMETYPE_EXT[actorJSON.icon.mediaType] | ||
112 | |||
113 | const avatarName = uuidv4() + extension | ||
114 | const destPath = join(CONFIG.STORAGE.AVATARS_DIR, avatarName) | ||
115 | |||
116 | await doRequestAndSaveToFile({ | ||
117 | method: 'GET', | ||
118 | uri: actorJSON.icon.url | ||
119 | }, destPath) | ||
120 | |||
121 | return avatarName | ||
122 | } | ||
123 | |||
124 | return undefined | ||
125 | } | ||
126 | |||
87 | export { | 127 | export { |
88 | getOrCreateActorAndServerAndModel, | 128 | getOrCreateActorAndServerAndModel, |
89 | buildActorInstance, | 129 | buildActorInstance, |
90 | setAsyncActorKeys | 130 | setAsyncActorKeys, |
131 | fetchActorTotalItems, | ||
132 | fetchAvatarIfExists | ||
91 | } | 133 | } |
92 | 134 | ||
93 | // --------------------------------------------------------------------------- | 135 | // --------------------------------------------------------------------------- |
@@ -166,7 +208,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu | |||
166 | const requestResult = await doRequest(options) | 208 | const requestResult = await doRequest(options) |
167 | const actorJSON: ActivityPubActor = requestResult.body | 209 | const actorJSON: ActivityPubActor = requestResult.body |
168 | 210 | ||
169 | if (isRemoteActorValid(actorJSON) === false) { | 211 | if (isActorObjectValid(actorJSON) === false) { |
170 | logger.debug('Remote actor JSON is not valid.', { actorJSON: actorJSON }) | 212 | logger.debug('Remote actor JSON is not valid.', { actorJSON: actorJSON }) |
171 | return undefined | 213 | return undefined |
172 | } | 214 | } |
@@ -190,22 +232,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu | |||
190 | followingUrl: actorJSON.following | 232 | followingUrl: actorJSON.following |
191 | }) | 233 | }) |
192 | 234 | ||
193 | // Fetch icon? | 235 | const avatarName = await fetchAvatarIfExists(actorJSON) |
194 | let avatarName: string = undefined | ||
195 | if ( | ||
196 | actorJSON.icon && actorJSON.icon.type === 'Image' && actorJSON.icon.mediaType === 'image/png' && | ||
197 | isActivityPubUrlValid(actorJSON.icon.url) | ||
198 | ) { | ||
199 | const extension = actorJSON.icon.mediaType === 'image/png' ? '.png' : '.jpg' | ||
200 | |||
201 | avatarName = uuidv4() + extension | ||
202 | const destPath = join(CONFIG.STORAGE.AVATARS_DIR, avatarName) | ||
203 | |||
204 | await doRequestAndSaveToFile({ | ||
205 | method: 'GET', | ||
206 | uri: actorJSON.icon.url | ||
207 | }, destPath) | ||
208 | } | ||
209 | 236 | ||
210 | const name = actorJSON.name || actorJSON.preferredUsername | 237 | const name = actorJSON.name || actorJSON.preferredUsername |
211 | return { | 238 | return { |
@@ -217,25 +244,6 @@ async function fetchRemoteActor (actorUrl: string): Promise<FetchRemoteActorResu | |||
217 | } | 244 | } |
218 | } | 245 | } |
219 | 246 | ||
220 | async function fetchActorTotalItems (url: string) { | ||
221 | const options = { | ||
222 | uri: url, | ||
223 | method: 'GET', | ||
224 | json: true, | ||
225 | activityPub: true | ||
226 | } | ||
227 | |||
228 | let requestResult | ||
229 | try { | ||
230 | requestResult = await doRequest(options) | ||
231 | } catch (err) { | ||
232 | logger.warn('Cannot fetch remote actor count %s.', url, err) | ||
233 | return undefined | ||
234 | } | ||
235 | |||
236 | return requestResult.totalItems ? requestResult.totalItems : 0 | ||
237 | } | ||
238 | |||
239 | function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) { | 247 | function saveAccount (actor: ActorModel, result: FetchRemoteActorResult, t: Transaction) { |
240 | const account = new AccountModel({ | 248 | const account = new AccountModel({ |
241 | name: result.name, | 249 | name: result.name, |