def main():
    args, config = init()

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

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

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

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

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

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

    for track in os.listdir(config['PROG']['DownloadPath']):
        print('Uploading {}'.format(track))
        uploaded_id = gm_extract_id(mm.upload('{}{}'.format(config['PROG']['DownloadPath'], track)))
        mc.add_songs_to_playlist(playlist_id, uploaded_id)
def main():
    logger.info('Scanning the Billboard Charts......')
    chart_df_dict = {}
    global gmusic
    if not gmusic:
        gmusic = Mobileclient(debug_logging=False)
        gmusic.login(email=USER_NAME,
                     password=APP_PASSWORD,
                     locale='en_US',
                     android_id=Mobileclient.FROM_MAC_ADDRESS)
    for chart, chart_name in charts_to_playlist:
        logger.info('Getting {}......'.format(chart_name))
        chart_scraped = billboard.ChartData(config['BILLBOARD'][chart])
        chart_df = get_song_df(chart_scraped)
        #Delete Playlist if present.
        logger.info('Updating {} Playlist......'.format(chart_name))
        delete_playlist_if_exists(chart_name)
        #Create Playlist
        playlist_id = gmusic.create_playlist(
            name=chart_name,
            description=chart_name + ' from Billboard on week {}'.format(
                current_week(dt.datetime.today())),
            public=True)
        gmusic.add_songs_to_playlist(
            playlist_id=playlist_id,
            song_ids=chart_df.song_id.dropna().tolist())
        chart_df_dict[chart] = chart_df
        #Top Rising from Hot 100
        if chart_df_dict.has_key('HOT_100'):
            logger.info('Updating {} Playlist......'.format('Top 25 Risers'))
            top_100 = chart_df_dict['HOT_100']
            top_100.loc[top_100.change == 'Hot Shot Debut', 'change'] = 100
            top_100.change = pd.to_numeric(top_100.change,
                                           errors='coerce').fillna(0)
            hot25_risers = top_100.sort_values(
                by=['change'],
                ascending=False).head(25).sort_values(by=['rank'],
                                                      ascending=True)
            delete_playlist_if_exists('Top 25 Risers')
            playlist_id = gmusic.create_playlist(
                'Top 25 Risers',
                'Top 25 Risers from Hot 100 Billboard on week {}'.format(
                    current_week(dt.datetime.today())))
            gmusic.add_songs_to_playlist(
                playlist_id=playlist_id,
                song_ids=hot25_risers.song_id.dropna().tolist())
            logger.info('Finished Updating......'.format('Top 25 Risers'))
Example #3
0
class Playlist():
    '''
    Parent class for specific types of playlists, like:
        Live Setlist Playlist
            setlist based on the set of songs played at a live concert
        Upcoming Concert Playlist
            setlist generated from a list of bands that have upcoming concerts in an area
    '''
    def __init__(self, make=False):
        self.setup_logging()
        self.api = Mobileclient()
        self.logged_in = self.api.login(
            EMAIL,
            TOKEN,
            # Mobileclient.FROM_MAC_ADDRESS)
            DEVICE_ID)
        if self.logged_in:
            self.info("Logged into GPMAA successfully")

    def setup_logging(self):
        logger_name = '.'.join([__name__, __class__.__name__])
        self.logger = logging.getLogger(logger_name)
        logging.getLogger('gmusicapi.protocol.shared').setLevel(logging.INFO)
        logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING)

    def error(self, msg):
        self.logger.error(msg)

    def info(self, msg):
        self.logger.info(msg)

    def debug(self, msg):
        self.logger.debug(msg)

    def search(self, query):
        '''
        This function got pulled to the parent class because we'll always be searching
        for things and wanting the song results. They're always going to have to be
        processed this way because of how the search result is formatted.

        The result is a list of song dictionaries with keys such as storeId, artist, etc.
        '''
        res = self.api.search(query)['song_hits']
        res = [song['track'] for song in res]
        return res

    def create_playlist(self, song_ids, name, description='', public=False):
        self.info("Creating {}".format(name))
        self.id = self.api.create_playlist(name, description, public)
        self.api.add_songs_to_playlist(self.id, song_ids)

    def delete_playlist(self):
        if hasattr(self, 'id') and self.id is not None:
            self.info("Deleting playlist id: %s".format(self.id))
            self.api.delete_playlist(self.id)
        else:
            self.info("Can't delete a playlist without its id")
Example #4
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 #5
0
class GMusicPodcastSyncDestination(PodcastSyncDestination):
    def __init__(self):
        super(GMusicPodcastSyncDestination, self).__init__()
        self.serviceIdentifier = "GOO"
        self.serviceName = "Google Music"
        self.musicManager = Musicmanager()
        self.mobileClient = Mobileclient()
        oAuthFile = "gMusic.oauth"
        if not os.path.isfile(oAuthFile):
            if not self.musicManager.perform_oauth(oAuthFile, True):
                print "Failed to authenticate Music Manager."
                raise PodcastSyncDestinationException("Authentication Failure.")
        else:
            try:
                self.musicManagerauthenticated = self.musicManager.login(oAuthFile)
            except gmusicapi.exceptions.AlreadyLoggedIn:
                pass
        username = raw_input("Enter Google Username: "******"Enter Google Password: "******"Authentication Failure.")
            # perform a push task. should return a PodFastPodcastPushedEpisode instance

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

    def pullEpisode(self, podcastSyncTaskEpisodePull):
        self.mobileClient.delete_songs([podcastSyncTaskEpisodePull.syncDestinationID])
        # TODO: Error check here.
        return True
Example #6
0
    def add_songs_to_library(self):
        api = Mobileclient()
        logged_in = api.login('*****@*****.**', '1944_D-d@y',
                              Mobileclient.FROM_MAC_ADDRESS)

        playlist = api.create_playlist("JackFM #2",
                                       "This is what Jack is playing next")
        for sn in crawler.songs:
            print sn.name
            search_res = api.search(sn.name + " " + sn.artist, 10)
            songid = search_res["song_hits"][0]["track"]["storeId"]
            api.add_songs_to_playlist(playlist, songid)
Example #7
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 #8
0
def export_song_data(name, data, dry_run):
    gmusic = Mobileclient()
    logged_in = gmusic.oauth_login(Mobileclient.FROM_MAC_ADDRESS)

    if not logged_in:
        print("Couldn't log in. Starting authentication...")
        gmusic.perform_oauth()
        logged_in = gmusic.oauth_login(Mobileclient.FROM_MAC_ADDRESS)
        if logged_in:
            print("Logged in!")
        else:
            print("Login failed.")
            sys.exit(1)

    song_ids = data_to_song_ids(gmusic, data)
    print("Found %d/%d tracks on Google Music." % (len(song_ids), len(data)))
    if song_ids and not dry_run:
        playlist_id = gmusic.create_playlist(name)
        gmusic.add_songs_to_playlist(playlist_id, song_ids)
        print("Created playlist \"%s\"." % name)
Example #9
0
class GoogleMusicProvider:
    api = None

    def __init__(self, login, password, android_id, *args):
        self.api = Mobileclient()
        auth = self.api.login(login, password, android_id)
        if not auth:
            self.api.get
        print('GPM login: {0}'.format(auth))

    def search(self, query):
        return self.api.search(query, max_results=1)['song_hits'][0]['track']

    def getUrl(self, id):
        return self.api.get_stream_url(id)

    def add_playlist(self, name):
        return self.api.create_playlist(name)

    def add_to_playlist(self, trackId, playlistId):
        self.api.add_songs_to_playlist(playlist_id=playlistId,
                                       song_ids=trackId)
Example #10
0
def main():
    log.setLevel(logging.INFO)
    logging.getLogger('gmusicapi').setLevel(logging.INFO)
    
    cred_path = os.path.join(os.path.expanduser('~'), '.gmusic-sync')

    if not os.path.isfile(cred_path):
        raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
    if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
        raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
    
    config = ConfigParser.ConfigParser()
    config.read(cred_path)

    src_user = config.get('src','username')
    src_pass = config.get('src','password')
    src_device = config.get('src','deviceid')

    dst_user = config.get('dst','username')
    dst_pass = config.get('dst','password')
    dst_device = config.get('dst','deviceid')

    if not src_user or not src_pass or not dst_user or not dst_pass:
        raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
    if not src_device or not dst_device:
         raise NoCredentialException(
                    'No deviceId could be read from config file'
                    ': %s' % cred_path)

    parser = argparse.ArgumentParser(description='gmusic-sync', add_help=False)

    parser.add_argument('-hs', '--strict-heuristics', help='Songs must match artist, album, and title to be considered a match.', action='store_true', dest='strict_heuristics')
    parser.add_argument('-l', '--list', help='List playlists on the src account', action='store_true', dest='lst')
    parser.add_argument('-p', '--playlist', help='Playlist ID from src account to transfer', dest='playlist')
    args = parser.parse_args()

    api = Mobileclient()
    api.login(src_user, src_pass, src_device)

    playlists = api.get_all_playlists()

    if args.lst:
        for playlist in playlists:
            print playlist['name'] + ' (' + playlist['id'] + ') '
        exit()

    library = api.get_all_songs()

    api2 = Mobileclient()
    api2.login(dst_user, dst_pass, dst_device)
    library2 = api2.get_all_songs()

    if args.playlist is None:
        print 'Error: no playlist selected'

    all_playlist_entries = api.get_all_user_playlist_contents()

    selected_playlist_entries = []
    dst_playlist_id = None
    
    for entry in all_playlist_entries:
        if entry['id'] == args.playlist:
            selected_playlist_entries = entry['tracks']
            dst_playlist_id = api2.create_playlist(entry['name'])

    if dst_playlist_id is None:
        print 'Error creating new playlist'
        exit()

    playlist_tracks = []

    for ptrack in selected_playlist_entries:
        track_found = False
        for track in library:
            if ptrack['trackId'] == track['id']:
                playlist_tracks.append(track)
                track_found = True
                break
            try:
                if ptrack['trackId'] == track['storeId']:
                    playlist_tracks.append(track)
                    track_found = True
                    break
            except:
                pass
        if not track_found:
            print 'ERROR: could not find playlist entry ' + str(ptrack)
            api.add_aa_track(ptrack['trackId'])

    if len(playlist_tracks) != len(selected_playlist_entries):
        print 'Error: could not locate all playlist tracks in src library'
        exit()
    
    failed_tracks = []

    for track in playlist_tracks:
        try:
            if track['storeId'].startswith('T'):
                #It's a store track: does it exist in the target store?
                #Perform a store lookup: this will raise an exception if the track
                #Is not in the target store
                store_track = api2.get_track_info(track['storeId'])
                #If we got here, we're good to go for adding the track to the playlist
                retval = api2.add_songs_to_playlist(dst_playlist_id, track['storeId'])
                if track['storeId'] not in retval:
                    print 'Error adding   '  + track['title'] + ' - ' + track['artist'] + ' (' + track['album'] + ')'
            else:
                dst_track = heuristic_search(library2, track, args.strict_heuristics)
                if dst_track is not None:
                    api2.add_songs_to_playlist(dst_playlist_id, dst_track['id'])
                else:
                    failed_tracks.append(track)
        except:
            #Not a store track: do heuristics lookup
            dst_track = heuristic_search(library2, track, args.strict_heuristics)
            if dst_track is not None:
                api2.add_songs_to_playlist(dst_playlist_id, dst_track['id'])
            else:
                failed_tracks.append(track)

            continue

    print '----------------- FAILED TRACKS --------------------'
    for track in failed_tracks:
        print track['title'] + ' - ' + track['artist'] + ' (' + track['album'] + ')'
Example #11
0
class MusicPlayer(object):

    def __init__(self):
        self.playlist = []                  # Array of all tracks
        self.playlist_id = 0                # Id of playlist
        self.current_track_index = 0        # Index of current song
        self.player = Player()              # MPlayer instance
        self.webclient = Webclient()        # Client for WebInterface
        self.mobileclient = Mobileclient()  # Client for MobileInterface
        self.timer = None                   # Timer to start next track
        self.deviceid = 0                   # DeviceId to use
        self.playtype = PlayType.LINEAR     # LINEAR or SHUFFLE

    def login(self, username, password):
        """ Login to Google Music.

        Keyword arguments:
        username -- the username
        password -- the password

        Returns:
        True if successful else False

        """

        # If either the web client or the mobile client failed to login return False
        if not self.webclient.login(username, password) or not self.mobileclient.login(username, password):
            return False

        # Use first found devices as ID
        devices = self.webclient.get_registered_devices();

        # Convert HEX to INT
        self.deviceid = int(devices[0]['id'], 16)

        return True

    def load_playlist(self, playlist_name):
        # Load playlist
        for playlist in self.mobileclient.get_all_user_playlist_contents():
            if playlist['name'] == playlist_name:
                for track_obj in playlist['tracks']:
                    track_obj['track']['id'] = track_obj['id']
                    self.playlist.append(track_obj['track'])

                # Set playlist_id
                self.playlist_id = playlist['id']
                break;

        # If playlist has not been found, create it
        if self.playlist_id == 0:
            self.playlist_id = self.mobileclient.create_playlist(playlist_name)

    def add_track_to_playlist(self, track):
        """ Append a track to the end of playlist

        Keyword arguments:
        track -- a dictionary containing the track informations

        """
        track_id = self.mobileclient.add_songs_to_playlist(self.playlist_id, track['nid'])[0]
        track['id'] = track_id
        self.playlist.append(track)

        # Notify all clients about the new track
        factory.forwarder.dispatch(PLAYLIST_EVENT_TRACK_ADDED, json.dumps(track))

    def remove_track_from_playlist(self, track_id):
        """ Removes a track from the playlist

        Keyword arguments:
        track_id -- The id of the track to remove

        """
        self.mobileclient.remove_entries_from_playlist(track_id)

        index_to_remove = self._find_index_of_track_id(track_id)

        del self.playlist[index_to_remove]

        factory.forwarder.dispatch(PLAYLIST_EVENT_TRACK_REMOVED, track_id)

    def play_track(self, track_id):
        """ Play a track

        Keyword arguments:
        track_id -- Id of the track to play

        """

        index_of_track = self._find_index_of_track_id(track_id)

        track_to_play = self.playlist[index_of_track]

        if track_to_play is not None:
            # Request stream url from google music
            stream_url = self.mobileclient.get_stream_url(track_to_play["storeId"], self.deviceid)

            # Load stream url to mplayer
            self.player.loadfile(stream_url)

            # For some reason OSX needs to unpause mplayer
            if sys.platform == "darwin":
                self.player.pause()

            # Set track
            self.current_track_index = index_of_track

            # Cancel previous timer
            if self.timer is not None:
                self.timer.cancel()

            # How many minutes does the track last
            track_duration = long(track_to_play["durationMillis"]) / 1000

            # Set Timer to play next track when trackDuration is over
            self.timer = Timer(track_duration, self.play_next_track)
            self.timer.daemon = True
            self.timer.start()

            print "playing", track_to_play["artist"], " - ", track_to_play["title"], " : ", stream_url

            # Fire event that a new track is playing
            factory.forwarder.dispatch(TRACK_EVENT_PLAYBACK, json.dumps(track_to_play))

            return True
        else:
            return False

    def play_next_track(self):
        """ Play the next track in the playlist.

        Returns:
        True or False

        """

        if self.playtype == PlayType.LINEAR:
            # Index of next track to play
            next_track_index = self.current_track_index + 1

            # Restart at index 0 if end of playlist is reached
            if next_track_index >= len(self.playlist):
                next_track_index = 0

        elif self.playtype == PlayType.SHUFFLE:
            # Index of next track to play at random
            next_track_index = random.randrange(0, len(self.playlist), 1)

        # Obtain the id of the next track to play
        next_track_id = self.playlist[next_track_index]['id']

        # Play track with that id
        return self.play_track(next_track_id)

    def play_previous_track(self):
        """ Play the previous track in the playlist.

        Returns:
        True or False

        """

        if self.playtype == PlayType.LINEAR:
            # Index of previous track to play
            previous_track_index = self.current_track_index - 1

            # Contiune from the end of the playlist
            if previous_track_index <= 0:
                previous_track_index = len(self.playlist) - 1

        elif self.playtype == PlayType.SHUFFLE:
            # Index of the previous track is random
            previous_track_index = random.randrange(0, len(self.playlist), 1)

        # Obtain the id of the previous track to play
        previous_track_id = self.playlist[previous_track_index]['id']

        # Play track with that id
        return self.play_track(previous_track_id)

    def stop(self):
        """ Stop playback.

        """

        if self.timer is not None:
            self.timer.cancel()

        if self.player is not None:
            self.player.stop()

    def play(self):
        """ Start playing current track

        Returns:
        True if track has been started. Else False

        """
        current_track_id = self.playlist[self.current_track_index]
        return self.play_track(current_track_id)

    def _find_index_of_track_id(self, track_id):
        index = 0

        for track in self.playlist:
            if track['id'] == track_id:
                return index
            index += 1

        return None
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 #13
0
    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(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)
Example #14
0
class GoogleMusic:

    __metaclass__ = Singleton
    SKIP_ARTIST = ['vox freaks']

    def __init__(self):
        self.gmusicapi = Mobileclient(debug_logging=False)
        logged_in = self.gmusicapi.login(
            email=Config.GOOGLE_MUSIC_USER_NAME,
            password=Config.GOOGLE_MUSIC_APP_PASSWORD,
            locale='en_US',
            android_id=Mobileclient.FROM_MAC_ADDRESS)
        if not logged_in:
            raise Exception('Unable to log in to GoogleMusic')

    def get_lib_from_gmusic(self):
        lib = self.gmusicapi.get_all_songs()
        lib_list = []
        song = None
        for song in lib:
            song = Song(artist=song['artist'], title=song['title'])
            lib_list.append(song)
        return lib_list

    def delete_playlist_if_exists(self, name):
        all_playlists = self.gmusicapi.get_all_playlists()
        for playlist in all_playlists:
            if playlist['name'] == name:
                self.gmusicapi.delete_playlist(playlist['id'])

    def create_playlist(self, name, description, public=True):
        return self.gmusicapi.create_playlist(name=name,
                                              description=description,
                                              public=public)

    def add_songs_to_playlist(self, playlist_id, song_ids=None, song_df=None):
        if (song_ids is None and song_df is None):
            raise ValueError('Need song_ids or song_dfs to add to playlist')
        if song_df is not None and (not song_df.empty):
            song_ids = song_df.google_music_store_id.dropna().tolist()
        return self.gmusicapi.add_songs_to_playlist(playlist_id, song_ids)

    def gmusic_constrained_search(self, song, query, strict):
        song_hits = query['song_hits']
        for result in song_hits:
            track = result['track']
            if track['albumArtist'].lower() in SKIP_ARTIST:
                continue
            if song.remix:
                if "remix" not in track['title'].lower():
                    continue
            else:
                if "remix" in track['title'].lower():
                    continue
            if strict:
                full_title = "{} - {}".format(track['albumArtist'],
                                              track['title'])
                score = difflib.SequenceMatcher(None, song.full_title.lower(),
                                                full_title.lower()).ratio()
                if score < 0.6:
                    continue
            return track
        return None

    def search_song(self, song, strict=False):
        try:
            first_query = self.gmusicapi.search(song.full_title)
            first_result = self.gmusic_constrained_search(
                song, first_query, strict)
            if first_result is None:
                second_query = self.gmusicapi.search(song.full_title_stripped)
                first_result = self.gmusic_constrained_search(
                    song, second_query, strict)
            if first_result is None:
                logger.warning(
                    'No satisfactory result found in Google Music for {}'.
                    format(song.full_title))
            return first_result
        except Exception as e:
            logger.debug('Exception: {}'.format(e))
            logger.info(u'Skipped {}'.format(song.title))
            return None

    def get_store_id(self, result):
        store_id = None
        if result:
            if result.has_key('storeId'):
                store_id = result['storeId']
        return store_id

    def get_google_rating(self, result):
        rating = None
        if result:
            if result.has_key('rating'):
                return result['rating']
        return rating

    def update_playlist(self, playlist, public=True, exclude_0_rating=True):
        #Delete Playlist if present.
        logger.info(u'Updating the playlist {} in GoogleMusic'.format(
            playlist.name))
        self.delete_playlist_if_exists(playlist.name)
        #Create Playlist
        playlist_id = self.create_playlist(name=playlist.name,
                                           description=playlist.description,
                                           public=public)
        if exclude_0_rating:
            playlist.song_df = playlist.song_df[
                playlist.song_df['google_music_rating'] != '1']
        self.add_songs_to_playlist(playlist_id=playlist_id,
                                   song_df=playlist.song_df)
Example #15
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)
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 #17
0
    print "usage:" + sys.argv[0] + " filename [playlist name]"
    sys.exit()

file = params[1]

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

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

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

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

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

    api.add_songs_to_playlist(playlist_id, track_id)
Example #18
0
            tempList.append(filledPlaylist[k][x])
    while len(tempList) > 0:
        selected = choice(tempList)
        mergedPlaylist.append(selected)
        tempList.remove(selected)

print('done')
print('Saving playlist... ', end='')

finalPlaylist = []
localBumperPool = []
segmentCount = 0

for i in mergedPlaylist:
    finalPlaylist.append(i)
    segmentCount += 1
    if segmentCount > 3:
        segmentCount = 0
        if len(localBumperPool) == 0:
            localBumperPool = bumpersPool[:]
        selected = choice(localBumperPool)
        finalPlaylist.append(selected)
        localBumperPool.remove(selected)
    
finalPlaylist.append(choice(signoffPool))

newPlaylist = api.create_playlist('JRay-FM ' + datetime.now().strftime('%m/%d/%Y %H:%M:%S'))
api.add_songs_to_playlist(newPlaylist, finalPlaylist)
api.logout()

print('done')
Example #19
0
class GPM(object):
    _api = None

    def __init__(self):
        self._api = Mobileclient(debug_logging=False)
        if not self._api.login(GPM_EMAIL_ADDRESS, GPM_APP_PASSWORD,
                               Mobileclient.FROM_MAC_ADDRESS):
            raise Exception("Failed to authenticate with GPM")

    def _delete_playlist(self, playlist_id):
        return self._api.delete_playlist(playlist_id)

    def _create_playlist(self, name, description):
        return self._api.create_playlist(name, description)

    def _add_songs_to_playlist(self, playlist_id, song_ids):
        return self._api.add_songs_to_playlist(playlist_id, song_ids)

    def _match_song(self, song):
        query = f'{song.title} {song.artist}'
        results = self._api.search(query)

        hits = [song_hit['track'] for song_hit in results.get('song_hits')]
        # Check if song is a match
        for hit in hits:
            if is_match(hit['title'], song.title) and is_match(
                    hit['artist'], song.artist):
                return hit['storeId']

        return None

    def _get_playlist(self, name):
        playlists = self._api.get_all_user_playlist_contents()
        for playlist in playlists:
            if playlist['name'] == name:
                return playlist
        return None

    def get_playlist(self, name):
        playlist = self._get_playlist(name)
        return Playlist.from_gpm(playlist) if playlist else None

    def create_playlist(self, playlist, override):
        gpm_playlist = self.get_playlist(playlist.title)
        gpm_playlist_id = gpm_playlist.id if gpm_playlist else None

        # Delete if it already exists
        if gpm_playlist_id and override:
            self._delete_playlist(gpm_playlist_id)
        # Create it if we are re-making it or it didn't already exist
        if not gpm_playlist_id or override:
            gpm_playlist_id = self._create_playlist(playlist.title,
                                                    playlist.description)

        # Get all song_ids and remove results we could not match
        matches = [self._match_song(song) for song in playlist.songs]
        song_ids = [match for match in matches if match is not None]

        self._add_songs_to_playlist(gpm_playlist_id, song_ids)
        # Return number of songs added to playlist
        return len(song_ids)
import os
import json

from gmusicapi import Mobileclient

api = Mobileclient()

api.login('*****@*****.**', 'my-password')
# => True

library = api.get_all_songs()
sweet_track_ids = [track['id'] for track in library
                   if track['artist'] == 'The Cat Empire']

playlist_id = api.create_playlist('Rad muzak')
api.add_songs_to_playlist(playlist_id, sweet_track_ids)
Example #21
0
                                # try to use album match
                                pl_songs.append(sd["id"])
                                sd_find = 1
                                break
                        else:
                            # we assume if the title and artist match, that's the song we're looking for
                            pl_songs.append(sd["id"])
                            sd_find = 1
                            break
                if not sd_find:
                    print "Could not find " + check_title + " by " + check_artist
            line = f.readline()

    # create new playlist
    print 'creating playlist ' + str(need_to_create_name[cnt])
    playlist_id = mc.create_playlist(str(need_to_create_name[cnt]))
    # run through list of songs and add each song_id
    song_cnt = 0
    while (song_cnt < len(pl_songs)):
        try:
            mc.add_songs_to_playlist(playlist_id, str(pl_songs[song_cnt]))
            song_cnt += 1
        except:
            next
    print str(song_cnt) + " songs added ..."

    cnt += 1

print str(cnt) + " new playlists added ..."

###################
Example #22
0
class Playlister(object):

    WMBR_SITE = "https://track-blaster.com/wmbr/index.php"
    WMBR_SITE_NO_PHP = "https://track-blaster.com/wmbr/"
    PROG_SEARCH_FILL = {
        "startdt": "June 28, 1984",
        "enddt": datetime.datetime.now().strftime("%B %d, %Y"),
        "sort": "desc"
    }

    CRED_PATH = os.path.join(str(Path.home()), ".wmbr", "cred")

    def __init__(self):
        self.programs = {}
        site_data = requests.get(self.WMBR_SITE)
        parser = BeautifulSoup(site_data.content, "html.parser")
        program_selector = None

        for selector in parser.find_all("select"):
            if selector.get("name") == "program":
                program_selector = selector

        for option in program_selector.find_all("option"):
            self.programs[option.string] = option.get("value")

        self.mb = Mobileclient()

        if not os.path.exists(os.path.dirname(self.CRED_PATH)):
            os.mkdir(os.path.dirname(self.CRED_PATH))

        if not self.mb.oauth_login(Mobileclient.FROM_MAC_ADDRESS,
                                   oauth_credentials=self.CRED_PATH):
            self.mb.perform_oauth(storage_filepath=self.CRED_PATH)

    def playlist_visitor(self, lonk):
        lonk = "".join([self.WMBR_SITE_NO_PHP, lonk])
        print("Visting %s" % lonk)
        lonk_data = requests.get(lonk)
        lonk_parser = BeautifulSoup(lonk_data.content, "html.parser")

        row_divs = lonk_parser.find_all("div",
                                        {"id": re.compile("row_[0-9]+")})

        store_ids = []

        for row in row_divs:
            try:
                artist_row = row.find_all(
                    "div", class_=re.compile(r"-Artist$")
                )[1]  # gonna get a hidden row with this, actual result should be second in the list
                song_row = row.find_all(
                    "div", class_=re.compile(r"-Song$")
                )[1]  # gonna get a hidden row with this, actual result should be second in the list
            except IndexError:
                # apparently there are rows with no contents or are filled with comments instead
                continue

            artist = artist_row.find("a").string
            song = song_row.find("a").string

            print("%s : %s" % (artist, song))
            try:
                track_dict = self.mb.search(
                    "%s %s" % (artist, song),
                    max_results=10)['song_hits'][0]['track']
                store_ids.append(track_dict['storeId'])
            except IndexError:
                print("No results for %s by %s" % (song, artist))

        return store_ids

    def select_a_program(self):
        playlist_links = set()
        cli = ScrollBar("Select a show: ", [*self.programs],
                        pointer="🎵",
                        height=6,
                        align=5,
                        margin=3)

        program = cli.launch()
        search_fill = self.PROG_SEARCH_FILL.copy(
        )  # make a copy of the dict in case we want to do another search
        search_fill['program'] = self.programs[program]
        search_url = "?".join([self.WMBR_SITE, parse.urlencode(search_fill)])
        search_data = requests.get(search_url)
        search_parser = BeautifulSoup(search_data.content, "html.parser")
        playlist_a_tags = search_parser.find_all(
            "a", href=re.compile(r"playlist.php*"))

        for a in playlist_a_tags:
            playlist_links.add(a.get('href'))

        playlist_links = list(playlist_links)

        songz = []
        for lonk in playlist_links:
            time.sleep(1)
            songz.extend(self.playlist_visitor(lonk))

        playlist_id = self.mb.create_playlist(program)

        self.mb.add_songs_to_playlist(playlist_id, songz)
Example #23
0
    action = ""

#library = api.get_track_info('Ttk6fmoytroyauv2simicl62hlu')
#print data[['storeId','id']]
#for i,v in data.iterrows():
#    for i2,v2 in enumerate(library):
#	if v2['storeId'] == data.loc[i, "storeId"]:
#	    print i
#	    data.loc[i, "id"] = v2['id']
#	    library.pop(i2)
#	    break

#data.to_csv("gpmusic_fixed.csv")

#print data.describe()

#print json.dumps(library[len(library)-1], indent=4, separators=(',', ': '))
#print json.dumps(library, indent=4, separators=(',', ': '))

#device = webapi.get_registered_devices()
#streamURL = api.get_stream_url(guid, device[0]['id'][2:])
streamURL = api.get_stream_url(guid, '320b3128904ea650')
if action == "":
    pid = api.create_playlist("Tempo: " + dt.datetime.now().strftime("%m-%d-%Y %I:%M:%S%p"))
    api.add_songs_to_playlist(pid, guid)
    #print json.dumps(device, indent=4, separators=(',', ': '))
    #print webapi.get_stream_urls(library['storeId'])
    print json.dumps({"streamURL": streamURL, "pid": pid}, indent=4, separators=(',', ': '))
else:
    print json.dumps({"streamURL": streamURL}, indent=4, separators=(',', ': '))
		return True
	else:
		print 'unable to login to google music'
		return False
	
# main
if __name__ == '__main__':	

	# input show name
	show = raw_input('Input show: ').lower()

	# authenticate to google music
	if login():
		
		# create playlist
		playlist_id = api.create_playlist(show)

		# load seasons in show
		data = get_show(show.replace(' ', '-'))
		
		# song id array (added per season to single playlist)
		song_ids = []

		# for each season
		for season in data['seasons']:
			season_url = season['tunefind_api_url']
			season_number = season['number']

			print show + ' Season: ' + season_number, '\n'

			data = get(season_url)
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

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


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

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

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

        print "Authenticated"
        print ""


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

        plid = ""

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

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

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

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

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

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

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

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

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

            if not song_id:
                failed_files += 1
                continue

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

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

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


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

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

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

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

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

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

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
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 #27
0
        missing.append(row)

print "##### {} of {} Songs Found. #####".format(len(songs), len(rows))

log("### Missing Songs ###")

for row in missing:
    log(decode(row['title']) + " could not be found.")

log("### Fetching Playlists ###")
playlists = api.get_all_user_playlist_contents()
playlist = [p for p in playlists if p['name'] == gmusic_playlist_name]

song_ids = [s['id'] for s in songs]

if len(playlist) == 0:  # Playlist not found, create a new one.
    playlist_id = api.create_playlist(u'foobar2000')
else:
    playlist_id = playlist[0]['id']
    # Prevent duplicated songs in existing playlist
    for track in playlist[0]['tracks']:
        if track['trackId'] in song_ids:
            song_ids.remove(track['trackId'])

log("Importing to Playlist ID: " + playlist_id)
api.add_songs_to_playlist(playlist_id, song_ids)

log("### Import Completed ###")

logfile.close()
api.logout()
Example #28
0
class GMusic(object):
    def __init__(self):
        self.mob_client = Mobileclient()
        self.web_client = Webclient()
        self.logfile = None
        self.logfile_open = False
        # logged_in is True if login was successful
        logged_in = self.mob_client.login(MY_GMAIL, MY_PASSWORD, Mobileclient.FROM_MAC_ADDRESS)
        if logged_in:
            print("GoogleMusic MobileClient Logged In")
        else:
            raise Exception("Couldn't log in, exiting...")
        logged_in = self.web_client.login(MY_GMAIL, MY_PASSWORD)
        if logged_in:
            print("GoogleMusic WebClient Logged In")
        else:
            raise Exception("Couldn't log in, exiting...")

    def build_play_list_dummy(self):
        library = self.mob_client.get_all_songs()
        tracks = [track for track in library if track['artist'] == 'Adhesive Wombat'
                  and "night shade" in track['title'].lower()]
        # for track in sweet_tracks:
        #     print(track)

        playlist_id = self.mob_client.create_playlist('Test playlist')
        for track in tracks:
            self.mob_client.add_songs_to_playlist(playlist_id, track['id'])

        return playlist_id

    def _setlogfile(self, logfile):
        if self.logfile_open:
            self._print_and_log("logfile {} already opened! Not opening again!")
        else:
            self.logfile = logfile
            with open(self.logfile, "w") as logfile:
                logfile.write("LOGSTART: {}, script: {}\n".format(asctime(localtime()), __file__))
            self.logfile_open = True

    def _print_and_log(self, msg):
        if self.logfile:
            with open(self.logfile, "a") as logfile:
                logfile.write(msg+"\n")
        print msg

    def find_duplicate_songs(self, outfile=None):
        duplicates = []
        if outfile:
            if path.exists(path.dirname(outfile)):
                self._setlogfile(outfile)
            else:
                raise IOError("Output filename given: {} is in an none-existing dir".format(outfile))

        library = self.mob_client.get_all_songs()
        tracks = [track for track in library]
        while tracks:
            track = tracks[0]
            dup_list = []
            dup_idx_list = []
            for idx, track_i in enumerate(tracks):
                if track['artist'].lower() == track_i['artist'].lower() and\
                   track['album'].lower() == track_i['album'].lower() and\
                    track['discNumber'] == track_i['discNumber'] and\
                    track['trackNumber'] == track_i['trackNumber'] and\
                   track['title'].lower() == track_i['title'].lower():
                    dup_idx_list.append(idx)
                    dup_list.append(track_i)
            # Remove them:
            for index in sorted(dup_idx_list, reverse=True):
                del tracks[index]
            if len(dup_list) > 1:
                duplicates.append(dup_list)
        for idx, dup_list in enumerate(duplicates):
            self._print_and_log("{}: '{}' was found {} times!".format(idx+1, dup_list[0]['title'].encode("utf-8"),
                                                                      len(dup_list)))
        self._print_and_log("Found a total of {} duplicate songs!".format(len(duplicates)))
        # Display important stuff
        for idx, track_list in enumerate(duplicates):
            self._print_and_log("{}: BAND: {}, NAME:  '{}'".format(idx+1, track_list[0]['artist'],
                                                                   track_list[0]['title'].encode("utf-8")))
            for el in track_list[0]:
                for track in track_list:
                    if el not in track:
                        track[el] = "NO VALUE"
                    if track[el] != track_list[0][el] and el not in ['id', 'url', 'recentTimestamp', 'storeId', 'nid', 'clientId']:
                        # unicode?
                        try:
                            r_val = track_list[0][el].encode("utf-8")
                        except:
                            r_val = track_list[0][el]
                        # unicode?
                        try:
                            l_val = track[el].encode("utf-8")
                        except:
                            l_val = track[el]

                        self._print_and_log("track_id {}: {}='{}'".format(track_list[0]['id'], el, r_val))
                        self._print_and_log("track_id {}: {}='{}'".format(track['id'], el, l_val))

            # raw_input("Press any key to continue...")
        return duplicates

    def delete_duplicates(self, duplicates):
        self._print_and_log("Cleaning duplicates [removing oldest of each duplicant]:")
        old_song_ids = []
        for idx, dup_list in enumerate(duplicates):
            self._print_and_log("{}: BAND: {}, NAME:  '{}'".format(idx+1, dup_list[0]['artist'],
                                                                   dup_list[0]['title'].encode("utf-8")))
            track_timstamp = None
            oldest_id = None
            for el in dup_list:
                if track_timstamp is None and oldest_id is None:
                    track_timstamp = el["timestamp"]
                    oldest_id = el["id"]
                elif el["timestamp"] < track_timstamp:
                    track_timstamp = el["timestamp"]
                    oldest_id = el["id"]
            # finished with dup_list - log oldest id:
            self._print_and_log("Will delete {}, track_id: {}".format(el["title"], el["id"]))
            old_song_ids.append(oldest_id)

        self.mob_client.delete_songs(old_song_ids)
        self._print_and_log("track_ids deleted:\n{}".format(old_song_ids))
Example #29
0
sModeYN = raw_input(
    'Do you want to enable explicit mode (which, in cases of ambiguity, will select the explicit versions of songs.\n'
)
if sModeYN in y:
    explicit_mode = True
else:
    explicit_mode = False
print "If the program cannot uniquely determine which song to import, based on results," + \
      "it will present a list of options. To pick, just enter the number of the choice" + \
      "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,
Example #30
0
class FetchSongs(object):
    """
        Class to manage updating and creating of playlists and songs in the Google Play Music service for a specific
         Play Music account
    """
    def __init__(self):

        self.songs = []
        self.nids = []

        os.environ['REQUESTS_CA_BUNDLE'] = '/etc/ssl/certs/ca-certificates.crt'

        self.api = Mobileclient()
        self.api.login('xxxxxx', 'xxxxx', Mobileclient.FROM_MAC_ADDRESS)

    def add_songs_to_gmusic_playlist(self, playlist_id, song_ids):
        """ Add songs to the GMUSIC API playlist using song ids

        :param playlist_id: str playlist id
        :param song_ids: list of strings
        :returns: None
        """

        return self.api.add_songs_to_playlist(playlist_id, song_ids)

    def search_for_songs(self, artist, title):
        """ Search for songs in the GMUSIC API

        :param artist: string
        :param title: string
        :return song_nid: string
        """

        song_nid = None
        search_content = self.api.search(''.join([artist, ' ', title]))
        for each_song in search_content['song_hits']:
            song_detail = box.Box(each_song['track'])
            if artist.casefold() in song_detail.artist.casefold(
            ) and title.casefold() in song_detail.title.casefold():
                song_nid = song_detail.storeId
                break
        return song_nid

    def get_playlists_length(self, api_content):
        """ Get size of GMUSIC playlists in terms of number of songs

        :param api_content: dict
        :returns playlist_sizes: dict
        """

        playlist_sizes = {}
        api_playlists = self.api.get_all_playlists()
        for api_playlist in api_playlists:
            for content_playlist in api_content:
                if content_playlist['id'] == api_playlist['id']:
                    playlist_sizes[api_playlist['id']] = len(
                        content_playlist['tracks'])
        return playlist_sizes

    def get_available_playlists(playlist_dict):
        """ Get available playlist ids and associated number of songs
        :param playlist_dict: dict
        :return list_id, number_of_songs: tuple of list_id and number of songs
        """

        available_lists = {k for (k, v) in playlist_dict.items() if v <= 800}
        if available_lists:
            for list_id, number_of_songs in available_lists.items():
                yield (list_id, number_of_songs)
        else:
            return None

    @classmethod
    def create_gmusic_playlist(self, name):
        """ Create GMUSIC playlist
        :param name: string name of playlist
        :return: string success or fail"""
        return self.api.create_playlist(name)
Example #31
0
		missing.append(row)
	
print "##### {} of {} Songs Found. #####".format(len(songs), len(rows))

log("### Missing Songs ###")

for row in missing:
	log(decode(row['title']) + " could not be found.")

log("### Fetching Playlists ###")
playlists = api.get_all_user_playlist_contents()
playlist = [p for p in playlists if p['name'] == gmusic_playlist_name]

song_ids = [s['id'] for s in songs]

if len(playlist) == 0: # Playlist not found, create a new one.
	playlist_id = api.create_playlist(u'foobar2000')
else:
	playlist_id = playlist[0]['id']
	# Prevent duplicated songs in existing playlist
	for track in playlist[0]['tracks']:
		if track['trackId'] in song_ids:
			song_ids.remove(track['trackId'])

log("Importing to Playlist ID: " + playlist_id)
api.add_songs_to_playlist(playlist_id, song_ids)

log("### Import Completed ###")

logfile.close()
api.logout()
def allaccessimport(playlist=None, username=None, password=None, dry_run=False):
    """
    Exports a Spotify playlist to stdout or csv.
    """

    if not username or not password:
        raise CommandError(
            "Username and password must be provided as either command-line " +
            "argument or in the application configuration file."
        )

    playlist_name = playlist
    playlist_description = ""
    if playlist:
        playlist_name = os.path.basename(playlist_name)
        playlist_name = os.path.splitext(playlist_name)[0]
    logging.debug("Playlist name will be: {}".format(playlist_name))

    api = Mobileclient(False, False)
    logged_in = api.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
    if not logged_in:
        raise CommandError('Error. Unable to login to Google Music All Access.')

    playlist_ref = None
    currenttracks = None

    failed_tracks = list()
    songs_added = 0
    total = 0

    stream = open(playlist, "rb") if playlist else sys.stdin

    for input_line in stream:
        input_line = input_line.strip()

        # Lazily search the beginning of the file for a Playlist name
        if input_line.startswith("#"):
            data = input_line[1:]
            parts = [x.strip() for x in data.split(":", 1)]

            if len(parts) == 2:
                if parts[0] == "Playlist":
                    playlist_name = parts[1]
                elif parts[0] == "Description":
                    playlist_description = parts[1]

            continue

        if not playlist_ref:
            if not playlist_name:
                raise CommandError(
                    "A playlist name was not given and it was not found " +
                    "in the file either. Can't continue."
                )
            else:
                playlist_ref, currenttracks = get_playlist(api, playlist_name)
                if not playlist_ref and not dry_run:
                    sys.stderr.write('Playlist not found. Creating new.\n')
                    playlist_ref = api.create_playlist(playlist_name, description=playlist_description)
                yield 'Going to update playlist {0} ({1})\n'.format(
                    playlist_name, playlist_ref
                )

        trackinfo = list(csv.reader([input_line], quoting=csv.QUOTE_ALL))[0]

        if trackinfo[0] == 'Track' and trackinfo[1] == 'Artist':
            yield 'Skipping header.'
            continue

        search_term = "{0} {1}".format(trackinfo[0], trackinfo[1])
        total = total + 1
        newtrackid, error_reason = search_track(api, search_term, currenttracks)
        if newtrackid:
            if not dry_run:
                #print("Add to {} song {}".format(playlist_ref, newtrackid))
                api.add_songs_to_playlist(playlist_ref, newtrackid)
            songs_added = songs_added + 1
        else:
            failed_tracks.append(trackinfo)
        sys.stderr.write(
            "Searching {}...{}\n".format(search_term, error_reason)
        )


    yield "{0} songs added out of {1}. {2} Failed.".format(
        songs_added, total, total-songs_added
    )

    yield "Failed tracks:"
    for line in failed_tracks:
        print "  ", line
Example #33
0
songs_ids = []

for line in options.file.readlines():
    line = line.strip().decode('utf-8')
    if not line:
        continue

    log.info('Searching for %s', line)

    result = cached_search(cache, api, line)
    songs = result['song_hits']

    songs = filter_songs(songs, line)

    if len(songs):
        songs_ids.append(songs[0]['track']['storeId'])
        continue

    log.debug(songs)

for pl in api.get_all_playlists():
    if pl['name'] == options.playlist:
        api.delete_playlist(pl['id'])

playlist_id = api.create_playlist(options.playlist)
try:
    api.add_songs_to_playlist(playlist_id, songs_ids)
except Exception, _:
    api.delete_playlist(playlist_id)
Example #34
0
                                    playlist_to_transfer['id'],
                                    fields="tracks,next")
        tracks = playlist['tracks']
        add_search_string(tracks, search_strings)
        while tracks['next']:
            tracks = sp.next(tracks)
            add_search_string(tracks, search_strings)
else:
    print("Can't get token for", username)

print(f'Detected {len(search_strings)} songs to transfer.')

mm = Mobileclient()
mm.perform_oauth()
mm.oauth_login(Mobileclient.FROM_MAC_ADDRESS)
playlist_id = mm.create_playlist(playlist_name)

print(f'Playlist \'{playlist_name}\' created.')
found_songs = 0
for row in search_strings:
    print(f'\t Searching \'{row}\'.')

    search_result = mm.search(row)
    songs = search_result.get('song_hits')

    song_id = None
    if len(songs) > 0:
        song_id = songs[0].get('track').get('storeId')
        found_songs += 1
    else:
        print('Song not found.')
        track_ids = [get_aa_id(t) for t in matched_tracks if t]
        
        # name noname playlists using date created
        if not playlist_name:
            log.warning('Replacing blank playlist name with timestamp')
            playlist_name = playlist_created

        # skip empty playlists
        if len(track_ids) == 0:
            log.warning('Skipping playlist ' + playlist_name + ' (no tracks available in All Access)')
            continue
            
        log.debug('Creating playlist ' + playlist_name)
        if not simulate:
            try:
                playlist_id = import_api.create_playlist(playlist_name)
            except CallFailure as e:
                log.error('Failed to create playlist ' + playlist_name)
                continue

        log.debug('Adding ' + str(len(track_ids)) + ' tracks to playlist')
        if not simulate:
            try:
                import_api.add_songs_to_playlist(playlist_id, track_ids)
            except CallFailure as e:
                log.error('Failed to add tracks to playlist ' + playlist_name)
                continue

# import all radio stations
if migration_type == 'all' or migration_type == 'stations':
    log.info('Importing ' + str(len(radio_stations)) + ' radio stations to ' + import_username)
Example #36
0
        # name noname playlists using date created
        if not playlist_name:
            log.warning('Replacing blank playlist name with timestamp')
            playlist_name = playlist_created

        # skip empty playlists
        if len(track_ids) == 0:
            log.warning('Skipping playlist ' + playlist_name +
                        ' (no tracks available in All Access)')
            continue

        log.debug('Creating playlist ' + playlist_name)
        if not simulate:
            try:
                playlist_id = import_api.create_playlist(playlist_name)
            except CallFailure as e:
                log.error('Failed to create playlist ' + playlist_name)
                continue

        log.debug('Adding ' + str(len(track_ids)) + ' tracks to playlist')
        if not simulate:
            try:
                import_api.add_songs_to_playlist(playlist_id, track_ids)
            except CallFailure as e:
                log.error('Failed to add tracks to playlist ' + playlist_name)
                continue

# import all radio stations
if migration_type == 'all' or migration_type == 'stations':
    log.info('Importing ' + str(len(radio_stations)) + ' radio stations to ' +
Example #37
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 #38
0
# Check if the playlist exists
# If it does, abort unless --replace is specified, in which case delete the old list
playlists = gpm.get_all_playlists()
for playlist in playlists:
    if playlist["deleted"]:
        continue
    if playlist["name"] == playlistName:
        if args.replace:
            logger.info("Deleting existing playlist")
            gpm.delete_playlist(playlist["id"])
        else:
            logger.error("Playlist already exists: " + playlistName)
            exit(1)

logger.info("Creating playlist: " + playlistName)
playlistId = gpm.create_playlist(playlistName, description="Autogenerated by RPG", public=False)

logger.info("Adding " + str(len(trackRows)) + " tracks to playlist")

trackIds = []
for row in trackRows:
    trackIds.append(row[0])

    if len(trackIds) >= 50:
        gpm.add_songs_to_playlist(playlist_id=playlistId, song_ids=trackIds)
        trackIds = []
        logger.debug("Added 50 tracks to playlist")
        time.sleep(10)


if len(trackIds) > 0:
        return True
    else:
        print 'unable to login to google music'
        return False
	
# main
if __name__ == '__main__':	

    # input show name
    show = raw_input('Input show: ').lower()

    # authenticate to google music
    if login():
            
        # create playlist
        playlist_id = api.create_playlist(show)

        # load seasons in show
        data = get_show(show.replace(' ', '-'))
        
        # song id array (added per season to single playlist)
        song_ids = []

        # for each season
        for season in data['seasons']:
            season_url = season['tunefind_api_url']
            season_number = season['number']

            print show + ' Season: ' + season_number, '\n'

            data = get(season_url)
print "Available genres:"
for g in genres_map.keys():
    if len(g) == 0:
        continue  # empty genre tag

    if len(genres_map[g]) >= 20:
        print g + "\t" + str(len(genres_map[g])) + " tracks --> generating playlist"
        good_genres.append(g)

    else:
        print g + "\t" + str(len(genres_map[g])) + " tracks --> too few tracks"

print

# remove all existing auto-playlists first
playlists = api.get_all_playlists()
for p in playlists:
    if p["name"].startswith("genre auto-playlist"):
        print "Removing playlist " + p["name"]
        api.delete_playlist(p["id"])

for genre in good_genres:
    playlist = genres_map[genre]
    playlist_name = "genre auto-playlist - " + genre
    print "Creating playlist " + playlist_name

    pid = api.create_playlist(
        playlist_name, description="Test " + genre + " playlist created automatically with a script", public=False
    )
    api.add_songs_to_playlist(pid, playlist)
Example #41
0
        artist = textstr.split(',')[0]
    else:
        song = textstr.split(',')[0]
        artist = ''
    return (artist, song)


playlists = api.get_all_playlists()
dt = datetime.datetime.now()
plname = 'sms_' + str(dt.month) + '_' + str(dt.day) + '_' + str(dt.year)
summerlist = False
for i in playlists:
    if plname in i['name'].lower():
        summerlist = i['id']
if not summerlist:
    api.create_playlist(name=plname)
    api.get_all_playlists()
    for i in playlists:
        if plname in i['name'].lower():
            summerlist = i['id']


@app.route("/", methods=['GET', 'POST'])
def listener():
    """Respond to incoming calls with a simple text message."""
    resp = twilio.twiml.Response()
    from_number = request.values.get('From', None)
    body = request.values.get('Body', None)
    music = process_sms(body)
    print"got a text from: " + str(from_number)
    print "They want to add " + str(music)
Example #42
0
class Gopma():
    def __init__(self, action=None):
        print "Initialising GOPMA."
        config = ConfigParser.ConfigParser()
        config.read('config.ini')

        email = config.get('login', 'email')
        password = config.get('login', 'password')
        try:
            auth_token = config.get('login', 'auth_token')
        except:
            auth_token = False
            print "No auth token could be found"

        print "Logging into Google Play Music as", email
        logged_in = False
        bad_auth = False
        while not logged_in:
            if not auth_token or bad_auth:
                self.api = Mobileclient()
                login = self.api.login(email, password,
                                       Mobileclient.FROM_MAC_ADDRESS)
                if not login:
                    print "Login failed, check your credentials."
                    sys.exit()

                # Save the auth token for later
                with open('config.ini', 'w+') as f:
                    config.set('login', 'auth_token',
                               self.api.session._authtoken)
                    config.write(f)
                    f.close()
                    print "Saved auth token for later."

                logged_in = True
            else:
                print "Found an auth token, trying it."
                self.api = Mobileclient()
                self.api.session._authtoken = auth_token
                self.api.session.is_authenticated = True
                try:
                    # Test the auth token
                    self.api.get_registered_devices()
                    logged_in = True
                except:
                    # Failed
                    print "Bad auth token, manually signing in."
                    bad_auth = True
        print "Successfully logged in as", email

        if action != 'reset_genres':
            print "Loading data."
            self.playlists = self.api.get_all_playlists()
            self.content = self.api.get_all_user_playlist_contents()
            self.root_genres, self.child_genres = self.load_genres()
            print "Data successfully loaded."

    def create_or_retrieve_playlists(self, playlists):
        """ Helper function to create or retrieve playlist IDs for a given agg_lists

            Input: List of playlist names
            Output: Dict of playlist names and IDs
        """
        if type(playlists) is not list:
            print "Stop passing non-lists to this function."
            sys.exit()

        agg_lists = [
            p for p in self.content
            if p.get('type') == 'USER_GENERATED' and p.get('name') in playlists
        ]

        # Get all playlist IDs
        agg_playlists = {}
        existing_playlists = [playlist['name'] for playlist in agg_lists]
        for name in playlists:
            if name not in existing_playlists:
                print "Playlist not found, creating", name
                agg_playlists[name] = self.api.create_playlist(name)
                self.api.edit_playlist(agg_playlists[name], public=True)
            else:
                print "Playlist found", name + ", retrieving ID."
                playlist_id = [
                    p['id'] for p in agg_lists if p.get('name') == name
                ][0]
                agg_playlists[name] = playlist_id
                # self.api.edit_playlist(agg_playlists[name], public=True)

        return agg_playlists

    def load_genres(self, reset=False):
        """ Load all genres
        """
        # Get the root genres
        if os.path.isfile(ROOT_GENRE_FILE):
            print "Found a root genres file."
            if reset:
                root_genres = self.api.get_genres()

                with open(ROOT_GENRE_FILE, 'w') as fp:
                    pickle.dump(root_genres, fp)
                print "Root genres have been reset."
            else:
                with open(ROOT_GENRE_FILE) as fp:
                    root_genres = pickle.load(fp)
        else:
            print "Couldn't find a root genres file, retrieving data."
            root_genres = self.api.get_genres()

            with open(ROOT_GENRE_FILE, 'w') as fp:
                pickle.dump(root_genres, fp)

            print "Root genres file created."

        # Get the child genres
        if os.path.isfile(CHILD_GENRE_FILE):
            print "Found a child genres file."
            if reset:
                child_genres = {}

                for genre in root_genres:
                    children = self.api.get_genres(genre['id'])
                    child_names = []
                    for child in children:
                        child_names.append(child['name'])
                    child_genres[genre['id']] = child_names

                with open(CHILD_GENRE_FILE, 'w') as fp:
                    pickle.dump(child_genres, fp)
                print "Child genres have been reset."
            else:
                with open(CHILD_GENRE_FILE) as fp:
                    child_genres = pickle.load(fp)
        else:
            print "Couldn't find a child genres file, retrieving data."
            child_genres = {}

            for genre in root_genres:
                children = self.api.get_genres(genre['id'])
                child_names = []
                for child in children:
                    child_names.append(child['name'])
                child_genres[genre['id']] = child_names

            with open(CHILD_GENRE_FILE, 'w') as fp:
                pickle.dump(child_genres, fp)
            print "Child genres file created."

        return root_genres, child_genres

    def delete_empty_playlists(self):
        """ Delete ALL empty playlists. Be careful with this.
        """
        playlists = self.content
        for playlist in playlists:
            if len(playlist['tracks']
                   ) == 0 and playlist['name'] != AGGREGATE_PLAYLIST_NAME:
                self.api.delete_playlist(playlist['id'])
                print "Deleted", playlist['name']

    def create_playlists(self):
        """ Create all needed playlists
        """
        print "Creating/updating playlists."
        self.create_or_retrieve_playlists(
            [AGGREGATE_PLAYLIST_NAME, SHARED_PLAYLIST_NAME])
        self.create_or_retrieve_playlists(
            [PLAYLIST_PREFIX + genre for genre in GENRE_PLAYLISTS.values()])

    def get_playlist_urls(self):
        """ Get all gopma playlist URLS
        """
        urls = {}
        for playlist in self.playlists:
            if PLAYLIST_PREFIX in playlist['name'] and playlist[
                    'type'] == 'USER_GENERATED':
                urls[playlist[
                    'name']] = "https://play.google.com/music/playlist/" + playlist[
                        'shareToken']
        return urls

    def get_playlist_id(self, name):
        """ Get the playlist ID for a given playlist name
        """
        playlist = [p for p in self.playlists if p.get('name') == name][0]
        return playlist['id']

    def get_share_token(self, playlist_id):
        """ Get the share token for a given playlist ID
        """
        playlist = [p for p in self.playlists if p.get('id') == playlist_id]
        return playlist[0]['shareToken']

    def get_playlist_tracks(self, playlist_id):
        """ Get the tracks for a specified playlist id
        """
        return [p for p in self.content
                if p.get('id') == playlist_id][0]['tracks']

    def get_parent_genre_id(self, genre_name):
        """ Get the parent id for a given genre name
        """
        # Check the root genres first
        for genre in self.root_genres:
            if genre_name == genre['name']:
                return genre['id']

        # Check children genres
        for gid, genres in self.child_genres.items():
            for genre in genres:
                if genre == genre_name:
                    return gid

    def wipe_all_playlists(self):
        """ Wipe all Gopma playlists
        """
        for playlist in self.playlists:
            if PLAYLIST_PREFIX in playlist[
                    'name'] and SHARED_PLAYLIST_NAME not in playlist['name']:
                print "Wiping playlist: ", playlist['name']
                self.wipe_playlist(playlist['id'])

    def wipe_playlist(self, playlist_id):
        """ Wipe a given playlist
        """
        playlist_tracks = self.get_playlist_tracks(playlist_id)
        song_ids = [track['id'] for track in playlist_tracks]
        self.api.remove_entries_from_playlist(song_ids)

    def reset_daily_playlists(self):
        """ Reset the daily playlists
        """
        # Get playlists
        agg_playlists = self.create_or_retrieve_playlists([TODAY, YESTERDAY])
        yest_id = agg_playlists[YESTERDAY]
        today_id = agg_playlists[TODAY]

        # Wipe yesterday
        print "Wiping yesterday's playlist."
        self.wipe_playlist(yest_id)

        # Copy today to yesterday
        print "Copying", TODAY, "to", YESTERDAY
        today_tracks = self.get_playlist_tracks(today_id)
        self.api.add_songs_to_playlist(yest_id,
                                       [t['trackId'] for t in today_tracks])

        # Wipe today
        print "Wiping today's playlist."
        self.wipe_playlist(today_id)

    def update_group_playlist(self):
        """ Update the big group aggregate and the daily playlist with any new shared songs
        """
        # Get the aggregate playlist songs
        agg_token = self.get_share_token(
            self.get_playlist_id(AGGREGATE_PLAYLIST_NAME))
        agg_playlists = [
            p for p in self.playlists if p.get('type') == 'USER_GENERATED'
            and p.get('shareToken') == agg_token
        ]
        agg_id = agg_playlists[0]['id']

        # Get tracks
        agg_tracks = self.api.get_shared_playlist_contents(agg_token)
        agg_tracks_ids = [track['trackId'] for track in agg_tracks]
        print "Updating group playlists."

        # Get the playlists we want to update with
        shared_lists = [
            p for p in self.playlists if p.get('name') == SHARED_PLAYLIST_NAME
        ]

        for playlist in shared_lists:
            shared_tracks = self.api.get_shared_playlist_contents(
                playlist['shareToken'])
            print "\nRetrieving from", playlist[
                'name'], "by", playlist['ownerName'] + ":"

            # Add songs to aggregate playlist
            if len(shared_tracks) == 0:
                print "<< Playlist is empty. >>"
            else:
                no_new = True
                for track in shared_tracks:
                    if track['trackId'] not in agg_tracks_ids:
                        # Add to giant aggregate playlist
                        self.api.add_songs_to_playlist(agg_id,
                                                       track['trackId'])
                        # Add to daily playlist
                        self.api.add_songs_to_playlist(
                            self.get_playlist_id(TODAY), track['trackId'])
                        # Add to genre relevant playlist
                        self.api.add_songs_to_playlist(
                            self.get_playlist_id(
                                PLAYLIST_PREFIX +
                                GENRE_PLAYLISTS[self.get_parent_genre_id(
                                    track['track']['genre'])]),
                            track['trackId'])
                        title = track['track']['title'].encode(
                            'ascii', 'ignore')
                        artist = track['track']['artist'].encode(
                            'ascii', 'ignore')
                        print "+", title, "by", artist, "has been added."
                        no_new = False
                if no_new:
                    print "<< There are no new tracks to be added from this playlist. >>"

        print "Finished updating group playlists."

    def update_songs(self):
        """ Update the database with song information
        """
        # Connect to the database
        config = ConfigParser.ConfigParser()
        config.read('config.ini')

        dbname = config.get('database', 'dbname')
        dbuser = config.get('database', 'user')
        dbhost = config.get('database', 'host')
        dbpass = config.get('database', 'password')

        try:
            conn = psycopg2.connect("dbname=" + dbname + " user="******" host=" + dbhost + " password="******"<< Could not connect to the db. >>"
            print e
            sys.exit()

        # Update songs
        for c in self.content:
            if c.get('type') == 'USER_GENERATED' and c.get(
                    'name') == AGGREGATE_PLAYLIST_NAME:
                songs = c.get('tracks')
                for s in songs:
                    # Song details
                    details = s['track']
                    # Date song was added
                    date_added = datetime.fromtimestamp(
                        int(s.get('creationTimestamp')) / 1000000)
                    # Values to save
                    values = [
                        str(s.get('trackId')),
                        str(details.get('title').encode('UTF-8', 'ignore')),
                        str(details.get('artist').encode('UTF-8', 'ignore')),
                        str(details.get('album').encode('UTF-8', 'ignore')),
                        str(details.get('genre')), date_added
                    ]
                    # SQL query
                    insert_song = "INSERT INTO playlists_song VALUES (%s, %s, %s, %s, %s, %s) ON CONFLICT (tid) DO NOTHING;"
                    # Save to DB
                    self.commit_changes(conn, cur, insert_song, values)

        print "Songs successfully updated."
        # Close connection
        cur.close()
        conn.close()

    def commit_changes(self, conn, cur, query, values):
        try:  # Commit our changes made
            cur.execute(query, values)
            conn.commit()
        except psycopg2.Error as exc:
            print exc
            sys.exit()
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

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

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

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

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

        print "Authenticated"
        print ""

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

        plid = ""

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

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

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

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

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

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

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

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

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

            if not song_id:
                failed_files += 1
                continue

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

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

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

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

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

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

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

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

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

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
#We're going to want to check to make sure that this name isn't already used for a playlist
users_playlists_names = []
for user_playlist in users_playlists:
    users_playlists_names.append(user_playlist["name"])

#Start this number at 2 since that's most likely what a human would do (playlist, playlist2, playlist3, etc)
appendable_num = 2
while playlist_name in users_playlists_names:
    playlist_name = playlist_root_name + " " + str(appendable_num)
    appendable_num = appendable_num + 1

#Once that loop finishes, playlist_name will be a uniquie-to-user playlist name, and we can go ahead and create that playlist.
#So create the actual playlist and keep its id so we can add songs to it easily later
playlist_id = mc.create_playlist(name=playlist_name,
                                 description="A playlist of nostalgic songs",
                                 public=False)

#Present some interesting stats to the user about the content on their account
print(str(len(owned_songs)) + " songs on account.")

#Begin looping through the list of songs from billboard.com
for song_to_add in songs_to_add:

    #Perform the search with the specified criteria
    artist_name = song_to_add[0]
    song_title = song_to_add[1]

    song_already_in_library = 0
    library_song_id = None
Example #45
0
# If "Uncategorized" playlist already exists, remove all songs from it.
# Otherwise create the playlist.
if uncategorized_lst:
    uncategorized_playlist = uncategorized_lst[0]
    if 'tracks' in uncategorized_playlist:
        old_uncategorized_songs_set = {
            song['id']
            for song in uncategorized_playlist['tracks']
        }
        old_uncategorized_songs_lst = list(old_uncategorized_songs_set)
        api.remove_entries_from_playlist(old_uncategorized_songs_lst)
        print("Cleared all songs from uncategorized playlist named",
              secret.UNCATEGORIZED)
else:
    api.create_playlist(secret.UNCATEGORIZED)
    print("Created playlist for uncategorized songs, named",
          secret.UNCATEGORIZED)

# If "Category A"playlist does not exist, create it
if not category_a_lst:
    api.create_playlist(secret.CATEGORY_A)
    print("Created playlist named", secret.CATEGORY_A)

# If "Category B"playlist does not exist, create it
if not category_b_lst:
    api.create_playlist(secret.CATEGORY_B)
    print("Created playlist named", secret.CATEGORY_B)

print("Finding uncategorized songs...")
playlists = api.get_all_user_playlist_contents()
Example #46
0
    for i in allcontents:
        if i['name'] == playlist_name:
            playlist_id = i['id']
            if delete_old == True:
                print(('Deleting old playlist {0}'.format(playlist_name)))
                print(('Playlist ID: {0}'.format(playlist_id)))
                api.delete_playlist(playlist_id)
            else:
                exists = True
                existing_tracks = i['tracks']

    if exists == False:
        print(('Creating playlist {0}'.format(playlist_name)))
        playlist_id = api.create_playlist(playlist_name,
                                          description=None,
                                          public=False)
        print(('Playlist ID: {0}'.format(playlist_id)))
        existing_tracks = []

    if exists == False:
        print(('Creating playlist {0}'.format(playlist_name)))
        playlist_id = api.create_playlist(playlist_name,
                                          description=None,
                                          public=False)
        print(('Playlist ID: {0}'.format(playlist_id)))
        existing_tracks = []

    existing_nids = []
    existing_bands = defaultdict(int)
    for j in existing_tracks:
#[artist name, album name, song id, isthumbsup, tracks to ignore]
slow = [['Artist 1', 'Album 1', 0, False, []],
        ['Artist 2', 'Album 2', 0, False, []],
        ['Artist 3', 'Album 3', 0, False, []]]
fast = [['Artist 4', 'Album 4', 0, False, []],
        ['Artist 5', 'Album 5', 0, False, []],
        ['Artist 6', 'Album 6', 0, False, []]]
#auth=Mobileclient.is_authenticated()
if (logged_in) == True:
    print("Log In Successful")
songsTooBig = api.get_all_songs(incremental=False,
                                include_deleted=None,
                                updated_after=None)
#print(len(songs))
print("Song data recieved")
fastId = api.create_playlist('dayFASTList', description=None, public=False)
slowId = api.create_playlist('daySLOWList', description=None, public=False)
songs = []
for song in songsTooBig:
    #print(song['rating'])
    yes = False
    try:
        if song['playCount'] < 7:
            yes = True
        else:
            yes = False
    except:
        song['playCount'] = 0
        yes = True
    if yes:
        try:
from gmusicapi import Mobileclient

client = Mobileclient()
assert client.login('*****@*****.**', PASSWORD, Mobileclient.FROM_MAC_ADDRESS)
tracks = client.get_all_songs()
genres_to_merge = {'Alternative Rock', 'Alt. Rock'}
playlist_track_ids = [t['id'] for t in tracks if t['genre'] in genres_to_merge]
print "Creating playlist with %d tracks" % len(playlist_track_ids)
playlist_id = client.create_playlist('Alt Rock')
client.add_songs_to_playlist(playlist_id, playlist_track_ids)
Example #49
0
    if path_data[path_piece] == 'user':
        spotify_user_id = path_data[path_piece + 1]
    if path_data[path_piece] == 'playlist':
        spotify_playlist_id = path_data[path_piece + 1]

# authenticate
gapi = Mobileclient()
logged_in = gapi.login(g_username, g_password, Mobileclient.FROM_MAC_ADDRESS)
client_credentials_manager = spotipy.oauth2.SpotifyClientCredentials(
    client_id=SPOTIFY_CLIENT_ID, client_secret=SPOTIFY_CLIENT_SECRET)
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

# get playlist
playlist = sp.user_playlist(spotify_user_id, spotify_playlist_id)
track_response = playlist['tracks']
gplaylist = []

for song in track_response['items']:
    song_search_string = "%s - %s - %s" % (song['track']['artists'][0]['name'],
                                           song['track']['name'],
                                           song['track']['album']['name'])
    song_result = gapi.search(song_search_string)
    gplaylist.append(song_result['song_hits'][0]['track']['storeId'])

if g_playlist_name == '':
    g_playlist_name = playlist['name']

playlist_id = gapi.create_playlist(g_playlist_name, 'Imported From Spotify')

gapi.add_songs_to_playlist(playlist_id, gplaylist)
Example #50
0
class Gmusic(object):
    """Class to handle Google Music-related functionality"""
    def __init__(self, bot):
        """ init """
        self.bot = bot
        self.mob = Mobileclient()

    def login(self,
              username,
              password,
              android_id=Mobileclient.FROM_MAC_ADDRESS):
        """ login method """
        self.mob.login(username, password, android_id)
        return self.mob.is_authenticated()

    def search(self, searchterms):
        """ search for stuff """
        hits = self.mob.search("{0}".format(searchterms))
        return hits

    def create_playlist(self, name, song_ids, public=True):
        """
        create new playlist named 'name', containing songs with 'song_id'
        """
        playlist_id = self.mob.create_playlist(name,
                                               description="Bot Playlist",
                                               public=public)
        self.mob.add_songs_to_playlist(playlist_id, song_ids)
        return playlist_id

    def _make_playlist_share_link(self, share_token):
        base_share_url = "https://play.google.com/music/playlist"
        return "{}/{}".format(base_share_url, share_token)

    def share_playlist(self, playlist_id):
        try:
            [share_token] = [
                plist['shareToken'] for plist in self.mob.get_all_playlists()
                if plist['id'] == playlist_id
            ]
            return self._make_playlist_share_link(share_token)
        except ValueError:
            return "Cannot find playlist"

    def get_best_song_match(self, artist, title):
        hits = self.search("{0} {1}".format(artist, title))
        tracks = self.filter_to_song_minimum_info(self.get_songs(hits))
        similarities = [(similarity(track['artist'], artist, track['title'],
                                    title), track) for track in tracks]

        sorted_tracks = sorted(similarities, key=lambda k: k[0])

        best_track = None
        if len(sorted_tracks) > 0:
            best_track = sorted_tracks[0][1]
        return best_track

    def get_best_album_match(self, artist, album):
        hits = self.search("{0} {1}".format(artist, album))
        albums = self.get_albums(hits)
        similarities = [(similarity(a['artist'], artist, a['album'], album), a)
                        for a in albums]

        sorted_albums = sorted(similarities, key=lambda k: k[0])

        if len(sorted_albums) == 0:
            return []

        best_album = sorted_albums[0][1]
        album_info = self.mob.get_album_info(best_album['albumId'])
        store_ids = [t['storeId'] for t in album_info['tracks']]
        print("Store ids in best_album_match: {0}".format(store_ids))
        return store_ids

    def format_best_match(self, artist, title):
        track = self.get_best_song_match(artist, title)
        share_base_url = 'https://play.google.com/music/m/'

        return "{0} {1} {2} - {3}{4}".format(track['artist'], track['album'],
                                             track['title'], share_base_url,
                                             track['storeId'])

    def get_albums(self, results):
        albums = [album.get('album', None) for album in results['album_hits']]
        album_details = [{
            'artist': a['artist'],
            'album': a['name'],
            'albumId': a['albumId']
        } for a in albums]
        return album_details

    def get_songs(self, results):
        return [song.get('track', None) for song in results['song_hits']]

    def filter_to_song_minimum_info(self, results):
        return [{
            'artist': song.get('artist', None),
            'album': song.get('album', None),
            'title': song.get('title', None),
            'storeId': song.get('storeId', None)
        } for song in results]

    def convert_spotify_embed_to_gmusic(self, url):
        s_list = SpotifyPlaylist(url)
        title = s_list.title
        best_matches = [
            self.get_best_song_match(i.artist, i.track) for i in s_list.items
        ]
        filtered_matches = [i for i in best_matches if i is not None]
        store_ids = [i.get('storeId') for i in filtered_matches]
        new_plist = self.create_playlist(title, store_ids)
        return self.share_playlist(new_plist)

    def convert_hbih_to_gmusic(self, url):
        hbih_list = HBIHPlaylist(url)
        title = hbih_list.title
        store_ids = []
        for item in hbih_list.items:
            album_store_ids = self.get_best_album_match(item[0], item[1])
            print("Adding store ids: {0}".format(album_store_ids))
            store_ids.extend(album_store_ids)

        store_id_set = IndexedSet(store_ids)
        no_dupes_store_ids = list(store_id_set)
        new_plist = self.create_playlist(title, no_dupes_store_ids[0:1000])
        return self.share_playlist(new_plist)

    def create_playlist_from_song_names(self, artist, songs):
        year = datetime.datetime.now().year
        title = "{} setlist ({})".format(artist, year)
        best_matches = [self.get_best_song_match(artist, s) for s in songs]
        filtered_matches = [i for i in best_matches if i is not None]
        store_ids = [i.get('storeId') for i in filtered_matches]
        new_plist = self.create_playlist(title, store_ids)
        return self.share_playlist(new_plist)

    def get_newest_playlists(self, count=5):
        """ return 'count' newest playlists """
        all_plists = self.mob.get_all_playlists()
        sorted_plists = sorted(all_plists,
                               key=lambda k: k['lastModifiedTimestamp'],
                               reverse=True)
        if count > 0:
            newest_plists = sorted_plists[:count]
        else:
            newest_plists = sorted_plists
        info = [{
            'name': p['name'],
            'share': self._make_playlist_share_link(p['shareToken'])
        } for p in newest_plists]
        return info

    def get_all_playlists(self):
        """ return all playlists """
        return self.get_newest_playlists(0)  # 0 = return everything

    def find_playlists(self, searchterm):
        """ find all playlists that have a name containing 'searchterm' """
        all_plists = self.get_all_playlists()
        all_matches = all_plists
        all_terms = searchterm.split(' ')
        for term in all_terms:
            all_matches = [
                p for p in all_matches
                if p['name'].lower().find(term.lower()) != -1
            ]
        return all_matches
Example #51
0
    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(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)
    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

playlist_id = mc.create_playlist(playlist_name)
mc.add_songs_to_playlist(playlist_id, track_ids)
print 'Playlist "{}" successfully added to Google Music with {} songs'.format(playlist_name, hits)
Example #53
0
def allaccessimport(playlist=None,
                    username=None,
                    password=None,
                    dry_run=False):
    """
    Exports a Spotify playlist to stdout or csv.
    """

    if not username or not password:
        raise CommandError(
            "Username and password must be provided as either command-line " +
            "argument or in the application configuration file.")

    playlist_name = playlist
    playlist_description = ""
    if playlist:
        playlist_name = os.path.basename(playlist_name)
        playlist_name = os.path.splitext(playlist_name)[0]
    logging.debug("Playlist name will be: {}".format(playlist_name))

    api = Mobileclient(False, False)
    logged_in = api.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
    if not logged_in:
        raise CommandError(
            'Error. Unable to login to Google Music All Access.')

    playlist_ref = None
    currenttracks = None

    failed_tracks = list()
    songs_added = 0
    total = 0

    stream = open(playlist, "rb") if playlist else sys.stdin

    for input_line in stream:
        input_line = input_line.strip()

        # Lazily search the beginning of the file for a Playlist name
        if input_line.startswith("#"):
            data = input_line[1:]
            parts = [x.strip() for x in data.split(":", 1)]

            if len(parts) == 2:
                if parts[0] == "Playlist":
                    playlist_name = parts[1]
                elif parts[0] == "Description":
                    playlist_description = parts[1]

            continue

        if not playlist_ref:
            if not playlist_name:
                raise CommandError(
                    "A playlist name was not given and it was not found " +
                    "in the file either. Can't continue.")
            else:
                playlist_ref, currenttracks = get_playlist(api, playlist_name)
                if not playlist_ref and not dry_run:
                    sys.stderr.write('Playlist not found. Creating new.\n')
                    playlist_ref = api.create_playlist(
                        playlist_name, description=playlist_description)
                yield 'Going to update playlist {0} ({1})\n'.format(
                    playlist_name, playlist_ref)

        trackinfo = list(csv.reader([input_line], quoting=csv.QUOTE_ALL))[0]

        if trackinfo[0] == 'Track' and trackinfo[1] == 'Artist':
            yield 'Skipping header.'
            continue

        search_term = "{0} {1}".format(trackinfo[0], trackinfo[1])
        total = total + 1
        newtrackid, error_reason = search_track(api, search_term,
                                                currenttracks)
        if newtrackid:
            if not dry_run:
                #print("Add to {} song {}".format(playlist_ref, newtrackid))
                api.add_songs_to_playlist(playlist_ref, [newtrackid])
            songs_added = songs_added + 1
        else:
            failed_tracks.append(trackinfo)
        sys.stderr.write("Searching {}...{}\n".format(search_term,
                                                      error_reason))

    yield "{0} songs added out of {1}. {2} Failed.".format(
        songs_added, total, total - songs_added)

    yield "Failed tracks:"
    for line in failed_tracks:
        print "  ", line