def login(user, pwd): mcw = MobileClientWrapper() print 'lit' logged_in = mcw.login(user, pwd) print 'lit2' if logged_in: data['client'] = mcw return logged_in
def main(): cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper(enable_logging=cli['log']) mcw.login(username=cli['user'], password=cli['pass'], android_id=cli['android-id']) if not mcw.is_authenticated: sys.exit() include_filters = [ tuple(filt.split(':', 1)) for filt in cli['include-filter'] ] exclude_filters = [ tuple(filt.split(':', 1)) for filt in cli['exclude-filter'] ] logger.info("Scanning for songs...\n") search_results, _ = mcw.get_google_songs(include_filters=include_filters, exclude_filters=exclude_filters, all_includes=cli['all-includes'], all_excludes=cli['all-excludes']) search_results.sort(key=lambda song: (song.get('artist'), song.get( 'album'), song.get('trackNumber'))) if search_results: confirm = cli['yes'] or cli['quiet'] logger.info("") if confirm or input("Display {} results? (y/n) ".format( len(search_results))) in ("y", "Y"): logger.log(QUIET, "") for song in search_results: title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.log( QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs found matching query") mcw.logout() logger.info("\nAll done!")
def main(): cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper(enable_logging=cli['log']) mcw.login(username=cli['user'], password=cli['pass'], android_id=cli['android-id']) if not mcw.is_authenticated: sys.exit() include_filters = [tuple(filt.split(':', 1)) for filt in cli['include-filter']] exclude_filters = [tuple(filt.split(':', 1)) for filt in cli['exclude-filter']] logger.info("Scanning for songs...\n") search_results, _ = mcw.get_google_songs( include_filters=include_filters, exclude_filters=exclude_filters, all_includes=cli['all-includes'], all_excludes=cli['all-excludes'] ) search_results.sort(key=lambda song: (song.get('artist'), song.get('album'), song.get('trackNumber'))) if search_results: confirm = cli['yes'] or cli['quiet'] logger.info("") if confirm or input("Display {} results? (y/n) ".format(len(search_results))) in ("y", "Y"): logger.log(QUIET, "") for song in search_results: title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.log(QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs found matching query") mcw.logout() logger.info("\nAll done!")
def main(): if os.name == 'nt': sys.argv = win32_unicode_argv() else: sys.argv = [arg.decode(sys.stdin.encoding) for arg in sys.argv] cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper() mcw.login(cli['user'], cli['pass'], cli['android-id']) include_filters = [tuple(filt.split(':', 1)) for filt in cli['include-filter']] exclude_filters = [tuple(filt.split(':', 1)) for filt in cli['exclude-filter']] logger.info("Scanning for songs...\n") search_results, _ = mcw.get_google_songs(include_filters, exclude_filters, cli['include-all'], cli['exclude-all']) search_results.sort(key=lambda song: (song.get('artist'), song.get('album'), song.get('trackNumber'))) if search_results: confirm = cli['yes'] or cli['quiet'] logger.info("") if confirm or raw_input("Display {} results? (y/n) ".format(len(search_results))) in ("y", "Y"): logger.log(QUIET, "") for song in search_results: title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.log(QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs found matching query") mcw.logout() logger.info("\nAll done!")
def main(): if os.name == 'nt': sys.argv = win32_unicode_argv() else: sys.argv = [arg.decode(sys.stdin.encoding) for arg in sys.argv] cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper() mcw.login(cli['user'], cli['pass'], cli['android-id']) include_filters = [tuple(filt.split(':', 1)) for filt in cli['include-filter']] exclude_filters = [tuple(filt.split(':', 1)) for filt in cli['exclude-filter']] songs_to_delete, _ = mcw.get_google_songs(include_filters, exclude_filters, cli['include-all'], cli['exclude-all']) if cli['dry-run']: logger.info("Found {0} songs to delete".format(len(songs_to_delete))) if songs_to_delete: logger.info("\nSongs to delete:\n") for song in songs_to_delete: title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.log(QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs to delete") else: if songs_to_delete: confirm = cli['yes'] or cli['quiet'] logger.info("") if confirm or raw_input("Are you sure you want to delete {0} song(s) from Google Music? (y/n) ".format(len(songs_to_delete))) in ("y", "Y"): logger.info("\nDeleting {0} songs from Google Music\n".format(len(songs_to_delete))) songnum = 0 total = len(songs_to_delete) pad = len(str(total)) for song in songs_to_delete: mcw.api.delete_songs(song['id']) songnum += 1 title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.debug("Deleting {0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) logger.info("Deleted {num:>{pad}}/{total} song(s) from Google Music".format(num=songnum, pad=pad, total=total)) else: logger.info("\nNo songs deleted.") else: logger.info("\nNo songs to delete") mcw.logout() logger.info("\nAll done!")
def main(): cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli["quiet"]: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper(enable_logging=cli["log"]) mcw.login(cli["user"], cli["pass"], cli["android-id"]) include_filters = [tuple(filt.split(":", 1)) for filt in cli["include-filter"]] exclude_filters = [tuple(filt.split(":", 1)) for filt in cli["exclude-filter"]] songs_to_delete, _ = mcw.get_google_songs( include_filters, exclude_filters, cli["all-includes"], cli["all-excludes"] ) if cli["dry-run"]: logger.info("Found {0} songs to delete".format(len(songs_to_delete))) if songs_to_delete: logger.info("\nSongs to delete:\n") for song in songs_to_delete: title = song.get("title", "<empty>") artist = song.get("artist", "<empty>") album = song.get("album", "<empty>") song_id = song["id"] logger.log(QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs to delete") else: if songs_to_delete: confirm = cli["yes"] or cli["quiet"] logger.info("") if confirm or input( "Are you sure you want to delete {0} song(s) from Google Music? (y/n) ".format(len(songs_to_delete)) ) in ("y", "Y"): logger.info("\nDeleting {0} songs from Google Music\n".format(len(songs_to_delete))) songnum = 0 total = len(songs_to_delete) pad = len(str(total)) for song in songs_to_delete: mcw.api.delete_songs(song["id"]) songnum += 1 title = song.get("title", "<empty>") artist = song.get("artist", "<empty>") album = song.get("album", "<empty>") song_id = song["id"] logger.debug("Deleting {0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) logger.info( "Deleted {num:>{pad}}/{total} song(s) from Google Music".format( num=songnum, pad=pad, total=total ) ) else: logger.info("\nNo songs deleted.") else: logger.info("\nNo songs to delete") mcw.logout() logger.info("\nAll done!")
def main(): cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) mcw = MobileClientWrapper(enable_logging=cli['log']) mcw.login(username=cli['user'], password=cli['pass'], android_id=cli['android-id']) if not mcw.is_authenticated: sys.exit() include_filters = [ tuple(filt.split(':', 1)) for filt in cli['include-filter'] ] exclude_filters = [ tuple(filt.split(':', 1)) for filt in cli['exclude-filter'] ] songs_to_delete, _ = mcw.get_google_songs(include_filters=include_filters, exclude_filters=exclude_filters, all_includes=cli['all-includes'], all_excludes=cli['all-excludes']) if cli['dry-run']: logger.info("Found {0} songs to delete".format(len(songs_to_delete))) if songs_to_delete: logger.info("\nSongs to delete:\n") for song in songs_to_delete: title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.log( QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) else: logger.info("\nNo songs to delete") else: if songs_to_delete: confirm = cli['yes'] or cli['quiet'] logger.info("") if confirm or input( "Are you sure you want to delete {0} song(s) from Google Music? (y/n) " .format(len(songs_to_delete))) in ("y", "Y"): logger.info("\nDeleting {0} songs from Google Music\n".format( len(songs_to_delete))) songnum = 0 total = len(songs_to_delete) pad = len(str(total)) for song in songs_to_delete: mcw.api.delete_songs(song['id']) songnum += 1 title = song.get('title', "<empty>") artist = song.get('artist', "<empty>") album = song.get('album', "<empty>") song_id = song['id'] logger.debug("Deleting {0} -- {1} -- {2} ({3})".format( title, artist, album, song_id)) logger.info( "Deleted {num:>{pad}}/{total} song(s) from Google Music" .format(num=songnum, pad=pad, total=total)) else: logger.info("\nNo songs deleted.") else: logger.info("\nNo songs to delete") mcw.logout() logger.info("\nAll done!")
def main(): cli = dict((key.lstrip("-<").rstrip(">"), value) for key, value in docopt(__doc__).items()) if cli['no-recursion']: cli['max-depth'] = 0 else: cli['max-depth'] = int(cli['max-depth']) if cli['max-depth'] else float('inf') if cli['quiet']: logger.setLevel(QUIET) else: logger.setLevel(logging.INFO) if not cli['input']: cli['input'] = [os.getcwd()] if not cli['output']: cli['output'] = os.getcwd() include_filters = [tuple(filt.split(':', 1)) for filt in cli['include-filter']] exclude_filters = [tuple(filt.split(':', 1)) for filt in cli['exclude-filter']] mmw = MusicManagerWrapper(enable_logging=cli['log']) mmw.login(oauth_filename=cli['cred'], uploader_id=cli['uploader-id']) if not mmw.is_authenticated: sys.exit() mcw = MobileClientWrapper(enable_logging=cli['log']) if cli['playlists']: login_mobile_client_from_cache(mcw, oauth_filename=cli['cred']) if not mcw.is_authenticated: sys.exit() if cli['down']: matched_google_songs, filtered_google_songs = mmw.get_google_songs( include_filters=include_filters, exclude_filters=exclude_filters, all_includes=cli['all-includes'], all_excludes=cli['all-excludes'] ) cli['input'] = [template_to_base_path(cli['output'], matched_google_songs)] matched_local_songs, filtered_local_songs, excluded_local_songs = mmw.get_local_songs(cli['input'], exclude_patterns=cli['exclude']) # keep track of all local songs all_local_songs_dict = dict() def add_to_local_songs (filepath): all_local_songs_dict[os.path.abspath(filepath)] = True def all_local_songs (): return list(all_local_songs_dict.keys()) for filepath in matched_local_songs + filtered_local_songs + excluded_local_songs: metadata = _get_mutagen_metadata(filepath); songpath = template_to_filepath(cli['output'], metadata) + '.mp3' if filepath != songpath: utils.make_sure_path_exists(os.path.dirname(songpath), 0o700) print("{0} ~> {1}".format(filepath, songpath)) shutil.move(filepath, songpath) add_to_local_songs(songpath) # add_to_local_songs(filepath) # for filepath in matched_local_songs + filtered_local_songs + excluded_local_songs: # add_to_local_songs(filepath) def download_songs(songs_to_download): if songs_to_download: if cli['dry-run']: logger.info("\nFound {0} song(s) to download".format(len(songs_to_download))) for song in songs_to_download: title = song.get('title', "<title>") artist = song.get('artist', "<artist>") album = song.get('album', "<album>") song_id = song['id'] metadata = metadata_from_mobile_client_song(song) songpath = template_to_filepath(cli['output'], metadata) + '.mp3' logger.log(QUIET, "{0} -- {1} -- {2} ({3})".format(title, artist, album, song_id)) add_to_local_songs(songpath) else: logger.info("\nDownloading {0} song(s) from Google Music\n".format(len(songs_to_download))) results = mmw.download(songs_to_download, template=cli['output']) # keep track of new filepaths for res in results: if res['result'] == 'downloaded': add_to_local_songs(res['filepath']) else: logger.info("\nNo songs to download") def download_missing_google_songs(mmw_songs): # recheck the local songs after any previous sync logger.info("\nFinding missing songs...") songs_to_download = compare_song_collections(mmw_songs, all_local_songs()) songs_to_download.sort(key=lambda song: (song.get('artist'), song.get('album'), song.get('track_number'))) return download_songs(songs_to_download) logger.info("\nFetching Library songs...") download_missing_google_songs(matched_google_songs) if cli['playlists']: logger.info("Syncing playlists...") # get all songs from mobileClient api (to include ratings) all_songs = mcw.api.get_all_songs() # get id, prioritize trackId over id def songid (track): return track['trackId'] if 'trackId' in track else track['id'] # create a dictionary of all fetched google songs, indexed by id def songs_to_dict (songs, song): id = songid(song) songs[id] = song return songs # create lookup dicts for tracks (mmw) and songs (mcw) songs_dict = reduce(songs_to_dict, all_songs, {}) tracks_dict = reduce(songs_to_dict, matched_google_songs + filtered_google_songs, {}) # returns music manager wrapper tracks for list of objects with song id or trackId # also removes duplicates def get_mmw_tracks (songs): tracks = [] seen = {} for song in songs: id = songid(song) if id not in seen: tracks.append(tracks_dict[id]) seen[id] = True return tracks; # path to save playlists playlists_dir = os.path.abspath(cli['playlists']) # ensure directory is there utils.make_sure_path_exists(playlists_dir, 0o700) def create_playlist_file (name, songs, outpath): filename = os.path.join(outpath, name + '.m3u') if not cli['dry-run']: m3u = [u'#EXTM3U'] for track in songs: id = songid(track) song = songs_dict[id] artist = song['artist'] title = song['title'] duration = str(int(int(song['durationMillis']) / 1000)) if 'durationMillis' in song else '0' metadata = metadata_from_mobile_client_song(song) songpath = template_to_filepath(cli['output'], metadata) + '.mp3' m3u.append(u'#EXTINF,' + duration + ',' + song['artist'] + ' - ' + song['title']) m3u.append(os.path.relpath(songpath, outpath)) # track this song as a local song to keep add_to_local_songs(songpath) # write m3u file contentstr = u'\n'.join(m3u) # write to temp file with tempfile.NamedTemporaryFile(suffix='.m3u', delete=False) as temp: temp.write(contentstr.encode('UTF-8-SIG')) # move tempfile into place utils.make_sure_path_exists(os.path.dirname(filename), 0o700) shutil.move(temp.name, filename) logger.log(QUIET, "Playlist ({0} tracks): {1}".format(len(songs), filename)) return filename # get playlists with ordered lists of tracks playlists = mcw.api.get_all_user_playlist_contents() # concatenate all the playlist tracks into a single list playlist_tracks = reduce(lambda x, y: x + y, map(lambda x: x['tracks'], playlists)) if len(playlists) else [] # remove duplicates and get mmw tracks to download playlist_tracks = get_mmw_tracks(playlist_tracks) # download any missing songs logger.info("\nFetching Playlist songs...") download_missing_google_songs(playlist_tracks) # create the m3u files for the playlists created_playlists = []; for playlist in playlists: playlist_filename = create_playlist_file(playlist['name'], playlist['tracks'], playlists_dir) created_playlists.append(playlist_filename) # create an m3u file for all favorited songs favorites_playlist_name = cli['favorites'] if 'favorites' in cli else '___auto_favorites___' # filter mobile client songs into favorites list thumbs_up = [t for t in all_songs if int(t['rating']) > 3] # most recent first thumbs_up.sort(key=lambda song: (int(song.get('lastModifiedTimestamp')) * -1)) # get music_manager_wrapper style tracks to compare thumbs_up_tracks = get_mmw_tracks(thumbs_up) # download any missing favorited songs logger.info("\nFetching Favorited songs...") download_missing_google_songs(thumbs_up_tracks) # create favorites playlist created_playlist_filename = create_playlist_file(favorites_playlist_name, thumbs_up, playlists_dir) created_playlists.append(created_playlist_filename) if cli['removed']: logger.info("Moving Removed songs...") # path to move songs removed from google music removed_dir = os.path.abspath(cli['removed']) # ensure directory is there utils.make_sure_path_exists(removed_dir, 0o700) # local songs after sync all_google_songs = matched_google_songs + filtered_google_songs songs_to_move = compare_song_collections(all_local_songs(), all_google_songs) for filepath in songs_to_move: rel_file_path = os.path.relpath(filepath, cli['input'][0]) removed_filepath = os.path.join(removed_dir, rel_file_path) utils.make_sure_path_exists(os.path.dirname(removed_filepath), 0o700) logger.info("Removing {0} ~> {1}".format(filepath, removed_filepath)) if not cli['dry-run']: shutil.move(filepath, removed_filepath) # clean up empty folders logger.info(" ") if not cli['dry-run']: removeEmptyFolders(cli['input'][0], False) if cli['playlists']: logger.info("Moving Removed playlists...") # path to move songs removed from google music removed_playlists_dir = os.path.join(os.path.abspath(cli['removed']), cli['playlists']) # local playlists after sync local_playlists = [os.path.join(dp, f) for dp, dn, fn in os.walk(playlists_dir) for f in fn] playlists_to_remove = list(set(local_playlists) - set(created_playlists)) for filepath in playlists_to_remove: rel_file_path = os.path.relpath(filepath, playlists_dir) removed_filepath = os.path.join(removed_playlists_dir, rel_file_path) utils.make_sure_path_exists(os.path.dirname(removed_filepath), 0o700) logger.info("Removing {0}".format(rel_file_path)) if not cli['dry-run']: shutil.move(filepath, removed_filepath) # clean up empty folders logger.info(" ") if not cli['dry-run']: removeEmptyFolders(playlists_dir, False) else: matched_google_songs, _ = mmw.get_google_songs() logger.info("") matched_local_songs, songs_to_filter, songs_to_exclude = mmw.get_local_songs( cli['input'], include_filters=include_filters, exclude_filters=exclude_filters, all_includes=cli['all-includes'], all_excludes=cli['all-excludes'], exclude_patterns=cli['exclude'], max_depth=cli['max-depth'] ) logger.info("\nFinding missing songs...") songs_to_upload = compare_song_collections(matched_local_songs, matched_google_songs) # Sort lists for sensible output. songs_to_upload.sort() songs_to_exclude.sort() if cli['dry-run']: logger.info("\nFound {0} song(s) to upload".format(len(songs_to_upload))) if songs_to_upload: logger.info("\nSongs to upload:\n") for song in songs_to_upload: logger.log(QUIET, song) else: logger.info("\nNo songs to upload") if songs_to_filter: logger.info("\nSongs to filter:\n") for song in songs_to_filter: logger.log(QUIET, song) else: logger.info("\nNo songs to filter") if songs_to_exclude: logger.info("\nSongs to exclude:\n") for song in songs_to_exclude: logger.log(QUIET, song) else: logger.info("\nNo songs to exclude") else: if songs_to_upload: logger.info("\nUploading {0} song(s) to Google Music\n".format(len(songs_to_upload))) mmw.upload(songs_to_upload, enable_matching=cli['match'], delete_on_success=cli['delete-on-success']) else: logger.info("\nNo songs to upload") # Delete local files if they already exist on Google Music. if cli['delete-on-success']: for song in matched_local_songs: try: os.remove(song) except: logger.warning("Failed to remove {} after successful upload".format(song)) mmw.logout() mcw.logout() logger.info("\nAll done!")