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)
Beispiel #2
0
def machineautn():

    mm = Mobileclient()
    mm.perform_oauth()

    mm2 = Musicmanager()
    mm2.perform_oauth()
Beispiel #3
0
def initializeClient():
    client = Musicmanager()

    if (client.login()):
        return client
    else:
        client.perform_oauth(open_browser=True)
        initializeClient()
Beispiel #4
0
def run():
    global download_dir, notify_plex, mm
    download_dir, notify_plex = parse_args()
    log("Creating music manager")
    mm = Musicmanager()
    log("Attempting login")
    if not mm.login():
        print "OAuth required:"
        mm.perform_oauth()

    get_songs()
Beispiel #5
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")
class GoogleClient():
    def __init__(self, username=None, password=None):
        self._username = username
        self._password = password

    # Initiates the oAuth
    def Authenticate(self):
        self.MusicManager = Musicmanager(debug_logging=False)

        attempts = 0
        # Attempt to login. Perform oauth only when necessary.
        while attempts < 3:
                if self.MusicManager.login():
                        break
                self.MusicManager.perform_oauth()
                attempts += 1

        if not self.MusicManager.is_authenticated():
                print("Sorry, login failed.")
                return False

        print("OAuth successfull\n")

        username = self._username
        password = self._password
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise Exception(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
            if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise Exception(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials','username')
            password = self.config.get('credentials','password')
            if not username or not password:
                raise Exception(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
        self.Api = Mobileclient(debug_logging = False)
        if not self.Api.login(username, password, Mobileclient.FROM_MAC_ADDRESS):
           raise Exception('login failed for %s' % username)

        return True
Beispiel #7
0
def main():
    cli = Musicmanager(debug_logging=False)

    if credfile.is_file():
        if cli.login(oauth_credentials=str(credfile)):
            print("Login successful. Don't need to perform oauth.")
            return
        else:
            os.remove(credfile)

    cli.perform_oauth(storage_filepath=str(credfile), open_browser=True)

    if cli.login(oauth_credentials=str(credfile)):
        print("Login successful. Restart the bot!")
    else:
        print("Failed to auth. Try again later.")
Beispiel #8
0
def authorize_manager(parameters):
    # api = Webclient()
    # api = Mobileclient()
    api = Musicmanager()
    # after running api.perform_oauth() once:
    # api.oauth_login('<a previously-registered device id>')
    # api.login(email=parameters.username, password=parameters.password)
    # => True
    if not os.path.exists(authorize_file + '_manager'):
        api.perform_oauth(authorize_file + '_manager', True)

    api.login(authorize_file + '_manager')
    if not api.is_authenticated():
        return None

    return api
Beispiel #9
0
	def download_songs(self):
		api = Musicmanager()
		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
		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)		
		playlist_id = raw_input("insert id: ")
		
		api_ = Mobileclient()
		api_.login(self.email, self.password)
		playlist_method = api_.get_all_playlists()
Beispiel #10
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)
Beispiel #11
0
def api_init():
    mm = Musicmanager()
    e = settings['email']
    creds = os.path.expanduser("~/.local/share/gmusicapi/oauth.cred") # default oauth store location
    if OTHERACCOUNT:
        e = settings['email2']
        creds = os.path.expanduser("~/.local/share/gmusicapi/oauth2.cred")
    if e is not None:
        if settings['first'] == '1' or OTHERACCOUNT and settings['first2'] == '1':
            print "Performing OAUTH for %s" % e
            mm.perform_oauth(storage_filepath=creds)
            update_first(e)
    log("Logging in as %s" % e)
    if mm.login(oauth_credentials=creds):
        return mm
    log("Login failed for second user")
    return False
Beispiel #12
0
def api_init():
  mm = Musicmanager()
  e = settings['email']
  creds = os.path.expanduser("~/.local/share/gmusicapi/oauth.cred") # default oauth store location
  if OTHERACCOUNT:
    e = settings['email2']
    creds = os.path.expanduser("~/.local/share/gmusicapi/oauth2.cred")
  if e is not None:
    if settings['first'] == '1' or OTHERACCOUNT and settings['first2'] == '1':
      print("Performing OAUTH for %s" % e)
      mm.perform_oauth(storage_filepath=creds)
      update_first(e)
  log("Logging in as %s" % e)
  if mm.login(oauth_credentials=creds, uploader_id=settings['uploader_id']):
    return mm
  log("Login failed for second user")
  return False
class GoogleClient():
    # Initiates the oAuth
    def Authenticate(self):
        self.MusicManager = Musicmanager(debug_logging=False)

        attempts = 0
        # Attempt to login. Perform oauth only when necessary.
        while attempts < 3:
                if self.MusicManager.login():
                        break
                self.MusicManager.perform_oauth()
                attempts += 1

        if not self.MusicManager.is_authenticated():
                print "Sorry, login failed."
                return False

        print "Successfully logged in.\n"
        return True
Beispiel #14
0
class GoogleClient():
    # Initiates the oAuth
    def Authenticate(self):
        self.MusicManager = Musicmanager(debug_logging=False)

        attempts = 0
        # Attempt to login. Perform oauth only when necessary.
        while attempts < 3:
            if self.MusicManager.login():
                break
            self.MusicManager.perform_oauth()
            attempts += 1

        if not self.MusicManager.is_authenticated():
            print "Sorry, login failed."
            return False

        print "Successfully logged in.\n"
        return True
def main():
    if len(sys.argv) != 2:
        print_help()
        sys.exit(1)
    else:
        username = sys.argv[1]
    password = getpass.getpass()

    mc = Mobileclient()
    mc.login(username, password, Mobileclient.FROM_MAC_ADDRESS)

    mm = Musicmanager()
    mm.perform_oauth()
    mm.login()

    uploaded_songs = mm.get_uploaded_songs()
    uploaded_ids = [track['id'] for track in uploaded_songs]
    for part in chunks(uploaded_ids, 100):
        complete = mc.delete_songs(part)
        if len(complete) != len(part):
            print("Something is wrong")
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
Beispiel #17
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()
def setup_music_manager_api():
    global music_manager_api
    music_manager_api = Musicmanager()

    if not config.get_is_authenticated():
        print "Follow the instructions to authenticate with Google..."
        credentials = music_manager_api.perform_oauth()
        if credentials is not None:
            config.set_is_authenticated(True)
        else:
            print "Failed to authenticate, try again."
            sys.exit(0)

    music_manager_logged_in = music_manager_api.login()

    if not music_manager_logged_in:
        print "Failed to log in to the music manager API, you will be asked to authenticate again next run."

        sys.exit(0)
Beispiel #19
0
from gmusicapi import Musicmanager, clients
import os.path

oauth_path = clients.OAUTH_FILEPATH

if os.path.isfile(oauth_path):
    print 'OAuth credentials already exist'
else:
    # oauth login
    mm = Musicmanager()
    oath_path = mm.perform_oauth(oauth_path, True)

class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        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.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""

    def auth(self):
        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, artist_title_array, playlist_title=-99):
        if playlist_title == -99:
            title = "GMusicSync Playlist %3d" % time.time()
        else:
            title = str(playlist_title)
        print "Synching playlist: %s" % title
        if title not in self.playlists['user']:
            print "   didn't exist... creating..."
            self.playlists['user'][title] = [self.wc.create_playlist(title)]
        print ""

        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 = artist_title_array
        print "%d songs in local playlist" % len(pc_songs)

        # 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):
                existing_files += 1
                continue
            print ""
            try:
                print "Adding: %s - %s" % (fn[0], fn[1])
            except:
                print "Incorrect format for %r, expecting ('artist','title')" % fn
                continue
            online = self.find_song(fn)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                print "   Sorry, can't find song."

            if not song_id:
                failed_files += 1
                continue

            added = self.wc.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

        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='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, artist_title, goog_songs):
        i = 0
        while i < len(goog_songs):
            if self.song_compare(goog_songs[i], artist_title):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def find_song(self, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except:
            return None
        results = self.wc.search(title)
        print "\t", results[:2]
        for r in results['song_hits']:
            if self.song_compare(r, artist_title):
                return r
        return None

    def song_compare(self, g_song, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except:
            return False
        # TODO: add fuzzy matching
        return g_song['title'].lower() == title.lower() and\
               g_song['artist'].lower() == artist.lower()

    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('\\', '/'))
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('\\', '/'))
#!/usr/bin/env python
from gmusicapi import Mobileclient
from gmusicapi import Musicmanager
from getpass import getpass

api = Musicmanager()

api.perform_oauth()
Beispiel #23
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)
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        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.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""


    def auth(self):
        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, artist_title_array, playlist_title = -99):
        if playlist_title == -99:
            title = "GMusicSync Playlist %3d"%time.time()
        else: title = str(playlist_title)
        print "Synching playlist: %s" % title
        if title not in self.playlists['user']:
            print "   didn't exist... creating..."
            self.playlists['user'][title] = [self.wc.create_playlist(title)]
        print ""

        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 = artist_title_array
        print "%d songs in local playlist" % len(pc_songs)

        # 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):
                existing_files += 1
                continue
            print ""
            try:
                print "Adding: %s - %s"%(fn[0],fn[1])
            except:
                print "Incorrect format for %r, expecting ('artist','title')"%fn
                continue
            online = self.find_song(fn)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                print "   Sorry, can't find song."

            if not song_id:
                failed_files += 1
                continue

            added = self.wc.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

        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='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, artist_title, goog_songs):
        i = 0
        while i < len(goog_songs):
            if self.song_compare(goog_songs[i], artist_title):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def find_song(self, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except: return None
        results = self.wc.search(title)
        print "\t",results[:2]
        for r in results['song_hits']:
            if self.song_compare(r, artist_title):
                return r
        return None

    def song_compare(self, g_song, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except: return False
        # TODO: add fuzzy matching
        return g_song['title'].lower() == title.lower() and\
               g_song['artist'].lower() == artist.lower()

    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('\\', '/'))
Beispiel #25
0
class MusicLibrary(object):
    'Read information about your Google Music library'

    def __init__(self,
                 username=None,
                 password=None,
                 true_file_size=False,
                 scan=True,
                 verbose=0):
        self.verbose = False
        self.manager_id = 0
        if verbose > 1:
            self.verbose = True

        self.__login_and_setup(username, password)
        self.__register_music_manager()
        if scan:
            self.rescan()
        self.true_file_size = true_file_size

    def rescan(self):
        self.__artists = {}  # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = []  # [Album(), ...]
        self.__aggregate_albums()

    def __login_and_setup(self, username=None, password=None):
        # If credentials are not specified, get them from $HOME/.gmusicfs
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.' %
                    cred_path)
            if not oct(
                    os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials', 'username')
            password = self.config.get('credentials', 'password')
            if not username or not password:
                raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)

        self.api = GoogleMusicAPI(debug_logging=self.verbose)
        log.info('Logging in...')
        self.api.login(username, password)
        log.info('Login successful.')

    def __register_music_manager(self):
        self.manager = GoogleMusicManager()
        self.manager_id = ':'.join(re.findall('..', '%012x' %
                                              uuid.getnode())).upper()
        log.info('Registering the google music manager...')
        cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs.ocred')
        if not os.path.isfile(cred_path):
            log.info('Authorizing GMusicFS application against Google...')
            self.manager.perform_oauth(storage_filepath=cred_path)
            os.chmod(cred_path, 0600)
        if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
            raise NoCredentialException(
                'Config file is not protected. Please run: '
                'chmod 600 %s' % cred_path)
        self.manager.login(cred_path, self.manager_id, 'GMusicFS')
        log.info('Successfully registered the google music manager...')

    def __aggregate_albums(self):
        'Get all the tracks in the library, parse into artist and album dicts'
        all_artist_albums = {}  # 'Artist|||Album' -> Album()
        log.info('Gathering track information...')
        tracks = self.api.get_all_songs()
        for track in tracks:
            # Prefer the album artist over the track artist if there is one:
            artist = normalize(track['artist'])
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(artist),
                               formatNames(normalize(track['album'])))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(normalize(track['album'])))
                self.__albums.append(album)
                artist_albums = self.__artists.get(artist, None)
                if artist_albums:
                    artist_albums[formatNames(album.normtitle)] = album
                else:
                    self.__artists[artist] = {album.normtitle: album}
                    artist_albums = self.__artists[artist]
            album.add_track(track)
        log.debug('%d tracks loaded.' % len(tracks))
        log.debug('%d artists loaded.' % len(self.__artists))
        log.debug('%d albums loaded.' % len(self.__albums))

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]

    def cleanup(self):
        pass
Beispiel #26
0
class MusicLibrary(object):
    'Read information about your Google Music library'
    
    def __init__(self, username=None, password=None,
                 true_file_size=False, scan=True, verbose=0):
        self.verbose = False
	self.manager_id = 0
        if verbose > 1:
            self.verbose = True

        self.__login_and_setup(username, password)
	self.__register_music_manager()
        if scan:
            self.rescan()
        self.true_file_size = true_file_size

    def rescan(self):
        self.__artists = {} # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = [] # [Album(), ...]
        self.__aggregate_albums()

    def __login_and_setup(self, username=None, password=None):
        # If credentials are not specified, get them from $HOME/.gmusicfs
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
            if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials','username')
            password = self.config.get('credentials','password')
            if not username or not password:
                raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
                
        self.api = GoogleMusicAPI(debug_logging=self.verbose)
        log.info('Logging in...')
        self.api.login(username, password)
        log.info('Login successful.')

    def __register_music_manager(self):
	self.manager = GoogleMusicManager()
	self.manager_id = ':'.join(re.findall('..', '%012x' % uuid.getnode())).upper()
	log.info('Registering the google music manager...')
        cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs.ocred')
	if not os.path.isfile(cred_path):
	    log.info('Authorizing GMusicFS application against Google...')
	    self.manager.perform_oauth(storage_filepath=cred_path)
	    os.chmod(cred_path, 0600)
        if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
            raise NoCredentialException(
                'Config file is not protected. Please run: '
                'chmod 600 %s' % cred_path)
	self.manager.login(cred_path, self.manager_id, 'GMusicFS')
	log.info('Successfully registered the google music manager...')
        
    def __aggregate_albums(self):
        'Get all the tracks in the library, parse into artist and album dicts'
        all_artist_albums = {} # 'Artist|||Album' -> Album()
        log.info('Gathering track information...')
        tracks = self.api.get_all_songs()
        for track in tracks:
            # Prefer the album artist over the track artist if there is one:
            artist = normalize(track['artist'])
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(artist), formatNames(normalize(track['album'])))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(normalize(track['album'])))
                self.__albums.append(album)
                artist_albums = self.__artists.get(artist, None)
                if artist_albums:
                    artist_albums[formatNames(album.normtitle)] = album
                else:
                    self.__artists[artist] = {album.normtitle: album}
                    artist_albums = self.__artists[artist]
            album.add_track(track)
        log.debug('%d tracks loaded.' % len(tracks))
        log.debug('%d artists loaded.' % len(self.__artists))
        log.debug('%d albums loaded.' % len(self.__albums))

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]

    def cleanup(self):
        pass
Beispiel #27
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'])
Beispiel #28
0
from gmusicapi import Mobileclient, Musicmanager

# This only needs to be run once.  Re-use the creds from where it is stored
mobile = Mobileclient()
mobile.perform_oauth(storage_filepath="/Users/jd/ws/gmusic/.creds",
                     open_browser=True)

manager = Musicmanager()
manager.perform_oauth(storage_filepath="/Users/jd/ws/gmusic/.manager_creds",
                      open_browser=True)
Beispiel #29
0
from gmusicapi import Musicmanager
import os.path
storage_filepath = '/home/alex/.local/share/gmusicapi/oauth.cred'
mm = Musicmanager()
if os.path.isfile(storage_filepath):
    mm.login()
else:
    Musicmanager.perform_oauth(storage_filepath, open_browser=True)
songs = mm.get_uploaded_songs(incremental=False)
print(songs)
song_id = []
for x in songs:
    song_id.append(x.get('id'))
print(song_id)
for an_id in song_id:
    filename, audio = mm.download_song(an_id)
    with open(filename, 'wb') as f:
        f.write(audio)

input("Enter: ")
mm.logout(revoke_oauth=False)
Beispiel #30
0
from gmusicapi import Musicmanager

# login
mm = Musicmanager()
mm.perform_oauth()  # once
mm.login()

# get music dict
mymusics = mm.get_uploaded_songs()

# diff?
# MUST consider directories
oldmusics = "hogehoge"

# for example
id = mymusics[0]["id"]
filename, audio_bytes = mm.download_song(id)

with open(filename, "wb") as f:
    f.write(audio_bytes)

# logout
mm.logout()
Beispiel #31
0
def gmtConfigRead():
	global std_usr, root_dir, trash_path, cred_path, list_path
	
	try:
		with open(conf_path, "r") as file:
			for line in file:
				
				if(line[:17] == "StandardUsername="******"gmtConfigRead: StandardUser Config: " + std_usr)
					
				elif(line[:14] == "RootDirectory="):
					root_dir = line[14:-1]
					gmtPrintV("gmtConfigRead: RootDirectory Config: " + root_dir)
					if not os.path.exists(root_dir):
						gmtPrintV("gmtConfigRead: Song directory not found")
						error.e = error.ROOT_DIR_NOT_FOUND
						return

				elif(line[:10] == "TrashPath="):
					trash_path = line[10:-1]
					gmtPrintV("gmtConfigRead: TrashPath Config: " + trash_path)
					if not os.path.exists(trash_path):
						gmtPrintV("gmtConfigRead: Couldn't find trash directory, generating empty one now")
						try:
							os.makedirs(trash_path)
						except IOError:
							gmtPrintV("gmtConfigReadCouldn't generate trash directory")
							error.e = error.TRASH_ERROR
							return
				
				elif(line[:16] == "CredentialsPath="):
					cred_path = line[16:-1]
					gmtPrintV("gmtConfigRead: CredentialsPath Config: " + cred_path)
					if not os.path.isfile(cred_path):
						if gmtAskUser("Couldn't find credentials. Generate them now (y/n)? ") == "y":
							try:
								Musicmanager.perform_oauth(cred_path)
							except:
								gmtPrintV("gmtConfigRead: Generating credentials failed")
								error.e = error.FILE_ERROR
						else:
							gmtPrintV("gmtConfigRead: Credentials needed to upload songs")
							error.e = error.LOGIN_FAILED
				
				elif(line[:17] == "UploadedListPath="):
					list_path = line[17:-1]
					gmtPrintV("gmtConfigRead: UploadedListPath Config: " + list_path)
					if not os.path.isfile(list_path):
						gmtPrintV("gmtConfigRead: Couldn't find list of uploaded files, generating empty one now")
						try:
							file = open(list_path, "w")
							file.close()
						except IOError:
							gmtError("gmtConfigRead: Couldn't generate list of uploaded files")
							error.e = error.LIST_ERROR
							return
	except IOError:
		gmtPrintV("gmtConfigRead: Couldn't open config file")
		error.e = error.CONFIG_READ_ERROR
		return
#!/usr/bin/python
##################
from gmusicapi import Musicmanager
from os.path import expanduser

oauthPath = expanduser("~") + "/.oauthfile"

print("storing the oauthPath in " + oauthPath)
manager = Musicmanager()
manager.perform_oauth(storage_filepath = oauthPath)
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('\\', '/'))
Beispiel #34
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'])
Beispiel #35
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)
Beispiel #36
0
class Gmusic(object):
    def __init__(self, playlists_to_sync, credentials_storage_location, debug):
        self.playlists_to_sync = playlists_to_sync
        self.credentials_storage_location = credentials_storage_location
        self._client = Mobileclient(debug_logging=debug)
        self._manager = Musicmanager(debug_logging=debug)

    def client_login(self):
        credentials = self.credentials_storage_location

        if not os.path.isfile(credentials):
            credentials = self._client.perform_oauth(
                storage_filepath=self.credentials_storage_location,
                open_browser=True)

        if not self._client.oauth_login(
                device_id=Mobileclient.FROM_MAC_ADDRESS,
                oauth_credentials=credentials,
        ):
            logger.error("Gmusic mobile client authentication failed")
            return False

        logger.info("Gmusic mobile client authentication succeeded.")
        return True

    def manager_login(self):
        credentials = self.credentials_storage_location

        if not os.path.isfile(credentials):
            credentials = self._manager.perform_oauth(
                storage_filepath=self.credentials_storage_location,
                open_browser=True)

        if not self._manager.login(oauth_credentials=credentials, ):
            logger.error("Gmusic music manager authentication failed")
            return False

        logger.info("Gmusic music manager authentication succeeded.")
        return True

    @property
    def client(self):
        if not self._client.is_authenticated():
            self.client_login()
        return self._client

    @property
    def manager(self):
        if not self._manager.is_authenticated():
            self.manager_login()
        return self._manager

    @cached_property
    def uploaded_songs(self):
        return {song['id']: song for song in self.manager.get_uploaded_songs()}

    @property
    def _playlists(self):
        playlists = self.client.get_all_user_playlist_contents()
        logger.debug("Loaded {} playlists".format(len(playlists)))
        return playlists

    @cached_property
    def playlists(self):
        playlists_to_sync = []
        for playlist in self._playlists:
            if playlist['name'] in self.playlists_to_sync:
                playlists_to_sync.append(playlist)
        return playlists_to_sync

    def get_latest_addition_date(self, playlist):
        lastModified = playlist.get('lastModifiedTimestamp')
        if lastModified:
            return datetime.fromtimestamp(int(lastModified) /
                                          10**6).replace(tzinfo=pytz.utc)

        return None
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.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists["user"])
        print ""

    def auth(self):
        self.logged_in = self.wc.login(self.email, self.password)
        self.logged_in = self.mc.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 add_rhapsody_playlist(self, filename, remove_missing=False):
        filename = self.get_platform_path(filename)
        os.chdir(os.path.dirname(filename))
        # playlist_title = os.path.splitext(os.path.basename(filename))[0]
        print "Synching File: %s" % filename

        print "Parsing Songs from %s" % filename
        pc_songs = self.get_songs_from_file(filename)
        # print (pc_songs)
        print "%d songs in local file: %s" % (len(pc_songs), filename)

        # 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 song in pc_songs:
            playlist_title = song["playlist"]
            if playlist_title not in self.playlists["user"]:
                self.playlists["user"][playlist_title] = [self.mc.create_playlist(playlist_title)]
                time.sleep(0.7)
        print "Starting Playlist Sync with Google music..."
        for song in pc_songs:
            # print song

            plid = ""

            print "--------------------------------"
            print ""
            print "Playlist: %s" % song["playlist"]
            print "Artist: %s" % song["artist"]
            print "Song: %s" % song["title"]
            print "Album: %s" % song["album"]

            playlist_title = song["playlist"]

            plid = self.playlists["user"][playlist_title][0]

            goog_songs = self.wc.get_playlist_songs(plid)

            if self.song_already_in_list(song, goog_songs):
                existing_files += 1
                print "Result: Song Already Added"
                continue
            print "Total %d songs in Google playlist: %s" % (len(goog_songs), playlist_title)
            print "%s - %s,   didn't exist...Will try to add..." % (song["artist"], song["title"])

            print ""
            print "--------------------------------"
            results = self.mc.search_all_access(song["title"], max_results=50)
            nid = self.filter_search_results(results, song)
            print "AA nId: %s " % nid
            if nid:
                song_id = self.mc.add_aa_track(nid)
                added = self.wc.add_songs_to_playlist(plid, song_id)

                print "Playlist UUid: %s" % plid
                print "Song ID: %s" % song_id
                time.sleep(0.3)  # Don't spam the server too fast...
                print "Result: done adding to playlist"
                added_files += 1
                continue
            else:
                query = "%s %s" % (song["artist"], song["title"].split(" ")[0])
                print "Query %s" % query
                results = self.mc.search_all_access(query, max_results=50)
                nid = self.filter_search_results(results, song)
                if nid:
                    song_id = self.mc.add_aa_track(nid)
                    added = self.wc.add_songs_to_playlist(plid, song_id)

                    print "Playlist UUid: %s" % plid
                    print "Song ID: %s" % song_id
                    time.sleep(0.3)  # Don't spam the server too fast...
                    print " -- done adding to playlist"
                    added_files += 1
                    continue
            print "Result: NID Blank, Song not Found in All Access"

        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_songs_from_file(self, filename):
        songs = []
        f = codecs.open(filename, encoding="utf-8")
        for line in f:
            line = line.rstrip().replace(u"\ufeff", u"")
            if line == "" or line[0] == "#":
                continue
            la = line.split("\\")
            regex_filter = "[^A-Za-z0-9\,\-\.\ \(\)'\!\?\$\/ \& \:]"

            artist = re.sub(regex_filter, "", la[1])
            playlist = re.sub(regex_filter, "", la[0])
            album = re.sub(regex_filter, "", la[2])
            title = re.sub(regex_filter, "", la[3])

            # print "Filtered Strings:"
            # print "Artist: %s" % artist
            # print "Playlist: %s" % playlist
            # print "Song: %s" % title
            # print "Album: %s" % album

            dt = {"playlist": playlist, "artist": artist, "album": album, "title": title}
            # print (dt)

            songs.append(dt)
        f.close()
        return songs

    def get_songs_from_playlist(self, filename):
        songs = []
        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
            songs.append(path)
        f.close()
        return songs

    def get_files_from_playlist(self, filename):
        files = []
        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 song_already_in_list(self, song, goog_songs):
        # tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            # print goog_songs
            if self.tag_compare(goog_songs[i], song):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def file_already_in_list(self, filename, goog_songs):
        tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            if self.tag_compare(goog_songs[i], tag):
                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, plid):
        tag = self.get_id3_tag(filename)
        print "Song Tag: %s " % tag
        print "Filename: %s" % filename
        ws_plids = []
        ws_plids.append(plid)
        print (ws_plids)
        playlists = self.wc.get_all_playlist_ids()
        print (playlists)
        results = self.wc.get_playlist_songs(ws_plids)
        # NOTE - dianostic print here to check results if you're creating duplicates
        print results
        print "%s ][ %s ][ %s ][ %s" % (tag["title"], tag["artist"], tag["album"], tag["track"])
        for r in results:
            if self.tag_compare(r, tag):
                # TODO: add rough time check to make sure its "close"
                return r
        return None

    def filter_search_results(self, results, song):
        # Try Exact Matching
        for g_song in results["song_hits"]:
            if self.tag_compare(g_song["track"], song):
                return g_song["track"]["nid"]
            elif self.song_compare(g_song["track"], song, "artist"):
                # try just the artist
                return g_song["track"]["nid"]
            elif self.song_compare(g_song["track"], song, "part-song"):
                # try part of song and artist
                return g_song["track"]["nid"]
        return None

    def song_compare(self, g_song, tag, type):
        if "track" not in g_song:
            g_song["track"] = 0
        title_parts = tag["title"].split("(")  # removing shit like (featuring wiz)
        tp = title_parts[0].split(" ")  # First word maybe
        if "artist" in type:
            return g_song["artist"].lower() == tag["artist"].lower()
        if "part-song" in type:
            return g_song["title"].find(tp[0]) and g_song["artist"].lower() == tag["artist"].lower()

        return None

    def tag_compare(self, g_song, tag):
        if "track" not in g_song:
            g_song["track"] = 0

        return (
            g_song["title"].split(" ")[0].lower() == tag["title"].split(" ")[0].lower()
            and g_song["artist"].lower() == tag["artist"].lower()
        )

    def delete_song(self, sid):
        self.wc.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("\\", "/"))
# find the mp3 file that was downloaded
files = glob.glob(f'{downloadPath}\*.mp3')
latestFile = max(files, key=os.path.getctime)

# connect to gmusicapi
mm = Musicmanager()
# check if firstRun
if "True" in firstRun:
    print(
        "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.")
Beispiel #39
0
def get_musicmanager(debug=True):
    mm = Musicmanager(debug_logging=debug)
    if not mm.login():
        mm.perform_oauth()
    return mm
Beispiel #40
0
class GoogleMusic(object):
    def __init__(self, config, log=print):
        self.OAUTH_PATH = config.get('oauth_path', '/tmp/oauth.cred')
        self.mm = Musicmanager()
        if os.path.isfile(self.OAUTH_PATH):
            success = self.mm.login(oauth_credentials=self.OAUTH_PATH)
            if not success:
                self.mm.perform_oauth(storage_filepath=self.OAUTH_PATH,
                                      open_browser=True)
        else:
            self.mm.perform_oauth(storage_filepath=self.OAUTH_PATH,
                                  open_browser=True)
        random.seed()
        self.songs = self.mm.get_uploaded_songs()
        self.queue = Queue()
        self.thread = None
        self.log = log
        self._enqueue_output()

    def _enqueue_output(self):
        song = random.choice(self.songs)
        self.log("get song id" + song['id'])
        retry = 3
        while retry > 0:
            try:
                filename, audio = self.mm.download_song(song['id'])
                if len(audio) == 0:
                    self.log("audio size 0")
                    song = random.choice(self.songs)
                    continue

                filelike = StringIO.StringIO(audio)
                metadata = mutagen.File(filelike)
                output = {
                    'song_length': 0,
                    'album': '',
                    'artist': '',
                    'title': '',
                    'audio': audio
                }

                if metadata:
                    output['song_length'] = metadata.info.length
                    output['album'] = fix_name(
                        (metadata.tags or metadata).get('TALB', dummy).text[0])
                    output['artist'] = fix_name(
                        (metadata.tags or metadata).get('TPE1', dummy).text[0])
                    output['title'] = fix_name(
                        (metadata.tags or metadata).get('TIT2', dummy).text[0])

                self.queue.put(output)
                break
            except CallFailure:
                self.log("call failure")
                song = random.choice(self.songs)
                retry -= 1

        if retry == 0:
            self.log("Google Music download fail, please restart the program")
            self.queue.put({})

    def get(self):
        # TODO: set timeout from config, blacklist this instance when retry fail
        output = self.queue.get(block=True)
        self.thread = StoppableThread(target=self._enqueue_output)
        self.thread.daemon = True
        self.thread.start()
        return output
Beispiel #41
0
def play_song_by_artist(song, artist):
    if Mobileclient.is_authenticated(gpm):
        mm = Musicmanager()
        mm.login('/home/pi/oauth.cred')

        if Musicmanager.is_authenticated(mm):
            song_dict = mm.get_purchased_songs()
            song_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(song) + r')\s?(?:.)*', re.IGNORECASE)
            artist_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(artist) + r')\s?(?:.)*',
                re.IGNORECASE)

            btn = OnButtonPress()
            btn.start()

            for song in song_dict:
                m = re.match(artist_pattern, song['artist'])
                print(m)

                if (re.match(song_pattern, song['title']) is not None and
                        re.match(artist_pattern, song['artist']) is not None):
                    print('Song found!')
                    song_id = song['id']
                    (filename, audio) = mm.download_song(song_id)

                    # get rid of non-ascii characters in file name

                    filename = filename.encode('ascii', errors='ignore')

                    # check if song is already downloaded
                    # path will look something like:
                    # /home/pi/Music/02 - Raindrop Prelude.mp3
                    # forces filename to be a string

                    filename = filename.decode('ascii')
                    path = song_location + filename
                    try:
                        if os.path.isfile(path):
                            print('Song is already downloaded...')
                            print(path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                (m, s) = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                        else:
                            with open(path, 'wb') as f:
                                f.write(audio)
                            print('Song has been added to: ' + path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                m, s = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                    except (OSError, IOError):
                        print('An error has occurred.')
                        break

                else:
                    print('Song not found yet.')

        else:
            print('Looks like you need to authenticate.')
            mm.perform_oauth('/home/pi/oauth.cred')

        print('Logging out.')
        Mobileclient.logout(gpm)
        mm.logout()

    else:
        print('Mobile client is not authenticated.')
        Mobileclient.logout(gpm)
Beispiel #42
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'])
def auth(auth_file: str = os.environ['HOME'] + '/oauth') -> None:
    api = Musicmanager()
    if api.perform_oauth(auth_file):
        print("Logged successfully")
from gmusicapi import Musicmanager

mm = Musicmanager()
mm.perform_oauth(storage_filepath=u'./oauth.cred') 
Beispiel #45
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'])
def main():
    storage = oauth2client.file.Storage(CREDENTIALS_PATH)
    credentials = storage.get()

    if not credentials or credentials.invalid:
        Musicmanager.perform_oauth(CREDENTIALS_PATH, open_browser=False)
Beispiel #47
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
Beispiel #48
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()]