diff --git a/spotify_to_ytmusic/settings.ini.example b/spotify_to_ytmusic/settings.ini.example index ced616e..99e915b 100644 --- a/spotify_to_ytmusic/settings.ini.example +++ b/spotify_to_ytmusic/settings.ini.example @@ -1,6 +1,7 @@ [youtube] headers = headers_json_from_browser user_id = +auth_type = browser [spotify] client_id = id_from_developer_console diff --git a/spotify_to_ytmusic/setup.py b/spotify_to_ytmusic/setup.py index 1426c37..9a9c34e 100644 --- a/spotify_to_ytmusic/setup.py +++ b/spotify_to_ytmusic/setup.py @@ -17,8 +17,9 @@ def setup(file: Optional[Path] = None): if not DEFAULT_PATH.is_file(): shutil.copy(EXAMPLE_PATH, DEFAULT_PATH) - choice = input("Choose which API to set up\n" "(1) Spotify\n" "(2) YouTube\n" "(3) both\n") - choices = ["1", "2", "3"] + choice = input("Choose which API to set up\n(1) Spotify\n(2) YouTube (oAuth)\n(3) Youtube (Browser)\n(4) both \n") + + choices = ["1", "2", "3", "4"] if choice not in choices: sys.exit("Invalid choice") @@ -27,6 +28,8 @@ def setup(file: Optional[Path] = None): elif choice == choices[1]: setup_youtube() elif choice == choices[2]: + setup_youtube_browser() + elif choice == choices[3]: setup_spotify() setup_youtube() @@ -35,6 +38,15 @@ def setup_youtube(): settings = Settings() credentials = ytmusicapi.setup_oauth(open_browser=has_browser()) settings["youtube"]["headers"] = json.dumps(credentials.as_dict()) + settings["youtube"]["auth_type"] = "oauth" + settings.save() + +def setup_youtube_browser(): + settings = Settings() + print('Please see https://ytmusicapi.readthedocs.io/en/stable/setup/browser.html for instructions.') + credentials = ytmusicapi.setup() + settings["youtube"]["headers"] = credentials + settings["youtube"]["auth_type"] = "browser" settings.save() diff --git a/spotify_to_ytmusic/ytmusic.py b/spotify_to_ytmusic/ytmusic.py index 906c78e..7275dd7 100644 --- a/spotify_to_ytmusic/ytmusic.py +++ b/spotify_to_ytmusic/ytmusic.py @@ -6,18 +6,23 @@ from spotify_to_ytmusic.utils.match import get_best_fit_song_id from spotify_to_ytmusic.settings import Settings +from spotify_to_ytmusic.setup import setup_youtube_browser path = os.path.dirname(os.path.realpath(__file__)) + os.sep class YTMusicTransfer: def __init__(self): - settings = Settings() - headers = settings["youtube"]["headers"] + self.settings = Settings() + headers = self.settings["youtube"]["headers"] assert headers.startswith("{"), "ytmusicapi headers not set or invalid" - self.api = YTMusic(headers, settings["youtube"]["user_id"]) + self.api = YTMusic(headers, self.settings["youtube"]["user_id"]) def create_playlist(self, name, info, privacy="PRIVATE", tracks=None): + if self.settings["youtube"]["auth_type"] == "browser": + setup_youtube_browser() + self.api = YTMusic(self.settings["youtube"]["headers"], self.settings["youtube"]["user_id"]) + return self.api.create_playlist(name, info, privacy, video_ids=tracks) def rate_song(self, id, rating): diff --git a/tests/test_cli.py b/tests/test_cli.py index 78d719f..98d34ff 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -60,7 +60,7 @@ def test_setup(self): tmp_path = DEFAULT_PATH.with_suffix(".tmp") with ( mock.patch("sys.argv", ["", "setup"]), - mock.patch("builtins.input", side_effect=["3", "a", "b", "yes", ""]), + mock.patch("builtins.input", side_effect=["4", "a", "b", "yes", ""]), mock.patch( "ytmusicapi.auth.oauth.credentials.OAuthCredentials.token_from_code", return_value=json.loads(Settings()["youtube"]["headers"]),