]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/blobdiff - server/lib/sync-channel.ts
Add test on AP hooks
[github/Chocobozzz/PeerTube.git] / server / lib / sync-channel.ts
index 50f80e6f9273c94de64d0cff33033a406902979b..3a805a943d6ab5c01271c37807ae54cf4d0ac58e 100644 (file)
@@ -1,10 +1,10 @@
 import { logger } from '@server/helpers/logger'
 import { YoutubeDLWrapper } from '@server/helpers/youtube-dl'
 import { CONFIG } from '@server/initializers/config'
-import { buildYoutubeDLImport } from '@server/lib/video-import'
+import { buildYoutubeDLImport } from '@server/lib/video-pre-import'
 import { UserModel } from '@server/models/user/user'
 import { VideoImportModel } from '@server/models/video/video-import'
-import { MChannelAccountDefault, MChannelSync } from '@server/types/models'
+import { MChannel, MChannelAccountDefault, MChannelSync } from '@server/types/models'
 import { VideoChannelSyncState, VideoPrivacy } from '@shared/models'
 import { CreateJobArgument, JobQueue } from './job-queue'
 import { ServerConfigManager } from './server-config-manager'
@@ -12,70 +12,100 @@ import { ServerConfigManager } from './server-config-manager'
 export async function synchronizeChannel (options: {
   channel: MChannelAccountDefault
   externalChannelUrl: string
+  videosCountLimit: number
   channelSync?: MChannelSync
-  videosCountLimit?: number
   onlyAfter?: Date
 }) {
   const { channel, externalChannelUrl, videosCountLimit, onlyAfter, channelSync } = options
 
-  const user = await UserModel.loadByChannelActorId(channel.actorId)
-  const youtubeDL = new YoutubeDLWrapper(
-    externalChannelUrl,
-    ServerConfigManager.Instance.getEnabledResolutions('vod'),
-    CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
-  )
+  if (channelSync) {
+    channelSync.state = VideoChannelSyncState.PROCESSING
+    channelSync.lastSyncAt = new Date()
+    await channelSync.save()
+  }
 
-  const infoList = await youtubeDL.getInfoForListImport({ latestVideosCount: videosCountLimit })
+  try {
+    const user = await UserModel.loadByChannelActorId(channel.actorId)
+    const youtubeDL = new YoutubeDLWrapper(
+      externalChannelUrl,
+      ServerConfigManager.Instance.getEnabledResolutions('vod'),
+      CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
+    )
 
-  const targetUrls = infoList
-    .filter(videoInfo => {
-      if (!onlyAfter) return true
+    const targetUrls = await youtubeDL.getInfoForListImport({ latestVideosCount: videosCountLimit })
 
-      return videoInfo.originallyPublishedAt.getTime() >= onlyAfter.getTime()
-    })
-    .map(videoInfo => videoInfo.webpageUrl)
+    logger.info(
+      'Fetched %d candidate URLs for sync channel %s.',
+      targetUrls.length, channel.Actor.preferredUsername, { targetUrls }
+    )
 
-  logger.info(
-    'Fetched %d candidate URLs for sync channel %s.',
-    targetUrls.length, channel.Actor.preferredUsername, { targetUrls }
-  )
+    if (targetUrls.length === 0) {
+      if (channelSync) {
+        channelSync.state = VideoChannelSyncState.SYNCED
+        await channelSync.save()
+      }
 
-  if (targetUrls.length === 0) {
-    if (channelSync) {
-      channelSync.state = VideoChannelSyncState.SYNCED
-      await channelSync.save()
+      return
     }
 
-    return
-  }
+    const children: CreateJobArgument[] = []
+
+    for (const targetUrl of targetUrls) {
+      if (await skipImport(channel, targetUrl, onlyAfter)) continue
 
-  const children: CreateJobArgument[] = []
+      const { job } = await buildYoutubeDLImport({
+        user,
+        channel,
+        targetUrl,
+        channelSync,
+        importDataOverride: {
+          privacy: VideoPrivacy.PUBLIC
+        }
+      })
 
-  for (const targetUrl of targetUrls) {
-    if (await VideoImportModel.urlAlreadyImported(channel.id, targetUrl)) {
-      logger.debug('%s is already imported for channel %s, skipping video channel synchronization.', channel.name, targetUrl)
-      continue
+      children.push(job)
     }
 
-    const { job } = await buildYoutubeDLImport({
-      user,
-      channel,
-      targetUrl,
-      channelSync,
-      importDataOverride: {
-        privacy: VideoPrivacy.PUBLIC
+    // Will update the channel sync status
+    const parent: CreateJobArgument = {
+      type: 'after-video-channel-import',
+      payload: {
+        channelSyncId: channelSync?.id
       }
-    })
+    }
+
+    await JobQueue.Instance.createJobWithChildren(parent, children)
+  } catch (err) {
+    logger.error(`Failed to import ${externalChannelUrl} in channel ${channel.name}`, { err })
+    channelSync.state = VideoChannelSyncState.FAILED
+    await channelSync.save()
+  }
+}
 
-    children.push(job)
+// ---------------------------------------------------------------------------
+
+async function skipImport (channel: MChannel, targetUrl: string, onlyAfter?: Date) {
+  if (await VideoImportModel.urlAlreadyImported(channel.id, targetUrl)) {
+    logger.debug('%s is already imported for channel %s, skipping video channel synchronization.', targetUrl, channel.name)
+    return true
   }
 
-  const parent: CreateJobArgument = {
-    type: 'after-video-channel-import',
-    payload: {
-      channelSyncId: channelSync?.id
+  if (onlyAfter) {
+    const youtubeDL = new YoutubeDLWrapper(
+      targetUrl,
+      ServerConfigManager.Instance.getEnabledResolutions('vod'),
+      CONFIG.TRANSCODING.ALWAYS_TRANSCODE_ORIGINAL_RESOLUTION
+    )
+
+    const videoInfo = await youtubeDL.getInfoForDownload()
+
+    const onlyAfterWithoutTime = new Date(onlyAfter)
+    onlyAfterWithoutTime.setHours(0, 0, 0, 0)
+
+    if (videoInfo.originallyPublishedAtWithoutTime.getTime() < onlyAfterWithoutTime.getTime()) {
+      return true
     }
   }
 
-  await JobQueue.Instance.createJobWithChildren(parent, children)
+  return false
 }