コード例 #1
0
ファイル: mydownload.py プロジェクト: Newportboy45/mp3
 def download_by_id(self, key, upload=False):
     if self.logstack.has_key(key) and self.logstack[key]["state"] != "fail":
         return
     url = "http://www.youtube.com/watch?v=%s" % (key)
     if upload:
         print "upload google music!!!"
     self.current_key = key
     self.logstack[key] = {"path": "", "process": "", "state": "downloading"}
     result = None
     try:
         self.download([url])
     except:
         self.logstack[key]["state"] = "fail"
         return
     if upload:
         self.logstack[key]["state"] = "uploading"
         print self.logstack[key]["path"]
         path = self.logstack[key]["path"].encode("utf-8")
         api = Api()
         api.login(gpass.id, gpass.passwd)
         ids = api.get_all_playlist_ids(auto=False, instant=False)
         playlist_id = ids["user"]["youtube"]
         try:
             result = api.upload([path])
         except:
             print "upload error"
             self.logstack[key]["state"] = "fail"
             return
         if len(result):
             api.add_songs_to_playlist(playlist_id, result.values()[0])
     self.logstack[key]["state"] = "complete"
コード例 #2
0
ファイル: thunner.py プロジェクト: brainwater/thunner
def apiinit(email,password):
    api = Api()
    
    logged_in = False
    attempts = 0
    api.login(email, password)
    return api
コード例 #3
0
ファイル: models.py プロジェクト: tryba/shared-queue
 def get_google_music_api(user_id):
   api = Api()
   try:
     result = api.login(self.email, self.profile.google_music_password)
     return api, result
   except:
     user = User.objects.get(pk=user_id)
     result = api.login(user.email, user.profile.google_music_password)
     return api, result
コード例 #4
0
def init():
    api = Api() 
    
    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        email = raw_input("Google username or email: ")

        # Try to read the password from a file
        # If file doesn't exist, ask for password
        # This is useful for 2-step authentication only
        # Don't store your regular password in plain text
        try:
            pw_file = open("pass.txt")
            password = pw_file.readline()
            print "Reading password from pass.txt."
        except IOError:
            password = getpass()

        print "\nLogging in..."
        logged_in = api.login(email, password)
        if not logged_in:
            print "Log in failed."
        attempts += 1

    return api
コード例 #5
0
ファイル: gmusic.py プロジェクト: bchang/musicdb-python
def importGmusicApi(email, password, gmusicCollection, keysCollection):
    api = Api()
    api.login(email, password)
    allSongs = api.get_all_songs()
    api.logout()

    gmusicCollection.remove()
    keys = set()
    for song in allSongs:
        gmusicCollection.insert(song)
        for key in song.iterkeys():
            keys.add(key)

    doc = { '_id' : 'gmusic', 'keys' : list(keys) }
    keysCollection.save(doc)
    print 'done importing', len(allSongs), 'gmusic songs into db'
コード例 #6
0
def init():
    api = Api()
    (email, account, password) = netrc.netrc().hosts['google.com']
    logged_in = api.login(email, password)
    if not logged_in:
        api = None
    return api
コード例 #7
0
ファイル: pusher.py プロジェクト: bryfry/scrapem
def init(args):
	api = Api()
	if args.user_name == None:
		email =	 raw_input("Email: ")
	else :
		email = args.user_name
	if args.password == None:
		password = getpass()
	else :
		password = args.password 
	print "Signing in : " + email
	logged_in = api.login(email, password)
    	return api
コード例 #8
0
class AlbumArtist(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()


    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 fix_album_artist(self):

        def noAlbumArtist(x): return len(x['albumArtist']) == 0

        def fixSong(song):
            song['albumArtist'] = song['artist']
            return song

        def chunks(l, n):
            """ Yield successive n-sized chunks from l.
            """
            for i in xrange(0, len(l), n):
                yield l[i:i+n]

        songs = filter(noAlbumArtist, self.api.get_all_songs())

        print "Found %d songs that have no albumArtist" % len(songs)

        fixedSongs = map(fixSong, songs)

        fixedSongChunks = chunks(fixedSongs, 100)

        map(self.api.change_song_metadata, fixedSongChunks)

        print "Fixed %d songs" % len(fixedSongs)
コード例 #9
0
 def download_by_id(self, key, upload=False):
     if self.logstack.has_key(
             key) and self.logstack[key]['state'] != 'fail':
         return
     url = 'http://www.youtube.com/watch?v=%s' % (key)
     if upload:
         print 'upload google music!!!'
     self.current_key = key
     self.logstack[key] = {
         'path': '',
         'process': '',
         'state': 'downloading'
     }
     result = None
     try:
         self.download([url])
     except:
         self.logstack[key]['state'] = 'fail'
         return
     if upload:
         self.logstack[key]['state'] = 'uploading'
         print self.logstack[key]['path']
         path = self.logstack[key]['path'].encode('utf-8')
         api = Api()
         api.login(gpass.id, gpass.passwd)
         ids = api.get_all_playlist_ids(auto=False, instant=False)
         playlist_id = ids['user']['youtube']
         try:
             result = api.upload([path])
         except:
             print 'upload error'
             self.logstack[key]['state'] = 'fail'
             return
         if len(result):
             api.add_songs_to_playlist(playlist_id, result.values()[0])
     self.logstack[key]['state'] = 'complete'
コード例 #10
0
def init():
    """Makes an instance of the api and attempts to login with it.
    Returns the authenticated api.
    """
    
    api = Api() 
    
    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        logged_in = api.login(args.email, args.password)
        attempts += 1

    return api
コード例 #11
0
def init(email=None, password=None):
    api = Api()

    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        if email is None:
            email = raw_input("Email: ")
        if password is None or attempts > 0:
            password = getpass()

        logged_in = api.login(email, password)
        attempts += 1

    return api, logged_in
コード例 #12
0
def init():
    """Makes an instance of the api and attempts to login with it.
    Returns the authenticated api.
    """

    api = Api()

    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        email = raw_input("Email: ")
        password = getpass()

        logged_in = api.login(email, password)
        attempts += 1

    return api
コード例 #13
0
def init():
    """Makes an instance of the api and attempts to login with it.
    Returns the authenticated api.
    """

    api = Api()

    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        email = raw_input("Email: ")
        password = getpass()

        logged_in = api.login(email, password)
        attempts += 1

    return api
コード例 #14
0
def init():
    """Makes an instance of the api and attempts to login with it.
    Returns the authenticated api.
    """
    
    api = Api() 
    
    logged_in = False
    attempts = 0

    while not logged_in and attempts < 3:
        email = "*****@*****.**"
        password = "******"

        logged_in = api.login(email, password)
        attempts += 1

    return api
コード例 #15
0
        def run(self):
            api = Api()

            if len(self.username) == 0 or len(self.password) == 0:
                print "Credentials not supplied, cannot get information from Google Music"
            else:

                logged_in = False
                attempts = 0

                while not logged_in and attempts < 3:
                    logged_in = api.login(self.username, self.password)
                    attempts += 1

                if not api.is_authenticated():
                    print "Could not log in to Google Music with the supplied credentials."
                else:
                    print "Logged in to Google Music"

            self.callback(api)
コード例 #16
0
ファイル: login.py プロジェクト: stetro/pygmusic
class Login:

	def __init__(self):
		loginGuiPath = "guis/logingui.glade"
		self.builder = gtk.Builder()
		self.builder.add_from_file(loginGuiPath)
		self.builder.connect_signals(self)
		self.builder.get_object("loginGUI").show_all()
		self.builder.get_object("loginGUI").connect("delete_event", self.delete_event)

	def delete_event(self, widget, event, data=None):
		gtk.main_quit()
		return False

	def on_loginButton_clicked(self, widget):
		self.api = Api()
		logged_in = False
		attempts = 0

		email = self.builder.get_object("user").get_text()
		password = self.builder.get_object("password").get_text()

		logged_in = self.api.login(email, password)
		attempts += 1

		if(logged_in):
			self.builder.get_object("loginGUI").destroy()
			player = Player(self.api)
			pass
		else:
			diag = gtk.Dialog(title="Login Fehler !", parent=self.builder.get_object("loginGUI"), flags= gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
			label = gtk.Label("Login Fehler !")
			diag.vbox.pack_start(label)
			label.show()
			diag.run()
			diag.destroy()
コード例 #17
0
ファイル: gmusicfs.py プロジェクト: ealasu/GMusicFS
class MusicLibrary(object):
    'Read information about your Google Music library'
    
    def __init__(self, username=None, password=None, true_file_size=False):
        self.__artists = {} # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = [] # [Album(), ...]
        self.__login(username, password)
        self.__aggregate_albums()
        self.true_file_size = true_file_size

    def __login(self, username=None, password=None):
        # If credentials are not specified, get them from $HOME/.gmusicfs
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise NoCredentialException(
                    'No username/password was specified. No config file could '
                    'be found either. Try creating %s and specifying your '
                    'username/password there. Make sure to chmod 600.'
                    % cred_path)
            if not oct(os.stat(cred_path)[os.path.stat.ST_MODE]).endswith('00'):
                raise NoCredentialException(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            config = ConfigParser.ConfigParser()
            config.read(cred_path)
            username = config.get('credentials','username')
            password = config.get('credentials','password')
            if not username or not password:
                raise NoCredentialException(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
            
        self.api = GoogleMusicAPI()
        log.info('Logging in...')
        self.api.login(username, password, perform_upload_auth=False)
        log.info('Login successful.')
        
    def __aggregate_albums(self):
        'Get all the tracks in the library, parse into artist and album dicts'
        all_artist_albums = {} # 'Artist|||Album' -> Album()
        log.info('Gathering track information...')
        tracks = self.api.get_all_songs()
        for track in tracks:
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(track['artistNorm']), formatNames(track['albumNorm']))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                artist = formatNames(track['artistNorm'])
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(track['albumNorm']))
                self.__albums.append(album)
                artist_albums = self.__artists.get(artist, None)
                if artist_albums:
                    artist_albums[formatNames(album.normtitle)] = album
                else:
                    self.__artists[artist] = {album.normtitle: album}
                    artist_albums = self.__artists[artist]
            album.add_track(track)
        log.debug('%d tracks loaded.' % len(tracks))
        log.debug('%d artists loaded.' % len(self.__artists))
        log.debug('%d albums loaded.' % len(self.__albums))

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]
コード例 #18
0
def main(argv):
    '''Farm out work to task-based methods.

    :param argv: list of command line arguments
    '''

    # process command line options
    usage = """%prog [OPTIONS]... [COMMAND] [ARGS]...
       %prog [OPTIONS]... diff
       %prog [OPTIONS]... sync
       %prog [OPTIONS]... fs (not working)
       %prog [OPTIONS]... track UPDATE_KEYS[...]
       %prog [OPTIONS]... playlist [PLAYLIST]...
       %prog [OPTIONS]... delete [PLAYLIST]...
       %prog [OPTIONS]... validate
       %prog [OPTIONS]... dump TRACK_KEY[...]"""
    version_str = "{0} {1}".format(pkg, __version__)
    parser = OptionParser(usage=usage, version=version_str)
    # default banshee database
    banshee_db_def = os.environ['HOME'] + '/.config/banshee-1/banshee.db'
    banshee_db_help = "use Banshee database BANSHEE_DB (default {0})".format(banshee_db_def)
    parser.add_option("-b", "--banshee-db", default=banshee_db_def,
                      help=banshee_db_help)
    parser.add_option("-d", "--dry-run", action="store_true", default=False,
                      help="perform no action, just report what would be done")
    parser.add_option("-q", "--quiet", action="store_true",
                      help="do not print status messages")
    # default minimum rating
    rating_def = 3
    rating_help = "only consider Banshee songs with rating >= RATING (default {0})".format(rating_def)
    parser.add_option("-r", "--rating", type="int", default=rating_def,
                      help=rating_help)

    (options, args) = parser.parse_args()
    # set "globals"
    global dryrun
    dryrun = options.dry_run
    logmsg.quiet = options.quiet

    # open log file
    logmsg.log_f = codecs.open(pkg + '.log', mode='w', encoding='utf-8')

    # determine action
    command = 'diff'
    if len(args):
        command = args[0]
        # save the rest
        args = args[1:]

    # log in to Google Music (gm)
    api = Api() 

    gm_tracks = {}
    # sync and fs do not need connection to gm
    if command != 'sync' and command != 'fs':
        logged_in = False
        attempts = 0
        while not logged_in and attempts < 3:
            email = raw_input("Email: ")
            password = getpass()

            logged_in = api.login(email, password)
            attempts += 1

        if not api.is_authenticated():
            logmsg('google credentials were not accepted', True)
            return

        logmsg("successfully logged in to google")

        # get the google music library
        gm_tracks = get_gm_library(api)

    # connect to banshee database
    banshee_conn = sqlite3.connect(options.banshee_db)
    if not banshee_conn:
        logmsg('unable to connect to banshee: {0}'.format(options.banshee_db),
               True)
        return

    # get the banshee library
    b_tracks = get_b_library(banshee_conn, options.rating)

    # dispatch
    rv = 0
    if command == 'diff':
        # create files not in google music
        rv = diff(gm_tracks, b_tracks)
    elif command == 'sync':
        # create all files with sufficient rating
        rv = sync(b_tracks)
    elif command == 'fs':
        # check banshee database and file system for consistency
        rv = fs(b_tracks)
    elif command == 'track':
        # update track metadata
        rv = track(api, gm_tracks, b_tracks, args)
    elif command == 'playlist':
        # get banshee playlists
        b_playlists = get_b_playlists(banshee_conn, args)
        # upload banshee playlists to google music
        rv = playlist(api, gm_tracks, b_playlists)
    elif command == 'validate':
        # make sure the gm track metadata does not have bad characters
        rv = validate(gm_tracks)
    elif command == 'delete':
        # get banshee playlists
        b_playlists = get_b_playlists(banshee_conn, args)
        # delete tracks on banshee playlists from google music
        rv = delete(api, gm_tracks, b_playlists)
    elif command == 'dump':
        rv = dump(gm_tracks, args)
    else:
        logmsg('unknown command: {0}'.format(command), True)
        return

    # logout of gm
    api.logout()

    # disconnect from banshee database
    banshee_conn.close()

    # close log file
    logmsg.log_f.close

    if rv:
        sys.exit(0)
    # else
    sys.exit(1)
    # just in case
    return
コード例 #19
0
ファイル: gmusic-ratings.py プロジェクト: nickbp/misc-utils
class GMusicRater:
    def __init__(self, files):
        self.__api = Api()
        self.__by_rating = {}
        self.__needs_rating_update = []

        # fill list of songs
        lib = []
        cachefile = "gmusic.pickle"
        if os.path.isfile(cachefile):
            print "Loading cached library..."
            infile = open(cachefile, "rb")
            lib = cPickle.load(infile)
        else:
            self.__log_in()
            print "Getting music..."
            lib = self.__api.get_all_songs()
            print "Writing..."
            outfile = open(cachefile, "wb+")
            cPickle.dump(lib, outfile)

        # order list of songs by rating
        notfound = []
        total_found = 0
        for s in lib:
            r = files.find_rating(s)
            # error finding file:
            if r < 0:
                notfound.append(s)
                continue

            # print "Got rating for %s: %s" % (s["title"], s["rating"])
            # file rating is different from cloud rating:
            if not r == s["rating"]:
                s["rating"] = r
                self.__needs_rating_update.append(s)
            if not self.__by_rating.has_key(r):
                self.__by_rating[r] = []
            self.__by_rating[r].append(s)
            total_found += 1

        print "Found %d cloud songs, %d of which need rating updates." % (total_found, len(self.__needs_rating_update))
        print "Not found on disk: %d" % len(notfound)
        for s in notfound:
            print "  %s - %s" % (s["artist"], s["title"])

    def __log_in(self):
        if self.__api.is_authenticated():
            return

        print "Logging in..."
        email = raw_input("Email: ")
        password = getpass.getpass()
        if not self.__api.login(email, password):
            print "couldnt log in"
            sys.exit(1)

    def reset_playlists(self):
        self.__log_in()
        playlists = self.__api.get_all_playlist_ids(auto=False, user=True)["user"]
        print "Got %d playlists:" % len(playlists)
        for k, v in playlists.iteritems():
            print "  Deleting %s (%s)" % (k, v)
            for playlistid in v:
                self.__api.delete_playlist(playlistid)

        def get_ids(slist):
            ret = []
            for s in slist:
                ret.append(s["id"])
            return ret

        awesome_songids = get_ids(self.__by_rating.get(5, []))
        good_songids = awesome_songids + get_ids(self.__by_rating.get(4, []))
        unrated_songids = get_ids(self.__by_rating.get(0, []))

        awesome_pid = self.__api.create_playlist("Awesome")
        print "Awesome %s -> %d songs" % (awesome_pid, len(awesome_songids))
        self.__api.add_songs_to_playlist(awesome_pid, awesome_songids)

        good_pid = self.__api.create_playlist("Good")
        print "Good %s -> %d songs" % (good_pid, len(good_songids))
        self.__api.add_songs_to_playlist(good_pid, good_songids)

        unrated_pid = self.__api.create_playlist("Unrated")
        print "Unrated %s -> %d songs" % (unrated_pid, len(unrated_songids))
        self.__api.add_songs_to_playlist(unrated_pid, unrated_songids)

    def update_ratings(self):
        total = len(self.__needs_rating_update)
        if total == 0:
            return
        self.__log_in()
        print "Updating %d songs..." % total
        # divide updates into chunks.
        start = 0
        chunksz = 100  # could probably be larger, wasn't tested for max possible
        while start < total:
            end = start + chunksz
            if end >= total:
                end = total
            print "%d - %d" % (start, end)
            self.__api.change_song_metadata(self.__needs_rating_update[start:end])
            start = end

    def logout(self):
        if self.__api.is_authenticated():
            print "Logging out..."
            self.__api.logout()
コード例 #20
0
class Serenade():


	def __init__(self):
		self.app = QtGui.QApplication(sys.argv)
		self.app.setApplicationName("Serenade")
		signal.signal(signal.SIGINT, signal.SIG_DFL)

		self.position = 0

		self.player = MultimediaKit.QMediaPlayer(self.app)
		self.player.positionChanged.connect(self.positionChanged)

		self.signals = Signals()

		self.client = gconf.client_get_default()

		self.api = Api()
		self.artists = []
		self.library = {}

		self.cacheDir = QtGui.QDesktopServices.storageLocation(QtGui.QDesktopServices.CacheLocation)
		if not os.path.exists(self.cacheDir):
			os.mkdir(self.cacheDir)
		self.artistModel = ArtistModel()
		self.songModel = SongModel()
		self.signals.onDoneWorking.connect(self.doneWorking)
		self.signals.onError.connect(self.error)
		self.view = QtDeclarative.QDeclarativeView()
		self.view.setSource("/opt/serenade/qml/Main.qml")
		self.rootObject = self.view.rootObject()
		self.context = self.view.rootContext()
		self.context.setContextProperty('songModel', self.songModel)
		self.context.setContextProperty('artistModel', self.artistModel)
		self.rootObject.openFile("MenuPage.qml")
		self.rootObject.refresh.connect(self.updateSongs)
		self.rootObject.newLogin.connect(self.newLogin)
		self.rootObject.play.connect(self.play)
		self.rootObject.togglePause.connect(self.togglePause)
		self.login()
		self.view.showFullScreen()

		sys.exit(self.app.exec_())


	def login(self):
		email = self.client.get_string('/apps/serenade/email')
		passwd = self.client.get_string('/apps/serenade/passwd')
		if not email or not passwd:
			self.rootObject.openFile("LoginPage.qml")
		else:
			logged_in = self.api.login(email, passwd)
			if not logged_in:
				self.rootObject.openFile("LoginPage.qml")
				self.rootObject.showMessage("Login failed", "Please check your email and password and try again. If you're using two-factor authentication you may need to set an application specific password in your Google account.")
			else:
				self.rootObject.openFile("MenuPage.qml")
				self.updateSongs()

	
	def newLogin(self, email, passwd):
		self.client.set_string('/apps/serenade/email', email)
		self.client.set_string('/apps/serenade/passwd', passwd)
		self.login()


	def updateSongs(self):
		self.rootObject.startWorking()
		thread = threading.Thread(target=self._updateSongs)
		thread.start()


	def _updateSongs(self):
		self.library = sorted(self.api.get_all_songs(), key=lambda x: x['title'])
		self.library.reverse()
		for s in self.library:
			if "albumArtUrl" in s:
				art = self.getImage(s['albumArtUrl'])
			else:
				art = "/opt/serenade/no-art.png"
			if s['artist'] not in self.artists:
				artist = Artist(s['artist'], art)
				self.artists.append(s['artist'])
				self.artistModel.add(artist)
			song = Song(s['id'], s['title'], s['album'], s['artist'], False, art)
			self.songModel.add(song)
		self.artistModel.sort()
		self.signals.onDoneWorking.emit()


	def doneWorking(self):
		self.rootObject.stopWorking()


	def error(self, title, message):
		self.rootObject.showMessage(title, message)


	def getImage(self, url):
		filename = url.split("/")[-1]
		imagePath = os.path.join(self.cacheDir, filename)		
		imagePath = imagePath.replace("?", "")
		if not os.path.exists(imagePath):
			try:   
				out = open(imagePath, 'wb')
				out.write(urllib2.urlopen("http:" + url).read())
				out.close()
			except Exception, err:
				return "/opt/serenade/no-art.png"
		return imagePath
コード例 #21
0
class GoogleMusic():
    """This class handles the communication with Google Music."""
    def __init__(self, email, password):
        if not email or not password:
            raise Exception("Username and password needs to be given")

        self._library = None
        self._artists = None
        self._albums = None
        self._playlists = None

        self._email = email
        self._password = password

        # Initialize the Google Music API
        self._api_init(self._email, self._password)

        if not self._api.is_authenticated():
            raise Exception("Credentials were not accepted!")

        # Initial load of the library
        self.load_library()

    def _api_init(self, email, password):
        """Inits the API object and login to Google Music"""
        self._api = Api()
        self._api.login(email, password)

    def load_library(self):
        """
		This function downloads the music library from Google Music and
		processes it.
		"""
        self._library = self._api.get_all_songs()

        # Generate artists and albums trees
        self._gen_trees()

    def _gen_trees(self):
        """
		This function generates trees of artists and albums from the library.

		Parts of this function are taken from: https://github.com/mstill/thunner/blob/master/thunner
		=> Thanks for the great code :)
		"""
        # Use defaultdict to group song dictionaries by artists
        artists_dict = collections.defaultdict(list)
        for i in self._library:
            artists_dict[i['artist']].append(i)

        artists = []
        albums = []
        for artist, songs_of_artist in artists_dict.iteritems():
            albums_of_artists_dict = collections.defaultdict(list)
            for i in songs_of_artist:
                albums_of_artists_dict[i['album']].append(i)

            albums_of_artist = []
            for album, tracks in albums_of_artists_dict.iteritems():
                album_name = album
                if album == "":
                    album_name = "Untitled album"

                albums_of_artist.append({
                    "name":
                    album_name,
                    "subtree":
                    sorted(tracks, key=itemgetter('track')),
                    "subtreeline":
                    0
                })

            albums = albums + albums_of_artist
            artists.append({
                "name":
                artist,
                "subtree":
                sorted(albums_of_artist, key=lambda x: x['name'].lower()),
                "subtreeline":
                0
            })

        self._artists = sorted(artists, key=lambda x: x['name'].lower())
        self._albums = sorted(albums, key=lambda x: x['name'].lower())

    def get_songs(self):
        """This function returns all songs from the music library."""
        songs = []
        for entry in self._library:
            song = {
                'id': entry['id'],
                'title': entry['title'],
                'artist': entry['artist'],
                'album': entry['album']
            }
            songs.append(song)

        return songs

    def get_artists(self):
        pass

    def get_albums(self):
        pass

    def get_stream_url(self, id):
        return self._api.get_stream_url(id)
コード例 #22
0
ファイル: googlemusic.py プロジェクト: hypebeast/piJukebox
class GoogleMusic():
	"""This class handles the communication with Google Music."""
	def __init__(self, email, password):
		if not email or not password:
			raise Exception("Username and password needs to be given")

		self._library = None
		self._artists = None
		self._albums = None
		self._playlists = None

		self._email = email
		self._password = password

		# Initialize the Google Music API
		self._api_init(self._email, self._password)

		if not self._api.is_authenticated():
			raise Exception("Credentials were not accepted!")

		# Initial load of the library
		self.load_library()

	def _api_init(self, email, password):
		"""Inits the API object and login to Google Music"""
		self._api = Api()
		self._api.login(email, password)

	def load_library(self):
		"""
		This function downloads the music library from Google Music and
		processes it.
		"""
		self._library = self._api.get_all_songs()

		# Generate artists and albums trees
		self._gen_trees()

	def _gen_trees(self):
		"""
		This function generates trees of artists and albums from the library.

		Parts of this function are taken from: https://github.com/mstill/thunner/blob/master/thunner
		=> Thanks for the great code :)
		"""
		# Use defaultdict to group song dictionaries by artists
		artists_dict = collections.defaultdict(list)
		for i in self._library:
			artists_dict[i['artist']].append(i)

		artists = []
		albums =  []
		for artist, songs_of_artist in artists_dict.iteritems():
			albums_of_artists_dict = collections.defaultdict(list)
			for i in songs_of_artist:
				albums_of_artists_dict[i['album']].append(i)

			albums_of_artist = []
			for album,tracks in albums_of_artists_dict.iteritems():
				album_name = album
				if album == "":
					album_name = "Untitled album"

				albums_of_artist.append({
											"name": album_name,
											"subtree": sorted(tracks, key=itemgetter('track')),
											"subtreeline": 0
										})

			albums = albums + albums_of_artist
			artists.append({
								"name": artist,
								"subtree": sorted(albums_of_artist, key=lambda x: x['name'].lower()),
								"subtreeline": 0
							})

		self._artists = sorted(artists, key=lambda x: x['name'].lower())
		self._albums = sorted(albums, key=lambda x: x['name'].lower())

	def get_songs(self):
		"""This function returns all songs from the music library."""
		songs = []
		for entry in self._library:
			song = {
				'id': entry['id'],
				'title': entry['title'], 
				'artist': entry['artist'], 
				'album': entry['album'] 
			}
			songs.append(song)

		return songs

	def get_artists(self):
		pass

	def get_albums(self):
		pass 

	def get_stream_url(self, id):
		return self._api.get_stream_url(id)
コード例 #23
0
ファイル: gmusicfs.py プロジェクト: ealasu/GMusicFS
class MusicLibrary(object):
    'Read information about your Google Music library'

    def __init__(self, username=None, password=None, true_file_size=False):
        self.__artists = {}  # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = []  # [Album(), ...]
        self.__login(username, password)
        self.__aggregate_albums()
        self.true_file_size = true_file_size

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

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

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

    def get_artists(self):
        return self.__artists

    def get_albums(self):
        return self.__albums

    def get_artist_albums(self, artist):
        log.debug(artist)
        return self.__artists[artist]
コード例 #24
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('\\', '/'))