From d55dddea2e7928bd5cac2c4c02d876d6a093ed9e Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 10:00:00 +0000 Subject: [PATCH 01/42] core/api: normalize bearer authorization --- api/src/core/api.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/api/src/core/api.js b/api/src/core/api.js index b11d689a..b3123033 100644 --- a/api/src/core/api.js +++ b/api/src/core/api.js @@ -158,19 +158,20 @@ export const runAPI = (express, app, __dirname) => { return fail(res, "error.api.auth.jwt.missing"); } - if (!authorization.startsWith("Bearer ") || authorization.length > 256) { + if (authorization.length >= 256) { return fail(res, "error.api.auth.jwt.invalid"); } - const verifyJwt = jwt.verify( - authorization.split("Bearer ", 2)[1] - ); - - if (!verifyJwt) { + const [ type, token, ...rest ] = authorization.split(" "); + if (!token || type.toLowerCase() !== 'bearer' || rest.length) { return fail(res, "error.api.auth.jwt.invalid"); } - req.rateLimitKey = generateHmac(req.header("Authorization"), ipSalt); + if (!jwt.verify(token)) { + return fail(res, "error.api.auth.jwt.invalid"); + } + + req.rateLimitKey = generateHmac(token, ipSalt); } catch { return fail(res, "error.api.generic"); } From f5d09f86db73ed82b5d18b2ff0f8ca09c716f4cd Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 10:18:51 +0000 Subject: [PATCH 02/42] tests/soundcloud: replace private link --- api/src/util/tests.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/util/tests.json b/api/src/util/tests.json index 94005c0a..402a2baf 100644 --- a/api/src/util/tests.json +++ b/api/src/util/tests.json @@ -238,7 +238,7 @@ }, { "name": "private song", - "url": "https://soundcloud.com/4kayy/unhappy-new-year-prod4kay/s-9bKbvwLdRWG", + "url": "https://soundcloud.com/user-798052861/asdasdasdsdsd/s-9TqZ7edLJ90", "params": { "audioFormat": "mp3" }, @@ -249,7 +249,7 @@ }, { "name": "private song (wav, isAudioMuted)", - "url": "https://soundcloud.com/4kayy/unhappy-new-year-prod4kay/s-9bKbvwLdRWG", + "url": "https://soundcloud.com/user-798052861/asdasdasdsdsd/s-9TqZ7edLJ90", "params": { "downloadMode": "mute", "audioFormat": "wav" @@ -261,7 +261,7 @@ }, { "name": "private song (ogg, isAudioMuted, isAudioOnly)", - "url": "https://soundcloud.com/4kayy/unhappy-new-year-prod4kay/s-9bKbvwLdRWG", + "url": "https://soundcloud.com/user-798052861/asdasdasdsdsd/s-9TqZ7edLJ90", "params": { "downloadMode": "audio", "audioFormat": "ogg" From 1cf82e4d69fb667518c09b23c447ac923d80f703 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 16:23:09 +0600 Subject: [PATCH 03/42] docs: add a tutorial document for protecting an instance --- docs/images/protect-an-instance/add.png | Bin 0 -> 15590 bytes docs/images/protect-an-instance/created.png | Bin 0 -> 29173 bytes docs/images/protect-an-instance/domain.png | Bin 0 -> 13460 bytes docs/images/protect-an-instance/mode.png | Bin 0 -> 27968 bytes docs/images/protect-an-instance/name.png | Bin 0 -> 14816 bytes docs/images/protect-an-instance/sidebar.png | Bin 0 -> 6662 bytes docs/protect-an-instance.md | 58 ++++++++++++++++++++ docs/run-an-instance.md | 2 +- 8 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 docs/images/protect-an-instance/add.png create mode 100644 docs/images/protect-an-instance/created.png create mode 100644 docs/images/protect-an-instance/domain.png create mode 100644 docs/images/protect-an-instance/mode.png create mode 100644 docs/images/protect-an-instance/name.png create mode 100644 docs/images/protect-an-instance/sidebar.png create mode 100644 docs/protect-an-instance.md diff --git a/docs/images/protect-an-instance/add.png b/docs/images/protect-an-instance/add.png new file mode 100644 index 0000000000000000000000000000000000000000..e186a65ce99e5a3b31d98b524348af049fba3a38 GIT binary patch literal 15590 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 literal 0 HcmV?d00001 diff --git a/docs/images/protect-an-instance/created.png b/docs/images/protect-an-instance/created.png new file mode 100644 index 0000000000000000000000000000000000000000..546a68978caa3b604e5ef283c178aae7112d16e3 GIT binary patch literal 29173 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 literal 0 HcmV?d00001 diff --git a/docs/images/protect-an-instance/domain.png b/docs/images/protect-an-instance/domain.png new file mode 100644 index 0000000000000000000000000000000000000000..249a8a9250c51e5939bc6067c11d43436f2f3ec7 GIT binary patch literal 13460 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 NRgh5uS4o)$|1W`nisJwP literal 0 HcmV?d00001 diff --git a/docs/images/protect-an-instance/mode.png b/docs/images/protect-an-instance/mode.png new file mode 100644 index 0000000000000000000000000000000000000000..242b35a5b00c4f293e7cddb480d9660f131ffd88 GIT binary patch literal 27968 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 X0`LXhsc+ZC{sk$@s>#$#nT7r@@y`EQ literal 0 HcmV?d00001 diff --git a/docs/images/protect-an-instance/name.png b/docs/images/protect-an-instance/name.png new file mode 100644 index 0000000000000000000000000000000000000000..fd39dc954e9925f2f97b58ccdcfb4baf7d65e867 GIT binary patch literal 14816 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 H@aO*p%%Qsl literal 0 HcmV?d00001 diff --git a/docs/images/protect-an-instance/sidebar.png b/docs/images/protect-an-instance/sidebar.png new file mode 100644 index 0000000000000000000000000000000000000000..8294c4a059a39b5f922bd40521998cb6a20bdd4b GIT binary patch literal 6662 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 F{{buvy|@4X literal 0 HcmV?d00001 diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md new file mode 100644 index 00000000..650f155e --- /dev/null +++ b/docs/protect-an-instance.md @@ -0,0 +1,58 @@ +# how to protect your cobalt instance +if you keep getting a ton of unknown traffic that hurts the performance of your instance, then it might be a good idea to enable bot protection. + +``` +⚠️ this tutorial will work reliably on the latest official version of cobalt 10. we can't promise full compatibility with anything else. +``` + +## configure cloudflare turnstile +turnstile is a free, safe, and privacy-respecting alternative to captcha. +cobalt uses it automatically to weed out bots and automated scripts. +your instance doesn't have to be proxied by cloudflare to use turnstile. +all you need is a free cloudflare account to get started. + +cloudflare dashboard interface might change over time, but basics should stay the same. + +1. open [the cloudflare dashboard](https://dash.cloudflare.com/) and log into your account. +2. once logged in, select `turnstile` in the sidebar. +![](images/protect-an-instance/sidebar.png) +3. press `add widget`. +![](images/protect-an-instance/add.png) +4. enter the widget name (can be anything, such as "cobalt"). +![](images/protect-an-instance/name.png) +5. add cobalt frontend domains you want the widget to work with. you can change this list later at any time. + - if you want to use your processing instance with [cobalt.tools](https://cobalt.tools/) frontend, then add `cobalt.tools` to the list. +![](images/protect-an-instance/domain.png) +6. select `invisible` widget mode. +![](images/protect-an-instance/mode.png) +7. press `create`. +8. keep the page with sitekey and secret key open, you'll need them later. +if you closed it, no worries! +just open the same turnstile page and press "settings" on your freshly made turnstile widget. +**never share your secret turnstile key with anyone.** +![](images/protect-an-instance/created.png) + +you've successfully created a turnstile widget! time to add it to your processing instance. + +### enable turnstile on your processing instance +this tutorial assumes that you only have `API_URL` in your `environment` variables list. +if you have other variables there, just add new ones after existing ones. +**example values in the tutorial should never be used**. + +1. open your `docker-compose.yml` config file in any text editor of choice. +2. copy the turnstile sitekey & secret key and paste them to their respective variables. `TURNSTILE_SITEKEY` for the sitekey and `TURNSTILE_SECRET` for the secret key: +```yml +environment: + API_URL: "https://your.instance.url.here.local/" + TURNSTILE_SITEKEY: "2x00000000000000000000BB" # use your key + TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key +``` +3. generate a `JWT_SECRET`. we recommend using an alphanumeric collection with a length of at least 64 characters. this string will be used as salt for all JWT keys. **do NOT use the example secret**. + +```yml +environment: + API_URL: "https://your.instance.url.here.local/" + TURNSTILE_SITEKEY: "2x00000000000000000000BB" # use your key + TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key + JWT_SECRET: "bgBmF4efNCKPirDqTc4FMmbX8P22I31oCj5R1zDiDi5sy8CWPnfLUct7rk5RlZUS" # create a new secret, NEVER use this one +``` diff --git a/docs/run-an-instance.md b/docs/run-an-instance.md index 272fbd35..1d4dcdc0 100644 --- a/docs/run-an-instance.md +++ b/docs/run-an-instance.md @@ -1,4 +1,4 @@ -# how to host a cobalt instance yourself +# how to run a cobalt instance ## using docker compose and package from github (recommended) to run the cobalt docker package, you need to have `docker` and `docker-compose` installed and configured. From 90114bdbea2d757681e7c78686b5e45acec22e18 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 16:28:22 +0600 Subject: [PATCH 04/42] docs/protect-an-instance: update the note to show up as such --- docs/protect-an-instance.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 650f155e..7c9bec7b 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -1,9 +1,9 @@ # how to protect your cobalt instance if you keep getting a ton of unknown traffic that hurts the performance of your instance, then it might be a good idea to enable bot protection. -``` -⚠️ this tutorial will work reliably on the latest official version of cobalt 10. we can't promise full compatibility with anything else. -``` +> [!NOTE] +> this tutorial will work reliably on the latest official version of cobalt 10. +we can't promise full compatibility with anything else. ## configure cloudflare turnstile turnstile is a free, safe, and privacy-respecting alternative to captcha. From 5ce3a941f9ef345a74439bfffdb33fb9c417ff39 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 16:31:55 +0600 Subject: [PATCH 05/42] docs/protect-an-instance: emphasize a warning in env variable section --- docs/protect-an-instance.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 7c9bec7b..c95bf135 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -37,7 +37,9 @@ you've successfully created a turnstile widget! time to add it to your processin ### enable turnstile on your processing instance this tutorial assumes that you only have `API_URL` in your `environment` variables list. if you have other variables there, just add new ones after existing ones. -**example values in the tutorial should never be used**. + +> [!IMPORTANT] +> never use any of the values from the tutorial, especially `JWT_SECRET`! 1. open your `docker-compose.yml` config file in any text editor of choice. 2. copy the turnstile sitekey & secret key and paste them to their respective variables. `TURNSTILE_SITEKEY` for the sitekey and `TURNSTILE_SECRET` for the secret key: @@ -47,7 +49,7 @@ environment: TURNSTILE_SITEKEY: "2x00000000000000000000BB" # use your key TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key ``` -3. generate a `JWT_SECRET`. we recommend using an alphanumeric collection with a length of at least 64 characters. this string will be used as salt for all JWT keys. **do NOT use the example secret**. +3. generate a `JWT_SECRET`. we recommend using an alphanumeric collection with a length of at least 64 characters. this string will be used as salt for all JWT keys. ```yml environment: From c3f3499a42e04a24c8a63c3f174bd68aff9b4e5d Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 10:35:05 +0000 Subject: [PATCH 06/42] api/util: add script to generate secure `JWT_SECRET` --- api/package.json | 3 ++- api/src/util/generate-jwt-secret.js | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 api/src/util/generate-jwt-secret.js diff --git a/api/package.json b/api/package.json index 339d383f..ba346f39 100644 --- a/api/package.json +++ b/api/package.json @@ -12,7 +12,8 @@ "start": "node src/cobalt", "setup": "node src/util/setup", "test": "node src/util/test", - "token:youtube": "node src/util/generate-youtube-tokens" + "token:youtube": "node src/util/generate-youtube-tokens", + "token:jwt": "node src/util/generate-jwt-secret" }, "repository": { "type": "git", diff --git a/api/src/util/generate-jwt-secret.js b/api/src/util/generate-jwt-secret.js new file mode 100644 index 00000000..83f0aa5b --- /dev/null +++ b/api/src/util/generate-jwt-secret.js @@ -0,0 +1,13 @@ +// run with `pnpm -r token:jwt` + +const makeSecureString = (length = 64) => { + const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; + const out = []; + + for (const byte of crypto.getRandomValues(new Uint8Array(length))) + out.push(alphabet[byte % alphabet.length]); + + return out.join(''); +} + +console.log(`JWT_SECRET: ${JSON.stringify(makeSecureString(64))}`) From 7515204bb73a858a82853a456cef576dd64cd038 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 16:51:38 +0600 Subject: [PATCH 07/42] docs/api: update warnings --- docs/api.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index 39b17209..dfcac1ed 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,8 +1,8 @@ # cobalt api documentation this document provides info about methods and acceptable variables for all cobalt api requests. -> if you are looking for the documentation for the old (7.x) api, you can find -> it [here](https://github.com/imputnet/cobalt/blob/7/docs/api.md) +> [!IMPORTANT] +> hosted api instances (such as api.cobalt.tools) use bot protection and are not intended to be used in other projects without explicit permission. if you want to access the cobalt api reliably, you should [host your own instance](/docs/run-an-instance.md). ## authentication an api instance may be configured to require you to authenticate yourself. @@ -46,9 +46,10 @@ cobalt's main processing endpoint. request body type: `application/json` response body type: `application/json` -``` -⚠️ you must include Accept and Content-Type headers with every `POST /` request. +> [!IMPORTANT] +> you must include `Accept` and `Content-Type` headers with every `POST /` request. +``` Accept: application/json Content-Type: application/json ``` From 67ffcdc5047ef314a6f042c0634ee7539ba98449 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 16:52:59 +0600 Subject: [PATCH 08/42] docs/api: update the general api warning --- docs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index dfcac1ed..dc7e9c59 100644 --- a/docs/api.md +++ b/docs/api.md @@ -2,7 +2,7 @@ this document provides info about methods and acceptable variables for all cobalt api requests. > [!IMPORTANT] -> hosted api instances (such as api.cobalt.tools) use bot protection and are not intended to be used in other projects without explicit permission. if you want to access the cobalt api reliably, you should [host your own instance](/docs/run-an-instance.md). +> hosted api instances (such as `api.cobalt.tools`) use bot protection and are **not** intended to be used in other projects without explicit permission. if you want to access the cobalt api reliably, you should [host your own instance](/docs/run-an-instance.md) or ask an instance owner for access. ## authentication an api instance may be configured to require you to authenticate yourself. From 51adfc85cd03bd24fbf4b535f7a6c5b220dbc4db Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 17:20:38 +0600 Subject: [PATCH 09/42] api: update readme --- api/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/api/README.md b/api/README.md index 5c281246..05664321 100644 --- a/api/README.md +++ b/api/README.md @@ -11,12 +11,14 @@ as long as you: ## running your own instance if you want to run your own instance for whatever purpose, [follow this guide](/docs/run-an-instance.md). -it's *highly* recommended to use a docker compose method unless you run for developing/debugging purposes. +we recommend to use docker compose unless you intend to run cobalt for developing/debugging purposes. ## accessing the api -currently, there is no publicly accessible main api. we plan on providing a public api for -cobalt 10 in some form in the future. we recommend deploying your own instance if you wish -to use the latest api. you can access [the documentation](/docs/api.md) for it here. +there is currently no publicly available pre-hosted api. +we recommend [deploying your own instance](/docs/run-an-instance.md) if you wish to use the cobalt api. -if you are looking for the documentation for the old (7.x) api, you can find -it [here](https://github.com/imputnet/cobalt/blob/7/docs/api.md) \ No newline at end of file +you can read [the api documentation here](/docs/api.md). + +> [!WARNING] +> the v7 public api (/api/json) will be shut down on **november 11th, 2024**. +> you can access documentation for it [here](https://github.com/imputnet/cobalt/blob/7/docs/api.md). From c494850cfff1d4f3977e735b73cc690c39ad065b Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 17:45:10 +0600 Subject: [PATCH 10/42] repo: update readme & remove old docs --- README.md | 114 ++++-------------- .../troubleshooting/clipboard/config.png | Bin 4154 -> 0 bytes .../images/troubleshooting/clipboard/risk.png | Bin 17944 -> 0 bytes .../troubleshooting/clipboard/search.png | Bin 6867 -> 0 bytes .../troubleshooting/clipboard/toggle.png | Bin 18725 -> 0 bytes .../troubleshooting/clipboard/toggled.png | Bin 17312 -> 0 bytes docs/troubleshooting.md | 37 ------ 7 files changed, 24 insertions(+), 127 deletions(-) delete mode 100644 docs/images/troubleshooting/clipboard/config.png delete mode 100644 docs/images/troubleshooting/clipboard/risk.png delete mode 100644 docs/images/troubleshooting/clipboard/search.png delete mode 100644 docs/images/troubleshooting/clipboard/toggle.png delete mode 100644 docs/images/troubleshooting/clipboard/toggled.png delete mode 100644 docs/troubleshooting.md diff --git a/README.md b/README.md index 5bf8ae8e..ca108a86 100644 --- a/README.md +++ b/README.md @@ -15,108 +15,42 @@ 💬 community discord server - 🐦 twitter/x + 🐦 twitter


-cobalt is a media downloader that doesn't piss you off. it's fast, friendly, and doesn't have any bullshit that modern web is filled with: ***no ads, trackers, or paywalls***. +cobalt is a media downloader that doesn't piss you off. it's friendly, efficient, and doesn't have ads, trackers, paywalls or other nonsense. -paste the link, get the file, move on. it's that simple. just how it should be. +paste the link, get the file, move on. that simple, just how it should be. -### supported services -this list is not final and keeps expanding over time. if support for a service you want is missing, create an issue (or a pull request 👀). +### cobalt monorepo +this monorepo includes source code for api, frontend, and related packages: +- [api tree](/api/) +- [web tree](/web/) +- [packages tree](/packages/) -| service | video + audio | only audio | only video | metadata | rich file names | -| :-------- | :-----------: | :--------: | :--------: | :------: | :-------------: | -| bilibili | ✅ | ✅ | ✅ | ➖ | ➖ | -| bluesky | ✅ | ✅ | ✅ | ➖ | ➖ | -| dailymotion | ✅ | ✅ | ✅ | ✅ | ✅ | -| instagram | ✅ | ✅ | ✅ | ➖ | ➖ | -| facebook | ✅ | ❌ | ✅ | ➖ | ➖ | -| loom | ✅ | ❌ | ✅ | ✅ | ➖ | -| ok.ru | ✅ | ❌ | ✅ | ✅ | ✅ | -| pinterest | ✅ | ✅ | ✅ | ➖ | ➖ | -| reddit | ✅ | ✅ | ✅ | ❌ | ❌ | -| rutube | ✅ | ✅ | ✅ | ✅ | ✅ | -| snapchat | ✅ | ✅ | ✅ | ➖ | ➖ | -| soundcloud | ➖ | ✅ | ➖ | ✅ | ✅ | -| streamable | ✅ | ✅ | ✅ | ➖ | ➖ | -| tiktok | ✅ | ✅ | ✅ | ❌ | ❌ | -| tumblr | ✅ | ✅ | ✅ | ➖ | ➖ | -| twitch clips | ✅ | ✅ | ✅ | ✅ | ✅ | -| twitter/x | ✅ | ✅ | ✅ | ➖ | ➖ | -| vimeo | ✅ | ✅ | ✅ | ✅ | ✅ | -| vine | ✅ | ✅ | ✅ | ➖ | ➖ | -| vk videos & clips | ✅ | ❌ | ✅ | ✅ | ✅ | -| youtube | ✅ | ✅ | ✅ | ✅ | ✅ | - -| emoji | meaning | -| :-----: | :---------------------- | -| ✅ | supported | -| ➖ | impossible/unreasonable | -| ❌ | not supported | - -### additional notes or features (per service) -| service | notes or features | -| :-------- | :----- | -| instagram | supports reels, photos, and videos. lets you pick what to save from multi-media posts. | -| facebook | supports public accessible videos content only. | -| pinterest | supports photos, gifs, videos and stories. | -| reddit | supports gifs and videos. | -| snapchat | supports spotlights and stories. lets you pick what to save from stories. | -| rutube | supports yappy & private links. | -| soundcloud | supports private links. | -| tiktok | supports videos with or without watermark, images from slideshow without watermark, and full (original) audios. | -| twitter/x | lets you pick what to save from multi-media posts. may not be 100% reliable due to current management. | -| vimeo | audio downloads are only available for dash. | -| youtube | supports videos, music, and shorts. 8K, 4K, HDR, VR, and high FPS videos. rich metadata & dubs. h264/av1/vp9 codecs. | +it also includes documentation in the [docs tree](/docs/): +- [how to run a cobalt instance](/docs/run-an-instance.md) +- [how to protect a cobalt instance](/docs/protect-an-instance.md) +- [cobalt api documentation](/docs/api.md) ### partners -cobalt is sponsored by [royalehosting.net](https://royalehosting.net/?partner=cobalt), all main instances are currently hosted on their network :) +cobalt is sponsored by [royalehosting.net](https://royalehosting.net/?partner=cobalt) and the main processing instance is hosted on their network. we really appreciate their kindness! -### ethics and disclaimer -cobalt is a tool for easing content downloads from internet and takes ***zero liability***. you are responsible for what you download, how you use and distribute that content. please be mindful when using content of others and always credit original creators. fair use and credits benefit everyone. +### ethics +cobalt is a tool that makes downloading public content easier. it takes **zero liability**. +the end user is responsible for what they download, how they use and distribute that content. +cobalt never caches any content, it [works like a fancy proxy](/api/src/stream/). -cobalt is ***NOT*** a piracy tool and cannot be used as such. it can only download free, publicly accessible content. such content can be easily downloaded through any browser's dev tools. pressing one button is easier, so i made a convenient, ad-less tool for such repeated actions. +cobalt is in no way a piracy tool and cannot be used as such. +it can only download free & publicly accessible content. +same content can be downloaded via dev tools of any modern web browser. -### cobalt license +### contributing +thank you for considering making a contribution to cobalt! please check the [contributing guidelines here](/CONTRIBUTING.md) before making a pull request. + +### licenses for relevant licensing information, see the [api](api/README.md) and [web](web/README.md) READMEs. unless specified otherwise, the remainder of this repository is licensed under [AGPL-3.0](LICENSE). - -## acknowledgements -### ffmpeg -cobalt heavily relies on ffmpeg for converting and merging media files. it's an absolutely amazing piece of software offered for anyone for free, yet doesn't receive as much credit as it should. - -you can [support ffmpeg here](https://ffmpeg.org/donations.html)! - -#### ffmpeg-static -we use [ffmpeg-static](https://github.com/eugeneware/ffmpeg-static) to get binaries for ffmpeg depending on the platform. - -you can support the developer via various methods listed on their github page! (linked above) - -### youtube.js -cobalt relies on [youtube.js](https://github.com/LuanRT/YouTube.js) for interacting with the innertube api, it wouldn't have been possible without it. - -you can support the developer via various methods listed on their github page! (linked above) - -### many others -cobalt also depends on: - -- [content-disposition-header](https://www.npmjs.com/package/content-disposition-header) to simplify the provision of `content-disposition` headers. -- [cors](https://www.npmjs.com/package/cors) to manage cross-origin resource sharing within expressjs. -- [dotenv](https://www.npmjs.com/package/dotenv) to load environment variables from the `.env` file. -- [esbuild](https://www.npmjs.com/package/esbuild) to minify the frontend files. -- [express](https://www.npmjs.com/package/express) as the backbone of cobalt servers. -- [express-rate-limit](https://www.npmjs.com/package/express-rate-limit) to rate limit api endpoints. -- [hls-parser](https://www.npmjs.com/package/hls-parser) to parse `m3u8` playlists for certain services. -- [ipaddr.js](https://www.npmjs.com/package/ipaddr.js) to parse ip addresses (for rate limiting). -- [nanoid](https://www.npmjs.com/package/nanoid) to generate unique (temporary) identifiers for each requested stream. -- [node-cache](https://www.npmjs.com/package/node-cache) to cache stream info in server ram for a limited amount of time. -- [psl](https://www.npmjs.com/package/psl) as the domain name parser. -- [set-cookie-parser](https://www.npmjs.com/package/set-cookie-parser) to parse cookies that cobalt receives from certain services. -- [undici](https://www.npmjs.com/package/undici) for making http requests. -- [url-pattern](https://www.npmjs.com/package/url-pattern) to match provided links with supported patterns. - -...and many other packages that these packages rely on. diff --git a/docs/images/troubleshooting/clipboard/config.png b/docs/images/troubleshooting/clipboard/config.png deleted file mode 100644 index b0c0a04803397f14957aef152d84e3449757f3d0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4154 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 OK>9i+=yKHc$o~VoUOguO diff --git a/docs/images/troubleshooting/clipboard/risk.png b/docs/images/troubleshooting/clipboard/risk.png deleted file mode 100644 index 1948f0eb48baad049c38a83297ecf8709d94c275..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17944 zcmeIaWmJ@18$YTbpdg@9A}QSs(jg_?ozfv7Lk>eY@*oY;9n#$m1E?Sk(#-%ejKnZ9 zbf3ZJed1l~oNwpDS?B+Lx!0Q6`@Z(x*S_L+#Z0)Sx*|UAGu%6O?%*rElGDC(2b1Z} zox8aAvC-eazscy|xkGzLNlr%B*Br6@U`gNl`g9*@NlX$xML(oN_)KL$`zuStplb3y zeTb^g^Jqafl?et%9y-uV!RUaAIn;$#k%Cq*uXn;YUBMr$Y$(E;`jr!-s`}+IV73Q$ z&czYxe54wlxnnwe(KZ@j0rlX7Gq*Q69pwL#xpVj4Bk8{$e8i^@z)By^O`rYy+lO~C zh@N3!+^2na=RXe{E@{hnAj!vn&w515^9lc-DYWmTH!m~1H7lY_Sn=bT^U9PhH59jq!1KX80-!hp{(;qnbs#*B{Ry4F^ zh~Pa+b!coi%crqH>6Ob9s_N#{`XE_!vgbN87w_82{-wK*q-k})5rnFTxi+7tNb1af z(7a@SiT-#egz(?0TfnWk4<7hB8}Lk6dmTnCUKJvKqMd)}3?_d3kDivi1xFC5`dwQE zt5P?LdJ~;GOzThBe&4H&g-id-Ts#V6)*J^9T(Yv;G$&{LP%=`)?`mxwPF-dg7om*$ zx0=lu0632}I88(U$4)uAjo^BqhPkxBkvA zy8EhS$0<7MPo;4BQWsW6#%(gh?Q9TN?qj4 z4!D2*!xlc49X}N0UYn@rZ^F=HgL!KZX#>C!4^=-LUsV6RAvtHA)*|BPab!V?3+kAk zEoq(GO#{03Dhq5Eok|zH+2clXhQ2Ivf1G6Q)Mj}MpH|3a!A$r8i;;h!Qk_ia43CM! z#96VBeo+5Vb)i4px+-Nz!Q zwy%|?V&9Jg_x{M)6=YGAGo=!Eqi}b+m-SB`PSs2IVllZl%*^c!F)r2bMPy%O zR?k{U)@O{@!?nu{3fd0>e8m*EeDxsP=C>o-Hq2eeNLYwT7T%Gya7NW0d!K5b$>A{B zDV3>1bnMI*b&RY0v`0lQp8%_LaSgf7I3~IoGGC~Fe+*AeWUnoYRrP(Fm^o#3969oBhY?qb1>Z z#7|Qjx{hx)!UH*N zuIDfdZxUDSoGE87RMNg5d$vmatf>l0?9#ZPiR&9pqz}DX79ULEE)S*@&DeKIGp)qJ zR=`*xXl#cP)N`B#PWqkgN^uWZ`aUzXU^3!4yXUC; zi@@r$BSqwoF(iAJxDB`C{M2ysGC_7HuptU)3K{uDq7gtFY$D10RVewhq9RCMHQJ8d#HbfvS0zbrJLrQvcAr8An$J}M;?6dTZ` zG*f*oo!xa43%JVS-HYvaGa>kG#aZmZ5%*OO-^mfG=1E4bII$F)H>vE^w7|E(QPkgw zFVI3V;q}Ed%?}{kOJE+;z0nDQ4LI5lNK!!K;P4K%oWS~MU9TmX6{$U+vu?Sa(}!JK z3L@~DtPSQ2{h^7Fn~!8EMka#JCJo-Z-(?o|Y9W_4S0GfsZ7^)GX4FAVDoq&p2cs6%(^=6q6$fWAz;c)(|JZ{boi~(sRczY`6AG!)6-q#i0BZ zGVUEi!Ddv(#!B2mj6J^4z;tm)hh>rP#V9I2FKdMiooM%TQ_U0e8nHhIE+8{ z2#p!bUq}MgrC$c^vUu2uiPh^-F?lQ&gp;wM3-Fm9FNq3Ammc1H=Q(0Z=8i-1MZ#yI}Hv-+s5+60b()rVWa z!Y+Onq-WFQHV|-NYcP=2xkm0H2Vauv$Nx$YFNmy4_C`D-`?cv){-YX^PkO4`smwm~ z9$Z&_Z2XxUeh-UB&loZ?nY|~4RA=^NU>-fByGT`peg42a6mBx24RXqVJLyKnW!7|2 ztSW3wF&!RQwAzl0qP2w1!ba0qP<>N-$|J4=rFDo*CBRXt()D8@&bOU#@c0De>JlL^7z}M3U-%)_K`5uLxLv0Pm;2dli*{^wp}8Y6|b5 zuvaWlHyEstB1~*z*ZnM`*y??J1@J5X*v)vSvG{o7a+Ih!S;XKt`8gquPnf79{XN3t zMYU_e+V)JoabRYv{@SdG6t}_kSS#3;q!!h3u>(+nJLBG0l^Yhl*0&@0$@F#eOsnjJB%KGh11%EL9_u-GtwiqIbAO-4J6pW& z)N1~MaV(N}5?3`nfIDMWoIC%eI3i@nnOay0?=Zg8R#M@e{&%%GGe4?}7;z%LGW$~k z2}6Cc;%=i^w)F0ecdt>ip@GbZ&Is4obAo^XWE$)2(P=4P3D2Sl|Cu?6bthBn`N`Z} zW6hJFMs-Nk1+2jO+pCFZoF#3-4{iZk?#8`ANuD$*+mPKEfJa3{shVY;#cKM1*kC}c z8_kZf5hXDiU~0VTi;6plDV;esfEZvq=}2D&lO4CcM>evun>A9kV~AepkqugGnz7)p zVd8sjfmTpHtrxS=HhVv1Z9ZD3e%swea3eJ&)!NP9b44eGO58lQH(=uQ^;N;6PKL6Z zH2@Y1`Krz6x%+?<7|C$AZ_I}Uk4Toq%`t+OY$$QJVzFaM#%y)5Hx8sw@A7qFQuDxohAQ@8>P5xaU(H1$N|nkzu3q7GDRmTZ9J*-G6(3}=Ch zbHLpTyEFf_EWnDR%w&Cqx&^#XUP8;;rkY}_|TZkYz;y=nUT(1my%iP_M**4NKW zbez!H+&U!SaNf01meU2dpv=*?oOlcVD%@YMT;*ri`Ot~lt+quhNmwUqdm9afqW4A; zCo|3u%qYR(wg+aH$0aJ{F6+Mt15P@wvYs@qz0dwIUzPF8wV=((uORXk`hlhAv6&VH z&p-R7t$RlYg_)@};;SCwsrg&t{OGc}oYQ!51)TIQK6i@tM=kgR55d38d;xf=U1!eS z0<`>I`Scz=ihQsdqK))9oxw`=$%W93*#%=lk2iAD^RdOw-bKkhfiHKU4_LQ!K=Pq2 z${Bf0Z*v<`CA0}dF2;Syx!)Ra@w>C9E|{3)tSx&DJ$*1QYezBJG2C&zE@A(uFvsm0 zG+X#$XzYAtZPd*etTY@K#Xtr0QK<9_bI9Lkqd(J~6=xZ8~tO?;GdUS?{>|AI{O8F*0=Zy9eXIt!xy(W}hS&k>8Md;b%0N%0b`U0 z5h0%UoXJze0Lq!L6BwqBB5mI+4wA%O}7WnMxa+A6QJAVxB^Q_4<;=`-K%o z`yVb3SD}Mz`1e))n@wF7y>>yVn7<=>WxZSu%!C$hg+qN~V{mwORp-pckLk^!n+RBf zon<`evz7E3E<(46Ib#t*Us(NryI9&Z&wOh@Dj{Qm|bmcC18pJBrsC;>C(;#D%$ESMhG; zA*PZt(vw(l7CtjCG2yvgCB2HjEdFIPzXaUMSPBF0fB8(ma?kF>(IX(ReX2 zsv)*=yvO180E-FG{S@fENv?e`U;#6AQL(w8ic>1*_VG_@a_>GM8@fAGJTz|~bJX>< zC+@8l4%6Ux!&9~j-f(cw^WWiFBMD1;_r^DsnODd?3$l%PJIg%#)v2L!oAHcA;>46T z;ZjM=gaR=ua+scXdc~?`l821HIF$!kE@`9hMRVg~QmF98h|d@~WdF1ruCr=E;~lp18C-@#fmMnX^#rDj!>$=a5AE*Lxx=Q_r3 zJG@pi=6*EN9h96RT4R?E#`Y(!aBg&~PBVB7#o`e=rpS$9mrPc7nZ6RC)Uf3H&?INC z4xC4<_m;**VE57f@eWv4erYjw3Gvh)-W=i9T!{n!#hr`^9Djn;Vs~{^wRJxcf zDw^D^tjMzsN~A6M^sDQ`9``!sMwhzB-IPo> zGuJ}ZKV2=gb56l2|vD!DU zXAa0HY)~cBSjELThN}5YwPFUJ7@JluuNMj@wldQ`DKdc$+K&kmLe&%W-If`P9l57G zu=uiuyBfzuL2GUnCr7A8`R`*+k-1%w`!A&sOX;H%h5Hz3NK+0MwY9CoEFmWpJK~Dz zalm3aS61QpCDz`hN!E1bjeEW4Y||>f`b*Hz@iM=S=}DGNIVYa~=e*!vgxw4&T|d=U!&7rt(a_ymYxKQRW&D1}pv4?{?2VgyU)c6lJt$FA+UbPXoGW zIJRyD0BttT0B1i`@Y-^$qdWDE;*^4@Sk0Q8ITl?tJA!)ClUvMw4&5JlQE36v<(~%( zonR=?t#?TC^@y%zK%?V|zrGmYPod_5&+jB~$YUhDPbXsjo$k1IKM{?ca2Wh7wHL?c z+IXtn>St(_?EZAPs`jRQX0YMhhe z?%0-zxOXgxbjD8kx4&W{5SMi|*v*?#+9B4U>gejPV}=pho6((s3@9lcIEpbHEt`Lf zy79;^OK9o_r8mKlGwil|YV@!{F)|j6U?IRdj2?E$e;h{`7~~u1-jWm%fT%PWO~~MG zSKiZ=0M1qgoRu6DKqXadhCjh0+HdTzDQBtc6Dojf3auqK5~#XrzQum>X4Pc&m_>!n z5hHp?jH6b2sj2b#rpb;^61V;ygIJ(v`3;0YpE~MJ(Kf$PElB5#XV*6Iv5xz&^iP-8 zLT8J#k`9s`DW37jxvfkPZ1b_1ZAwl>3M02TOLJ_y47EWc%~#n)?9)VOKM*06^xQyX zAr4~4$Rb>|#Y}{RsQOg|X=caQ7gPf#Lyq~@_b*^e-WEfb6d#mt+Aa1QFe<6cgW63& zmkMboPV8G=a=(a67mR(LiOBAW)dvfhQcV<}2#|P+=sok)vc1lWEk~aj0NkIx}06-*4y@Ccj8;af0?_Ups za8+~EuW(OR7>j!Uq;)x&Gnd;rym9|WJMZXVQUgeX9nW-pt91uopP{98`FfLAb> zRY61aF?D$Gq7n!(a)iIqsd7A}V49gz#`V=^oin&lhd)lOJZ0dEJog}qJDRAmd4-07 zir@_==d(+eoUUX0vn$~2Ab+R2SCS_=uM88x7Q={5LWOzTD^kw4<`;KFYSi!?fBk@? z77oi{m$f(L_X9--zboz~9t3p;ul?H0lSgeTdw9Bq&V&wq3T;fzx`qOPR!eutXEwPI zw%(0|syz!{<;%$#4O_<7FFMedeI9;gJEX>aVKMmgk0@h$OT<#cSNKi5kp`r6dW2x& zxTFZR9T&X8M4$BrgD9Weo1CtThF`92Rv?*E9`xzwAgs>!h`Dav3qtMlahsrB<-o3e zfSNNy+1iC-6=`wOOfM$wQgdw${L!0IaXz{5{cfleePgA~(2Y1-3Vxe1K`JGRAV-~S zkUn8_a$!BTZtrWe&G?rWFdYcF!^xMmP#P|f%SG)lbWyc+KlNiH1*;((QwXBw zd@?C@e4*beq=ZBr#Q6nAw|iOOMnLoJMj zTsXe5vvfikc4n)RPb{*SHCBRRFIlbdU+Se?1IAl13qb9p6H{$XW*-dTl8l5)RBsWc z&ku{yX+sh?4LhQOpe7kOf7+`Iv>p{`9U2Ac-g(r{XcT$kb7SAn@*z1DLaLbIvbq2!P1{ADvuBtFFPEedYOX~Okye7CZj#;@KkrLrVgJn*q`jsD^gBrrwi6C zfTu}cRNQDw`t5iDk6UqIX*gGlcXk}7GKGz+T2Bo{a;Iag1gtCZuTFmWz(N#V<8~^? zTl!fY&R_Mw=r^MBPlg-UMku;IYOJI(5-COtDtN3%$rV^t#vYoTQ=Gw`gJ4KJh+1Hy zf+WzTX^DT0`fSMLGyS+bD$V&N?}El|(FpiAez0ZLB>lUX6500t&$7n;e^qF^qz7=A z9AlG*&F5aN7_~J%_u35KDF|hAr{xccK4vr^KJ;d5R zA0lpc&Q$;PtBUmFp{UfdS!-rxh*m;fn-9ywTLgS-8{SDrU@%gpK17^YjNhp2BpicO zJI*E))%+Y69|v_Tm|B0v`FGV<6&#PRIzi1j&buwjGhWSWtxiN9sN=Cf^EW*-QQ>>a zLOiYe@q!cW7qg`XMc32`J}E*x6A-6g@W#N{aJJxcV#&(87i66;qyO>OF7IG?F=)nvl@`R@r{i2K>&}f6jswbeF6vAP|JfcmkA!8Q zn*kw@G@4Ss&?%c26~^p;DBV z>QC5Hik}11cpV58$*;NS%f}K!H)zQvkXnusKn?O!OK*8`mjxWY&ho6{UDO(+Zf$0h z+EHS4ZGAv@IFnd*CQu_(U!SkC^31=r!3eM`(NMfkHa; z%rU7panXVmp0)VGkhZcZ+WqSOqtvNbkH@CH55=+dL84d1P-Y#NDk8L07$br1ownVl zr=lkz3pUv&!HNS*eQg6v39-qwHyjPbUY^-A*D3hsOpx}N1gjxq8AdLzl2lKe`JJw=3RJ=CJ9c#1hqh*qweb2Uem%JgAeb%cD8^r0OLJ6Y6Zi3EOABs`pQ) z{~qq%=^f$B2KK)0@A696k73o`qZ##_I81ucK)E^o`b^-ODc^Lm%@k~btG>eObL@#H z;kMTW+-CVuTXy}!LPHFcUBA2LwUHs}kX61-8`6vq!O!6w@<)vC-J3sq%E%X(=}F>j z!&AWJKWY3DMXF0M$!9L+)wT$u;R+hosMKB2$VUA!6=X;qyr}xl#6c|5VCB?haPq^E z`qxu>POhK}Z&7S>`Vf$&p2hL2V56XglQpd$6-Z@7)Aue5GO;fD<^0KUud4jefWCAQ z?WD8T>}*!!Dv*FhJUT&lwQNF$7`vjfO15tmEEEos!Z+Q!j%ieRJjAPiF_Pjkk?2Ie zp1HpJE7Awqo^@DSrnIQ&yF9xuQGBY!Qn1vCqw)L%FojG#U*X#I>8>F3D9}8DNNIly zxhX0S6gX=ZC8Fgi*8+)ogEk+wdb9XxSNB8!sc(2l=3DFv?=KT}J)_}7^2^aTRq3M}{6WK~HeT8N! zX6r`aYG)j`#xm*V+SXIwYO)2#uqvMeoY^bl=|!1{QJ)T)0#{>cKA+TO1+VHFq4LIu zy$SqoD|uq-ybr~rzhAqXO7>>!=Xd5@!uF&5{g5spUcMQ;)fu~@<1o$^d{FUZW>w== zukoV6a6Mj^0y<~a0VN+iUJ$&2B<{$;-mAC;Y|?n&n+1A;@Yy{ww^)@h6KoJ)2r8CN z{FW|?7oo$T=T4qd=PTjo*}BcZ=@Z@E4p67husD-5jnTF1X%Kz>``$aUvpSe##O8ev z$|Et-rBS>Ks$Y#D7%}xM*U7#3%@B>kxCY^6K}lXyA|a;CWupmAtcnyu z3Y6=rSP}fVyV4qmW-vG5!R{WtpomM~g>Yn4y5s(d6uvxbdD7_2({~-#f}PFT0$rmfEx1BFn1fT$)HvGTrJkFuD%> z$JM?=DD|Ws46UDE;a3sPF0kbUe1RVJt7G9zDZJ}05b`SoxW4c1X=G2a;>~sQojv%2 z=a)Z1(R6z4S5=Uv2J_op;>}^5VFA5qV#AnswDcS~D_!KgSw1KAE$S|^3eBcp*Y~tx z#c`)%US*fCQ37WQaF9n}IQt9}a8Ye4Oo`*b7aZ=>Ys%s|TzIEL$YpNf4{OUtK|wZ$(C(*DM=WS?#5g&ck5y9g7rOVD*1TMW z;=BD7lSIn$ckm>aqWMtmFY3(hHA+o8K%neo0$8fD^&aKaNA3mo4N@Ss+;tG2Lp~V{ zLX_mwdzJ4Q<4Tiuo4+eG1?*|UG%!)Cghm1K;?#5?IJCZ9;Zsxp5fpTvH_52$d? zfVH{v4L&Ni&P%N`I0U1Q{xa}m-gX`_W#Wwp73;iC!e=R zM{n+$godu*X&q4?nZa-DDs#FEYLHB`vLC{zHsjS{fPfsufSach&SRJ*hFPXQ(#bj7 zMb{ybWT^~qy0G99mE8r&E<(|u(ajh=`)vTbGe@)QU|UN5g4PCv%D(c`MI(+oM#7~m z8`8~hH=7ivhyjgKp4hlE|Hwh^j=A;3Hd=XpkD!SK>*jH-2p46ffq|QAIWz?A2 z!kZYixyQw+$i1a3E~g#_PRud<;>?*J=Q8RmKq0QR#uz7lEreEUDB$&ppJb4GbBw;m zP?&0Q(}^WjOsemTk+%|W!UlbG&1R0ml%|dn8l-H+ruU{3QU+GTDtqaXS^fUlo@GB) z#I&G6>A_OI5l?x;%PvYTrcML6e))V|BxgAk<8C0@Xi2d@!i7poHeBPLQfW?yqRbzh zs&Vg)ni*}zbQf@x>*=xd5|Ll=Ah7ZMW0ed;=L2z{_(V)dRj$6G6a&u7wmpu728%)V zCk}C#Vz}R0h*)t1Ha`&v^lu0`Lp47>JHhbn(j^jOHTNtke9ayBqF78ght3&$(r=*R z?j}e$k1XzD@dNir$<9_}p@*}Gm1k}~2GNe9kEO%nFYH-;(5Qq~Yz85MwZms>jDN7e z{O2yOhEp!CYMW@Wa4M|ynB&8Vx>{t}O>Q*y`$g4XL{K@n??S-3kZtqY(n%Zv>9wxV zuV>#xlWIWX3MN`pDIU-C*JFwU+&)YLH+&RNePlPn%IdymayxA3R+*B&?+UVNmg>Dq z@Z1Ll7QaM7^8Jho4nTZ%mQQq7ND9L1J&*5wx?W)IR|M&YP;QE_)mS$1&2eH)3YZo>i7qO4c z9qXz)16>2AwRrK_>M~HhJzNzxHUq;f#Q>jFAg;I9l58nDpi#fTyCB$?P^~46fCqc( znf)R50m{6ONhFcg0}axrVl)d*L?Az$7}V7O+O@-5QoaWDeOUmapm%SA|9A(IC;8)1 z>M4aH)eSlTqryz^Z+Ulvmw#;K6=#R=kjGWR8f>K=YJH=$)2ba)JUUtGNIB`wKoTMy zwe_)O8iI~EmMJ_!Xu&1&Z$tX0<0^e{B9&*ph}0TWrj+Z2k(VWxQaZD?E z@0)tk*#9PmCMEP&T%$^*dwG(XriCeXw(DJYrF0k=b({$Aobn}l) zdQ0RL>BBwv{uLx@p)XYHrR}eimzW8hGeMkE0|3y$7}nkj$lGSEm^ zG3y(Uq6&H-+W9byKH}}isO*!HhU|{whyFEz$|kKdM?Xx`4N7mkQ$r>{=jWu52Oodu zy7D163Mdj!lxJ#Tx?NIQ2E7}4L?`eZAFN6|2wMQ=Uz={NtTTOw(!s6rDxu5lRC-@-0~OeHigGlQ47&+OA3C^+eq zl8RL$a<=1gu%86t2ld_PrnUKJ3i&7IRN0y|Q2*)_Okx+m`8?aC7N2AxIKov-tc{~E z-zF*!kLKH%Ja9WE?&PU|x&2wZIQC(Rl(7z=p+k5fj4fzz>yKJgd0}PJ7^t&cFr>-g z;8intdZxk=w12bdIQcDXBTiqRG6?V7N3m#Hq0uFD0qbQI)yc|uJ-J>VT^aJOhq3;5 zua41Czv#~9Oz4ZX*#S7`z!l{Tlhq6;?q>9(1e)oz_-LjJ5J!sROYoF-TGdoYockIr zUY&L?mA!v*wOZ4QJR5Cp9qrkB>v^#%K09e_uXw#Welk#7KiW_PG}7rxUd)nZpBu-B zZ~ZFXCtMVYRcT#|XYW0Xk~(dTQK|~wfmBVei8#3ip2q{q(!H>dlfLa=H-Bzy1Am@n zQkR?-Hv95LIfrb|$naJK*lGqpDw&YDKPBj;`6z8(|E97XesrNNz z5kREah{-8b1~^egHBFF+s4pjV!=9<#2GM@=BBp0@->Y=3LS~fg$U$REXWPpHBQJeI zcW+ZZA?T2vI8WaS{u8V;DWaiNZc>%3!F3Md6MlfJoQFYl@SqGbDn}zIY?4fV&Ba0L4?mbs2Ryxw6`x-5OGkQpD z3xG*&FKEFpC~R~s*TrN>9OSW?w9c9^h-R@LT*ooGef%`sUaeDMi1~vvvD&(7u-aRD zVoR#ZlLR&Zqu+KrhU7W8ee2J*Qr3>|z`n=y`9w=D02?+iJ!8EjHiP*P8kSuiqX)$t zM~qmcXu*jAStS>>1ly3FK#zVdw6<%OppDcg0HbHNL=roT@B=($I!vN`9V;xV^<558 z(W3~0Xt#wBdxo!&;3PWfFvI$Iiq_hq)bO%{jop^kqLLQ&*;I_pMYW+c=H=W_aRUhx zzXh<-;vGCOD*NjrYY!c7-C3@R%TGG3hu6NYCv-dMqpV);q+NYHDyD?`#d(w`eo^ zXL>}3zYq>b-ykN@n7_MAK)5pke0+0a?$>0U9#7uyiNAZVT!9sLC$(LyIfA*kvzsB8 z|FPyttK*wy1gi&gDm^2}WU|>6dH`(IQZUTgG4`~HawgNiUhQTmL(8u&Iz%!oUgBfF z>Sp*-rVmz%I!-o$t{V}O93n@Xj5RH_rL(OXFp-?PzLrnoq--spc&lq##{Z(Uct=K> zN^EKRrAx|&3T+f$(V=m@T)ABA5m#VyZ~{JpAo+s|Dcl>1%Vs`>M>-<1G-R9YfajGZ z=59ol3_OTQbh>!pyFvL2-P-=r8-H>Pt(XHrJ50d{S~+fyF9h${>2_$*aPe!!_wF7tU7%Q3NL1=Q*o!xQx`}$JGM|F*N`hvIITX9MZ+zIn1z;r` zF?5p&ZS9N&wUFT4;Pcg@iWBmaXA~k&6YNP?17$*vCx>m0Im!8FjMOnV6fpu47OPZv7_2^@ATCOJuY6^+3Kw*ycAPh zc`ThPe(%2OU_Q01N}Nr*rQXXpaJb;KL+-r}#Pam~NrlUI%=m#yTLsqzO$B-;{m%%h zPj5mmt7M$4ZuTr^7Tzs!S)T*PsmQNNR-OCAplM%AdXZIvM4h7jaG+)5ahHc!G;CHv zxY-JypIv}w-}Pu0I$@AS=EGSUyI(~XUiQO*-EFxQ)3aG)4ocas3ws|>FV`xLebrtE z^c!+>Bil9PFZ6v+W0>=JRvmy$MSOu|HMhr1gOyGL@~#9e581~dBxh!ikb$a=E9|R2 z5p;BDgV%<(1y~KiNgADWQUWgeno7-v7lpfkmwoR?VGQ?hA8S@iu`n=>vg+U6ZZUNJ z;D2i*=W)>(a>s((0Q$YWxq<>w6^7>UhYZgzj+Eev~_zj$swYEJH;G#ESdvnds4@QLC*S|AIjGH_#b+2mJp* z)Bmqx?}C>L-99cSDb+!s&Nth0@_`QDYhEg=@jhmu0dooku;ZJjajRW>w!eX#B2cVP z8UL&lcBA2M>ARv_9L5~z_5Hg_SW|-X96@&_r02ITJMS^WET$805n_ojS|V^uP~6`% z;@w0~O5Vk5%iUv>wamb(x9y9QWy`NgeDWJeTA|gFEw{{IG%$2L9=F6k!cYX`ykvk& z;mcGL+3L`-qP3^d8^-t)2IB*>) zIy%_d7R2k*t->v_i7<3WgL4uC81Yl|X<0z%)$6L){T`}Hrf~_%x+Z;?(AU@Sla_ST z+iqdEDUMW+Ck1@EgePC4%-DKsCrr1Mc7JAUWPMUJym@-k<{qoU_~Uu_oUN$3zPO-5 zCxHlHr|*2ge3G<1#t<}Jj#4Ua8@8?$E;LcVNbrk>YU)o=5!ERw66+K%_!iq?QBCSK)fWLuCr1sc#E`G4 z-cJ8~|Ds#-9_2#+m%v%^toB@ytAU`*c~-Iq&uUQ`g@713d837t6W>M=^_juR2~WrF zutYaGmeZnNFmB5Tle)Ii*?bX3ZgmlhkNSNUbZXYBwUHJlTY=>0n&FO;({F<|e;bKg z;CN*RpWjFO#x#iyu(7-O90B-+evhWw_d9a zV{K;_AFZtBdV|BQbU$~R+gx|-ywQz>La6*SET7EP`cTfgmF^bCmb7I5QhdSLtkUnG zZU{ug1a*gnOXNLzmRdsDxZ56_^z>{fE1&uS0Eg-MQ5jZH96eL`j%1r;Jf#d8BSl*O z**YqN&X^E8l_mo#4!V0zdMtWo$?-u>)IZ$VFb+yvNm6}%Mo|Su<=s6AP3)Xw#O(Hx z)AVH7qm5riZ~lO8Gf;$=i!Qmq77HT_KezsA@6+wDgs$cZqKZ@qJdh#}^ zovL(p%D0*daw?%N%8QZE<7F{KG4CM?R%**G_;6dw{CI0Vj=ePDA|*TBJye6u^6dU9S{!mc0;JNg7o9FOeNA;FoaJhO z-+oJQUrTn{R@=N=qZ$i0W`E1U%W*A1r_;KCA8_a3;o6hoVj`oQj z@SHEz3pxl%DmxPNUbWHS#5J~GuVjbj9WlU;TorP=1b8U$9Kl`1=I7VB_`B|APcrF)a!uJ!MdwZ#g z+;tvQAAFPz=b$}{B2%L9aua8y#(2}9pk!wpW}j$uw-y$Xcg4kSq(ExS0o;oU&8{5;yNFMgO8>quWe3|&RMAL;!ibM#D89dZjtltc4y~SrH z(fUhaXx~OFf15A-Gs&lU_txoX4n(EuN;B&8L=ai_6s(tJV%%=p7A+3i$9f!ffMYR~ zZ14vXP3>EUdjC!BmdSi!Utp4!q4Mt*7ERvYM5ZmGau}eVds=rH3&ZZ~e&`m$vm1(` z57kw8&C2+D8@=eTTUS~yXx2OE?DAOgsbJ~5wxTc?cW!L*u4kadyx;yJ%)(GP?3NLl zw}~+l?Pb5Ws3W(r6g8^$N4dJMvUG+~PtX7yyLvcs0M;!E zxb}jRQ8?|4MpFTfU_DXA0U6-@0hNYK(vX)cp>cRKs6X{zvL>p8k(l|346h cYpKC;r0VcLr9Su7T2?+_Es)~Xx2?;3z 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 diff --git a/docs/images/troubleshooting/clipboard/toggle.png b/docs/images/troubleshooting/clipboard/toggle.png deleted file mode 100644 index 32060dc7f9e01dd447d66db8b6e493e47997e3a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18725 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 diff --git a/docs/images/troubleshooting/clipboard/toggled.png b/docs/images/troubleshooting/clipboard/toggled.png deleted file mode 100644 index 6afa0ace793db75be3e30184f2a2a2d96ea9b4bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17312 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 diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index 4c97511f..00000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,37 +0,0 @@ -# self-troubleshooting cobalt -``` -🚧 this page is work-in-progress. expect more guides to be added in the future! -``` -if any issues occur while using cobalt, you can fix many of them yourself. this document aims to provide guides on how to fix most complicated of them. -use wiki navigation on right to jump between solutions. - -## how to fix clipboard pasting in older versions of firefox -``` -🎉 firefox finally supports pasting by default starting from version 125. - -👍 you don't need to follow this tutorial if you're on the latest version of firefox. -``` -you can fix this issue by changing a single preference in `about:config`. - -### steps to enable clipboard functionality -1. go to `about:config`: - ![screenshot showing about:config entered into address bar](images/troubleshooting/clipboard/config.png) - -2. if asked, read what firefox has to say and press "accept the risk and continue". - ⚠ tinkering with other preferences may break your browser. **do not** edit them unless you know what you're doing. - - ![screenshot showing about:config security warning that reads: "proceed with caution. changing advanced configuration preferences can impact firefox performance or security." lower there's a pre-checked checkbox that says: "warn me when i attempt to access these preferences". lowest element is a blue button that says "accept the risk and continue"](images/troubleshooting/clipboard/risk.png) - -3. search for `dom.events.asyncClipboard.readText` - - ![screenshot showing "dom.events.asyncclipboard.readtext" entered into search on about:config page](images/troubleshooting/clipboard/search.png) - -4. press the toggle button on very right. - - ![screenshot showing "dom.events.asyncclipboard.readtext" preference on about:config page with highlighted toggle button on very right](images/troubleshooting/clipboard/toggle.png) - -5. "false" should change to "true". - - ![screenshot showing "dom.events.asyncclipboard.readtext" preference on about:config page, this one with "true" text highlighted](images/troubleshooting/clipboard/toggled.png) - -6. go back to cobalt, reload the page, press `paste` button again. this time it works! enjoy simpler downloading experience :) From 71c3d64331a148250510dd9837c198b8a4b24fc1 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 17:45:37 +0600 Subject: [PATCH 11/42] repo: update contribution guidelines --- CONTRIBUTING.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2668242b..073d0fb1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,7 @@ if you're reading this, you are probably interested in contributing to cobalt, w this document serves as a guide to help you make contributions that we can merge into the cobalt codebase. ## translations -currently, we are **not accepting** translations of cobalt. this is because we are making significant changes to the frontend, and the currently used localization structure is being completely reworked. if this changes, this document will be updated. +currently, we are **not accepting** translations of cobalt. we're working on changing this soon! ## adding features or support for services before putting in the effort to implement a feature, it's worth considering whether it would be appropriate to add it to cobalt. the cobalt api is built to assist people **only with downloading freely accessible content**. other functionality, such as: @@ -22,9 +22,9 @@ when contributing code to cobalt, there are a few guidelines in place to ensure ### clean commit messages internally, we use a format similar to [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) - the first part signifies which part of the code you are changing (the *scope*), and the second part explains the change. for inspiration on how to write appropriate commit titles, you can take a look at the [commit history](https://github.com/imputnet/cobalt/commits/). -the scope is not strictly defined, you can write whatever you find most fitting for the particular change. suppose you are changing a small part of a more significant part of the codebase. in that case, you can specify both the larger and smaller scopes in the commit message for clarity (e.g., if you were changing something in internal streams, the commit could be something like `stream/internal: fix object not being handled properly`). +the scope is not strictly defined, you can write whatever you find most fitting for the particular change. suppose you are changing a small part of a more significant part of the codebase. in that case, you can specify both the larger and smaller scopes in the commit message for clarity (e.g., if you were changing something in internal streams, the commit could be something like `api/stream: fix object not being handled properly`). -if you think a change deserves further explanation, we encourage you to write a short explanation in the commit message ([example](https://github.com/imputnet/cobalt/commit/d2e5b6542f71f3809ba94d56c26f382b5cb62762)), which will save both you and us time having to enquire about the change, and you explaining the reason behind it. +if you think a change deserves further explanation, we encourage you to write a short explanation in the commit message ([example](https://github.com/imputnet/cobalt/commit/31be60484de8eaf63bba8a4f508e16438aa7ba6e)), which will save both you and us time having to enquire about the change, and you explaining the reason behind it. if your contribution has uninformative commit titles, you may be asked to interactively rebase your branch and amend each commit to include a meaningful title. From 6499d079ef869585d4687b6d9b0eac1a218b8f5f Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 17:49:37 +0600 Subject: [PATCH 12/42] api/readme: add supported services & acknowledgements --- api/README.md | 103 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/api/README.md b/api/README.md index 05664321..38104626 100644 --- a/api/README.md +++ b/api/README.md @@ -1,13 +1,5 @@ # cobalt api - -## license -cobalt api code is licensed under [AGPL-3.0](LICENSE). - -this license allows you to modify, distribute and use the code for any purpose -as long as you: -- give appropriate credit to the original repo when using or modifying any parts of the code, -- provide a link to the license and indicate if changes to the code were made, and -- release the code under the **same license** +this directory includes the source code for cobalt api. it's made with [express.js](https://www.npmjs.com/package/express) and love! ## running your own instance if you want to run your own instance for whatever purpose, [follow this guide](/docs/run-an-instance.md). @@ -22,3 +14,96 @@ you can read [the api documentation here](/docs/api.md). > [!WARNING] > the v7 public api (/api/json) will be shut down on **november 11th, 2024**. > you can access documentation for it [here](https://github.com/imputnet/cobalt/blob/7/docs/api.md). + +## supported services +this list is not final and keeps expanding over time. if support for a service you want is missing, create an issue (or a pull request 👀). + +| service | video + audio | only audio | only video | metadata | rich file names | +| :-------- | :-----------: | :--------: | :--------: | :------: | :-------------: | +| bilibili | ✅ | ✅ | ✅ | ➖ | ➖ | +| bluesky | ✅ | ✅ | ✅ | ➖ | ➖ | +| dailymotion | ✅ | ✅ | ✅ | ✅ | ✅ | +| instagram | ✅ | ✅ | ✅ | ➖ | ➖ | +| facebook | ✅ | ❌ | ✅ | ➖ | ➖ | +| loom | ✅ | ❌ | ✅ | ✅ | ➖ | +| ok.ru | ✅ | ❌ | ✅ | ✅ | ✅ | +| pinterest | ✅ | ✅ | ✅ | ➖ | ➖ | +| reddit | ✅ | ✅ | ✅ | ❌ | ❌ | +| rutube | ✅ | ✅ | ✅ | ✅ | ✅ | +| snapchat | ✅ | ✅ | ✅ | ➖ | ➖ | +| soundcloud | ➖ | ✅ | ➖ | ✅ | ✅ | +| streamable | ✅ | ✅ | ✅ | ➖ | ➖ | +| tiktok | ✅ | ✅ | ✅ | ❌ | ❌ | +| tumblr | ✅ | ✅ | ✅ | ➖ | ➖ | +| twitch clips | ✅ | ✅ | ✅ | ✅ | ✅ | +| twitter/x | ✅ | ✅ | ✅ | ➖ | ➖ | +| vimeo | ✅ | ✅ | ✅ | ✅ | ✅ | +| vine | ✅ | ✅ | ✅ | ➖ | ➖ | +| vk videos & clips | ✅ | ❌ | ✅ | ✅ | ✅ | +| youtube | ✅ | ✅ | ✅ | ✅ | ✅ | + +| emoji | meaning | +| :-----: | :---------------------- | +| ✅ | supported | +| ➖ | impossible/unreasonable | +| ❌ | not supported | + +### additional notes or features (per service) +| service | notes or features | +| :-------- | :----- | +| instagram | supports reels, photos, and videos. lets you pick what to save from multi-media posts. | +| facebook | supports public accessible videos content only. | +| pinterest | supports photos, gifs, videos and stories. | +| reddit | supports gifs and videos. | +| snapchat | supports spotlights and stories. lets you pick what to save from stories. | +| rutube | supports yappy & private links. | +| soundcloud | supports private links. | +| tiktok | supports videos with or without watermark, images from slideshow without watermark, and full (original) audios. | +| twitter/x | lets you pick what to save from multi-media posts. may not be 100% reliable due to current management. | +| vimeo | audio downloads are only available for dash. | +| youtube | supports videos, music, and shorts. 8K, 4K, HDR, VR, and high FPS videos. rich metadata & dubs. h264/av1/vp9 codecs. | + +## license +cobalt api code is licensed under [AGPL-3.0](LICENSE). + +this license allows you to modify, distribute and use the code for any purpose +as long as you: +- give appropriate credit to the original repo when using or modifying any parts of the code, +- provide a link to the license and indicate if changes to the code were made, and +- release the code under the **same license** + +## acknowledgements +### ffmpeg +cobalt heavily relies on ffmpeg for converting and merging media files. it's an absolutely amazing piece of software offered for anyone for free, yet doesn't receive as much credit as it should. + +you can [support ffmpeg here](https://ffmpeg.org/donations.html)! + +#### ffmpeg-static +we use [ffmpeg-static](https://github.com/eugeneware/ffmpeg-static) to get binaries for ffmpeg depending on the platform. + +you can support the developer via various methods listed on their github page! (linked above) + +### youtube.js +cobalt relies on [youtube.js](https://github.com/LuanRT/YouTube.js) for interacting with the innertube api, it wouldn't have been possible without it. + +you can support the developer via various methods listed on their github page! (linked above) + +### many others +cobalt also depends on: + +- [content-disposition-header](https://www.npmjs.com/package/content-disposition-header) to simplify the provision of `content-disposition` headers. +- [cors](https://www.npmjs.com/package/cors) to manage cross-origin resource sharing within expressjs. +- [dotenv](https://www.npmjs.com/package/dotenv) to load environment variables from the `.env` file. +- [esbuild](https://www.npmjs.com/package/esbuild) to minify the frontend files. +- [express](https://www.npmjs.com/package/express) as the backbone of cobalt servers. +- [express-rate-limit](https://www.npmjs.com/package/express-rate-limit) to rate limit api endpoints. +- [hls-parser](https://www.npmjs.com/package/hls-parser) to parse `m3u8` playlists for certain services. +- [ipaddr.js](https://www.npmjs.com/package/ipaddr.js) to parse ip addresses (for rate limiting). +- [nanoid](https://www.npmjs.com/package/nanoid) to generate unique (temporary) identifiers for each requested stream. +- [node-cache](https://www.npmjs.com/package/node-cache) to cache stream info in server ram for a limited amount of time. +- [psl](https://www.npmjs.com/package/psl) as the domain name parser. +- [set-cookie-parser](https://www.npmjs.com/package/set-cookie-parser) to parse cookies that cobalt receives from certain services. +- [undici](https://www.npmjs.com/package/undici) for making http requests. +- [url-pattern](https://www.npmjs.com/package/url-pattern) to match provided links with supported patterns. + +...and many other packages that these packages rely on. From b837f291b5bb8ce21a53334deb4d5afa0329b171 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 17:59:38 +0600 Subject: [PATCH 13/42] docs/protect-an-instance: fix image sizes, add a secret warning --- docs/protect-an-instance.md | 57 ++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index c95bf135..5b9aea1f 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -13,32 +13,69 @@ all you need is a free cloudflare account to get started. cloudflare dashboard interface might change over time, but basics should stay the same. +> [!CAUTION] +> never share the turnstile secret key, always keep it private. if accidentally exposed, rotate it in widget settings. + 1. open [the cloudflare dashboard](https://dash.cloudflare.com/) and log into your account. + 2. once logged in, select `turnstile` in the sidebar. -![](images/protect-an-instance/sidebar.png) +
+

+ +

+
+ 3. press `add widget`. -![](images/protect-an-instance/add.png) +
+

+ +

+
+ 4. enter the widget name (can be anything, such as "cobalt"). -![](images/protect-an-instance/name.png) +
+

+ +

+
+ 5. add cobalt frontend domains you want the widget to work with. you can change this list later at any time. - if you want to use your processing instance with [cobalt.tools](https://cobalt.tools/) frontend, then add `cobalt.tools` to the list. -![](images/protect-an-instance/domain.png) +
+

+ +

+
+ 6. select `invisible` widget mode. -![](images/protect-an-instance/mode.png) +
+

+ +

+
+ 7. press `create`. + 8. keep the page with sitekey and secret key open, you'll need them later. if you closed it, no worries! just open the same turnstile page and press "settings" on your freshly made turnstile widget. -**never share your secret turnstile key with anyone.** -![](images/protect-an-instance/created.png) - -you've successfully created a turnstile widget! time to add it to your processing instance. +
+

+ +

+
+
+

+ you've successfully created a turnstile widget! + time to add it to your processing instance. +

+
### enable turnstile on your processing instance this tutorial assumes that you only have `API_URL` in your `environment` variables list. if you have other variables there, just add new ones after existing ones. -> [!IMPORTANT] +> [!CAUTION] > never use any of the values from the tutorial, especially `JWT_SECRET`! 1. open your `docker-compose.yml` config file in any text editor of choice. From 722223f6d337304d3a464b8f9bce9f4243a69239 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 18:02:24 +0600 Subject: [PATCH 14/42] docs/protect-an-instance: fix image alignment --- docs/protect-an-instance.md | 38 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 5b9aea1f..96f3a309 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -16,60 +16,58 @@ cloudflare dashboard interface might change over time, but basics should stay th > [!CAUTION] > never share the turnstile secret key, always keep it private. if accidentally exposed, rotate it in widget settings. -1. open [the cloudflare dashboard](https://dash.cloudflare.com/) and log into your account. +1. open [the cloudflare dashboard](https://dash.cloudflare.com/) and log into your account -2. once logged in, select `turnstile` in the sidebar. -
+2. once logged in, select `Turnstile` in the sidebar +

-3. press `add widget`. -
+3. press `Add widget` +

-4. enter the widget name (can be anything, such as "cobalt"). -
+4. enter the widget name (can be anything, such as "cobalt") +

-5. add cobalt frontend domains you want the widget to work with. you can change this list later at any time. - - if you want to use your processing instance with [cobalt.tools](https://cobalt.tools/) frontend, then add `cobalt.tools` to the list. -
+5. add cobalt frontend domains you want the widget to work with, you can change this list later at any time + - if you want to use your processing instance with [cobalt.tools](https://cobalt.tools/) frontend, then add `cobalt.tools` to the list +

-6. select `invisible` widget mode. -
+6. select `invisible` widget mode +

-7. press `create`. +7. press `create` 8. keep the page with sitekey and secret key open, you'll need them later. if you closed it, no worries! just open the same turnstile page and press "settings" on your freshly made turnstile widget. -
+ +

-
-

- you've successfully created a turnstile widget! - time to add it to your processing instance. -

-
+ +you've successfully created a turnstile widget! +time to add it to your processing instance. ### enable turnstile on your processing instance this tutorial assumes that you only have `API_URL` in your `environment` variables list. From a58684f314b6a539e948d6423b5c6d00de41d4ba Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 18:05:50 +0600 Subject: [PATCH 15/42] docs/protect-an-instance: update the tuto value warning --- docs/protect-an-instance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 96f3a309..59c7fa27 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -74,7 +74,7 @@ this tutorial assumes that you only have `API_URL` in your `environment` variabl if you have other variables there, just add new ones after existing ones. > [!CAUTION] -> never use any of the values from the tutorial, especially `JWT_SECRET`! +> never use any values from the tutorial, especially `JWT_SECRET`! 1. open your `docker-compose.yml` config file in any text editor of choice. 2. copy the turnstile sitekey & secret key and paste them to their respective variables. `TURNSTILE_SITEKEY` for the sitekey and `TURNSTILE_SECRET` for the secret key: From 4c43a00e884b3eba06d9d2931dfdad3a6bae5a9d Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 11:46:09 +0000 Subject: [PATCH 16/42] web/api/session: replace writable with normal variable --- web/src/lib/api/session.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/web/src/lib/api/session.ts b/web/src/lib/api/session.ts index f7974393..f627b6f2 100644 --- a/web/src/lib/api/session.ts +++ b/web/src/lib/api/session.ts @@ -1,12 +1,11 @@ import turnstile from "$lib/api/turnstile"; -import { writable, get } from "svelte/store"; import { currentApiURL } from "$lib/api/api-url"; import type { CobaltSession, CobaltErrorResponse, CobaltSessionResponse } from "$lib/types/api"; -const cachedSession = writable(); +let cache: CobaltSession | undefined; -export const requestSession = async() => { +export const requestSession = async () => { const apiEndpoint = `${currentApiURL()}/session`; let requestHeaders = {}; @@ -43,7 +42,6 @@ export const requestSession = async() => { export const getSession = async () => { const currentTime = () => Math.floor(new Date().getTime() / 1000); - const cache = get(cachedSession); if (cache?.token && cache?.exp - 2 > currentTime()) { return cache; @@ -60,7 +58,7 @@ export const getSession = async () => { if (!("status" in newSession)) { newSession.exp = currentTime() + newSession.exp; - cachedSession.set(newSession); + cache = newSession; } return newSession; } From be7c09bd07e2f8e2c9b3767de0803e03d44889b3 Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 11:50:39 +0000 Subject: [PATCH 17/42] web/lib: move `dialogs` to `state` folder --- web/src/components/dialog/DialogContainer.svelte | 2 +- web/src/components/dialog/DialogHolder.svelte | 2 +- web/src/components/save/Omnibox.svelte | 2 +- web/src/components/save/buttons/DownloadButton.svelte | 2 +- web/src/components/settings/ManageSettings.svelte | 2 +- web/src/components/settings/ResetSettingsButton.svelte | 2 +- web/src/lib/api/safety-warning.ts | 2 +- web/src/lib/download.ts | 2 +- web/src/lib/{ => state}/dialogs.ts | 0 web/src/routes/remux/+page.svelte | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename web/src/lib/{ => state}/dialogs.ts (100%) diff --git a/web/src/components/dialog/DialogContainer.svelte b/web/src/components/dialog/DialogContainer.svelte index 993efd7c..363395ba 100644 --- a/web/src/components/dialog/DialogContainer.svelte +++ b/web/src/components/dialog/DialogContainer.svelte @@ -1,6 +1,6 @@ {#if $settings.advanced.debug} From 6933daf0463e44b406b304c1ff78a0e832ed1e85 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 18:56:23 +0600 Subject: [PATCH 19/42] docs: add configure-for-youtube document --- README.md | 3 ++- docs/configure-for-youtube.md | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 docs/configure-for-youtube.md diff --git a/README.md b/README.md index ca108a86..434b5943 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,10 @@ this monorepo includes source code for api, frontend, and related packages: - [packages tree](/packages/) it also includes documentation in the [docs tree](/docs/): +- [cobalt api documentation](/docs/api.md) - [how to run a cobalt instance](/docs/run-an-instance.md) - [how to protect a cobalt instance](/docs/protect-an-instance.md) -- [cobalt api documentation](/docs/api.md) +- [how to configure a cobalt instance for youtube](/docs/configure-for-youtube.md) ### partners cobalt is sponsored by [royalehosting.net](https://royalehosting.net/?partner=cobalt) and the main processing instance is hosted on their network. we really appreciate their kindness! diff --git a/docs/configure-for-youtube.md b/docs/configure-for-youtube.md new file mode 100644 index 00000000..345776a4 --- /dev/null +++ b/docs/configure-for-youtube.md @@ -0,0 +1,33 @@ +# how to configure a cobalt instance for youtube +if you get various errors when attempting to download videos that are: +publicly available, not region locked, and not age-restricted; +then your instance's ip address may have bad reputation. + +in this case you have to use disposable google accounts. +there's no other known workaround as of time of writing this document. + +> [!CAUTION] +> **NEVER** use your personal google account for downloading videos via any means. +> you can use any google accounts that you're willing to sacrifice, +> but be prepared to have them **permanently suspended**. +> +> we recommend that you use accounts that don't link back to your personal google account or identity, just in case. +> +> use incognito mode when signing in. +> we also recommend using vpn/proxy services (such as [mullvad](https://mullvad.net/)). + +1. if you haven't done it already, clone the cobalt repo, go to the cloned directory, and run `pnpm install` + +2. run `pnpm -r token:youtube` + +3. follow instructions, use incognito mode in your browser when signing in. +i cannot stress this enough, but again, **DO NOT USE YOUR PERSONAL GOOGLE ACCOUNT**. + +4. once you have the oauth token, add it to your cookies file. +you can see an [example here](/docs/examples/cookies.example.json). +you can have several account tokens in this file, if you like. + +5. all done! enjoy freedom. + +### liability +you're responsible for any damage done to any of your google accounts or any other damages. you do this by yourself and at your own risk. From f33cf12fd3f13a4ac5d62e17782206950fc69d50 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 18:56:37 +0600 Subject: [PATCH 20/42] docs/run-an-instance: update headings --- docs/run-an-instance.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/run-an-instance.md b/docs/run-an-instance.md index 1d4dcdc0..63841625 100644 --- a/docs/run-an-instance.md +++ b/docs/run-an-instance.md @@ -54,8 +54,7 @@ sudo apt install nscd sudo service nscd start ``` -## list of all environment variables -### variables for api +## list of environment variables for api | variable name | default | example | description | |:----------------------|:----------|:------------------------|:------------| | `API_PORT` | `9000` | `9000` | changes port from which api server is accessible. | @@ -89,7 +88,7 @@ requests it makes for that particular download. to use freebind in cobalt, you n in a docker container, you also need to set the `API_LISTEN_ADDRESS` env to `127.0.0.1`, and set `network_mode` for the container to `host`. -#### api key file format +## api key file format the file is a JSON-serialized object with the following structure: ```typescript From 155322a47bc44f5b77c7fc0796928f887e11ce49 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 18:59:07 +0600 Subject: [PATCH 21/42] docs/configure-for-youtube: clarify where to put the token --- docs/configure-for-youtube.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure-for-youtube.md b/docs/configure-for-youtube.md index 345776a4..5a397f92 100644 --- a/docs/configure-for-youtube.md +++ b/docs/configure-for-youtube.md @@ -23,7 +23,7 @@ there's no other known workaround as of time of writing this document. 3. follow instructions, use incognito mode in your browser when signing in. i cannot stress this enough, but again, **DO NOT USE YOUR PERSONAL GOOGLE ACCOUNT**. -4. once you have the oauth token, add it to your cookies file. +4. once you have the oauth token, add it to `youtube_oauth` in your cookies file. you can see an [example here](/docs/examples/cookies.example.json). you can have several account tokens in this file, if you like. From 9d68247523890c83dc8ce13f150f11fddd12f051 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 19:06:48 +0600 Subject: [PATCH 22/42] api: remove the outdated setup script --- api/package.json | 1 - api/src/util/setup.js | 105 ------------------------------------------ 2 files changed, 106 deletions(-) delete mode 100644 api/src/util/setup.js diff --git a/api/package.json b/api/package.json index ba346f39..948f8180 100644 --- a/api/package.json +++ b/api/package.json @@ -10,7 +10,6 @@ }, "scripts": { "start": "node src/cobalt", - "setup": "node src/util/setup", "test": "node src/util/test", "token:youtube": "node src/util/generate-youtube-tokens", "token:jwt": "node src/util/generate-jwt-secret" diff --git a/api/src/util/setup.js b/api/src/util/setup.js deleted file mode 100644 index 34b870cb..00000000 --- a/api/src/util/setup.js +++ /dev/null @@ -1,105 +0,0 @@ -import { existsSync, unlinkSync, appendFileSync } from "fs"; -import { createInterface } from "readline"; -import { Cyan, Bright } from "../misc/console-text.js"; -import { loadJSON } from "../misc/load-from-fs.js"; -import { execSync } from "child_process"; - -const { version } = loadJSON("./package.json"); - -let envPath = './.env'; -let q = `${Cyan('?')} \x1b[1m`; -let ob = {}; -let rl = createInterface({ input: process.stdin, output: process.stdout }); - -let final = () => { - if (existsSync(envPath)) unlinkSync(envPath); - - for (let i in ob) { - appendFileSync(envPath, `${i}=${ob[i]}\n`) - } - console.log(Bright("\nAwesome! I've created a fresh .env file for you.")); - console.log(`${Bright("Now I'll run")} ${Cyan("npm install")} ${Bright("to install all dependencies. It shouldn't take long.\n\n")}`); - execSync('pnpm install', { stdio: [0, 1, 2] }); - console.log(`\n\n${Cyan("All done!\n")}`); - console.log(Bright("You can re-run this script at any time to update the configuration.")); - console.log(Bright("\nYou're now ready to start cobalt. Simply run ") + Cyan("npm start") + Bright('!\nHave fun :)')); - rl.close() -} - -console.log( - `${Cyan(`Hey, this is cobalt v.${version}!`)}\n${Bright("Let's start by creating a new ")}${Cyan(".env")}${Bright(" file. You can always change it later.")}` -) - -function setup() { - console.log(Bright("\nWhat kind of server will this instance be?\nOptions: api, web.")); - - rl.question(q, r1 => { - switch (r1.toLowerCase()) { - case 'api': - console.log(Bright("\nCool! What's the domain this API instance will be running on? (localhost)\nExample: api.cobalt.tools")); - - rl.question(q, apiURL => { - ob.API_URL = `http://localhost:9000/`; - ob.API_PORT = 9000; - if (apiURL && apiURL !== "localhost") ob.API_URL = `https://${apiURL.toLowerCase()}/`; - - console.log(Bright("\nGreat! Now, what port will it be running on? (9000)")); - - rl.question(q, apiPort => { - if (apiPort) ob.API_PORT = apiPort; - if (apiPort && (apiURL === "localhost" || !apiURL)) ob.API_URL = `http://localhost:${apiPort}/`; - - console.log(Bright("\nWhat will your instance's name be? Usually it's something like eu-nl aka region-country. (local)")); - - rl.question(q, apiName => { - ob.API_NAME = apiName.toLowerCase(); - if (!apiName || apiName === "local") ob.API_NAME = "local"; - - console.log(Bright("\nOne last thing: would you like to enable CORS? It allows other websites and extensions to use your instance's API.\ny/n (n)")); - - rl.question(q, apiCors => { - let answCors = apiCors.toLowerCase().trim(); - if (answCors !== "y" && answCors !== "yes") ob.CORS_WILDCARD = '0' - final() - }) - }) - }); - - }) - break; - case 'web': - console.log(Bright("\nAwesome! What's the domain this web app instance will be running on? (localhost)\nExample: cobalt.tools")); - - rl.question(q, webURL => { - ob.WEB_URL = `http://localhost:9001/`; - ob.WEB_PORT = 9001; - if (webURL && webURL !== "localhost") ob.WEB_URL = `https://${webURL.toLowerCase()}/`; - - console.log( - Bright("\nGreat! Now, what port will it be running on? (9001)") - ) - rl.question(q, webPort => { - if (webPort) ob.WEB_PORT = webPort; - if (webPort && (webURL === "localhost" || !webURL)) ob.WEB_URL = `http://localhost:${webPort}/`; - - console.log( - Bright("\nOne last thing: what default API domain should be used? (api.cobalt.tools)\nIf it's hosted locally, make sure to include the port:") + Cyan(" localhost:9000") - ); - - rl.question(q, apiURL => { - ob.API_URL = `https://${apiURL.toLowerCase()}/`; - if (apiURL.includes(':')) ob.API_URL = `http://${apiURL.toLowerCase()}/`; - if (!apiURL) ob.API_URL = "https://api.cobalt.tools/"; - final() - }) - }); - - }); - break; - default: - console.log(Bright("\nThis is not an option. Try again.")); - setup() - } - }) -} -setup() From 16c5450d408b73e8ca683805aa02f9aef9b9c83e Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 19:07:42 +0600 Subject: [PATCH 23/42] api/cobalt: update api url error message --- api/src/cobalt.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/api/src/cobalt.js b/api/src/cobalt.js index c548e792..363930ba 100644 --- a/api/src/cobalt.js +++ b/api/src/cobalt.js @@ -2,26 +2,24 @@ import "dotenv/config"; import express from "express"; -import path from 'path'; -import { fileURLToPath } from 'url'; +import path from "path"; +import { fileURLToPath } from "url"; import { env } from "./config.js" -import { Bright, Green, Red } from "./misc/console-text.js"; +import { Red } from "./misc/console-text.js"; const app = express(); const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename).slice(0, -4); -app.disable('x-powered-by'); +app.disable("x-powered-by"); if (env.apiURL) { - const { runAPI } = await import('./core/api.js'); + const { runAPI } = await import("./core/api.js"); runAPI(express, app, __dirname) } else { console.log( - Red(`cobalt wasn't configured yet or configuration is invalid.\n`) - + Bright(`please run the setup script to fix this: `) - + Green(`npm run setup`) + Red("API_URL env variable is missing, cobalt api can't start.") ) } From a81a19de6825d6c4199a1f4989322328332c50d4 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 19:26:19 +0600 Subject: [PATCH 24/42] docs/protect-an-instance: add a command for generating a secret --- docs/protect-an-instance.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 59c7fa27..5604ddec 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -77,14 +77,18 @@ if you have other variables there, just add new ones after existing ones. > never use any values from the tutorial, especially `JWT_SECRET`! 1. open your `docker-compose.yml` config file in any text editor of choice. -2. copy the turnstile sitekey & secret key and paste them to their respective variables. `TURNSTILE_SITEKEY` for the sitekey and `TURNSTILE_SECRET` for the secret key: +2. copy the turnstile sitekey & secret key and paste them to their respective variables. +`TURNSTILE_SITEKEY` for the sitekey and `TURNSTILE_SECRET` for the secret key: ```yml environment: API_URL: "https://your.instance.url.here.local/" TURNSTILE_SITEKEY: "2x00000000000000000000BB" # use your key TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key ``` -3. generate a `JWT_SECRET`. we recommend using an alphanumeric collection with a length of at least 64 characters. this string will be used as salt for all JWT keys. +3. generate a `JWT_SECRET`. we recommend using an alphanumeric collection with a length of at least 64 characters. +this string will be used as salt for all JWT keys. + + you can generate a random secret with `pnpm -r token:jwt` or use any other that you like. ```yml environment: From 9790179e29e498494e01d7d300ff2203aa681df2 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 19:51:35 +0600 Subject: [PATCH 25/42] docs/protect-an-instance: add api keys configuration --- docs/protect-an-instance.md | 52 ++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 5604ddec..e0ba7f3b 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -13,7 +13,7 @@ all you need is a free cloudflare account to get started. cloudflare dashboard interface might change over time, but basics should stay the same. -> [!CAUTION] +> [!WARNING] > never share the turnstile secret key, always keep it private. if accidentally exposed, rotate it in widget settings. 1. open [the cloudflare dashboard](https://dash.cloudflare.com/) and log into your account @@ -97,3 +97,53 @@ environment: TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key JWT_SECRET: "bgBmF4efNCKPirDqTc4FMmbX8P22I31oCj5R1zDiDi5sy8CWPnfLUct7rk5RlZUS" # create a new secret, NEVER use this one ``` +4. restart the docker container. + +## configure api keys +if you want to use your instance outside of web interface, you'll need an api key! + +> [!NOTE] +> this tutorial assumes that you'll keep your keys file locally, on the instance server. +> if you wish to upload your file to a remote location, +> replace the value for `API_KEYS_URL` with a direct url to the file. + +> [!WARNING] +> when storing keys file remotely, make sure that it's not publicly accessible +> and that link to it is either authenticated (via query) or impossible to guess. +> +> if api keys leak, you'll have to update/remove all UUIDs to revoke them. + +1. create a `keys.json` file following [the schema and example here](/docs//run-an-instance.md#api-key-file-format). + +2. expose the `keys.json` to the docker container: +```yml +volumes: + - ./keys.json:/keys.json:ro # ro - read-only +``` + +3. add a path to the keys file to container environment: +```yml +environment: + # ... other variables here ... + API_KEY_URL: "file:///keys.json" +``` + +4. restart the docker container. + +## limit access to an instance with api keys but no turnstile +by default, api keys are additional, meaning that they're not *required*, +but work alongside with turnstile or no auth (regular ip hash rate limiting). + +to always require auth (via keys or turnstile, if configured), set `API_AUTH_REQUIRED` to 1: +```yml +environment: + # ... other variables here ... + API_AUTH_REQUIRED: 1 +``` + +- if both keys and turnstile are enabled, then nothing will change. +- if only keys are configured, then all requests without a valid api key will be refused. + +### why not make keys exclusive by default? +keys may be useful for going around rate limiting, +while keeping the rest of api rate limited, with no turnstile in place. From 43b3139b4a318ecc27a33fead946fe990f19a89e Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 19:53:17 +0600 Subject: [PATCH 26/42] docs/protect-an-instance: skip second step of api keys config if remote --- docs/protect-an-instance.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index e0ba7f3b..2cfcd808 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -105,7 +105,8 @@ if you want to use your instance outside of web interface, you'll need an api ke > [!NOTE] > this tutorial assumes that you'll keep your keys file locally, on the instance server. > if you wish to upload your file to a remote location, -> replace the value for `API_KEYS_URL` with a direct url to the file. +> replace the value for `API_KEYS_URL` with a direct url to the file +> and skip the second step. > [!WARNING] > when storing keys file remotely, make sure that it's not publicly accessible From 4efe6d9350bb6770757632d2ddf81b24fcc90e8a Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 14:14:47 +0000 Subject: [PATCH 27/42] api/config: disallow `JWT_SECRET`s shorter than 16 chars --- api/src/config.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/src/config.js b/api/src/config.js index 3a28d7ce..02584212 100644 --- a/api/src/config.js +++ b/api/src/config.js @@ -54,6 +54,10 @@ const env = { const genericUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"; const cobaltUserAgent = `cobalt/${version} (+https://github.com/imputnet/cobalt)`; +if (env.sessionEnabled && env.jwtSecret.length < 16) { + throw new Error("JWT_SECRET env is too short (must be at least 16 characters long)"); +} + export { env, genericUserAgent, From 4b1ea6ed8034818b79af9cf01425454184b409b0 Mon Sep 17 00:00:00 2001 From: wukko Date: Sun, 20 Oct 2024 20:18:50 +0600 Subject: [PATCH 28/42] docs/protect-an-instance: update the template secret to fail --- docs/protect-an-instance.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/protect-an-instance.md b/docs/protect-an-instance.md index 2cfcd808..9b4131c1 100644 --- a/docs/protect-an-instance.md +++ b/docs/protect-an-instance.md @@ -95,7 +95,7 @@ environment: API_URL: "https://your.instance.url.here.local/" TURNSTILE_SITEKEY: "2x00000000000000000000BB" # use your key TURNSTILE_SECRET: "2x0000000000000000000000000000000AA" # use your key - JWT_SECRET: "bgBmF4efNCKPirDqTc4FMmbX8P22I31oCj5R1zDiDi5sy8CWPnfLUct7rk5RlZUS" # create a new secret, NEVER use this one + JWT_SECRET: "bgBmF4efNCKPirD" # create a new secret, NEVER use this one ``` 4. restart the docker container. From 429b7c85aa91b284c01435dd49ea8d2e417a8d9c Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 23:12:07 +0200 Subject: [PATCH 29/42] docs/configure-for-youtube: change pnpm command --- docs/configure-for-youtube.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure-for-youtube.md b/docs/configure-for-youtube.md index 5a397f92..65795912 100644 --- a/docs/configure-for-youtube.md +++ b/docs/configure-for-youtube.md @@ -18,7 +18,7 @@ there's no other known workaround as of time of writing this document. 1. if you haven't done it already, clone the cobalt repo, go to the cloned directory, and run `pnpm install` -2. run `pnpm -r token:youtube` +2. run `pnpm run -C api token:youtube` 3. follow instructions, use incognito mode in your browser when signing in. i cannot stress this enough, but again, **DO NOT USE YOUR PERSONAL GOOGLE ACCOUNT**. From 1b9855206ee5861f48262a390f5dcd7e8949482f Mon Sep 17 00:00:00 2001 From: jj Date: Sun, 20 Oct 2024 23:12:35 +0200 Subject: [PATCH 30/42] docs/configure-for-youtube: omit `run` from pnpm command --- docs/configure-for-youtube.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configure-for-youtube.md b/docs/configure-for-youtube.md index 65795912..fe286d86 100644 --- a/docs/configure-for-youtube.md +++ b/docs/configure-for-youtube.md @@ -18,7 +18,7 @@ there's no other known workaround as of time of writing this document. 1. if you haven't done it already, clone the cobalt repo, go to the cloned directory, and run `pnpm install` -2. run `pnpm run -C api token:youtube` +2. run `pnpm -C api token:youtube` 3. follow instructions, use incognito mode in your browser when signing in. i cannot stress this enough, but again, **DO NOT USE YOUR PERSONAL GOOGLE ACCOUNT**. From 9d59a2f5d20e59e1918a2df6b01773d5c396c668 Mon Sep 17 00:00:00 2001 From: wukko Date: Tue, 22 Oct 2024 14:16:10 +0600 Subject: [PATCH 31/42] web/about/terms: point out even more that safety email is not support --- web/i18n/en/about/terms.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/web/i18n/en/about/terms.md b/web/i18n/en/about/terms.md index a134ab84..aa32fd65 100644 --- a/web/i18n/en/about/terms.md +++ b/web/i18n/en/about/terms.md @@ -48,9 +48,10 @@ fair use and credits benefit everyone. sectionId="abuse" /> -we have no way of detecting abusive behavior automatically, as cobalt is 100% anonymous. -however, you can report such activities to us and we will do our best to comply manually: [safety@imput.net](mailto:safety@imput.net) +we have no way of detecting abusive behavior automatically because cobalt is 100% anonymous. +however, you can report such activities to us and we will do our best to comply manually: **safety@imput.net** + +**this email is not intended for user support, you will not get a response if your concern is not related to abuse.** -please note that this email is not intended for user support. if you're experiencing issues, contact us via any preferred method on [the support page](/about/community). From a3ee3d9c16bf8b636c3cab773d48e26543055cc4 Mon Sep 17 00:00:00 2001 From: wukko Date: Wed, 23 Oct 2024 14:01:10 +0600 Subject: [PATCH 32/42] api/youtube: catch one more age limit error --- api/src/processing/services/youtube.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/src/processing/services/youtube.js b/api/src/processing/services/youtube.js index 46f72a5b..a6cdc9a2 100644 --- a/api/src/processing/services/youtube.js +++ b/api/src/processing/services/youtube.js @@ -170,6 +170,10 @@ export default async function(o) { } } + if (playability.status === "AGE_VERIFICATION_REQUIRED") { + return { error: "content.video.age" } + } + if (playability.status !== "OK") { return { error: "content.video.unavailable" }; } From ae271fd3c631c1b0a90cd0bb7dca5c8660802e83 Mon Sep 17 00:00:00 2001 From: wukko Date: Wed, 23 Oct 2024 18:08:50 +0600 Subject: [PATCH 33/42] api/youtube: refactor playability status handling --- api/src/processing/services/youtube.js | 79 +++++++++++++------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/api/src/processing/services/youtube.js b/api/src/processing/services/youtube.js index a6cdc9a2..95581863 100644 --- a/api/src/processing/services/youtube.js +++ b/api/src/processing/services/youtube.js @@ -1,5 +1,4 @@ import { fetch } from "undici"; - import { Innertube, Session } from "youtubei.js"; import { env } from "../../config.js"; @@ -146,41 +145,49 @@ export default async function(o) { const playability = info.playability_status; const basicInfo = info.basic_info; - if (playability.status === "LOGIN_REQUIRED") { - if (playability.reason.endsWith("bot")) { - return { error: "youtube.login" } - } - if (playability.reason.endsWith("age")) { - return { error: "content.video.age" } - } - if (playability?.error_screen?.reason?.text === "Private video") { - return { error: "content.video.private" } - } + switch(playability.status) { + case "OK": + break; + + case "LOGIN_REQUIRED": + if (playability.reason.endsWith("bot")) { + return { error: "youtube.login" } + } + if (playability.reason.endsWith("age")) { + return { error: "content.video.age" } + } + if (playability?.error_screen?.reason?.text === "Private video") { + return { error: "content.video.private" } + } + break; + + case "UNPLAYABLE": + if (playability?.reason?.endsWith("request limit.")) { + return { error: "fetch.rate" } + } + if (playability?.error_screen?.subreason?.text?.endsWith("in your country")) { + return { error: "content.video.region" } + } + if (playability?.error_screen?.reason?.text === "Private video") { + return { error: "content.video.private" } + } + break; + + case "AGE_VERIFICATION_REQUIRED": + return { error: "content.video.age" }; + + default: + return { error: "content.video.unavailable" }; } - if (playability.status === "UNPLAYABLE") { - if (playability?.reason?.endsWith("request limit.")) { - return { error: "fetch.rate" } - } - if (playability?.error_screen?.subreason?.text?.endsWith("in your country")) { - return { error: "content.video.region" } - } - if (playability?.error_screen?.reason?.text === "Private video") { - return { error: "content.video.private" } - } - } - - if (playability.status === "AGE_VERIFICATION_REQUIRED") { - return { error: "content.video.age" } - } - - if (playability.status !== "OK") { - return { error: "content.video.unavailable" }; - } if (basicInfo.is_live) { return { error: "content.video.live" }; } + if (basicInfo.duration > env.durationLimit) { + return { error: "content.too_long" }; + } + // return a critical error if returned video is "Video Not Available" // or a similar stub by youtube if (basicInfo.id !== o.id) { @@ -212,11 +219,9 @@ export default async function(o) { if (bestVideo) bestQuality = qual(bestVideo); - if ((!bestQuality && !o.isAudioOnly) || !hasAudio) + if ((!bestQuality && !o.isAudioOnly) || !hasAudio) { return { error: "youtube.codec" }; - - if (basicInfo.duration > env.durationLimit) - return { error: "content.too_long" }; + } const checkBestAudio = (i) => (i.has_audio && !i.has_video); @@ -226,9 +231,7 @@ export default async function(o) { if (o.dubLang) { let dubbedAudio = adaptive_formats.find(i => - checkBestAudio(i) - && i.language === o.dubLang - && i.audio_track + checkBestAudio(i) && i.language === o.dubLang && i.audio_track ) if (dubbedAudio && !dubbedAudio?.audio_track?.audio_is_default) { @@ -313,5 +316,5 @@ export default async function(o) { } } - return { error: "fetch.fail" } + return { error: "fetch.fail" }; } From cfb05282c351185b44f7768e75f2354f4ff72cb7 Mon Sep 17 00:00:00 2001 From: wukko Date: Wed, 23 Oct 2024 19:56:59 +0600 Subject: [PATCH 34/42] api/youtube: refactor, fallback codecs, don't return premuxed videos --- api/src/processing/services/youtube.js | 99 ++++++++++---------------- 1 file changed, 39 insertions(+), 60 deletions(-) diff --git a/api/src/processing/services/youtube.js b/api/src/processing/services/youtube.js index 95581863..e2f83c5d 100644 --- a/api/src/processing/services/youtube.js +++ b/api/src/processing/services/youtube.js @@ -9,7 +9,7 @@ const PLAYER_REFRESH_PERIOD = 1000 * 60 * 15; // ms let innertube, lastRefreshedAt; -const codecMatch = { +const codecList = { h264: { videoCodec: "avc1", audioCodec: "mp4a", @@ -120,12 +120,12 @@ export default async function(o) { let info, isDubbed, format = o.format || "h264"; - function qual(i) { + const qual = (i) => { if (!i.quality_label) { return; } - return i.quality_label.split('p')[0].split('s')[0] + return i.quality_label.split('p', 2)[0].split('s', 2)[0] } try { @@ -198,36 +198,31 @@ export default async function(o) { } const filterByCodec = (formats) => - formats - .filter(e => - e.mime_type.includes(codecMatch[format].videoCodec) - || e.mime_type.includes(codecMatch[format].audioCodec) - ) - .sort((a, b) => Number(b.bitrate) - Number(a.bitrate)); + formats.filter(e => + e.mime_type.includes(codecList[format].videoCodec) + || e.mime_type.includes(codecList[format].audioCodec) + ).sort((a, b) => + Number(b.bitrate) - Number(a.bitrate) + ); let adaptive_formats = filterByCodec(info.streaming_data.adaptive_formats); - if (adaptive_formats.length === 0 && format === "vp9") { - format = "h264" - adaptive_formats = filterByCodec(info.streaming_data.adaptive_formats) + if (adaptive_formats.length === 0 && ["vp9", "av1"].includes(format)) { + format = "h264"; + adaptive_formats = filterByCodec(info.streaming_data.adaptive_formats); } - let bestQuality; - const bestVideo = adaptive_formats.find(i => i.has_video && i.content_length); const hasAudio = adaptive_formats.find(i => i.has_audio && i.content_length); - if (bestVideo) bestQuality = qual(bestVideo); - - if ((!bestQuality && !o.isAudioOnly) || !hasAudio) { - return { error: "youtube.codec" }; + if (!bestVideo || (!hasAudio && o.isAudioOnly)) { + return { error: "fetch.empty" }; } + const bestQuality = qual(bestVideo); const checkBestAudio = (i) => (i.has_audio && !i.has_video); - let audio = adaptive_formats.find(i => - checkBestAudio(i) && i.is_original - ); + let audio = adaptive_formats.find(i => checkBestAudio(i) && i.is_original); if (o.dubLang) { let dubbedAudio = adaptive_formats.find(i => @@ -244,13 +239,14 @@ export default async function(o) { audio = adaptive_formats.find(i => checkBestAudio(i)); } - let fileMetadata = { + const fileMetadata = { title: cleanString(basicInfo.title.trim()), - artist: cleanString(basicInfo.author.replace("- Topic", "").trim()), + artist: cleanString(basicInfo.author.replace("- Topic", "").trim()) } if (basicInfo?.short_description?.startsWith("Provided to YouTube by")) { - let descItems = basicInfo.short_description.split("\n\n", 5); + const descItems = basicInfo.short_description.split("\n\n", 5); + if (descItems.length === 5) { fileMetadata.album = descItems[2]; fileMetadata.copyright = descItems[3]; @@ -260,7 +256,7 @@ export default async function(o) { } } - let filenameAttributes = { + const filenameAttributes = { service: "youtube", id: o.id, title: fileMetadata.title, @@ -271,46 +267,29 @@ export default async function(o) { if (audio && o.isAudioOnly) return { type: "audio", isAudioOnly: true, - urls: audio.decipher(yt.session.player), - filenameAttributes: filenameAttributes, - fileMetadata: fileMetadata, - bestAudio: format === "h264" ? "m4a" : "opus" + urls: audio.url, + filenameAttributes, + fileMetadata, + bestAudio: format === "h264" ? "m4a" : "opus", } - const matchingQuality = Number(quality) > Number(bestQuality) ? bestQuality : quality, - checkSingle = i => - qual(i) === matchingQuality && i.mime_type.includes(codecMatch[format].videoCodec), - checkRender = i => - qual(i) === matchingQuality && i.has_video && !i.has_audio; + const matchingQuality = Number(quality) > Number(bestQuality) ? bestQuality : quality; + const video = adaptive_formats.find(i => + qual(i) === matchingQuality && i.has_video && !i.has_audio + ); - let match, type, urls; - - // prefer good premuxed videos if available - if (!o.isAudioOnly && !o.isAudioMuted && format === "h264" && bestVideo.fps <= 30) { - match = info.streaming_data.formats.find(checkSingle); - type = "proxy"; - urls = match?.decipher(yt.session.player); - } - - const video = adaptive_formats.find(checkRender); - - if (!match && video && audio) { - match = video; - type = "merge"; - urls = [ - video.decipher(yt.session.player), - audio.decipher(yt.session.player) - ] - } - - if (match) { - filenameAttributes.qualityLabel = match.quality_label; - filenameAttributes.resolution = `${match.width}x${match.height}`; - filenameAttributes.extension = codecMatch[format].container; + if (video && audio) { + filenameAttributes.qualityLabel = video.quality_label; + filenameAttributes.resolution = `${video.width}x${video.height}`; + filenameAttributes.extension = codecList[format].container; filenameAttributes.youtubeFormat = format; + return { - type, - urls, + type: "merge", + urls: [ + video.url, + audio.url + ], filenameAttributes, fileMetadata } From 52c171460833215ca2af0bb33a049c40ac267363 Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 26 Oct 2024 22:38:42 +0600 Subject: [PATCH 35/42] web/i18n/settings: fix typo in youtube codec description --- web/i18n/en/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/i18n/en/settings.json b/web/i18n/en/settings.json index 8d003439..2b34eb62 100644 --- a/web/i18n/en/settings.json +++ b/web/i18n/en/settings.json @@ -30,7 +30,7 @@ "video.quality.description": "if preferred video quality isn't available, next best is picked instead.", "video.youtube.codec": "youtube video codec and container", - "video.youtube.codec.description": "h264: best compatibility, average bitrate. max quality is 1080p. \nav1: best quality, efficiency, and bitrate. supports 8k & HDR. \nvp9: same quality & bitrate as av1, but file is approximately two times bigger. supports 4k & HDR.\n\nav1 and vp9 aren't as widely supported as h264.", + "video.youtube.codec.description": "h264: best compatibility, average bitrate. max quality is 1080p. \nav1: best quality, efficiency, and bitrate. supports 8k & HDR. \nvp9: same quality as av1, but file is approximately two times bigger. supports 4k & HDR.\n\nav1 and vp9 aren't as widely supported as h264.", "video.twitter.gif": "twitter/x", "video.twitter.gif.title": "convert looping videos to GIF", From 3907697fa708e5c1d19b4d23c9c1809e86801f9f Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 26 Oct 2024 22:45:16 +0600 Subject: [PATCH 36/42] web/i18n/settings: rephrase the youtube codec desc also added info about fallback --- web/i18n/en/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/i18n/en/settings.json b/web/i18n/en/settings.json index 2b34eb62..8e5a402c 100644 --- a/web/i18n/en/settings.json +++ b/web/i18n/en/settings.json @@ -30,7 +30,7 @@ "video.quality.description": "if preferred video quality isn't available, next best is picked instead.", "video.youtube.codec": "youtube video codec and container", - "video.youtube.codec.description": "h264: best compatibility, average bitrate. max quality is 1080p. \nav1: best quality, efficiency, and bitrate. supports 8k & HDR. \nvp9: same quality as av1, but file is approximately two times bigger. supports 4k & HDR.\n\nav1 and vp9 aren't as widely supported as h264.", + "video.youtube.codec.description": "h264: best compatibility, average quality. max quality is 1080p. \nav1: best quality and efficiency. supports 8k & HDR. \nvp9: same quality as av1, but file is ~2x bigger. supports 4k & HDR.\n\nav1 and vp9 aren't as widely supported as h264. if av1 or vp9 isn't available, h264 is used instead.", "video.twitter.gif": "twitter/x", "video.twitter.gif.title": "convert looping videos to GIF", From 8b15fe78637588a71c34dc712ef6c689e114d340 Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 26 Oct 2024 22:49:16 +0600 Subject: [PATCH 37/42] api/youtube: check if playability is ok after the status switch --- api/src/processing/services/youtube.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/api/src/processing/services/youtube.js b/api/src/processing/services/youtube.js index e2f83c5d..7517c351 100644 --- a/api/src/processing/services/youtube.js +++ b/api/src/processing/services/youtube.js @@ -146,9 +146,6 @@ export default async function(o) { const basicInfo = info.basic_info; switch(playability.status) { - case "OK": - break; - case "LOGIN_REQUIRED": if (playability.reason.endsWith("bot")) { return { error: "youtube.login" } @@ -175,9 +172,10 @@ export default async function(o) { case "AGE_VERIFICATION_REQUIRED": return { error: "content.video.age" }; + } - default: - return { error: "content.video.unavailable" }; + if (playability.status !== "OK") { + return { error: "content.video.unavailable" }; } if (basicInfo.is_live) { From 66bb76e1c7410e62146abc5f52cf0c097806e4d6 Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 26 Oct 2024 23:06:43 +0600 Subject: [PATCH 38/42] web/i18n/settings: update preferred language description --- web/i18n/en/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/i18n/en/settings.json b/web/i18n/en/settings.json index 8e5a402c..ba2fc886 100644 --- a/web/i18n/en/settings.json +++ b/web/i18n/en/settings.json @@ -91,7 +91,7 @@ "language.auto.title": "automatic selection", "language.auto.description": "cobalt will use your browser's default language if translation is available. if not, english will be used instead.", "language.preferred.title": "preferred language", - "language.preferred.description": "this language will be used when automatic selection is disabled. any text that isn't translated will be displayed in english.\n\nwe use community-sourced translations for languages other than english, russian, and czech. they may be inaccurate or incomplete.", + "language.preferred.description": "this language will be used when automatic selection is disabled. any text that isn't translated will be displayed in english.\n\nsome languages use community-sourced translations, they may be inaccurate or incomplete.", "privacy.analytics": "anonymous traffic analytics", "privacy.analytics.title": "don't contribute to analytics", From fb7325f3b2a9ebcbe60061a10bf343800cff0a90 Mon Sep 17 00:00:00 2001 From: wukko Date: Sat, 26 Oct 2024 23:53:43 +0600 Subject: [PATCH 39/42] api/youtube: more refactoring, return audio even if there's no video --- api/src/processing/services/youtube.js | 31 +++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/api/src/processing/services/youtube.js b/api/src/processing/services/youtube.js index 7517c351..b4583051 100644 --- a/api/src/processing/services/youtube.js +++ b/api/src/processing/services/youtube.js @@ -115,19 +115,7 @@ export default async function(o) { } else throw e; } - const quality = o.quality === "max" ? "9000" : o.quality; - - let info, isDubbed, - format = o.format || "h264"; - - const qual = (i) => { - if (!i.quality_label) { - return; - } - - return i.quality_label.split('p', 2)[0].split('s', 2)[0] - } - + let info; try { info = await yt.getBasicInfo(o.id, yt.session.logged_in ? 'ANDROID' : 'IOS'); } catch(e) { @@ -195,6 +183,8 @@ export default async function(o) { } } + let format = o.format || "h264"; + const filterByCodec = (formats) => formats.filter(e => e.mime_type.includes(codecList[format].videoCodec) @@ -213,14 +203,14 @@ export default async function(o) { const bestVideo = adaptive_formats.find(i => i.has_video && i.content_length); const hasAudio = adaptive_formats.find(i => i.has_audio && i.content_length); - if (!bestVideo || (!hasAudio && o.isAudioOnly)) { + if ((!bestVideo && !o.isAudioOnly) || (!hasAudio && o.isAudioOnly)) { return { error: "fetch.empty" }; } - const bestQuality = qual(bestVideo); const checkBestAudio = (i) => (i.has_audio && !i.has_video); let audio = adaptive_formats.find(i => checkBestAudio(i) && i.is_original); + let isDubbed; if (o.dubLang) { let dubbedAudio = adaptive_formats.find(i => @@ -271,7 +261,18 @@ export default async function(o) { bestAudio: format === "h264" ? "m4a" : "opus", } + const qual = (i) => { + if (!i.quality_label) { + return; + } + + return i.quality_label.split('p', 2)[0].split('s', 2)[0] + } + + const quality = o.quality === "max" ? "9000" : o.quality; + const bestQuality = qual(bestVideo); const matchingQuality = Number(quality) > Number(bestQuality) ? bestQuality : quality; + const video = adaptive_formats.find(i => qual(i) === matchingQuality && i.has_video && !i.has_audio ); From 2ccc2106224b61915c7b4f85c0d5b2ce8aa81d18 Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 26 Oct 2024 18:07:13 +0000 Subject: [PATCH 40/42] api/test: add test for audio download if no video found tests for bug fixed in fb7325f3b2a9ebcbe60061a10bf343800cff0a90 --- api/src/util/tests.json | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/api/src/util/tests.json b/api/src/util/tests.json index 402a2baf..c8a1782d 100644 --- a/api/src/util/tests.json +++ b/api/src/util/tests.json @@ -486,6 +486,17 @@ "code": 400, "status": "error" } + }, + { + "name": "broken audioOnly download", + "url": "https://www.youtube.com/watch?v=ink80Al5nbw", + "params": { + "downloadMode": "audio" + }, + "expected": { + "code": 200, + "status": "tunnel" + } } ], "vk": [ From d8b7a6b5591d484a593126c8d319d9e32caf4bfa Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 26 Oct 2024 18:08:24 +0000 Subject: [PATCH 41/42] api/test: remove youtube vp9 test we fall back to h264 now, so this will always succeed --- api/src/util/tests.json | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/api/src/util/tests.json b/api/src/util/tests.json index c8a1782d..2d8d8708 100644 --- a/api/src/util/tests.json +++ b/api/src/util/tests.json @@ -437,17 +437,6 @@ "status": "tunnel" } }, - { - "name": "audio bitrate higher than video, no vp9 video in response (vp9)", - "url": "https://www.youtube.com/watch?v=t5nC_ucYBrc", - "params": { - "youtubeVideoCodec": "vp9" - }, - "expected": { - "code": 400, - "status": "error" - } - }, { "name": "short, defaults", "url": "https://www.youtube.com/shorts/r5FpeOJItbw", From a4e6b49d7fc2b375013981b3c37698805ba4dd9a Mon Sep 17 00:00:00 2001 From: jj Date: Sat, 26 Oct 2024 18:28:25 +0000 Subject: [PATCH 42/42] util/jwt: ensure uniform distribution of characters --- api/src/util/generate-jwt-secret.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/api/src/util/generate-jwt-secret.js b/api/src/util/generate-jwt-secret.js index 83f0aa5b..8db6e230 100644 --- a/api/src/util/generate-jwt-secret.js +++ b/api/src/util/generate-jwt-secret.js @@ -4,8 +4,17 @@ const makeSecureString = (length = 64) => { const alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-'; const out = []; - for (const byte of crypto.getRandomValues(new Uint8Array(length))) - out.push(alphabet[byte % alphabet.length]); + while (out.length < length) { + for (const byte of crypto.getRandomValues(new Uint8Array(length))) { + if (byte < alphabet.length) { + out.push(alphabet[byte]); + } + + if (out.length === length) { + break; + } + } + } return out.join(''); }