feat: add YT_COOKIES_FILE support for Netscape cookies.txt
Previously, the only way to pass YouTube cookies was via the YT_COOKIES env var, which was incorrectly documented as a raw cookie string (name=value; ...) but internally mapped to yt-dlp's --cookies-from-browser, which expects a browser name (e.g. chrome, firefox). This made the feature non-functional as documented and unusable in Docker environments where no browser is present. This change introduces a second option, YT_COOKIES_FILE, which accepts a path to a Netscape-format cookies.txt file and maps to yt-dlp's --cookies flag. This is the recommended approach for Docker deployments, where users can export cookies via a browser extension and bind mount the file into the container. The file is only passed to yt-dlp if it actually exists on disk, so the default path (./config/cookies.txt) does not cause errors when no file is provided. YT_COOKIES retains priority over YT_COOKIES_FILE if both are set. README is updated to clarify the correct usage of both options, fix the misleading cookie string instructions, add a dedicated YouTube cookies section to the table of contents, and include the cookies.txt bind mount in the Docker usage examples. Resolves #40, resolves #48
This commit is contained in:
@@ -12,5 +12,6 @@ REDIS_RUN=false
|
||||
SPOTIFY_CLIENT_ID=your_client_id
|
||||
SPOTIFY_CLIENT_SECRET=your_client_secret
|
||||
|
||||
YT_COOKIES="AEC=xxx; APISID=xxx; APISID=xxx; HSID=xxx; HSID=xxx; LOGIN_INFO=xxx; NID=xxx; PREF=xxx; SAPISID=xxx; SAPISID=Nxxx; SEARCH_SAMESITE=xxx; SID=xxx; SID=xxx; SIDCC=xxx; SIDCC=xxx; SSID=xxx; SSID=xxx; STRP=xxx; VISITOR_PRIVACY_METADATA=xxx; YSC=xxx"
|
||||
YT_COOKIES=
|
||||
YT_COOKIES_FILE=./config/cookies.txt
|
||||
YT_DOWNLOADS_PER_MINUTE=3
|
||||
@@ -6,4 +6,6 @@ export enum EnvironmentEnum {
|
||||
REDIS_PORT = 'REDIS_PORT',
|
||||
REDIS_HOST = 'REDIS_HOST',
|
||||
REDIS_RUN = 'REDIS_RUN',
|
||||
YT_COOKIES = 'YT_COOKIES',
|
||||
YT_COOKIES_FILE = 'YT_COOKIES_FILE',
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import { TrackService } from '../track/track.service';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { YtDlp } from 'ytdlp-nodejs';
|
||||
import * as yts from 'yt-search';
|
||||
import * as fs from 'fs';
|
||||
const NodeID3 = require('node-id3');
|
||||
|
||||
const HEADERS = {
|
||||
@@ -25,6 +26,27 @@ export class YoutubeService {
|
||||
return url;
|
||||
}
|
||||
|
||||
private getCookiesOptions(): {
|
||||
cookiesFromBrowser?: string;
|
||||
cookies?: string;
|
||||
} {
|
||||
const cookiesBrowser = this.configService.get<string>(
|
||||
EnvironmentEnum.YT_COOKIES,
|
||||
);
|
||||
if (cookiesBrowser) {
|
||||
this.logger.debug(`Using cookies from browser: ${cookiesBrowser}`);
|
||||
return { cookiesFromBrowser: cookiesBrowser };
|
||||
}
|
||||
const cookiesFile = this.configService.get<string>(
|
||||
EnvironmentEnum.YT_COOKIES_FILE,
|
||||
);
|
||||
if (cookiesFile && fs.existsSync(cookiesFile)) {
|
||||
this.logger.debug(`Using cookies file: ${cookiesFile}`);
|
||||
return { cookies: cookiesFile };
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
async downloadAndFormat(track: TrackEntity, output: string): Promise<void> {
|
||||
this.logger.debug(
|
||||
`Downloading ${track.artist} - ${track.name} (${track.youtubeUrl}) from YT`,
|
||||
@@ -39,7 +61,7 @@ export class YoutubeService {
|
||||
this.configService.get<'m4a'>(EnvironmentEnum.FORMAT),
|
||||
{
|
||||
output,
|
||||
cookiesFromBrowser: this.configService.get<string>('YT_COOKIES'),
|
||||
...this.getCookiesOptions(),
|
||||
headers: HEADERS,
|
||||
jsRuntime: 'node',
|
||||
audioQuality: this.configService.get<string>('QUALITY'),
|
||||
|
||||
Reference in New Issue
Block a user