コード例 #1
0
class GoogleMusicApi():
    def __init__(self):
        self.xbmc = sys.modules["__main__"].xbmc
        self.xbmcgui = sys.modules["__main__"].xbmcgui
        self.xbmcplugin = sys.modules["__main__"].xbmcplugin

        self.settings = sys.modules["__main__"].settings
        self.language = sys.modules["__main__"].language
        self.dbg = sys.modules["__main__"].dbg
        self.common = sys.modules["__main__"].common
        self.storage = sys.modules["__main__"].storage

        self.gmusicapi = Api()
        self.login = GoogleMusicLogin.GoogleMusicLogin(self.gmusicapi)

    def getPlaylistSongs(self, playlist_id, forceRenew=False):
        if not self.storage.isPlaylistFetched(playlist_id) or forceRenew:
            self.updatePlaylistSongs(playlist_id)

        songs = self.storage.getPlaylistSongs(playlist_id)

        return songs

    def getPlaylistsByType(self, playlist_type, forceRenew=False):
        if forceRenew:
            self.updatePlaylists(playlist_type)

        playlists = self.storage.getPlaylistsByType(playlist_type)
        if len(playlists) == 0 and not forceRenew:
            self.updatePlaylists(playlist_type)
            playlists = self.storage.getPlaylistsByType(playlist_type)

        return playlists

    def getSong(self, song_id):
        return self.storage.getSong(song_id)

    def updatePlaylistSongs(self, playlist_id):
        api_songs = []

        self.login.login()
        if playlist_id == 'all_songs':
            api_songs = self.gmusicapi.get_all_songs()
        else:
            api_songs = self.gmusicapi.get_playlist_songs(playlist_id)

        self.storage.storeApiSongs(api_songs, playlist_id)

    def updatePlaylists(self, playlist_type):
        self.login.login()
        playlists = self.gmusicapi.get_all_playlist_ids(playlist_type=="auto", playlist_type=="instant", playlist_type=="user", always_id_lists=True)
        self.storage.storePlaylists(playlists[playlist_type], playlist_type)

    def getSongStreamUrl(self, song_id):
        self.login.login()
        stream_url = self.gmusicapi.get_stream_url(song_id)
        #self.storage.updateSongStreamUrl(song_id, stream_url)

        return stream_url
コード例 #2
0
class GoogleMusicApi():
    def __init__(self):
        self.storage = sys.modules["__main__"].storage

        self.gmusicapi = Api(debug_logging=False)
        self.login = GoogleMusicLogin.GoogleMusicLogin(self.gmusicapi)

    def getPlaylistSongs(self, playlist_id, forceRenew=False):

        if playlist_id == 'thumbsup':
            return self.storage.getThumbsup()
        if playlist_id == 'lastadded':
            return self.storage.getLastadded()
        if playlist_id == 'mostplayed':
            return self.storage.getMostplayed()
        if playlist_id == 'freepurchased':
            return self.storage.getFreepurchased()

        if not self.storage.isPlaylistFetched(playlist_id) or forceRenew:
            self.updatePlaylistSongs(playlist_id)

        songs = self.storage.getPlaylistSongs(playlist_id)

        return songs

    def getPlaylistsByType(self, playlist_type, forceRenew=False):
        if playlist_type == 'auto':
            return [['thumbsup', 'Highly Rated'], ['lastadded', 'Last Added'],
                    ['freepurchased', 'Free and Purchased'],
                    ['mostplayed', 'Most Played']]

        if forceRenew:
            self.updatePlaylists(playlist_type)

        playlists = self.storage.getPlaylistsByType(playlist_type)
        if len(playlists) == 0 and not forceRenew:
            self.updatePlaylists(playlist_type)
            playlists = self.storage.getPlaylistsByType(playlist_type)

        return playlists

    def getSong(self, song_id):
        return self.storage.getSong(song_id)

    def updatePlaylistSongs(self, playlist_id):
        api_songs = []

        self.login.login()
        if playlist_id == 'all_songs':
            api_songs = self.gmusicapi.get_all_songs()
        else:
            api_songs = self.gmusicapi.get_playlist_songs(playlist_id)

        if api_songs:
            self.storage.storeApiSongs(api_songs, playlist_id)

    def updatePlaylists(self, playlist_type):
        self.login.login()
        playlists = self.gmusicapi.get_all_playlist_ids(playlist_type)
        self.storage.storePlaylists(playlists[playlist_type], playlist_type)

    def getSongStreamUrl(self, song_id):
        self.login.login()
        stream_url = self.gmusicapi.get_stream_url(song_id)
        #self.storage.updateSongStreamUrl(song_id, stream_url)

        return stream_url

    def getFilterSongs(self, filter_type, filter_criteria):
        songs = self.storage.getFilterSongs(filter_type, filter_criteria)

        return songs

    def getCriteria(self, criteria):
        return self.storage.getCriteria(criteria)

    def getSearch(self, query):
        return self.storage.getSearch(query)

    def clearCache(self):
        self.storage.clearCache()
        self.login.clearCookie()

    def clearCookie(self):
        self.login.clearCookie()
コード例 #3
0
class GoogleMusicApi():
    def __init__(self):
        self.storage = sys.modules["__main__"].storage

        self.gmusicapi = Api(debug_logging=False)
        self.login = GoogleMusicLogin.GoogleMusicLogin(self.gmusicapi)

    def getPlaylistSongs(self, playlist_id, forceRenew=False):

        if playlist_id == 'thumbsup':
            return self.storage.getThumbsup()
        if playlist_id == 'lastadded':
            return self.storage.getLastadded()
        if playlist_id == 'mostplayed':
            return self.storage.getMostplayed()
        if playlist_id == 'freepurchased':
            return self.storage.getFreepurchased()

        if not self.storage.isPlaylistFetched(playlist_id) or forceRenew:
            self.updatePlaylistSongs(playlist_id)

        songs = self.storage.getPlaylistSongs(playlist_id)

        return songs

    def getPlaylistsByType(self, playlist_type, forceRenew=False):
        if playlist_type == 'auto':
            return [['thumbsup','Highly Rated'],['lastadded','Last Added'],['freepurchased','Free and Purchased'],['mostplayed','Most Played']]

        if forceRenew:
            self.updatePlaylists(playlist_type)

        playlists = self.storage.getPlaylistsByType(playlist_type)
        if len(playlists) == 0 and not forceRenew:
            self.updatePlaylists(playlist_type)
            playlists = self.storage.getPlaylistsByType(playlist_type)

        return playlists

    def getSong(self, song_id):
        return self.storage.getSong(song_id)

    def updatePlaylistSongs(self, playlist_id):
        api_songs = []

        self.login.login()
        if playlist_id == 'all_songs':
            api_songs = self.gmusicapi.get_all_songs()
        else:
            api_songs = self.gmusicapi.get_playlist_songs(playlist_id)
 
        if api_songs:
            self.storage.storeApiSongs(api_songs, playlist_id)

    def updatePlaylists(self, playlist_type):
        self.login.login()
        playlists = self.gmusicapi.get_all_playlist_ids(playlist_type)
        self.storage.storePlaylists(playlists[playlist_type], playlist_type)

    def getSongStreamUrl(self, song_id):
        self.login.login()
        stream_url = self.gmusicapi.get_stream_url(song_id)
        #self.storage.updateSongStreamUrl(song_id, stream_url)

        return stream_url

    def getFilterSongs(self, filter_type, filter_criteria):
        songs = self.storage.getFilterSongs(filter_type, filter_criteria)

        return songs

    def getCriteria(self, criteria):
        return self.storage.getCriteria(criteria)
        
    def getSearch(self, query):
        return self.storage.getSearch(query)

    def clearCache(self):
        self.storage.clearCache()
        self.login.clearCookie()

    def clearCookie(self):
        self.login.clearCookie()
コード例 #4
0
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.api = Api()
        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.api.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""


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

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


    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 "Synching playlist: %s" % filename
        if title not in self.playlists['user']:
            print "   didn't exist... creating..."
            self.playlists['user'][title] = [self.api.create_playlist(title)]
        print ""

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

        # Sanity check max 1000 songs per playlist
        if len(local_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 local_songs[MAX_SONGS_IN_PLAYLIST:]

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

        for fn, song in local_songs:
            if self.file_already_in_list(song, goog_songs):
                existing_files += 1
                continue
            print ""
            print "Adding: %s" % os.path.basename(fn)
            online = self.find_song(song)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                if not os.path.isfile(fn):
                    print "    Attempted to upload non-existent file", song
                    continue
                attempts = 0
                result = []
                while not result and attempts < MAX_UPLOAD_ATTEMPTS_PER_FILE:
                    print "   uploading... (may take a while)"
                    attempts += 1
                    try:
                        result = self.api.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.api.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"

            if not song_id:
                failed_files += 1
                continue

            added = self.api.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 s in goog_songs:
                print ""
                print "Removing: %s" % s['title']
                self.api.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_songs_from_playlist(self, filename):
        ext = os.path.splitext(filename)[1].lower()
        if ext == '.m3u':
            return list(self._get_songs_from_m3u_playlist(filename))
        elif ext == '.xml':
            return list(self._get_songs_from_itunes_playlist(filename))

    def _get_songs_from_m3u_playlist(self, filename):
        with codecs.open(filename, encoding='utf-8') as f:
            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
                yield (path, self.get_id3_tag(path))

    def _get_songs_from_itunes_playlist(self, filename):
        plist = plistlib.readPlist(filename)
        for track_id, track in plist['Tracks'].iteritems():
            p = urlparse.urlparse(track['Location'])
            path = os.path.abspath(os.path.join(p.netloc, p.path))
            yield (path, {
                'name': track['Name'],
                #'artist': track['Artist'],
                'album': track['Album'],
                'track': track['Track Number'] if 'Track Number' in track else 0,
                'disc': track['Disc Number'] if 'Disc Number' in track else 1
                })

    def file_already_in_list(self, song, goog_songs):
        i = 0
        while i < len(goog_songs):
            if self.tag_compare(goog_songs[i], song):
                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['name'] = 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, song):
        results = self.api.search(song['name'])
        # NOTE - dianostic print here to check results if you're creating duplicates
        #print results['song_hits']
        #print "%s ][ %s ][ %s ][ %s" % (tag['title'], tag['artist'], tag['album'], tag['track'])
        return find_in_list(results['song_hits'], song)

    def tag_compare(self, g_song, tag):
        # If a google result has no track, google doesn't return a field for it
        if 'track' not in g_song:
            g_song['track'] = 0
        #g_song['artist'].lower() == tag['artist'].lower() and\
        return g_song['name'].lower() == tag['name'].lower() and\
               g_song['album'].lower() == tag['album'].lower() and\
               g_song['track'] == tag['track']

    def delete_song(self, sid):
        self.api.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('\\', '/'))
コード例 #5
0
class GoogleMusicApi():
    def __init__(self):
        self.xbmc = sys.modules["__main__"].xbmc
        self.xbmcgui = sys.modules["__main__"].xbmcgui
        self.xbmcplugin = sys.modules["__main__"].xbmcplugin

        self.settings = sys.modules["__main__"].settings
        self.language = sys.modules["__main__"].language
        self.dbg = sys.modules["__main__"].dbg
        self.common = sys.modules["__main__"].common
        self.storage = sys.modules["__main__"].storage

        self.gmusicapi = Api()
        self.login = GoogleMusicLogin.GoogleMusicLogin(self.gmusicapi)

    def getPlaylistSongs(self, playlist_id, forceRenew=False):
        if not self.storage.isPlaylistFetched(playlist_id) or forceRenew:
            self.updatePlaylistSongs(playlist_id)

        songs = self.storage.getPlaylistSongs(playlist_id)

        return songs

    def getPlaylistsByType(self, playlist_type, forceRenew=False):
        if forceRenew:
            self.updatePlaylists(playlist_type)

        playlists = self.storage.getPlaylistsByType(playlist_type)
        if len(playlists) == 0 and not forceRenew:
            self.updatePlaylists(playlist_type)
            playlists = self.storage.getPlaylistsByType(playlist_type)

        return playlists

    def getSong(self, song_id):
        return self.storage.getSong(song_id)

    def updatePlaylistSongs(self, playlist_id):
        api_songs = []

        self.login.login()
        if playlist_id == 'all_songs':
            api_songs = self.gmusicapi.get_all_songs()
        else:
            api_songs = self.gmusicapi.get_playlist_songs(playlist_id)

        self.storage.storeApiSongs(api_songs, playlist_id)

    def updatePlaylists(self, playlist_type):
        self.login.login()
        playlists = self.gmusicapi.get_all_playlist_ids(
            playlist_type == "auto",
            playlist_type == "instant",
            playlist_type == "user",
            always_id_lists=True)
        self.storage.storePlaylists(playlists[playlist_type], playlist_type)

    def getSongStreamUrl(self, song_id):
        self.login.login()
        stream_url = self.gmusicapi.get_stream_url(song_id)
        #self.storage.updateSongStreamUrl(song_id, stream_url)

        return stream_url