aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2019-03-19 14:13:53 +0100
committerChocobozzz <me@florianbigard.com>2019-03-19 14:13:53 +0100
commit9f79ade627f0044606a9fbbe16ca0154661d12b9 (patch)
treeccfc1876da591bc52cbb4b8ccddedbeae7876679 /server/lib
parent0e0c745b62b2f18e228328e8c4f95b17e54f7a5e (diff)
downloadPeerTube-9f79ade627f0044606a9fbbe16ca0154661d12b9.tar.gz
PeerTube-9f79ade627f0044606a9fbbe16ca0154661d12b9.tar.zst
PeerTube-9f79ade627f0044606a9fbbe16ca0154661d12b9.zip
Refresh playlists
Diffstat (limited to 'server/lib')
-rw-r--r--server/lib/activitypub/actor.ts3
-rw-r--r--server/lib/activitypub/playlist.ts56
-rw-r--r--server/lib/job-queue/handlers/activitypub-refresher.ts14
3 files changed, 67 insertions, 6 deletions
diff --git a/server/lib/activitypub/actor.ts b/server/lib/activitypub/actor.ts
index f77df8b78..63e810642 100644
--- a/server/lib/activitypub/actor.ts
+++ b/server/lib/activitypub/actor.ts
@@ -375,7 +375,8 @@ async function fetchRemoteActor (actorUrl: string): Promise<{ statusCode?: numbe
375 } 375 }
376 376
377 if (checkUrlsSameHost(actorJSON.id, actorUrl) !== true) { 377 if (checkUrlsSameHost(actorJSON.id, actorUrl) !== true) {
378 throw new Error('Actor url ' + actorUrl + ' has not the same host than its AP id ' + actorJSON.id) 378 logger.warn('Actor url %s has not the same host than its AP id %s', actorUrl, actorJSON.id)
379 return { result: undefined, statusCode: requestResult.response.statusCode }
379 } 380 }
380 381
381 const followersCount = await fetchActorTotalItems(actorJSON.followers) 382 const followersCount = await fetchActorTotalItems(actorJSON.followers)
diff --git a/server/lib/activitypub/playlist.ts b/server/lib/activitypub/playlist.ts
index 70389044e..c4a8f12ec 100644
--- a/server/lib/activitypub/playlist.ts
+++ b/server/lib/activitypub/playlist.ts
@@ -95,7 +95,7 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
95 return Promise.resolve() 95 return Promise.resolve()
96 }) 96 })
97 97
98 // Empty playlists generally do not have a miniature, so skip it 98 // Empty playlists generally do not have a miniature, so skip this
99 if (accItems.length !== 0) { 99 if (accItems.length !== 0) {
100 try { 100 try {
101 await generateThumbnailFromUrl(playlist, playlistObject.icon) 101 await generateThumbnailFromUrl(playlist, playlistObject.icon)
@@ -107,13 +107,45 @@ async function createOrUpdateVideoPlaylist (playlistObject: PlaylistObject, byAc
107 return resetVideoPlaylistElements(accItems, playlist) 107 return resetVideoPlaylistElements(accItems, playlist)
108} 108}
109 109
110async function refreshVideoPlaylistIfNeeded (videoPlaylist: VideoPlaylistModel): Promise<VideoPlaylistModel> {
111 if (!videoPlaylist.isOutdated()) return videoPlaylist
112
113 try {
114 const { statusCode, playlistObject } = await fetchRemoteVideoPlaylist(videoPlaylist.url)
115 if (statusCode === 404) {
116 logger.info('Cannot refresh remote video playlist %s: it does not exist anymore. Deleting it.', videoPlaylist.url)
117
118 await videoPlaylist.destroy()
119 return undefined
120 }
121
122 if (playlistObject === undefined) {
123 logger.warn('Cannot refresh remote playlist %s: invalid body.', videoPlaylist.url)
124
125 await videoPlaylist.setAsRefreshed()
126 return videoPlaylist
127 }
128
129 const byAccount = videoPlaylist.OwnerAccount
130 await createOrUpdateVideoPlaylist(playlistObject, byAccount, playlistObject.to)
131
132 return videoPlaylist
133 } catch (err) {
134 logger.warn('Cannot refresh video playlist %s.', videoPlaylist.url, { err })
135
136 await videoPlaylist.setAsRefreshed()
137 return videoPlaylist
138 }
139}
140
110// --------------------------------------------------------------------------- 141// ---------------------------------------------------------------------------
111 142
112export { 143export {
113 createAccountPlaylists, 144 createAccountPlaylists,
114 playlistObjectToDBAttributes, 145 playlistObjectToDBAttributes,
115 playlistElementObjectToDBAttributes, 146 playlistElementObjectToDBAttributes,
116 createOrUpdateVideoPlaylist 147 createOrUpdateVideoPlaylist,
148 refreshVideoPlaylistIfNeeded
117} 149}
118 150
119// --------------------------------------------------------------------------- 151// ---------------------------------------------------------------------------
@@ -162,3 +194,23 @@ function generateThumbnailFromUrl (playlist: VideoPlaylistModel, icon: ActivityI
162 194
163 return downloadImage(icon.url, CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName, THUMBNAILS_SIZE) 195 return downloadImage(icon.url, CONFIG.STORAGE.THUMBNAILS_DIR, thumbnailName, THUMBNAILS_SIZE)
164} 196}
197
198async function fetchRemoteVideoPlaylist (playlistUrl: string): Promise<{ statusCode: number, playlistObject: PlaylistObject }> {
199 const options = {
200 uri: playlistUrl,
201 method: 'GET',
202 json: true,
203 activityPub: true
204 }
205
206 logger.info('Fetching remote playlist %s.', playlistUrl)
207
208 const { response, body } = await doRequest(options)
209
210 if (isPlaylistObjectValid(body) === false || checkUrlsSameHost(body.id, playlistUrl) !== true) {
211 logger.debug('Remote video playlist JSON is not valid.', { body })
212 return { statusCode: response.statusCode, playlistObject: undefined }
213 }
214
215 return { statusCode: response.statusCode, playlistObject: body }
216}
diff --git a/server/lib/job-queue/handlers/activitypub-refresher.ts b/server/lib/job-queue/handlers/activitypub-refresher.ts
index 454b975fe..4d6c38cfa 100644
--- a/server/lib/job-queue/handlers/activitypub-refresher.ts
+++ b/server/lib/job-queue/handlers/activitypub-refresher.ts
@@ -1,11 +1,12 @@
1import * as Bull from 'bull' 1import * as Bull from 'bull'
2import { logger } from '../../../helpers/logger' 2import { logger } from '../../../helpers/logger'
3import { fetchVideoByUrl } from '../../../helpers/video' 3import { fetchVideoByUrl } from '../../../helpers/video'
4import { refreshVideoIfNeeded, refreshActorIfNeeded } from '../../activitypub' 4import { refreshActorIfNeeded, refreshVideoIfNeeded, refreshVideoPlaylistIfNeeded } from '../../activitypub'
5import { ActorModel } from '../../../models/activitypub/actor' 5import { ActorModel } from '../../../models/activitypub/actor'
6import { VideoPlaylistModel } from '../../../models/video/video-playlist'
6 7
7export type RefreshPayload = { 8export type RefreshPayload = {
8 type: 'video' | 'actor' 9 type: 'video' | 'video-playlist' | 'actor'
9 url: string 10 url: string
10} 11}
11 12
@@ -15,13 +16,13 @@ async function refreshAPObject (job: Bull.Job) {
15 logger.info('Processing AP refresher in job %d for %s.', job.id, payload.url) 16 logger.info('Processing AP refresher in job %d for %s.', job.id, payload.url)
16 17
17 if (payload.type === 'video') return refreshVideo(payload.url) 18 if (payload.type === 'video') return refreshVideo(payload.url)
19 if (payload.type === 'video-playlist') return refreshVideoPlaylist(payload.url)
18 if (payload.type === 'actor') return refreshActor(payload.url) 20 if (payload.type === 'actor') return refreshActor(payload.url)
19} 21}
20 22
21// --------------------------------------------------------------------------- 23// ---------------------------------------------------------------------------
22 24
23export { 25export {
24 refreshActor,
25 refreshAPObject 26 refreshAPObject
26} 27}
27 28
@@ -50,5 +51,12 @@ async function refreshActor (actorUrl: string) {
50 if (actor) { 51 if (actor) {
51 await refreshActorIfNeeded(actor, fetchType) 52 await refreshActorIfNeeded(actor, fetchType)
52 } 53 }
54}
55
56async function refreshVideoPlaylist (playlistUrl: string) {
57 const playlist = await VideoPlaylistModel.loadByUrlAndPopulateAccount(playlistUrl)
53 58
59 if (playlist) {
60 await refreshVideoPlaylistIfNeeded(playlist)
61 }
54} 62}