Example #1
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 #2
0
"""
cursor.execute(sql)
trackRows = cursor.fetchall()

playlistName = "BG Rand " + datetime.now().strftime("%Y-%m %B")

# 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)
Example #3
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 #4
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 #5
0
from gmusicapi import Mobileclient
from gmusicapi import Webclient
import json
import requests
requests.packages.urllib3.disable_warnings()
api = Mobileclient()
logged_in = api.login('*****@*****.**', 'musicatyourspeed')

playlists = api.get_all_playlists()

for i,v in enumerate(playlists):
    api.delete_playlist(v['id'])

print "All playlists deleted"
Example #6
0
def reverseplaylist(playlist_name='', repeat=False, quick=False):
    mc = Mobileclient()
    mc.__init__()

    # Find location of this script
    dir_path = os.path.dirname(os.path.realpath(__file__))

    # Check whether this is the first time the program has been run by searching the directory for the log file
    file_list = os.listdir(dir_path)

    # No log file means not run
    if '.gmusiclog.txt' not in file_list:
        print(
            '\n' +
            'This is the first time this program has been run in this folder.'
            + '\n' + 'performing initial authentication.' + '\n')

        # Autorepeat cannot be true without logfile, override if true
        repeat = False

        # Start with a bogus device ID to determine real id from error message
        devID = 'ffffffff'
        mc.perform_oauth()
        try:
            mc.oauth_login(devID)
        except Exception as e:
            error = str(e)
            IDpos = error.find('*')
            nextIDpos = error.find('\n', IDpos + 1, len(error))
            devID = error[IDpos + 2:nextIDpos]
            # Perform login
            mc.oauth_login(devID)

        # Write authentication stuff to logfile
        with open(dir_path + '/.gmusiclog.txt', 'w') as log:
            log.write(devID + '\n')
            x = datetime.datetime.now()
            timeString = (str(x.day) + '/' + str(x.month) + '/' + str(x.year) +
                          '  ' + str(x.hour) + ':' + str(x.minute) + ':' +
                          str(x.second) + '.' + str(x.microsecond))
            log.write('Initial authentication performed at ' + timeString +
                      '\n')

    # Log file exists, we will check whether the user has requested autorepeat
    else:
        print(
            '\n' +
            'This is not the first time this program has been run in this folder'
            + '\n' + 'performing login.' + '\n')

        # Open the logfile to read device id and previous playlists
        with open(dir_path + '/.gmusiclog.txt', 'r') as log:
            # Get device ID
            devID = log.readline().strip()
            # Look for the playlist name from the bottom of the list
            contents = log.read()

        # Perform login
        mc.oauth_login(devID)
        playlistLocation = contents.rfind('PLAYLIST')
        if playlistLocation != -1:
            # Define end of playlist to make defining desired playlist a little cleaner
            endOfPlaylist = contents.find('\n', playlistLocation,
                                          len(contents))
            desired_playlist = contents[playlistLocation + 10:endOfPlaylist]

        with open(dir_path + '/.gmusiclog.txt', 'a+') as log:

            # Write authentication stuff to logfile
            x = datetime.datetime.now()
            timeString = (str(x.day) + '/' + str(x.month) + '/' + str(x.year) +
                          '  ' + str(x.hour) + ':' + str(x.minute) + ':' +
                          str(x.second) + '.' + str(x.microsecond))
            log.write('Login performed at ' + timeString + '\n')

    # Get user input for desired playlist if autorepeat is not enabled
    if repeat == False and playlist_name == '':
        desired_playlist = input(
            'Name of the playlist being reversed (case sensetive): ')
    elif playlist_name != '':
        # If a name is given this overrides all else
        desired_playlist = playlist_name
    else:
        print('Autorepeat enabled, reversing playlist: ' + desired_playlist +
              '\n')

    # Establish the name of the reversed playlist
    reversed_playlist = desired_playlist + 'REVERSED'

    # Check to see whether the desired and reversed playlists exist yet
    allPlaylists = mc.get_all_playlists()
    desired_playlist_index = -1
    reversed_playlist_index = -1
    for n in allPlaylists:
        if n['name'] == reversed_playlist:
            reversed_playlist_index = n
            reversedID = n['id']
        elif n['name'] == desired_playlist:
            desired_playlist_index = n
            desiredID = n['id']

    # Desired playlist exists, so we check to see if it has also been reversed
    if desired_playlist_index != -1:
        # We cache the playlist name so that it can be automatically re-reversed next time
        with open(dir_path + '/.gmusiclog.txt', 'a+') as log:
            log.write('PLAYLIST: ' + desired_playlist + '\n')

        # Desired playlist has been reversed, we can either delete the old one before proceeding
        # or perform a quick update
        if reversed_playlist_index != -1:
            print('The ' + desired_playlist + ' playlist has been reversed.')

            # Determine whether to do a quick update or not
            if quick == True:
                print('performing quick update')
                quick_update(mc, desiredID, reversedID)
                return
            else:
                print('Performing full update\n' +
                      'Deleting the old playlist...\n')
                mc.delete_playlist(reversedID)

        # Desired playlist has not been reversed, create the reverse
        else:
            print('The ' + desired_playlist +
                  ' playlist has not been reversed, creating the reverse now.')

        # If we have got this far, the reversed playlist doesn't exist
        print('Generating reversed song list...')
        reversedID, id_list = create_new(mc, desired_playlist)
        print('Adding songs to the playlist...')
        mc.add_songs_to_playlist(reversedID, id_list)
        print('Done!')

    # No such playlist exists
    else:
        print(
            'No playlist by the name of ' + desired_playlist +
            ' found. Did you spell it correctly? A reminder here that the playlist name is case sensetive.'
        )
Example #7
0
hKey = OpenKey(HKEY_LOCAL_MACHINE, "Software\\Lattuce")
username = QueryValueEx(hKey, "GoogleUsername")[0]
password = QueryValueEx(hKey, "GooglePassword")[0]

# Log into Google
api = Mobileclient()
api.login(username, password, Mobileclient.FROM_MAC_ADDRESS)  # => True

# Reactivate
# Delete Playlist
playlists = api.get_all_playlists()
for playlist in playlists:
    if playlist['name'] == 'Reactivate':
        id_to_delete = playlist['id']
        print('Deleting Playlist ID: ', id_to_delete)
        api.delete_playlist(id_to_delete)
# Add new Playlist
playlist_id = api.create_playlist('Reactivate')
songs = api.get_all_songs()
playlistsongs = []
for song in songs:
    if 'Reactivate' in song['album']:
        print('Adding song ID: ', song['id'], 'to playlist Reactivate')
        playlistsongs.append(song['id'])
api.add_songs_to_playlist(playlist_id, playlistsongs)

# Dance etc.
# Delete Playlist
playlists = api.get_all_playlists()
for playlist in playlists:
    if playlist['name'] == 'Dance':
Example #8
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()
Example #9
0
def main():
    #### Requests user specifies update library and/or playlists
    if len(sys.argv) != 3:
        print('Specify T/F arguments for uploading and updating playlists')
        print('e.g. python ' + sys.argv[0] + ' 1 0')
        print('which would:\n--> upload new songs\n--> NOT update playlists')
        sys.exit(0)

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

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

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

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

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

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

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

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

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

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

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

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

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

                mc.add_songs_to_playlist(pid, sid)
            completed += 1
            # Console output for number of songs sorted
            sys.stdout.write("\r{}/{} processed".format(completed, total))
            sys.stdout.flush()
        print()
playlistcnx2 = mysql.connector.connect(user=(MySQLUsername), password=(MySQLPassword), host='lattuce-dc', database='music')
playlistsongcursor = playlistsongcnx.cursor()
playlistcursor = playlistcnx.cursor()
playlistcursortodelete = playlistcnxtodelete.cursor()
playlistdelcursor = playlistdelcnx.cursor()
playlistcursor1 = playlistcnx1.cursor()
playlistcursor2 = playlistcnx2.cursor()

################
# Delete playlists which dont exist in the database anymore
# TODO: Temp code until i can figure out how to truncate existing google playlists
playlists = api.get_all_playlists()
for playlist in playlists:
    id_to_delete = playlist['id']
    print("Deleting Playlist:", playlist['name'], [id_to_delete])
    api.delete_playlist(id_to_delete)
################

# Delete playlists which dont exist in the database anymore
playlists = api.get_all_playlists()
for playlist in playlists:
    print("Fround in Google:", playlist['name'])
    query = ("select Count(*) as cnt from playlist where playlist_name = '" + playlist['name'] + "'")
    playlistdelcursor.execute(query)
    row = playlistdelcursor.fetchone()
    if row[0] == 0:
        id_to_delete = playlist['id']
        print("Deleting Playlist:", playlist['name'], [id_to_delete], "because it does not exist in the database")
        api.delete_playlist(id_to_delete)
playlistdelcursor.close()
def main():
    sys.stdout = codecs.getwriter('utf8')(sys.stdout)
    sys.stderr = codecs.getwriter('utf8')(sys.stderr)

    with open('settings.json') as f:
        settings = json.load(f)

    with open('settings_schema.json') as f:
        schema = json.load(f)

    try:
        jsonschema.validate(settings, schema)
    except:
        print traceback.format_exc()
        return

    client_id = settings['client_id']
    client_secret = settings['client_secret']
    redirect_url = settings['redirect_url']
    gmusic_login = settings['gmusic_login']

    if 'gmusic_pw' not in settings:
        gmusic_pw = getpass.getpass(
            'Enter your google music password (you only need to do this once): '
        )
    else:
        gmusic_pw = base64.b64decode(settings['gmusic_pw'])

    # client credentials flow
    print 'Logging into Spotify'
    client_credentials_manager = SpotifyClientCredentials(
        client_id, client_secret)
    sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

    # gmusic controller
    print 'logging into Google music'
    gmusic = Mobileclient()
    logged_in = gmusic.login(gmusic_login, gmusic_pw,
                             Mobileclient.FROM_MAC_ADDRESS)
    if logged_in:
        settings['gmusic_pw'] = base64.b64encode(gmusic_pw)
        with open('settings.json', 'w') as f:
            json.dump(settings,
                      f,
                      sort_keys=True,
                      indent=2,
                      separators=(',', ': '))
    else:
        print 'Unable to login, check credentials'
        return

    all_gmusic_playlists = gmusic.get_all_playlists()
    errors = []
    for playlist_settings in settings['playlists']:
        # get all names and artists from the particular playlists
        username = playlist_settings['username']
        tid = playlist_settings['id']
        playlist = sp.user_playlist(username, tid)
        print 'Found spotify playlist: ' + playlist['name']
        playlist_name = 'Spotify ' + playlist['name']
        spotify_tracks = playlist['tracks']['items']
        song_names = [t['track']['name'] for t in spotify_tracks]
        artists = [t['track']['artists'][0]['name'] for t in spotify_tracks]
        if (len(artists) != len(song_names)):
            print 'Error: can\'t match up all songs to artists'
            return
        spotify_tracks = zip(song_names, artists)

        # delete existing playlists we imported
        for playlist in all_gmusic_playlists:
            if playlist['name'] == playlist_name:
                gmusic.delete_playlist(playlist['id'])

        print 'Creating Google music playlist: ' + playlist_name
        g_playlist = gmusic.create_playlist(playlist_name)
        for spotify_track in spotify_tracks:
            try:
                spotify_song_name = spotify_track[0]
                spotify_artist_name = spotify_track[1]
                songs = gmusic.search(spotify_song_name + ' ' +
                                      spotify_artist_name)['song_hits']

                found_song = False
                # if we found a song match
                if (len(songs) > 0):
                    for song in songs:
                        found_song_name = song['track']['title']
                        found_song_artist = song['track']['albumArtist']
                        fuzz_ratio_name = fuzz.partial_ratio(
                            found_song_name, spotify_song_name)
                        fuzz_ratio_artist = fuzz.partial_ratio(
                            found_song_artist, spotify_artist_name)
                        # check that it's a close match to what we are looking for
                        if (fuzz_ratio_name + fuzz_ratio_artist > 70):
                            print 'Adding: ' + spotify_song_name + ', ' + spotify_artist_name
                            gmusic.add_songs_to_playlist(
                                g_playlist, song['track']['storeId'])
                            found_song = True
                            break

                    if not found_song:
                        error = 'FuzzRatio not in threshold|spotify: ' + spotify_song_name + ',' + spotify_artist_name +\
                                '|gmusic: ' + found_song_name + ',' + found_song_artist
                        print error
                        errors.append(error)
                else:
                    error = 'Unable to add, song: ' + spotify_song_name + ', artist: ' + spotify_artist_name
                    print error
                    errors.append(error)
            except:
                error = traceback.format_exc()
                print error
                errors.append(error)

    with codecs.open('errors.log', 'w', 'utf-8') as f:
        for error in errors:
            f.write(error + '\n')
Example #12
0
class GoogleMusic:
    def __init__(self):
        self.api = Mobileclient(debug_logging=False)
        with open(path + "oauth.cred", 'w+') as tmp:
            tmp.write(settings['google']['mobileclient'])
            tmp.close()
            self.api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, tmp.name)
            os.remove(tmp.name)

    def createPlaylist(self, name, songs, public):
        playlistId = self.api.create_playlist(name=name, description=None, public=public)
        self.addSongs(playlistId, songs)
        print("Success: created playlist \"" + name + "\"")

    def addSongs(self, playlistId, songs):
        songIds = []
        songlist = list(songs)
        notFound = list()
        for i, song in enumerate(songlist):
            song = song.replace(" &", "")
            result = self.api.search(query=song, max_results=2)
            if len(result['song_hits']) == 0:
                notFound.append(song)
            else:
                songIds.append(self.get_best_fit_song_id(result['song_hits'], song))
            if i % 20 == 0:
                print(str(i) + ' searched')

        self.api.add_songs_to_playlist(playlistId, songIds)

        with open(path + 'noresults.txt', 'w', encoding="utf-8") as f:
            f.write("\n".join(notFound))
            f.close()

    def removeSongs(self, playlistId):
        pl = self.api.get_all_user_playlist_contents()
        tracks = next(x for x in pl if x['id'] == playlistId)['tracks']
        self.api.remove_entries_from_playlist([x['id'] for x in tracks])

    def getPlaylistId(self, name):
        pl = self.api.get_all_playlists()
        return next(x for x in pl if x['name'].find(name) != -1)['id']

    def get_best_fit_song_id(self, results, song):
        match_score = {}
        for res in results:
            compare = res['track']['artist'] + ' ' + res['track']['title']
            match_score[res['track']['storeId']] = difflib.SequenceMatcher(a=song.lower(), b=compare.lower()).ratio()

        return max(match_score, key=match_score.get)

    def remove_playlists(self, pattern):
        pl = self.api.get_all_playlists()
        p = re.compile("{0}".format(pattern))
        matches = [song for song in pl if p.match(song['name'])]
        print("The following playlists will be removed:")
        print("\n".join([song['name'] for song in matches]))
        print("Please confirm (y/n):")

        choice = input().lower()
        if choice[:1] == 'y':
            [self.api.delete_playlist(song['id']) for song in matches]
            print(str(len(matches)) + " playlists deleted.")
        else:
            print("Aborted. No playlists were deleted.")
Example #13
0
class MobileClientWrapper:
    def __init__(self, config):
        self.client = Mobileclient(debug_logging=False)
        login = self.client.login(config.user_name, config.password,
                                  Mobileclient.FROM_MAC_ADDRESS)
        if not login:
            raise ConnectionError(
                'MobileClientWrapper - Login Error Please Check Google Play Username and Password'
            )

    def logout(self):
        self.client.logout()

    def get_all_playlist_content(self):
        """
        :return: list of all Playlist content as dictionaries.
        """
        return self.client.get_all_user_playlist_contents()

    def create_playlist(self, new_playlist_name, description_text,
                        public_bool):
        """
        Creates a Playlist with given information and returns its id

        :param new_playlist_name: name to give new PlayList
        :param description_text: description text of new Playlist
        :param public_bool: True/False value to specify public sharing on new Playlist
        :return: playlist id
        """
        return self.client.create_playlist(new_playlist_name,
                                           description=description_text,
                                           public=public_bool)

    def delete_playlist(self, play_list_id):
        """
        Delete a Playlist with given Id

        :param play_list_id: playlist ID
        """
        self.client.delete_playlist(play_list_id)

    def add_songs_to_playlist(self, play_list_id, song_ids):
        """
        Adds given song(s) to given Playlist.

        :param play_list_id: id of the target Playlist
        :param song_ids: id(s) of the target Song to add
        :return: list of Playlist Entry ids added
        """
        return self.client.add_songs_to_playlist(play_list_id, song_ids)

    def get_track_info(self, store_track_id):
        """
        Returns information on a store track

        :param store_track_id: target TrackId
        """
        return self.client.get_track_info(store_track_id)

    def search(self, search_query):
        """
        Searches based on searchQuery
        :param search_query: query to run through music library

        :return: dictionary of hits
        """
        return self.client.search(search_query, max_results=10)
Example #14
0
from gmusicapi import Mobileclient

# google play musicのプレイリストを順に削除

mc = Mobileclient()
mc.oauth_login(mc.FROM_MAC_ADDRESS)

# google play musicのプレイリストを取得
gPlaylists = mc.get_all_playlists()

for gPlaylist in gPlaylists:
    mc.delete_playlist(gPlaylist['id'])
    print("deleted playlistName = {p}".format(p=gPlaylist['name']))
Example #15
0
                              filteredPlaylistAndContents['tracks'])

    # プレイリストから消去
    mc.remove_entries_from_playlist(
        [trackId for trackId in includeTrackIdsIter])
    break

# プレイリストの登録曲数がgoogle play musicの最大登録数よりも多い場合は
iPlaylistItems = len(iPlaylist.items)
if (iPlaylistItems > MAX_GPLAYLIST_SONGS_NUM):
    # オーバーしている旨のメッセージを出す
    print("playlistName = {p} is over max playlist song size :{n}".format(
        p=iPlaylist.itunesAttibutes['Name'], n=iPlaylistItems))
    # プレイリストが存在している場合は削除する。
    if gPlaylistId != None:
        mc.delete_playlist(gPlaylistId)
    # return
    exit()

# プレイリストが見つからなかったら新たに作成する。
if gPlaylistId == None:
    gPlaylistId = mc.create_playlist(iPlaylist.itunesAttibutes['Name'])


# google play musicのsong idを取得
def getGSongId(songName, artist, album):
    # itunesのタイトル、アルバム、アーティストに一致するgoogle play musicのトラックを取得
    foundGTrack = [
        gTrack for gTrack in gLibrary if gTrack['title'] == songName
        and gTrack['album'] == album and gTrack['artist'] == artist
    ]
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 #17
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)
Example #18
0
    allcontents = api.get_all_user_playlist_contents()
    playlist_name = 'scout'

    exists = False
    existing_tracks = []
    exists = False
    delete_old = False

    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,
Example #19
0
class LivePlaylist:
    'Class to handle logging into the GPMAA server and creating the playlist'

    def __init__(self, url, make=False):
        self.setup_logging()
        self.setlist = Setlist(url)
        self.api = Mobileclient()
        self.logged_in = self.api.login(EMAIL,
            TOKEN,
            Mobileclient.FROM_MAC_ADDRESS)
        if self.logged_in:
            self.search_for_songs()
            if make:
                self.make_playlist()

    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 info(self, msg):
        self.logger.info(msg)

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

    def make_playlist(self):
        self.songIDs = [self.resdict[s][0]['storeId'] for s in self.resdict.keys()]
        self.info("Creating playlist...")
        name = "{} - {}".format(self.setlist.artist, self.setlist.date)
        self.debug(name)
        desc = "{} live at {} on {}".format(self.setlist.artist,
            self.setlist.venue,
            self.setlist.date)
        self.debug(desc)
        self.id = self.api.create_playlist(name, desc)
        self.info("Playlist id: {}".format(self.id))
        self.debug("Song IDs {!s}".format(self.songIDs))
        self.api.add_songs_to_playlist(self.id, self.songIDs)
        return self.id

    def search_for_songs(self):
        self.info("Finding song info...")
        self.resdict = {name: [] for name in self.setlist.song_names}

        for song_name, r in self.resdict.items():
            query = "{} {}".format(self.setlist.artist, song_name)
            self.debug("Searching".ljust(20, '.') + query)
            results = self.api.search(query)['song_hits']
            results = [x['track'] for x in results]
            r.extend(results)
            self.debug('{} results found'.format(len(results)))

        # Remove songs that had 0 results
        self.resdict = {name: results for name, results in self.resdict.items() if len(results) > 0}

    def print_results(self):
        for k, r in self.resdict.items():
            self.info("{:50}|{:35}|{:25}".format("Title", "Album", "Artist"))
            for result in r:
                t = result['title']
                alb = result['album']
                art = result['artist']
                self.info("{:50}|{:35}|{:25}".format(t, alb, art))
                self.info("-" * 110)

    def delete_playlist(self):
        self.info("Deleting playlist id: %s" % self.id)
        self.api.delete_playlist(self.id)