Пример #1
0
def _process_youtube_upload(youtube_url, ydl_opts, music, metadata_opts,
                            credential, uploader_name):
    manager = Musicmanager()
    manager.login(credential, uploader_name=uploader_name)
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        info_dict = ydl.extract_info(youtube_url, download=False)
        if music.title == "":
            music.title = info_dict.get('title', None)
            music.save()
            metadata_opts = {
                i: getattr(music, i)
                for i in [
                    'title', 'album', 'composer', 'genre', 'language',
                    'artist', 'album_artist'
                ]
            }
            logger.debug('New metadata opts: ' + str(metadata_opts))
            ffmpeg_mp3_metadata_pp = FFmpegMP3MetadataPP(ydl, metadata_opts)
            ydl.add_post_processor(ffmpeg_mp3_metadata_pp)
            ydl.download([youtube_url])
            music_filepath = ydl.prepare_filename(info_dict)
            if not music_filepath.endswith('.mp3'):
                music_filepath = music_filepath.replace(
                    music_filepath[music_filepath.rfind('.'):], '.mp3')
                logger.debug("Music filepath: " + music_filepath)
    manager.upload(music_filepath,
                   enable_matching=True,
                   enable_transcoding=False)  # Already transcoding.
    if os.path.isfile(music_filepath):
        os.remove(music_filepath)
Пример #2
0
def download(mode, url, num):
    print(f"Downloading for {mode}")

    #Options
    ydl_opts = {
        'format':
        'bestaudio/best',
        'postprocessors': [{
            'key': 'FFmpegExtractAudio',
            'preferredcodec': 'mp3',
            'preferredquality': '320',
        }],
        'logger':
        MyLogger(),
        'progress_hooks': [my_hook],
        'outtmpl':
        folders[num][mode][0] + '/%(title)s.%(ext)s'
    }

    #Download the video and extract all the metadata
    with youtube_dl.YoutubeDL(ydl_opts) as ydl:
        info_dict = ydl.extract_info(url, download=True)
        video_title = info_dict.get('title', None)
        video_filename = '.'.join(
            ydl.prepare_filename(info_dict).split('.')[:-1]) + '.mp3'
    print(video_filename)

    #Edit mp3 tag.
    try:
        print(f"Editing artist tag to {mode.capitalize()}...")
        mp3 = MP3File(video_filename)
        mp3.artist = mode.title()
        mp3.save()
        insert_album_art(video_filename, info_dict['id'])
        print("Done!\n")
    except Exception as e:
        print("Error at editing mp3 tag.\n")
        print(e)

    #Backup
    if num != 3:
        try:
            print(f"Making a backup of {video_title}...")
            copy(video_filename, folders[num][mode][1])
            print("Done!\n")
        except:
            print("Error at doing backup.\n")

    #Upload to google
    if num != 3:
        try:
            print(f"Uploading {video_title} to Google Music\n")
            print(f'With url {url}')
            mm = Musicmanager()
            mm.login(uploader_id='D0:50:99:83:B0:0C')
            mm.upload(video_filename)
            print("Done!\n")
        except Exception as e:
            print("Error at uploading the song to google:\n" + e)
Пример #3
0
def upload(path):
    mm = Musicmanager()
    mm.login()

    for root, dirs, files in os.walk(path):
        for file_ in files:
            mp3FilePath = os.path.join(root, file_)
            print( "upload : " + file_ )
            mm.upload(mp3FilePath)
            os.remove(mp3FilePath)
Пример #4
0
class GoogleMusicManager:
    def __init__(self):
        self.api = Musicmanager(debug_logging=False)
        refresh_token = json.loads(
            settings['google']['musicmanager'])['refresh_token']
        credentials = session.credentials_from_refresh_token(
            refresh_token, session.Mobileclient.oauth)
        self.api.login(credentials)

    def upload_song(self, file):
        self.api.upload(file)
Пример #5
0
class GoogleMusicManager:
    def __init__(self):
        self.api = Musicmanager(debug_logging=False)
        with open(path + "oauth.cred", 'w+') as tmp:
            tmp.write(settings['google']['musicmanager'])
            tmp.close()
            self.api.login(tmp.name)
            os.remove(tmp.name)

    def upload_song(self, file):
        self.api.upload(file)
Пример #6
0
class GoogleMusic:
    def __init__(self):
        self.api = Musicmanager()
        try:
            print(os.getcwd())
            if not self.api.login(oauth_credentials=config.auth):
                self.api.perform_oauth(storage_filepath=config.auth, open_browser=False)
                self.api.login(oauth_credentials=config.auth)
        except:
            pass

    def upload_audio(self, filepath, transcode_quality='320k'):
        self.api.upload(filepath, enable_matching=False, transcode_quality=transcode_quality)
        print("Upload finished")
Пример #7
0
def main():
    args, config = init()

    if not os.path.isdir(config['PROG']['DownloadPath']):
        os.mkdir(config['PROG']['DownloadPath'])

    sc_download(
        config['SOUNDCLOUD']['PlaylistUrl'],
        config['PROG']['DownloadPath']
    )

    mc = Mobileclient()
    mc.login(config['GMUSIC']['User'], config['GMUSIC']['Password'], Mobileclient.FROM_MAC_ADDRESS)

    mm = Musicmanager()
    if not (os.path.exists(gmclients.OAUTH_FILEPATH) and mm.login(gmclients.OAUTH_FILEPATH)):
        mm.perform_oauth(gmclients.OAUTH_FILEPATH, open_browser=True)
        if not mm.login(gmclients.OAUTH_FILEPATH):
            sys.stderr.write('Musicmanager could not authenticate')

    if config['GMUSIC']['TargetPlaylist'] not in set([item['name'] for item in mc.get_all_playlists() if not item['deleted']]):
        mc.create_playlist(name=config['GMUSIC']['TargetPlaylist'], description='Tracks synchronized using {}'.format(__prog__), public=False)

    playlist_id, current_members = gm_get_current_pl_member(mc, config['GMUSIC']['TargetPlaylist'])

    for track in os.listdir(config['PROG']['DownloadPath']):
        print('Uploading {}'.format(track))
        uploaded_id = gm_extract_id(mm.upload('{}{}'.format(config['PROG']['DownloadPath'], track)))
        mc.add_songs_to_playlist(playlist_id, uploaded_id)
def upload(directory='.',
           oauth=os.environ['HOME'] + '/oauth',
           remove=False,
           uploader_id=__DEFAULT_MAC__):
    logging.basicConfig(level=logging.INFO)
    logger = logging.getLogger(__name__)
    logger.info("Init Daemon - Press Ctrl+C to quit")

    api = Musicmanager()
    event_handler = MusicToUpload()
    event_handler.api = api
    event_handler.path = directory
    event_handler.willDelete = remove
    event_handler.logger = logger
    if not api.login(oauth, uploader_id):
        print("Error with oauth credentials")
        sys.exit(1)
    files = [file for file in glob.glob(directory + '/**/*', recursive=True)]
    for file_path in files:
        if os.path.isfile(file_path):
            logger.info("Uploading : " + file_path)
            uploaded, matched, not_uploaded = api.upload(file_path, True)
            if remove and (uploaded or matched):
                os.remove(file_path)
    observer = Observer()
    observer.schedule(event_handler, directory, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
Пример #9
0
class GMusicPodcastSyncDestination(PodcastSyncDestination):
    def __init__(self):
        super(GMusicPodcastSyncDestination, self).__init__()
        self.serviceIdentifier = "GOO"
        self.serviceName = "Google Music"
        self.musicManager = Musicmanager()
        self.mobileClient = Mobileclient()
        oAuthFile = "gMusic.oauth"
        if not os.path.isfile(oAuthFile):
            if not self.musicManager.perform_oauth(oAuthFile, True):
                print "Failed to authenticate Music Manager."
                raise PodcastSyncDestinationException("Authentication Failure.")
        else:
            try:
                self.musicManagerauthenticated = self.musicManager.login(oAuthFile)
            except gmusicapi.exceptions.AlreadyLoggedIn:
                pass
        username = raw_input("Enter Google Username: "******"Enter Google Password: "******"Authentication Failure.")
            # perform a push task. should return a PodFastPodcastPushedEpisode instance

    def pushEpisode(self, podcastSyncTaskEpisodePush):
        (uploaded, matched, not_uploaded) = self.musicManager.upload([podcastSyncTaskEpisodePush.localFilename])
        songGoogleMusicID = ""
        if not_uploaded:  # If the track was not uploaded, it may have been uploaded in the past.
            p = re.compile("ALREADY_EXISTS\\((.*)\\)")
            m = p.findall(not_uploaded[podcastSyncTaskEpisodePush.localFilename])
            songGoogleMusicID = m[0]
        else:
            songGoogleMusicID = uploaded[podcastSyncTaskEpisodePush.localFilename]
        print "Track uploaded Successfully. ID:" + songGoogleMusicID
        gmusicPlayLists = self.mobileClient.get_all_playlists()
        playListExists = False
        gmusicPlaylistID = ""
        for gmusicPlayList in gmusicPlayLists:
            if gmusicPlayList["name"] == podcastSyncTaskEpisodePush.playlistName:
                playListExists = True
                gmusicPlaylistID = gmusicPlayList["id"]
                break
        if not playListExists:
            print "Creating playlist..."
            gmusicPlaylistID = self.mobileClient.create_playlist(podcastSyncTaskEpisodePush.playlistName)
        addedEntries = self.mobileClient.add_songs_to_playlist(gmusicPlaylistID, [songGoogleMusicID])
        print "Moved track to playlist."
        return songGoogleMusicID
        # Pull (deletes) an episode from the destination returns true on success, False on faiilure

    def pullEpisode(self, podcastSyncTaskEpisodePull):
        self.mobileClient.delete_songs([podcastSyncTaskEpisodePull.syncDestinationID])
        # TODO: Error check here.
        return True
Пример #10
0
def upload(request):
    # TODO: Async status updates?
    if not request.user.is_authenticated:
        return HttpResponse('log in first')
    credential = request.user.profile.google_oauth
    if not credential:
        return HttpResponse('no creds')
    manager = Musicmanager()
    # TODO: Maybe change mac address for each user?
    login_success = manager.login(
        credential,
        uploader_name="GMusicManagerOnline - {}".format(request.user.username))
    form = MusicUploadForm()
    args = {'can_login': login_success, 'form': form, 'success': False}
    if request.method == "POST":
        form = MusicUploadForm(request.POST, request.FILES)
        if form.is_valid():
            music = form.save()
            music_file = request.FILES.get('music_file')
            ext = music_file.name[music_file.name.rfind('.'):]
            fs = FileSystemStorage()
            filename = fs.save("{0}{1}".format(request.user.username, ext),
                               music_file)
            music_filepath = fs.path(filename)
            post_filepath = music_filepath + ".mp3"
            options = {
                i: getattr(music, i)
                for i in [
                    'title', 'album', 'composer', 'genre', 'language',
                    'artist', 'album_artist'
                ] if getattr(music, i) != ""
            }
            logger.info("Transcoding metadata: " + str(options))
            options.update({'quality': '320k'})
            _transcode(music_filepath, options, post_filepath)
            if os.path.isfile(music_filepath):
                os.remove(music_filepath)
            success, _, _ = manager.upload(  # Already transcoding.
                post_filepath,
                enable_matching=True,
                enable_transcoding=False)
            if os.path.isfile(post_filepath):
                os.remove(post_filepath)
            args.update({'success': True})
        args.update({'form': form})
    manager.logout()
    return render(request, 'core/upload.html', args)
Пример #11
0
def upload(file_path):
    storage = oauth2client.file.Storage(CREDENTIALS_PATH)
    credentials = storage.get()

    if not credentials or credentials.invalid:
        Musicmanager.perform_oauth(CREDENTIALS_PATH, open_browser=False)

    mm = Musicmanager()
    mm.login(CREDENTIALS_PATH)

    result = mm.upload(file_path, enable_matching=True)
    if result[1]:
        raise Exception('{}はアップロード済みです'.format(file_path))
    elif result[2]:
        raise Exception('アップロード失敗 {}'.format(result[2][file_path]))

    os.remove(file_path)
Пример #12
0
class GoogleManager():

    def __init__(self, directory):
        self.music_dir = directory

        self.Google = Musicmanager()
        self.Google.login()

    def upload(self):
        files = []
        for dirpath, dirnames, filenames in walk(self.music_dir):
            for name in filenames:
                if name.endswith('.mp3'):
                    files += [join(dirpath, name)]

        for f in files:
            ret = self.Google.upload(f)
            print(ret)
Пример #13
0
def main():
    path = sys.argv[1]
    if not os.path.exists(path):
        print("Invalid file path. %s" % path)
        return

    api = Musicmanager()
    api.login()

    if not api.is_authenticated():
        print("Login Error\n")
        return

    print("start upload...\n")
    upload_info = api.upload(path)
    print(upload_info)
    print("upload is completed.\n")

    api.logout()
Пример #14
0
class Kotone:

    def __init__(self, device_id: str, cred_mc: oauth2client.client.OAuth2Credentials, cred_mm: oauth2client.client.OAuth2Credentials):
        self._mc = Mobileclient()
        if not self._mc.oauth_login(device_id, cred_mc):
            raise RuntimeError('Mobileclient login failed')
        self._mm = Musicmanager()
        if not self._mm.login(cred_mm, _UPLOADER_ID, _UPLOADER_NAME):
            raise RuntimeError('Musicmanager login failed')

    def get_songs(self):
        return self._mc.get_all_songs()

    def download_song(self, song_id: str) -> Tuple[str, bytes]:
        return self._mm.download_song(song_id)

    def stream_url(self, song_id: str) -> str:
        return self._mc.get_stream_url(song_id)

    def upload(self, paths):
        return self._mm.upload(paths)
Пример #15
0
	def songs_uploader(self):
		ip = urllib2.urlopen('http://ip.42.pl/raw').read() #Obtain your public IP address
		mac_binary = str(get_mac()) #Obtain binary MAC address
		temp = mac_binary.replace(':', '').replace('-', '').replace('.', '').upper()
		mac_h3x = temp[:2] + ":" + ":".join([temp[i] + temp[i+1] for i in range(2,12,2)]) #Convert MAC from 48bit int to hexadecimal string
		user = pwd.getpwuid(os.getuid())[0] #Get your system's username
		
		api = Musicmanager()
		hostname = '<' + ip + '>' + '' + '(gmusicapi-{2.0.0})'
		Musicmanager.perform_oauth(storage_filepath='/home/' + user + '/.config/gmusicapi/oauth.cred', open_browser=False)
		api.login(oauth_credentials='/home/' + user + '/.config/gmusicapi/oauth.cred', uploader_id=mac_h3x, uploader_name=hostname)
		gmusicapi.clients.Musicmanager(debug_logging=True, validate=True)
		
		#newWorkingDirectory = '../home'
		#os.path.join(os.path.abspath(sys.path[0]), newWorkingDirectory) #Change the working directory
		filepath = '/home/blackram/Scrivania/BRES_/UMM/ciao.mp3'
		uploading = api.upload(filepath, transcode_quality=3, enable_matching=False)
		print 'Uploading...'
		f = open('uploading.txt','w') #log
		f.write(str(uploading))
		f.close()
		
		final = re.search("GetUploadSession error 200: this song is already uploaded", open('uploading.txt','r').read())
		if final is None:
			print '\033[32mTrack uploaded!\033[0m'
		else:
			print '\033[31mTrack already exists in your library!\033[0m'
		
		choice = raw_input("Exit from uploader? [Y/N] ")
		if choice == 'y' or choice == 'Y':
			print 'Return to main menu.'
			Musicmanager.logout(revoke_oauth=False)
			UMM.read_information()
		elif choice == 'n' or choice == 'N':
			print 'Okay.'
			UMM.songs_uploader()
Пример #16
0
    print "usage:" + sys.argv[0] + " filename [playlist name]"
    sys.exit()

file = params[1]

if len(params) == 3:
    plname = params[2]
else:
    plname = None

mm = Musicmanager()
api = Mobileclient()
mm.login()
api.login('GoogleID', 'Password')

track = mm.upload(file)
track_id = track[0][file]

if plname:
    playlist_id = None
    playlists = api.get_all_playlists()
    for playlist in playlists:
        if plname == playlist['name']:
            playlist_id = playlist['id']
            break

    if playlist_id == None:
        playlist_id = api.create_playlist(plname)

    api.add_songs_to_playlist(playlist_id, track_id)
Пример #17
0
class Gmusic(BeetsPlugin):
    def __init__(self):
        super(Gmusic, self).__init__()
        # Checks for OAuth2 credentials,
        # if they don't exist - performs authorization
        self.m = Musicmanager()
        if os.path.isfile(gmusicapi.clients.OAUTH_FILEPATH):
            self.m.login()
        else:
            self.m.perform_oauth()

    def commands(self):
        gupload = Subcommand('gmusic-upload',
                             help=u'upload your tracks to Google Play Music')
        gupload.func = self.upload

        search = Subcommand('gmusic-songs',
                            help=u'list of songs in Google Play Music library'
                            )
        search.parser.add_option('-t', '--track', dest='track',
                                 action='store_true',
                                 help='Search by track name')
        search.parser.add_option('-a', '--artist', dest='artist',
                                 action='store_true',
                                 help='Search by artist')
        search.func = self.search
        return [gupload, search]

    def upload(self, lib, opts, args):
        items = lib.items(ui.decargs(args))
        files = [x.path.decode('utf-8') for x in items]
        ui.print_(u'Uploading your files...')
        self.m.upload(filepaths=files)
        ui.print_(u'Your files were successfully added to library')

    def search(self, lib, opts, args):
        password = config['gmusic']['password']
        email = config['gmusic']['email']
        password.redact = True
        email.redact = True
        # Since Musicmanager doesn't support library management
        # we need to use mobileclient interface
        mobile = Mobileclient()
        try:
            mobile.login(email.as_str(), password.as_str(),
                         Mobileclient.FROM_MAC_ADDRESS)
            files = mobile.get_all_songs()
        except NotLoggedIn:
            ui.print_(
                u'Authentication error. Please check your email and password.'
            )
            return
        if not args:
            for i, file in enumerate(files, start=1):
                print(i, ui.colorize('blue', file['artist']),
                      file['title'], ui.colorize('red', file['album']))
        else:
            if opts.track:
                self.match(files, args, 'title')
            else:
                self.match(files, args, 'artist')

    @staticmethod
    def match(files, args, search_by):
        for file in files:
            if ' '.join(ui.decargs(args)) in file[search_by]:
                print(file['artist'], file['title'], file['album'])
Пример #18
0
translator = Translator()

# Get file paths from node
file_names = translator.get_input()

# Returns path to system stored oauth
oauth_path = clients.OAUTH_FILEPATH

# Init Musicmanager and login
mm = Musicmanager()
is_logged_in = mm.login(oauth_path)

if is_logged_in:
    # Matching set to false due to lack of ffmpeg or avconv
    upload_result = mm.upload(file_names, '320k', False)
    print json.dumps(upload_result)
    # return upload_result

    if upload_result[0] != {}:
        print('Something happened here!')
else:
    sys.exit('Not logged in')







Пример #19
0
def main():
    #### Requests user specifies update library and/or playlists
    if len(sys.argv) != 3:
        print('Specify T/F arguments for uploading and updating playlists')
        print('e.g. python ' + sys.argv[0] + ' 1 0')
        print('which would:\n--> upload new songs\n--> NOT update playlists')
        sys.exit(0)

    #### Parameters
    music_dir = '/home/conor/Music/'
    print('Local music directory set to:', music_dir)
    accepted = input('Type "y" if this is correct directory: ')
    if accepted.lower() != 'y':
        print('Edit music_dir variable in source to run script...')
        print('Ending music management.')
        sys.exit(0)

    #### Some general information needed for both tasks is collected here

    # Get mp3 file names from music folder
    local_song_paths = glob.glob(music_dir + '*.mp3')

    # Get individual song names
    local_song_names = set()
    for p in local_song_paths:
        _, song_name = os.path.split(p)
        local_song_names.add(song_name)

    # Authenticate
    mc = Mobileclient()
    mc.oauth_login('38e42c4b00ca0a10')  # Authenticates using on-disk token
    print('Mobile client authentication complete...')

    # Create dict of gpm 'song'': 'id' pairs
    song_ids = {}
    gpm_songs = mc.get_all_songs()
    for song in gpm_songs:
        song_ids[song['title']] = song['id']

    #### Manage upload/deletion of songs
    uploading = sys.argv[1]
    if uploading == '1':
        mm = Musicmanager()
        mm.login(uploader_id='EE:20:80:B4:17:A9'
                 )  # Authenticates using on-disk token
        print('Music manager authentication complete...')

        # Delete songs that no longer exist locally
        to_delete = set()
        for song in song_ids:
            if song not in local_song_names:
                to_delete.add(song)
        if len(to_delete) == 0:
            print('No songs to delete.')
        else:
            print('{} songs to delete:'.format(len(to_delete)))
            print([s for s in to_delete])
            # delete_songs() method requires a list as input
            to_delete_ids = []
            for s in to_delete:
                song_id = song_ids[s]
                to_delete_ids.append(song_id)
            mc.delete_songs(to_delete_ids)
            print('Deleted songs.')

        #### Uploading
        to_upload = []
        for s in local_song_names:
            if s not in song_ids:
                to_upload.append(music_dir + s)
        print('{} songs to upload.'.format(len(to_upload)))
        if len(to_upload) != 0:
            accepted = input('Type "y" to commence upload now: ')
            if accepted.lower() != 'y':
                print('Ending music management.')
                sys.exit(0)
            mm.upload(to_upload)

    #### Create and edit playlists as required
    # Works by deleting all playlists and then re-creating from scratch
    playlisting = sys.argv[2]
    if playlisting == '1':
        # Refresh song list
        # (since we have uploaded new songs since original list generated)
        song_ids = {}
        gpm_songs = mc.get_all_songs()
        for song in gpm_songs:
            song_ids[song['title']] = song['id']

        # Flush old playlists
        print('Deleting old playlists...')
        gpm_playlists = mc.get_all_playlists()
        for pl in gpm_playlists:
            mc.delete_playlist(pl['id'])
        print('Playlists deleted.')

        # Keep a dictionary of created playlists to prevent duplication
        playlist_ids = {}
        total = len(song_ids)
        completed = 0

        # Create and update playlists
        print('Organising songs:')
        for s in song_ids:
            sid = song_ids[s]
            req_pls = required_playlists(s)
            for pl in req_pls:
                if pl in playlist_ids:
                    pid = playlist_ids[pl]
                else:
                    pid = mc.create_playlist(name=pl)
                    playlist_ids[pl] = pid

                mc.add_songs_to_playlist(pid, sid)
            completed += 1
            # Console output for number of songs sorted
            sys.stdout.write("\r{}/{} processed".format(completed, total))
            sys.stdout.flush()
        print()
Пример #20
0
class GoolgeMusicUploader(object):
    "Google music upload class"

    def __init__(self, config):
        self.credential_file = ''

        if len(config.googleplay_credential_file) > 0:
            self.credential_file = config.googleplay_credential_file
        else:
            self.credential_file = clients.OAUTH_FILEPATH

        self.mac_address = config.mac_address_for_gplay
        self.manager = Musicmanager(False)
        self.logger = logging.getLogger(__name__)

    def login(self):
        "Logs in"

        if not self.manager.login(self.credential_file, self.mac_address):
            raise AuthError(
                'Could not authenticate music manager using {}'.format(
                    self.credential_file))

    def logout(self):
        "Logs out"
        if self.manager.is_authenticated:
            success = self.manager.logout()
            if success:
                self.logger.info('Logged out of Google Play Music')
            else:
                self.logger.warning('Failed to log out of Google Play Music')

    def upload(self, track_dir):
        "Does the upload."

        if not self.manager.is_authenticated:
            raise AuthError(
                "Music Manager not authenticated. Call 'login' first.")

        if not isdir(track_dir):
            raise DirectoryNotFoundError(track_dir)

        files = absolute_files(track_dir)

        info = TrackInfo()
        info.load(get_track_info_file(files))

        track_file = get_track_file(files)

        result = UploadResult(track_dir, track_file, info.full_title)

        if track_file == DEFAULT_FILE_NAME:
            result.set_failure('MP3 Track file not found')
            return result

        locked = lock_file_exists(track_dir)
        if locked:
            result.set_failure('Lock file exists')
            return result

        metadata = AudioMetadata(track_file)
        metadata.apply_album_art(get_album_art_file(files))
        metadata.apply_track_info(info)

        success, message = self.__upload_file__(track_file)
        if success:
            result.set_success(message)
        else:
            result.set_failure(message)
        return result

    def __upload_file__(self, track_file):
        self.logger.info('Uploading %s', track_file)
        upload_result = self.manager.upload(track_file)

        if upload_result[0] != {}:
            return True, upload_result[0]

        elif upload_result[1] != {}:
            return True, upload_result[2]

        elif upload_result[2] != {}:
            reason = list(upload_result[2].items())[0]
            return False, 'Couldn\'t upload {} because {}'.format(
                reason[0], reason[1])
Пример #21
0
from gmusicapi import Musicmanager
from os import listdir
from os.path import isfile, join
import os
import time
import subprocess

api = Musicmanager()
api.login()
mypath = '/home/pi/musics'
while True:
    onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
    if len(onlyfiles) > 0:
        time.sleep(5)
        for file in onlyfiles:
            print(file)
            api.upload(mypath + '/' + file)
            os.remove(mypath + '/' + file)
	


Пример #22
0
os.chdir('.yt_to_play')
Path('download_temp').mkdir(exist_ok=True)
os.chdir('download_temp')

ydl_opts = {
    'format':
    'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
    'outtmpl':
    '%(title)s.%(ext)s',
    'download_archive':
    '../downloaded.txt',
}

with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(args)

print('Uploading...')
mm = Musicmanager()
oauth = Path('../oauth.cred')
if not (oauth.exists() and oauth.is_file()):
    mm.perform_oauth(oauth)
mm.login(oauth)
mm.upload([os.path.join(os.getcwd(), f) for f in os.listdir(os.getcwd())])
for f in os.listdir(os.getcwd()):
    os.remove(f)
Пример #23
0
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.mc.get_all_user_playlist_contents()
        #self.playlists = self.mc.get_all_playlists()
        #self.playlists = self.wc.get_all_playlist_ids(auto=False)
        self.all_songs = self.mc.get_all_songs()
        #print "Got %d playlists." % len(self.playlists['user'])
        print "Got %d playlists containing %d songs." % (len(
            self.playlists), len(self.all_songs))
        print ""

    def auth(self):
        self.logged_in = self.mc.login(self.email, self.password)
        #self.logged_in = self.wc.login(self.email, self.password)
        if not self.logged_in:
            print "Login failed..."
            exit()

        print ""
        print "Logged in as %s" % self.email
        print ""

        if not os.path.isfile(OAUTH_FILEPATH):
            print "First time login. Please follow the instructions below:"
            self.mm.perform_oauth()
        self.logged_in = self.mm.login()
        if not self.logged_in:
            print "OAuth failed... try deleting your %s file and trying again." % OAUTH_FILEPATH
            exit()

        print "Authenticated"
        print ""

    def sync_playlist(self, filename, remove_missing):
        #def sync_playlist(self, filename, remove_missing=False):
        filename = self.get_platform_path(filename)
        os.chdir(os.path.dirname(filename))
        title = os.path.splitext(os.path.basename(filename))[0]
        print "Syncing playlist: %s" % filename
        #if title not in self.playlists['user']:
        #print "   didn't exist... creating..."
        #self.playlists['user'][title] = [self.wc.create_playlist(title)]
        print ""

        plid = ""

        for pl in self.playlists:
            if pl['name'] == title:
                plid = pl['id']
                goog_songs = pl['tracks']

        if plid == "":
            print "   didn't exist... creating..."
            plid = self.mc.create_playlist(self, title)

        #plid = self.playlists['user'][title][0]
        #goog_songs = self.wc.get_playlist_songs(plid)
        print "%d songs already in Google Music playlist" % len(goog_songs)
        pc_songs = self.get_files_from_playlist(filename)
        print "%d songs in local playlist" % len(pc_songs)
        print ""

        # Sanity check max 1000 songs per playlist
        if len(pc_songs) > MAX_SONGS_IN_PLAYLIST:
            print "    Google music doesn't allow more than %d songs in a playlist..." % MAX_SONGS_IN_PLAYLIST
            print "    Will only attempt to sync the first %d songs." % MAX_SONGS_IN_PLAYLIST
            del pc_songs[MAX_SONGS_IN_PLAYLIST:]

        existing_files = 0
        added_files = 0
        failed_files = 0
        removed_files = 0
        fatal_count = 0

        for fn in pc_songs:
            if self.file_already_in_list(fn, goog_songs, self.all_songs):
                existing_files += 1
                continue
            print ""
            print "Adding: %s" % os.path.basename(fn).encode('cp1252')
            #print "Adding: %s" % os.path.basename(fn)
            #online = False
            online = self.find_song(fn, goog_songs, self.all_songs)
            #online = self.find_song(fn)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                attempts = 0
                result = []
                while not result and attempts < MAX_UPLOAD_ATTEMPTS_PER_FILE:
                    print "   uploading... (may take a while)"
                    attempts += 1
                    try:
                        result = self.mm.upload(fn)
                    except (BadStatusLine, CannotSendRequest):
                        # Bail out if we're getting too many disconnects
                        if fatal_count >= MAX_CONNECTION_ERRORS_BEFORE_QUIT:
                            print ""
                            print "Too many disconnections - quitting. Please try running the script again."
                            print ""
                            exit()

                        print "Connection Error -- Reattempting login"
                        fatal_count += 1
                        self.wc.logout()
                        self.mc.logout()
                        self.mm.logout()
                        result = []
                        time.sleep(STANDARD_SLEEP)

                    except:
                        result = []
                        time.sleep(STANDARD_SLEEP)

                try:
                    if result[0]:
                        song_id = result[0].itervalues().next()
                    else:
                        song_id = result[1].itervalues().next()
                    print "   upload complete [%s]" % song_id
                except:
                    print "      upload failed - skipping"
                    tag = self.get_id3_tag(fn)
                    print "      failed song:\t%s\t%s\t%s" % (
                        tag['title'].encode('cp1252'),
                        tag['artist'].encode('cp1252'),
                        tag['album'].encode('cp1252'))

            if not song_id:
                failed_files += 1
                continue

            added = self.mc.add_songs_to_playlist(plid, song_id)
            time.sleep(.3)  # Don't spam the server too fast...
            print "   done adding to playlist"
            added_files += 1

        if remove_missing:
            for g in goog_songs:
                for s in self.all_songs:
                    if g['trackId'] == s['id']:
                        print ""
                        print "Removing: %s" % s['title'].encode('cp1252')
                        self.mc.remove_entries_from_playlist(g['id'])
                        #self.wc.remove_songs_from_playlist(plid, s.id)
                        time.sleep(.3)  # Don't spam the server too fast...
                        removed_files += 1

        print ""
        print "---"
        print "%d songs unmodified" % existing_files
        print "%d songs added" % added_files
        print "%d songs failed" % failed_files
        print "%d songs removed" % removed_files

    def get_files_from_playlist(self, filename):
        files = []
        f = codecs.open(filename, encoding='cp1252')
        #f = codecs.open(filename, encoding='utf-8')
        for line in f:
            line = line.rstrip().replace(u'\ufeff', u'')
            if line == "" or line[0] == "#":
                continue
            path = os.path.abspath(self.get_platform_path(line))
            if not os.path.exists(path):
                print "File not found: %s" % line
                continue
            files.append(path)
        f.close()
        return files

    def file_already_in_list(self, filename, goog_songs, all_songs):
        tag = self.get_id3_tag(filename)
        print "Searching for\t%s\t%s\t%s" % (tag['title'].encode('cp1252'),
                                             tag['artist'].encode('cp1252'),
                                             tag['album'].encode('cp1252'))
        i = 0
        while i < len(goog_songs):
            for s in all_songs:
                if goog_songs[i]['trackId'] == s['id']:
                    if self.tag_compare(s, tag):
                        print "Found match\t%s\t%s\t%s" % (
                            s['title'].encode('cp1252'),
                            s['artist'].encode('cp1252'),
                            s['album'].encode('cp1252'))
                        goog_songs.pop(i)
                        return True
            i += 1
        return False

    def get_id3_tag(self, filename):
        data = mutagen.File(filename, easy=True)
        r = {}
        if 'title' not in data:
            title = os.path.splitext(os.path.basename(filename))[0]
            print 'Found song with no ID3 title, setting using filename:'
            print '  %s' % title
            print '  (please note - the id3 format used (v2.4) is invisible to windows)'
            data['title'] = [title]
            data.save()
        r['title'] = data['title'][0]
        r['track'] = int(data['tracknumber'][0].split('/')
                         [0]) if 'tracknumber' in data else 0
        # If there is no track, try and get a track number off the front of the file... since thats
        # what google seems to do...
        # Not sure how google expects it to be formatted, for now this is a best guess
        if r['track'] == 0:
            m = re.match("(\d+) ", os.path.basename(filename))
            if m:
                r['track'] = int(m.group(0))
        r['artist'] = data['artist'][0] if 'artist' in data else ''
        r['album'] = data['album'][0] if 'album' in data else ''
        return r

    def find_song(self, filename, goog_songs, all_songs):
        tag = self.get_id3_tag(filename)
        print "Searching for\t%s\t%s\t%s" % (tag['title'].encode('cp1252'),
                                             tag['artist'].encode('cp1252'),
                                             tag['album'].encode('cp1252'))
        #results = self.wc.search(tag['title'])
        # NOTE - diagnostic print here to check results if you're creating duplicates
        #print results['song_hits']
        #for r in goog_songs:
        #for r in results['song_hits']:
        for s in all_songs:
            #if r['trackId'] == s['id']:
            if self.tag_compare(s, tag):
                # TODO: add rough time check to make sure its "close"
                print "Found match\t%s\t%s\t%s" % (
                    s['title'].encode('cp1252'), s['artist'].encode('cp1252'),
                    s['album'].encode('cp1252'))
                return s
        return None

    def tag_compare(self, g_song, tag):
        # If a google result has no track, google doesn't return a field for it
        if 'title' not in g_song:
            g_song['title'] = ""
        if 'artist' not in g_song:
            g_song['artist'] = ""
        if 'album' not in g_song:
            g_song['album'] = ""
        if 'track' not in g_song:
            g_song['track'] = 0
        if (g_song['title'].lower() == tag['title'].lower() and g_song['artist'].lower() == tag['artist'].lower()) or\
           (g_song['album'].lower() == tag['album'].lower() and g_song['title'].lower() == tag['title'].lower()) or\
           (g_song['artist'].lower() == tag['artist'].lower() and g_song['album'].lower() == tag['album'].lower() and g_song['track'] == tag['track']):
            print "Partial match\t%s\t%s\t%s" % (
                g_song['title'].encode('cp1252'),
                g_song['artist'].encode('cp1252'),
                g_song['album'].encode('cp1252'))
        return g_song['title'].lower() == tag['title'].lower() and\
               g_song['artist'].lower() == tag['artist'].lower() and\
               g_song['album'].lower() == tag['album'].lower() #and\
        #g_song['track'] == tag['track']

    def delete_song(self, sid):
        self.mc.delete_songs(sid)
        print "Deleted song by id [%s]" % sid

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
Пример #24
0
class Gmusic(BeetsPlugin):
    def __init__(self):
        super().__init__()
        self.m = Musicmanager()

        # OAUTH_FILEPATH was moved in gmusicapi 12.0.0.
        if hasattr(Musicmanager, 'OAUTH_FILEPATH'):
            oauth_file = Musicmanager.OAUTH_FILEPATH
        else:
            oauth_file = gmusicapi.clients.OAUTH_FILEPATH

        self.config.add({
            'auto': False,
            'uploader_id': '',
            'uploader_name': '',
            'device_id': '',
            'oauth_file': oauth_file,
        })
        if self.config['auto']:
            self.import_stages = [self.autoupload]

    def commands(self):
        gupload = Subcommand('gmusic-upload',
                             help='upload your tracks to Google Play Music')
        gupload.func = self.upload

        search = Subcommand('gmusic-songs',
                            help='list of songs in Google Play Music library')
        search.parser.add_option('-t',
                                 '--track',
                                 dest='track',
                                 action='store_true',
                                 help='Search by track name')
        search.parser.add_option('-a',
                                 '--artist',
                                 dest='artist',
                                 action='store_true',
                                 help='Search by artist')
        search.func = self.search
        return [gupload, search]

    def authenticate(self):
        if self.m.is_authenticated():
            return
        # Checks for OAuth2 credentials,
        # if they don't exist - performs authorization
        oauth_file = self.config['oauth_file'].as_filename()
        if os.path.isfile(oauth_file):
            uploader_id = self.config['uploader_id']
            uploader_name = self.config['uploader_name']
            self.m.login(oauth_credentials=oauth_file,
                         uploader_id=uploader_id.as_str().upper() or None,
                         uploader_name=uploader_name.as_str() or None)
        else:
            self.m.perform_oauth(oauth_file)

    def upload(self, lib, opts, args):
        items = lib.items(ui.decargs(args))
        files = self.getpaths(items)
        self.authenticate()
        ui.print_('Uploading your files...')
        self.m.upload(filepaths=files)
        ui.print_('Your files were successfully added to library')

    def autoupload(self, session, task):
        items = task.imported_items()
        files = self.getpaths(items)
        self.authenticate()
        self._log.info('Uploading files to Google Play Music...', files)
        self.m.upload(filepaths=files)
        self._log.info('Your files were successfully added to your ' +
                       'Google Play Music library')

    def getpaths(self, items):
        return [x.path for x in items]

    def search(self, lib, opts, args):
        password = config['gmusic']['password']
        email = config['gmusic']['email']
        uploader_id = config['gmusic']['uploader_id']
        device_id = config['gmusic']['device_id']
        password.redact = True
        email.redact = True
        # Since Musicmanager doesn't support library management
        # we need to use mobileclient interface
        mobile = Mobileclient()
        try:
            new_device_id = (device_id.as_str()
                             or uploader_id.as_str().replace(':', '')
                             or Mobileclient.FROM_MAC_ADDRESS).upper()
            mobile.login(email.as_str(), password.as_str(), new_device_id)
            files = mobile.get_all_songs()
        except NotLoggedIn:
            ui.print_(
                'Authentication error. Please check your email and password.')
            return
        if not args:
            for i, file in enumerate(files, start=1):
                print(i, ui.colorize('blue', file['artist']), file['title'],
                      ui.colorize('red', file['album']))
        else:
            if opts.track:
                self.match(files, args, 'title')
            else:
                self.match(files, args, 'artist')

    @staticmethod
    def match(files, args, search_by):
        for file in files:
            if ' '.join(ui.decargs(args)) in file[search_by]:
                print(file['artist'], file['title'], file['album'])
Пример #25
0
from gmusicapi import Mobileclient, Musicmanager, Webclient
from subprocess import getoutput

os.chdir('/tmp')

yt_url = sys.argv[1]

# download song
print('Downloading Song..')
output = getoutput('youtube-dl -x --audio-format m4a --audio-quality 0 ' +
                   yt_url)

song_file = [
    l.replace('[ffmpeg] Destination: ', '') for l in output.splitlines()
    if '[ffmpeg] Destination: ' in l
][0]

gm_manager = Musicmanager()
print("Logging in...")
gm_manager.login()

print("Uploading " + song_file)
(uploaded, matched, not_uploaded) = gm_manager.upload([song_file])

if len(uploaded):
    print("Success")
else:
    print("Unsucessful!")
    if len(matched):
        print("Already Exists...")
print("\n\nConverting to Audio")
for vidName in onlyfiles:
    #clip = mp.VideoFileClip(mypath + "/" + vidName)

    #audioName = vidName.split(".mp4")[0]
    #clip.audio.write_audiofile(mypath + "/" + audioName+".mp3")
    with mp.VideoFileClip(mypath + "/" + vidName) as clip:
        audioName = vidName.split(".mp4")[0][num_digits:]
        clip.audio.write_audiofile(mypath + "/" + audioName + ".mp3")
    os.remove(mypath + "/" + vidName)

# Uploads songs
print("\n\nUploading songs to Google Music")
audiofiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
audiofiles = [mypath + "/" + f for f in audiofiles]
results = mm.upload(audiofiles, enable_matching=False, enable_transcoding=True)

# Gets song IDs
uploaded = {**results[0], **results[1]}
not_uploaded = results[2]

ids = []
for audiofile in audiofiles:
    try:
        ids.append(uploaded[audiofile])
    except KeyError:
        ids.append(not_uploaded[audiofile].split('ALREADY_EXISTS')[1][1:-1])

# Creates new Playlist
print("\n\nCreating new playlist")
playlistID = api.create_playlist(
Пример #27
0
from gmusicapi import Musicmanager
from os import listdir
from os.path import isfile, join
import os
import time
import subprocess

api = Musicmanager()
api.login()
mypath = '/home/pi/musics'
while True:
    onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
    if len(onlyfiles) > 0:
        time.sleep(5)
        for file in onlyfiles:
            print(file)
            api.upload(mypath + '/' + file)
            os.remove(mypath + '/' + file)
        "Since this is your first time using the app you will need to allow your google account to authenticate..."
    )
    print(
        "If you would like to change the app settings please modify the config file."
    )
    mm.perform_oauth()
    config = open("yt2gpmCONFIG.txt", "w")
    firstRun = False
    config.write(
        f"firstRun:{firstRun}\nYoutube-DL Args:{ytDlString}\nremoveDownloadedFile (saves storage space):{removeFile}"
    )
    config.close()

print("Attempting to login to GPM.")
mm.login()
print(f"Successfuly logged into GPM, Uploading file: {latestFile}...")

c = mm.upload(latestFile)
mm.logout()

print("File upload complete! Finishing up.")

# remove mp3 file from directory (default)
# if you want to keep the file change config (removeFile to true)
if "True" in removeFile:
    os.remove(latestFile)
    print("Removed downloaded file. Goodbye.")
else:
    print("Goodbye.")
time.sleep(1)
Пример #29
0
#!/usr/bin/env python2
# see http://unofficial-google-music-api.readthedocs.org/en/latest/usage.html#usage
# arch linux 'pacman -S python2-pip && pip2 install gmusicapi'

from gmusicapi import Musicmanager
from gmusicapi.compat import my_appdirs
import sys
import os.path

mm = Musicmanager()

# TODO use generic path for credentials
OAUTH_FILEPATH = os.path.join(my_appdirs.user_data_dir, 'oauth.cred')
if not os.path.isfile(OAUTH_FILEPATH):
    mm.perform_oauth()

mm.login()
# TODO handle errors (existing tracks/duplicates ...)
# TODO handle errors (existing tracks/duplicates ...)
track = sys.argv[1]
uploaded, matched, not_uploaded = mm.upload(track)
if uploaded[track]:
    sys.exit(0)
sys.exit(1)
Пример #30
0
class User:
    def __init__(self, email, app_data_dir):
        self.email = email
        self.app_data_dir = app_data_dir
        self.db_lock = threading.Lock()

    def init(self, oauth_credentials):
        # Initialize the database
        logger.info("%s: Initializing database" % self.email)
        self._data_init()
        # Create the Musicmanager
        logger.info("%s: Logging in to Google music" % self.email)
        self.mm = Musicmanager()
        if not self.mm.login(oauth_credentials):
            logger.info("%s: Error logging in to Google music" % self.email)
            return False
        # Check if we already have any watch paths configured
        config = self._read_config()
        watched_paths = config["watched_paths"] if "watched_paths" in config else []
        logger.info("%s: Found previously watched paths %s" % (self.email, watched_paths))
        # Create the FileWatcher
        logger.info("%s: Creating the FileWatcher" % (self.email))
        self.fw = FileWatcher(self.email, self._finished_writing_callback, watched_paths)
        return True

    def logout(self):
        self.mm.logout()
        self.fw.stop_watching()

    def _read_config(self):
        return util.read_config(os.path.join(self.app_data_dir, self.email, CFG_FILE_NAME))

    def _write_config(self, config):
        util.write_config(config, os.path.join(self.app_data_dir, self.email, CFG_FILE_NAME))

    def get_watched_paths(self):
        logger.debug("reading config from %s" % os.path.join(self.app_data_dir, self.email))
        config = self._read_config()
        logger.debug("read config: %s" % config)
        return config["watched_paths"] if "watched_paths" in config else []

    def add_watch_path(self, path):
        # Add to file watcher
        self.fw.watch(path)
        # Add to the config
        config = self._read_config()
        if "watched_paths" not in config:
            config["watched_paths"] = [path]
        else:
            if path not in config["watched_paths"]:
                config["watched_paths"].append(path)
        self._write_config(config)

    def remove_watch_path(self, path):
        # Remove from the file watcher
        self.fw.remove_watch(path)
        # Remove from the config
        config = self._read_config()
        if "watched_paths" in config:
            if path in config["watched_paths"]:
                config["watched_paths"].remove(path)
        else:
            logger.info("%s trying to remove watch path %s that we weren't watching" % (self.email, path))
        self._write_config(config)

    def set_default_action(self, default_action):
        config = self._read_config()
        config["default_action"] = default_action
        self._write_config(config)

    def get_default_action(self):
        config = self._read_config()
        return config.get("default_action", "scan_only")

    def scan_existing_files(self):
        watched_paths = self.get_watched_paths()
        logger.debug("%s Scanning existing files in these directories: %s" % (self.email, watched_paths))
        for watched_path in watched_paths:
            logger.debug("Scanning existing files in %s" % watched_path)
            for root, subFolders, files in os.walk(watched_path):
                logger.debug("root: %s, subfolders: %s, files: %s" % (root, subFolders, files))
                for file in files:
                    filename, fileExtension = os.path.splitext(file)
                    logger.debug("looking at file %s, filename = %s, file extension = %s" % (file, filename, fileExtension))
                    if fileExtension == ".mp3":
                        logger.debug("Found file %s" % file);
                        self._update_path(os.path.join(root, file), FileStatus.Scanned)
        logger.debug("scanning finished");

    def upload_scanned(self):
        songs = self.get_all_songs() 
        for song_path in songs.keys():
            if songs[song_path]["status"] == FileStatus.Scanned:
                logger.debug("Uploading song %s" % song_path)
                self.upload(song_path)
        return


    def _data_init(self):
        with self.db_lock:
            con = sql.connect(os.path.join(self.app_data_dir, self.email, DB_NAME))
            with con:
                cur = con.cursor()
                cur.execute('''CREATE TABLE IF NOT EXISTS songs(path TEXT PRIMARY KEY, id TEXT, status TEXT)''')

    def _update_path(self, path, status, id=None, override=False):
        logger.info("Updating path %s with id %s and status %s" % (path, id, status))
        info = ((path,
                 "" if not id else id,
                 status)
                )

        with self.db_lock:
            con = sql.connect(os.path.join(self.app_data_dir, self.email, DB_NAME))
            with con:
                cur = con.cursor()
                if not override:
                    # Check if the song is already in the data store and, if so, what its status is
                    cur.execute('''SELECT status FROM songs WHERE path=(?)''', (path,))
                    res = cur.fetchone()
                    if res:
                        res = res[0]
                        if res == FileStatus.Uploaded:
                            # If it's already been uploaded, don't override that status with something else
                            return
                cur.execute('''REPLACE INTO songs VALUES(?, ?, ?)''', info)

    def _finished_writing_callback(self, new_file_path):
        logger.debug("New file %s" % new_file_path)
        filename, file_extension = os.path.splitext(new_file_path)
        if file_extension != ".mp3":
            logger.debug("Skipping non-mp3 file")
            return
        self._update_path(new_file_path, FileStatus.Scanned)
        if self.get_default_action() == "auto_upload":
            logger.info("Uploading new file: %s" % new_file_path)
            self.upload(new_file_path)

    @staticmethod
    def _find_gmusic_song(scanned_song_tags, gmusic_songs):
        try:
            artist = scanned_song_tags.artist.lower()
            album = scanned_song_tags.album.lower()
            title = scanned_song_tags.title.lower()
            #logger.debug("Found scanned song %s - %s - %s" % (artist, album, title))
        except:
            logger.debug("Error grabbing song meta data")
            return
        # Search for an uploaded song that matches
        for gmusic_song in gmusic_songs:
            up_artist = gmusic_song['artist'].lower()
            up_album = gmusic_song['album'].lower()
            up_title = gmusic_song['title'].lower()
            #logger.debug("Looking at song %s - %s - %s" % (up_artist, up_album, up_title))
            if artist == up_artist and album == up_album and title == up_title:
                #logger.debug("Found match!")
                return gmusic_song
        return None

    def sync_library(self):
        logger.debug("Syncing")
        uploaded_songs = self.mm.get_all_songs()
        scanned_songs = self.get_all_songs()
        logger.debug("found %d scanned songs" % len(scanned_songs))
        # Go through all songs marked 'scanned' and search for a matching that's already been uploaded.
        #  If we find one, grab the id and mark the song as uploaded
        for song_path in scanned_songs.keys():
            # Since we only have the path, scan its tags to get the meta data
            audioFile = eyed3.load(song_path)
            if audioFile and audioFile.tag:
                local_song = scanned_songs[song_path]
                gmusic_song = User._find_gmusic_song(audioFile.tag, uploaded_songs)
                # Now make sure our static is in sync, possibilities:
                # 1) We show it as uploaded but google doesn't -> mark it as 'scanned', remove our id
                # 2) Google shows it as uploaded but we don't -> mark it as 'uploaded', add the id
                # 3) We both show it as uploaded and the ids match -> do nothing
                # 4) Neither of us think it was uploaded -> do nothing
                # 5) Google has it but we don't at all -> TODO!! (option for download?) we'll need to detect this another way (currently searching only by scanned songs)
                if gmusic_song:
                    # Google shows this song
                    if local_song['status'] == FileStatus.Scanned:
                        # Google shows it as uploaded but we don't.  Mark it as uploaded and update the id
                        #logger.debug("'%s - %s - %s' was already uploaded, updating its id to %s" % (gmusic_song['artist'], gmusic_song['album'], gmusic_song['title'], gmusic_song['id']))
                        self._update_path(song_path, FileStatus.Uploaded, gmusic_song['id'], override=True)
                    elif local_song['status'] == FileStatus.Uploaded:
                        # We both show it as uploaded, make sure ids match
                        if local_song['id'] != gmusic_song['id']:
                            #logger.debug("Ids differ!  Updating to use google's id")
                            self._update_path(song_path, FileStatus.Uploaded, gmusic_song['id'], override=True)
                        else:
                            pass
                            #logger.debug("Ids match! No update needed")
                else:
                    # No matching song on google found
                    if local_song['status'] == FileStatus.Uploaded:
                        #logger.debug("We show the song as uploaded but google doesn't, changing status to scanned and clearing id")
                        self._update_path(song_path, FileStatus.Scanned, override=True)
                    else:
                        pass
                        #logger.debug("Neither side thinks it's uploaded, no update needed")
            else:
                logger.debug("Error loading metadata for song %s" % song_path)

    def upload(self, file_path):
        uploaded, matched, not_uploaded = self.mm.upload(file_path, enable_matching=False) # async me!
        if uploaded:
            logger.info("Uploaded song %s with ID %s" % (file_path, uploaded[file_path]))
            self._update_path(file_path, FileStatus.Uploaded, uploaded[file_path])
        if matched:
            logger.info("Matched song %s with ID %s" % (file_path, matched[file_path]))
            self._update_path(file_path, FileStatus.Uploaded, uploaded[file_path])
        if not_uploaded:
            reason_string = not_uploaded[file_path]
            if "ALREADY_EXISTS" in reason_string:
                song_id = reason_string[reason_string.find("(") + 1 : reason_string.find(")")]
                logger.info("Song already exists with ID %s, updating database" % song_id)
                # The song ID is located within parentheses in the reason string
                self._update_path(file_path, FileStatus.Uploaded, song_id)
            else:
                logger.info("Unable to upload song %s because %s" % (file_path, reason_string))
                self._update_path(file_path, FileStatus.Error, reason_string)

    def get_all_songs(self):
        songs = {}
        with self.db_lock:
            con = sql.connect(os.path.join(self.app_data_dir, self.email, DB_NAME))
            with con:
                cur = con.cursor()
                for row in cur.execute('''SELECT * FROM songs'''):
                    song_path = row[0]
                    song_id = row[1]
                    song_status = row[2]
                    songs[song_path] = {'id': song_id,
                                        'status': song_status}

        return songs
Пример #31
0
#!/usr/bin/env python

import sys
from gmusicapi import Musicmanager

mm = Musicmanager()
# second parameter is the MAC address of the machine that was used to generate the oauth.cred.
mm.login('/config/oauth.cred', '9C:B6:D0:D0:CE:1D')
mm.upload("/files/" + sys.argv[1])

Пример #32
0
class Gmusic(BeetsPlugin):
    def __init__(self):
        super(Gmusic, self).__init__()
        self.m = Musicmanager()
        self.config.add({
            u'auto': False,
            u'uploader_id': '',
            u'uploader_name': '',
            u'device_id': '',
            u'oauth_file': gmusicapi.clients.OAUTH_FILEPATH,
        })
        if self.config['auto']:
            self.import_stages = [self.autoupload]

    def commands(self):
        gupload = Subcommand('gmusic-upload',
                             help=u'upload your tracks to Google Play Music')
        gupload.func = self.upload

        search = Subcommand('gmusic-songs',
                            help=u'list of songs in Google Play Music library')
        search.parser.add_option('-t', '--track', dest='track',
                                 action='store_true',
                                 help='Search by track name')
        search.parser.add_option('-a', '--artist', dest='artist',
                                 action='store_true',
                                 help='Search by artist')
        search.func = self.search
        return [gupload, search]

    def authenticate(self):
        if self.m.is_authenticated():
            return
        # Checks for OAuth2 credentials,
        # if they don't exist - performs authorization
        oauth_file = self.config['oauth_file'].as_str()
        if os.path.isfile(oauth_file):
            uploader_id = self.config['uploader_id']
            uploader_name = self.config['uploader_name']
            self.m.login(oauth_credentials=oauth_file,
                         uploader_id=uploader_id.as_str().upper() or None,
                         uploader_name=uploader_name.as_str() or None)
        else:
            self.m.perform_oauth(oauth_file)

    def upload(self, lib, opts, args):
        items = lib.items(ui.decargs(args))
        files = self.getpaths(items)
        self.authenticate()
        ui.print_(u'Uploading your files...')
        self.m.upload(filepaths=files)
        ui.print_(u'Your files were successfully added to library')

    def autoupload(self, session, task):
        items = task.imported_items()
        files = self.getpaths(items)
        self.authenticate()
        self._log.info(u'Uploading files to Google Play Music...', files)
        self.m.upload(filepaths=files)
        self._log.info(u'Your files were successfully added to your '
                       + 'Google Play Music library')

    def getpaths(self, items):
        return [x.path for x in items]

    def search(self, lib, opts, args):
        password = config['gmusic']['password']
        email = config['gmusic']['email']
        uploader_id = config['gmusic']['uploader_id']
        device_id = config['gmusic']['device_id']
        password.redact = True
        email.redact = True
        # Since Musicmanager doesn't support library management
        # we need to use mobileclient interface
        mobile = Mobileclient()
        try:
            new_device_id = (device_id.as_str()
                             or uploader_id.as_str().replace(':', '')
                             or Mobileclient.FROM_MAC_ADDRESS).upper()
            mobile.login(email.as_str(), password.as_str(), new_device_id)
            files = mobile.get_all_songs()
        except NotLoggedIn:
            ui.print_(
                u'Authentication error. Please check your email and password.'
            )
            return
        if not args:
            for i, file in enumerate(files, start=1):
                print(i, ui.colorize('blue', file['artist']),
                      file['title'], ui.colorize('red', file['album']))
        else:
            if opts.track:
                self.match(files, args, 'title')
            else:
                self.match(files, args, 'artist')

    @staticmethod
    def match(files, args, search_by):
        for file in files:
            if ' '.join(ui.decargs(args)) in file[search_by]:
                print(file['artist'], file['title'], file['album'])
Пример #33
0
class Gmusic(BeetsPlugin):
    def __init__(self):
        super(Gmusic, self).__init__()
        # Checks for OAuth2 credentials,
        # if they don't exist - performs authorization
        self.m = Musicmanager()
        if os.path.isfile(gmusicapi.clients.OAUTH_FILEPATH):
            self.m.login()
        else:
            self.m.perform_oauth()

    def commands(self):
        gupload = Subcommand('gmusic-upload',
                             help=u'upload your tracks to Google Play Music')
        gupload.func = self.upload

        search = Subcommand('gmusic-songs',
                            help=u'list of songs in Google Play Music library')
        search.parser.add_option('-t',
                                 '--track',
                                 dest='track',
                                 action='store_true',
                                 help='Search by track name')
        search.parser.add_option('-a',
                                 '--artist',
                                 dest='artist',
                                 action='store_true',
                                 help='Search by artist')
        search.func = self.search
        return [gupload, search]

    def upload(self, lib, opts, args):
        items = lib.items(ui.decargs(args))
        files = [x.path.decode('utf-8') for x in items]
        ui.print_(u'Uploading your files...')
        self.m.upload(filepaths=files)
        ui.print_(u'Your files were successfully added to library')

    def search(self, lib, opts, args):
        password = config['gmusic']['password']
        email = config['gmusic']['email']
        password.redact = True
        email.redact = True
        # Since Musicmanager doesn't support library management
        # we need to use mobileclient interface
        mobile = Mobileclient()
        try:
            mobile.login(email.as_str(), password.as_str(),
                         Mobileclient.FROM_MAC_ADDRESS)
            files = mobile.get_all_songs()
        except NotLoggedIn:
            ui.print_(
                u'Authentication error. Please check your email and password.')
            return
        if not args:
            for i, file in enumerate(files, start=1):
                print(i, ui.colorize('blue', file['artist']), file['title'],
                      ui.colorize('red', file['album']))
        else:
            if opts.track:
                self.match(files, args, 'title')
            else:
                self.match(files, args, 'artist')

    @staticmethod
    def match(files, args, search_by):
        for file in files:
            if ' '.join(ui.decargs(args)) in file[search_by]:
                print(file['artist'], file['title'], file['album'])
Пример #34
0
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.mc.get_all_user_playlist_contents()
        #self.playlists = self.mc.get_all_playlists()
        #self.playlists = self.wc.get_all_playlist_ids(auto=False)
        self.all_songs = self.mc.get_all_songs()
        #print "Got %d playlists." % len(self.playlists['user'])
        print "Got %d playlists containing %d songs." % (len(self.playlists), len(self.all_songs))
        print ""


    def auth(self):
        self.logged_in = self.mc.login(self.email, self.password)
        #self.logged_in = self.wc.login(self.email, self.password)
        if not self.logged_in:
            print "Login failed..."
            exit()

        print ""
        print "Logged in as %s" % self.email
        print ""

        if not os.path.isfile(OAUTH_FILEPATH):
            print "First time login. Please follow the instructions below:"
            self.mm.perform_oauth()
        self.logged_in = self.mm.login()
        if not self.logged_in:
            print "OAuth failed... try deleting your %s file and trying again." % OAUTH_FILEPATH
            exit()

        print "Authenticated"
        print ""


    def sync_playlist(self, filename, remove_missing):
    #def sync_playlist(self, filename, remove_missing=False):
        filename = self.get_platform_path(filename)
        os.chdir(os.path.dirname(filename))
        title = os.path.splitext(os.path.basename(filename))[0]
        print "Syncing playlist: %s" % filename
        #if title not in self.playlists['user']:
            #print "   didn't exist... creating..."
            #self.playlists['user'][title] = [self.wc.create_playlist(title)]
        print ""

        plid = ""

        for pl in self.playlists:
            if pl['name'] == title:
                plid = pl['id']
                goog_songs = pl['tracks']

        if plid == "":
            print "   didn't exist... creating..."
            plid = self.mc.create_playlist(self, title)

        #plid = self.playlists['user'][title][0]
        #goog_songs = self.wc.get_playlist_songs(plid)
        print "%d songs already in Google Music playlist" % len(goog_songs)
        pc_songs = self.get_files_from_playlist(filename)
        print "%d songs in local playlist" % len(pc_songs)
        print ""

        # Sanity check max 1000 songs per playlist
        if len(pc_songs) > MAX_SONGS_IN_PLAYLIST:
            print "    Google music doesn't allow more than %d songs in a playlist..." % MAX_SONGS_IN_PLAYLIST
            print "    Will only attempt to sync the first %d songs." % MAX_SONGS_IN_PLAYLIST
            del pc_songs[MAX_SONGS_IN_PLAYLIST:]

        existing_files = 0
        added_files = 0
        failed_files = 0
        removed_files = 0
        fatal_count = 0

        for fn in pc_songs:
            if self.file_already_in_list(fn, goog_songs, self.all_songs):
                existing_files += 1
                continue
            print ""
            print "Adding: %s" % os.path.basename(fn).encode('cp1252')
            #print "Adding: %s" % os.path.basename(fn)
            #online = False
            online = self.find_song(fn, goog_songs, self.all_songs)
            #online = self.find_song(fn)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                attempts = 0
                result = []
                while not result and attempts < MAX_UPLOAD_ATTEMPTS_PER_FILE:
                    print "   uploading... (may take a while)"
                    attempts += 1
                    try:
                        result = self.mm.upload(fn)
                    except (BadStatusLine, CannotSendRequest):
                        # Bail out if we're getting too many disconnects
                        if fatal_count >= MAX_CONNECTION_ERRORS_BEFORE_QUIT:
                            print ""
                            print "Too many disconnections - quitting. Please try running the script again."
                            print ""
                            exit()

                        print "Connection Error -- Reattempting login"
                        fatal_count += 1
                        self.wc.logout()
                        self.mc.logout()
                        self.mm.logout()
                        result = []
                        time.sleep(STANDARD_SLEEP)

                    except:
                        result = []
                        time.sleep(STANDARD_SLEEP)

                try:
                    if result[0]:
                        song_id = result[0].itervalues().next()
                    else:
                        song_id = result[1].itervalues().next()
                    print "   upload complete [%s]" % song_id
                except:
                    print "      upload failed - skipping"
                    tag = self.get_id3_tag(fn)
                    print "      failed song:\t%s\t%s\t%s" % (tag['title'].encode('cp1252'), tag['artist'].encode('cp1252'), tag['album'].encode('cp1252'))

            if not song_id:
                failed_files += 1
                continue

            added = self.mc.add_songs_to_playlist(plid, song_id)
            time.sleep(.3) # Don't spam the server too fast...
            print "   done adding to playlist"
            added_files += 1

        if remove_missing:
            for g in goog_songs:
                for s in self.all_songs:
                    if g['trackId'] == s['id']:
                        print ""
                        print "Removing: %s" % s['title'].encode('cp1252')
                        self.mc.remove_entries_from_playlist(g['id'])
                        #self.wc.remove_songs_from_playlist(plid, s.id)
                        time.sleep(.3) # Don't spam the server too fast...
                        removed_files += 1

        print ""
        print "---"
        print "%d songs unmodified" % existing_files
        print "%d songs added" % added_files
        print "%d songs failed" % failed_files
        print "%d songs removed" % removed_files


    def get_files_from_playlist(self, filename):
        files = []
        f = codecs.open(filename, encoding='cp1252')
        #f = codecs.open(filename, encoding='utf-8')
        for line in f:
            line = line.rstrip().replace(u'\ufeff',u'')
            if line == "" or line[0] == "#":
                continue
            path  = os.path.abspath(self.get_platform_path(line))
            if not os.path.exists(path):
                print "File not found: %s" % line
                continue
            files.append(path)
        f.close()
        return files

    def file_already_in_list(self, filename, goog_songs, all_songs):
        tag = self.get_id3_tag(filename)
        print "Searching for\t%s\t%s\t%s" % (tag['title'].encode('cp1252'), tag['artist'].encode('cp1252'), tag['album'].encode('cp1252'))
        i = 0
        while i < len(goog_songs):
            for s in all_songs:
                if goog_songs[i]['trackId'] == s['id']:
                    if self.tag_compare(s, tag):
                        print "Found match\t%s\t%s\t%s" % (s['title'].encode('cp1252'), s['artist'].encode('cp1252'), s['album'].encode('cp1252'))
                        goog_songs.pop(i)
                        return True
            i += 1
        return False

    def get_id3_tag(self, filename):
        data = mutagen.File(filename, easy=True)
        r = {}
        if 'title' not in data:
            title = os.path.splitext(os.path.basename(filename))[0]
            print 'Found song with no ID3 title, setting using filename:'
            print '  %s' % title
            print '  (please note - the id3 format used (v2.4) is invisible to windows)'
            data['title'] = [title]
            data.save()
        r['title'] = data['title'][0]
        r['track'] = int(data['tracknumber'][0].split('/')[0]) if 'tracknumber' in data else 0
        # If there is no track, try and get a track number off the front of the file... since thats
        # what google seems to do...
        # Not sure how google expects it to be formatted, for now this is a best guess
        if r['track'] == 0:
            m = re.match("(\d+) ", os.path.basename(filename))
            if m:
                r['track'] = int(m.group(0))
        r['artist'] = data['artist'][0] if 'artist' in data else ''
        r['album'] = data['album'][0] if 'album' in data else ''
        return r

    def find_song(self, filename, goog_songs, all_songs):
        tag = self.get_id3_tag(filename)
        print "Searching for\t%s\t%s\t%s" % (tag['title'].encode('cp1252'), tag['artist'].encode('cp1252'), tag['album'].encode('cp1252'))
        #results = self.wc.search(tag['title'])
        # NOTE - diagnostic print here to check results if you're creating duplicates
        #print results['song_hits']
        #for r in goog_songs:
        #for r in results['song_hits']:
        for s in all_songs:
            #if r['trackId'] == s['id']:
            if self.tag_compare(s, tag):
                # TODO: add rough time check to make sure its "close"
                print "Found match\t%s\t%s\t%s" % (s['title'].encode('cp1252'), s['artist'].encode('cp1252'), s['album'].encode('cp1252'))
                return s
        return None

    def tag_compare(self, g_song, tag):
        # If a google result has no track, google doesn't return a field for it
        if 'title' not in g_song:
            g_song['title'] = ""
        if 'artist' not in g_song:
            g_song['artist'] = ""
        if 'album' not in g_song:
            g_song['album'] = ""
        if 'track' not in g_song:
            g_song['track'] = 0
        if (g_song['title'].lower() == tag['title'].lower() and g_song['artist'].lower() == tag['artist'].lower()) or\
           (g_song['album'].lower() == tag['album'].lower() and g_song['title'].lower() == tag['title'].lower()) or\
           (g_song['artist'].lower() == tag['artist'].lower() and g_song['album'].lower() == tag['album'].lower() and g_song['track'] == tag['track']):
            print "Partial match\t%s\t%s\t%s" % (g_song['title'].encode('cp1252'), g_song['artist'].encode('cp1252'), g_song['album'].encode('cp1252'))
        return g_song['title'].lower() == tag['title'].lower() and\
               g_song['artist'].lower() == tag['artist'].lower() and\
               g_song['album'].lower() == tag['album'].lower() #and\
               #g_song['track'] == tag['track']

    def delete_song(self, sid):
        self.mc.delete_songs(sid)
        print "Deleted song by id [%s]" % sid

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
Пример #35
0
class GMusicSync(BeetsPlugin):
    def __init__(self):
        super(GMusicSync, self).__init__()

        self._mm = Musicmanager(debug_logging=False)
        self._library_paths = get_library_paths('default')

        if not os.path.exists(self._library_paths.base):
            os.mkdir(self._library_paths.base);

        self._db = open_db(self._library_paths.db_file)

        if not os.path.exists(self._library_paths.oauth_file):
            self._mm.perform_oauth(self._library_paths.oauth_file)
        else:
            self._mm.login(self._library_paths.oauth_file)

        sync_command = make_command('gmusic-sync', self.sync_library, help='Sync library with Google Play Music')
        sync_command.parser.add_option('-p', '--pretend', dest='pretend', action='store_true', default=False)

        self._commands = [
            sync_command,
        ]

        self.config['password'].redact = True

    def commands(self):
        return self._commands

    def sync_library(self, lib, opts, args):
        total_count = 0
        uploaded_count = 0
        error_count = 0

        for item in lib.items(query=args):
            total_count = total_count + 1
            status = self.sync_track(item, pretend=opts.pretend)
            if status == 'uploaded':
                uploaded_count = uploaded_count + 1
            elif status == 'error':
                error_count = error_count + 1

        print 'Summary:'
        print '  {0} tracks analyzed.'.format(total_count)
        print '  {0} tracks {1}uploaded.'.format(uploaded_count, 'would be ' if opts.pretend else '')
        print '  {0} tracks errored.'.format(error_count)

    def sync_track(self, item, pretend=False):
        item_mtime = arrow.get(item.current_mtime())

        track_row = self._db.get_track(item.id)

        upload_track = track_row is None or \
            track_row.gmusic_sync_time is None or \
            track_row.gmusic_sync_time < item_mtime

        if upload_track:
            try:
                track_id = self.upload_track(item, pretend)

                if not pretend:
                    track_row = TrackRow(id=item.id, gmusic_track_id=track_id, gmusic_sync_time=arrow.utcnow())
                    self._db.update_track(track_row)

                return 'uploaded'
            except Exception as err:
                print '>>> track failed to upload: {0}'.format(err)
                return 'error'

        return 'ok'

    def upload_track(self, item, pretend=False):
        print u'Uploading track: {artist} - {album} - [{track}] {title}'.format(**item)
        track_id = None

        if not pretend:
            uploaded, matched, not_uploaded = self._mm.upload(item.path, enable_matching=True)
            if item.path in uploaded:
                track_id = uploaded[item.path]
                print '>>> track uploaded (gmusic_trackid: {track_id})'.format(track_id=track_id)
            elif item.path in matched:
                track_id = matched[item.path]
                print '>>> track matched (gmusic_trackid: {track_id})'.format(track_id=track_id)
            else:
                reason = not_uploaded[item.path]
                m = re.search('ALREADY_EXISTS\((.*)\)', reason)
                if not m:
                    raise GMusicTrackError(reason)

                track_id = m.group(1)
                print '>>> track already exists (gmusic_trackid: {track_id}'.format(track_id=track_id)
        else:
            track_id = '?'
            print '>>> track would be uploaded'

        return track_id
Пример #36
0
class GMClient(object):
    'Wrapper class of gmusicapi.Mobileclient'

    def __init__(self):
        # Aplying patch to session.Musicmanager
        session.Musicmanager.login = MethodType(patched_musicmanaer_login,
                                                None, session.Musicmanager)
        self.man = Musicmanager(verify_ssl=False)

        self.all_songs = None

    def login(self):
        if not os.path.exists(OAUTH_PATH):
            logging.error('No {} exists'.format(OAUTH_PATH))
            raise Exception('No {} exists'.format(OAUTH_PATH))
        else:
            self.man.login(oauth_credentials=OAUTH_PATH,
                           uploader_name='raspi_home')
            logging.info('Success!')

        # These are required to change meta data.
        # raspi_home does not require it.
        # if ('GOOGLE_PLAY_MUSIC_PASS' in os.environ and
        #     'GOOGLE_PLAY_MUSIC_USER' in os.environ):
        #     self.api = Mobileclient()
        #     self.api.login(os.environ['GOOGLE_PLAY_MUSIC_USER'],
        #                    os.environ['GOOGLE_PLAY_MUSIC_PASS'],
        #                    Mobileclient.FROM_MAC_ADDRESS)
        #     logging.info('Logged in to google music')
        #     self.is_available = True
        # else:
        #     logging.warn('environmental variable GOOGLE_PLAY_MUSIC_PASS or GOOGLE_PLAY_MUSIC_USER'
        #                  ' is not available')
        #     self.api = None

    def oauth(self):
        'Run oauth for uploading/downloading songs'
        oauth_dir = os.path.dirname(OAUTH_PATH)
        if not os.path.exists(oauth_dir):
            logging.info('No oauth directory, create it')
            os.makedirs(oauth_dir)
        self.man.perform_oauth(open_browser=False, storage_filepath=OAUTH_PATH)

    # methods communicating with google server
    def update_songs(self):
        # if self.api is not None:
        #     self.all_songs = self.api.get_all_songs()
        # else:
        #     self.all_songs = []
        self.all_songs = self.man.get_uploaded_songs()

    def get_all_songs(self):
        if self.all_songs is None:
            self.update_songs()
        return self.all_songs

    def get_songs(self, artist=None):
        return [
            song for song in self.get_all_songs() if song['artist'] == artist
        ]

    def upload(self, file):
        if not os.path.exists(file):
            logging.error('No {} exists'.format(file))
        else:
            (uploaded, matched,
             not_uploaded) = self.man.upload([file], enable_matching=True)
            if not_uploaded:
                logging.error('not uploaded because {}'.format(not_uploaded))

    def has_song(self, title):
        return title in [song['title'] for song in self.get_all_songs()]