diff --git a/.gitignore b/.gitignore index 857051b..b1793e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ dump -howlong-stub +*-stub .yarn/* !.yarn/patches diff --git a/.pnp.js b/.pnp.js index b27a023..744d26c 100755 --- a/.pnp.js +++ b/.pnp.js @@ -43,10 +43,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["fast-xml-parser", "npm:3.18.0"], ["got", "npm:11.8.2"], ["howlongtobeat", "npm:1.3.1"], + ["imagemagick", "npm:0.1.3"], ["jest", "npm:26.6.3"], ["lunr", "npm:2.3.9"], ["mockdate", "npm:3.0.2"], - ["parser-front-matter", "npm:1.6.4"] + ["parser-front-matter", "npm:1.6.4"], + ["youtube-dl-exec", "npm:1.2.4"] ], "linkType": "SOFT", }] @@ -1016,6 +1018,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["@types/minimist", [ + ["npm:1.2.1", { + "packageLocation": "./.yarn/cache/@types-minimist-npm-1.2.1-dc316d808d-3a6f5fe35f.zip/node_modules/@types/minimist/", + "packageDependencies": [ + ["@types/minimist", "npm:1.2.1"] + ], + "linkType": "HARD", + }] + ]], ["@types/node", [ ["npm:14.14.31", { "packageLocation": "./.yarn/cache/@types-node-npm-14.14.31-4f1a9dff64-635dc8a089.zip/node_modules/@types/node/", @@ -1278,6 +1289,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["arrify", [ + ["npm:1.0.1", { + "packageLocation": "./.yarn/cache/arrify-npm-1.0.1-affafba9fe-f1d3bae819.zip/node_modules/arrify/", + "packageDependencies": [ + ["arrify", "npm:1.0.1"] + ], + "linkType": "HARD", + }], + ["npm:3.0.0", { + "packageLocation": "./.yarn/cache/arrify-npm-3.0.0-84cf7a301c-2df1968102.zip/node_modules/arrify/", + "packageDependencies": [ + ["arrify", "npm:3.0.0"] + ], + "linkType": "HARD", + }] + ]], ["asn1", [ ["npm:0.2.4", { "packageLocation": "./.yarn/cache/asn1-npm-0.2.4-219dd49411-5743ace942.zip/node_modules/asn1/", @@ -1499,6 +1526,41 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["bin-version", [ + ["npm:6.0.0", { + "packageLocation": "./.yarn/cache/bin-version-npm-6.0.0-21aa4ae30a-2ac9d4c1bd.zip/node_modules/bin-version/", + "packageDependencies": [ + ["bin-version", "npm:6.0.0"], + ["execa", "npm:5.1.1"], + ["find-versions", "npm:5.0.0"] + ], + "linkType": "HARD", + }] + ]], + ["bin-version-check", [ + ["npm:5.0.0", { + "packageLocation": "./.yarn/cache/bin-version-check-npm-5.0.0-3c24fb1216-751f11b2c2.zip/node_modules/bin-version-check/", + "packageDependencies": [ + ["bin-version-check", "npm:5.0.0"], + ["bin-version", "npm:6.0.0"], + ["semver", "npm:7.3.5"], + ["semver-truncate", "npm:2.0.0"] + ], + "linkType": "HARD", + }] + ]], + ["bin-version-check-cli", [ + ["npm:3.0.0", { + "packageLocation": "./.yarn/cache/bin-version-check-cli-npm-3.0.0-c889a0774a-77809c6001.zip/node_modules/bin-version-check-cli/", + "packageDependencies": [ + ["bin-version-check-cli", "npm:3.0.0"], + ["arrify", "npm:3.0.0"], + ["bin-version-check", "npm:5.0.0"], + ["meow", "npm:9.0.0"] + ], + "linkType": "HARD", + }] + ]], ["boolbase", [ ["npm:1.0.0", { "packageLocation": "./.yarn/cache/boolbase-npm-1.0.0-965fe9af6d-e827963c41.zip/node_modules/boolbase/", @@ -1656,6 +1718,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["camelcase-keys", [ + ["npm:6.2.2", { + "packageLocation": "./.yarn/cache/camelcase-keys-npm-6.2.2-d13777ec12-d4bd5fa524.zip/node_modules/camelcase-keys/", + "packageDependencies": [ + ["camelcase-keys", "npm:6.2.2"], + ["camelcase", "npm:5.3.1"], + ["map-obj", "npm:4.2.1"], + ["quick-lru", "npm:4.0.1"] + ], + "linkType": "HARD", + }] + ]], ["caniuse-lite", [ ["npm:1.0.30001196", { "packageLocation": "./.yarn/cache/caniuse-lite-npm-1.0.30001196-4ed833c388-42c3841806.zip/node_modules/caniuse-lite/", @@ -2025,6 +2099,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["dargs", [ + ["npm:7.0.0", { + "packageLocation": "./.yarn/cache/dargs-npm-7.0.0-62701e0c7a-ca99396d24.zip/node_modules/dargs/", + "packageDependencies": [ + ["dargs", "npm:7.0.0"] + ], + "linkType": "HARD", + }] + ]], ["dashdash", [ ["npm:1.14.1", { "packageLocation": "./.yarn/cache/dashdash-npm-1.14.1-be8f10a286-5959409ee4.zip/node_modules/dashdash/", @@ -2105,6 +2188,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["decamelize-keys", [ + ["npm:1.1.0", { + "packageLocation": "./.yarn/cache/decamelize-keys-npm-1.1.0-75168ffadd-dbfe6d5948.zip/node_modules/decamelize-keys/", + "packageDependencies": [ + ["decamelize-keys", "npm:1.1.0"], + ["decamelize", "npm:1.2.0"], + ["map-obj", "npm:1.0.1"] + ], + "linkType": "HARD", + }] + ]], ["decimal.js", [ ["npm:10.2.1", { "packageLocation": "./.yarn/cache/decimal.js-npm-10.2.1-6eff4c0574-ba28b27bb8.zip/node_modules/decimal.js/", @@ -2513,6 +2607,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["strip-final-newline", "npm:2.0.0"] ], "linkType": "HARD", + }], + ["npm:5.1.1", { + "packageLocation": "./.yarn/cache/execa-npm-5.1.1-191347acf5-4286ade8cd.zip/node_modules/execa/", + "packageDependencies": [ + ["execa", "npm:5.1.1"], + ["cross-spawn", "npm:7.0.3"], + ["get-stream", "npm:6.0.1"], + ["human-signals", "npm:2.1.0"], + ["is-stream", "npm:2.0.0"], + ["merge-stream", "npm:2.0.0"], + ["npm-run-path", "npm:4.0.1"], + ["onetime", "npm:5.1.2"], + ["signal-exit", "npm:3.0.3"], + ["strip-final-newline", "npm:2.0.0"] + ], + "linkType": "HARD", }] ]], ["exit", [ @@ -2715,6 +2825,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["find-versions", [ + ["npm:5.0.0", { + "packageLocation": "./.yarn/cache/find-versions-npm-5.0.0-af7d21fa2f-ec5ed95f3d.zip/node_modules/find-versions/", + "packageDependencies": [ + ["find-versions", "npm:5.0.0"], + ["semver-regex", "npm:4.0.0"] + ], + "linkType": "HARD", + }] + ]], ["for-in", [ ["npm:1.0.2", { "packageLocation": "./.yarn/cache/for-in-npm-1.0.2-37e3d7aae5-e8d7280a65.zip/node_modules/for-in/", @@ -2853,6 +2973,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["pump", "npm:3.0.0"] ], "linkType": "HARD", + }], + ["npm:6.0.1", { + "packageLocation": "./.yarn/cache/get-stream-npm-6.0.1-83e51a4642-83de1fde5b.zip/node_modules/get-stream/", + "packageDependencies": [ + ["get-stream", "npm:6.0.1"] + ], + "linkType": "HARD", }] ]], ["get-value", [ @@ -2969,6 +3096,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["hard-rejection", [ + ["npm:2.1.0", { + "packageLocation": "./.yarn/cache/hard-rejection-npm-2.1.0-a80f2a977d-27bc09d185.zip/node_modules/hard-rejection/", + "packageDependencies": [ + ["hard-rejection", "npm:2.1.0"] + ], + "linkType": "HARD", + }] + ]], ["has", [ ["npm:1.0.3", { "packageLocation": "./.yarn/cache/has-npm-1.0.3-b7f00631c1-c686e15300.zip/node_modules/has/", @@ -3051,6 +3187,14 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["hosted-git-info", "npm:2.8.8"] ], "linkType": "HARD", + }], + ["npm:4.0.2", { + "packageLocation": "./.yarn/cache/hosted-git-info-npm-4.0.2-7330924e0c-838315face.zip/node_modules/hosted-git-info/", + "packageDependencies": [ + ["hosted-git-info", "npm:4.0.2"], + ["lru-cache", "npm:6.0.0"] + ], + "linkType": "HARD", }] ]], ["howlongtobeat", [ @@ -3137,6 +3281,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["human-signals", "npm:1.1.1"] ], "linkType": "HARD", + }], + ["npm:2.1.0", { + "packageLocation": "./.yarn/cache/human-signals-npm-2.1.0-f75815481d-70bfd94d27.zip/node_modules/human-signals/", + "packageDependencies": [ + ["human-signals", "npm:2.1.0"] + ], + "linkType": "HARD", }] ]], ["iconv-lite", [ @@ -3149,6 +3300,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["imagemagick", [ + ["npm:0.1.3", { + "packageLocation": "./.yarn/cache/imagemagick-npm-0.1.3-b7d16160cd-49a6479ae0.zip/node_modules/imagemagick/", + "packageDependencies": [ + ["imagemagick", "npm:0.1.3"] + ], + "linkType": "HARD", + }] + ]], ["import-local", [ ["npm:3.0.2", { "packageLocation": "./.yarn/cache/import-local-npm-3.0.2-c8afc1fd5f-9ba5f1697b.zip/node_modules/import-local/", @@ -3169,6 +3329,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["indent-string", [ + ["npm:4.0.0", { + "packageLocation": "./.yarn/cache/indent-string-npm-4.0.0-7b717435b2-3e54996c6e.zip/node_modules/indent-string/", + "packageDependencies": [ + ["indent-string", "npm:4.0.0"] + ], + "linkType": "HARD", + }] + ]], ["inflight", [ ["npm:1.0.6", { "packageLocation": "./.yarn/cache/inflight-npm-1.0.6-ccedb4b908-17c53fc42c.zip/node_modules/inflight/", @@ -3380,6 +3549,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["is-plain-obj", [ + ["npm:1.1.0", { + "packageLocation": "./.yarn/cache/is-plain-obj-npm-1.1.0-1046f64c0b-d2eb5a32ea.zip/node_modules/is-plain-obj/", + "packageDependencies": [ + ["is-plain-obj", "npm:1.1.0"] + ], + "linkType": "HARD", + }] + ]], ["is-plain-object", [ ["npm:2.0.4", { "packageLocation": "./.yarn/cache/is-plain-object-npm-2.0.4-da3265d804-2f32322673.zip/node_modules/is-plain-object/", @@ -3424,6 +3602,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["is-unix", [ + ["npm:1.0.0", { + "packageLocation": "./.yarn/cache/is-unix-npm-1.0.0-87997095f2-861bfee497.zip/node_modules/is-unix/", + "packageDependencies": [ + ["is-unix", "npm:1.0.0"] + ], + "linkType": "HARD", + }] + ]], ["is-whitespace", [ ["npm:0.3.0", { "packageLocation": "./.yarn/cache/is-whitespace-npm-0.3.0-994f2b3b8c-defe0fe748.zip/node_modules/is-whitespace/", @@ -3577,10 +3764,12 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["fast-xml-parser", "npm:3.18.0"], ["got", "npm:11.8.2"], ["howlongtobeat", "npm:1.3.1"], + ["imagemagick", "npm:0.1.3"], ["jest", "npm:26.6.3"], ["lunr", "npm:2.3.9"], ["mockdate", "npm:3.0.2"], - ["parser-front-matter", "npm:1.6.4"] + ["parser-front-matter", "npm:1.6.4"], + ["youtube-dl-exec", "npm:1.2.4"] ], "linkType": "SOFT", }] @@ -4408,6 +4597,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["map-obj", [ + ["npm:1.0.1", { + "packageLocation": "./.yarn/cache/map-obj-npm-1.0.1-fa55100fac-e68b20e4fa.zip/node_modules/map-obj/", + "packageDependencies": [ + ["map-obj", "npm:1.0.1"] + ], + "linkType": "HARD", + }], + ["npm:4.2.1", { + "packageLocation": "./.yarn/cache/map-obj-npm-4.2.1-754eda8456-59c2f09ffc.zip/node_modules/map-obj/", + "packageDependencies": [ + ["map-obj", "npm:4.2.1"] + ], + "linkType": "HARD", + }] + ]], ["map-visit", [ ["npm:1.0.0", { "packageLocation": "./.yarn/cache/map-visit-npm-1.0.0-33a7988a9d-9e85e6d802.zip/node_modules/map-visit/", @@ -4418,6 +4623,27 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["meow", [ + ["npm:9.0.0", { + "packageLocation": "./.yarn/cache/meow-npm-9.0.0-8b2707248e-d1573809d6.zip/node_modules/meow/", + "packageDependencies": [ + ["meow", "npm:9.0.0"], + ["@types/minimist", "npm:1.2.1"], + ["camelcase-keys", "npm:6.2.2"], + ["decamelize", "npm:1.2.0"], + ["decamelize-keys", "npm:1.1.0"], + ["hard-rejection", "npm:2.1.0"], + ["minimist-options", "npm:4.1.0"], + ["normalize-package-data", "npm:3.0.2"], + ["read-pkg-up", "npm:7.0.1"], + ["redent", "npm:3.0.0"], + ["trim-newlines", "npm:3.0.1"], + ["type-fest", "npm:0.18.1"], + ["yargs-parser", "npm:20.2.7"] + ], + "linkType": "HARD", + }] + ]], ["merge-stream", [ ["npm:2.0.0", { "packageLocation": "./.yarn/cache/merge-stream-npm-2.0.0-2ac83efea5-cde834809a.zip/node_modules/merge-stream/", @@ -4502,6 +4728,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["min-indent", [ + ["npm:1.0.1", { + "packageLocation": "./.yarn/cache/min-indent-npm-1.0.1-77031f50e1-c3aeea46bc.zip/node_modules/min-indent/", + "packageDependencies": [ + ["min-indent", "npm:1.0.1"] + ], + "linkType": "HARD", + }] + ]], ["minimatch", [ ["npm:3.0.4", { "packageLocation": "./.yarn/cache/minimatch-npm-3.0.4-6e76f51c23-47eab92639.zip/node_modules/minimatch/", @@ -4521,6 +4756,18 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["minimist-options", [ + ["npm:4.1.0", { + "packageLocation": "./.yarn/cache/minimist-options-npm-4.1.0-64ca250fc1-51f1aba56f.zip/node_modules/minimist-options/", + "packageDependencies": [ + ["minimist-options", "npm:4.1.0"], + ["arrify", "npm:1.0.1"], + ["is-plain-obj", "npm:1.1.0"], + ["kind-of", "npm:6.0.3"] + ], + "linkType": "HARD", + }] + ]], ["minipass", [ ["npm:3.1.3", { "packageLocation": "./.yarn/cache/minipass-npm-3.1.3-af723e33f3-d12b95a845.zip/node_modules/minipass/", @@ -4707,6 +4954,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["validate-npm-package-license", "npm:3.0.4"] ], "linkType": "HARD", + }], + ["npm:3.0.2", { + "packageLocation": "./.yarn/cache/normalize-package-data-npm-3.0.2-4ca0cf04d6-a1053ccfe0.zip/node_modules/normalize-package-data/", + "packageDependencies": [ + ["normalize-package-data", "npm:3.0.2"], + ["hosted-git-info", "npm:4.0.2"], + ["resolve", "patch:resolve@npm%3A1.20.0#builtin::version=1.20.0&hash=3388aa"], + ["semver", "npm:7.3.5"], + ["validate-npm-package-license", "npm:3.0.4"] + ], + "linkType": "HARD", }] ]], ["normalize-path", [ @@ -4897,6 +5155,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["p-event", [ + ["npm:4.2.0", { + "packageLocation": "./.yarn/cache/p-event-npm-4.2.0-1d17e9941e-2f57be6597.zip/node_modules/p-event/", + "packageDependencies": [ + ["p-event", "npm:4.2.0"], + ["p-timeout", "npm:3.2.0"] + ], + "linkType": "HARD", + }] + ]], ["p-finally", [ ["npm:1.0.0", { "packageLocation": "./.yarn/cache/p-finally-npm-1.0.0-35fbaa57c6-01f49b2d9c.zip/node_modules/p-finally/", @@ -4926,6 +5194,25 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["p-reflect", [ + ["npm:2.1.0", { + "packageLocation": "./.yarn/cache/p-reflect-npm-2.1.0-3e8a379d2e-997f198dae.zip/node_modules/p-reflect/", + "packageDependencies": [ + ["p-reflect", "npm:2.1.0"] + ], + "linkType": "HARD", + }] + ]], + ["p-timeout", [ + ["npm:3.2.0", { + "packageLocation": "./.yarn/cache/p-timeout-npm-3.2.0-7fdb33f733-d7e71c1547.zip/node_modules/p-timeout/", + "packageDependencies": [ + ["p-timeout", "npm:3.2.0"], + ["p-finally", "npm:1.0.0"] + ], + "linkType": "HARD", + }] + ]], ["p-try", [ ["npm:2.2.0", { "packageLocation": "./.yarn/cache/p-try-npm-2.2.0-e0390dbaf8-20983f3765.zip/node_modules/p-try/", @@ -5170,6 +5457,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["quick-lru", [ + ["npm:4.0.1", { + "packageLocation": "./.yarn/cache/quick-lru-npm-4.0.1-ef8aa17c9c-91847e4b07.zip/node_modules/quick-lru/", + "packageDependencies": [ + ["quick-lru", "npm:4.0.1"] + ], + "linkType": "HARD", + }], ["npm:5.1.1", { "packageLocation": "./.yarn/cache/quick-lru-npm-5.1.1-e38e0edce3-fafb2b2fa1.zip/node_modules/quick-lru/", "packageDependencies": [ @@ -5228,6 +5522,17 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["redent", [ + ["npm:3.0.0", { + "packageLocation": "./.yarn/cache/redent-npm-3.0.0-31892f4906-78c8aa0a10.zip/node_modules/redent/", + "packageDependencies": [ + ["redent", "npm:3.0.0"], + ["indent-string", "npm:4.0.0"], + ["strip-indent", "npm:3.0.0"] + ], + "linkType": "HARD", + }] + ]], ["regex-not", [ ["npm:1.0.2", { "packageLocation": "./.yarn/cache/regex-not-npm-1.0.2-06a03c9206-3d6d95b4fd.zip/node_modules/regex-not/", @@ -5532,6 +5837,33 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["lru-cache", "npm:6.0.0"] ], "linkType": "HARD", + }], + ["npm:7.3.5", { + "packageLocation": "./.yarn/cache/semver-npm-7.3.5-618cf5db6a-c53624ddf4.zip/node_modules/semver/", + "packageDependencies": [ + ["semver", "npm:7.3.5"], + ["lru-cache", "npm:6.0.0"] + ], + "linkType": "HARD", + }] + ]], + ["semver-regex", [ + ["npm:4.0.0", { + "packageLocation": "./.yarn/cache/semver-regex-npm-4.0.0-9bc5f556bb-7d5aad3100.zip/node_modules/semver-regex/", + "packageDependencies": [ + ["semver-regex", "npm:4.0.0"] + ], + "linkType": "HARD", + }] + ]], + ["semver-truncate", [ + ["npm:2.0.0", { + "packageLocation": "./.yarn/cache/semver-truncate-npm-2.0.0-72072c2328-ce009febda.zip/node_modules/semver-truncate/", + "packageDependencies": [ + ["semver-truncate", "npm:2.0.0"], + ["semver", "npm:6.3.0"] + ], + "linkType": "HARD", }] ]], ["set-blocking", [ @@ -5953,6 +6285,16 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["strip-indent", [ + ["npm:3.0.0", { + "packageLocation": "./.yarn/cache/strip-indent-npm-3.0.0-519e75a28d-4a7860e943.zip/node_modules/strip-indent/", + "packageDependencies": [ + ["strip-indent", "npm:3.0.0"], + ["min-indent", "npm:1.0.1"] + ], + "linkType": "HARD", + }] + ]], ["supports-color", [ ["npm:5.5.0", { "packageLocation": "./.yarn/cache/supports-color-npm-5.5.0-183ac537bc-edacee6425.zip/node_modules/supports-color/", @@ -6139,6 +6481,15 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "linkType": "HARD", }] ]], + ["trim-newlines", [ + ["npm:3.0.1", { + "packageLocation": "./.yarn/cache/trim-newlines-npm-3.0.1-22f1f216de-a1cc3d5992.zip/node_modules/trim-newlines/", + "packageDependencies": [ + ["trim-newlines", "npm:3.0.1"] + ], + "linkType": "HARD", + }] + ]], ["tunnel-agent", [ ["npm:0.6.0", { "packageLocation": "./.yarn/cache/tunnel-agent-npm-0.6.0-64345ab7eb-03db75a4f9.zip/node_modules/tunnel-agent/", @@ -6185,6 +6536,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "HARD", }], + ["npm:0.18.1", { + "packageLocation": "./.yarn/cache/type-fest-npm-0.18.1-47b079775d-0d6d338e72.zip/node_modules/type-fest/", + "packageDependencies": [ + ["type-fest", "npm:0.18.1"] + ], + "linkType": "HARD", + }], ["npm:0.6.0", { "packageLocation": "./.yarn/cache/type-fest-npm-0.6.0-76b229965b-c77f687caf.zip/node_modules/type-fest/", "packageDependencies": [ @@ -6600,6 +6958,31 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["decamelize", "npm:1.2.0"] ], "linkType": "HARD", + }], + ["npm:20.2.7", { + "packageLocation": "./.yarn/cache/yargs-parser-npm-20.2.7-5ab0b83136-124e7f1c24.zip/node_modules/yargs-parser/", + "packageDependencies": [ + ["yargs-parser", "npm:20.2.7"] + ], + "linkType": "HARD", + }] + ]], + ["youtube-dl-exec", [ + ["npm:1.2.4", { + "packageLocation": "./.yarn/unplugged/youtube-dl-exec-npm-1.2.4-9b07f4a151/node_modules/youtube-dl-exec/", + "packageDependencies": [ + ["youtube-dl-exec", "npm:1.2.4"], + ["bin-version-check-cli", "npm:3.0.0"], + ["dargs", "npm:7.0.0"], + ["execa", "npm:5.1.1"], + ["get-stream", "npm:6.0.1"], + ["got", "npm:11.8.2"], + ["is-unix", "npm:1.0.0"], + ["mkdirp", "npm:1.0.4"], + ["p-event", "npm:4.2.0"], + ["p-reflect", "npm:2.1.0"] + ], + "linkType": "HARD", }] ]] ] diff --git a/README.md b/README.md index 5fa251a..5907c12 100644 --- a/README.md +++ b/README.md @@ -168,3 +168,18 @@ Calls the set webmention endpoint using a `PUT`. Based on the RSS feed located a Parameters: just one, the `domain`. +### 6. YouTube + +Thanks to ideas from [rubenerd.com](https://rubenerd.com) and his [video.sh script](https://gitlab.com/rubenerd/rubenerd.com/-/blob/trunk/scripts/video.sh). This downloads a thumbnail using `youtube-dl`, smacks a play button on it using `convert`, and stores that in the specified folder. Use in conjunction with a Hugo shortcode to get rid of YouTube's iframes! + +Usage example: + +```js + await download({ + postDir: 'somewhere/posts', + downloadDir: 'static/youtube-thumbs', + overlayImg: 'playbtn.png' + }) +``` +It scans all `.md` files in the posts dir for `{{< youtube xxx >}}` shortcodes. + diff --git a/package.json b/package.json index 6023d8a..7c81743 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jam-my-stack", - "version": "1.0.17", + "version": "1.0.18", "repository": { "url": "https://github.com/wgroeneveld/jam-my-stack", "type": "git" @@ -18,8 +18,10 @@ "fast-xml-parser": "^3.18.0", "got": "^11.8.2", "howlongtobeat": "^1.3.1", + "imagemagick": "^0.1.3", "lunr": "^2.3.9", - "parser-front-matter": "^1.6.4" + "parser-front-matter": "^1.6.4", + "youtube-dl-exec": "^1.2.4" }, "devDependencies": { "jest": "^26.6.3", diff --git a/src/youtube/thumbify.js b/src/youtube/thumbify.js new file mode 100644 index 0000000..2e8a165 --- /dev/null +++ b/src/youtube/thumbify.js @@ -0,0 +1,91 @@ +const youtubedl = require('youtube-dl-exec'); +const got = require("got"); +const { createWriteStream, existsSync, unlinkSync } = require("fs"); +const fs = require('fs').promises; +const { getFiles } = require('./../file-utils'); +var im = require("imagemagick"); + +async function downloadThumbnail(youtubeid, downloadDir, overlayImg) { + const dlLoc = `${downloadDir}/${youtubeid}.jpg` + if(existsSync(dlLoc)) { + console.log(` -- SKIPPING ${youtubeid}: already downloaded.`) + return + } + + console.log(` -- downloading YouTube ${youtubeid} thumb...`) + const fStream = createWriteStream(dlLoc) + + const done = new Promise(function(resolve, reject) { + fStream.on('finish', () => { + var args = [ + "-resize", + "700x400", + dlLoc, + "+repage", + "+page", + overlayImg, + "-flatten", + dlLoc + ] + //console.log(`convert ${args}`) + im.convert(args, function(err) { + if(err) reject(err) + resolve() + }) + }) + fStream.on('error', () => { + unlinkSync(dlLoc) + reject() + }) + + youtubedl(`https://www.youtube.com/watch?v=${youtubeid}`, { + getThumb: true, + noWarnings: true + }) + .then(url => { + got.stream(url).pipe(fStream) + }) + .catch(err => { + unlinkSync(dlLoc) + reject(err) + }) + }) + + return done +} + +async function loadPostsWithVideos(postsDirectoryPath) { + const postNames = await getFiles(postsDirectoryPath); + const posts = await Promise.all( + postNames.filter(name => name.endsWith('.md')).map(async fileName => { + const fileContent = await fs.readFile(fileName, 'utf8'); + return { + file: fileName, + content: fileContent + } + }) + ); + return posts +} + +async function run(options) { + const { postDir, downloadDir, overlayImg } = options + console.log(`-- Scanning for YouTube embeds in ${postDir}... --`) + + const posts = await loadPostsWithVideos(postDir) + for(let post of posts) { + const matches = post.content.matchAll(/\{\{\<\syoutube\s\"?(.+)\"?\s\>\}\}/gi) + for(let youtubeid of matches) { + try { + await downloadThumbnail(youtubeid[1].replace(/\"/g, ""), downloadDir, overlayImg) + } catch(e) { + console.log(`-- error while processing: ${e}`) + } + } + } + console.log("-- DONE scanning for YouTube embeds --") +} + +module.exports = { + download: run +} diff --git a/test/mastodon/mastodon-e2e.test.js b/test/mastodon/mastodon-e2e.test.js index 3c8559c..58d6886 100644 --- a/test/mastodon/mastodon-e2e.test.js +++ b/test/mastodon/mastodon-e2e.test.js @@ -25,11 +25,11 @@ describe("mastodon feed parser end to end scenario test", () => { }) const dirroot = await fsp.readdir(`${dumpdir}`, { withFileTypes: true }) - expect(dirroot.length).toBe(1) + expect(dirroot.length).not.toBe(0) const year = dirroot[0].name const dirmonth = await fsp.readdir(`${dumpdir}/${year}`, { withFileTypes: true }) - expect(dirmonth.length).toBe(1) + expect(dirmonth.length).not.toBe(0) const month = dirmonth[0].name const dir = await fsp.readdir(`${dumpdir}/${year}/${month}`, { withFileTypes: true }) diff --git a/test/youtube/play.png b/test/youtube/play.png new file mode 100644 index 0000000..1879fc3 Binary files /dev/null and b/test/youtube/play.png differ diff --git a/test/youtube/thumbify.test.js b/test/youtube/thumbify.test.js new file mode 100644 index 0000000..c8bbe32 --- /dev/null +++ b/test/youtube/thumbify.test.js @@ -0,0 +1,111 @@ +const { download } = require('../../src/youtube/thumbify.js') +const fs = require('fs'); +const fsp = require('fs').promises; +const { rmdir } = require('./../utils') +const { getFiles } = require('../../src/file-utils'); + +const dumpdir = `${__dirname}/youtubeposts-stub` + +jest.disableAutomock() +jest.unmock('got') + +beforeEach(async () => { + if(fs.existsSync(dumpdir)) { + rmdir(dumpdir) + } + fs.mkdirSync(dumpdir) +}) + +test('Posts without YouTube links downloads nothing', async () => { + const md = `--- +title: "wizardry 8 review" +--- + +here's a post + +it doesn't contain a link, sorry... +` + + await fsp.writeFile(`${dumpdir}/post.md`, md, 'utf-8') + await download({ + postDir: dumpdir, + downloadDir: dumpdir, + overlayImg: `${__dirname}/play.png` + }) + const output = await getFiles(dumpdir) + expect(output.length).toBe(1) +}) + +test('Posts of which one youtube ID is invalid does carry on downloading the next', async () => { + const md = `--- +title: "wizardry 8 review" +--- + +here's a post + +{{< youtube lol >}} + +tsjek it out nog ene + +{{< youtube OjKWKxYrUWs >}} + +cool vid eh? +` + + await fsp.writeFile(`${dumpdir}/post.md`, md, 'utf-8') + await download({ + postDir: dumpdir, + downloadDir: dumpdir, + overlayImg: `${__dirname}/play.png` + }) + const output = await getFiles(dumpdir) + expect(output.length).toBe(2) +}) + +test('Posts with multiple YouTube links download all thumbs', async () => { + const md = `--- +title: "wizardry 8 review" +--- + +here's a post + +{{< youtube 7L-rDDGpYs0 >}} + +tsjek it out nog ene + +{{< youtube OjKWKxYrUWs >}} + +cool vid eh? +` + + await fsp.writeFile(`${dumpdir}/post.md`, md, 'utf-8') + await download({ + postDir: dumpdir, + downloadDir: dumpdir, + overlayImg: `${__dirname}/play.png` + }) + const output = await getFiles(dumpdir) + expect(output.length).toBe(3) +}) + +test('Posts with YouTube link in quotes downloads thumbs', async () => { + const md = `--- +title: "wizardry 8 review" +--- + +here's a post + +{{< youtube "7L-rDDGpYs0" >}} + +cool vid eh? +` + + await fsp.writeFile(`${dumpdir}/post.md`, md, 'utf-8') + await download({ + postDir: dumpdir, + downloadDir: dumpdir, + overlayImg: `${__dirname}/play.png` + }) + const output = await getFiles(dumpdir) + expect(output.length).toBe(2) +}) \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index c91cb73..40dc72b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -758,6 +758,13 @@ __metadata: languageName: node linkType: hard +"@types/minimist@npm:^1.2.0": + version: 1.2.1 + resolution: "@types/minimist@npm:1.2.1" + checksum: 3a6f5fe35f1656b34a4ccd5a5db1c38509d8d5b59625865b8c2b997994fcb0cfde0d9af7c5507b95dc5a0a32a22886c189e505cd2e52a7ef36d3c9982f07ed5a + languageName: node + linkType: hard + "@types/node@npm:*": version: 14.14.31 resolution: "@types/node@npm:14.14.31" @@ -985,6 +992,20 @@ __metadata: languageName: node linkType: hard +"arrify@npm:^1.0.1": + version: 1.0.1 + resolution: "arrify@npm:1.0.1" + checksum: f1d3bae819f49f51a09da5f5c5ce282e79ca69bbdb32db1d9f6c62b151ef801b74398d007cfe89686e2c5aeb62576a398b9068e5172b7f4e20157aa3284076d3 + languageName: node + linkType: hard + +"arrify@npm:^3.0.0": + version: 3.0.0 + resolution: "arrify@npm:3.0.0" + checksum: 2df19681029ba3014cbdba5edc47511002cf8065ff07b154901f4b5f4a7971b4795c4a6917b151efa4c42b8ea88c138eeb9e1193879ed03273edd35fdf052993 + languageName: node + linkType: hard + "asn1@npm:~0.2.3": version: 0.2.4 resolution: "asn1@npm:0.2.4" @@ -1153,6 +1174,40 @@ __metadata: languageName: node linkType: hard +"bin-version-check-cli@npm:~3.0.0": + version: 3.0.0 + resolution: "bin-version-check-cli@npm:3.0.0" + dependencies: + arrify: ^3.0.0 + bin-version-check: ^5.0.0 + meow: ^9.0.0 + bin: + bin-version-check: cli.js + checksum: 77809c6001fd8b2f732ad53299e3eaf4abf9433829695933126d14e225c14aaed3b7063c17c6af4288673f958227cd1c1f4b76c6582f0ef3b5621da313bbfa17 + languageName: node + linkType: hard + +"bin-version-check@npm:^5.0.0": + version: 5.0.0 + resolution: "bin-version-check@npm:5.0.0" + dependencies: + bin-version: ^6.0.0 + semver: ^7.3.5 + semver-truncate: ^2.0.0 + checksum: 751f11b2c2a62555f2fc35cd16c30c401074003cedfc4dfb8accba85d155292d1581b084450469e1e2a40c20cc8256ee688995e6161ec56f782551972ef18dee + languageName: node + linkType: hard + +"bin-version@npm:^6.0.0": + version: 6.0.0 + resolution: "bin-version@npm:6.0.0" + dependencies: + execa: ^5.0.0 + find-versions: ^5.0.0 + checksum: 2ac9d4c1bdb80967caba860b3de2afa788bc1b1966ed95860ed60ad594ff89068900cf7b8ecd5beecd6eb31b5c631013376962c510071baef890b1708170aead + languageName: node + linkType: hard + "boolbase@npm:^1.0.0": version: 1.0.0 resolution: "boolbase@npm:1.0.0" @@ -1281,6 +1336,17 @@ __metadata: languageName: node linkType: hard +"camelcase-keys@npm:^6.2.2": + version: 6.2.2 + resolution: "camelcase-keys@npm:6.2.2" + dependencies: + camelcase: ^5.3.1 + map-obj: ^4.0.0 + quick-lru: ^4.0.1 + checksum: d4bd5fa5249127be0f5b1aa961da3a9de7d0a578d9524c5013f21c0ed345637eaa1e42bab28a75bbfc8511911ffb30fec4191a9efcec52741c1a3402dc38dd53 + languageName: node + linkType: hard + "camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" @@ -1563,7 +1629,7 @@ __metadata: languageName: node linkType: hard -"cross-spawn@npm:^7.0.0": +"cross-spawn@npm:^7.0.0, cross-spawn@npm:^7.0.3": version: 7.0.3 resolution: "cross-spawn@npm:7.0.3" dependencies: @@ -1617,6 +1683,13 @@ __metadata: languageName: node linkType: hard +"dargs@npm:~7.0.0": + version: 7.0.0 + resolution: "dargs@npm:7.0.0" + checksum: ca99396d247c46a90e53b67b95ffd005588c15a1162ca6a7bf4fa6213b51d341f4e82b70a4d0e8086e6e13e1c757b966524d237bbd0454efcffafcc1008d5a59 + languageName: node + linkType: hard + "dashdash@npm:^1.12.0": version: 1.14.1 resolution: "dashdash@npm:1.14.1" @@ -1665,7 +1738,17 @@ __metadata: languageName: node linkType: hard -"decamelize@npm:^1.2.0": +"decamelize-keys@npm:^1.1.0": + version: 1.1.0 + resolution: "decamelize-keys@npm:1.1.0" + dependencies: + decamelize: ^1.1.0 + map-obj: ^1.0.0 + checksum: dbfe6d594810ef134f8e3b8aa1684c854187a225999a0c3871b8c32d8fda886d1832b79b952a53e9557be17a78ec0198b6c26a5a5a35d012d6b18340a4dc6356 + languageName: node + linkType: hard + +"decamelize@npm:^1.1.0, decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" checksum: 8ca9d03ea8ac07920f4504e219d18edff2491bdd0a3e05a1e5ca2e9a0bf6333564231de3528b01d5e76c40a38c37bbc1e09cb5a0424714f53dd615ed78ced464 @@ -2037,6 +2120,23 @@ __metadata: languageName: node linkType: hard +"execa@npm:^5.0.0, execa@npm:~5.1.0": + version: 5.1.1 + resolution: "execa@npm:5.1.1" + dependencies: + cross-spawn: ^7.0.3 + get-stream: ^6.0.0 + human-signals: ^2.1.0 + is-stream: ^2.0.0 + merge-stream: ^2.0.0 + npm-run-path: ^4.0.1 + onetime: ^5.1.2 + signal-exit: ^3.0.3 + strip-final-newline: ^2.0.0 + checksum: 4286ade8cdb267bfb982bddbf894a58df29ff4f3bb871252a4832c4608e485dd71e5a8bbfde9f95d7db4af864f5de1aa6a1780017217bd946a16409b8e022987 + languageName: node + linkType: hard + "exit@npm:^0.1.2": version: 0.1.2 resolution: "exit@npm:0.1.2" @@ -2218,6 +2318,15 @@ __metadata: languageName: node linkType: hard +"find-versions@npm:^5.0.0": + version: 5.0.0 + resolution: "find-versions@npm:5.0.0" + dependencies: + semver-regex: ^4.0.0 + checksum: ec5ed95f3d0818765e28f70c764ceb55a7301e5312506102b4bdde1583101339923df1eebfb3d81dcb866f39f62b64b06d6941495cd587e00a08a69f0a2fc263 + languageName: node + linkType: hard + "for-in@npm:^1.0.2": version: 1.0.2 resolution: "for-in@npm:1.0.2" @@ -2348,6 +2457,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"get-stream@npm:^6.0.0, get-stream@npm:~6.0.1": + version: 6.0.1 + resolution: "get-stream@npm:6.0.1" + checksum: 83de1fde5b21f879b91e45c1be765f53cf041873d65aea3b5a15cd53d4bc7825118693b1f50efb5c33a5d979dd20b398b6af955ffd70a013017da933b18fa5c8 + languageName: node + linkType: hard + "get-value@npm:^2.0.3, get-value@npm:^2.0.6": version: 2.0.6 resolution: "get-value@npm:2.0.6" @@ -2385,7 +2501,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"got@npm:^11.8.2": +"got@npm:^11.8.2, got@npm:~11.8.2": version: 11.8.2 resolution: "got@npm:11.8.2" dependencies: @@ -2447,6 +2563,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"hard-rejection@npm:^2.1.0": + version: 2.1.0 + resolution: "hard-rejection@npm:2.1.0" + checksum: 27bc09d185ca8131356f0f3391ae5965c5ed8ec9eddf697d604e33c76eb995831e60ac636e5e5839587d0499f29719171c19d0af5fa12e9e7f7c0a1689e22b6f + languageName: node + linkType: hard + "has-flag@npm:^3.0.0": version: 3.0.0 resolution: "has-flag@npm:3.0.0" @@ -2523,6 +2646,15 @@ fsevents@^2.1.2: languageName: node linkType: hard +"hosted-git-info@npm:^4.0.1": + version: 4.0.2 + resolution: "hosted-git-info@npm:4.0.2" + dependencies: + lru-cache: ^6.0.0 + checksum: 838315facefdb2d0beb99c68d5a419e5f4f6151385fac4aff021d5817349b77f7780f18e04f48b11ad0fbeaf6ac5594351bc3eecdb353b8db41a4e080abdde67 + languageName: node + linkType: hard + "howlongtobeat@npm:^1.3.1": version: 1.3.1 resolution: "howlongtobeat@npm:1.3.1" @@ -2598,6 +2730,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"human-signals@npm:^2.1.0": + version: 2.1.0 + resolution: "human-signals@npm:2.1.0" + checksum: 70bfd94d27b8ca94f76f92f56d294694860c15264393a8ffee83f49535a08da02e477064d91e2b511cc642ec5c7922675d2babcca2b6bf6f45e4d037b632759d + languageName: node + linkType: hard + "iconv-lite@npm:0.4.24": version: 0.4.24 resolution: "iconv-lite@npm:0.4.24" @@ -2607,6 +2746,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"imagemagick@npm:^0.1.3": + version: 0.1.3 + resolution: "imagemagick@npm:0.1.3" + checksum: 49a6479ae08a7b845ab13df835b87ecd46b8bf93a1872c7c0b3ace7858bf1edc7defd1f84dda9fe8e765051877a82487914551557939048236b7465a31d6f783 + languageName: node + linkType: hard + "import-local@npm:^3.0.2": version: 3.0.2 resolution: "import-local@npm:3.0.2" @@ -2626,6 +2772,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"indent-string@npm:^4.0.0": + version: 4.0.0 + resolution: "indent-string@npm:4.0.0" + checksum: 3e54996c6e15ca00a7a4403be705bce4fb3bb4ac637da2e1473006e42a651863f53bfb8c3438c1b3aac77817768ac0cde0e7b7a81a6cf24a1286227a06510dbf + languageName: node + linkType: hard + "inflight@npm:^1.0.4": version: 1.0.6 resolution: "inflight@npm:1.0.6" @@ -2822,6 +2975,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"is-plain-obj@npm:^1.1.0": + version: 1.1.0 + resolution: "is-plain-obj@npm:1.1.0" + checksum: d2eb5a32eacd7c79f3b2fe20552d091805a5ae88a7ca2aa71226bf822e4d690ef046ed2beb795f32666a401dfbf9a25ee3d4acde5426f963d55474468708ad22 + languageName: node + linkType: hard + "is-plain-object@npm:^2.0.3, is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -2859,6 +3019,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"is-unix@npm:~1.0.0": + version: 1.0.0 + resolution: "is-unix@npm:1.0.0" + checksum: 861bfee497e8fe0ebff8954922fd3ea4b04e84b97aac6e437b3117b0ebf5bb26000c699ffa4853064e07e052b54bed97bd6206735ebbe6e8cb694c0dc82f82fe + languageName: node + linkType: hard + "is-whitespace@npm:^0.3.0": version: 0.3.0 resolution: "is-whitespace@npm:0.3.0" @@ -2994,10 +3161,12 @@ fsevents@^2.1.2: fast-xml-parser: ^3.18.0 got: ^11.8.2 howlongtobeat: ^1.3.1 + imagemagick: ^0.1.3 jest: ^26.6.3 lunr: ^2.3.9 mockdate: ^3.0.2 parser-front-matter: ^1.6.4 + youtube-dl-exec: ^1.2.4 languageName: unknown linkType: soft @@ -3614,7 +3783,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2": +"kind-of@npm:^6.0.0, kind-of@npm:^6.0.2, kind-of@npm:^6.0.3": version: 6.0.3 resolution: "kind-of@npm:6.0.3" checksum: 5de5d6577796af87a983199d6350ed41c670abec4a306cc43ca887c1afdbd6b89af9ab00016e3ca17eb7ad89ebfd9bb817d33baa89f855c6c95398a8b8abbf08 @@ -3739,6 +3908,20 @@ fsevents@^2.1.2: languageName: node linkType: hard +"map-obj@npm:^1.0.0": + version: 1.0.1 + resolution: "map-obj@npm:1.0.1" + checksum: e68b20e4fa76efdbba9a7af05b879eb7a6c5ccb7a9d813796de825da4c182fc3dab66f4b2a32a9aefae83db152a0172deb1e19a9c2322c6d412b8f9f81ca51a4 + languageName: node + linkType: hard + +"map-obj@npm:^4.0.0": + version: 4.2.1 + resolution: "map-obj@npm:4.2.1" + checksum: 59c2f09ffccf8878cdb67dc46d0dd73a55bcfb27c20afc2fb87250ac95f2b19e3187c8de887c40f41b96b0200aac3dfdbc31759615cb666b35864a307885c896 + languageName: node + linkType: hard + "map-visit@npm:^1.0.0": version: 1.0.0 resolution: "map-visit@npm:1.0.0" @@ -3748,6 +3931,26 @@ fsevents@^2.1.2: languageName: node linkType: hard +"meow@npm:^9.0.0": + version: 9.0.0 + resolution: "meow@npm:9.0.0" + dependencies: + "@types/minimist": ^1.2.0 + camelcase-keys: ^6.2.2 + decamelize: ^1.2.0 + decamelize-keys: ^1.1.0 + hard-rejection: ^2.1.0 + minimist-options: 4.1.0 + normalize-package-data: ^3.0.0 + read-pkg-up: ^7.0.1 + redent: ^3.0.0 + trim-newlines: ^3.0.0 + type-fest: ^0.18.0 + yargs-parser: ^20.2.3 + checksum: d1573809d6e3df55ab7b8c49f2ecfb8006664856700b556c794013ef887e47991bf1fef8ba9de60bb4afda9b62136823e4008c7f2cc459a7c036b7b649a42c0d + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -3823,6 +4026,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"min-indent@npm:^1.0.0": + version: 1.0.1 + resolution: "min-indent@npm:1.0.1" + checksum: c3aeea46bc432e6ce69b86717e98fbb544e338abb5e3c93cfa196c427e3d5a4a6ee4f76e6931a9e424fb53e83451b90fc417ce7db04440a92d68369704ad11d1 + languageName: node + linkType: hard + "minimatch@npm:^3.0.4": version: 3.0.4 resolution: "minimatch@npm:3.0.4" @@ -3832,6 +4042,17 @@ fsevents@^2.1.2: languageName: node linkType: hard +"minimist-options@npm:4.1.0": + version: 4.1.0 + resolution: "minimist-options@npm:4.1.0" + dependencies: + arrify: ^1.0.1 + is-plain-obj: ^1.1.0 + kind-of: ^6.0.3 + checksum: 51f1aba56f9c2c2986d85c98a29abec26c632019abd2966a151029cf2cf0903d81894781460e0d5755d4f899bb3884bc86fc9af36ab31469a38d82cf74f4f651 + languageName: node + linkType: hard + "minimist@npm:^1.1.1, minimist@npm:^1.2.0, minimist@npm:^1.2.5": version: 1.2.5 resolution: "minimist@npm:1.2.5" @@ -3868,7 +4089,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"mkdirp@npm:^1.0.3": +"mkdirp@npm:^1.0.3, mkdirp@npm:~1.0.4": version: 1.0.4 resolution: "mkdirp@npm:1.0.4" bin: @@ -4009,6 +4230,18 @@ fsevents@^2.1.2: languageName: node linkType: hard +"normalize-package-data@npm:^3.0.0": + version: 3.0.2 + resolution: "normalize-package-data@npm:3.0.2" + dependencies: + hosted-git-info: ^4.0.1 + resolve: ^1.20.0 + semver: ^7.3.4 + validate-npm-package-license: ^3.0.1 + checksum: a1053ccfe091bbb83692deaad52450d3d214858bd02063a9267d38d618f13045528b81fef8729417303136c0b34ad5bfcf78d48aa0a3e36a90615726897e24e9 + languageName: node + linkType: hard + "normalize-path@npm:^2.1.1": version: 2.1.1 resolution: "normalize-path@npm:2.1.1" @@ -4041,7 +4274,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"npm-run-path@npm:^4.0.0": +"npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" dependencies: @@ -4137,7 +4370,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"onetime@npm:^5.1.0": +"onetime@npm:^5.1.0, onetime@npm:^5.1.2": version: 5.1.2 resolution: "onetime@npm:5.1.2" dependencies: @@ -4174,6 +4407,15 @@ fsevents@^2.1.2: languageName: node linkType: hard +"p-event@npm:~4.2.0": + version: 4.2.0 + resolution: "p-event@npm:4.2.0" + dependencies: + p-timeout: ^3.1.0 + checksum: 2f57be65972285794231072b188a1f0ff542285e5629066b6902db4420ce09bec9b4c75829ce0f996132d2ca0e38b16f675e2be15a20a03fc9e7ab515571b0b8 + languageName: node + linkType: hard + "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -4199,6 +4441,22 @@ fsevents@^2.1.2: languageName: node linkType: hard +"p-reflect@npm:~2.1.0": + version: 2.1.0 + resolution: "p-reflect@npm:2.1.0" + checksum: 997f198dae1d45f532753ae48140021dfd7d4c0751da896deb07e1d6c500c4bfb9dd56be94ce86047d216891b074e7e9176e192884eaec10a1596feb612d0b05 + languageName: node + linkType: hard + +"p-timeout@npm:^3.1.0": + version: 3.2.0 + resolution: "p-timeout@npm:3.2.0" + dependencies: + p-finally: ^1.0.0 + checksum: d7e71c1547736ecd392be3c4ea956af1abd2b6f56179f37443672cfaccb41383533cdf2e927890bb5282e1eb41c979be133eef26a6a84a8224ff4f5c9455b517 + languageName: node + linkType: hard + "p-try@npm:^2.0.0": version: 2.2.0 resolution: "p-try@npm:2.2.0" @@ -4404,6 +4662,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"quick-lru@npm:^4.0.1": + version: 4.0.1 + resolution: "quick-lru@npm:4.0.1" + checksum: 91847e4b07453655f73513b96a3b49e3bb8bf37de1ce2075d44e5dddb2f08050c5dc858d97884d61618bb44487945880b4b481fe93e94a3622b43036f8b94e11 + languageName: node + linkType: hard + "quick-lru@npm:^5.1.1": version: 5.1.1 resolution: "quick-lru@npm:5.1.1" @@ -4456,6 +4721,16 @@ fsevents@^2.1.2: languageName: node linkType: hard +"redent@npm:^3.0.0": + version: 3.0.0 + resolution: "redent@npm:3.0.0" + dependencies: + indent-string: ^4.0.0 + strip-indent: ^3.0.0 + checksum: 78c8aa0a1076f47e0e198bfc8a9aa7d4ae3163c6951bd5de1015e47661bba62ea36573337bbeb4b309b48cc71954edbe43ae4aa3163db1996a781b757c5c47d7 + languageName: node + linkType: hard + "regex-not@npm:^1.0.0, regex-not@npm:^1.0.2": version: 1.0.2 resolution: "regex-not@npm:1.0.2" @@ -4583,7 +4858,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"resolve@^1.10.0, resolve@^1.18.1": +"resolve@^1.10.0, resolve@^1.18.1, resolve@^1.20.0": version: 1.20.0 resolution: "resolve@npm:1.20.0" dependencies: @@ -4593,7 +4868,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"resolve@patch:resolve@^1.10.0#builtin, resolve@patch:resolve@^1.18.1#builtin": +"resolve@patch:resolve@^1.10.0#builtin, resolve@patch:resolve@^1.18.1#builtin, resolve@patch:resolve@^1.20.0#builtin": version: 1.20.0 resolution: "resolve@patch:resolve@npm%3A1.20.0#builtin::version=1.20.0&hash=3388aa" dependencies: @@ -4695,6 +4970,22 @@ fsevents@^2.1.2: languageName: node linkType: hard +"semver-regex@npm:^4.0.0": + version: 4.0.0 + resolution: "semver-regex@npm:4.0.0" + checksum: 7d5aad31000ecefbe6d7c4dd5dfcb2b6f3e4de0931bf54abfeeee716d2054f503e5ffc0b929371e5b0d9c1c0b39b79c8412343db87f4f8aeb89f48202adbacc0 + languageName: node + linkType: hard + +"semver-truncate@npm:^2.0.0": + version: 2.0.0 + resolution: "semver-truncate@npm:2.0.0" + dependencies: + semver: ^6.0.0 + checksum: ce009febdaee709d16ba04e09081832337f7aa66174030a1768050a717613bc5a99b640debca772db1eaec38fadf1c10afab053a96a1f6646a78ff99ba66ea5d + languageName: node + linkType: hard + "semver@npm:2 || 3 || 4 || 5, semver@npm:^5.5.0": version: 5.7.1 resolution: "semver@npm:5.7.1" @@ -4724,6 +5015,17 @@ fsevents@^2.1.2: languageName: node linkType: hard +"semver@npm:^7.3.4, semver@npm:^7.3.5": + version: 7.3.5 + resolution: "semver@npm:7.3.5" + dependencies: + lru-cache: ^6.0.0 + bin: + semver: bin/semver.js + checksum: c53624ddf4b9779bcbf55a1eb8b37074cc44bfeca416f3cc263429408202a8a3c59b00eef8c647d697303bc39b95c022a5c61959221d3814bfb1270ff7c14986 + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0, set-blocking@npm:~2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" @@ -4791,7 +5093,7 @@ fsevents@^2.1.2: languageName: node linkType: hard -"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2": +"signal-exit@npm:^3.0.0, signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": version: 3.0.3 resolution: "signal-exit@npm:3.0.3" checksum: f8f3fec95c8d1f9ad7e3cce07e1195f84e7a85cdcb4e825e8a2b76aa5406a039083d2bc9662b3cf40e6948262f41277047d20e6fbd58c77edced0b18fab647d8 @@ -5102,6 +5404,15 @@ fsevents@^2.1.2: languageName: node linkType: hard +"strip-indent@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-indent@npm:3.0.0" + dependencies: + min-indent: ^1.0.0 + checksum: 4a7860e94372753b90a48d032758464efbf194880880fd7636965b7137ae4af24ce77a43d223a602cac787e2e95214aaa2f2470a65986e3d6ffa0e1c3dd887f6 + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" @@ -5272,6 +5583,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"trim-newlines@npm:^3.0.0": + version: 3.0.1 + resolution: "trim-newlines@npm:3.0.1" + checksum: a1cc3d5992d47349fa0b48206038e524f42d0ade81913cc72322e4f5a99c5e936eb730af762c9f5bafa3c19ab1e9eaf14bdff487cbe3f2c5d525dd03f3f89fb0 + languageName: node + linkType: hard + "tunnel-agent@npm:^0.6.0": version: 0.6.0 resolution: "tunnel-agent@npm:0.6.0" @@ -5311,6 +5629,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"type-fest@npm:^0.18.0": + version: 0.18.1 + resolution: "type-fest@npm:0.18.1" + checksum: 0d6d338e72b625a0d2c8fb4c138f5221301e40ac127e1b909bc12890ce358ef9cf11136e13aa0efd82e248bbeefd7148c01985dce2e5ab79d47a2efa75dfe8d2 + languageName: node + linkType: hard + "type-fest@npm:^0.6.0": version: 0.6.0 resolution: "type-fest@npm:0.6.0" @@ -5658,6 +5983,13 @@ fsevents@^2.1.2: languageName: node linkType: hard +"yargs-parser@npm:^20.2.3": + version: 20.2.7 + resolution: "yargs-parser@npm:20.2.7" + checksum: 124e7f1c24c9609d5d1c343f14b83289634e19bb43770708ebb6a19852647aaa0f89edcbf0e5b18a21bee77f54513ab5051518b2950cda69eb607a7c6251aa4f + languageName: node + linkType: hard + "yargs@npm:^15.4.1": version: 15.4.1 resolution: "yargs@npm:15.4.1" @@ -5676,3 +6008,20 @@ fsevents@^2.1.2: checksum: dbf687d6b938f01bbf11e158dde6df906282b70cd9295af0217ee8cefbd83ad09d49fa9458d0d5325b0e66f03df954a38986db96f91e5b46ccdbbaf9a0157b23 languageName: node linkType: hard + +"youtube-dl-exec@npm:^1.2.4": + version: 1.2.4 + resolution: "youtube-dl-exec@npm:1.2.4" + dependencies: + bin-version-check-cli: ~3.0.0 + dargs: ~7.0.0 + execa: ~5.1.0 + get-stream: ~6.0.1 + got: ~11.8.2 + is-unix: ~1.0.0 + mkdirp: ~1.0.4 + p-event: ~4.2.0 + p-reflect: ~2.1.0 + checksum: 6c36b9d6554bd0c0f04171daa72d3a44f1a2c268d8a6bed8020f4841cf5f2f7d6603859323ed7de880a0d4dfd91fd1d6aca71108f995e446ba5ec9a129ccd7eb + languageName: node + linkType: hard