* Builds the full document for a video, combining title and description as plain-text * content. Returns null for unlisted/private/deleted videos, and (when configured) for * Shorts shorter than 60 seconds. * * Captions/transcripts are intentionally not fetched: `captions.download` requires OAut
(video: VideoItem, excludeShorts: boolean)
| 269 | * the video title plus description only. |
| 270 | */ |
| 271 | function videoToDocument(video: VideoItem, excludeShorts: boolean): ExternalDocument | null { |
| 272 | const videoId = video.id |
| 273 | if (!videoId) return null |
| 274 | |
| 275 | const privacyStatus = video.status?.privacyStatus |
| 276 | if (privacyStatus && privacyStatus !== 'public' && privacyStatus !== 'unlisted') { |
| 277 | return null |
| 278 | } |
| 279 | |
| 280 | if (excludeShorts) { |
| 281 | const seconds = parseIso8601Duration(video.contentDetails?.duration) |
| 282 | if (seconds != null && seconds > 0 && seconds < SHORTS_MAX_DURATION_SECONDS) { |
| 283 | return null |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | const snippet = video.snippet ?? {} |
| 288 | const title = snippet.title || 'Untitled' |
| 289 | const description = snippet.description ?? '' |
| 290 | const publishedAt = snippet.publishedAt ?? '' |
| 291 | const content = description.trim() ? `${title}\n\n${description}` : title |
| 292 | const tags = Array.isArray(snippet.tags) ? snippet.tags : [] |
| 293 | |
| 294 | return { |
| 295 | externalId: videoId, |
| 296 | title, |
| 297 | content, |
| 298 | contentDeferred: false, |
| 299 | mimeType: 'text/plain', |
| 300 | sourceUrl: `https://www.youtube.com/watch?v=${videoId}`, |
| 301 | contentHash: buildContentHash(videoId, publishedAt), |
| 302 | metadata: { |
| 303 | channelTitle: snippet.channelTitle ?? '', |
| 304 | publishedAt, |
| 305 | duration: video.contentDetails?.duration ?? '', |
| 306 | categoryId: snippet.categoryId ?? '', |
| 307 | tags, |
| 308 | }, |
| 309 | } |
| 310 | } |
| 311 | |
| 312 | export const youtubeConnector: ConnectorConfig = { |
| 313 | ...youtubeConnectorMeta, |
no test coverage detected