diff --git a/.gitignore b/.gitignore index 09662de..cde1126 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ __pycache__ /data .github/.tmp/ +/.vs diff --git a/README.md b/README.md index 89fa898..af92b95 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,18 @@ ytimport: max_likes: 15 set: loved: true - auth_headers: /path/to/your/http/headers + auth_headers: '' + oauth_client_id: '' + oauth_client_secret: '' + cookiefile: path/to/your/cookies min_length: 60 # 1m; min track length in seconds max_length: 7200 # 2h; max track length in seconds max_length_nochapter: 900 # 15m; max track length when no chapters defined split_tracks: true group_albums: true quiet_fallback: skip # optional; alternatively, to import as is, set 'asis'. + oauth_client_id: '' + oauth_client_secret: '' ``` For more information, see [CLI](#cli). @@ -57,7 +62,10 @@ Once you enabled the `ytimport` plugin within your beets configuration, you can beet ytimport --likes --max-likes 3 ``` -Please note that the command prompts you for Google authentication, unless you specified the `auth_headers` option within your beets configuration file pointing to a file containing HTTP headers (to get the HTTP headers, see [here](https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers)). +Please note that the command prompts you for Google authentication, unless you specified the `auth_headers` option within your beets configuration file pointing to a file containing HTTP headers (to get the HTTP headers, see [here](https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html#copy-authentication-headers)). +For Authentication oauth clientID and Secret are required (this requres a google cloud console account, see [here](https://ytmusicapi.readthedocs.io/en/stable/setup/oauth.html)). +Alternativly you can pass your cookie file to ytimport (to retrieve it use one of many cookie export extensions [eg](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/) +To imp Import auto-tagger prompts can be disabled by specifying the `-q` option. You can interrupt and continue or repeat the command to synchronize likes from your Youtube account(s) into your beets library incrementally. @@ -99,6 +107,8 @@ Options: --quiet-fallback=skip|asis decision in quiet mode when there is no strong match --pretend don't import but print the files when importing + --cookiefile path to a file containing the cookies for a logged in + user on music.youtube.com in Netscape format ``` ## Development diff --git a/beetsplug/ytimport/__init__.py b/beetsplug/ytimport/__init__.py index 5e8e874..7b8f527 100644 --- a/beetsplug/ytimport/__init__.py +++ b/beetsplug/ytimport/__init__.py @@ -47,6 +47,7 @@ def commands(self): def run_import_cmd(lib, opts, args): ytdir = os.path.expanduser(opts.directory) headers = os.path.expanduser(opts.auth_headers) + cookiefile = os.path.expanduser(opts.cookiefile) if headers: with open(headers, 'r') as f: headers = f.read() @@ -95,7 +96,7 @@ def run_import_cmd(lib, opts, args): # Maybe a cookiefile with some picked cookies from the headers can be generated? #if opts.auth and headers: # h = dict([l.split(': ', 1) for l in headers.strip().split('\n')[1:]]) - youtube.download(urls, ytdir, format=opts.format, min_len=opts.min_length, max_len=opts.max_length, max_len_nochapter=opts.max_length_nochapter, split=opts.split_tracks, like=opts.likes, reimport=opts.reimport, auth_headers=h) + youtube.download(urls, ytdir, cookiefile, format=opts.format, min_len=opts.min_length, max_len=opts.max_length, max_len_nochapter=opts.max_length_nochapter, split=opts.split_tracks, like=opts.likes, reimport=opts.reimport, auth_headers=h) else: self._log.info('Nothing to download') if opts.do_import: @@ -118,6 +119,9 @@ def run_import_cmd(lib, opts, args): p.add_option('--auth-headers', type='string', metavar='FILE', default=self.config['auth_headers'].get(), dest='auth_headers', help="path to a file containing the HTTP headers of an authenticated POST request to music.youtube.com, copied from your browser's development tool") + p.add_option('--cookiefile', type='string', metavar='FILE', + default=self.config['cookiefile'].get(), + dest='cookiefile', help='path to a file containing the cookies for a logged in user on music.youtube.com in Netscape format') p.add_option('--url-file', type='string', metavar='URL', default=self.config['url_file'].get(), dest='url_file', help='URL/path to a file containing a download URL per line') diff --git a/beetsplug/ytimport/config_default.yaml b/beetsplug/ytimport/config_default.yaml index 3b7bc31..df31dae 100644 --- a/beetsplug/ytimport/config_default.yaml +++ b/beetsplug/ytimport/config_default.yaml @@ -15,3 +15,4 @@ group_albums: true #quiet_fallback: skip # defaults to import configuration oauth_client_id: '' oauth_client_secret: '' +#cookies: '/path/to/your/cookies' diff --git a/beetsplug/ytimport/youtube.py b/beetsplug/ytimport/youtube.py index 728f73c..6238150 100644 --- a/beetsplug/ytimport/youtube.py +++ b/beetsplug/ytimport/youtube.py @@ -56,7 +56,7 @@ def run(self, info): os.remove(fname) return [], info -def download(urls, target_dir, format='bestaudio/best', min_len=60, max_len=7200, max_len_nochapter=900, split=False, like=False, reimport=False, auth_headers={}): +def download(urls, target_dir, cookiefile, format='bestaudio/best', min_len=60, max_len=7200, max_len_nochapter=900, split=False, like=False, reimport=False, auth_headers={}): def download_filter(info): duration = info.get('duration') @@ -129,7 +129,7 @@ def download_filter(info): 'key': 'XAttrMetadata', }, ], - # TODO: maybe enable for premium quality: 'cookiefile': 'path/to/cookies.txt', + 'cookiefile': cookiefile, } if not reimport: ytdl_opts['download_archive'] = target_dir+'/ytdownloads.txt'