Example #1
0
class GMusicWS:
    def __init__(self, user, password, playlistName):
        self.playlistName = playlistName
        self.api = Mobileclient()
        print("Logging into MobileClient API")
        self.api.login(user, password,
                       "android_id")  #insert unique android_id here

    def mapUnknownTracks(self, db):
        playlist = db.unmappedTracks()

        for track in playlist:
            searchstr = track.artist + " " + track.song
            print("Searching for %s" % (searchstr))
            try:
                result = self.api.search_all_access(searchstr, max_results=1)
                print("Found " + result['song_hits'][0]['track']['artist'] +
                      " - " + result['song_hits'][0]['track']['title'])
                nid = result['song_hits'][0]['track']['nid']
                db.storemapping(track.song, track.artist, nid)
            except:
                print("Error parsing result: " + str(result))

            time.sleep(1)

    def maintain(self, tracks):
        print("Searching for playlist %s" % (self.playlistName))

        found = False
        searchres = self.api.get_all_playlists()
        for list in searchres:
            if list['name'] == self.playlistName:
                found = True
                pid = list['id']

        if not found:
            print("Not found - creating")
            pid = self.api.create_playlist(self.playlistName)

        print("Playlist id is %s" % (pid))

        print("Getting current contents")
        playlists = self.api.get_all_user_playlist_contents()
        currentEntries = []
        for playlist in playlists:
            if playlist['name'] == self.playlistName:
                for entry in playlist['tracks']:
                    currentEntries.append(entry['id'])

        print("Removing songs")
        self.api.remove_entries_from_playlist(currentEntries)

        print("Adding songs")
        self.api.add_songs_to_playlist(pid, tracks)
Example #2
0
class GMusicWS:
	def __init__(self, user, password, playlistName):
		self.playlistName = playlistName
		self.api = Mobileclient()
		print ("Logging into MobileClient API")
		self.api.login(user, password,"android_id") #insert unique android_id here

	def mapUnknownTracks(self, db):
		playlist = db.unmappedTracks()
		
		for track in playlist:
			searchstr = track.artist + " " + track.song
			print ("Searching for %s" % (searchstr))
			try:
				result = self.api.search_all_access(searchstr, max_results=1)
				print ("Found " + result['song_hits'][0]['track']['artist'] + " - " + result['song_hits'][0]['track']['title'])
				nid = result['song_hits'][0]['track']['nid']
				db.storemapping(track.song, track.artist, nid)
			except:
				print ("Error parsing result: " + str(result))
				
			time.sleep(1)
	
	def maintain(self, tracks):
		print ("Searching for playlist %s" % (self.playlistName))
				
		found = False
		searchres = self.api.get_all_playlists()
		for list in searchres:
			if list['name'] == self.playlistName:
				found = True
				pid = list['id']
				
		if not found:
			print ("Not found - creating")
			pid = self.api.create_playlist(self.playlistName)
		
		print ("Playlist id is %s" % (pid))
		
		print ("Getting current contents")
		playlists = self.api.get_all_user_playlist_contents()
		currentEntries = []
		for playlist in playlists:
			if playlist['name'] == self.playlistName:
				for entry in playlist['tracks']:
					currentEntries.append(entry['id'])

		print ("Removing songs")		
		self.api.remove_entries_from_playlist(currentEntries)
		
		print ("Adding songs")
		self.api.add_songs_to_playlist(pid, tracks)
Example #3
0
class PlayMusic:
    def __init__(self, google_username, google_password):
        self.client = Mobileclient(validate=False)
        # generate a stable, unique android id
        h = hashlib.sha256()
        h.update(google_username)
        android_id = h.hexdigest()[:16]
        self.client.login(google_username, google_password, android_id)

    def is_authenticated(self):
        return self.client.is_authenticated()

    @staticmethod
    def track_url(play_track):
        return "https://play.google.com/music/m/%s" % play_track["nid"]

    @staticmethod
    def playlist_url(playlist_id):
        return "https://play.google.com/music/playlist/%s" % playlist_id

    def search_tracks(self, query):
        if len(query) >= MAX_QUERY_LENGTH:
            # long queries don't work for some reason
            # for example "The Moderately Talented Yet Attractive Young Woman vs. The Exceptionally Talented Yet Not
            # So Attractive Middle Aged Man / Sun Kil Moon / Among The Leaves"
            parts = query.split(" ")
            query = parts.pop(0)
            for part in parts:
                if len(query) + 1 + len(part) > MAX_QUERY_LENGTH:
                    break
                query += " " + part

        retries = RETRIES
        response = None
        while retries and not response:
            retries -= 1
            try:
                response = self.client.search_all_access(query)
            except Exception, e:
                if not retries:
                    raise e
                # sleep for two seconds before retrying
                time.sleep(2)
        return [PlayTrack(song["track"]) for song in response["song_hits"]]
Example #4
0
class PlayMusic():
    def __init__(self, google_username, google_password):
        self.client = Mobileclient(validate=False)
        # generate a stable, unique android id
        h = hashlib.sha256()
        h.update(google_username)
        android_id = h.hexdigest()[:16]
        self.client.login(google_username, google_password, android_id)

    def is_authenticated(self):
        return self.client.is_authenticated()

    @staticmethod
    def track_url(play_track):
        return 'https://play.google.com/music/m/%s' % play_track['nid']

    @staticmethod
    def playlist_url(playlist_id):
        return 'https://play.google.com/music/playlist/%s' % playlist_id

    def search_tracks(self, query):
        if len(query) >= MAX_QUERY_LENGTH:
            # long queries don't work for some reason
            # for example "The Moderately Talented Yet Attractive Young Woman vs. The Exceptionally Talented Yet Not
            # So Attractive Middle Aged Man / Sun Kil Moon / Among The Leaves"
            parts = query.split(' ')
            query = parts.pop(0)
            for part in parts:
                if len(query) + 1 + len(part) > MAX_QUERY_LENGTH:
                    break
                query += ' ' + part

        retries = RETRIES
        response = None
        while retries and not response:
            retries -= 1
            try:
                response = self.client.search_all_access(query)
            except Exception, e:
                if not retries:
                    raise e
                # sleep for two seconds before retrying
                time.sleep(2)
        return [PlayTrack(song['track']) for song in response['song_hits']]
Example #5
0
#!/bin/python2

import sys
from gmusicapi import Mobileclient

if len(sys.argv) < 2:
    print "Please provide a query string"
    sys.exit(1)
song_name = sys.argv[1]

api = Mobileclient()
is_logged_in = api.login('ztaticnull', 'kkjyumnguxiqiixx','0000000000000000')

if not is_logged_in:
    print "Could not authenticate"
    sys.exit(1)

results = api.search_all_access(song_name, max_results=100)

songs = [(s['track']['storeId'],
          s['track']['artist'], 
          s['track']['title'])
          for s in results['song_hits']]

for s in songs:
    s = [x.encode('utf-8') for x in s]
    print "%s:%s - %s" % tuple(s)
Example #6
0
class GooglePlayMusic(BaseModule):
	def __init__(self, client, options):
		super(GooglePlayMusic, self).__init__(client, options)

		self.api = Mobileclient()
		if self.api.login(self.options["username"], self.options["password"]):
			print "Login Successful"
		self.webClient = Webclient()
		self.webClient.login(self.options["username"], self.options["password"])

		#self.findRegisteredDevice()
		self.deviceId = self.options["deviceId"]
		self.speaker = self.options["speaker"]

		self.playing_track_list = False
		self.current_track_list = []
		self.current_track_index = 0

	"""
	def findRegisteredDevice(self):
		webClient = Webclient()
		webClient.login(self.options["username"], self.options["password"])
		registered_devices = webClient.get_registered_devices()
		for device in registered_devices:
			if device["type"] == "PHONE":
				self.deviceId = device["id"][2:] #removes the 0x from the front
	"""

	def onEvent(self, message):
		if message["from"] == self.speaker:
			if message["event"] == "streamEnded":
				if self.playing_track_list:
					self.continue_track_list()

	def onAction(self, message):
		if message["action"] == "search_and_play":
			query = message["data"]["query"]
			self.search_and_play(query)

		if message["action"] == "stopMusic" or message["action"] == "stop":
			self.stop_music()

		if message["action"] == "startRadio":
			query = message["data"]["query"]
			self.start_radio(query)

	def search_and_play(self, query):
		results = self.api.search_all_access(query)
		if not len(results["song_hits"]) > 0:
			return
		song_data = results["song_hits"][0]["track"]
		print song_data
		self.play_track(song_data)

	def play_track(self, song_data):
		print "Playing %s, by %s" % (song_data["title"], song_data["artist"])
		stream_url = self.api.get_stream_url(song_data["nid"], self.deviceId)
		self.client.emitAction(self.speaker, "streamMP3", {"url": stream_url})

	def stop_music(self):
		self.playing_track_list = False
		self.client.emitAction(self.speaker, "stopStreaming", {})

	def start_radio(self, query):
		results = self.api.search_all_access(query, max_results=10)
		top_song = results["song_hits"][0] if len(results["song_hits"]) else None
		top_album = results["album_hits"][0] if len(results["album_hits"]) else None
		top_artist = results["artist_hits"][0] if len(results["artist_hits"]) else None

		if not top_song:
			top_song = {"score": 0}
		if not top_album:
			top_album = {"score": 0}
		if not top_artist:
			top_artist = {"score": 0}

		station_id = None
		if top_song["score"] > top_album["score"]and top_song["score"] > top_artist["score"]:
			station_id = self.api.create_station(query, track_id=top_song["track"]["nid"])
		elif top_album["score"] > top_song["score"] and top_album["score"] > top_artist["score"]:
			station_id = self.api.create_station(query, album_id=top_album["album"]["albumId"])
		else:
			station_id = self.api.create_station(query, artist_id=top_artist["artist"]["artistId"])
		
		tracks = self.api.get_station_tracks(station_id)
		
		self.play_track_list(tracks)

	def play_track_list(self, tracks):
		self.playing_track_list = True
		self.current_track_list = tracks
		self.current_track_index = 0
		self.play_track(self.current_track_list[0])

	def continue_track_list(self):
		self.current_track_index += 1
		self.play_track(self.current_track_list[self.current_track_index])
Example #7
0
    if logged_in == True:
        print ("Succesfully logged into Google!")
    ## Take a file with song names - artists and Playlists names beginning with P:

    all_playlists = parse_file("playlists.txt")
    missing_songs = []
    for i in all_playlists:
        for j in i:
            if j[0:2] == "P:":
                current_playlist_name = j[3:]
                print ("Creating playlist: " + j[3:])
                # current_playlist = api.create_playlist(j[3:]) #COMMENT OUT THIS LINE TO PREVENT PLAYLIST CREATION
            else:
                current_song = j[0][0] + " " + j[0][1]

                search_current_song = api.search_all_access(current_song, 1)
                if search_current_song["song_hits"] == []:
                    print ("No results found for " + current_song)
                    missing_songs.append([current_song, current_playlist_name])

                    continue
                current_song_id = search_current_song["song_hits"][0]["track"]["storeId"]
                print ("Adding " + current_song + " to playlist " + current_playlist_name)
                # api.add_songs_to_playlist(current_playlist, current_song_id) #COMMENT OUT THIS LINE TO PREVENT PLAYLIST CREATION
    for i in missing_songs:
        print ("Could not find " + i[0] + " for playlist " + i[1])

    ##desperado = api.search_all_access("Desperado - The Eagles", 1)
    ##print(desperado['song_hits'])
    ##for i in desperado['song_hits']:
    ##song_ids = [i['track']['storeId']]
from gmusicapi import Mobileclient
from grooveshark import Client
import sys

api = Mobileclient()
api.login(sys.argv[1], sys.argv[2])

groove_client = Client()

playlist = groove_client.playlist(sys.argv[3])

gp_songs=[]

for song in playlist.songs:
    query = song.name + " " + song.artist.name
    gp_query_result = api.search_all_access( query, 1)
    try:
        track = gp_query_result['song_hits'][0]['track']
        print( "Adding " + track['title'] + " by " +  track['artist'] )
        gp_songs.append(track['nid'])
    except IndexError as e:
        print("Coudn't find " + query);
        pass
    except:
        print(e)
        pass

gp_playlist = api.create_playlist(playlist.name)
api.add_songs_to_playlist(gp_playlist, gp_songs)
Example #9
0
data = {'zipCode': zipcode,
        'radius': radius_in_miles,
        'page': 0,
        'api_key': jambase_api_key}

response = requests.get("http://api.jambase.com/events", params=data)
data = response.json()

for event in data['Events']:
    for artist in event['Artists']:
        artist_name = artist['Name']
        print "\n", artist_name, "@", event['Venue']['Name'],
        
        # search Google All Access for the artist
        result = gapi.search_all_access(artist_name)
        
        # look at the first result
        for google_artist_data in result.get('artist_hits', []):
            google_artist = google_artist_data['artist']
            google_artist_id = google_artist['artistId']
            print "----> %s (%0.2f)" % (google_artist['name'], google_artist_data['score'])
            if google_artist_data['score'] > 200:
                # TODO: confirm high string similarity, as sometimes Google gives high scores to 
                # strange matches.
                song_data = gapi.get_artist_info(google_artist_id, include_albums=False, max_top_tracks=5, max_rel_artist=0)
                for top_track in song_data.get('topTracks', []):
                    #if top_track['genre'] in banned_genres:
                    #   continue 
                    print " + %s [%s]" % (top_track['title'], top_track.get('genre','N/A'))
                    song_id = top_track.get('id') or top_track.get('nid')
Example #10
0
class GMusic(object):
    def __init__(self):
        self.authenticated = False
        self.all_access = False
        self._device = None
        self._webclient = Webclient(debug_logging=False)
        self._mobileclient = Mobileclient(debug_logging=False)
        self._playlists = []
        self._playlist_contents = []
        self._all_songs = []
        self._all_artists = {}
        self._all_albums = {}
        self._all_genres = {}
        self._stations = []

    def _get_device_id(self):
        if self.authenticated:
            devices = self._webclient.get_registered_devices()
            for dev in devices:
                if dev['type'] == 'PHONE':
                    self._device = dev['id'][2:]
                    break

    def _set_all_access(self):
        settings = self._webclient._make_call(webclient.GetSettings, '')
        self.all_access = True if 'isSubscription' in settings['settings'] and settings['settings']['isSubscription'] == True else False

    def authenticate(self, email, password):
        try:
            mcauthenticated = self._mobileclient.login(email, password)
        except AlreadyLoggedIn:
            mcauthenticated = True

        try:
            wcauthenticated = self._webclient.login(email, password)
        except AlreadyLoggedIn:
            wcauthenticated = True

        self.authenticated = mcauthenticated and wcauthenticated
        self._get_device_id()
        self._set_all_access()
        return self.authenticated

    def get_all_songs(self, id=None):
        if len(self._all_songs) == 0:
            try:
                self._all_songs = self._mobileclient.get_all_songs()
            except NotLoggedIn:
                if self.authenticate():
                    self._all_songs = self._mobileclient.get_all_songs()
                else:
                    return []

        if id:
            return [x for x in self._all_songs if x['id'] == id][0]
        else:
            return self._all_songs

    def get_all_artists(self):
        if not self._all_artists:
            songs = self.get_all_songs()
            for song in songs:
                artist = song['artist']
                thumb = None
                if artist not in self._all_artists:
                    self._all_artists[artist] = []

                track = {'title': song['title'],
                        'album': song['album'],
                        'artist': artist,
                        'durationMillis': song['durationMillis'],
                        'trackType': song['trackNumber'],
                        'id': song['id']}

                if 'albumArtRef' in song:
                    track['albumArtRef'] = song['albumArtRef']

                if 'artistArtRef' in song:
                    thumb = song['artistArtRef'][0]['url']

                if 'storeId' in song:
                    track['storeId'] = song['storeId']

                self._all_artists[artist].append({'track': track, 'thumb': thumb, 'id': song['id']})

        return self._all_artists

    def get_all_albums(self):
        if not self._all_albums:
            songs = self.get_all_songs()
            for song in songs:
                album = song['album']
                thumb = None
                if album not in self._all_albums:
                    self._all_albums[album] = []

                track = {'title': song['title'],
                        'album': album,
                        'artist': song['artist'],
                        'durationMillis': song['durationMillis'],
                        'trackType': song['trackNumber'],
                        'id': song['id']}

                if 'albumArtRef' in song:
                    track['albumArtRef'] = song['albumArtRef']
                    thumb = song['albumArtRef'][0]['url']

                if 'storeId' in song:
                    track['storeId'] = song['storeId']

                self._all_albums[album].append({'track': track, 'thumb': thumb, 'id': song['id']})

        return self._all_albums

    def get_all_genres(self):
        if not self._all_genres:
            songs = self.get_all_songs()
            for song in songs:
                genre = song['genre']
                if genre not in self._all_genres:
                    self._all_genres[genre] = []

                track = {'title': song['title'],
                        'album': song['album'],
                        'artist': song['artist'],
                        'durationMillis': song['durationMillis'],
                        'trackType': song['trackNumber'],
                        'id': song['id']}

                if 'albumArtRef' in song:
                    track['albumArtRef'] = song['albumArtRef']

                if 'storeId' in song:
                    track['storeId'] = song['storeId']

                self._all_genres[genre].append({'track': track, 'id': song['id']})

        return self._all_genres

    def get_all_playlists(self):
        if len(self._playlists) == 0:
            try:
                self._playlists = self._mobileclient.get_all_playlists()
            except NotLoggedIn:
                if self.authenticate():
                    self._playlists = self._mobileclient.get_all_playlists()
                else:
                    return []

        return self._playlists

    def get_all_user_playlist_contents(self, id):
        tracks = []
        if len(self._playlist_contents) == 0:
            try:
                self._playlist_contents = self._mobileclient.get_all_user_playlist_contents()
            except NotLoggedIn:
                if self.authenticate():
                    self._playlist_contents = self._mobileclient.get_all_user_playlist_contents()
                else:
                    return []

        for playlist in self._playlist_contents:
            if id == playlist['id']:
                tracks = playlist['tracks']
                break

        return tracks

    def get_shared_playlist_contents(self, token):
        playlist = []
        try:
            playlist = self._mobileclient.get_shared_playlist_contents(token)
        except NotLoggedIn:
            if self.authenticate():
                playlist = self._mobileclient.get_shared_playlist_contents(token)
            else:
                return []

        return playlist

    def get_all_stations(self):
        if len(self._stations) == 0:
            try:
                self._stations = self._mobileclient.get_all_stations()
            except NotLoggedIn:
                if self.authenticate():
                    self._stations = self._mobileclient.get_all_stations()
                else:
                    return []

        return self._stations

    def get_station_tracks(self, id, num_tracks=200):
        tracks = []
        try:
            tracks = self._mobileclient.get_station_tracks(id, num_tracks)
        except NotLoggedIn:
            if self.authenticate():
                tracks = self._mobileclient.get_station_tracks(id, num_tracks)
            else:
                return []

        return tracks

    def get_genres(self):
        genres = []
        try:
            genres = self._mobileclient.get_genres()
        except NotLoggedIn:
            if self.authenticate():
                genres = self._mobileclient.get_genres()
            else:
                return []

        return genres

    def create_station(self, name, id):
        station = None
        try:
            station = self._mobileclient.create_station(name=name, genre_id=id)
        except NotLoggedIn:
            if self.authenticate():
                station = self._mobileclient.create_station(name=name, genre_id=id)
            else:
                return []

        return station

    def search_all_access(self, query, max_results=50):
        results = None
        try:
            results = self._mobileclient.search_all_access(query, max_results)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.search_all_access(query, max_results)
            else:
                return []

        return results

    def get_artist_info(self, id, include_albums=True, max_top_tracks=5, max_rel_artist=5):
        results = None
        try:
            results = self._mobileclient.get_artist_info(id, include_albums=include_albums, max_top_tracks=max_top_tracks, max_rel_artist=max_rel_artist)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_artist_info(id, include_albums=include_albums, max_top_tracks=max_top_tracks, max_rel_artist=max_rel_artist)
            else:
                return []

        return results

    def get_album_info(self, id, include_tracks=True):
        results = None
        try:
            results = self._mobileclient.get_album_info(id, include_tracks=include_tracks)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_album_info(id, include_tracks=include_tracks)
            else:
                return []

        return results

    def get_stream_url(self, id):
        try:
            stream_url = self._mobileclient.get_stream_url(id, self._device)
        except NotLoggedIn:
            if self.authenticate():
                stream_url = self._mobileclient.get_stream_url(id, self._device)
            else:
                return ''
        except CallFailure:
            raise CallFailure('Could not play song with id: ' + id, 'get_stream_url')

        return stream_url
Example #11
0
    if 'nid' not in t or t['nid'][0] != 'T':
      missing.append(info)

def summary(track):
    print title(track)
    if 'nid' in track and track['nid'].startswith('T'):
        print 'https://play.google.com/music/m/%s' % track['nid']

def title(track):
    return "%35.33s / %.20s / \"%.20s\"" % (track['album'], track['artist'], track['title'])

nomatch = ''
toomany = []
found = []
for t in missing:
    res = (mc.search_all_access('"%s" "%s"' % (t['artist'], t['title'])))['song_hits']
    if len(res) == 0:
      nomatch += title(t) + "\n"
      continue
    if t['nid'] in [x['track'].get('nid', None) for x in res]:
      found.append(title(t))
      continue
    if len(res) < 10:
      summary(t)
      print '-' * 80
      print "%d possible suggestions:" % len(res)
      for r in res:
        summary(r['track'])
      print "\n\n"
      continue
    toomany.append((title(t), len(res)))
Example #12
0
import sys
from gmusicapi import Mobileclient

if __name__ == "__main__":
    if sys.argv[1] == "1":
        mc = Mobileclient()
        success = mc.login(sys.argv[3], sys.argv[4])
        if success == True:
            sresults = mc.search_all_access(sys.argv[2], 1)  #2 = query
            song = sresults['song_hits'][0]
            sid = song['track']['nid']
            sname = song['track']['title']
            sartist = song['track']['artist']
            sartistid = song['track']['artistId'][0]
            salbum = song['track']['album']
            salbumart = song['track']['albumArtRef'][0]['url']
            aresults = mc.get_artist_info(sartistid, False, 1, 1)
            artistart = aresults['artistArtRef']
            print(sid)
            print(sname)
            print(sartist)
            print(salbum)
            print(salbumart)
            print(artistart)
    if sys.argv[1] == "2":
        print("Spotify is not yet supported.")
class GoogleMusicClient(object):

  def __init__(self, username, password):
    self._username = username
    self._password = password
    self._apiClient = None

  def initConnection(self):
    self._apiClient = Mobileclient(debug_logging=False)
    if not self._apiClient.login(self._username, self._password):
      raise RuntimeError("Could not connect %s to Google Music." % \
                          self._username)

  def addPlaylist(self, playlist):
    plid = self._apiClient.create_playlist(playlist.name)
    tids = []
    for track in playlist.tracks:
      aaid = self._getAllAccessTrackId(track)
      if aaid:
        try:
          tid = self._apiClient.add_aa_track(aaid)
          if tid:
            tids.append(tid)
          else:
            LOGGER.warning( "Could not add track %s to library.", str(track))
        except:
          LOGGER.error("Could not add track %s to library.", str(track))
          continue
      else:
        LOGGER.warning("Track %s not found.", str(track))
    self._apiClient.add_songs_to_playlist(plid, tids)

  def addAlbum(self, album):
    aaid = self._getAllAccessAlbumId(album)
    if aaid:
      albumInfo = self._apiClient.get_album_info(aaid, include_tracks=True)
      for track in albumInfo["tracks"]:
        try:
          self._apiClient.add_aa_track(track[Track.GM_ID_KEY])
        except:
          LOGGER.error("Could not add track %s to library.", str(track))
          continue
    else:
      LOGGER.warning("Album %s not found.", str(album))

  def _getAllAccessFirstResult(self, resource):
    queryStr = re.sub("[-:\(\)\",]","", "%s %s" % (resource.name,
                                                   resource.artist))
    queryStr = re.sub("\s+", "+", queryStr)
    searchResults = self._apiClient.search_all_access(queryStr)
    gmusicResources = searchResults.get(resource.GM_HITS_KEY)
    if gmusicResources:
      firstResult = gmusicResources[0][resource.GM_NAME]
      return firstResult[resource.GM_ID_KEY]
    else:
      return None

  def _getAllAccessTrackId(self, track):
    return self._getAllAccessFirstResult(track)

  def _getAllAccessAlbumId(self, album):
    return self._getAllAccessFirstResult(album)
Example #14
0
from gmusicapi import Mobileclient
from getpass import getpass
import json

# fill this in
email = ''

api = Mobileclient()
logged_in = api.login(email, getpass())

if logged_in:
  for track in json.load(open('dump.json')):
    title = track['title']
    artist = track['artist']
    query = u"{title!s} - {artist!s}".format(**locals())
    results = api.search_all_access(query)['song_hits']

    if len(results) > 0:
      storeId = results[0]['track']['storeId']
      api.add_aa_track(storeId)
    else:
      print u"Google Music lacks: {query!s}".format(**locals())
else:
  print "failed to log in"
def summary(track):
    print title(track)
    if 'nid' in track and track['nid'].startswith('T'):
        print 'https://play.google.com/music/m/%s' % track['nid']


def title(track):
    return "%35.33s / %.20s / \"%.20s\"" % (track['album'], track['artist'],
                                            track['title'])


nomatch = ''
toomany = []
found = []
for t in missing:
    res = (mc.search_all_access('"%s" "%s"' %
                                (t['artist'], t['title'])))['song_hits']
    if len(res) == 0:
        nomatch += title(t) + "\n"
        continue
    if t['nid'] in [x['track'].get('nid', None) for x in res]:
        found.append(title(t))
        continue
    if len(res) < 10:
        summary(t)
        print '-' * 80
        print "%d possible suggestions:" % len(res)
        for r in res:
            summary(r['track'])
        print "\n\n"
        continue
    toomany.append((title(t), len(res)))
Example #16
0
class GoogleMusicApi:
    def __init__(self):
        self._api = Mobileclient()

    def login(self, username, password, device_id):
        try:
            return self._api.login(username, password, device_id)
        except AlreadyLoggedIn:
            Logger.debug('API: Already logged in')
            return True

    def relogin(self, username, password, device_id):
        try:
            return self._api.login(username, password, device_id)
        except AlreadyLoggedIn:
            self._api.logout()
            return self._api.login(username, password, device_id)

    def logout(self):
        return self._api.logout()

    def get_registered_mobile_devices(self):
        devices = self._api.get_registered_devices()
        mobile_devices = []
        for device in devices:
            if device['type'] == "ANDROID":  # TODO: Add iOS
                mobile_devices.append({
                    'name': device['friendlyName'],
                    'id': device['id'][2:]
                })
        return mobile_devices

    def get_stream_url(self, track_id, quality):
        return self._api.get_stream_url(song_id=track_id, quality=quality)

    def get_library(self):
        return self._api.get_all_songs()

    def get_album_info(self, album_id):
        return self._api.get_album_info(album_id)

    def search(self, query, max_results=25):
        # TODO: make number of results configurable / add to settings
        try:
            return self._api.search_all_access(query, max_results)
            # TODO: remove when gmusicapi 9.0.1 is stable
        except AttributeError:  # develop version of gmusicapi is installed
            return self._api.search(query, max_results)

    def get_station_tracks(self, title, seed, num_tracks=25, recently_played_ids=None):
        # TODO: make number of results configurable / add to settings
        # TODO: check for existing stations, so we don't always create new ones (maybe not necessary: stations created with same seed have the same id
        seed_type = seed['type']
        seed = seed['seed']
        station_id = ''
        Logger.debug('Station: Creating station (Title: {}, Seed: {}, Type:{}'.format(title, seed, seed_type))
        if seed_type == 'track':
            station_id = self.create_station(title, track_id=seed)
        elif seed_type == 'artist':
            station_id = self.create_station(title, artist_id=seed)
        elif seed_type == 'album':
            station_id = self.create_station(title, album_id=seed)
        elif seed_type == 'genre':
            station_id = self.create_station(title, genre_id=seed)
        elif seed_type == 'curated':
            Logger.debug("Station: CuratedStationId seed, don't know what to do :(")
        else:
            Logger.error("Station: Unknown seed, don't know what to do :(")

        if station_id:
            Logger.debug('Station: ID is ' + station_id)
            station_tracks = self._api.get_station_tracks(station_id, num_tracks, recently_played_ids)
            Logger.debug('Station: Station has {} tracks'.format(len(station_tracks)))
            return station_tracks
        else:
            Logger.warning("Station: Could not retrieve station ID")
            return []

    def get_feeling_lucky_station_tracks(self, num_tracks=25, recently_played_ids=None):
        # TODO: make number of results configurable / add to settings
        return self._api.get_station_tracks('IFL', num_tracks, recently_played_ids)

    def create_station(self, name, track_id=None, artist_id=None, album_id=None, genre_id=None, playlist_token=None):
        return self._api.create_station(name, track_id=track_id, artist_id=artist_id, album_id=album_id,
                                        genre_id=genre_id, playlist_token=playlist_token)

    def increment_track_playcount(self, track_id):
        self._api.increment_song_playcount(track_id)
Example #17
0
class GMusicClient(ContentConsumer):
    '''Element in charge of interfacing with GMusicApi Client'''

    def __init__(self, data_cache):
        self.client = Mobileclient()
        self.data_cache = data_cache

    def login(self):
        '''Use data/unlocked/credentials.json to log in'''
        mac = Mobileclient.FROM_MAC_ADDRESS
        credentials = json.load(open('data/unlocked/credentials.json', 'r'))
        self.client.login(credentials['username'], credentials['password'], mac)

    def load_my_library(self):
        '''Load user's songs, playlists, and stations'''
        track_load = threading.Thread(target=self.load_tracks)
        radio_load = threading.Thread(target=self.load_radios)
        playlist_load = threading.Thread(target=self.load_playlists)

        track_load.start()
        radio_load.start()
        playlist_load.start()

        track_load.join()
        radio_load.join()
        playlist_load.join()

    def load_playlists(self):
        playlists = self.client.get_all_user_playlist_contents()
        playlists.reverse()
        self.data_cache.playlists = playlists

    def load_tracks(self):
        self.data_cache.tracks = [t for t in self.client.get_all_songs() if 'nid' in t]

    def scrape_song(self, track):
        return track

    def load_radios(self):
        radios = self.client.get_all_stations()
        radios.reverse()
        self.data_cache.radios = radios

    def get_radio_contents(self, radio_id):
        tracks = self.client.get_station_tracks(radio_id)
        return tracks

    def get_radio_list(self, name):
        return [r for r in self.data_cache.radios if name in r['name']]

    def filter(self, element, field, filter_by):
        return [e for e in element if filter_by in e[field]]

    def get_playlist_list(self, name):
        return self.filter(self.data_cache.playlists, 'name', name)

    def search_all_access(self, query):
        return self.client.search_all_access(query)

    def create_radio(self, seed_type, id, name):
        '''Create a radio'''
        # This is a weird way to do this, but there's no other choice
        ids = {"track": None, "album": None, "artist": None}
        seed_id_name = self.get_type_name(seed_type)
        ids[seed_id_name] = id
        return self.client.create_station(name=name, track_id=ids['track'], album_id=ids['album'], artist_id=ids['artist'])

    def search_items_all_access(self, type, query):
        '''Searches Albums, Artists, and Songs; uses metaprogramming'''
        index_arguments = self.get_index_arguments(type)

        items = self.search_all_access(query)['{0}_hits'.format(type[:-1])]
        return [self.format_item(item, type, index_arguments) for item in items]

    def get_sub_items(self, type_from, search_type, from_id):
        '''Here type_from refers to artist or album we're indexing against'''
        args = self.get_index_arguments(search_type)

        if type_from == 'playlist':
            return self.get_playlist_contents(from_id)

        else:
            # Get the appropriate search method and execute it
            search_method_name = 'get_{0}_info'.format(type_from)
            search_method = getattr(self.client, search_method_name)
            try:
                items = search_method(from_id, True)[args['type']+'s'] # True here includes subelements
            except:
                # User passed in a bad id or something
                return

        # Now return appropriately
        return [self.format_subitems(t, args) for t in items if args['id'] in t]

    def get_playlist_contents(self, from_id):
        '''Playlist exclusive stuff'''
        shareToken = [t for t in self.data_cache.playlists \
            if t['id'] == from_id][0]['shareToken']

        contents = self.client.get_shared_playlist_contents(shareToken)
        return [self.format_playlist_contents(t) for t in contents if 'track' in t]

    def get_suggested(self):
        '''Returns a list of tracks that the user might be interested in'''
        items = sorted(self.client.get_promoted_songs(), key=lambda y: y['title'])
        return [self.format_suggested(t) for t in items if 'storeId' in t]

    def get_information_about(self, from_type, from_id):
        '''Gets specific information about an id (depending on the type)'''
        if 'artist' in from_type.lower():
            return self.client.get_artist_info(from_id, include_albums=False)
        if 'album' in from_type.lower():
            return self.client.get_album_info(from_id, include_tracks=False)
        return self.client.get_track_info(from_id)

    def get_stream_url(self, nid):
        return self.client.get_stream_url(nid)

    def lookup(self, nid):
        return self.client.get_track_info(nid)

    def add_track_to_library(self, nid):
        self.client.add_aa_track(nid)

    def add_to_playlist(self, playlist_id, nid):
        self.client.add_songs_to_playlist(playlist_id, nid)

        playlist_load = threading.Thread(target=self.load_playlists)
        playlist_load.daemon = True
        playlist_load.start()

    def format_suggested(self, t):
        return (t['title'], t['storeId'], 'Play', t['album'])

    def format_playlist_contents(self, t):
        return (t['track']['title'], t['trackId'], 'Play', t['track']['album'])

    def format_subitems(self, t, args):
        return (t[args['name']], t[args['id']], args['command'], t[args['alt']])
Example #18
0
class MusicManager(object):
    def __init__(self):

        self.api = Mobileclient(validate=False, debug_logging=False)
        if config.GOOGLE_STREAMKEY is not None:
            self.api.login(config.GOOGLE_USERNAME, config.GOOGLE_PASSWORD, config.GOOGLE_STREAMKEY)
        else:
            self.api.login(config.GOOGLE_USERNAME, config.GOOGLE_PASSWORD, Mobileclient.FROM_MAC_ADDRESS)

        self.queue = []
        self.current_index = len(self.queue) - 1

        self.vlc = VlcManager()

        self.state_thread = Thread(target=self.check_state)
        self.state_thread.daemon = True
        self.state_thread.start()

    def play_song(self, id):
        song = self.queue_song(id)
        self.current_index = len(self.queue) - 1
        self.load_song()
        return song

    def queue_song(self, id):
        self.queue.append(self.getSongInfo(id))

    def play_radio_station(self, id):
        results = self.api.get_station_tracks(id, num_tracks=40)

        for song in results:
            song['albumArtRef'] = song['albumArtRef'][0]['url']
            if 'artistId' in song:
                song['artistId'] = song['artistId'][0]

        self.current_index = len(self.queue) - 1
        self.queue.append(results)
        self.load_song()

    def play_album(self, args):
        album = self.get_album_details(args)
        songs = []
        for index in range(len(album['tracks'])):
            song = album['tracks'][index]
            if index == 0:
                songs.append(self.play_song(song['nid']))
            else:
                songs.append(self.queue_song(song['nid']))
        return songs

    def queue_album(self, args):
        album = self.get_album_details(args)
        songs = []
        for song in album['tracks']:
            songs.append(self.queue_song(song['nid']))
        return songs

    def next(self):
        self.current_index += 1
        self.load_song()

    def prev(self):
        self.current_index -= 1
        self.load_song()

    def pause(self):
        self.vlc.vlc_pause()

    def resume(self):
        self.vlc.vlc_resume()

    def volume(self, val):
        self.vlc.vlc_volume(val)

    def delete(self, id):
        if id > self.current_index:
            del self.queue[id]
        elif id < self.current_index:
            del self.queue[id]
            self.current_index -= 1
        else:
            del self.queue[id]
            self.load_song()

    def go_to(self, id):
        self.current_index = id
        self.load_song()

    def load_song(self):
        if self.current_index < len(self.queue):
            song = self.queue[self.current_index]
            url = self.api.get_stream_url(song['nid'], config.GOOGLE_STREAMKEY)
            self.vlc.vlc_play(url)

    def check_state(self):
        while True:
            status = self.vlc.player.get_state()
            if status == vlc.State.Ended:
                if self.current_index != len(self.queue) - 1:
                    self.next()

            time.sleep(1)

    def get_status(self):

        status = self.vlc.vlc_status()

        # status['queue'] = self.queue[:]
        # for i in range(len(status['queue'])):
        #     status['queue'][i]['vlcid'] = i
        #     if i == self.current_index:
        #         status['queue'][i]['current'] = True
        #         status['current'] = status['queue'][i]
        if len(self.queue) > 0:
            status['current'] = self.queue[self.current_index]
        return status

    def get_queue(self):
        queue = self.queue[:]
        for i in range(len(queue)):
            queue[i]['vlcid'] = i

        return queue


    def search(self, query):
        results = self.api.search_all_access(query, max_results=50)

        results['artist_hits'] = [artist['artist'] for artist in results['artist_hits']]

        results['album_hits'] = [album['album'] for album in results['album_hits']]
        for album in results['album_hits']:
            album['artistId'] = album['artistId'][0]

        results['song_hits'] = [song['track'] for song in results['song_hits']]
        for song in results['song_hits']:
            song['albumArtRef'] = song['albumArtRef'][0]['url']
            if 'artistId' in song:
                song['artistId'] = song['artistId'][0]
        return results

    def get_album_details(self, id):
        results = self.api.get_album_info(album_id=id, include_tracks=True)
        results['artistId'] = results['artistId'][0]
        for song in results['tracks']:
            song['albumArtRef'] = song['albumArtRef'][0]['url']
            if 'artistId' in song:
                song['artistId'] = song['artistId'][0]
        return results

    def get_artist_details(self, id):
        results = self.api.get_artist_info(artist_id=id)
        for album in results['albums']:
            album['artistId'] = album['artistId'][0]

        for song in results['topTracks']:
            song['albumArtRef'] = song['albumArtRef'][0]['url']
            if 'artistId' in song:
                song['artistId'] = song['artistId'][0]
        return results


    def create_radio_station(self, name, id):
        if id[0] == 'A':
            station_id = self.api.create_station(name, artist_id=id)

        elif id[0] == 'B':
            station_id = self.api.create_station(name, album_id=id)

        else:
            station_id = self.api.create_station(name, track_id=id)

        return station_id

    def get_radio_stations(self):
        return self.api.get_all_stations()

    def flush(self):
        self.vlc.vlc_stop()
        self.queue = []

    def getSongInfo(self, id):
        song = self.api.get_track_info(id)
        song['albumArtRef'] = song['albumArtRef'][0]['url']
        if 'artistId' in song:
            song['artistId'] = song['artistId'][0]
        return song
Example #19
0
class GoogleMusic(object):
    def __init__(self):
        self.webclient = Webclient()
        self.mobileclient = Mobileclient()

    def is_authenticated(self):
        if self.webclient.is_authenticated():
            if self.mobileclient.is_authenticated():
                return True

        return False

    def login(self, username, password):
        if not self.is_authenticated():
            try:
                self.mobileclient.login(username, password)
                self.webclient.login(username, password)
            except:
                raise Exception('Couldn\'t log into Google Music')

    def search(self, query, kind):
        if self.is_authenticated():
            results = self.mobileclient.search_all_access(query)[kind + '_hits']

            return results

    def get_track(self, store_id):
        return self.mobileclient.get_track_info(store_id)

    def save_stream(self, track, destination):
        if self.is_authenticated():
            with open(destination, 'w+b') as stream_file:
                urls = self.webclient.get_stream_urls(track.get('storeId'))

                if len(urls) == 1:
                    stream_file.write(self.webclient.session._rsession.get(urls[0]).content)

                range_pairs = [[int(s) for s in val.split('-')]
                               for url in urls
                               for key, val in parse_qsl(urlparse(url)[4])
                               if key == 'range']

                for url, (start, end) in zip(urls, range_pairs):
                    stream_file.truncate(start)
                    stream_file.seek(0, 2)
                    audio = self.webclient.session._rsession.get(url).content
                    stream_file.write(audio)

            tag = easyid3.EasyID3()
            tag['title'] = track.get('title').__str__()
            tag['artist'] = track.get('artist').__str__()
            tag['album'] = track.get('album').__str__()
            tag['date'] = track.get('year').__str__()
            tag['discnumber'] = track.get('discNumber').__str__()
            tag['tracknumber'] = track.get('trackNumber').__str__()
            tag['performer'] = track.get('albumArtist').__str__()
            tag.save(destination)

            tag = mp3.MP3(destination)
            tag.tags.add(
                id3.APIC(3, 'image/jpeg', 3, 'Front cover', urllib.urlopen(track.get('albumArtRef')[0].get('url')).read())
            )
            tag.save()
Example #20
0
class GMusicClient(ContentConsumer):
    """Element in charge of interfacing with GMusicApi Client"""

    def __init__(self, data_cache):
        self.client = Mobileclient()
        self.data_cache = data_cache

    def login(self):
        """Use data/unlocked/credentials.json to log in"""
        mac = Mobileclient.FROM_MAC_ADDRESS
        try:
            credentials = json.load(open("data/unlocked/credentials.json", "r"))
            result = self.client.login(credentials["username"], credentials["password"], mac)
            if result == False:
                print("\n\033[93mLogin failed.")
                print("Please double check that data/unlocked/credentials.json has correct information.\033[m\n")
                os._exit(1)
        except:
            print("\n\033[93mdata/unlocked/credentials.json is not valid.")
            print("You may need to delete and regnerate the credentials file.\033[m\n")
            exit(1)

    def load_my_library(self):
        """Load user's songs, playlists, and stations"""
        track_load = threading.Thread(target=self.load_tracks)
        radio_load = threading.Thread(target=self.load_radios)
        playlist_load = threading.Thread(target=self.load_playlists)

        track_load.start()
        radio_load.start()
        playlist_load.start()

        track_load.join()
        radio_load.join()
        playlist_load.join()

    def load_playlists(self):
        playlists = self.client.get_all_user_playlist_contents()
        playlists.reverse()
        self.data_cache.playlists = playlists

    def load_tracks(self):
        self.data_cache.tracks = [t for t in self.client.get_all_songs() if "nid" in t]

    def scrape_song(self, track):
        return track

    def load_radios(self):
        radios = self.client.get_all_stations()
        radios.reverse()
        self.data_cache.radios = radios

    def get_radio_contents(self, radio_id):
        tracks = self.client.get_station_tracks(radio_id)
        return tracks

    def get_radio_list(self, name):
        return [r for r in self.data_cache.radios if name in r["name"]]

    def filter(self, element, field, filter_by):
        return [e for e in element if filter_by in e[field]]

    def get_playlist_list(self, name):
        return self.filter(self.data_cache.playlists, "name", name)

    def search_all_access(self, query):
        return self.client.search_all_access(query)

    def create_radio(self, seed_type, id, name):
        """Create a radio"""
        # This is a weird way to do this, but there's no other choice
        ids = {"track": None, "album": None, "artist": None}
        seed_id_name = self.get_type_name(seed_type)
        ids[seed_id_name] = id
        return self.client.create_station(
            name=name, track_id=ids["track"], album_id=ids["album"], artist_id=ids["artist"]
        )

    def search_items_all_access(self, type, query):
        """Searches Albums, Artists, and Songs; uses metaprogramming"""
        index_arguments = self.get_index_arguments(type)

        items = self.search_all_access(query)["{0}_hits".format(type[:-1])]
        return [self.format_item(item, type, index_arguments) for item in items]

    def get_sub_items(self, type_from, search_type, from_id):
        """Here type_from refers to artist or album we're indexing against"""
        args = self.get_index_arguments(search_type)

        if type_from == "playlist":
            return self.get_playlist_contents(from_id)

        else:
            # Get the appropriate search method and execute it
            search_method_name = "get_{0}_info".format(type_from)
            search_method = getattr(self.client, search_method_name)
            try:
                items = search_method(from_id, True)[args["type"] + "s"]  # True here includes subelements
            except:
                # User passed in a bad id or something
                return

        # Now return appropriately
        return [self.format_subitems(t, args) for t in items if args["id"] in t]

    def get_playlist_contents(self, from_id):
        """Playlist exclusive stuff"""
        shareToken = [t for t in self.data_cache.playlists if t["id"] == from_id][0]["shareToken"]

        contents = self.client.get_shared_playlist_contents(shareToken)
        return [self.format_playlist_contents(t) for t in contents if "track" in t]

    def get_suggested(self):
        """Returns a list of tracks that the user might be interested in"""
        items = sorted(self.client.get_promoted_songs(), key=lambda y: y["title"])
        return [self.format_suggested(t) for t in items if "storeId" in t]

    def get_information_about(self, from_type, from_id):
        """Gets specific information about an id (depending on the type)"""
        if "artist" in from_type.lower():
            return self.client.get_artist_info(from_id, include_albums=False)
        if "album" in from_type.lower():
            return self.client.get_album_info(from_id, include_tracks=False)
        return self.client.get_track_info(from_id)

    def get_stream_url(self, nid):
        return self.client.get_stream_url(nid)

    def lookup(self, nid):
        return self.client.get_track_info(nid)

    def add_track_to_library(self, nid):
        self.client.add_aa_track(nid)

    def add_to_playlist(self, playlist_id, nid):
        self.client.add_songs_to_playlist(playlist_id, nid)

        playlist_load = threading.Thread(target=self.load_playlists)
        playlist_load.daemon = True
        playlist_load.start()

    def format_suggested(self, t):
        return (t["title"], t["storeId"], "Play", t["album"])

    def format_playlist_contents(self, t):
        return (t["track"]["title"], t["trackId"], "Play", t["track"]["album"])

    def format_subitems(self, t, args):
        return (t[args["name"]], t[args["id"]], args["command"], t[args["alt"]])
from gmusicapi import Mobileclient
from grooveshark import Client
import sys

api = Mobileclient()
api.login(sys.argv[1], sys.argv[2])

groove_client = Client()

playlist = groove_client.playlist(sys.argv[3])

gp_songs = []

for song in playlist.songs:
    query = song.name + " " + song.artist.name
    gp_query_result = api.search_all_access(query, 1)
    try:
        track = gp_query_result['song_hits'][0]['track']
        print("Adding " + track['title'] + " by " + track['artist'])
        gp_songs.append(track['nid'])
    except IndexError as e:
        print("Coudn't find " + query)
        pass
    except:
        print(e)
        pass

gp_playlist = api.create_playlist(playlist.name)
api.add_songs_to_playlist(gp_playlist, gp_songs)
Example #22
0
class Playlist():
    api = None
    dryrun = False
    def __init__(self, credentials_path = DEFAULT_CREDS, user = None, dryrun = False, **kwargs):
        
        self.dryrun = dryrun

        self.api = Mobileclient()

        password = None
        if not user:
            user, password = self._loadCredentials(credentials_path)
        else:
            password = self._queryPass(user)

        logged_in = self.api.login(user, password)
        if not logged_in:
            print("Login failed, exiting")
            sys.exit(1)

    def _queryPass(self, user):
        return getpass("Provide password for user %s: " % user)

    def _loadCredentials(self, path = DEFAULT_CREDS):
        credentials = anymarkup.parse_file(path)

        return credentials["credentials"]["user"], credentials["credentials"]["password"]

    def _searchForSong(self, song_item):
        query = "%(artist)s %(title)s" % song_item
        result = self.api.search_all_access(query, 10)
        print("Query: %s, found %d hits" % (query, len(result["song_hits"])))
        first = None
        for item in result["song_hits"]:
            track = item["track"]
            if not first:
                first = track
            if (song_item["title"] in track["title"] or track["title"] in song_item["title"]) and (song_item["artist"] in track["albumArtist"] or\
                                                            song_item["artist"] in track["artist"] or\
                                                            track["artist"] in song_item["artist"] or\
                                                            track["albumArtist"] in song_item["artist"]\
                                                            ):
                return track

        if first:
            print("=> Given title and artist don't match, using first result: %s - %s" % (first["title"], first["artist"]))
            return first

        return None

    def _createPlaylist(self):
        name = "BBC Radio 1 Chart %s" % time.strftime("%Y-%m-%d")
        return self.api.create_playlist(name, public=True)

    def _addToPlaylist(self, playlist_id, song_item):
        self.api.add_songs_to_playlist(playlist_id, song_item["nid"])

    def create(self, songs_list):
        if not self.dryrun:
            playlist_id = self._createPlaylist()
        for song_item in songs_list:
            song = self._searchForSong(song_item)
            if not song:
                print("=> Couldn't find %s" % song_item)
                continue
            if not self.dryrun:
                self._addToPlaylist(playlist_id, song)
Example #23
0
    pw = getpass.getpass()
    if not client.login(args.username, pw, Mobileclient.FROM_MAC_ADDRESS):
        print("Authentication failed. Please check the provided credentials.")
    with open(args.source) as f:
        data = json.load(f)
    if args.dryrun:
        print("[/!\] We're currently running in dry-run mode")
    for playlist in data["playlists"]:
        if args.dryrun:
            print("Checking importability of %s" % playlist["title"])
        else:
            print("Importing %s" % playlist["title"])
        toimport = []
        for track in playlist["tracks"]:
            query = "%s %s" % (track["title"], track["artist"])
            results = client.search_all_access(query)
            match = None
            if args.verbose:
                print("Fetching matches for %s" % query)
            for hit_i, hit in enumerate(results["song_hits"]):
		trackDeets = hit["track"]["title"]
		match = hit["track"]["storeId"]
		print("Found match:\n%s" % trackDeets)
		break
            if match is not None:
                toimport.append(match)
            else:
                print("[!!!] No good match for %s" % query)
        if not args.dryrun and toimport:
            playlist_id = client.create_playlist(playlist["title"])
            client.add_songs_to_playlist(playlist_id, toimport)
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("\\", "/"))
Example #25
0
class GMusic(object):
    def __init__(self):
        self.authenticated = False
        self.all_access = False
        self.library_loaded = False
        self.all_songs = []
        self.letters = {}
        self.artists = {}
        self.albums = {}
        self.genres = {}
        self.tracks_by_letter = {}
        self.tracks_by_artist = {}
        self.tracks_by_album = {}
        self.tracks_by_genre = {}
        self._device = None
        self._webclient = Webclient(debug_logging=False)
        self._mobileclient = Mobileclient(debug_logging=False)
        self._playlists = []
        self._playlist_contents = []
        self._stations = []

    def _get_device_id(self):
        if self.authenticated:
            devices = self._webclient.get_registered_devices()
            for dev in devices:
                if dev['type'] == 'PHONE':
                    self._device = dev['id'][2:]
                    break
                elif dev['type'] == 'IOS':
                    self._device = dev['id']
                    break

    def _set_all_access(self):
        settings = self._webclient._make_call(webclient.GetSettings, '')
        self.all_access = True if 'isSubscription' in settings['settings'] and settings['settings']['isSubscription'] == True else False

    def _set_all_songs(self):
        if len(self.all_songs) == 0:
            try:
                self.all_songs = self._mobileclient.get_all_songs()
            except NotLoggedIn:
                if self.authenticate():
                    self.all_songs = self._mobileclient.get_all_songs()
                else:
                    return []

        else:
            return self.all_songs

    def authenticate(self, email, password):
        try:
            mcauthenticated = self._mobileclient.login(email, password)
        except AlreadyLoggedIn:
            mcauthenticated = True

        try:
            wcauthenticated = self._webclient.login(email, password)
        except AlreadyLoggedIn:
            wcauthenticated = True

        self.authenticated = mcauthenticated and wcauthenticated
        self._set_all_access()
        self._get_device_id()
        return self.authenticated

    def load_data(self):
        self._set_all_songs()
        for song in self.all_songs:
            thumb = None
            letter = song['title'][0]
            artist = song['artist']
            album = song['album']
            genre = song['genre'] if 'genre' in song else '(None)'

            if letter not in self.tracks_by_letter:
                self.tracks_by_letter[letter] = []
                self.letters[letter] = None

            if artist not in self.tracks_by_artist:
                self.tracks_by_artist[artist] = []
                self.artists[artist] = None

            if album not in self.tracks_by_album:
                self.tracks_by_album[album] = []
                self.albums[album] = None

            if genre not in self.tracks_by_genre:
                self.tracks_by_genre[genre] = []
                self.genres[genre] = None

            track = {'artist': artist, 'album': album}

            if 'title' in song:
                track['title'] = song['title']

            if 'album' in song:
                track['album'] = song['album']

            if 'artist' in song:
                track['artist'] = song['artist']

            if 'durationMillis' in song:
                track['durationMillis'] = song['durationMillis']

            if 'id' in song:
                track['id'] = song['id']

            if 'trackNumber' in song:
                track['trackType'] = song['trackNumber']

            if 'storeId' in song:
                track['storeId'] = song['storeId']

            if 'albumArtRef' in song:
                track['albumArtRef'] = song['albumArtRef']
                thumb = song['albumArtRef'][0]['url']
                self.letters[letter] = thumb
                self.artists[artist] = thumb
                self.albums[album] = thumb
                self.genres[genre] = thumb

            self.tracks_by_letter[letter].append({'track': track, 'thumb': thumb, 'id': song['id']})
            self.tracks_by_artist[artist].append({'track': track, 'thumb': thumb, 'id': song['id']})
            self.tracks_by_album[album].append({'track': track, 'thumb': thumb, 'id': song['id']})
            self.tracks_by_genre[genre].append({'track': track, 'thumb': thumb, 'id': song['id']})

        self.library_loaded = True

    def get_tracks_for_type(self, type, name):
        type = type.lower()
        if type == 'artists':
            return self.tracks_by_artist[name]
        elif type == 'albums':
            return self.tracks_by_album[name]
        elif type == 'genres':
            return self.tracks_by_genre[name]
        elif type == 'songs by letter':
            return self.tracks_by_letter[name]
        else:
            return {}

    def get_song(self, id):
        return [x for x in self.all_songs if x['id'] == id][0]

    def get_all_playlists(self):
        if len(self._playlists) == 0:
            try:
                self._playlists = self._mobileclient.get_all_playlists()
            except NotLoggedIn:
                if self.authenticate():
                    self._playlists = self._mobileclient.get_all_playlists()
                else:
                    return []

        return self._playlists

    def get_all_user_playlist_contents(self, id):
        tracks = []
        if len(self._playlist_contents) == 0:
            try:
                self._playlist_contents = self._mobileclient.get_all_user_playlist_contents()
            except NotLoggedIn:
                if self.authenticate():
                    self._playlist_contents = self._mobileclient.get_all_user_playlist_contents()
                else:
                    return []

        for playlist in self._playlist_contents:
            if id == playlist['id']:
                tracks = playlist['tracks']
                break

        return tracks

    def get_shared_playlist_contents(self, token):
        playlist = []
        try:
            playlist = self._mobileclient.get_shared_playlist_contents(token)
        except NotLoggedIn:
            if self.authenticate():
                playlist = self._mobileclient.get_shared_playlist_contents(token)
            else:
                return []

        return playlist

    def get_all_stations(self):
        if len(self._stations) == 0:
            try:
                self._stations = self._mobileclient.get_all_stations()
            except NotLoggedIn:
                if self.authenticate():
                    self._stations = self._mobileclient.get_all_stations()
                else:
                    return []

        return self._stations

    def get_station_tracks(self, id, num_tracks=200):
        tracks = []
        try:
            tracks = self._mobileclient.get_station_tracks(id, num_tracks)
        except NotLoggedIn:
            if self.authenticate():
                tracks = self._mobileclient.get_station_tracks(id, num_tracks)
            else:
                return []

        return tracks

    def get_genres(self):
        genres = []
        try:
            genres = self._mobileclient.get_genres()
        except NotLoggedIn:
            if self.authenticate():
                genres = self._mobileclient.get_genres()
            else:
                return []

        return genres

    def create_station(self, name, id):
        station = None
        try:
            station = self._mobileclient.create_station(name=name, genre_id=id)
        except NotLoggedIn:
            if self.authenticate():
                station = self._mobileclient.create_station(name=name, genre_id=id)
            else:
                return []

        return station

    def search_all_access(self, query, max_results=50):
        results = None
        try:
            results = self._mobileclient.search_all_access(query, max_results)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.search_all_access(query, max_results)
            else:
                return []

        return results

    def get_artist_info(self, id, include_albums=True, max_top_tracks=5, max_rel_artist=5):
        results = None
        try:
            results = self._mobileclient.get_artist_info(id, include_albums=include_albums, max_top_tracks=max_top_tracks, max_rel_artist=max_rel_artist)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_artist_info(id, include_albums=include_albums, max_top_tracks=max_top_tracks, max_rel_artist=max_rel_artist)
            else:
                return []

        return results

    def get_album_info(self, id, include_tracks=True):
        results = None
        try:
            results = self._mobileclient.get_album_info(id, include_tracks=include_tracks)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_album_info(id, include_tracks=include_tracks)
            else:
                return []

        return results

    def add_aa_track(self, id):
        track = None
        try:
            track = self._mobileclient.add_aa_track(id)
        except NotLoggedIn:
            if self.authenticate():
                track = self._mobileclient.add_aa_track(id)
            else:
                return None

        return track

    def add_songs_to_playlist(self, playlist_id, song_ids):
        tracks = None
        try:
            tracks = self._mobileclient.add_songs_to_playlist(playlist_id, song_ids)
        except NotLoggedIn:
            if self.authenticate():
                tracks = self._mobileclient.add_songs_to_playlist(playlist_id, song_ids)
            else:
                return None

        return tracks

    def get_stream_url(self, id):
        try:
            stream_url = self._mobileclient.get_stream_url(id, self._device)
        except NotLoggedIn:
            if self.authenticate():
                stream_url = self._mobileclient.get_stream_url(id, self._device)
            else:
                return ''
        except CallFailure:
            raise CallFailure('Could not play song with id: ' + id, 'get_stream_url')

        return stream_url

    def reset_library(self):
        self.library_loaded = False
        self.all_songs[:] = []
        self._playlists[:] = []
        self._playlist_contents[:] = []
        self._stations[:] = []
        self.letters.clear()
        self.artists.clear()
        self.albums.clear()
        self.genres.clear()
        self.tracks_by_letter.clear()
        self.tracks_by_artist.clear()
        self.tracks_by_album.clear()
        self.tracks_by_genre.clear()
class tizgmusicproxy(object):
    """A class for logging into a Google Play Music account and retrieving song
    URLs.

    """

    all_songs_album_title = "All Songs"
    thumbs_up_playlist_name = "Thumbs Up"

    def __init__(self, email, password, device_id):
        self.__gmusic = Mobileclient()
        self.__email = email
        self.__device_id = device_id
        self.logged_in = False
        self.queue = list()
        self.queue_index = -1
        self.play_queue_order = list()
        self.play_modes = TizEnumeration(["NORMAL", "SHUFFLE"])
        self.current_play_mode = self.play_modes.NORMAL
        self.now_playing_song = None

        userdir = os.path.expanduser('~')
        tizconfig = os.path.join(userdir, ".config/tizonia/." + email + ".auth_token")
        auth_token = ""
        if os.path.isfile(tizconfig):
            with open(tizconfig, "r") as f:
                auth_token = pickle.load(f)
                if auth_token:
                    # 'Keep track of the auth token' workaround. See:
                    # https://github.com/diraimondo/gmusicproxy/issues/34#issuecomment-147359198
                    print_msg("[Google Play Music] [Authenticating] : " \
                              "'with cached auth token'")
                    self.__gmusic.android_id = device_id
                    self.__gmusic.session._authtoken = auth_token
                    self.__gmusic.session.is_authenticated = True
                    try:
                        self.__gmusic.get_registered_devices()
                    except CallFailure:
                        # The token has expired. Reset the client object
                        print_wrn("[Google Play Music] [Authenticating] : " \
                                  "'auth token expired'")
                        self.__gmusic = Mobileclient()
                        auth_token = ""

        if not auth_token:
            attempts = 0
            print_nfo("[Google Play Music] [Authenticating] : " \
                      "'with user credentials'")
            while not self.logged_in and attempts < 3:
                self.logged_in = self.__gmusic.login(email, password, device_id)
                attempts += 1

            with open(tizconfig, "a+") as f:
                f.truncate()
                pickle.dump(self.__gmusic.session._authtoken, f)

        self.library = CaseInsensitiveDict()
        self.song_map = CaseInsensitiveDict()
        self.playlists = CaseInsensitiveDict()
        self.stations = CaseInsensitiveDict()

    def logout(self):
        """ Reset the session to an unauthenticated, default state.

        """
        self.__gmusic.logout()

    def set_play_mode(self, mode):
        """ Set the playback mode.

        :param mode: curren tvalid values are "NORMAL" and "SHUFFLE"

        """
        self.current_play_mode = getattr(self.play_modes, mode)
        self.__update_play_queue_order()

    def current_song_title_and_artist(self):
        """ Retrieve the current track's title and artist name.

        """
        logging.info("current_song_title_and_artist")
        song = self.now_playing_song
        if song is not None:
            title = to_ascii(self.now_playing_song.get('title'))
            artist = to_ascii(self.now_playing_song.get('artist'))
            logging.info("Now playing {0} by {1}".format(title, artist))
            return artist, title
        else:
            return '', ''

    def current_song_album_and_duration(self):
        """ Retrieve the current track's album and duration.

        """
        logging.info("current_song_album_and_duration")
        song = self.now_playing_song
        if song is not None:
            album = to_ascii(self.now_playing_song.get('album'))
            duration = to_ascii \
                       (self.now_playing_song.get('durationMillis'))
            logging.info("album {0} duration {1}".format(album, duration))
            return album, int(duration)
        else:
            return '', 0

    def current_track_and_album_total(self):
        """Return the current track number and the total number of tracks in the
        album, if known.

        """
        logging.info("current_track_and_album_total")
        song = self.now_playing_song
        track = 0
        total = 0
        if song is not None:
            try:
                track = self.now_playing_song['trackNumber']
                total = self.now_playing_song['totalTrackCount']
                logging.info("track number {0} total tracks {1}"
                             .format(track, total))
            except KeyError:
                logging.info("trackNumber or totalTrackCount : not found")
        else:
            logging.info("current_song_track_number_"
                         "and_total_tracks : not found")
        return track, total

    def current_song_year(self):
        """ Return the current track's year of publication.

        """
        logging.info("current_song_year")
        song = self.now_playing_song
        year = 0
        if song is not None:
            try:
                year = song['year']
                logging.info("track year {0}".format(year))
            except KeyError:
                logging.info("year : not found")
        else:
            logging.info("current_song_year : not found")
        return year

    def clear_queue(self):
        """ Clears the playback queue.

        """
        self.queue = list()
        self.queue_index = -1

    def enqueue_artist(self, arg):
        """ Search the user's library for tracks from the given artist and adds
        them to the playback queue.

        :param arg: an artist
        """
        try:
            self.__update_local_library()
            artist = None
            if not arg in self.library.keys():
                for name, art in self.library.iteritems():
                    if arg.lower() in name.lower():
                        artist = art
                        print_wrn("[Google Play Music] '{0}' not found. " \
                                  "Playing '{1}' instead." \
                                  .format(arg, name))
                        break
                if not artist:
                    raise KeyError("Artist not found : {0}".format(arg))
            else:
                artist = self.library[arg]
            tracks_added = 0
            for album in artist:
                tracks_added += self.__enqueue_tracks(artist[album])
            logging.info("Added {0} tracks by {1} to queue" \
                         .format(tracks_added, arg))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Artist not found : {0}".format(arg))

    def enqueue_album(self, arg):
        """ Search the user's library for albums with a given name and adds
        them to the playback queue.

        """
        try:
            self.__update_local_library()
            album = None
            artist = None
            tentative_album = None
            tentative_artist = None
            for library_artist in self.library:
                for artist_album in self.library[library_artist]:
                    print_nfo("[Google Play Music] [Album] '{0}'." \
                              .format(to_ascii(artist_album)))
                    if not album:
                        if arg.lower() == artist_album.lower():
                            album = artist_album
                            artist = library_artist
                            break
                    if not tentative_album:
                        if arg.lower() in artist_album.lower():
                            tentative_album = artist_album
                            tentative_artist = library_artist
                if album:
                    break

            if not album:
                album = tentative_album
                artist = tentative_artist
                print_wrn("[Google Play Music] '{0}' not found. " \
                          "Playing '{1}' instead." \
                          .format(arg, album))
            if not album:
                raise KeyError("Album not found : {0}".format(arg))
            tracks_added = self.__enqueue_tracks(self.library[artist][album])
            logging.info("Added {0} tracks from {1} by " \
                         "{2} to queue" \
                         .format(tracks_added, album, artist))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Album not found : {0}".format(arg))

    def enqueue_playlist(self, arg):
        """Search the user's library for playlists with a given name
        and adds the tracks of the first match to the playback queue.

        Requires Unlimited subscription.

        """
        try:
            self.__update_local_library()
            self.__update_playlists()
            self.__update_playlists_unlimited()
            playlist = None
            for name, plist in self.playlists.items():
                print_nfo("[Google Play Music] [Playlist] '{0}'." \
                          .format(to_ascii(name)))
            if not arg in self.playlists.keys():
                for name, plist in self.playlists.iteritems():
                    if arg.lower() in name.lower():
                        playlist = plist
                        print_wrn("[Google Play Music] '{0}' not found. " \
                                  "Playing '{1}' instead." \
                                  .format(arg, to_ascii(name)))
                        break
                if not playlist:
                    raise KeyError
            else:
                playlist = self.playlists[arg]

            tracks_added = self.__enqueue_tracks(playlist)
            logging.info("Added {0} tracks from {1} to queue" \
                         .format(tracks_added, arg))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Playlist not found : {0}".format(arg))

    def enqueue_station_unlimited(self, arg):
        """Search the user's library for a station with a given name
        and adds its tracks to the playback queue.

        Requires Unlimited subscription.

        """
        try:
            # First try to find a suitable station in the user's library
            self.__enqueue_user_station_unlimited(arg)

            if not len(self.queue):
                # If no suitable station is found in the user's library, then
                # search google play unlimited for a potential match.
                self.__enqueue_station_unlimited(arg)

            if not len(self.queue):
                raise KeyError

        except KeyError:
            raise KeyError("Station not found : {0}".format(arg))

    def enqueue_genre_unlimited(self, arg):
        """Search Unlimited for a genre with a given name and adds its
        tracks to the playback queue.

        Requires Unlimited subscription.

        """
        print_msg("[Google Play Music] [Retrieving genres] : '{0}'. " \
                  .format(self.__email))

        try:
            all_genres = list()
            root_genres = self.__gmusic.get_genres()
            second_tier_genres = list()
            for root_genre in root_genres:
                second_tier_genres += self.__gmusic.get_genres(root_genre['id'])
            all_genres += root_genres
            all_genres += second_tier_genres
            for genre in all_genres:
                print_nfo("[Google Play Music] [Genre] '{0}'." \
                          .format(to_ascii(genre['name'])))
            genre = dict()
            if not arg in all_genres:
                genre = next((g for g in all_genres \
                              if arg.lower() in to_ascii(g['name']).lower()), \
                             None)
                if genre:
                    print_wrn("[Google Play Music] '{0}' not found. " \
                              "Playing '{1}' instead." \
                              .format(arg, to_ascii(genre['name'])))
                else:
                    raise KeyError("Genre not found : {0}".format(arg))
            genre_name = genre['name']
            genre_id = genre['id']
            station_id = self.__gmusic.create_station(genre_name, \
                                                   None, None, None, genre_id)
            num_tracks = 200
            tracks = self.__gmusic.get_station_tracks(station_id, num_tracks)
            tracks_added = self.__enqueue_tracks(tracks)
            logging.info("Added {0} tracks from {1} to queue" \
                         .format(tracks_added, genre_name))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Genre not found : {0}".format(arg))
        except CallFailure:
            raise RuntimeError("Operation requires an Unlimited subscription.")

    def enqueue_artist_unlimited(self, arg):
        """Search Unlimited for an artist and adds the artist's 200 top tracks to the
        playback queue.

        Requires Unlimited subscription.

        """
        try:
            artist_hits = self.__gmusic.search_all_access(arg)['artist_hits']
            artist = next((hit for hit in artist_hits \
                           if 'best_result' in hit.keys()), None)
            if not artist and len(artist_hits):
                for hit in artist_hits:
                    print_nfo("[Google Play Music] [Artist] '{0}'." \
                              .format((hit['artist']['name']).encode('utf-8')))
                artist = artist_hits[0]
                print_wrn("[Google Play Music] Playing '{0}'." \
                          .format((artist['artist']['name']).encode('utf-8')))

            include_albums = False
            max_top_tracks = 200
            max_rel_artist = 0
            artist_tracks = dict()
            if artist:
                artist_tracks = self.__gmusic.get_artist_info \
                                (artist['artist']['artistId'],
                                 include_albums, max_top_tracks,
                                 max_rel_artist)['topTracks']
            if not artist_tracks:
                raise KeyError

            tracks_added = self.__enqueue_tracks(artist_tracks)
            logging.info("Added {0} tracks from {1} to queue" \
                         .format(tracks_added, arg))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Artist not found : {0}".format(arg))
        except CallFailure:
            raise RuntimeError("Operation requires an Unlimited subscription.")

    def enqueue_album_unlimited(self, arg):
        """Search Unlimited for an album and adds its tracks to the
        playback queue.

        Requires Unlimited subscription.

        """
        try:
            album_hits = self.__gmusic.search_all_access(arg)['album_hits']
            album = next((hit for hit in album_hits \
                          if 'best_result' in hit.keys()), None)

            if not album and len(album_hits):
                for hit in album_hits:
                    print_nfo("[Google Play Music] [Album] '{0}'." \
                              .format((hit['album']['name']).encode('utf-8')))
                album = album_hits[0]
                print_wrn("[Google Play Music] Playing '{0}'." \
                          .format((album['album']['name']).encode('utf-8')))

            album_tracks = dict()
            if album:
                album_tracks = self.__gmusic.get_album_info \
                               (album['album']['albumId'])['tracks']
            if not album_tracks:
                raise KeyError

            tracks_added = self.__enqueue_tracks(album_tracks)
            logging.info("Added {0} tracks from {1} to queue" \
                         .format(tracks_added, arg))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Album not found : {0}".format(arg))
        except CallFailure:
            raise RuntimeError("Operation requires an Unlimited subscription.")

    def enqueue_tracks_unlimited(self, arg):
        """ Search Unlimited for a track name and adds all the matching tracks
        to the playback queue.

        Requires Unlimited subscription.

        """
        print_msg("[Google Play Music] [Retrieving library] : '{0}'. " \
                  .format(self.__email))

        try:
            track_hits = self.__gmusic.search_all_access(arg)['song_hits']
            tracks = list()
            for hit in track_hits:
                tracks.append(hit['track'])
            tracks_added = self.__enqueue_tracks(tracks)
            logging.info("Added {0} tracks from {1} to queue" \
                         .format(tracks_added, arg))
            self.__update_play_queue_order()
        except KeyError:
            raise KeyError("Playlist not found : {0}".format(arg))
        except CallFailure:
            raise RuntimeError("Operation requires an Unlimited subscription.")

    def enqueue_promoted_tracks_unlimited(self):
        """ Retrieve the url of the next track in the playback queue.

        """
        try:
            tracks = self.__gmusic.get_promoted_songs()
            count = 0
            for track in tracks:
                store_track = self.__gmusic.get_track_info(track['storeId'])
                if not u'id' in store_track.keys():
                    store_track[u'id'] = store_track['nid']
                self.queue.append(store_track)
                count += 1
            if count == 0:
                print_wrn("[Google Play Music] Operation requires " \
                          "an Unlimited subscription.")
            logging.info("Added {0} Unlimited promoted tracks to queue" \
                         .format(count))
            self.__update_play_queue_order()
        except CallFailure:
            raise RuntimeError("Operation requires an Unlimited subscription.")

    def next_url(self):
        """ Retrieve the url of the next track in the playback queue.

        """
        if len(self.queue):
            self.queue_index += 1
            if (self.queue_index < len(self.queue)) \
               and (self.queue_index >= 0):
                next_song = self.queue[self.play_queue_order[self.queue_index]]
                return self.__retrieve_track_url(next_song)
            else:
                self.queue_index = -1
                return self.next_url()
        else:
            return ''

    def prev_url(self):
        """ Retrieve the url of the previous track in the playback queue.

        """
        if len(self.queue):
            self.queue_index -= 1
            if (self.queue_index < len(self.queue)) \
               and (self.queue_index >= 0):
                prev_song = self.queue[self.play_queue_order[self.queue_index]]
                return self.__retrieve_track_url(prev_song)
            else:
                self.queue_index = len(self.queue)
                return self.prev_url()
        else:
            return ''

    def __update_play_queue_order(self):
        """ Update the queue playback order.

        A sequential order is applied if the current play mode is "NORMAL" or a
        random order if current play mode is "SHUFFLE"

        """
        total_tracks = len(self.queue)
        if total_tracks:
            if not len(self.play_queue_order):
                # Create a sequential play order, if empty
                self.play_queue_order = range(total_tracks)
            if self.current_play_mode == self.play_modes.SHUFFLE:
                random.shuffle(self.play_queue_order)
            print_nfo("[Google Play Music] [Tracks in queue] '{0}'." \
                      .format(total_tracks))

    def __retrieve_track_url(self, song):
        """ Retrieve a song url

        """
        logging.info("__retrieve_track_url : {0}".format(song['id']))
        song_url = self.__gmusic.get_stream_url(song['id'], self.__device_id)
        try:
            self.now_playing_song = song
            return song_url
        except AttributeError:
            logging.info("Could not retrieve the song url!")
            raise

    def __update_local_library(self):
        """ Retrieve the songs and albums from the user's library

        """
        print_msg("[Google Play Music] [Retrieving library] : '{0}'. " \
                  .format(self.__email))

        songs = self.__gmusic.get_all_songs()
        self.playlists[self.thumbs_up_playlist_name] = list()

        # Retrieve the user's song library
        for song in songs:
            if "rating" in song and song['rating'] == "5":
                self.playlists[self.thumbs_up_playlist_name].append(song)

            song_id = song['id']
            song_artist = song['artist']
            song_album = song['album']

            self.song_map[song_id] = song

            if song_artist == "":
                song_artist = "Unknown Artist"

            if song_album == "":
                song_album = "Unknown Album"

            if not song_artist in self.library:
                self.library[song_artist] = CaseInsensitiveDict()
                self.library[song_artist][self.all_songs_album_title] = list()

            if not song_album in self.library[song_artist]:
                self.library[song_artist][song_album] = list()

            self.library[song_artist][song_album].append(song)
            self.library[song_artist][self.all_songs_album_title].append(song)

        # Sort albums by track number
        for artist in self.library.keys():
            logging.info("Artist : {0}".format(to_ascii(artist)))
            for album in self.library[artist].keys():
                logging.info("   Album : {0}".format(to_ascii(album)))
                if album == self.all_songs_album_title:
                    sorted_album = sorted(self.library[artist][album],
                                          key=lambda k: k['title'])
                else:
                    sorted_album = sorted(self.library[artist][album],
                                          key=lambda k: k.get('trackNumber',
                                                              0))
                self.library[artist][album] = sorted_album

    def __update_stations_unlimited(self):
        """ Retrieve stations (Unlimited)

        """
        self.stations.clear()
        stations = self.__gmusic.get_all_stations()
        self.stations[u"I'm Feeling Lucky"] = 'IFL'
        for station in stations:
            station_name = station['name']
            logging.info("station name : {0}" \
                         .format(to_ascii(station_name)))
            self.stations[station_name] = station['id']

    def __enqueue_user_station_unlimited(self, arg):
        """ Enqueue a user station (Unlimited)

        """
        print_msg("[Google Play Music] [Station search "\
                  "in user's library] : '{0}'. " \
                  .format(self.__email))
        self.__update_stations_unlimited()
        station_name = arg
        station_id = None
        for name, st_id in self.stations.iteritems():
            print_nfo("[Google Play Music] [Station] '{0}'." \
                      .format(to_ascii(name)))
        if not arg in self.stations.keys():
            for name, st_id in self.stations.iteritems():
                if arg.lower() in name.lower():
                    station_id = st_id
                    station_name = name
                    break
        else:
            station_id = self.stations[arg]

        num_tracks = 200
        tracks = dict()
        if station_id:
            try:
                tracks = self.__gmusic.get_station_tracks(station_id, \
                                                          num_tracks)
            except KeyError:
                raise RuntimeError("Operation requires an "
                                   "Unlimited subscription.")
            tracks_added = self.__enqueue_tracks(tracks)
            if tracks_added:
                if arg != station_name:
                    print_wrn("[Google Play Music] '{0}' not found. " \
                              "Playing '{1}' instead." \
                              .format(arg.encode('utf-8'), name.encode('utf-8')))
                logging.info("Added {0} tracks from {1} to queue" \
                             .format(tracks_added, arg))
                self.__update_play_queue_order()
            else:
                print_wrn("[Google Play Music] '{0}' has no tracks. " \
                          .format(station_name))

        if not len(self.queue):
            print_wrn("[Google Play Music] '{0}' unable to find a " \
                      "suitable station in user's library. " \
                      .format(arg))

    def __enqueue_station_unlimited(self, arg):
        """Search for a station and enqueue all of its tracks (Unlimited)

        """
        print_msg("[Google Play Music] [Station search in "\
                  "Google Play Music Unlimited] : '{0}'. " \
                  .format(arg))
        try:
            station_name = arg
            station_id = None
            station_hits = self.__gmusic.search_all_access(arg)['station_hits']
            station = next((hit for hit in station_hits \
                            if 'best_result' in hit.keys()), None)

            if not station and len(station_hits):
                for hit in station_hits:
                    print_nfo("[Google Play Music] [Station] '{0}'." \
                              .format((hit['station']['name']).encode('utf-8')))
                    if not station:
                        if arg.lower() in \
                           to_ascii(hit['station']['name']).lower():
                            station = hit
                if not station:
                    # Play some random station from the search results
                    random.seed()
                    station_index = random.randint(0, len(station_hits))
                    station = station_hits[station_index]

            if station:
                station = station['station']
                station_name = station['name']
                seed = station['seed']
                seed_type = seed['seedType']
                track_id = seed['trackId'] if seed_type == u'2' else None
                artist_id = seed['artistId'] if seed_type == u'3' else None
                album_id = seed['albumId'] if seed_type == u'4' else None
                genre_id = seed['genreId'] if seed_type == u'5' else None
                num_tracks = 200
                tracks = dict()
                try:
                    station_id \
                        = self.__gmusic.create_station(station_name, \
                                                       track_id, \
                                                       artist_id, \
                                                       album_id, \
                                                       genre_id)
                    tracks \
                        = self.__gmusic.get_station_tracks(station_id, \
                                                           num_tracks)
                except KeyError:
                    raise RuntimeError("Operation requires an "
                                       "Unlimited subscription.")
                tracks_added = self.__enqueue_tracks(tracks)
                if tracks_added:
                    print_wrn("[Google Play Music] [Station] : '{0}'." \
                              .format(station_name.encode('utf-8')))
                    logging.info("Added {0} tracks from {1} to queue" \
                                 .format(tracks_added, arg))
                    self.__update_play_queue_order()

        except KeyError:
            raise KeyError("Station not found : {0}".format(arg))

    def __enqueue_tracks(self, tracks):
        """ Add tracks to the playback queue

        """
        count = 0
        for track in tracks:
            if not u'id' in track.keys():
                track[u'id'] = track['nid']
            self.queue.append(track)
            count += 1
        return count

    def __update_playlists(self):
        """ Retrieve the user's playlists

        """
        plists = self.__gmusic.get_all_user_playlist_contents()
        for plist in plists:
            plist_name = plist['name']
            logging.info("playlist name : {0}".format(to_ascii(plist_name)))
            tracks = plist['tracks']
            tracks.sort(key=itemgetter('creationTimestamp'))
            self.playlists[plist_name] = list()
            for track in tracks:
                try:
                    song = self.song_map[track['trackId']]
                    self.playlists[plist_name].append(song)
                except IndexError:
                    pass

    def __update_playlists_unlimited(self):
        """ Retrieve shared playlists (Unlimited)

        """
        plists_subscribed_to = [p for p in self.__gmusic.get_all_playlists() \
                                if p.get('type') == 'SHARED']
        for plist in plists_subscribed_to:
            share_tok = plist['shareToken']
            playlist_items \
                = self.__gmusic.get_shared_playlist_contents(share_tok)
            plist_name = plist['name']
            logging.info("shared playlist name : {0}" \
                         .format(to_ascii(plist_name)))
            self.playlists[plist_name] = list()
            for item in playlist_items:
                try:
                    song = item['track']
                    song['id'] = item['trackId']
                    self.playlists[plist_name].append(song)
                except IndexError:
                    pass
Example #27
0
from gmusicapi import Mobileclient
from pprint import pprint
api = Mobileclient()

api.login('', '', Mobileclient.FROM_MAC_ADDRESS)

playlist_name = 'ToListenTo'
answer = api.search_all_access('', max_results=1)

sweet_track_ids = []
artist_id = answer['artist_hits'][0]['artist']['artistId']
response = api.get_artist_info(artist_id,
                               include_albums=False,
                               max_top_tracks=3,
                               max_rel_artist=0)
for song in response['topTracks']:
    sweet_track_ids.append(song['nid'])
    playlists = api.get_all_playlists()
playlist_id = None
for playlist in playlists:
    if playlist_name in playlist['name']:
        playlist_id = playlist['id']
    if not playlist_id:
        playlist_id = api.create_playlist(playlist_name)
api.add_songs_to_playlist(playlist_id, sweet_track_ids)
Example #28
0
class GMusic(object):
    def __init__(self):
        self.authenticated = False
        self.all_access = False
        self.library_loaded = False
        self.all_songs = []
        self.letters = {}
        self.artists = {}
        self.albums = {}
        self.genres = {}
        self.tracks_by_letter = {}
        self.tracks_by_artist = {}
        self.tracks_by_album = {}
        self.tracks_by_genre = {}
        self._device = None
        self._webclient = Webclient(debug_logging=False)
        self._mobileclient = Mobileclient(debug_logging=False)
        self._playlists = []
        self._playlist_contents = []
        self._stations = []

    def _get_device_id(self):
        if self.authenticated:
            devices = self._webclient.get_registered_devices()
            for dev in devices:
                if dev['type'] == 'PHONE':
                    self._device = dev['id'][2:]
                    break
                elif dev['type'] == 'IOS':
                    self._device = dev['id']
                    break

    def _set_all_access(self):
        settings = self._webclient._make_call(webclient.GetSettings, '')
        self.all_access = True if 'isSubscription' in settings[
            'settings'] and settings['settings'][
                'isSubscription'] == True else False

    def _set_all_songs(self):
        if len(self.all_songs) == 0:
            try:
                self.all_songs = self._mobileclient.get_all_songs()
            except NotLoggedIn:
                if self.authenticate():
                    self.all_songs = self._mobileclient.get_all_songs()
                else:
                    return []

        else:
            return self.all_songs

    def authenticate(self, email, password):
        try:
            mcauthenticated = self._mobileclient.login(email, password)
        except AlreadyLoggedIn:
            mcauthenticated = True

        try:
            wcauthenticated = self._webclient.login(email, password)
        except AlreadyLoggedIn:
            wcauthenticated = True

        self.authenticated = mcauthenticated and wcauthenticated
        self._set_all_access()
        self._get_device_id()
        return self.authenticated

    def load_data(self):
        self._set_all_songs()
        for song in self.all_songs:
            thumb = None
            letter = song['title'][0]
            artist = song['artist']
            album = song['album']
            genre = song['genre'] if 'genre' in song else '(None)'

            if letter not in self.tracks_by_letter:
                self.tracks_by_letter[letter] = []
                self.letters[letter] = None

            if artist not in self.tracks_by_artist:
                self.tracks_by_artist[artist] = []
                self.artists[artist] = None

            if album not in self.tracks_by_album:
                self.tracks_by_album[album] = []
                self.albums[album] = None

            if genre not in self.tracks_by_genre:
                self.tracks_by_genre[genre] = []
                self.genres[genre] = None

            track = {'artist': artist, 'album': album}

            if 'title' in song:
                track['title'] = song['title']

            if 'album' in song:
                track['album'] = song['album']

            if 'artist' in song:
                track['artist'] = song['artist']

            if 'durationMillis' in song:
                track['durationMillis'] = song['durationMillis']

            if 'id' in song:
                track['id'] = song['id']

            if 'trackNumber' in song:
                track['trackType'] = song['trackNumber']

            if 'storeId' in song:
                track['storeId'] = song['storeId']

            if 'albumArtRef' in song:
                track['albumArtRef'] = song['albumArtRef']
                thumb = song['albumArtRef'][0]['url']
                self.letters[letter] = thumb
                self.artists[artist] = thumb
                self.albums[album] = thumb
                self.genres[genre] = thumb

            self.tracks_by_letter[letter].append({
                'track': track,
                'thumb': thumb,
                'id': song['id']
            })
            self.tracks_by_artist[artist].append({
                'track': track,
                'thumb': thumb,
                'id': song['id']
            })
            self.tracks_by_album[album].append({
                'track': track,
                'thumb': thumb,
                'id': song['id']
            })
            self.tracks_by_genre[genre].append({
                'track': track,
                'thumb': thumb,
                'id': song['id']
            })

        self.library_loaded = True

    def get_tracks_for_type(self, type, name):
        type = type.lower()
        if type == 'artists':
            return self.tracks_by_artist[name]
        elif type == 'albums':
            return self.tracks_by_album[name]
        elif type == 'genres':
            return self.tracks_by_genre[name]
        elif type == 'songs by letter':
            return self.tracks_by_letter[name]
        else:
            return {}

    def get_song(self, id):
        return [x for x in self.all_songs if x['id'] == id][0]

    def get_all_playlists(self):
        if len(self._playlists) == 0:
            try:
                self._playlists = self._mobileclient.get_all_playlists()
            except NotLoggedIn:
                if self.authenticate():
                    self._playlists = self._mobileclient.get_all_playlists()
                else:
                    return []

        return self._playlists

    def get_all_user_playlist_contents(self, id):
        tracks = []
        if len(self._playlist_contents) == 0:
            try:
                self._playlist_contents = self._mobileclient.get_all_user_playlist_contents(
                )
            except NotLoggedIn:
                if self.authenticate():
                    self._playlist_contents = self._mobileclient.get_all_user_playlist_contents(
                    )
                else:
                    return []

        for playlist in self._playlist_contents:
            if id == playlist['id']:
                tracks = playlist['tracks']
                break

        return tracks

    def get_shared_playlist_contents(self, token):
        playlist = []
        try:
            playlist = self._mobileclient.get_shared_playlist_contents(token)
        except NotLoggedIn:
            if self.authenticate():
                playlist = self._mobileclient.get_shared_playlist_contents(
                    token)
            else:
                return []

        return playlist

    def get_all_stations(self):
        if len(self._stations) == 0:
            try:
                self._stations = self._mobileclient.get_all_stations()
            except NotLoggedIn:
                if self.authenticate():
                    self._stations = self._mobileclient.get_all_stations()
                else:
                    return []

        return self._stations

    def get_station_tracks(self, id, num_tracks=200):
        tracks = []
        try:
            tracks = self._mobileclient.get_station_tracks(id, num_tracks)
        except NotLoggedIn:
            if self.authenticate():
                tracks = self._mobileclient.get_station_tracks(id, num_tracks)
            else:
                return []

        return tracks

    def get_genres(self):
        genres = []
        try:
            genres = self._mobileclient.get_genres()
        except NotLoggedIn:
            if self.authenticate():
                genres = self._mobileclient.get_genres()
            else:
                return []

        return genres

    def create_station(self, name, id):
        station = None
        try:
            station = self._mobileclient.create_station(name=name, genre_id=id)
        except NotLoggedIn:
            if self.authenticate():
                station = self._mobileclient.create_station(name=name,
                                                            genre_id=id)
            else:
                return []

        return station

    def search_all_access(self, query, max_results=50):
        results = None
        try:
            results = self._mobileclient.search_all_access(query, max_results)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.search_all_access(
                    query, max_results)
            else:
                return []

        return results

    def get_artist_info(self,
                        id,
                        include_albums=True,
                        max_top_tracks=5,
                        max_rel_artist=5):
        results = None
        try:
            results = self._mobileclient.get_artist_info(
                id,
                include_albums=include_albums,
                max_top_tracks=max_top_tracks,
                max_rel_artist=max_rel_artist)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_artist_info(
                    id,
                    include_albums=include_albums,
                    max_top_tracks=max_top_tracks,
                    max_rel_artist=max_rel_artist)
            else:
                return []

        return results

    def get_album_info(self, id, include_tracks=True):
        results = None
        try:
            results = self._mobileclient.get_album_info(
                id, include_tracks=include_tracks)
        except NotLoggedIn:
            if self.authenticate():
                results = self._mobileclient.get_album_info(
                    id, include_tracks=include_tracks)
            else:
                return []

        return results

    def add_aa_track(self, id):
        track = None
        try:
            track = self._mobileclient.add_aa_track(id)
        except NotLoggedIn:
            if self.authenticate():
                track = self._mobileclient.add_aa_track(id)
            else:
                return None

        return track

    def add_songs_to_playlist(self, playlist_id, song_ids):
        tracks = None
        try:
            tracks = self._mobileclient.add_songs_to_playlist(
                playlist_id, song_ids)
        except NotLoggedIn:
            if self.authenticate():
                tracks = self._mobileclient.add_songs_to_playlist(
                    playlist_id, song_ids)
            else:
                return None

        return tracks

    def get_stream_url(self, id):
        try:
            stream_url = self._mobileclient.get_stream_url(id, self._device)
        except NotLoggedIn:
            if self.authenticate():
                stream_url = self._mobileclient.get_stream_url(
                    id, self._device)
            else:
                return ''
        except CallFailure:
            raise CallFailure('Could not play song with id: ' + id,
                              'get_stream_url')

        return stream_url
Example #29
0
    count = min(len(table), args.li)
else:
    count = len(table)

if logged_in:
    playLists = api.get_all_user_playlist_contents()
    playlist = next(p for p in playLists if p['name'] == args.pl)

    for i in range(0, count):
        column = table[i].xpath('td')

        """SomaFM prints breaks and in the schedule so we only want rows in the
            table that are a track"""
        if len(column) == 5:
            song.artist = column[1].xpath('a')[0].text
            song.songName = column[2].text
            song.album = column[3].xpath('a')[0].text

            result = api.search_all_access(song.artist + " " + song.songName, 1)

            if result['song_hits']:
                songInPlaylist = False
                for track in playlist['tracks']:
                    if track['trackId'] == result['song_hits'][0]['track']['nid']:
                        print 'playlist already contains ', song.songName
                        songInPlaylist = True

                if not songInPlaylist:
                    print 'playlist dose not already contain ', song.songName
                    api.add_songs_to_playlist(playlist['id'],
                                              result['song_hits'][0]['track']['nid'])
Example #30
0
      "you want imported. If none of them properly match, just type in 'none'."
matchHistory = {}
for k in playlist_map:
    print '**********************************'
    print 'now importing ' + k
    print '**********************************'
    newPID = api.create_playlist(k)
    playlist_songs = playlist_map[k]
    for song in playlist_songs:
        special_char = song.find('\\')
        while special_char >= 0:
            song = song[:special_char] + song[special_char + 1:]
            special_char = song.find('\\')
        sTokens = song.split('`')
        song, duration = sTokens[0], int(sTokens[1])
        results = api.search_all_access(song, 10)['song_hits']
        song_id = findMatch(results, song, duration, explicit_mode,
                            matchHistory)
        if song_id is None:
            results = api.search_all_access(song.split('~')[0],
                                            10)['song_hits']
            song_id = findMatch(results, song, duration, explicit_mode,
                                matchHistory)
        if song_id is not None:
            if errcount >= 20:
                raise Exception(
                    'Too many errors have occurred - the server is not responding properly.'
                )
            while errcount < 20:
                try:
                    api.add_songs_to_playlist(newPID, song_id)
Example #31
0
logged_in = mobile_client.login(email, password)

# logged_in is True if login was successful
if logged_in == True:
    print "Successfully logged in"
    
    if device_id == '':
        devices = web_client.get_registered_devices()
        valid = [device['id'][2:] + " (" + device['model'] + ")" for device in devices if device['type'] == 'PHONE']
        print valid
        id_index = int(raw_input("Device ID: "))
        device_id = valid[id_index].split(' ', 1)[0]
    
    while True:
        song_name = raw_input("Song title: ")

        results = mobile_client.search_all_access(song_name, 1)
        song = results['song_hits'][0]
        song_id = song['track']['nid']
        song_name = song['track']['title']
        song_artist = song['track']['artist']
        stream_url = mobile_client.get_stream_url(song_id, device_id)
        
        # Uncomment to save most recent song
        # urllib.urlretrieve (stream_url, "mp3.mp3")

        print "Now Playing " + song_name + " by " + song_artist
        p.set_mrl(stream_url)
        p.play()
else:
    print "Invalid login credintials"
Example #32
0
from gmusicapi import Mobileclient
from pprint import pprint
api = Mobileclient()

api.login('', '', Mobileclient.FROM_MAC_ADDRESS)

playlist_name = 'ToListenTo'
answer=api.search_all_access('', max_results=1)

sweet_track_ids = []
artist_id=answer['artist_hits'][0]['artist']['artistId']
response = api.get_artist_info(artist_id, include_albums=False, max_top_tracks=3, max_rel_artist=0)
for song in response['topTracks']:
    sweet_track_ids.append(song['nid'])
    playlists = api.get_all_playlists()
playlist_id = None
for playlist in playlists:
    if playlist_name in playlist['name']:
        playlist_id = playlist['id']
    if not playlist_id:
        playlist_id = api.create_playlist(playlist_name)
api.add_songs_to_playlist(playlist_id, sweet_track_ids)
Example #33
0
class GoogleMusic(object):
    def __init__(self):
        self.webclient = Webclient()
        self.mobileclient = Mobileclient()

    def is_authenticated(self):
        if self.webclient.is_authenticated():
            if self.mobileclient.is_authenticated():
                return True

        return False

    def login(self, username, password):
        if not self.is_authenticated():
            try:
                self.mobileclient.login(username, password)
                self.webclient.login(username, password)
            except:
                raise Exception('Couldn\'t log into Google Music')

    def search(self, query, kind):
        if self.is_authenticated():
            results = self.mobileclient.search_all_access(query)[kind +
                                                                 '_hits']

            return results

    def get_track(self, store_id):
        return self.mobileclient.get_track_info(store_id)

    def save_stream(self, track, destination):
        if self.is_authenticated():
            with open(destination, 'w+b') as stream_file:
                urls = self.webclient.get_stream_urls(track.get('storeId'))

                if len(urls) == 1:
                    stream_file.write(
                        self.webclient.session._rsession.get(urls[0]).content)

                range_pairs = [[int(s) for s in val.split('-')] for url in urls
                               for key, val in parse_qsl(urlparse(url)[4])
                               if key == 'range']

                for url, (start, end) in zip(urls, range_pairs):
                    stream_file.truncate(start)
                    stream_file.seek(0, 2)
                    audio = self.webclient.session._rsession.get(url).content
                    stream_file.write(audio)

            tag = easyid3.EasyID3()
            tag['title'] = track.get('title').__str__()
            tag['artist'] = track.get('artist').__str__()
            tag['album'] = track.get('album').__str__()
            tag['date'] = track.get('year').__str__()
            tag['discnumber'] = track.get('discNumber').__str__()
            tag['tracknumber'] = track.get('trackNumber').__str__()
            tag['performer'] = track.get('albumArtist').__str__()
            tag.save(destination)

            tag = mp3.MP3(destination)
            tag.tags.add(
                id3.APIC(
                    3, 'image/jpeg', 3, 'Front cover',
                    urllib.urlopen(
                        track.get('albumArtRef')[0].get('url')).read()))
            tag.save()
    else:
        track_name = link['track_name']

    q = link['artist_name'] + ' ' + track_name 
    queries.append(q)

#Now Google
mc = Mobileclient()
mc.login(config['email'], config['password'], config['android_device_id'])

hits = 0 
misses = 0 
track_ids = []
failed_queries = []
for q in queries:
    search = mc.search_all_access(q, max_results=5)
    g_songs = search['song_hits']
    if any(g_songs):
        sort_by_score = sorted(g_songs, key=itemgetter('score'), reverse=True)
        #print sort_by_score[0]['track']['storeId']
        track_ids.append(sort_by_score[0]['track']['storeId'])
        hits += 1
    else:
        misses += 1
        failed_queries.append(q)

print 'Hits: {0} Misses: {1}'.format(hits,misses)
if misses > 0:
    print 'Unable to find a Google Music match for these tracks:'
    print failed_queries
Example #35
0
from gmusicapi import Mobileclient

api = Mobileclient()
api.login("*****@*****.**", "osilgdgrnmiigtfz", Mobileclient.FROM_MAC_ADDRESS)

print(api.search_all_access("Hello"))