Example #1
0
class gmObject:
    
    def __init__(self):
        self.mc = Mobileclient()
        self.wc = Webclient()
        self.mm = Musicmanager()
    
    def login(self, username, password):
        error.e = 0
        
        if not self.mc.login(username, password):
            gmtPrintV("gmObject.login: Wrong username or password (or no internet connection)")
            error.e = error.LOGIN_FAILED
            return
        
        if not self.wc.login(username, password):
            gmtPrintV("gmObject.login: Wrong username or password (or no internet connection)")
            error.e = error.LOGIN_FAILED
            return
        
        if not self.mm.login(config.cred_path):
            gmtPrintV("gmObject.login: Wrong credentials (or no internet connection)")
            error.e = error.LOGIN_FAILED
            return
        
    def logout(self):
        error.e = 0
        
        try:
            self.mc.logout()
            self.wc.logout()
            self.mm.logout()
        except:
            gmtPrintV("gmObject.logout: Logout failed")
            error.e = error.LOGOUT_FAILED
Example #2
0
def run():
    global download_dir, notify_plex, mm
    download_dir, notify_plex = parse_args()
    log("Creating music manager")
    mm = Musicmanager()
    log("Attempting login")
    if not mm.login():
        print "OAuth required:"
        mm.perform_oauth()

    get_songs()
Example #3
0
class GMusicPodcastSyncDestination(PodcastSyncDestination):
    def __init__(self):
        super(GMusicPodcastSyncDestination, self).__init__()
        self.serviceIdentifier = "GOO"
        self.serviceName = "Google Music"
        self.musicManager = Musicmanager()
        self.mobileClient = Mobileclient()
        oAuthFile = "gMusic.oauth"
        if not os.path.isfile(oAuthFile):
            if not self.musicManager.perform_oauth(oAuthFile, True):
                print "Failed to authenticate Music Manager."
                raise PodcastSyncDestinationException("Authentication Failure.")
        else:
            try:
                self.musicManagerauthenticated = self.musicManager.login(oAuthFile)
            except gmusicapi.exceptions.AlreadyLoggedIn:
                pass
        username = raw_input("Enter Google Username: "******"Enter Google Password: "******"Authentication Failure.")
            # perform a push task. should return a PodFastPodcastPushedEpisode instance

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

    def pullEpisode(self, podcastSyncTaskEpisodePull):
        self.mobileClient.delete_songs([podcastSyncTaskEpisodePull.syncDestinationID])
        # TODO: Error check here.
        return True
class GoogleClient():
    def __init__(self, username=None, password=None):
        self._username = username
        self._password = password

    # Initiates the oAuth
    def Authenticate(self):
        self.MusicManager = Musicmanager(debug_logging=False)

        attempts = 0
        # Attempt to login. Perform oauth only when necessary.
        while attempts < 3:
                if self.MusicManager.login():
                        break
                self.MusicManager.perform_oauth()
                attempts += 1

        if not self.MusicManager.is_authenticated():
                print("Sorry, login failed.")
                return False

        print("OAuth successfull\n")

        username = self._username
        password = self._password
        if not username or not password:
            cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs')
            if not os.path.isfile(cred_path):
                raise Exception(
                    '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 Exception(
                    'Config file is not protected. Please run: '
                    'chmod 600 %s' % cred_path)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials','username')
            password = self.config.get('credentials','password')
            if not username or not password:
                raise Exception(
                    'No username/password could be read from config file'
                    ': %s' % cred_path)
        self.Api = Mobileclient(debug_logging = False)
        if not self.Api.login(username, password, Mobileclient.FROM_MAC_ADDRESS):
           raise Exception('login failed for %s' % username)

        return True
Example #5
0
	def download_songs(self):
		api = Musicmanager()
		ip = urllib2.urlopen('http://ip.42.pl/raw').read() #Obtain your public IP address
		mac_binary = str(get_mac()) #Obtain binary MAC address
		temp = mac_binary.replace(':', '').replace('-', '').replace('.', '').upper()
		mac_h3x = temp[:2] + ":" + ":".join([temp[i] + temp[i+1] for i in range(2,12,2)]) #Convert MAC from 48bit int to hexadecimal string
		user = pwd.getpwuid(os.getuid())[0] #Get your system's username
		hostname = '<' + ip + '>' + '' + '(gmusicapi-{2.0.0})'
		Musicmanager.perform_oauth(storage_filepath='/home/' + user + '/.config/gmusicapi/oauth.cred', open_browser=False)
		api.login(oauth_credentials='/home/' + user + '/.config/gmusicapi/oauth.cred', uploader_id=mac_h3x, uploader_name=hostname)
		gmusicapi.clients.Musicmanager(debug_logging=True, validate=True)		
		playlist_id = raw_input("insert id: ")
		
		api_ = Mobileclient()
		api_.login(self.email, self.password)
		playlist_method = api_.get_all_playlists()
Example #6
0
def api_init():
    mm = Musicmanager()
    e = settings['email']
    creds = os.path.expanduser("~/.local/share/gmusicapi/oauth.cred") # default oauth store location
    if OTHERACCOUNT:
        e = settings['email2']
        creds = os.path.expanduser("~/.local/share/gmusicapi/oauth2.cred")
    if e is not None:
        if settings['first'] == '1' or OTHERACCOUNT and settings['first2'] == '1':
            print "Performing OAUTH for %s" % e
            mm.perform_oauth(storage_filepath=creds)
            update_first(e)
    log("Logging in as %s" % e)
    if mm.login(oauth_credentials=creds):
        return mm
    log("Login failed for second user")
    return False
Example #7
0
 def __init__(self):
     super(Gmusic, self).__init__()
     # Checks for OAuth2 credentials,
     # if they don't exist - performs authorization
     self.m = Musicmanager()
     if os.path.isfile(gmusicapi.clients.OAUTH_FILEPATH):
         self.m.login()
     else:
         self.m.perform_oauth()
Example #8
0
class GoogleManager():

    def __init__(self, directory):
        self.music_dir = directory

        self.Google = Musicmanager()
        self.Google.login()

    def upload(self):
        files = []
        for dirpath, dirnames, filenames in walk(self.music_dir):
            for name in filenames:
                if name.endswith('.mp3'):
                    files += [join(dirpath, name)]

        for f in files:
            ret = self.Google.upload(f)
            print(ret)
def setup_music_manager_api():
    global music_manager_api
    music_manager_api = Musicmanager()

    if not config.get_is_authenticated():
        print "Follow the instructions to authenticate with Google..."
        credentials = music_manager_api.perform_oauth()
        if credentials is not None:
            config.set_is_authenticated(True)
        else:
            print "Failed to authenticate, try again."
            sys.exit(0)

    music_manager_logged_in = music_manager_api.login()

    if not music_manager_logged_in:
        print "Failed to log in to the music manager API, you will be asked to authenticate again next run."

        sys.exit(0)
class GoogleClient():
    # Initiates the oAuth
    def Authenticate(self):
        self.MusicManager = Musicmanager(debug_logging=False)

        attempts = 0
        # Attempt to login. Perform oauth only when necessary.
        while attempts < 3:
                if self.MusicManager.login():
                        break
                self.MusicManager.perform_oauth()
                attempts += 1

        if not self.MusicManager.is_authenticated():
                print "Sorry, login failed."
                return False

        print "Successfully logged in.\n"
        return True
Example #11
0
def download_user_track(mgr:  gmusicapi.Musicmanager, full_path, track):
    dirname = os.path.dirname(full_path)
    fp, temp_path = tempfile.mkstemp(dir=dirname)

    try:
        fname, audio = mgr.download_song(track['id'])
        fp.write(audio)
        os.rename(temp_path, full_path)
    finally:
        if os.path.exists(temp_path):
            os.unlink(temp_path)
Example #12
0
 def __init__(self):
     super(Gmusic, self).__init__()
     self.m = Musicmanager()
     self.config.add({
         u'auto': False,
         u'uploader_id': '',
         u'uploader_name': '',
         u'device_id': '',
         u'oauth_file': gmusicapi.clients.OAUTH_FILEPATH,
     })
     if self.config['auto']:
         self.import_stages = [self.autoupload]
Example #13
0
 def __init__(self):
     """
     Log into Musicmanager and get the library, either by loading an
       existing library file, or by generating a new one.
     """
     self.kind = 'free'
     self.mm = Musicmanager()
     self.mm.login()
     self.songs = []
     self.load_library()
     if not self.songs:
         self.gen_library()
Example #14
0
    def __register_music_manager(self):
	self.manager = GoogleMusicManager()
	self.manager_id = ':'.join(re.findall('..', '%012x' % uuid.getnode())).upper()
	log.info('Registering the google music manager...')
        cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs.ocred')
	if not os.path.isfile(cred_path):
	    log.info('Authorizing GMusicFS application against Google...')
	    self.manager.perform_oauth(storage_filepath=cred_path)
	    os.chmod(cred_path, 0600)
        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)
	self.manager.login(cred_path, self.manager_id, 'GMusicFS')
	log.info('Successfully registered the google music manager...')
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""
Example #16
0
 def init(self, oauth_credentials):
     # Initialize the database
     logger.info("%s: Initializing database" % self.email)
     self._data_init()
     # Create the Musicmanager
     logger.info("%s: Logging in to Google music" % self.email)
     self.mm = Musicmanager()
     if not self.mm.login(oauth_credentials):
         logger.info("%s: Error logging in to Google music" % self.email)
         return False
     # Check if we already have any watch paths configured
     config = self._read_config()
     watched_paths = config["watched_paths"] if "watched_paths" in config else []
     logger.info("%s: Found previously watched paths %s" % (self.email, watched_paths))
     # Create the FileWatcher
     logger.info("%s: Creating the FileWatcher" % (self.email))
     self.fw = FileWatcher(self.email, self._finished_writing_callback, watched_paths)
     return True
Example #17
0
 def __init__(self):
     super(GMusicPodcastSyncDestination, self).__init__()
     self.serviceIdentifier = "GOO"
     self.serviceName = "Google Music"
     self.musicManager = Musicmanager()
     self.mobileClient = Mobileclient()
     oAuthFile = "gMusic.oauth"
     if not os.path.isfile(oAuthFile):
         if not self.musicManager.perform_oauth(oAuthFile, True):
             print "Failed to authenticate Music Manager."
             raise PodcastSyncDestinationException("Authentication Failure.")
     else:
         try:
             self.musicManagerauthenticated = self.musicManager.login(oAuthFile)
         except gmusicapi.exceptions.AlreadyLoggedIn:
             pass
     username = raw_input("Enter Google Username: "******"Enter Google Password: "******"Authentication Failure.")
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.mc.get_all_user_playlist_contents()
        #self.playlists = self.mc.get_all_playlists()
        #self.playlists = self.wc.get_all_playlist_ids(auto=False)
        self.all_songs = self.mc.get_all_songs()
        #print "Got %d playlists." % len(self.playlists['user'])
        print "Got %d playlists containing %d songs." % (len(self.playlists), len(self.all_songs))
        print ""
Example #19
0
	def songs_uploader(self):
		ip = urllib2.urlopen('http://ip.42.pl/raw').read() #Obtain your public IP address
		mac_binary = str(get_mac()) #Obtain binary MAC address
		temp = mac_binary.replace(':', '').replace('-', '').replace('.', '').upper()
		mac_h3x = temp[:2] + ":" + ":".join([temp[i] + temp[i+1] for i in range(2,12,2)]) #Convert MAC from 48bit int to hexadecimal string
		user = pwd.getpwuid(os.getuid())[0] #Get your system's username
		
		api = Musicmanager()
		hostname = '<' + ip + '>' + '' + '(gmusicapi-{2.0.0})'
		Musicmanager.perform_oauth(storage_filepath='/home/' + user + '/.config/gmusicapi/oauth.cred', open_browser=False)
		api.login(oauth_credentials='/home/' + user + '/.config/gmusicapi/oauth.cred', uploader_id=mac_h3x, uploader_name=hostname)
		gmusicapi.clients.Musicmanager(debug_logging=True, validate=True)
		
		#newWorkingDirectory = '../home'
		#os.path.join(os.path.abspath(sys.path[0]), newWorkingDirectory) #Change the working directory
		filepath = '/home/blackram/Scrivania/BRES_/UMM/ciao.mp3'
		uploading = api.upload(filepath, transcode_quality=3, enable_matching=False)
		print 'Uploading...'
		f = open('uploading.txt','w') #log
		f.write(str(uploading))
		f.close()
		
		final = re.search("GetUploadSession error 200: this song is already uploaded", open('uploading.txt','r').read())
		if final is None:
			print '\033[32mTrack uploaded!\033[0m'
		else:
			print '\033[31mTrack already exists in your library!\033[0m'
		
		choice = raw_input("Exit from uploader? [Y/N] ")
		if choice == 'y' or choice == 'Y':
			print 'Return to main menu.'
			Musicmanager.logout(revoke_oauth=False)
			UMM.read_information()
		elif choice == 'n' or choice == 'N':
			print 'Okay.'
			UMM.songs_uploader()
Example #20
0
def upload(file_path):
    storage = oauth2client.file.Storage(CREDENTIALS_PATH)
    credentials = storage.get()

    if not credentials or credentials.invalid:
        Musicmanager.perform_oauth(CREDENTIALS_PATH, open_browser=False)

    mm = Musicmanager()
    mm.login(CREDENTIALS_PATH)

    result = mm.upload(file_path, enable_matching=True)
    if result[1]:
        raise Exception('{}はアップロード済みです'.format(file_path))
    elif result[2]:
        raise Exception('アップロード失敗 {}'.format(result[2][file_path]))

    os.remove(file_path)
def main():
    if len(sys.argv) != 2:
        print_help()
        sys.exit(1)
    else:
        username = sys.argv[1]
    password = getpass.getpass()

    mc = Mobileclient()
    mc.login(username, password, Mobileclient.FROM_MAC_ADDRESS)

    mm = Musicmanager()
    mm.perform_oauth()
    mm.login()

    uploaded_songs = mm.get_uploaded_songs()
    uploaded_ids = [track['id'] for track in uploaded_songs]
    for part in chunks(uploaded_ids, 100):
        complete = mc.delete_songs(part)
        if len(complete) != len(part):
            print("Something is wrong")
Example #22
0
from gmusicapi import Musicmanager, clients
from node_translator import Translator
import sys, json

translator = Translator()

# Get file paths from node
file_names = translator.get_input()

# Returns path to system stored oauth
oauth_path = clients.OAUTH_FILEPATH

# Init Musicmanager and login
mm = Musicmanager()
is_logged_in = mm.login(oauth_path)

if is_logged_in:
    # Matching set to false due to lack of ffmpeg or avconv
    upload_result = mm.upload(file_names, '320k', False)
    print json.dumps(upload_result)
    # return upload_result

    if upload_result[0] != {}:
        print('Something happened here!')
else:
    sys.exit('Not logged in')




Example #23
0
from gmusicapi import Musicmanager
from os import listdir
from os.path import isfile, join
import os
import time
import subprocess

api = Musicmanager()
api.login()
mypath = '/home/pi/musics'
while True:
    onlyfiles = [ f for f in listdir(mypath) if isfile(join(mypath,f)) ]
    if len(onlyfiles) > 0:
        time.sleep(5)
        for file in onlyfiles:
            print(file)
            api.upload(mypath + '/' + file)
            os.remove(mypath + '/' + file)
	


Example #24
0
if __name__ == '__main__':

    original_sigint = signal.getsignal(signal.SIGINT)
    signal.signal(signal.SIGINT, exit_cleanly)


    parser = argparse.ArgumentParser(description="Google Music Player")
    parser.add_argument('-l','--login', required=False, help='Create login credentials.', action="store_true")
    parser.add_argument('-s','--shuffle', required=False, help='Play in random order.', action="store_true")
    parser.add_argument('-r', '--refresh', required=False, help='Refresh Library.', action="store_true")
    parser.add_argument('-d', '--display', required=False, help='Display playlist only.', action="store_true")
    parser.add_argument('-t', '--artist', required=False, help='Artist Filter' )
    args = parser.parse_args()    

    mm = Musicmanager()
    if args.login:
        mm.perform_oath()
        sys.exit(0)

    print "Logging In..."
    mm.login()

    if args.refresh:
        print "Getting Songs"
        library = mm.get_uploaded_songs()
        with open('library.txt','w') as f:
            pickle.dump( library, f)

    print "Loading Library..."
    with open('library.txt','r') as f:
Example #25
0
class GoolgeMusicUploader(object):
    "Google music upload class"

    def __init__(self, config):
        self.credential_file = ''

        if len(config.googleplay_credential_file) > 0:
            self.credential_file = config.googleplay_credential_file
        else:
            self.credential_file = clients.OAUTH_FILEPATH

        self.mac_address = config.mac_address_for_gplay
        self.manager = Musicmanager(False)
        self.logger = logging.getLogger(__name__)

    def login(self):
        "Logs in"

        if not self.manager.login(self.credential_file, self.mac_address):
            raise AuthError(
                'Could not authenticate music manager using {}'.format(
                    self.credential_file))

    def logout(self):
        "Logs out"
        if self.manager.is_authenticated:
            success = self.manager.logout()
            if success:
                self.logger.info('Logged out of Google Play Music')
            else:
                self.logger.warning('Failed to log out of Google Play Music')

    def upload(self, track_dir):
        "Does the upload."

        if not self.manager.is_authenticated:
            raise AuthError(
                "Music Manager not authenticated. Call 'login' first.")

        if not isdir(track_dir):
            raise DirectoryNotFoundError(track_dir)

        files = absolute_files(track_dir)

        info = TrackInfo()
        info.load(get_track_info_file(files))

        track_file = get_track_file(files)

        result = UploadResult(track_dir, track_file, info.full_title)

        if track_file == DEFAULT_FILE_NAME:
            result.set_failure('MP3 Track file not found')
            return result

        locked = lock_file_exists(track_dir)
        if locked:
            result.set_failure('Lock file exists')
            return result

        metadata = AudioMetadata(track_file)
        metadata.apply_album_art(get_album_art_file(files))
        metadata.apply_track_info(info)

        success, message = self.__upload_file__(track_file)
        if success:
            result.set_success(message)
        else:
            result.set_failure(message)
        return result

    def __upload_file__(self, track_file):
        self.logger.info('Uploading %s', track_file)
        upload_result = self.manager.upload(track_file)

        if upload_result[0] != {}:
            return True, upload_result[0]

        elif upload_result[1] != {}:
            return True, upload_result[2]

        elif upload_result[2] != {}:
            reason = list(upload_result[2].items())[0]
            return False, 'Couldn\'t upload {} because {}'.format(
                reason[0], reason[1])
Example #26
0
class GPMClient():
    def __init__(self, loop):
        self.loop = loop
        self.tpool = ThreadPoolExecutor(max_workers=2)
        self.client = Musicmanager(debug_logging=False)
        self.bot_dir = Path.cwd()
        self.dl_dir = self.bot_dir/"audio_cache"
        self.gpm_config_dir = self.bot_dir/"config"/"gpm"
        self.gpm_config_dir.mkdir(exist_ok=True)

        self.credential = None
        if (self.gpm_config_dir/"credential").is_file():
            self.credential = str(self.gpm_config_dir/"credential")

        self.logged_in = False
        # Throws exception
        self.logged_in = self.client.login(self.credential)

        self.ffprobe = self._find_ffprobe()
    
    # Just wrap blocking functions to run in other thread.
    async def update_db(self):
        return await self.loop.run_in_executor(self.tpool, partial(self._update_db))

    async def download(self, entry):
        return await self.loop.run_in_executor(self.tpool, partial(self._download, entry))

    async def search(self, args):
        return await self.loop.run_in_executor(self.tpool, partial(self._search, args))
    
    # This is a native coroutine
    async def play(self, player, trackinfo, **meta):
        return await player.playlist.add_gpm_entry(trackinfo, **meta)

    async def play_from_id(self, player, gpmid):
        trackinfo = await self.loop.run_in_executor(self.tpool, partial(self._get_trackinfo, gpmid))
        if not trackinfo:
            raise ExtractionError("Failed to get trackinfo matches given GPMID.")
            
        await player.playlist.add_gpm_entry(trackinfo)

    def _update_db(self):
        tracklist = self.client.get_uploaded_songs()
        if not tracklist:
            return None

        db = sqlite3.connect(str(self.gpm_config_dir/"track.db"))

        db.execute("DROP TABLE IF EXISTS gpm")
        db.execute("CREATE TABLE IF NOT EXISTS gpm(title, artist, album, gpmid)")
        db.executemany("INSERT INTO gpm VALUES (:title, :artist, :album, :id)", tracklist)
        db.commit()

        db.close()

        return len(tracklist)

    def _download(self, entry):
        target = self.dl_dir/entry.expected_filename
        # Let it try 3 times
        for _ in range(3):
            _, abyte = self.client.download_song(entry.gpmid)
            if abyte:
                break

        if not abyte:
            return False, None

        with open(target, "wb") as f:
            f.write(abyte)

        return True, target

    def _get_duration(self, audio_file):
        if not self.ffprobe:
            return

        target = str(audio_file)
        cmd = self.ffprobe + " -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 " + target
        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, __ = proc.communicate()
        log.debug("ffprobe stdout says: {}".format(stdout.decode("utf-8")))
        
        # S**T
        # Ensure with regular expression
        return int(float(stdout.decode("utf-8").strip()))

    def _search(self, args):
        db = sqlite3.connect(str(self.gpm_config_dir/"track.db"))
        db.execute("CREATE TABLE IF NOT EXISTS gpm(title, artist, album, gpmid)")

        # Need better way to search DB...
        query = "%" + "%".join(args) + "%"
        cur = db.execute("SELECT * FROM gpm WHERE title||' '||artist||' '||album LIKE ?", [query, ])
        result = cur.fetchall()

        db.close()

        res = []
        for item in result:
            res.append(GPMTrack(item))

        return res

    def _get_trackinfo(self, gpmid):
        db = sqlite3.connect(str(self.gpm_config_dir/"track.db"))
        db.execute("CREATE TABLE IF NOT EXISTS gpm(title, artist, album, gpmid)")

        true_gpmid = gpmid.split(":")[2]
        if not true_gpmid:
            return

        cur = db.execute("SELECT * FROM gpm WHERE gpmid = ?", [true_gpmid, ])
        result = cur.fetchone()

        db.close()

        return GPMTrack(result) if result else None

    def _find_ffprobe(self):
        program = "ffprobe"

        # Original: musicbot/player.py
        def is_exe(fpath):
            found = os.path.isfile(fpath) and os.access(fpath, os.X_OK)
            if not found and sys.platform == 'win32':
                fpath = fpath + ".exe"
                found = os.path.isfile(fpath) and os.access(fpath, os.X_OK)
            return found

        fpath, __ = os.path.split(program)
        if fpath:
            if is_exe(program):
                return program
        else:
            for path in os.environ["PATH"].split(os.pathsep):
                path = path.strip('"')
                exe_file = os.path.join(path, program)
                if is_exe(exe_file):
                    return exe_file

        log.debug("Failed to get ffprobe.")
        return None
Example #27
0
from gmusicapi import Musicmanager

mm = Musicmanager()
mm.login()
songs = mm.get_all_songs()

print len(songs)
def play_song(song):
    if Mobileclient.is_authenticated(gpm):
        mm = Musicmanager()
        mm.login('/home/pi/oauth.cred')

        if Musicmanager.is_authenticated(mm):
            song_dict = mm.get_purchased_songs()
            song_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(song) + r')\s?(?:.)*', re.IGNORECASE)

            btn = OnButtonPress()
            btn.start()

            for song in song_dict:
                m = re.match(song_pattern, song['title'])
                print(m)

                if re.match(song_pattern, song['title']) is not None:
                    print('Song found!')
                    song_id = song['id']
                    (filename, audio) = mm.download_song(song_id)

                    # get rid of non-ascii characters in file name

                    filename = filename.encode('ascii', errors='ignore')

                    # check if song is already downloaded
                    # path will look something like:
                    # /home/pi/Music/02 - Raindrop Prelude.mp3
                    # forces filename to be a string

                    filename = filename.decode('ascii')
                    path = song_location + filename
                    try:
                        if os.path.isfile(path):
                            print('Song is already downloaded...')
                            print(path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                (m, s) = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                        else:
                            with open(path, 'wb') as f:
                                f.write(audio)
                            print('Song has been added to: ' + path)
                            print('Playing song.')

                            vlc_instance = vlc.Instance()

                            p = vlc_instance.media_player_new()
                            media = vlc_instance.media_new(path)

                            p.set_media(media)
                            events = p.event_manager()
                            events.event_attach(
                                vlc.EventType.MediaPlayerEndReached,
                                SongFinished)
                            p.play()
                            p.audio_set_volume(58)

                            while finish == 0:
                                duration = p.get_time() / 1000
                                (m, s) = divmod(duration, 60)

                                print('Current song is: ', path)
                                print('Length:', '%02d:%02d' % (m, s))
                                time.sleep(5)

                            p.stop()
                            break
                    except (OSError, IOError):
                        print('An error has occurred.')
                        break
                else:

                    print('Song not found yet.')
        else:

            print('Looks like you need to authenticate.')
            mm.perform_oauth('/home/pi/oauth.cred')

        print('Logging out.')
        Mobileclient.logout(gpm)
        mm.logout()
    else:
        print('Mobileclient could not authenticate.')
        Mobileclient.logout(gpm)
Example #29
0
 def __init__(self, playlists_to_sync, credentials_storage_location, debug):
     self.playlists_to_sync = playlists_to_sync
     self.credentials_storage_location = credentials_storage_location
     self._client = Mobileclient(debug_logging=debug)
     self._manager = Musicmanager(debug_logging=debug)
Example #30
0
#! /usr/bin/env python3

from gmusicapi import Musicmanager
from os.path import expanduser, join

mm = Musicmanager()
if not mm.login():
    print('Login failed: did you run oauth_login.py?')
    quit()

# No point properly checking for duplicates when overwriting them
# gives the same result.
songs = {}
for song in mm.get_purchased_songs():
    songs[song['id']] = ' - '.join(
        [song['title'], song['artist'], song['album']]
    )
for song in mm.get_uploaded_songs():
    songs[song['id']] = ' - '.join(
        [song['title'], song['artist'], song['album']]
    )

print('Downloading %d songs to ~/.local/share/pmcli/songs. '
      'This might take a while...' % len(songs))

song_dir = join(expanduser('~'), '.local', 'share', 'pmcli', 'songs')
i = 1

for id in songs:
    print('%d/%d: %s' % (i, len(songs), songs[id]))
    dl_path = join(song_dir, '%s.mp3' % songs[id].replace('/', '---'))
Example #31
0
class MusicLibrary(object):
    'Read information about your Google Music library'

    def __init__(self,
                 username=None,
                 password=None,
                 true_file_size=False,
                 scan=True,
                 verbose=0):
        self.verbose = False
        self.manager_id = 0
        if verbose > 1:
            self.verbose = True

        self.__login_and_setup(username, password)
        self.__register_music_manager()
        if scan:
            self.rescan()
        self.true_file_size = true_file_size

    def rescan(self):
        self.__artists = {}  # 'artist name' -> {'album name' : Album(), ...}
        self.__albums = []  # [Album(), ...]
        self.__aggregate_albums()

    def __login_and_setup(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)
            self.config = ConfigParser.ConfigParser()
            self.config.read(cred_path)
            username = self.config.get('credentials', 'username')
            password = self.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(debug_logging=self.verbose)
        log.info('Logging in...')
        self.api.login(username, password)
        log.info('Login successful.')

    def __register_music_manager(self):
        self.manager = GoogleMusicManager()
        self.manager_id = ':'.join(re.findall('..', '%012x' %
                                              uuid.getnode())).upper()
        log.info('Registering the google music manager...')
        cred_path = os.path.join(os.path.expanduser('~'), '.gmusicfs.ocred')
        if not os.path.isfile(cred_path):
            log.info('Authorizing GMusicFS application against Google...')
            self.manager.perform_oauth(storage_filepath=cred_path)
            os.chmod(cred_path, 0600)
        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)
        self.manager.login(cred_path, self.manager_id, 'GMusicFS')
        log.info('Successfully registered the google music manager...')

    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:
            # Prefer the album artist over the track artist if there is one:
            artist = normalize(track['artist'])
            # Get the Album object if it already exists:
            key = '%s|||%s' % (formatNames(artist),
                               formatNames(normalize(track['album'])))
            album = all_artist_albums.get(key, None)
            if not album:
                # New Album
                if artist == '':
                    artist = 'unknown'
                album = all_artist_albums[key] = Album(
                    self, formatNames(normalize(track['album'])))
                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]

    def cleanup(self):
        pass
Example #32
0
class FreeClient(Client):
    """
    Client for free users with limited functionality.
      Free users only have access to songs that they have either purchased
      or uploaded, and they must be downloaded before they can be played.
      Artists and albums cannot be generated, so the expand and radio methods have no use.
    """
    def __init__(self):
        """
        Log into Musicmanager and get the library, either by loading an
          existing library file, or by generating a new one.
        """
        self.kind = 'free'
        self.mm = Musicmanager()
        self.mm.login()
        self.songs = []
        self.load_library()
        if not self.songs:
            self.gen_library()

    def load_library(self):
        path = join(common.DATA_DIR, 'library.zip')
        common.w.outbar_msg('Loading library...')
        if not isfile(path):
            common.w.addstr(common.w.infobar, 'Could not find library file.')
            return
        try:
            with zipfile.ZipFile(path) as z:
                try:
                    lib = json.loads(z.read('library.json').decode('utf-8'))
                except json.JSONDecodeError:  # The .json file is invalid.
                    common.w.addstr(common.w.infobar,
                                    'Library file is corrupt.')
                    return
        except zipfile.BadZipFile:  # The .zip file is invalid.
            common.w.addstr(common.w.infobar, 'Library file is corrupt.')
            return

        for item in lib['songs']:
            try:
                self.songs.append(
                    music_objects.LibrarySong(item, source='json'))
            except KeyError:  # The file has the wrong data.
                common.w.addstr(common.w.infobar, 'Library file is corrupt.')
                return

        l = len(self.songs)
        common.w.outbar_msg('Loaded %s song%s.' % (l, '' if l is 1 else 's'))

    def gen_library(self):
        ids = []  # Avoid duplicates between purchased and uploaded songs.
        common.w.outbar_msg('Generating your library...')

        for song in self.mm.get_uploaded_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        for song in self.mm.get_purchased_songs():
            if song['id'] not in ids:
                self.songs.append(music_objects.LibrarySong(song))
                ids.append(song['id'])
        # Todo: Use something other than json for library storage since it
        # doesn't really make logical sense (songs is a list, not a dict),
        # but for now it's very easy to use.
        with zipfile.ZipFile(join(common.DATA_DIR, 'library.zip'), 'w') as z:
            z.writestr('library.json', json.dumps({'songs': self.songs}))
        l = len(self.songs)
        common.w.outbar_msg('Generated %d song%s.' %
                            (l, '' if l is 1 else 's'))
        common.w.now_playing()

    def expand(self, arg=None):
        """
        Artists/albums cannot be generated. so free users cannot expand songs..

        Keyword arguments:
        arg=None: Irrelevant.
        """
        common.q.error_msg('Free users cannot use expand')

    def radio(self, arg=None):
        """
        Artists/albums cannot be generated. so free users cannot create radio stations.

        Keyword arguments:
        arg=None: Irrelevant.
        """
        common.q.error_msg('Free users cannot use radio')

    def search(self, query):
        """
        Search the library for some query. and update the
          view with the results.

        Keyword arguments:
        query=None: The search query.
        """
        if query is None:
            common.w.error_msg('Missing search query')
            return

        # Save the current view in case there are no results.
        cache = common.v.copy()

        if common.w.curses:
            limit = common.w.main.ylimit - 4
        else:
            limit = 10
        common.w.outbar_msg('Searching for \'%s\'...' % query)
        common.v.clear()
        count, query = 0, query.lower()  # Search is case-insensitive.
        for song in self.songs:
            if any(query in song[k].lower()
                   for k in ('name', 'artist', 'album')):
                count += 1
                common.v['songs'].append(song)
                if count == limit:
                    break
        common.w.outbar_msg('Search returned %d results.' % len(common.v))

        if common.v.is_empty():
            common.v.replace(cache)
Example #33
0
class GoogleMusic(object):
    def __init__(self, config, log=print):
        self.OAUTH_PATH = config.get('oauth_path', '/tmp/oauth.cred')
        self.mm = Musicmanager()
        if os.path.isfile(self.OAUTH_PATH):
            success = self.mm.login(oauth_credentials=self.OAUTH_PATH)
            if not success:
                self.mm.perform_oauth(storage_filepath=self.OAUTH_PATH,
                                      open_browser=True)
        else:
            self.mm.perform_oauth(storage_filepath=self.OAUTH_PATH,
                                  open_browser=True)
        random.seed()
        self.songs = self.mm.get_uploaded_songs()
        self.queue = Queue()
        self.thread = None
        self.log = log
        self._enqueue_output()

    def _enqueue_output(self):
        song = random.choice(self.songs)
        self.log("get song id" + song['id'])
        retry = 3
        while retry > 0:
            try:
                filename, audio = self.mm.download_song(song['id'])
                if len(audio) == 0:
                    self.log("audio size 0")
                    song = random.choice(self.songs)
                    continue

                filelike = StringIO.StringIO(audio)
                metadata = mutagen.File(filelike)
                output = {
                    'song_length': 0,
                    'album': '',
                    'artist': '',
                    'title': '',
                    'audio': audio
                }

                if metadata:
                    output['song_length'] = metadata.info.length
                    output['album'] = fix_name(
                        (metadata.tags or metadata).get('TALB', dummy).text[0])
                    output['artist'] = fix_name(
                        (metadata.tags or metadata).get('TPE1', dummy).text[0])
                    output['title'] = fix_name(
                        (metadata.tags or metadata).get('TIT2', dummy).text[0])

                self.queue.put(output)
                break
            except CallFailure:
                self.log("call failure")
                song = random.choice(self.songs)
                retry -= 1

        if retry == 0:
            self.log("Google Music download fail, please restart the program")
            self.queue.put({})

    def get(self):
        # TODO: set timeout from config, blacklist this instance when retry fail
        output = self.queue.get(block=True)
        self.thread = StoppableThread(target=self._enqueue_output)
        self.thread.daemon = True
        self.thread.start()
        return output
Example #34
0
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""


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

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

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

        print "Authenticated"
        print ""


    def sync_playlist(self, filename, remove_missing=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.wc.create_playlist(title)]
        print ""

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

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

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

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

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

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

                try:
                    if result[0]:
                        song_id = result[0].itervalues().next()
                    else:
                        song_id = result[1].itervalues().next()
                    print "   upload complete [%s]" % song_id
                except:
                    print "      upload failed - skipping"

            if not song_id:
                failed_files += 1
                continue

            added = self.wc.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.wc.remove_songs_from_playlist(plid, s.id)
                time.sleep(.3) # Don't spam the server too fast...
                removed_files += 1

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


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

    def file_already_in_list(self, filename, goog_songs):
        tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            if self.tag_compare(goog_songs[i], tag):
                goog_songs.pop(i)
                return True
            i += 1
        return False

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

    def find_song(self, filename):
        tag = self.get_id3_tag(filename)
        results = self.wc.search(tag['title'])
        # 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'])
        for r in results['song_hits']:
            if self.tag_compare(r, tag):
                # TODO: add rough time check to make sure its "close"
                return r
        return None

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

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

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
            # Join the two strings in order to form the full filepath.
            filepath = path.join(root, filename)
            file_paths.append(filepath)
    return file_paths


def uploadfiles(api, files):
    for f in files:
        upload = api.upload(f, transcode_quality="320k", enable_matching=True)
        print(upload)


def get_dir():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-dir', action='store', dest='dir', required=True,
        help='Full directory path from which to upload songs')
    args = parser.parse_args()
    return args.dir

if __name__ == "__main__":
    directory = get_dir()

    client = Musicmanager()
    logged_in = client.login()

    if logged_in:
        print "Successfully logged in. \n" \
              "Attempting upload songs in directory {}".format(directory)
        uploadfiles(client, get_file_paths(directory))
Example #36
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()
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists['user'])
        print ""


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

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

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

        print "Authenticated"
        print ""


    def sync_playlist(self, artist_title_array, playlist_title = -99):
        if playlist_title == -99:
            title = "GMusicSync Playlist %3d"%time.time()
        else: title = str(playlist_title)
        print "Synching playlist: %s" % title
        if title not in self.playlists['user']:
            print "   didn't exist... creating..."
            self.playlists['user'][title] = [self.wc.create_playlist(title)]
        print ""

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

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

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

        for fn in pc_songs:
            if self.file_already_in_list(fn, goog_songs):
                existing_files += 1
                continue
            print ""
            try:
                print "Adding: %s - %s"%(fn[0],fn[1])
            except:
                print "Incorrect format for %r, expecting ('artist','title')"%fn
                continue
            online = self.find_song(fn)
            song_id = None
            if online:
                song_id = online['id']
                print "   already uploaded [%s]" % song_id
            else:
                print "   Sorry, can't find song."

            if not song_id:
                failed_files += 1
                continue

            added = self.wc.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

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


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

    def file_already_in_list(self, artist_title, goog_songs):
        i = 0
        while i < len(goog_songs):
            if self.song_compare(goog_songs[i], artist_title):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def find_song(self, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except: return None
        results = self.wc.search(title)
        print "\t",results[:2]
        for r in results['song_hits']:
            if self.song_compare(r, artist_title):
                return r
        return None

    def song_compare(self, g_song, artist_title):
        try:
            artist = artist_title[0]
            title = artist_title[1]
        except: return False
        # TODO: add fuzzy matching
        return g_song['title'].lower() == title.lower() and\
               g_song['artist'].lower() == artist.lower()

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == '/' and '\\' not in full_path:
            return full_path
        if os.sep == '\\' and '\\' in full_path:
            return full_path
        if '\\' not in full_path:
            return full_path
        return os.path.normpath(full_path.replace('\\', '/'))
Example #38
0
from gmusicapi import Musicmanager
from os import listdir
from os.path import isfile, join
import os
import time
import subprocess

api = Musicmanager()
api.login()
mypath = '/home/pi/musics'
while True:
    onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]
    if len(onlyfiles) > 0:
        time.sleep(5)
        for file in onlyfiles:
            print(file)
            api.upload(mypath + '/' + file)
            os.remove(mypath + '/' + file)
class MusicSync(object):
    def __init__(self, email=None, password=None):
        self.mm = Musicmanager()
        self.wc = Webclient()
        self.mc = Mobileclient()
        if not email:
            email = raw_input("Email: ")
        if not password:
            password = getpass()

        self.email = email
        self.password = password

        self.logged_in = self.auth()

        print "Fetching playlists from Google..."
        self.playlists = self.wc.get_all_playlist_ids(auto=False)
        print "Got %d playlists." % len(self.playlists["user"])
        print ""

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

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

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

        print "Authenticated"
        print ""

    def add_rhapsody_playlist(self, filename, remove_missing=False):
        filename = self.get_platform_path(filename)
        os.chdir(os.path.dirname(filename))
        # playlist_title = os.path.splitext(os.path.basename(filename))[0]
        print "Synching File: %s" % filename

        print "Parsing Songs from %s" % filename
        pc_songs = self.get_songs_from_file(filename)
        # print (pc_songs)
        print "%d songs in local file: %s" % (len(pc_songs), filename)

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

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

        for song in pc_songs:
            playlist_title = song["playlist"]
            if playlist_title not in self.playlists["user"]:
                self.playlists["user"][playlist_title] = [self.mc.create_playlist(playlist_title)]
                time.sleep(0.7)
        print "Starting Playlist Sync with Google music..."
        for song in pc_songs:
            # print song

            plid = ""

            print "--------------------------------"
            print ""
            print "Playlist: %s" % song["playlist"]
            print "Artist: %s" % song["artist"]
            print "Song: %s" % song["title"]
            print "Album: %s" % song["album"]

            playlist_title = song["playlist"]

            plid = self.playlists["user"][playlist_title][0]

            goog_songs = self.wc.get_playlist_songs(plid)

            if self.song_already_in_list(song, goog_songs):
                existing_files += 1
                print "Result: Song Already Added"
                continue
            print "Total %d songs in Google playlist: %s" % (len(goog_songs), playlist_title)
            print "%s - %s,   didn't exist...Will try to add..." % (song["artist"], song["title"])

            print ""
            print "--------------------------------"
            results = self.mc.search_all_access(song["title"], max_results=50)
            nid = self.filter_search_results(results, song)
            print "AA nId: %s " % nid
            if nid:
                song_id = self.mc.add_aa_track(nid)
                added = self.wc.add_songs_to_playlist(plid, song_id)

                print "Playlist UUid: %s" % plid
                print "Song ID: %s" % song_id
                time.sleep(0.3)  # Don't spam the server too fast...
                print "Result: done adding to playlist"
                added_files += 1
                continue
            else:
                query = "%s %s" % (song["artist"], song["title"].split(" ")[0])
                print "Query %s" % query
                results = self.mc.search_all_access(query, max_results=50)
                nid = self.filter_search_results(results, song)
                if nid:
                    song_id = self.mc.add_aa_track(nid)
                    added = self.wc.add_songs_to_playlist(plid, song_id)

                    print "Playlist UUid: %s" % plid
                    print "Song ID: %s" % song_id
                    time.sleep(0.3)  # Don't spam the server too fast...
                    print " -- done adding to playlist"
                    added_files += 1
                    continue
            print "Result: NID Blank, Song not Found in All Access"

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

    def get_songs_from_file(self, filename):
        songs = []
        f = codecs.open(filename, encoding="utf-8")
        for line in f:
            line = line.rstrip().replace(u"\ufeff", u"")
            if line == "" or line[0] == "#":
                continue
            la = line.split("\\")
            regex_filter = "[^A-Za-z0-9\,\-\.\ \(\)'\!\?\$\/ \& \:]"

            artist = re.sub(regex_filter, "", la[1])
            playlist = re.sub(regex_filter, "", la[0])
            album = re.sub(regex_filter, "", la[2])
            title = re.sub(regex_filter, "", la[3])

            # print "Filtered Strings:"
            # print "Artist: %s" % artist
            # print "Playlist: %s" % playlist
            # print "Song: %s" % title
            # print "Album: %s" % album

            dt = {"playlist": playlist, "artist": artist, "album": album, "title": title}
            # print (dt)

            songs.append(dt)
        f.close()
        return songs

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

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

    def song_already_in_list(self, song, goog_songs):
        # tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            # print goog_songs
            if self.tag_compare(goog_songs[i], song):
                goog_songs.pop(i)
                return True
            i += 1
        return False

    def file_already_in_list(self, filename, goog_songs):
        tag = self.get_id3_tag(filename)
        i = 0
        while i < len(goog_songs):
            if self.tag_compare(goog_songs[i], tag):
                goog_songs.pop(i)
                return True
            i += 1
        return False

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

    def find_song(self, filename, plid):
        tag = self.get_id3_tag(filename)
        print "Song Tag: %s " % tag
        print "Filename: %s" % filename
        ws_plids = []
        ws_plids.append(plid)
        print (ws_plids)
        playlists = self.wc.get_all_playlist_ids()
        print (playlists)
        results = self.wc.get_playlist_songs(ws_plids)
        # NOTE - dianostic print here to check results if you're creating duplicates
        print results
        print "%s ][ %s ][ %s ][ %s" % (tag["title"], tag["artist"], tag["album"], tag["track"])
        for r in results:
            if self.tag_compare(r, tag):
                # TODO: add rough time check to make sure its "close"
                return r
        return None

    def filter_search_results(self, results, song):
        # Try Exact Matching
        for g_song in results["song_hits"]:
            if self.tag_compare(g_song["track"], song):
                return g_song["track"]["nid"]
            elif self.song_compare(g_song["track"], song, "artist"):
                # try just the artist
                return g_song["track"]["nid"]
            elif self.song_compare(g_song["track"], song, "part-song"):
                # try part of song and artist
                return g_song["track"]["nid"]
        return None

    def song_compare(self, g_song, tag, type):
        if "track" not in g_song:
            g_song["track"] = 0
        title_parts = tag["title"].split("(")  # removing shit like (featuring wiz)
        tp = title_parts[0].split(" ")  # First word maybe
        if "artist" in type:
            return g_song["artist"].lower() == tag["artist"].lower()
        if "part-song" in type:
            return g_song["title"].find(tp[0]) and g_song["artist"].lower() == tag["artist"].lower()

        return None

    def tag_compare(self, g_song, tag):
        if "track" not in g_song:
            g_song["track"] = 0

        return (
            g_song["title"].split(" ")[0].lower() == tag["title"].split(" ")[0].lower()
            and g_song["artist"].lower() == tag["artist"].lower()
        )

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

    def get_platform_path(self, full_path):
        # Try to avoid messing with the path if possible
        if os.sep == "/" and "\\" not in full_path:
            return full_path
        if os.sep == "\\" and "\\" in full_path:
            return full_path
        if "\\" not in full_path:
            return full_path
        return os.path.normpath(full_path.replace("\\", "/"))
Example #40
0
class Gmusic(object):
    def __init__(self, playlists_to_sync, credentials_storage_location, debug):
        self.playlists_to_sync = playlists_to_sync
        self.credentials_storage_location = credentials_storage_location
        self._client = Mobileclient(debug_logging=debug)
        self._manager = Musicmanager(debug_logging=debug)

    def client_login(self):
        credentials = self.credentials_storage_location

        if not os.path.isfile(credentials):
            credentials = self._client.perform_oauth(
                storage_filepath=self.credentials_storage_location,
                open_browser=True)

        if not self._client.oauth_login(
                device_id=Mobileclient.FROM_MAC_ADDRESS,
                oauth_credentials=credentials,
        ):
            logger.error("Gmusic mobile client authentication failed")
            return False

        logger.info("Gmusic mobile client authentication succeeded.")
        return True

    def manager_login(self):
        credentials = self.credentials_storage_location

        if not os.path.isfile(credentials):
            credentials = self._manager.perform_oauth(
                storage_filepath=self.credentials_storage_location,
                open_browser=True)

        if not self._manager.login(oauth_credentials=credentials, ):
            logger.error("Gmusic music manager authentication failed")
            return False

        logger.info("Gmusic music manager authentication succeeded.")
        return True

    @property
    def client(self):
        if not self._client.is_authenticated():
            self.client_login()
        return self._client

    @property
    def manager(self):
        if not self._manager.is_authenticated():
            self.manager_login()
        return self._manager

    @cached_property
    def uploaded_songs(self):
        return {song['id']: song for song in self.manager.get_uploaded_songs()}

    @property
    def _playlists(self):
        playlists = self.client.get_all_user_playlist_contents()
        logger.debug("Loaded {} playlists".format(len(playlists)))
        return playlists

    @cached_property
    def playlists(self):
        playlists_to_sync = []
        for playlist in self._playlists:
            if playlist['name'] in self.playlists_to_sync:
                playlists_to_sync.append(playlist)
        return playlists_to_sync

    def get_latest_addition_date(self, playlist):
        lastModified = playlist.get('lastModifiedTimestamp')
        if lastModified:
            return datetime.fromtimestamp(int(lastModified) /
                                          10**6).replace(tzinfo=pytz.utc)

        return None
shutil.rmtree(mypath, ignore_errors=True)
os.mkdir(mypath)

# Gets URL of playlist
url = input("Enter Youtube Playlist link (press enter for default): ")
if (url == ""):
    url = default_url

# Sets up Google Music
api = Mobileclient()
logged_in = False
while (not logged_in):
    email = input("\nEmail: ")
    password = input("Password: "******"\n\nDownloading Videos")
pl = Playlist(url)
pl.download_all(mypath)

# Gets list of all files
onlyfiles = [f for f in listdir(mypath) if isfile(join(mypath, f))]

# Converts each MP4 to audio
num_digits = len(
    str(len(onlyfiles))
)  # Determines the number of letters to take off the beginning of the audio file name
print("\n\nConverting to Audio")
Example #42
0
def api_init():
	api = Musicmanager()
	api.login()

	return api
#!/usr/bin/env python

"""
An upload script for Google Music using https://github.com/simon-weber/Unofficial-Google-Music-API.
You may contact the author (thebigmunch) in #gmusicapi on irc.freenode.net.
"""

import os
import sys
from gmusicapi import Musicmanager

input = sys.argv[1:] if len(sys.argv) > 1 else '.'
formats = ('.mp3', '.flac', '.ogg', '.m4a', '.m4b', '.wma')

MM = Musicmanager(debug_logging=False)


def do_auth():
	"""
	Authenticates the MM client.
	"""

	attempts = 0

	# Attempt to login. Perform oauth only when necessary.
	while attempts < 3:
		if MM.login():
			break
		MM.perform_oauth()
		attempts += 1
Example #44
0
def get_musicmanager(debug=True):
    mm = Musicmanager(debug_logging=debug)
    if not mm.login():
        mm.perform_oauth()
    return mm
Example #45
0
#!/usr/bin/env python2
# see http://unofficial-google-music-api.readthedocs.org/en/latest/usage.html#usage
# arch linux 'pacman -S python2-pip && pip2 install gmusicapi'

from gmusicapi import Musicmanager
from gmusicapi.compat import my_appdirs
import sys
import os.path

mm = Musicmanager()

# TODO use generic path for credentials
OAUTH_FILEPATH = os.path.join(my_appdirs.user_data_dir, 'oauth.cred')
if not os.path.isfile(OAUTH_FILEPATH):
    mm.perform_oauth()

mm.login()
# TODO handle errors (existing tracks/duplicates ...)
# TODO handle errors (existing tracks/duplicates ...)
track = sys.argv[1]
uploaded, matched, not_uploaded = mm.upload(track)
if uploaded[track]:
    sys.exit(0)
sys.exit(1)
Example #46
0
class GMClient(object):
    'Wrapper class of gmusicapi.Mobileclient'

    def __init__(self):
        # Aplying patch to session.Musicmanager
        session.Musicmanager.login = MethodType(patched_musicmanaer_login,
                                                None, session.Musicmanager)
        self.man = Musicmanager(verify_ssl=False)

        self.all_songs = None

    def login(self):
        if not os.path.exists(OAUTH_PATH):
            logging.error('No {} exists'.format(OAUTH_PATH))
            raise Exception('No {} exists'.format(OAUTH_PATH))
        else:
            self.man.login(oauth_credentials=OAUTH_PATH,
                           uploader_name='raspi_home')
            logging.info('Success!')

        # These are required to change meta data.
        # raspi_home does not require it.
        # if ('GOOGLE_PLAY_MUSIC_PASS' in os.environ and
        #     'GOOGLE_PLAY_MUSIC_USER' in os.environ):
        #     self.api = Mobileclient()
        #     self.api.login(os.environ['GOOGLE_PLAY_MUSIC_USER'],
        #                    os.environ['GOOGLE_PLAY_MUSIC_PASS'],
        #                    Mobileclient.FROM_MAC_ADDRESS)
        #     logging.info('Logged in to google music')
        #     self.is_available = True
        # else:
        #     logging.warn('environmental variable GOOGLE_PLAY_MUSIC_PASS or GOOGLE_PLAY_MUSIC_USER'
        #                  ' is not available')
        #     self.api = None

    def oauth(self):
        'Run oauth for uploading/downloading songs'
        oauth_dir = os.path.dirname(OAUTH_PATH)
        if not os.path.exists(oauth_dir):
            logging.info('No oauth directory, create it')
            os.makedirs(oauth_dir)
        self.man.perform_oauth(open_browser=False, storage_filepath=OAUTH_PATH)

    # methods communicating with google server
    def update_songs(self):
        # if self.api is not None:
        #     self.all_songs = self.api.get_all_songs()
        # else:
        #     self.all_songs = []
        self.all_songs = self.man.get_uploaded_songs()

    def get_all_songs(self):
        if self.all_songs is None:
            self.update_songs()
        return self.all_songs

    def get_songs(self, artist=None):
        return [
            song for song in self.get_all_songs() if song['artist'] == artist
        ]

    def upload(self, file):
        if not os.path.exists(file):
            logging.error('No {} exists'.format(file))
        else:
            (uploaded, matched,
             not_uploaded) = self.man.upload([file], enable_matching=True)
            if not_uploaded:
                logging.error('not uploaded because {}'.format(not_uploaded))

    def has_song(self, title):
        return title in [song['title'] for song in self.get_all_songs()]