diff options
Diffstat (limited to 'server/lib/activitypub')
-rw-r--r-- | server/lib/activitypub/actor.ts | 41 | ||||
-rw-r--r-- | server/lib/activitypub/crawl.ts | 25 | ||||
-rw-r--r-- | server/lib/activitypub/playlist.ts | 54 | ||||
-rw-r--r-- | server/lib/activitypub/share.ts | 9 | ||||
-rw-r--r-- | server/lib/activitypub/video-comments.ts | 14 | ||||
-rw-r--r-- | server/lib/activitypub/video-rates.ts | 22 | ||||
-rw-r--r-- | server/lib/activitypub/videos.ts | 31 |
7 files changed, 71 insertions, 125 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts index a726f9e20..52b6c1f56 100644 --- a/server/lib/activitypub/actor.ts +++ b/server/lib/activitypub/actor.ts | |||
@@ -1,26 +1,28 @@ | |||
1 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
2 | import { extname } from 'path' | ||
2 | import { Op, Transaction } from 'sequelize' | 3 | import { Op, Transaction } from 'sequelize' |
3 | import { URL } from 'url' | 4 | import { URL } from 'url' |
4 | import { v4 as uuidv4 } from 'uuid' | 5 | import { v4 as uuidv4 } from 'uuid' |
6 | import { getServerActor } from '@server/models/application/application' | ||
7 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
5 | import { ActivityPubActor, ActivityPubActorType, ActivityPubOrderedCollection } from '../../../shared/models/activitypub' | 8 | import { ActivityPubActor, ActivityPubActorType, ActivityPubOrderedCollection } from '../../../shared/models/activitypub' |
6 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' | 9 | import { ActivityPubAttributedTo } from '../../../shared/models/activitypub/objects' |
7 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' | 10 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' |
11 | import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor' | ||
8 | import { sanitizeAndCheckActorObject } from '../../helpers/custom-validators/activitypub/actor' | 12 | import { sanitizeAndCheckActorObject } from '../../helpers/custom-validators/activitypub/actor' |
9 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' | 13 | import { isActivityPubUrlValid } from '../../helpers/custom-validators/activitypub/misc' |
10 | import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' | 14 | import { retryTransactionWrapper, updateInstanceWithAnother } from '../../helpers/database-utils' |
11 | import { logger } from '../../helpers/logger' | 15 | import { logger } from '../../helpers/logger' |
12 | import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' | 16 | import { createPrivateAndPublicKeys } from '../../helpers/peertube-crypto' |
13 | import { doRequest } from '../../helpers/requests' | 17 | import { doJSONRequest } from '../../helpers/requests' |
14 | import { getUrlFromWebfinger } from '../../helpers/webfinger' | 18 | import { getUrlFromWebfinger } from '../../helpers/webfinger' |
15 | import { MIMETYPES, WEBSERVER } from '../../initializers/constants' | 19 | import { MIMETYPES, WEBSERVER } from '../../initializers/constants' |
20 | import { sequelizeTypescript } from '../../initializers/database' | ||
16 | import { AccountModel } from '../../models/account/account' | 21 | import { AccountModel } from '../../models/account/account' |
17 | import { ActorModel } from '../../models/activitypub/actor' | 22 | import { ActorModel } from '../../models/activitypub/actor' |
18 | import { AvatarModel } from '../../models/avatar/avatar' | 23 | import { AvatarModel } from '../../models/avatar/avatar' |
19 | import { ServerModel } from '../../models/server/server' | 24 | import { ServerModel } from '../../models/server/server' |
20 | import { VideoChannelModel } from '../../models/video/video-channel' | 25 | import { VideoChannelModel } from '../../models/video/video-channel' |
21 | import { JobQueue } from '../job-queue' | ||
22 | import { ActorFetchByUrlType, fetchActorByUrl } from '../../helpers/actor' | ||
23 | import { sequelizeTypescript } from '../../initializers/database' | ||
24 | import { | 26 | import { |
25 | MAccount, | 27 | MAccount, |
26 | MAccountDefault, | 28 | MAccountDefault, |
@@ -34,9 +36,7 @@ import { | |||
34 | MActorId, | 36 | MActorId, |
35 | MChannel | 37 | MChannel |
36 | } from '../../types/models' | 38 | } from '../../types/models' |
37 | import { extname } from 'path' | 39 | import { JobQueue } from '../job-queue' |
38 | import { getServerActor } from '@server/models/application/application' | ||
39 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
40 | 40 | ||
41 | // Set account keys, this could be long so process after the account creation and do not block the client | 41 | // Set account keys, this could be long so process after the account creation and do not block the client |
42 | async function generateAndSaveActorKeys <T extends MActor> (actor: T) { | 42 | async function generateAndSaveActorKeys <T extends MActor> (actor: T) { |
@@ -209,16 +209,10 @@ async function deleteActorAvatarInstance (actor: MActorDefault, t: Transaction) | |||
209 | } | 209 | } |
210 | 210 | ||
211 | async function fetchActorTotalItems (url: string) { | 211 | async function fetchActorTotalItems (url: string) { |
212 | const options = { | ||
213 | uri: url, | ||
214 | method: 'GET', | ||
215 | json: true, | ||
216 | activityPub: true | ||
217 | } | ||
218 | |||
219 | try { | 212 | try { |
220 | const { body } = await doRequest<ActivityPubOrderedCollection<unknown>>(options) | 213 | const { body } = await doJSONRequest<ActivityPubOrderedCollection<unknown>>(url, { activityPub: true }) |
221 | return body.totalItems ? body.totalItems : 0 | 214 | |
215 | return body.totalItems || 0 | ||
222 | } catch (err) { | 216 | } catch (err) { |
223 | logger.warn('Cannot fetch remote actor count %s.', url, { err }) | 217 | logger.warn('Cannot fetch remote actor count %s.', url, { err }) |
224 | return 0 | 218 | return 0 |
@@ -449,26 +443,19 @@ type FetchRemoteActorResult = { | |||
449 | attributedTo: ActivityPubAttributedTo[] | 443 | attributedTo: ActivityPubAttributedTo[] |
450 | } | 444 | } |
451 | async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: number, result: FetchRemoteActorResult }> { | 445 | async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: number, result: FetchRemoteActorResult }> { |
452 | const options = { | ||
453 | uri: actorUrl, | ||
454 | method: 'GET', | ||
455 | json: true, | ||
456 | activityPub: true | ||
457 | } | ||
458 | |||
459 | logger.info('Fetching remote actor %s.', actorUrl) | 446 | logger.info('Fetching remote actor %s.', actorUrl) |
460 | 447 | ||
461 | const requestResult = await doRequest<ActivityPubActor>(options) | 448 | const requestResult = await doJSONRequest<ActivityPubActor>(actorUrl, { activityPub: true }) |
462 | const actorJSON = requestResult.body | 449 | const actorJSON = requestResult.body |
463 | 450 | ||
464 | if (sanitizeAndCheckActorObject(actorJSON) === false) { | 451 | if (sanitizeAndCheckActorObject(actorJSON) === false) { |
465 | logger.debug('Remote actor JSON is not valid.', { actorJSON }) | 452 | logger.debug('Remote actor JSON is not valid.', { actorJSON }) |
466 | return { result: undefined, statusCode: requestResult.response.statusCode } | 453 | return { result: undefined, statusCode: requestResult.statusCode } |
467 | } | 454 | } |
468 | 455 | ||
469 | if (checkUrlsSameHost(actorJSON.id, actorUrl) !== true) { | 456 | if (checkUrlsSameHost(actorJSON.id, actorUrl) !== true) { |
470 | logger.warn('Actor url %s has not the same host than its AP id %s', actorUrl, actorJSON.id) | 457 | logger.warn('Actor url %s has not the same host than its AP id %s', actorUrl, actorJSON.id) |
471 | return { result: undefined, statusCode: requestResult.response.statusCode } | 458 | return { result: undefined, statusCode: requestResult.statusCode } |
472 | } | 459 | } |
473 | 460 | ||
474 | const followersCount = await fetchActorTotalItems(actorJSON.followers) | 461 | const followersCount = await fetchActorTotalItems(actorJSON.followers) |
@@ -496,7 +483,7 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe | |||
496 | 483 | ||
497 | const name = actorJSON.name || actorJSON.preferredUsername | 484 | const name = actorJSON.name || actorJSON.preferredUsername |
498 | return { | 485 | return { |
499 | statusCode: requestResult.response.statusCode, | 486 | statusCode: requestResult.statusCode, |
500 | result: { | 487 | result: { |
501 | actor, | 488 | actor, |
502 | name, | 489 | name, |
diff --git a/server/lib/activitypub/crawl.ts b/server/lib/activitypub/crawl.ts index 1ed105bbe..278abf7de 100644 --- a/server/lib/activitypub/crawl.ts +++ b/server/lib/activitypub/crawl.ts | |||
@@ -1,27 +1,26 @@ | |||
1 | import { ACTIVITY_PUB, REQUEST_TIMEOUT, WEBSERVER } from '../../initializers/constants' | ||
2 | import { doRequest } from '../../helpers/requests' | ||
3 | import { logger } from '../../helpers/logger' | ||
4 | import * as Bluebird from 'bluebird' | 1 | import * as Bluebird from 'bluebird' |
5 | import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub' | ||
6 | import { URL } from 'url' | 2 | import { URL } from 'url' |
3 | import { ActivityPubOrderedCollection } from '../../../shared/models/activitypub' | ||
4 | import { logger } from '../../helpers/logger' | ||
5 | import { doJSONRequest } from '../../helpers/requests' | ||
6 | import { ACTIVITY_PUB, REQUEST_TIMEOUT, WEBSERVER } from '../../initializers/constants' | ||
7 | 7 | ||
8 | type HandlerFunction<T> = (items: T[]) => (Promise<any> | Bluebird<any>) | 8 | type HandlerFunction<T> = (items: T[]) => (Promise<any> | Bluebird<any>) |
9 | type CleanerFunction = (startedDate: Date) => (Promise<any> | Bluebird<any>) | 9 | type CleanerFunction = (startedDate: Date) => (Promise<any> | Bluebird<any>) |
10 | 10 | ||
11 | async function crawlCollectionPage <T> (uri: string, handler: HandlerFunction<T>, cleaner?: CleanerFunction) { | 11 | async function crawlCollectionPage <T> (argUrl: string, handler: HandlerFunction<T>, cleaner?: CleanerFunction) { |
12 | logger.info('Crawling ActivityPub data on %s.', uri) | 12 | let url = argUrl |
13 | |||
14 | logger.info('Crawling ActivityPub data on %s.', url) | ||
13 | 15 | ||
14 | const options = { | 16 | const options = { |
15 | method: 'GET', | ||
16 | uri, | ||
17 | json: true, | ||
18 | activityPub: true, | 17 | activityPub: true, |
19 | timeout: REQUEST_TIMEOUT | 18 | timeout: REQUEST_TIMEOUT |
20 | } | 19 | } |
21 | 20 | ||
22 | const startDate = new Date() | 21 | const startDate = new Date() |
23 | 22 | ||
24 | const response = await doRequest<ActivityPubOrderedCollection<T>>(options) | 23 | const response = await doJSONRequest<ActivityPubOrderedCollection<T>>(url, options) |
25 | const firstBody = response.body | 24 | const firstBody = response.body |
26 | 25 | ||
27 | const limit = ACTIVITY_PUB.FETCH_PAGE_LIMIT | 26 | const limit = ACTIVITY_PUB.FETCH_PAGE_LIMIT |
@@ -35,9 +34,9 @@ async function crawlCollectionPage <T> (uri: string, handler: HandlerFunction<T> | |||
35 | const remoteHost = new URL(nextLink).host | 34 | const remoteHost = new URL(nextLink).host |
36 | if (remoteHost === WEBSERVER.HOST) continue | 35 | if (remoteHost === WEBSERVER.HOST) continue |
37 | 36 | ||
38 | options.uri = nextLink | 37 | url = nextLink |
39 | 38 | ||
40 | const res = await doRequest<ActivityPubOrderedCollection<T>>(options) | 39 | const res = await doJSONRequest<ActivityPubOrderedCollection<T>>(url, options) |
41 | body = res.body | 40 | body = res.body |
42 | } else { | 41 | } else { |
43 | // nextLink is already the object we want | 42 | // nextLink is already the object we want |
@@ -49,7 +48,7 @@ async function crawlCollectionPage <T> (uri: string, handler: HandlerFunction<T> | |||
49 | 48 | ||
50 | if (Array.isArray(body.orderedItems)) { | 49 | if (Array.isArray(body.orderedItems)) { |
51 | const items = body.orderedItems | 50 | const items = body.orderedItems |
52 | logger.info('Processing %i ActivityPub items for %s.', items.length, options.uri) | 51 | logger.info('Processing %i ActivityPub items for %s.', items.length, url) |
53 | 52 | ||
54 | await handler(items) | 53 | await handler(items) |
55 | } | 54 | } |
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts index d5a3ef7c8..795be60d7 100644 --- a/server/lib/activitypub/playlist.ts +++ b/server/lib/activitypub/playlist.ts | |||
@@ -1,24 +1,24 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
2 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | ||
3 | import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' | ||
1 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' | 4 | import { PlaylistObject } from '../../../shared/models/activitypub/objects/playlist-object' |
2 | import { crawlCollectionPage } from './crawl' | 5 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' |
3 | import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' | 6 | import { checkUrlsSameHost } from '../../helpers/activitypub' |
7 | import { isPlaylistElementObjectValid, isPlaylistObjectValid } from '../../helpers/custom-validators/activitypub/playlist' | ||
4 | import { isArray } from '../../helpers/custom-validators/misc' | 8 | import { isArray } from '../../helpers/custom-validators/misc' |
5 | import { getOrCreateActorAndServerAndModel } from './actor' | ||
6 | import { logger } from '../../helpers/logger' | 9 | import { logger } from '../../helpers/logger' |
10 | import { doJSONRequest } from '../../helpers/requests' | ||
11 | import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' | ||
12 | import { sequelizeTypescript } from '../../initializers/database' | ||
7 | import { VideoPlaylistModel } from '../../models/video/video-playlist' | 13 | import { VideoPlaylistModel } from '../../models/video/video-playlist' |
8 | import { doRequest } from '../../helpers/requests' | ||
9 | import { checkUrlsSameHost } from '../../helpers/activitypub' | ||
10 | import * as Bluebird from 'bluebird' | ||
11 | import { PlaylistElementObject } from '../../../shared/models/activitypub/objects/playlist-element-object' | ||
12 | import { getOrCreateVideoAndAccountAndChannel } from './videos' | ||
13 | import { isPlaylistElementObjectValid, isPlaylistObjectValid } from '../../helpers/custom-validators/activitypub/playlist' | ||
14 | import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element' | 14 | import { VideoPlaylistElementModel } from '../../models/video/video-playlist-element' |
15 | import { VideoPlaylistPrivacy } from '../../../shared/models/videos/playlist/video-playlist-privacy.model' | ||
16 | import { sequelizeTypescript } from '../../initializers/database' | ||
17 | import { createPlaylistMiniatureFromUrl } from '../thumbnail' | ||
18 | import { FilteredModelAttributes } from '../../types/sequelize' | ||
19 | import { MAccountDefault, MAccountId, MVideoId } from '../../types/models' | 15 | import { MAccountDefault, MAccountId, MVideoId } from '../../types/models' |
20 | import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist' | 16 | import { MVideoPlaylist, MVideoPlaylistId, MVideoPlaylistOwner } from '../../types/models/video/video-playlist' |
21 | import { HttpStatusCode } from '../../../shared/core-utils/miscs/http-error-codes' | 17 | import { FilteredModelAttributes } from '../../types/sequelize' |
18 | import { createPlaylistMiniatureFromUrl } from '../thumbnail' | ||
19 | import { getOrCreateActorAndServerAndModel } from './actor' | ||
20 | import { crawlCollectionPage } from './crawl' | ||
21 | import { getOrCreateVideoAndAccountAndChannel } from './videos' | ||
22 | 22 | ||
23 | function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) { | 23 | function playlistObjectToDBAttributes (playlistObject: PlaylistObject, byAccount: MAccountId, to: string[]) { |
24 | const privacy = to.includes(ACTIVITY_PUB.PUBLIC) | 24 | const privacy = to.includes(ACTIVITY_PUB.PUBLIC) |
@@ -56,11 +56,7 @@ async function createAccountPlaylists (playlistUrls: string[], account: MAccount | |||
56 | if (exists === true) return | 56 | if (exists === true) return |
57 | 57 | ||
58 | // Fetch url | 58 | // Fetch url |
59 | const { body } = await doRequest<PlaylistObject>({ | 59 | const { body } = await doJSONRequest<PlaylistObject>(playlistUrl, { activityPub: true }) |
60 | uri: playlistUrl, | ||
61 | json: true, | ||
62 | activityPub: true | ||
63 | }) | ||
64 | 60 | ||
65 | if (!isPlaylistObjectValid(body)) { | 61 | if (!isPlaylistObjectValid(body)) { |
66 | throw new Error(`Invalid playlist object when fetch account playlists: ${JSON.stringify(body)}`) | 62 | throw new Error(`Invalid playlist object when fetch account playlists: ${JSON.stringify(body)}`) |
@@ -164,12 +160,7 @@ async function resetVideoPlaylistElements (elementUrls: string[], playlist: MVid | |||
164 | 160 | ||
165 | await Bluebird.map(elementUrls, async elementUrl => { | 161 | await Bluebird.map(elementUrls, async elementUrl => { |
166 | try { | 162 | try { |
167 | // Fetch url | 163 | const { body } = await doJSONRequest<PlaylistElementObject>(elementUrl, { activityPub: true }) |
168 | const { body } = await doRequest<PlaylistElementObject>({ | ||
169 | uri: elementUrl, | ||
170 | json: true, | ||
171 | activityPub: true | ||
172 | }) | ||
173 | 164 | ||
174 | if (!isPlaylistElementObjectValid(body)) throw new Error(`Invalid body in video get playlist element ${elementUrl}`) | 165 | if (!isPlaylistElementObjectValid(body)) throw new Error(`Invalid body in video get playlist element ${elementUrl}`) |
175 | 166 | ||
@@ -199,21 +190,14 @@ async function resetVideoPlaylistElements (elementUrls: string[], playlist: MVid | |||
199 | } | 190 | } |
200 | 191 | ||
201 | async function fetchRemoteVideoPlaylist (playlistUrl: string): Promise<{ statusCode: number, playlistObject: PlaylistObject }> { | 192 | async function fetchRemoteVideoPlaylist (playlistUrl: string): Promise<{ statusCode: number, playlistObject: PlaylistObject }> { |
202 | const options = { | ||
203 | uri: playlistUrl, | ||
204 | method: 'GET', | ||
205 | json: true, | ||
206 | activityPub: true | ||
207 | } | ||
208 | |||
209 | logger.info('Fetching remote playlist %s.', playlistUrl) | 193 | logger.info('Fetching remote playlist %s.', playlistUrl) |
210 | 194 | ||
211 | const { response, body } = await doRequest<any>(options) | 195 | const { body, statusCode } = await doJSONRequest<any>(playlistUrl, { activityPub: true }) |
212 | 196 | ||
213 | if (isPlaylistObjectValid(body) === false || checkUrlsSameHost(body.id, playlistUrl) !== true) { | 197 | if (isPlaylistObjectValid(body) === false || checkUrlsSameHost(body.id, playlistUrl) !== true) { |
214 | logger.debug('Remote video playlist JSON is not valid.', { body }) | 198 | logger.debug('Remote video playlist JSON is not valid.', { body }) |
215 | return { statusCode: response.statusCode, playlistObject: undefined } | 199 | return { statusCode, playlistObject: undefined } |
216 | } | 200 | } |
217 | 201 | ||
218 | return { statusCode: response.statusCode, playlistObject: body } | 202 | return { statusCode, playlistObject: body } |
219 | } | 203 | } |
diff --git a/server/lib/activitypub/share.ts b/server/lib/activitypub/share.ts index dde0c628e..c22fa0893 100644 --- a/server/lib/activitypub/share.ts +++ b/server/lib/activitypub/share.ts | |||
@@ -3,7 +3,7 @@ import { Transaction } from 'sequelize' | |||
3 | import { getServerActor } from '@server/models/application/application' | 3 | import { getServerActor } from '@server/models/application/application' |
4 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' | 4 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' |
5 | import { logger, loggerTagsFactory } from '../../helpers/logger' | 5 | import { logger, loggerTagsFactory } from '../../helpers/logger' |
6 | import { doRequest } from '../../helpers/requests' | 6 | import { doJSONRequest } from '../../helpers/requests' |
7 | import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' | 7 | import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' |
8 | import { VideoShareModel } from '../../models/video/video-share' | 8 | import { VideoShareModel } from '../../models/video/video-share' |
9 | import { MChannelActorLight, MVideo, MVideoAccountLight, MVideoId } from '../../types/models/video' | 9 | import { MChannelActorLight, MVideo, MVideoAccountLight, MVideoId } from '../../types/models/video' |
@@ -40,12 +40,7 @@ async function changeVideoChannelShare ( | |||
40 | async function addVideoShares (shareUrls: string[], video: MVideoId) { | 40 | async function addVideoShares (shareUrls: string[], video: MVideoId) { |
41 | await Bluebird.map(shareUrls, async shareUrl => { | 41 | await Bluebird.map(shareUrls, async shareUrl => { |
42 | try { | 42 | try { |
43 | // Fetch url | 43 | const { body } = await doJSONRequest<any>(shareUrl, { activityPub: true }) |
44 | const { body } = await doRequest<any>({ | ||
45 | uri: shareUrl, | ||
46 | json: true, | ||
47 | activityPub: true | ||
48 | }) | ||
49 | if (!body || !body.actor) throw new Error('Body or body actor is invalid') | 44 | if (!body || !body.actor) throw new Error('Body or body actor is invalid') |
50 | 45 | ||
51 | const actorUrl = getAPId(body.actor) | 46 | const actorUrl = getAPId(body.actor) |
diff --git a/server/lib/activitypub/video-comments.ts b/server/lib/activitypub/video-comments.ts index d025ed7f1..f1edfb0ac 100644 --- a/server/lib/activitypub/video-comments.ts +++ b/server/lib/activitypub/video-comments.ts | |||
@@ -1,13 +1,13 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
2 | import { checkUrlsSameHost } from '../../helpers/activitypub' | ||
1 | import { sanitizeAndCheckVideoCommentObject } from '../../helpers/custom-validators/activitypub/video-comments' | 3 | import { sanitizeAndCheckVideoCommentObject } from '../../helpers/custom-validators/activitypub/video-comments' |
2 | import { logger } from '../../helpers/logger' | 4 | import { logger } from '../../helpers/logger' |
3 | import { doRequest } from '../../helpers/requests' | 5 | import { doJSONRequest } from '../../helpers/requests' |
4 | import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' | 6 | import { ACTIVITY_PUB, CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' |
5 | import { VideoCommentModel } from '../../models/video/video-comment' | 7 | import { VideoCommentModel } from '../../models/video/video-comment' |
8 | import { MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../types/models/video' | ||
6 | import { getOrCreateActorAndServerAndModel } from './actor' | 9 | import { getOrCreateActorAndServerAndModel } from './actor' |
7 | import { getOrCreateVideoAndAccountAndChannel } from './videos' | 10 | import { getOrCreateVideoAndAccountAndChannel } from './videos' |
8 | import * as Bluebird from 'bluebird' | ||
9 | import { checkUrlsSameHost } from '../../helpers/activitypub' | ||
10 | import { MCommentOwner, MCommentOwnerVideo, MVideoAccountLightBlacklistAllFiles } from '../../types/models/video' | ||
11 | 11 | ||
12 | type ResolveThreadParams = { | 12 | type ResolveThreadParams = { |
13 | url: string | 13 | url: string |
@@ -126,11 +126,7 @@ async function resolveRemoteParentComment (params: ResolveThreadParams) { | |||
126 | throw new Error('Recursion limit reached when resolving a thread') | 126 | throw new Error('Recursion limit reached when resolving a thread') |
127 | } | 127 | } |
128 | 128 | ||
129 | const { body } = await doRequest<any>({ | 129 | const { body } = await doJSONRequest<any>(url, { activityPub: true }) |
130 | uri: url, | ||
131 | json: true, | ||
132 | activityPub: true | ||
133 | }) | ||
134 | 130 | ||
135 | if (sanitizeAndCheckVideoCommentObject(body) === false) { | 131 | if (sanitizeAndCheckVideoCommentObject(body) === false) { |
136 | throw new Error(`Remote video comment JSON ${url} is not valid:` + JSON.stringify(body)) | 132 | throw new Error(`Remote video comment JSON ${url} is not valid:` + JSON.stringify(body)) |
diff --git a/server/lib/activitypub/video-rates.ts b/server/lib/activitypub/video-rates.ts index e246b1313..f40c07fea 100644 --- a/server/lib/activitypub/video-rates.ts +++ b/server/lib/activitypub/video-rates.ts | |||
@@ -1,26 +1,22 @@ | |||
1 | import * as Bluebird from 'bluebird' | ||
1 | import { Transaction } from 'sequelize' | 2 | import { Transaction } from 'sequelize' |
2 | import { sendLike, sendUndoDislike, sendUndoLike } from './send' | 3 | import { doJSONRequest } from '@server/helpers/requests' |
3 | import { VideoRateType } from '../../../shared/models/videos' | 4 | import { VideoRateType } from '../../../shared/models/videos' |
4 | import * as Bluebird from 'bluebird' | 5 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' |
5 | import { getOrCreateActorAndServerAndModel } from './actor' | ||
6 | import { AccountVideoRateModel } from '../../models/account/account-video-rate' | ||
7 | import { logger } from '../../helpers/logger' | 6 | import { logger } from '../../helpers/logger' |
8 | import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' | 7 | import { CRAWL_REQUEST_CONCURRENCY } from '../../initializers/constants' |
9 | import { doRequest } from '../../helpers/requests' | 8 | import { AccountVideoRateModel } from '../../models/account/account-video-rate' |
10 | import { checkUrlsSameHost, getAPId } from '../../helpers/activitypub' | ||
11 | import { getVideoDislikeActivityPubUrlByLocalActor, getVideoLikeActivityPubUrlByLocalActor } from './url' | ||
12 | import { sendDislike } from './send/send-dislike' | ||
13 | import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../types/models' | 9 | import { MAccountActor, MActorUrl, MVideo, MVideoAccountLight, MVideoId } from '../../types/models' |
10 | import { getOrCreateActorAndServerAndModel } from './actor' | ||
11 | import { sendLike, sendUndoDislike, sendUndoLike } from './send' | ||
12 | import { sendDislike } from './send/send-dislike' | ||
13 | import { getVideoDislikeActivityPubUrlByLocalActor, getVideoLikeActivityPubUrlByLocalActor } from './url' | ||
14 | 14 | ||
15 | async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) { | 15 | async function createRates (ratesUrl: string[], video: MVideo, rate: VideoRateType) { |
16 | await Bluebird.map(ratesUrl, async rateUrl => { | 16 | await Bluebird.map(ratesUrl, async rateUrl => { |
17 | try { | 17 | try { |
18 | // Fetch url | 18 | // Fetch url |
19 | const { body } = await doRequest<any>({ | 19 | const { body } = await doJSONRequest<any>(rateUrl, { activityPub: true }) |
20 | uri: rateUrl, | ||
21 | json: true, | ||
22 | activityPub: true | ||
23 | }) | ||
24 | if (!body || !body.actor) throw new Error('Body or body actor is invalid') | 20 | if (!body || !body.actor) throw new Error('Body or body actor is invalid') |
25 | 21 | ||
26 | const actorUrl = getAPId(body.actor) | 22 | const actorUrl = getAPId(body.actor) |
diff --git a/server/lib/activitypub/videos.ts b/server/lib/activitypub/videos.ts index c02578aad..a5f58dd01 100644 --- a/server/lib/activitypub/videos.ts +++ b/server/lib/activitypub/videos.ts | |||
@@ -2,7 +2,6 @@ import * as Bluebird from 'bluebird' | |||
2 | import { maxBy, minBy } from 'lodash' | 2 | import { maxBy, minBy } from 'lodash' |
3 | import * as magnetUtil from 'magnet-uri' | 3 | import * as magnetUtil from 'magnet-uri' |
4 | import { basename, join } from 'path' | 4 | import { basename, join } from 'path' |
5 | import * as request from 'request' | ||
6 | import { Transaction } from 'sequelize/types' | 5 | import { Transaction } from 'sequelize/types' |
7 | import { TrackerModel } from '@server/models/server/tracker' | 6 | import { TrackerModel } from '@server/models/server/tracker' |
8 | import { VideoLiveModel } from '@server/models/video/video-live' | 7 | import { VideoLiveModel } from '@server/models/video/video-live' |
@@ -31,7 +30,7 @@ import { isArray } from '../../helpers/custom-validators/misc' | |||
31 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' | 30 | import { isVideoFileInfoHashValid } from '../../helpers/custom-validators/videos' |
32 | import { deleteNonExistingModels, resetSequelizeInstance, retryTransactionWrapper } from '../../helpers/database-utils' | 31 | import { deleteNonExistingModels, resetSequelizeInstance, retryTransactionWrapper } from '../../helpers/database-utils' |
33 | import { logger } from '../../helpers/logger' | 32 | import { logger } from '../../helpers/logger' |
34 | import { doRequest } from '../../helpers/requests' | 33 | import { doJSONRequest } from '../../helpers/requests' |
35 | import { fetchVideoByUrl, getExtFromMimetype, VideoFetchByUrlType } from '../../helpers/video' | 34 | import { fetchVideoByUrl, getExtFromMimetype, VideoFetchByUrlType } from '../../helpers/video' |
36 | import { | 35 | import { |
37 | ACTIVITY_PUB, | 36 | ACTIVITY_PUB, |
@@ -115,36 +114,26 @@ async function federateVideoIfNeeded (videoArg: MVideoAPWithoutCaption, isNewVid | |||
115 | } | 114 | } |
116 | } | 115 | } |
117 | 116 | ||
118 | async function fetchRemoteVideo (videoUrl: string): Promise<{ response: request.RequestResponse, videoObject: VideoObject }> { | 117 | async function fetchRemoteVideo (videoUrl: string): Promise<{ statusCode: number, videoObject: VideoObject }> { |
119 | const options = { | ||
120 | uri: videoUrl, | ||
121 | method: 'GET', | ||
122 | json: true, | ||
123 | activityPub: true | ||
124 | } | ||
125 | |||
126 | logger.info('Fetching remote video %s.', videoUrl) | 118 | logger.info('Fetching remote video %s.', videoUrl) |
127 | 119 | ||
128 | const { response, body } = await doRequest<any>(options) | 120 | const { statusCode, body } = await doJSONRequest<any>(videoUrl, { activityPub: true }) |
129 | 121 | ||
130 | if (sanitizeAndCheckVideoTorrentObject(body) === false || checkUrlsSameHost(body.id, videoUrl) !== true) { | 122 | if (sanitizeAndCheckVideoTorrentObject(body) === false || checkUrlsSameHost(body.id, videoUrl) !== true) { |
131 | logger.debug('Remote video JSON is not valid.', { body }) | 123 | logger.debug('Remote video JSON is not valid.', { body }) |
132 | return { response, videoObject: undefined } | 124 | return { statusCode, videoObject: undefined } |
133 | } | 125 | } |
134 | 126 | ||
135 | return { response, videoObject: body } | 127 | return { statusCode, videoObject: body } |
136 | } | 128 | } |
137 | 129 | ||
138 | async function fetchRemoteVideoDescription (video: MVideoAccountLight) { | 130 | async function fetchRemoteVideoDescription (video: MVideoAccountLight) { |
139 | const host = video.VideoChannel.Account.Actor.Server.host | 131 | const host = video.VideoChannel.Account.Actor.Server.host |
140 | const path = video.getDescriptionAPIPath() | 132 | const path = video.getDescriptionAPIPath() |
141 | const options = { | 133 | const url = REMOTE_SCHEME.HTTP + '://' + host + path |
142 | uri: REMOTE_SCHEME.HTTP + '://' + host + path, | ||
143 | json: true | ||
144 | } | ||
145 | 134 | ||
146 | const { body } = await doRequest<any>(options) | 135 | const { body } = await doJSONRequest<any>(url) |
147 | return body.description ? body.description : '' | 136 | return body.description || '' |
148 | } | 137 | } |
149 | 138 | ||
150 | function getOrCreateVideoChannelFromVideoObject (videoObject: VideoObject) { | 139 | function getOrCreateVideoChannelFromVideoObject (videoObject: VideoObject) { |
@@ -534,8 +523,8 @@ async function refreshVideoIfNeeded (options: { | |||
534 | : await VideoModel.loadByUrlAndPopulateAccount(options.video.url) | 523 | : await VideoModel.loadByUrlAndPopulateAccount(options.video.url) |
535 | 524 | ||
536 | try { | 525 | try { |
537 | const { response, videoObject } = await fetchRemoteVideo(video.url) | 526 | const { statusCode, videoObject } = await fetchRemoteVideo(video.url) |
538 | if (response.statusCode === HttpStatusCode.NOT_FOUND_404) { | 527 | if (statusCode === HttpStatusCode.NOT_FOUND_404) { |
539 | logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url) | 528 | logger.info('Cannot refresh remote video %s: video does not exist anymore. Deleting it.', video.url) |
540 | 529 | ||
541 | // Video does not exist anymore | 530 | // Video does not exist anymore |