youtube-knowledge-mcp 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -38
- package/dist/brain-schemas.d.ts +10 -10
- package/dist/brain-schemas.d.ts.map +1 -1
- package/dist/brain-schemas.js +0 -4
- package/dist/brain-schemas.js.map +1 -1
- package/dist/harvest-schemas.d.ts +75 -0
- package/dist/harvest-schemas.d.ts.map +1 -0
- package/dist/harvest-schemas.js +106 -0
- package/dist/harvest-schemas.js.map +1 -0
- package/dist/http/app.d.ts +16 -0
- package/dist/http/app.d.ts.map +1 -0
- package/dist/http/app.js +176 -0
- package/dist/http/app.js.map +1 -0
- package/dist/http/auth.d.ts +38 -0
- package/dist/http/auth.d.ts.map +1 -0
- package/dist/http/auth.js +79 -0
- package/dist/http/auth.js.map +1 -0
- package/dist/http/config.d.ts +41 -0
- package/dist/http/config.d.ts.map +1 -0
- package/dist/http/config.js +65 -0
- package/dist/http/config.js.map +1 -0
- package/dist/http/rate-limiter.d.ts +24 -0
- package/dist/http/rate-limiter.d.ts.map +1 -0
- package/dist/http/rate-limiter.js +55 -0
- package/dist/http/rate-limiter.js.map +1 -0
- package/dist/http/sessions.d.ts +34 -0
- package/dist/http/sessions.d.ts.map +1 -0
- package/dist/http/sessions.js +62 -0
- package/dist/http/sessions.js.map +1 -0
- package/dist/http.d.ts +6 -48
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +35 -252
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -517
- package/dist/index.js.map +1 -1
- package/dist/prompts-brain.d.ts +4 -0
- package/dist/prompts-brain.d.ts.map +1 -0
- package/dist/prompts-brain.js +48 -0
- package/dist/prompts-brain.js.map +1 -0
- package/dist/prompts-research.d.ts +4 -0
- package/dist/prompts-research.d.ts.map +1 -0
- package/dist/prompts-research.js +74 -0
- package/dist/prompts-research.js.map +1 -0
- package/dist/prompts-shared.d.ts +13 -0
- package/dist/prompts-shared.d.ts.map +1 -0
- package/dist/prompts-shared.js +7 -0
- package/dist/prompts-shared.js.map +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +5 -100
- package/dist/prompts.js.map +1 -1
- package/dist/registry/brain-tools.d.ts +4 -0
- package/dist/registry/brain-tools.d.ts.map +1 -0
- package/dist/registry/brain-tools.js +104 -0
- package/dist/registry/brain-tools.js.map +1 -0
- package/dist/registry/channel-tools.d.ts +4 -0
- package/dist/registry/channel-tools.d.ts.map +1 -0
- package/dist/registry/channel-tools.js +53 -0
- package/dist/registry/channel-tools.js.map +1 -0
- package/dist/registry/harvest-tools.d.ts +10 -0
- package/dist/registry/harvest-tools.d.ts.map +1 -0
- package/dist/registry/harvest-tools.js +109 -0
- package/dist/registry/harvest-tools.js.map +1 -0
- package/dist/registry/health-tools.d.ts +4 -0
- package/dist/registry/health-tools.d.ts.map +1 -0
- package/dist/registry/health-tools.js +39 -0
- package/dist/registry/health-tools.js.map +1 -0
- package/dist/registry/index.d.ts +8 -0
- package/dist/registry/index.d.ts.map +1 -0
- package/dist/registry/index.js +29 -0
- package/dist/registry/index.js.map +1 -0
- package/dist/registry/library-tools.d.ts +4 -0
- package/dist/registry/library-tools.d.ts.map +1 -0
- package/dist/registry/library-tools.js +116 -0
- package/dist/registry/library-tools.js.map +1 -0
- package/dist/registry/media-tools.d.ts +4 -0
- package/dist/registry/media-tools.d.ts.map +1 -0
- package/dist/registry/media-tools.js +100 -0
- package/dist/registry/media-tools.js.map +1 -0
- package/dist/registry/thumbnail-tools.d.ts +7 -0
- package/dist/registry/thumbnail-tools.d.ts.map +1 -0
- package/dist/registry/thumbnail-tools.js +72 -0
- package/dist/registry/thumbnail-tools.js.map +1 -0
- package/dist/registry/transcript-tools.d.ts +4 -0
- package/dist/registry/transcript-tools.d.ts.map +1 -0
- package/dist/registry/transcript-tools.js +68 -0
- package/dist/registry/transcript-tools.js.map +1 -0
- package/dist/registry/types.d.ts +41 -0
- package/dist/registry/types.d.ts.map +1 -0
- package/dist/registry/types.js +17 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/registry/video-tools.d.ts +4 -0
- package/dist/registry/video-tools.d.ts.map +1 -0
- package/dist/registry/video-tools.js +101 -0
- package/dist/registry/video-tools.js.map +1 -0
- package/dist/resources.d.ts.map +1 -1
- package/dist/resources.js +13 -10
- package/dist/resources.js.map +1 -1
- package/dist/schemas.d.ts +250 -2
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +61 -0
- package/dist/schemas.js.map +1 -1
- package/dist/thumbnail-resource.d.ts +8 -0
- package/dist/thumbnail-resource.d.ts.map +1 -0
- package/dist/thumbnail-resource.js +38 -0
- package/dist/thumbnail-resource.js.map +1 -0
- package/dist/thumbnail-schemas.d.ts +512 -0
- package/dist/thumbnail-schemas.d.ts.map +1 -0
- package/dist/thumbnail-schemas.js +95 -0
- package/dist/thumbnail-schemas.js.map +1 -0
- package/dist/tools/ask-brain.js +1 -1
- package/dist/tools/ask-brain.js.map +1 -1
- package/dist/tools/batch.js +1 -1
- package/dist/tools/batch.js.map +1 -1
- package/dist/tools/brain-info.js +1 -1
- package/dist/tools/brain-info.js.map +1 -1
- package/dist/tools/build-brain.js +1 -1
- package/dist/tools/build-brain.js.map +1 -1
- package/dist/tools/check-health.d.ts +61 -0
- package/dist/tools/check-health.d.ts.map +1 -1
- package/dist/tools/check-health.js +94 -6
- package/dist/tools/check-health.js.map +1 -1
- package/dist/tools/clips.d.ts +9 -41
- package/dist/tools/clips.d.ts.map +1 -1
- package/dist/tools/clips.js +52 -128
- package/dist/tools/clips.js.map +1 -1
- package/dist/tools/fetch-channel-thumbnails.d.ts +179 -0
- package/dist/tools/fetch-channel-thumbnails.d.ts.map +1 -0
- package/dist/tools/fetch-channel-thumbnails.js +123 -0
- package/dist/tools/fetch-channel-thumbnails.js.map +1 -0
- package/dist/tools/fetch-videos.d.ts +18 -4
- package/dist/tools/fetch-videos.d.ts.map +1 -1
- package/dist/tools/fetch-videos.js +64 -20
- package/dist/tools/fetch-videos.js.map +1 -1
- package/dist/tools/frames-subtitles.d.ts +44 -0
- package/dist/tools/frames-subtitles.d.ts.map +1 -0
- package/dist/tools/frames-subtitles.js +104 -0
- package/dist/tools/frames-subtitles.js.map +1 -0
- package/dist/tools/get-channel-info.d.ts +2 -0
- package/dist/tools/get-channel-info.d.ts.map +1 -1
- package/dist/tools/get-channel-info.js +8 -1
- package/dist/tools/get-channel-info.js.map +1 -1
- package/dist/tools/get-comments.d.ts +238 -6
- package/dist/tools/get-comments.d.ts.map +1 -1
- package/dist/tools/get-comments.js +85 -21
- package/dist/tools/get-comments.js.map +1 -1
- package/dist/tools/get-coverage.d.ts +122 -0
- package/dist/tools/get-coverage.d.ts.map +1 -0
- package/dist/tools/get-coverage.js +105 -0
- package/dist/tools/get-coverage.js.map +1 -0
- package/dist/tools/get-playlist-info.d.ts.map +1 -1
- package/dist/tools/get-playlist-info.js +1 -0
- package/dist/tools/get-playlist-info.js.map +1 -1
- package/dist/tools/get-thumbnail.d.ts +38 -0
- package/dist/tools/get-thumbnail.d.ts.map +1 -0
- package/dist/tools/get-thumbnail.js +152 -0
- package/dist/tools/get-thumbnail.js.map +1 -0
- package/dist/tools/get-transcript.d.ts.map +1 -1
- package/dist/tools/get-transcript.js +2 -14
- package/dist/tools/get-transcript.js.map +1 -1
- package/dist/tools/harvest-channel.d.ts +92 -0
- package/dist/tools/harvest-channel.d.ts.map +1 -0
- package/dist/tools/harvest-channel.js +62 -0
- package/dist/tools/harvest-channel.js.map +1 -0
- package/dist/tools/harvest-comments.d.ts +81 -0
- package/dist/tools/harvest-comments.d.ts.map +1 -0
- package/dist/tools/harvest-comments.js +115 -0
- package/dist/tools/harvest-comments.js.map +1 -0
- package/dist/tools/library.d.ts.map +1 -1
- package/dist/tools/library.js +14 -4
- package/dist/tools/library.js.map +1 -1
- package/dist/tools/list-channel-thumbnails.d.ts +235 -0
- package/dist/tools/list-channel-thumbnails.d.ts.map +1 -0
- package/dist/tools/list-channel-thumbnails.js +79 -0
- package/dist/tools/list-channel-thumbnails.js.map +1 -0
- package/dist/tools/list-library.js +1 -1
- package/dist/tools/list-library.js.map +1 -1
- package/dist/tools/prune-harvest.d.ts +59 -0
- package/dist/tools/prune-harvest.d.ts.map +1 -0
- package/dist/tools/prune-harvest.js +108 -0
- package/dist/tools/prune-harvest.js.map +1 -0
- package/dist/tools/query-comments.d.ts +125 -0
- package/dist/tools/query-comments.d.ts.map +1 -0
- package/dist/tools/query-comments.js +106 -0
- package/dist/tools/query-comments.js.map +1 -0
- package/dist/tools/query-videos.d.ts +118 -0
- package/dist/tools/query-videos.d.ts.map +1 -0
- package/dist/tools/query-videos.js +97 -0
- package/dist/tools/query-videos.js.map +1 -0
- package/dist/tools/repair-store.d.ts +34 -0
- package/dist/tools/repair-store.d.ts.map +1 -0
- package/dist/tools/repair-store.js +58 -0
- package/dist/tools/repair-store.js.map +1 -0
- package/dist/tools/save-to-library.d.ts.map +1 -1
- package/dist/tools/save-to-library.js +5 -1
- package/dist/tools/save-to-library.js.map +1 -1
- package/dist/tools/search-channels.d.ts +6 -0
- package/dist/tools/search-channels.d.ts.map +1 -1
- package/dist/tools/search-channels.js +5 -1
- package/dist/tools/search-channels.js.map +1 -1
- package/dist/tools/search-transcript.d.ts.map +1 -1
- package/dist/tools/search-transcript.js +6 -13
- package/dist/tools/search-transcript.js.map +1 -1
- package/dist/tools/search-videos.d.ts +3 -0
- package/dist/tools/search-videos.d.ts.map +1 -1
- package/dist/tools/search-videos.js +1 -1
- package/dist/tools/search-videos.js.map +1 -1
- package/dist/utils/batches.d.ts +15 -0
- package/dist/utils/batches.d.ts.map +1 -0
- package/dist/utils/batches.js +31 -0
- package/dist/utils/batches.js.map +1 -0
- package/dist/utils/brain-build.d.ts.map +1 -1
- package/dist/utils/brain-build.js +1 -12
- package/dist/utils/brain-build.js.map +1 -1
- package/dist/utils/brain-index.d.ts.map +1 -1
- package/dist/utils/brain-index.js +3 -2
- package/dist/utils/brain-index.js.map +1 -1
- package/dist/utils/brain-lock.d.ts +2 -18
- package/dist/utils/brain-lock.d.ts.map +1 -1
- package/dist/utils/brain-lock.js +4 -80
- package/dist/utils/brain-lock.js.map +1 -1
- package/dist/utils/brain-lookup.d.ts +8 -0
- package/dist/utils/brain-lookup.d.ts.map +1 -1
- package/dist/utils/brain-lookup.js +5 -31
- package/dist/utils/brain-lookup.js.map +1 -1
- package/dist/utils/brain-storage.d.ts.map +1 -1
- package/dist/utils/brain-storage.js +5 -5
- package/dist/utils/brain-storage.js.map +1 -1
- package/dist/utils/caption-probe.d.ts +7 -0
- package/dist/utils/caption-probe.d.ts.map +1 -0
- package/dist/utils/caption-probe.js +36 -0
- package/dist/utils/caption-probe.js.map +1 -0
- package/dist/utils/channel-images.d.ts +16 -0
- package/dist/utils/channel-images.d.ts.map +1 -0
- package/dist/utils/channel-images.js +35 -0
- package/dist/utils/channel-images.js.map +1 -0
- package/dist/utils/channel-lookup.d.ts +5 -0
- package/dist/utils/channel-lookup.d.ts.map +1 -0
- package/dist/utils/channel-lookup.js +37 -0
- package/dist/utils/channel-lookup.js.map +1 -0
- package/dist/utils/chapters.d.ts +11 -0
- package/dist/utils/chapters.d.ts.map +1 -0
- package/dist/utils/chapters.js +24 -0
- package/dist/utils/chapters.js.map +1 -0
- package/dist/utils/clips.d.ts.map +1 -1
- package/dist/utils/clips.js +18 -26
- package/dist/utils/clips.js.map +1 -1
- package/dist/utils/comment-store.d.ts +71 -0
- package/dist/utils/comment-store.d.ts.map +1 -0
- package/dist/utils/comment-store.js +129 -0
- package/dist/utils/comment-store.js.map +1 -0
- package/dist/utils/comment-threads.d.ts +51 -0
- package/dist/utils/comment-threads.d.ts.map +1 -0
- package/dist/utils/comment-threads.js +76 -0
- package/dist/utils/comment-threads.js.map +1 -0
- package/dist/utils/coverage-text.d.ts +3 -0
- package/dist/utils/coverage-text.d.ts.map +1 -0
- package/dist/utils/coverage-text.js +62 -0
- package/dist/utils/coverage-text.js.map +1 -0
- package/dist/utils/coverage.d.ts +57 -0
- package/dist/utils/coverage.d.ts.map +1 -0
- package/dist/utils/coverage.js +142 -0
- package/dist/utils/coverage.js.map +1 -0
- package/dist/utils/env.d.ts +26 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +72 -0
- package/dist/utils/env.js.map +1 -0
- package/dist/utils/errors.d.ts +1 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +28 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/file-lock.d.ts +34 -0
- package/dist/utils/file-lock.d.ts.map +1 -0
- package/dist/utils/file-lock.js +91 -0
- package/dist/utils/file-lock.js.map +1 -0
- package/dist/utils/flat-listing.d.ts +89 -0
- package/dist/utils/flat-listing.d.ts.map +1 -0
- package/dist/utils/flat-listing.js +68 -0
- package/dist/utils/flat-listing.js.map +1 -0
- package/dist/utils/format.d.ts +18 -4
- package/dist/utils/format.d.ts.map +1 -1
- package/dist/utils/format.js +2 -6
- package/dist/utils/format.js.map +1 -1
- package/dist/utils/guard.d.ts +21 -0
- package/dist/utils/guard.d.ts.map +1 -0
- package/dist/utils/guard.js +105 -0
- package/dist/utils/guard.js.map +1 -0
- package/dist/utils/harvest-catalog.d.ts +44 -0
- package/dist/utils/harvest-catalog.d.ts.map +1 -0
- package/dist/utils/harvest-catalog.js +164 -0
- package/dist/utils/harvest-catalog.js.map +1 -0
- package/dist/utils/harvest-lock.d.ts +3 -0
- package/dist/utils/harvest-lock.d.ts.map +1 -0
- package/dist/utils/harvest-lock.js +26 -0
- package/dist/utils/harvest-lock.js.map +1 -0
- package/dist/utils/harvest-receipts.d.ts +14 -0
- package/dist/utils/harvest-receipts.d.ts.map +1 -0
- package/dist/utils/harvest-receipts.js +110 -0
- package/dist/utils/harvest-receipts.js.map +1 -0
- package/dist/utils/image-dimensions.d.ts +19 -0
- package/dist/utils/image-dimensions.d.ts.map +1 -0
- package/dist/utils/image-dimensions.js +93 -0
- package/dist/utils/image-dimensions.js.map +1 -0
- package/dist/utils/image-fetch.d.ts +31 -0
- package/dist/utils/image-fetch.d.ts.map +1 -0
- package/dist/utils/image-fetch.js +141 -0
- package/dist/utils/image-fetch.js.map +1 -0
- package/dist/utils/json-file.d.ts +14 -5
- package/dist/utils/json-file.d.ts.map +1 -1
- package/dist/utils/json-file.js +24 -9
- package/dist/utils/json-file.js.map +1 -1
- package/dist/utils/listing-cursor.d.ts +31 -0
- package/dist/utils/listing-cursor.d.ts.map +1 -0
- package/dist/utils/listing-cursor.js +39 -0
- package/dist/utils/listing-cursor.js.map +1 -0
- package/dist/utils/paths.d.ts +10 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -0
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/pattern.d.ts +30 -0
- package/dist/utils/pattern.d.ts.map +1 -0
- package/dist/utils/pattern.js +130 -0
- package/dist/utils/pattern.js.map +1 -0
- package/dist/utils/pot-preflight.d.ts +53 -0
- package/dist/utils/pot-preflight.d.ts.map +1 -0
- package/dist/utils/pot-preflight.js +146 -0
- package/dist/utils/pot-preflight.js.map +1 -0
- package/dist/utils/search-index.d.ts.map +1 -1
- package/dist/utils/search-index.js +9 -4
- package/dist/utils/search-index.js.map +1 -1
- package/dist/utils/sleep.d.ts +9 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +25 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/storage.d.ts.map +1 -1
- package/dist/utils/storage.js +14 -8
- package/dist/utils/storage.js.map +1 -1
- package/dist/utils/store-health.d.ts +37 -0
- package/dist/utils/store-health.d.ts.map +1 -0
- package/dist/utils/store-health.js +92 -0
- package/dist/utils/store-health.js.map +1 -0
- package/dist/utils/store-migrations.d.ts +33 -0
- package/dist/utils/store-migrations.d.ts.map +1 -0
- package/dist/utils/store-migrations.js +41 -0
- package/dist/utils/store-migrations.js.map +1 -0
- package/dist/utils/store-paths.d.ts +33 -0
- package/dist/utils/store-paths.d.ts.map +1 -0
- package/dist/utils/store-paths.js +48 -0
- package/dist/utils/store-paths.js.map +1 -0
- package/dist/utils/store-rows.d.ts +22 -0
- package/dist/utils/store-rows.d.ts.map +1 -0
- package/dist/utils/store-rows.js +62 -0
- package/dist/utils/store-rows.js.map +1 -0
- package/dist/utils/store-schema.d.ts +16 -0
- package/dist/utils/store-schema.d.ts.map +1 -0
- package/dist/utils/store-schema.js +168 -0
- package/dist/utils/store-schema.js.map +1 -0
- package/dist/utils/store.d.ts +34 -0
- package/dist/utils/store.d.ts.map +1 -0
- package/dist/utils/store.js +157 -0
- package/dist/utils/store.js.map +1 -0
- package/dist/utils/subtitles.d.ts +7 -0
- package/dist/utils/subtitles.d.ts.map +1 -0
- package/dist/utils/subtitles.js +30 -0
- package/dist/utils/subtitles.js.map +1 -0
- package/dist/utils/thumbnail-entry.d.ts +19 -0
- package/dist/utils/thumbnail-entry.d.ts.map +1 -0
- package/dist/utils/thumbnail-entry.js +119 -0
- package/dist/utils/thumbnail-entry.js.map +1 -0
- package/dist/utils/thumbnail-fetch.d.ts +37 -0
- package/dist/utils/thumbnail-fetch.d.ts.map +1 -0
- package/dist/utils/thumbnail-fetch.js +89 -0
- package/dist/utils/thumbnail-fetch.js.map +1 -0
- package/dist/utils/thumbnail-ladder.d.ts +44 -0
- package/dist/utils/thumbnail-ladder.d.ts.map +1 -0
- package/dist/utils/thumbnail-ladder.js +68 -0
- package/dist/utils/thumbnail-ladder.js.map +1 -0
- package/dist/utils/thumbnail-listing.d.ts +16 -0
- package/dist/utils/thumbnail-listing.d.ts.map +1 -0
- package/dist/utils/thumbnail-listing.js +26 -0
- package/dist/utils/thumbnail-listing.js.map +1 -0
- package/dist/utils/thumbnail-paths.d.ts +20 -0
- package/dist/utils/thumbnail-paths.d.ts.map +1 -0
- package/dist/utils/thumbnail-paths.js +35 -0
- package/dist/utils/thumbnail-paths.js.map +1 -0
- package/dist/utils/thumbnail-store.d.ts +19 -0
- package/dist/utils/thumbnail-store.d.ts.map +1 -0
- package/dist/utils/thumbnail-store.js +125 -0
- package/dist/utils/thumbnail-store.js.map +1 -0
- package/dist/utils/transcript-cache.d.ts +20 -0
- package/dist/utils/transcript-cache.d.ts.map +1 -0
- package/dist/utils/transcript-cache.js +127 -0
- package/dist/utils/transcript-cache.js.map +1 -0
- package/dist/utils/transcript-search.d.ts +20 -0
- package/dist/utils/transcript-search.d.ts.map +1 -0
- package/dist/utils/transcript-search.js +35 -0
- package/dist/utils/transcript-search.js.map +1 -0
- package/dist/utils/transcript.d.ts +10 -31
- package/dist/utils/transcript.d.ts.map +1 -1
- package/dist/utils/transcript.js +2 -64
- package/dist/utils/transcript.js.map +1 -1
- package/dist/utils/validate-youtube.d.ts +35 -0
- package/dist/utils/validate-youtube.d.ts.map +1 -0
- package/dist/utils/validate-youtube.js +87 -0
- package/dist/utils/validate-youtube.js.map +1 -0
- package/dist/utils/validate.d.ts +11 -4
- package/dist/utils/validate.d.ts.map +1 -1
- package/dist/utils/validate.js +43 -36
- package/dist/utils/validate.js.map +1 -1
- package/dist/utils/version.d.ts +2 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +19 -0
- package/dist/utils/version.js.map +1 -0
- package/dist/utils/video-stats-cache.d.ts +16 -0
- package/dist/utils/video-stats-cache.d.ts.map +1 -0
- package/dist/utils/video-stats-cache.js +81 -0
- package/dist/utils/video-stats-cache.js.map +1 -0
- package/dist/utils/video-stats.d.ts +186 -0
- package/dist/utils/video-stats.d.ts.map +1 -0
- package/dist/utils/video-stats.js +168 -0
- package/dist/utils/video-stats.js.map +1 -0
- package/dist/utils/video-store.d.ts +69 -0
- package/dist/utils/video-store.d.ts.map +1 -0
- package/dist/utils/video-store.js +77 -0
- package/dist/utils/video-store.js.map +1 -0
- package/dist/utils/youtube-channel.d.ts +51 -0
- package/dist/utils/youtube-channel.d.ts.map +1 -0
- package/dist/utils/youtube-channel.js +91 -0
- package/dist/utils/youtube-channel.js.map +1 -0
- package/dist/utils/youtube-download.d.ts +27 -0
- package/dist/utils/youtube-download.d.ts.map +1 -0
- package/dist/utils/youtube-download.js +118 -0
- package/dist/utils/youtube-download.js.map +1 -0
- package/dist/utils/youtube-schemas.d.ts +492 -0
- package/dist/utils/youtube-schemas.d.ts.map +1 -0
- package/dist/utils/youtube-schemas.js +148 -0
- package/dist/utils/youtube-schemas.js.map +1 -0
- package/dist/utils/youtube-search.d.ts +14 -0
- package/dist/utils/youtube-search.d.ts.map +1 -0
- package/dist/utils/youtube-search.js +39 -0
- package/dist/utils/youtube-search.js.map +1 -0
- package/dist/utils/youtube-url.d.ts +25 -0
- package/dist/utils/youtube-url.d.ts.map +1 -0
- package/dist/utils/youtube-url.js +75 -0
- package/dist/utils/youtube-url.js.map +1 -0
- package/dist/utils/youtube-video.d.ts +68 -0
- package/dist/utils/youtube-video.d.ts.map +1 -0
- package/dist/utils/youtube-video.js +110 -0
- package/dist/utils/youtube-video.js.map +1 -0
- package/dist/utils/youtube.d.ts +10 -122
- package/dist/utils/youtube.d.ts.map +1 -1
- package/dist/utils/youtube.js +11 -486
- package/dist/utils/youtube.js.map +1 -1
- package/dist/utils/ytdlp-env.d.ts +33 -0
- package/dist/utils/ytdlp-env.d.ts.map +1 -0
- package/dist/utils/ytdlp-env.js +121 -0
- package/dist/utils/ytdlp-env.js.map +1 -0
- package/dist/utils/ytdlp-limiter.d.ts +27 -0
- package/dist/utils/ytdlp-limiter.d.ts.map +1 -0
- package/dist/utils/ytdlp-limiter.js +85 -0
- package/dist/utils/ytdlp-limiter.js.map +1 -0
- package/dist/utils/ytdlp-pacer.d.ts +64 -0
- package/dist/utils/ytdlp-pacer.d.ts.map +1 -0
- package/dist/utils/ytdlp-pacer.js +165 -0
- package/dist/utils/ytdlp-pacer.js.map +1 -0
- package/dist/utils/ytdlp-parse.d.ts +13 -0
- package/dist/utils/ytdlp-parse.d.ts.map +1 -0
- package/dist/utils/ytdlp-parse.js +48 -0
- package/dist/utils/ytdlp-parse.js.map +1 -0
- package/dist/utils/ytdlp-stream.d.ts +32 -0
- package/dist/utils/ytdlp-stream.d.ts.map +1 -0
- package/dist/utils/ytdlp-stream.js +61 -0
- package/dist/utils/ytdlp-stream.js.map +1 -0
- package/dist/utils/ytdlp.d.ts +23 -18
- package/dist/utils/ytdlp.d.ts.map +1 -1
- package/dist/utils/ytdlp.js +56 -134
- package/dist/utils/ytdlp.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { VideoListItem } from './youtube-channel.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reading a flat channel or playlist listing.
|
|
5
|
+
*
|
|
6
|
+
* `--flat-playlist` lists a channel in one request instead of one per video,
|
|
7
|
+
* and each entry carries its thumbnail URLs — which is what makes a channel's
|
|
8
|
+
* thumbnails reachable without extracting every video. Printed as one JSON
|
|
9
|
+
* object per line with exactly these fields, so a title containing a delimiter
|
|
10
|
+
* cannot shift the others, and the parser checks each field's type.
|
|
11
|
+
*
|
|
12
|
+
* Verified against yt-dlp 2026.07.04: a flat entry carries `thumbnails` but no
|
|
13
|
+
* `upload_date`, so the date stays empty here and is resolved per video by the
|
|
14
|
+
* callers that need it.
|
|
15
|
+
*/
|
|
16
|
+
export declare const FLAT_PRINT_TEMPLATE = "%(.{id,title,duration,upload_date,timestamp,view_count,live_status,availability,thumbnails})j";
|
|
17
|
+
/** One entry of a thumbnails array; sizes are absent for some channel images. */
|
|
18
|
+
export declare const listedImageSchema: z.ZodObject<{
|
|
19
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
20
|
+
url: z.ZodString;
|
|
21
|
+
width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
22
|
+
height: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
23
|
+
}, "strip", z.ZodTypeAny, {
|
|
24
|
+
url: string;
|
|
25
|
+
id?: string | null | undefined;
|
|
26
|
+
width?: number | null | undefined;
|
|
27
|
+
height?: number | null | undefined;
|
|
28
|
+
}, {
|
|
29
|
+
url: string;
|
|
30
|
+
id?: string | null | undefined;
|
|
31
|
+
width?: number | null | undefined;
|
|
32
|
+
height?: number | null | undefined;
|
|
33
|
+
}>;
|
|
34
|
+
export type ListedImage = z.infer<typeof listedImageSchema>;
|
|
35
|
+
export declare const flatEntrySchema: z.ZodObject<{
|
|
36
|
+
id: z.ZodString;
|
|
37
|
+
title: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
38
|
+
duration: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
39
|
+
upload_date: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
40
|
+
view_count: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
41
|
+
live_status: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
42
|
+
thumbnails: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodObject<{
|
|
43
|
+
id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
44
|
+
url: z.ZodString;
|
|
45
|
+
width: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
46
|
+
height: z.ZodOptional<z.ZodNullable<z.ZodNumber>>;
|
|
47
|
+
}, "strip", z.ZodTypeAny, {
|
|
48
|
+
url: string;
|
|
49
|
+
id?: string | null | undefined;
|
|
50
|
+
width?: number | null | undefined;
|
|
51
|
+
height?: number | null | undefined;
|
|
52
|
+
}, {
|
|
53
|
+
url: string;
|
|
54
|
+
id?: string | null | undefined;
|
|
55
|
+
width?: number | null | undefined;
|
|
56
|
+
height?: number | null | undefined;
|
|
57
|
+
}>, "many">>>;
|
|
58
|
+
}, "strip", z.ZodTypeAny, {
|
|
59
|
+
id: string;
|
|
60
|
+
title?: string | null | undefined;
|
|
61
|
+
duration?: number | null | undefined;
|
|
62
|
+
upload_date?: string | null | undefined;
|
|
63
|
+
view_count?: number | null | undefined;
|
|
64
|
+
live_status?: string | null | undefined;
|
|
65
|
+
thumbnails?: {
|
|
66
|
+
url: string;
|
|
67
|
+
id?: string | null | undefined;
|
|
68
|
+
width?: number | null | undefined;
|
|
69
|
+
height?: number | null | undefined;
|
|
70
|
+
}[] | null | undefined;
|
|
71
|
+
}, {
|
|
72
|
+
id: string;
|
|
73
|
+
title?: string | null | undefined;
|
|
74
|
+
duration?: number | null | undefined;
|
|
75
|
+
upload_date?: string | null | undefined;
|
|
76
|
+
view_count?: number | null | undefined;
|
|
77
|
+
live_status?: string | null | undefined;
|
|
78
|
+
thumbnails?: {
|
|
79
|
+
url: string;
|
|
80
|
+
id?: string | null | undefined;
|
|
81
|
+
width?: number | null | undefined;
|
|
82
|
+
height?: number | null | undefined;
|
|
83
|
+
}[] | null | undefined;
|
|
84
|
+
}>;
|
|
85
|
+
export type FlatEntry = z.infer<typeof flatEntrySchema>;
|
|
86
|
+
/** The largest image by area, then by width; `undefined` for an empty list. */
|
|
87
|
+
export declare function largestThumbnail(thumbnails: ListedImage[]): ListedImage | undefined;
|
|
88
|
+
export declare function toVideoListItem(entry: FlatEntry): VideoListItem;
|
|
89
|
+
//# sourceMappingURL=flat-listing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flat-listing.d.ts","sourceRoot":"","sources":["../../src/utils/flat-listing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D;;;;;;;;;;;;GAYG;AAEH,eAAO,MAAM,mBAAmB,kGACiE,CAAC;AAElG,iFAAiF;AACjF,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAK5B,CAAC;AAEH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAQ1B,CAAC;AAEH,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAExD,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,GAAG,SAAS,CAQnF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAqB/D"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { formatYouTubeDate } from './format.js';
|
|
3
|
+
import { formatDuration, watchUrl } from './youtube-url.js';
|
|
4
|
+
/**
|
|
5
|
+
* Reading a flat channel or playlist listing.
|
|
6
|
+
*
|
|
7
|
+
* `--flat-playlist` lists a channel in one request instead of one per video,
|
|
8
|
+
* and each entry carries its thumbnail URLs — which is what makes a channel's
|
|
9
|
+
* thumbnails reachable without extracting every video. Printed as one JSON
|
|
10
|
+
* object per line with exactly these fields, so a title containing a delimiter
|
|
11
|
+
* cannot shift the others, and the parser checks each field's type.
|
|
12
|
+
*
|
|
13
|
+
* Verified against yt-dlp 2026.07.04: a flat entry carries `thumbnails` but no
|
|
14
|
+
* `upload_date`, so the date stays empty here and is resolved per video by the
|
|
15
|
+
* callers that need it.
|
|
16
|
+
*/
|
|
17
|
+
export const FLAT_PRINT_TEMPLATE = '%(.{id,title,duration,upload_date,timestamp,view_count,live_status,availability,thumbnails})j';
|
|
18
|
+
/** One entry of a thumbnails array; sizes are absent for some channel images. */
|
|
19
|
+
export const listedImageSchema = z.object({
|
|
20
|
+
id: z.string().nullish(),
|
|
21
|
+
url: z.string(),
|
|
22
|
+
width: z.number().nullish(),
|
|
23
|
+
height: z.number().nullish(),
|
|
24
|
+
});
|
|
25
|
+
export const flatEntrySchema = z.object({
|
|
26
|
+
id: z.string(),
|
|
27
|
+
title: z.string().nullish(),
|
|
28
|
+
duration: z.number().nullish(),
|
|
29
|
+
upload_date: z.string().nullish(),
|
|
30
|
+
view_count: z.number().nullish(),
|
|
31
|
+
live_status: z.string().nullish(),
|
|
32
|
+
thumbnails: z.array(listedImageSchema).nullish(),
|
|
33
|
+
});
|
|
34
|
+
/** The largest image by area, then by width; `undefined` for an empty list. */
|
|
35
|
+
export function largestThumbnail(thumbnails) {
|
|
36
|
+
const area = (image) => (image.width ?? 0) * (image.height ?? 0);
|
|
37
|
+
return thumbnails.reduce((best, image) => {
|
|
38
|
+
if (best === undefined)
|
|
39
|
+
return image;
|
|
40
|
+
if (area(image) > area(best))
|
|
41
|
+
return image;
|
|
42
|
+
if (area(image) === area(best) && (image.width ?? 0) > (best.width ?? 0))
|
|
43
|
+
return image;
|
|
44
|
+
return best;
|
|
45
|
+
}, undefined);
|
|
46
|
+
}
|
|
47
|
+
export function toVideoListItem(entry) {
|
|
48
|
+
const duration = entry.duration ?? 0;
|
|
49
|
+
const thumbnails = entry.thumbnails ?? [];
|
|
50
|
+
const largest = largestThumbnail(thumbnails);
|
|
51
|
+
return {
|
|
52
|
+
id: entry.id,
|
|
53
|
+
title: entry.title ?? 'Unknown title',
|
|
54
|
+
duration,
|
|
55
|
+
durationFormatted: formatDuration(duration),
|
|
56
|
+
uploadDate: formatYouTubeDate(entry.upload_date ?? ''),
|
|
57
|
+
url: watchUrl(entry.id),
|
|
58
|
+
...(largest === undefined ? {} : { thumbnailUrl: largest.url }),
|
|
59
|
+
...(thumbnails.length === 0 ? {} : { thumbnails }),
|
|
60
|
+
...(entry.view_count === null || entry.view_count === undefined
|
|
61
|
+
? {}
|
|
62
|
+
: { viewCount: entry.view_count }),
|
|
63
|
+
...(entry.live_status === null || entry.live_status === undefined
|
|
64
|
+
? {}
|
|
65
|
+
: { liveStatus: entry.live_status }),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=flat-listing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flat-listing.js","sourceRoot":"","sources":["../../src/utils/flat-listing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5D;;;;;;;;;;;;GAYG;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAC9B,+FAA+F,CAAC;AAElG,iFAAiF;AACjF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACxB,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;IACf,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;CAC7B,CAAC,CAAC;AAIH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE;IACd,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC3B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAC9B,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IAChC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE;IACjC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;CACjD,CAAC,CAAC;AAIH,+EAA+E;AAC/E,MAAM,UAAU,gBAAgB,CAAC,UAAyB;IACxD,MAAM,IAAI,GAAG,CAAC,KAAkB,EAAU,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;IACtF,OAAO,UAAU,CAAC,MAAM,CAA0B,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChE,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QACrC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QAC3C,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;YAAE,OAAO,KAAK,CAAC;QACvF,OAAO,IAAI,CAAC;IACd,CAAC,EAAE,SAAS,CAAC,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAgB;IAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,QAAQ,IAAI,CAAC,CAAC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC;IAC1C,MAAM,OAAO,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;IAE7C,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,eAAe;QACrC,QAAQ;QACR,iBAAiB,EAAE,cAAc,CAAC,QAAQ,CAAC;QAC3C,UAAU,EAAE,iBAAiB,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;QACtD,GAAG,EAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;QAC/D,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QAClD,GAAG,CAAC,KAAK,CAAC,UAAU,KAAK,IAAI,IAAI,KAAK,CAAC,UAAU,KAAK,SAAS;YAC7D,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE,CAAC;QACpC,GAAG,CAAC,KAAK,CAAC,WAAW,KAAK,IAAI,IAAI,KAAK,CAAC,WAAW,KAAK,SAAS;YAC/D,CAAC,CAAC,EAAE;YACJ,CAAC,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;KACvC,CAAC;AACJ,CAAC"}
|
package/dist/utils/format.d.ts
CHANGED
|
@@ -2,13 +2,11 @@ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
|
2
2
|
export declare function formatCount(count: number): string;
|
|
3
3
|
export declare function formatYouTubeDate(yyyymmdd: string): string;
|
|
4
4
|
export declare function formatFilesize(bytes?: number): string;
|
|
5
|
-
export declare function textContent(text: string): CallToolResult;
|
|
6
5
|
/**
|
|
7
6
|
* A tool result carrying both a human-readable rendering and machine-readable
|
|
8
7
|
* data.
|
|
9
8
|
*
|
|
10
|
-
* The text block is
|
|
11
|
-
* nothing a client already displays changes; `structuredContent` is additive and
|
|
9
|
+
* The text block is what a client displays; `structuredContent` is additive and
|
|
12
10
|
* is what the tool's `outputSchema` describes. Every tool that declares an
|
|
13
11
|
* output schema must return this, because the SDK validates the two against
|
|
14
12
|
* each other.
|
|
@@ -22,7 +20,23 @@ export interface PageInfo {
|
|
|
22
20
|
hasMore: boolean;
|
|
23
21
|
nextOffset?: number;
|
|
24
22
|
}
|
|
25
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Takes an object, not three adjacent numbers.
|
|
25
|
+
*
|
|
26
|
+
* The bug this replaces was not in the arithmetic: it was five call sites that
|
|
27
|
+
* passed `count` where `total` belonged, so `hasMore` computed `n < n` and a
|
|
28
|
+
* caller with 20 of a channel's 5,000 videos was told it had all of them.
|
|
29
|
+
* Positional arguments of the same type made that invisible; an object makes
|
|
30
|
+
* it impossible, and changing the signature forced every call site to be
|
|
31
|
+
* revisited, which was the point.
|
|
32
|
+
*/
|
|
33
|
+
export interface PageInput {
|
|
34
|
+
/** Items available in total. Never `count` — that is the bug this shape prevents. */
|
|
35
|
+
total: number;
|
|
36
|
+
count: number;
|
|
37
|
+
offset?: number;
|
|
38
|
+
}
|
|
39
|
+
export declare function pageInfo({ total, count, offset }: PageInput): PageInfo;
|
|
26
40
|
/** A link to a file this server produced, so clients can offer to open it. */
|
|
27
41
|
export declare function fileResourceLink(filePath: string, name: string, mimeType?: string): {
|
|
28
42
|
type: 'resource_link';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAKjD;AAOD,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAKrD;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAK5F;AAED,wEAAwE;AACxE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,SAAS;IACxB,qFAAqF;IACrF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,QAAQ,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAU,EAAE,EAAE,SAAS,GAAG,QAAQ,CAS1E;AAED,8EAA8E;AAC9E,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAChB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAOzE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACnC,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACtD,cAAc,CAQhB"}
|
package/dist/utils/format.js
CHANGED
|
@@ -25,15 +25,11 @@ export function formatFilesize(bytes) {
|
|
|
25
25
|
return `${(bytes / 1024 / 1024).toFixed(1)} MB`;
|
|
26
26
|
return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
27
27
|
}
|
|
28
|
-
export function textContent(text) {
|
|
29
|
-
return { content: [{ type: 'text', text }] };
|
|
30
|
-
}
|
|
31
28
|
/**
|
|
32
29
|
* A tool result carrying both a human-readable rendering and machine-readable
|
|
33
30
|
* data.
|
|
34
31
|
*
|
|
35
|
-
* The text block is
|
|
36
|
-
* nothing a client already displays changes; `structuredContent` is additive and
|
|
32
|
+
* The text block is what a client displays; `structuredContent` is additive and
|
|
37
33
|
* is what the tool's `outputSchema` describes. Every tool that declares an
|
|
38
34
|
* output schema must return this, because the SDK validates the two against
|
|
39
35
|
* each other.
|
|
@@ -44,7 +40,7 @@ export function toolResult(text, structured) {
|
|
|
44
40
|
structuredContent: structured,
|
|
45
41
|
};
|
|
46
42
|
}
|
|
47
|
-
export function pageInfo(total, count, offset = 0) {
|
|
43
|
+
export function pageInfo({ total, count, offset = 0 }) {
|
|
48
44
|
const hasMore = offset + count < total;
|
|
49
45
|
return {
|
|
50
46
|
total,
|
package/dist/utils/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,KAAK,IAAI,aAAa;QAAE,OAAO,GAAG,gBAAgB,CAAC,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC;IACjF,IAAI,KAAK,IAAI,SAAS;QAAE,OAAO,GAAG,gBAAgB,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC;IACzE,IAAI,KAAK,IAAI,KAAK;QAAE,OAAO,GAAG,gBAAgB,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC;IACjE,OAAO,KAAK,CAAC,QAAQ,EAAE,CAAC;AAC1B,CAAC;AAED,SAAS,gBAAgB,CAAC,CAAS;IACjC,MAAM,KAAK,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAC3B,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC3D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChD,OAAO,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAClE,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;QAAE,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;IAChF,OAAO,GAAG,CAAC,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACzD,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/utils/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
/** Any tool handler: whatever it takes, it answers with a tool result. */
|
|
3
|
+
type ToolLike = (...args: never[]) => CallToolResult | Promise<CallToolResult>;
|
|
4
|
+
/**
|
|
5
|
+
* Wrap a tool handler, keeping its exact type.
|
|
6
|
+
*
|
|
7
|
+
* A Proxy rather than an arrow function because the SDK's `registerTool` is
|
|
8
|
+
* generic over the input schema and demands a callback of the precise type it
|
|
9
|
+
* derives from it; a new function would need a cast to claim that type, while
|
|
10
|
+
* a Proxy over the original *is* that type.
|
|
11
|
+
*/
|
|
12
|
+
export declare function guarded<F extends ToolLike>(handler: F): F;
|
|
13
|
+
/**
|
|
14
|
+
* The resource counterpart. A read that fails used to propagate whatever was
|
|
15
|
+
* thrown — an `ENOENT` carrying an absolute local path, for instance — as the
|
|
16
|
+
* JSON-RPC error message. It now carries the same `[CODE] message` a tool
|
|
17
|
+
* would show, and nothing else.
|
|
18
|
+
*/
|
|
19
|
+
export declare function guardedResource<A extends unknown[], R>(handler: (...args: A) => Promise<R>): (...args: A) => Promise<R>;
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.d.ts","sourceRoot":"","sources":["../../src/utils/guard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAoEzE,0EAA0E;AAC1E,KAAK,QAAQ,GAAG,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,CAAC,SAAS,QAAQ,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAazD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,OAAO,EAAE,EAAE,CAAC,EACpD,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,GAClC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAc5B"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
import { runWithRequestContext } from './context.js';
|
|
4
|
+
import { asYouTubeError, toToolError } from './errors.js';
|
|
5
|
+
/**
|
|
6
|
+
* Wrapping every handler the server registers, once, so that each call gets a
|
|
7
|
+
* request context and no call can throw out of the server.
|
|
8
|
+
*
|
|
9
|
+
* The MCP request's AbortSignal is published to the request context so an
|
|
10
|
+
* in-flight yt-dlp is killed when the client cancels, and anything thrown is
|
|
11
|
+
* rendered as an actionable message rather than a raw stack trace, a yt-dlp
|
|
12
|
+
* command line, or a local path. Tools report failures inside the result with
|
|
13
|
+
* `isError`; resources have no such envelope, so theirs become protocol errors
|
|
14
|
+
* carrying the same normalised text.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* The parts of the SDK's `RequestHandlerExtra` this server uses.
|
|
18
|
+
*
|
|
19
|
+
* `sendNotification` is described with `z.custom` because a function is not
|
|
20
|
+
* something Zod can take apart structurally — the predicate is a real runtime
|
|
21
|
+
* check, and it is what lets the property be called without asserting a type
|
|
22
|
+
* over it.
|
|
23
|
+
*/
|
|
24
|
+
const requestExtraSchema = z.object({
|
|
25
|
+
signal: z.instanceof(AbortSignal).optional(),
|
|
26
|
+
sendNotification: z
|
|
27
|
+
.custom((value) => typeof value === 'function')
|
|
28
|
+
.optional(),
|
|
29
|
+
_meta: z.object({ progressToken: z.union([z.string(), z.number()]).optional() }).optional(),
|
|
30
|
+
});
|
|
31
|
+
/** The request context for a call, read from the SDK extra that arrives last. */
|
|
32
|
+
function contextOf(args) {
|
|
33
|
+
// Handlers declare only their own parameters; the SDK appends
|
|
34
|
+
// RequestHandlerExtra to every call, so it is whatever arrived last.
|
|
35
|
+
const parsed = requestExtraSchema.safeParse(args[args.length - 1]);
|
|
36
|
+
const extra = parsed.success ? parsed.data : undefined;
|
|
37
|
+
return {
|
|
38
|
+
signal: extra?.signal,
|
|
39
|
+
// Progress is only meaningful when the client asked for it by sending a
|
|
40
|
+
// token; without one the notification would be dropped anyway.
|
|
41
|
+
reportProgress: extra?.sendNotification && extra._meta?.progressToken !== undefined
|
|
42
|
+
? (progress, total, message) => {
|
|
43
|
+
void extra.sendNotification?.({
|
|
44
|
+
method: 'notifications/progress',
|
|
45
|
+
params: {
|
|
46
|
+
progressToken: extra._meta?.progressToken,
|
|
47
|
+
progress,
|
|
48
|
+
...(total === undefined ? {} : { total }),
|
|
49
|
+
...(message === undefined ? {} : { message }),
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
: undefined,
|
|
54
|
+
log: extra?.sendNotification
|
|
55
|
+
? (level, message) => {
|
|
56
|
+
void extra.sendNotification?.({
|
|
57
|
+
method: 'notifications/message',
|
|
58
|
+
params: { level, logger: 'youtube-knowledge-mcp', data: message },
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
: undefined,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrap a tool handler, keeping its exact type.
|
|
66
|
+
*
|
|
67
|
+
* A Proxy rather than an arrow function because the SDK's `registerTool` is
|
|
68
|
+
* generic over the input schema and demands a callback of the precise type it
|
|
69
|
+
* derives from it; a new function would need a cast to claim that type, while
|
|
70
|
+
* a Proxy over the original *is* that type.
|
|
71
|
+
*/
|
|
72
|
+
export function guarded(handler) {
|
|
73
|
+
const run = (args) => runWithRequestContext(contextOf(args), async () => {
|
|
74
|
+
try {
|
|
75
|
+
return await handler(...args);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
return toToolError(error);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
return new Proxy(handler, {
|
|
82
|
+
apply: (_target, _thisArg, args) => run(args),
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The resource counterpart. A read that fails used to propagate whatever was
|
|
87
|
+
* thrown — an `ENOENT` carrying an absolute local path, for instance — as the
|
|
88
|
+
* JSON-RPC error message. It now carries the same `[CODE] message` a tool
|
|
89
|
+
* would show, and nothing else.
|
|
90
|
+
*/
|
|
91
|
+
export function guardedResource(handler) {
|
|
92
|
+
return async (...args) => runWithRequestContext(contextOf(args), async () => {
|
|
93
|
+
try {
|
|
94
|
+
return await handler(...args);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
const failure = asYouTubeError(error);
|
|
98
|
+
const code = failure.code === 'INVALID_INPUT' || failure.code === 'NOT_FOUND'
|
|
99
|
+
? ErrorCode.InvalidParams
|
|
100
|
+
: ErrorCode.InternalError;
|
|
101
|
+
throw new McpError(code, `[${failure.code}] ${failure.toToolMessage()}`);
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guard.js","sourceRoot":"","sources":["../../src/utils/guard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { Coverage } from '../harvest-schemas.js';
|
|
3
|
+
/**
|
|
4
|
+
* Reading a channel's whole catalogue.
|
|
5
|
+
*
|
|
6
|
+
* The listing plane is cheap and is not bot-checked: measured 1,716 videos in
|
|
7
|
+
* 31 seconds from one spawn, so a catalogue costs about a minute per channel
|
|
8
|
+
* and the old 100-video cap was self-imposed rather than forced.
|
|
9
|
+
*
|
|
10
|
+
* Every tab is walked because a channel's videos are not all under /videos —
|
|
11
|
+
* shorts, streams, releases and podcasts each have their own. The first tab
|
|
12
|
+
* that lists a video owns it; later tabs record themselves in `also_in_tabs`.
|
|
13
|
+
* Last-writer-wins would mislabel most of a music channel's catalogue.
|
|
14
|
+
*/
|
|
15
|
+
export declare const HARVEST_TABS: readonly ["videos", "shorts", "streams", "releases", "podcasts"];
|
|
16
|
+
export type HarvestTab = (typeof HARVEST_TABS)[number];
|
|
17
|
+
export declare const MAX_VIDEOS_PER_CATALOG = 10000;
|
|
18
|
+
export interface TabResult {
|
|
19
|
+
tab: HarvestTab;
|
|
20
|
+
listed: number;
|
|
21
|
+
added: number;
|
|
22
|
+
complete: boolean;
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface CatalogResult {
|
|
26
|
+
channelId: string;
|
|
27
|
+
name: string;
|
|
28
|
+
handle: string;
|
|
29
|
+
tabs: TabResult[];
|
|
30
|
+
videosSeen: number;
|
|
31
|
+
videosAdded: number;
|
|
32
|
+
coverage: Coverage;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Walks every tab of a channel into the store.
|
|
36
|
+
*
|
|
37
|
+
* A tab the channel simply does not have is not a failure — yt-dlp says so in
|
|
38
|
+
* words, and treating that as an error would make every channel without a
|
|
39
|
+
* podcasts tab look broken.
|
|
40
|
+
*/
|
|
41
|
+
export declare function harvestCatalog(database: DatabaseSync, channel: string, options?: {
|
|
42
|
+
maxVideos?: number;
|
|
43
|
+
}): Promise<CatalogResult>;
|
|
44
|
+
//# sourceMappingURL=harvest-catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest-catalog.d.ts","sourceRoot":"","sources":["../../src/utils/harvest-catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAahD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,YAAY,kEAAmE,CAAC;AAC7F,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAK7C,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,UAAU,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,SAAS,EAAE,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAyCD;;;;;;GAMG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GACnC,OAAO,CAAC,aAAa,CAAC,CAQxB"}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { runYtDlp, TIMEOUTS } from './ytdlp.js';
|
|
2
|
+
import { FLAT_PRINT_TEMPLATE, flatEntrySchema, toVideoListItem } from './flat-listing.js';
|
|
3
|
+
import { parseYtDlpJsonLines } from './ytdlp-parse.js';
|
|
4
|
+
import { resolveListTarget } from './youtube-url.js';
|
|
5
|
+
import { getChannelInfo } from './youtube-channel.js';
|
|
6
|
+
import { coverageOf } from './coverage.js';
|
|
7
|
+
import { saveReceipt } from './harvest-receipts.js';
|
|
8
|
+
import { inTransaction } from './store.js';
|
|
9
|
+
import { throwIfAborted, reportProgress } from './context.js';
|
|
10
|
+
import { countRows } from './store-rows.js';
|
|
11
|
+
import { withChannelHarvestLock } from './harvest-lock.js';
|
|
12
|
+
import { YouTubeError } from './errors.js';
|
|
13
|
+
/**
|
|
14
|
+
* Reading a channel's whole catalogue.
|
|
15
|
+
*
|
|
16
|
+
* The listing plane is cheap and is not bot-checked: measured 1,716 videos in
|
|
17
|
+
* 31 seconds from one spawn, so a catalogue costs about a minute per channel
|
|
18
|
+
* and the old 100-video cap was self-imposed rather than forced.
|
|
19
|
+
*
|
|
20
|
+
* Every tab is walked because a channel's videos are not all under /videos —
|
|
21
|
+
* shorts, streams, releases and podcasts each have their own. The first tab
|
|
22
|
+
* that lists a video owns it; later tabs record themselves in `also_in_tabs`.
|
|
23
|
+
* Last-writer-wins would mislabel most of a music channel's catalogue.
|
|
24
|
+
*/
|
|
25
|
+
export const HARVEST_TABS = ['videos', 'shorts', 'streams', 'releases', 'podcasts'];
|
|
26
|
+
export const MAX_VIDEOS_PER_CATALOG = 10_000;
|
|
27
|
+
/** yt-dlp says this, in these words, for a tab the channel does not have. */
|
|
28
|
+
const NO_SUCH_TAB = 'does not have a';
|
|
29
|
+
const UPSERT_VIDEO = `
|
|
30
|
+
INSERT INTO video (
|
|
31
|
+
video_id, channel_id, title, duration_s, upload_date, view_count,
|
|
32
|
+
live_status, thumbnail_url, tab, also_in_tabs, catalog_rank, listed_at
|
|
33
|
+
) VALUES (?,?,?,?,?,?,?,?,?,'[]',?,?)
|
|
34
|
+
ON CONFLICT(video_id) DO UPDATE SET
|
|
35
|
+
title = excluded.title,
|
|
36
|
+
duration_s = excluded.duration_s,
|
|
37
|
+
view_count = excluded.view_count,
|
|
38
|
+
live_status = excluded.live_status,
|
|
39
|
+
thumbnail_url = excluded.thumbnail_url,
|
|
40
|
+
listed_at = excluded.listed_at,
|
|
41
|
+
-- The owning tab is kept; a later tab only records that it also lists this
|
|
42
|
+
-- video, so a re-walk in a different order cannot relabel the catalogue.
|
|
43
|
+
also_in_tabs = CASE
|
|
44
|
+
WHEN video.tab = excluded.tab THEN video.also_in_tabs
|
|
45
|
+
WHEN instr(video.also_in_tabs, excluded.tab) > 0 THEN video.also_in_tabs
|
|
46
|
+
ELSE json_insert(video.also_in_tabs, '$[#]', excluded.tab)
|
|
47
|
+
END`;
|
|
48
|
+
async function listTab(channelUrl, tab, limit) {
|
|
49
|
+
return runYtDlp([
|
|
50
|
+
'--skip-download',
|
|
51
|
+
'--flat-playlist',
|
|
52
|
+
'--lazy-playlist',
|
|
53
|
+
'--print',
|
|
54
|
+
FLAT_PRINT_TEMPLATE,
|
|
55
|
+
'--playlist-end',
|
|
56
|
+
String(limit),
|
|
57
|
+
], {
|
|
58
|
+
label: `harvest_channel:${tab}`,
|
|
59
|
+
timeoutMs: TIMEOUTS.transcript,
|
|
60
|
+
target: resolveListTarget(`${channelUrl}/${tab}`),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Walks every tab of a channel into the store.
|
|
65
|
+
*
|
|
66
|
+
* A tab the channel simply does not have is not a failure — yt-dlp says so in
|
|
67
|
+
* words, and treating that as an error would make every channel without a
|
|
68
|
+
* podcasts tab look broken.
|
|
69
|
+
*/
|
|
70
|
+
export async function harvestCatalog(database, channel, options = {}) {
|
|
71
|
+
const maxVideos = Math.min(options.maxVideos ?? 500, MAX_VIDEOS_PER_CATALOG);
|
|
72
|
+
// Resolving the channel comes before the lock because the lock is keyed on
|
|
73
|
+
// the channel id, and only YouTube can turn a handle into one.
|
|
74
|
+
const info = await getChannelInfo(channel);
|
|
75
|
+
return withChannelHarvestLock(info.channelId, () => walkTabs(database, info, maxVideos));
|
|
76
|
+
}
|
|
77
|
+
async function walkTabs(database, info, maxVideos) {
|
|
78
|
+
const now = Date.now();
|
|
79
|
+
database
|
|
80
|
+
.prepare(`INSERT INTO channel (channel_id, handle, name, channel_url, subscriber_count, description, first_seen_at, updated_at)
|
|
81
|
+
VALUES (?,?,?,?,?,?,?,?)
|
|
82
|
+
ON CONFLICT(channel_id) DO UPDATE SET
|
|
83
|
+
handle = excluded.handle, name = excluded.name, channel_url = excluded.channel_url,
|
|
84
|
+
subscriber_count = excluded.subscriber_count, description = excluded.description,
|
|
85
|
+
updated_at = excluded.updated_at`)
|
|
86
|
+
.run(info.channelId, info.handle, info.name, info.channelUrl, info.subscriberCount, info.description, now, now);
|
|
87
|
+
const tabs = [];
|
|
88
|
+
const seen = new Set();
|
|
89
|
+
let rank = 0;
|
|
90
|
+
// Counted from the store, not from `seen`: on a second run every video is
|
|
91
|
+
// new to the walk and none is new to the catalogue, and reporting the former
|
|
92
|
+
// as "added" would make a re-run look like a fresh harvest.
|
|
93
|
+
const countVideos = () => countRows(database.prepare('SELECT COUNT(*) FROM video WHERE channel_id = ?'), info.channelId);
|
|
94
|
+
const before = countVideos();
|
|
95
|
+
for (const tab of HARVEST_TABS) {
|
|
96
|
+
throwIfAborted();
|
|
97
|
+
reportProgress(tabs.length, HARVEST_TABS.length, `harvest_channel: ${tab}`);
|
|
98
|
+
let stdout;
|
|
99
|
+
try {
|
|
100
|
+
stdout = await listTab(info.channelUrl, tab, maxVideos);
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const message = error instanceof YouTubeError ? error.message : String(error);
|
|
104
|
+
const absent = error instanceof YouTubeError && error.message.includes(NO_SUCH_TAB);
|
|
105
|
+
tabs.push({
|
|
106
|
+
tab,
|
|
107
|
+
listed: 0,
|
|
108
|
+
added: 0,
|
|
109
|
+
// A tab the channel does not have is a complete answer, not a gap.
|
|
110
|
+
complete: absent,
|
|
111
|
+
...(absent ? {} : { error: message }),
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
const entries = parseYtDlpJsonLines(stdout, flatEntrySchema).map(toVideoListItem);
|
|
116
|
+
const insert = database.prepare(UPSERT_VIDEO);
|
|
117
|
+
const tabBefore = countVideos();
|
|
118
|
+
inTransaction(database, () => {
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
if (seen.size >= maxVideos)
|
|
121
|
+
break;
|
|
122
|
+
seen.add(entry.id);
|
|
123
|
+
insert.run(entry.id, info.channelId, entry.title, entry.duration, entry.uploadDate === '' ? null : entry.uploadDate, entry.viewCount ?? null, entry.liveStatus ?? null, entry.thumbnailUrl ?? null, tab, rank, now);
|
|
124
|
+
rank += 1;
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
tabs.push({
|
|
128
|
+
tab,
|
|
129
|
+
listed: entries.length,
|
|
130
|
+
added: countVideos() - tabBefore,
|
|
131
|
+
complete: entries.length < maxVideos,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
const everyTabComplete = tabs.every((tab) => tab.complete);
|
|
135
|
+
const coverage = coverageOf({
|
|
136
|
+
scope: 'channel-catalog',
|
|
137
|
+
targetId: info.channelId,
|
|
138
|
+
have: seen.size,
|
|
139
|
+
source: `yt-dlp --flat-playlist over ${HARVEST_TABS.join(', ')}`,
|
|
140
|
+
// Only an unbroken walk of every tab proves the catalogue is whole. A tab
|
|
141
|
+
// that errored, or one that filled to the cap, leaves it unprovable.
|
|
142
|
+
...(everyTabComplete
|
|
143
|
+
? {
|
|
144
|
+
expected: { value: seen.size, source: 'source-exhausted' },
|
|
145
|
+
ranToExhaustion: true,
|
|
146
|
+
}
|
|
147
|
+
: {}),
|
|
148
|
+
...(seen.size >= maxVideos ? { limitApplied: maxVideos } : {}),
|
|
149
|
+
...(everyTabComplete ? {} : { resumeToken: `catalog:${info.channelId}` }),
|
|
150
|
+
});
|
|
151
|
+
inTransaction(database, () => {
|
|
152
|
+
saveReceipt(database, coverage, { startedAt: now });
|
|
153
|
+
});
|
|
154
|
+
return {
|
|
155
|
+
channelId: info.channelId,
|
|
156
|
+
name: info.name,
|
|
157
|
+
handle: info.handle,
|
|
158
|
+
tabs,
|
|
159
|
+
videosSeen: seen.size,
|
|
160
|
+
videosAdded: countVideos() - before,
|
|
161
|
+
coverage,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=harvest-catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest-catalog.js","sourceRoot":"","sources":["../../src/utils/harvest-catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harvest-lock.d.ts","sourceRoot":"","sources":["../../src/utils/harvest-lock.ts"],"names":[],"mappings":"AAsBA,wBAAsB,sBAAsB,CAAC,CAAC,EAC5C,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,CAAC,CAKZ;AAED,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAKjG"}
|