Example #1
0
    def __init__(self, hass, config):
        """Initialize the books authors."""
        global GM_DEV_KEY
        global G_GM_MOBILE_CLIENT_API
        self.hass = hass
        self.all_gm_tracks = []
        self.selected_books = []
        _LOGGER.info("GM_USER: "******" GM_PASS: *******" +
                     " GM_DEV_KEY: " + str(GM_DEV_KEY))
        from gmusicapi import Mobileclient

        G_GM_MOBILE_CLIENT_API = Mobileclient()

        # if GM_DEV_KEY is None:
        #     G_GM_MOBILE_CLIENT_API.login(GM_USER, GM_PASS, Mobileclient.FROM_MAC_ADDRESS)
        # else:
        #     G_GM_MOBILE_CLIENT_API.login(GM_USER, GM_PASS, GM_DEV_KEY)
        #
        G_GM_MOBILE_CLIENT_API.oauth_login("3cf7d4cc166ab0ee")
        if not G_GM_MOBILE_CLIENT_API.is_authenticated():
            _LOGGER.error("Failed to log in, check Google Music api")
            return False
        else:
            _LOGGER.info("OK - we are in Google Music")
            registered_devices = G_GM_MOBILE_CLIENT_API.get_registered_devices(
            )
Example #2
0
def get_gmusic_playlists(username, password):
    api = Mobileclient()
    print(username + ":" + password)
    logged_in = api.login(username, password, Mobileclient.FROM_MAC_ADDRESS)

    if not logged_in:
        print("Login failed.")

    if api.is_authenticated():
        playlists = api.get_all_user_playlist_contents()

        output_dict = {}
        for playlist in playlists:
            name = playlist["name"]
            tracks = playlist["tracks"]

            for track in tracks:
                track = track["track"]
                artist = track["artist"]
                title = track["title"]

                if name in output_dict:
                    output_dict[name].append((artist, title))
                else:
                    output_dict[name] = [(artist, title)]

        return output_dict

    return None
Example #3
0
def gpm_login():
    client = Mobileclient()
    oauth = client.perform_oauth(open_browser=True)
    client.oauth_login(Mobileclient.FROM_MAC_ADDRESS,
                       oauth_credentials = oauth,
                       locale = 'en_US')
    if client.is_authenticated():
        print('👌')
    return client
Example #4
0
 def Google_Auth(self):
     api = Mobileclient()
     attempts = 0
     while not self.logged_in and attempts < 3:
         self.logged_in = api.login(self.username, self.password,
                                    self.devId)
         attempts += 1
     if api.is_authenticated():
         self.logged_in = True
     return api
Example #5
0
    def get_stream_client(self):
        device_id = self.get_device_id()
        client = Mobileclient(False, False, True)
        logger.info("Logging in '%s' with device id '%s'." % (self.username, device_id))
        client.login(self.username, self.password, device_id)

        if not client.is_authenticated():
            raise Exception("Client couldn't log in.")

        return client
Example #6
0
class GPM_client:
    def __init__(self):
        logging.info("Starting GPM client")
        self.gpm_client = Mobileclient()
        # login
        while not self.gpm_client.is_authenticated():
            logging.info("Logging you in...")
            if not self.gpm_client.oauth_login(device_id=Mobileclient.FROM_MAC_ADDRESS, oauth_credentials='./.gpmtoken'):
              logging.debug("No previous credentials - performing Oauth")
              self.gpm_client.perform_oauth(open_browser=True, storage_filepath='./.gpmtoken') 
Example #7
0
def get_authenitcated_client():
    email = input("Email: ")
    password = getpass.getpass("Password: "******"Failied to authenticate, try again.")
        return get_authenitcated_client()
    return client
Example #8
0
class GoogleMusic(object):
    def __init__(self):
        self.webclient = Webclient()
        self.mobileclient = Mobileclient()

    def is_authenticated(self):
        if not self.webclient.is_authenticated():
            if self.mobileclient.is_authenticated():
                return True

        return False

    def login(self, username, password):
        if not self.is_authenticated():
            try:
                self.mobileclient.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
                self.webclient.login(username, password)
            except Exception as e:
                raise Exception('Couldn\'t log into Google Music: ' + e.message)

    def search(self, query, kind):
        if self.is_authenticated():
            results = self.mobileclient.search(query)[kind + '_hits']

            return results

    def get_track(self, store_id):
        return self.mobileclient.get_track_info(store_id)

    def save_stream(self, track, destination):
        if self.is_authenticated():
            with open(destination, 'w+b') as stream_file:
                url = self.mobileclient.get_stream_url(track.get('storeId'))

                stream_file.truncate(0)
                stream_file.seek(0, 2)
                audio = self.webclient.session._rsession.get(url).content
                stream_file.write(audio)

            tag = easyid3.EasyID3()
            tag['title'] = track.get('title').__str__()
            tag['artist'] = track.get('artist').__str__()
            tag['album'] = track.get('album').__str__()
            tag['date'] = track.get('year').__str__()
            tag['discnumber'] = track.get('discNumber').__str__()
            tag['tracknumber'] = track.get('trackNumber').__str__()
            tag['performer'] = track.get('albumArtist').__str__()
            tag.save(destination)

            tag = mp3.MP3(destination)
            tag.tags.add(
                id3.APIC(3, 'image/jpeg', 3, 'Front cover', urllib.urlopen(track.get('albumArtRef')[0].get('url')).read())
            )
            tag.save()
def get_google_playlists():
    print("Retreiving playlists from Google Music.")
    playlists_path = f"{state_dir}/playlists.json"

    if os.path.exists(playlists_path) and not force_fetch:
        with open(playlists_path, 'r') as infile:
            return json.load(infile)

    print("Could not find saved favorites playlist, or force_fetch is True")
    credentials_path = f"{state_dir}/gmusic_credentials.json"

    mm = Mobileclient()
    if not os.path.exists(credentials_path):
        mm.perform_oauth(credentials_path, open_browser=True)

    mm.oauth_login(google_device_id, oauth_credentials=credentials_path)

    if mm.is_authenticated():
        print("Authenticated sucessfully!")
    else:
        print("Could not authenticate :(")
        raise SystemExit(1)

    playlists = mm.get_all_user_playlist_contents()
    playlist_names = [p['name'] for p in playlists]
    print(f'Found playlists: {playlist_names}')
    clean_playlists = []
    for p in playlists:
        playlist = {
            'name': p['name'],
            'tracks': [],
        }

        for track in p['tracks']:
            t = extract_google_track(track)
            if t is not None:
                playlist['tracks'].append(t)

        if len(playlist['tracks']) == 0:
            print(f"No tracks found in {p['name']}")
        else:
            clean_playlists.append(playlist)

    pprint(clean_playlists)
    if len(clean_playlists) == 0:
        print(f"No playlists with tracks found")
        raise SystemExit(1)

    with open(playlists_path, 'w') as outfile:
        json.dump(clean_playlists, outfile)

    return clean_playlists
Example #10
0
class AudioStream:
    __username = configuration.get('google_username')
    __password = configuration.get('google_password')
    __track_prefetch = 15
    __client = None
    __playlist = []

    def __init__(self, station_id = 'IFL'):
        self.__client = Mobileclient()
        self.__client.login(self.__username, self.__password, Mobileclient.FROM_MAC_ADDRESS)
        self.__playlist = self.__fetchTrackIDs(station_id)

    def __del__(self):
        if self.__client:
            self.__client.logout()

    def __fetchTrackIDs(self, station_id):
        if not self.__client or not self.__client.is_authenticated():
            logger.error("Client is not authenticated!")
            return []

        tracklist = self.__client.get_station_tracks(station_id, num_tracks=self.__track_prefetch)
        logger.info("Received tracks: %r" % json.dumps(tracklist))

        # Filter out explicit tracks, where non-explicit is explicitType=2
        tracklist = [track for track in tracklist if not 'explicitType' in track or track['explicitType'] == "2"]
        logger.info("Non-explicit tracks: %r" % json.dumps(tracklist))

        # Fetch both song IDs and Nautilus (old) IDs
        songids = [track['id'] for track in tracklist if 'id' in track]
        nautids = [track['nid'] for track in tracklist if 'nid' in track]

        return songids + nautids

    def pop(self):
        while self.__playlist:
            track_id = self.__playlist.pop()

            try:
                stream_url = self.__client.get_stream_url(track_id, quality='low')
                return stream_url
            except(exceptions.CallFailure):
                logger.warning("Failed to fetch Stream URL for ID %s" % track_id)

            raise IndexError("pop from empty list")

    def reverse(self):
        # Reverse just returns itself, since the playlist is already chaos
        return self

    def __len__(self):
        return len(self.__playlist)
Example #11
0
class GPM_client:
    def __init__(self):
        logging.info("Starting GPM client")
        self.gpm_client = Mobileclient()

        # login
        if self.gpm_client.is_authenticated():
            logging.info("Logging you in...")
            self.gpm_client.oauth_login(
                device_id=Mobileclient.FROM_MAC_ADDRESS)
        else:
            logging.debug("No previous credentials - performing Oauth")
            self.gpm_client.perform_oauth(open_browser=True)
Example #12
0
def login_to_gmusic(username, password):
    """
    DEPRECATED, use login_to_gmusic_with_oauth() instead
    params: username & password for your gmusic account
    returns the authenticated gmusic api object
    """
    gm_api = Mobileclient()
    gm_api.login(email=username, password=password, \
              android_id=gm_api.FROM_MAC_ADDRESS, locale=u'es_ES')
    if gm_api.is_authenticated():
        print('Logged in to Google Music')
        return gm_api
    else:
        sys.stderr.write('error logging in, exiting program')
        sys.exit()
Example #13
0
 def __init__(self, hass, config):
     """Initialize the books authors."""
     global G_GM_MOBILE_CLIENT_API
     self.hass = hass
     self.all_gm_tracks = []
     self.selected_books = []
     from gmusicapi import Mobileclient
     G_GM_MOBILE_CLIENT_API = Mobileclient()
     G_GM_MOBILE_CLIENT_API.login(GM_USER, GM_PASS, GM_DEV_KEY)
     if not G_GM_MOBILE_CLIENT_API.is_authenticated():
         _LOGGER.error("Failed to log in, check gmusicapi")
         return False
     else:
         _LOGGER.info("OK - we are in Gmusic")
         _LOGGER.info("devices: " +
                      str(G_GM_MOBILE_CLIENT_API.get_registered_devices()))
def create_playlist(playlist_name):

    if Mobileclient.is_authenticated(gpm):
        # the following prints all playlist names
        all_playlists = Mobileclient.get_all_playlists(gpm)
        for playlist in all_playlists:
            # print(playlist)
            temp = set()
            temp.add(playlist['name'])
            # print(temp)

        return gpm.create_playlist(playlist_name)
    else:
        print("Mobileclient could not authenticate.")

    Mobileclient.logout(gpm)
Example #15
0
def authorize_mobile(parameters):
    # api = Webclient()
    api = Mobileclient()
    # api = Musicmanager()
    # after running api.perform_oauth() once:
    # api.oauth_login('<a previously-registered device id>')
    # api.login(email=parameters.username, password=parameters.password)
    # => True
    if not os.path.exists(authorize_file):
        api.perform_oauth(authorize_file, True)

    api.oauth_login(Mobileclient.FROM_MAC_ADDRESS, authorize_file)
    if not api.is_authenticated():
        return None

    return api
Example #16
0
def main(argv=None):
    """
    Parse arguments, set up debugging and cache metadata.
    """
    api = Mobileclient()

    parser_args = get_parser_args(argv)

    logging_args = {
        'format': '%(asctime)s %(name)-12s %(levelname)-8s %(message)s',
        'datefmt': '%m-%d %H:%M'
    }
    if parser_args.debug_level:
        logging_args['level'] = DEBUG_LEVELS[parser_args.debug_level]

    logging.basicConfig(**logging_args)

    for item, value in list(vars(parser_args).items()):
        if item == "pwd":
            continue
        logging.info("Parser arg: %15s = %s", item, value)

    if not os.path.exists(api.OAUTH_FILEPATH):
        logging.info("performing oauth")

        perform_oauth_args = {'open_browser': parser_args.oauth_browser}
        if parser_args.oauth_creds_file:
            perform_oauth_args[
                'storage_filepath'] = parser_args.oauth_creds_file
        api.perform_oauth(**perform_oauth_args)

    logging.info("logging in to api")
    response = api.oauth_login(device_id=parser_args.device_id)

    try:
        assert api.is_authenticated()
        logging.debug("valid device IDs: %s",
                      pformat(api.get_registered_devices()))
        assert response
    except AssertionError:
        logging.warning("\n\n!!! failed to authenticate\n%s.",
                        traceback.format_exc())
        raise BadLoginException("Bad login. Check creds and internet")

        logging.info("api response: %s", response)
        cache_playlist(api, parser_args)
Example #17
0
def add_song_to_playlist(song, playlist_name):

    if Mobileclient.is_authenticated(gpm):

        # get_all_playlists() returns a dict object filled with
        # information about all of a user's playlists, and
        # each individual playlist is a dict as well.
        playlists = Mobileclient.get_all_playlists(gpm)
        # print playlists

        # one can get all playlist names by just accessing the
        # 'name' key of each playlist dict, as well as
        # compare the playlist name to a user given name
        playlist_pattern = re.compile(r'(?:.)*\s?(' + re.escape(playlist_name) + r')\s?(?:.)*', re.IGNORECASE)
        found = False

        for i in playlists:
            # print(i['name'])

            if re.match(playlist_pattern, i['name']):
                found = True
                print("Playlist found!")
                search = gpm.search(song, 1)
                
                for track in search['song_hits']:
                    temp = dict(track['track'])
                    # print(temp)
                    gpm.add_songs_to_playlist(i['id'], temp['storeId'])
                    print("Song " + temp['title'] + " was found, and placed in playlist: " + playlist_name)
                break

        if not found:
            i = create_playlist(playlist_name)
            print(playlist_name + ' was not found, but it was created.')

            search = gpm.search(song, 1)

            for track in search['song_hits']:
                temp = dict(track['track'])
                gpm.add_songs_to_playlist(i, temp['storeId'])
                print("Song " + temp['title'] + " was found, and placed in playlist: " + playlist_name)
    else:
        print('Mobileclient could not authenticate.')

    Mobileclient.logout(gpm)
def google_music_login():
    '''
    Ask for credentials and log into Google music.
    '''
    sys.stdout.write("Connecting to Google Music ...\n")
    api = Mobileclient()
    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():
        print("Login failed.", file=sys.stderr)
        return None
    sys.stdout.write("Successfully logged in.\n")
    return api
Example #19
0
class PlayMusic:
    def __init__(self, google_username, google_password):
        self.client = Mobileclient(validate=False)
        # generate a stable, unique android id
        h = hashlib.sha256()
        h.update(google_username)
        android_id = h.hexdigest()[:16]
        self.client.login(google_username, google_password, android_id)

    def is_authenticated(self):
        return self.client.is_authenticated()

    @staticmethod
    def track_url(play_track):
        return "https://play.google.com/music/m/%s" % play_track["nid"]

    @staticmethod
    def playlist_url(playlist_id):
        return "https://play.google.com/music/playlist/%s" % playlist_id

    def search_tracks(self, query):
        if len(query) >= MAX_QUERY_LENGTH:
            # long queries don't work for some reason
            # for example "The Moderately Talented Yet Attractive Young Woman vs. The Exceptionally Talented Yet Not
            # So Attractive Middle Aged Man / Sun Kil Moon / Among The Leaves"
            parts = query.split(" ")
            query = parts.pop(0)
            for part in parts:
                if len(query) + 1 + len(part) > MAX_QUERY_LENGTH:
                    break
                query += " " + part

        retries = RETRIES
        response = None
        while retries and not response:
            retries -= 1
            try:
                response = self.client.search_all_access(query)
            except Exception, e:
                if not retries:
                    raise e
                # sleep for two seconds before retrying
                time.sleep(2)
        return [PlayTrack(song["track"]) for song in response["song_hits"]]
Example #20
0
class PlayMusic():
    def __init__(self, google_username, google_password):
        self.client = Mobileclient(validate=False)
        # generate a stable, unique android id
        h = hashlib.sha256()
        h.update(google_username)
        android_id = h.hexdigest()[:16]
        self.client.login(google_username, google_password, android_id)

    def is_authenticated(self):
        return self.client.is_authenticated()

    @staticmethod
    def track_url(play_track):
        return 'https://play.google.com/music/m/%s' % play_track['nid']

    @staticmethod
    def playlist_url(playlist_id):
        return 'https://play.google.com/music/playlist/%s' % playlist_id

    def search_tracks(self, query):
        if len(query) >= MAX_QUERY_LENGTH:
            # long queries don't work for some reason
            # for example "The Moderately Talented Yet Attractive Young Woman vs. The Exceptionally Talented Yet Not
            # So Attractive Middle Aged Man / Sun Kil Moon / Among The Leaves"
            parts = query.split(' ')
            query = parts.pop(0)
            for part in parts:
                if len(query) + 1 + len(part) > MAX_QUERY_LENGTH:
                    break
                query += ' ' + part

        retries = RETRIES
        response = None
        while retries and not response:
            retries -= 1
            try:
                response = self.client.search_all_access(query)
            except Exception, e:
                if not retries:
                    raise e
                # sleep for two seconds before retrying
                time.sleep(2)
        return [PlayTrack(song['track']) for song in response['song_hits']]
Example #21
0
   def __init__(self, api: Mobileclient, hotkey_mgr: SystemHotkey, library: Library):
      self.initialized_val = Atomic(False)
      self.api = api
      self.hotkey_mgr = hotkey_mgr
      self.library = library
      if self.hotkey_mgr:
         self.setup_hotkeys()

      # List of track ids
      self.tracks_to_play = []
      self.current_track_index = Atomic(None)
      self.current_song_info = Atomic(None)

      self.player = None
      self.pending_events = []
      self.event_handler_thread = None

      if api.is_authenticated():
         self.initialize()
Example #22
0
File: app.py Project: kyeah/gspot
def login_google():
    """ Log into Google and retrieve user library and playlists """

    g = Mobileclient()
    logged_in = g.login(config.auth['GOOGLE_EMAIL'], 
                        config.auth['GOOGLE_PASSWORD'],
                        Mobileclient.FROM_MAC_ADDRESS)

    if not g.is_authenticated():
        log.error("Invalid Google email/password; exiting.")
        sys.exit(1)

    log.info("Retrieving Google Music playlists")
    g.playlists = g.get_all_user_playlist_contents()

    log.info("Retrieving Google Music library")
    g.library = get_google_library(g)

    return g
    def __init__(self, login=True, dry_run=False):
        if login:
            try:
                google_username = os.environ.get('USERNAME')
                google_password = os.environ.get('PASSWORD')

                api = Mobileclient()
                api.login(google_username, google_password,
                          Mobileclient.FROM_MAC_ADDRESS)
                if api.is_authenticated():
                    self.api = api
            except:
                print "ERROR: Unable to login with the credentials provided!"
                sys.exit(1)
        if dry_run:
            print "Dry-run mode enabled. Logging only. No changes will be made."
            self.dry_run = True
        else:
            self.dry_run = False
Example #24
0
    def get_library(mobile_client: Mobileclient) -> List[GpmTrack]:
        """
        Given an authenticated mobile client, return a list of GPM Tracks representing the users library

        Args:
            mobile_client (Mobileclient): Must be authenticated. Client is used to retrieve the library for the GPM
                user.

        Returns:
            List[GpmTrack]: A list of ``GpmTrack`` objects representing the user's library.

        """
        # Check if client isn't authenticated
        if not mobile_client.is_authenticated():
            raise UnauthenticatedClientException("Trying to get library with an unauthenticated mobile client")

        # Get the library as a list of dicts
        raw_tracks: List[dict] = mobile_client.get_all_songs()

        return [ApiWrapper.__map_dict_to_gpm_track(track) for track in raw_tracks]
Example #25
0
def get_google():
    global google_client
    if google_client is not None:
        return google_client

    credentials_path = f"{state_dir}/gmusic_credentials.json"

    google_client = Mobileclient()
    # mm.perform_oauth()
    if not os.path.exists(credentials_path):
        google_client.perform_oauth(credentials_path, open_browser=True)

    google_client.oauth_login(google_device_id,
                              oauth_credentials=credentials_path)
    if google_client.is_authenticated():
        print("Authenticated sucessfully!")
    else:
        print("Could not authenticate :(")
        raise SystemExit(1)

    return google_client
Example #26
0
def play_song_by_artist(song, artist):
    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)
            artist_pattern = re.compile(
                r'(?:.)*\s?(' + re.escape(artist) + r')\s?(?:.)*',
                re.IGNORECASE)

            btn = OnButtonPress()
            btn.start()

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

                if (re.match(song_pattern, song['title']) is not None and
                        re.match(artist_pattern, song['artist']) 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('Mobile client is not authenticated.')
        Mobileclient.logout(gpm)
Example #27
0
class IBCMusicClient():
    # Please have this be an absolute path
    SONG_DIR = "/home/pi/Desktop/JukeSite/songs"

    def __init__(self):
        self.api = None
        self.player = None

    def start(self):
        """
        Starts the MobileClient
        """
        self.api = Mobileclient()

    def stop(self):
        """
        Deletes MobileClient and sets self.api to default(None)
        """
        del self.api
        self.api = None

    def logon(self, email, password):
        """
        Logs onto google music as a mobile client. Returns true is sucessful.

        :param email: Email of the Google user
        :param password: Pass of the google user
        :return: Bool if connection was successful
        """
        if self.api is None:
            raise errors.MobileClientNotInitError(
                "The Client has not been init therefor it cannot logon.", 1000)

        try:
            res = self.api.login(email, password, self.api.FROM_MAC_ADDRESS)
        except AlreadyLoggedIn as e:
            self.api.logout()
            res = self.api.login(email, password, self.api.FROM_MAC_ADDRESS)

        del email
        del password
        return res

    def logout(self):
        """
        logs out of google music mobile client.

        :return: if it was succesful
        """
        return self.api.logout()

    def is_authenticated(self):
        if not self.api.is_authenticated():
            raise errors.SessionNotActive(
                "The session is no longer active. Either it timedout or you have not logged in",
                1001)

    def search_song(self, query):
        """
        Searchs for the given query and return the song results
        Will check for authentication.

        [{
            'track': {
                'album': 'Work Out',
                'albumArtRef': [{
                    'aspectRatio': '1',
                    'autogen': False,
                    'kind': 'sj#imageRef',
                    'url': 'http://lh5.ggpht.com/DVIg4GiD6msHfgPs_Vu_2eRxCyAoz0fFdxj5w...'
                }],
                'albumArtist': 'J.Cole',
                'albumAvailableForPurchase': True,
                'albumId': 'Bfp2tuhynyqppnp6zennhmf6w3y',
                'artist': 'J Cole',
                'artistId': ['Ajgnxme45wcqqv44vykrleifpji', 'Ampniqsqcwxk7btbgh5ycujij5i'],
                'composer': '',
                'discNumber': 1,
                'durationMillis': '234000',
                'estimatedSize': '9368582',
                'explicitType': '1',
                'genre': 'Pop',
                'kind': 'sj#track',
                'nid': 'Tq3nsmzeumhilpegkimjcnbr6aq',
                'primaryVideo': {
                    'id': '6PN78PS_QsM',
                    'kind': 'sj#video',
                    'thumbnails': [{
                        'height': 180,
                        'url': 'https://i.ytimg.com/vi/6PN78PS_QsM/mqdefault.jpg',
                        'width': 320
                    }]
                },
                'storeId': 'Tq3nsmzeumhilpegkimjcnbr6aq',
                'title': 'Work Out',
                'trackAvailableForPurchase': True,
                'trackAvailableForSubscription': True,
                'trackNumber': 1,
                'trackType': '7',
                'year': 2011
            },
            'type': '1'
        }]
        :param query: The song query
        :return: [list] all the song hits
        """
        self.is_authenticated()
        res = self.api.search(query)
        songs = res['song_hits']
        return songs

    def search_album(self, query):
        """
        Searchs for the given query and returns the album results.
        Will check for authenitcation.

        e.g return:
        [{
            'album': {
                'albumArtRef': 'http://lh5.ggpht.com/DVIg4GiD6msHfgPs_Vu_2eRxCyAoz0fF...',
                'albumArtist': 'J.Cole',
                'albumId': 'Bfp2tuhynyqppnp6zennhmf6w3y',
                'artist': 'J.Cole',
                'artistId': ['Ajgnxme45wcqqv44vykrleifpji'],
                'description_attribution': {
                    'kind': 'sj#attribution',
                    'license_title': 'Creative Commons Attribution CC-BY',
                    'license_url': 'http://creativecommons.org/licenses/by/4.0/legalcode',
                    'source_title': 'Freebase',
                    'source_url': ''
                },
                'explicitType': '1',
                'kind': 'sj#album',
                'name': 'Work Out',
                'year': 2011
            },
            'type': '3'
        }]

        :param query: [string] The album query
        :return: [list] A list of all the album hits
        """
        self.is_authenticated()
        res = self.api.search(query)
        albums = res['album_hits']
        return albums

    def get_album_info(self, album_id):
        """
        Returns information about an album

        e.g return:
        {
            'kind': 'sj#album',
            'name': 'Circle',
            'artist': 'Amorphis',
            'albumArtRef': 'http://lh6.ggpht.com/...',
            'tracks': [  # if `include_tracks` is True
            {
                'album': 'Circle',
                'kind': 'sj#track',
                'storeId': 'T5zb7luo2vkroozmj57g2nljdsy',  # can be used as a song id
                'artist': 'Amorphis',
                'albumArtRef': [
                {
                    'url': 'http://lh6.ggpht.com/...'
                }],
                'title': 'Shades of Grey',
                'nid': 'T5zb7luo2vkroozmj57g2nljdsy',
                'estimatedSize': '13115591',
                'albumId': 'Bfr2onjv7g7tm4rzosewnnwxxyy',
                'artistId': ['Apoecs6off3y6k4h5nvqqos4b5e'],
                'albumArtist': 'Amorphis',
                'durationMillis': '327000',
                'composer': '',
                'genre': 'Metal',
                'trackNumber': 1,
                'discNumber': 1,
                'trackAvailableForPurchase': True,
                'trackType': '7',
                'albumAvailableForPurchase': True
            }, # ...
            ],
            'albumId': 'Bfr2onjv7g7tm4rzosewnnwxxyy',
            'artistId': ['Apoecs6off3y6k4h5nvqqos4b5e'],
            'albumArtist': 'Amorphis',
            'year': 2013
        }

        :param album_id: The albumId
        :return: Dictionary in the format above
        """
        self.is_authenticated()
        return self.api.get_album_info(album_id)

    def get_song_info(self, song_id):
        """
        Returns information about a song

        e.g return
        {
            'album': 'Best Of',
            'kind': 'sj#track',
            'storeId': 'Te2qokfjmhqxw4bnkswbfphzs4m',
            'artist': 'Amorphis',
            'albumArtRef': [
            {
                'url': 'http://lh5.ggpht.com/...'
            }],
            'title': 'Hopeless Days',
            'nid': 'Te2qokfjmhqxw4bnkswbfphzs4m',
            'estimatedSize': '12325643',
            'albumId': 'Bsbjjc24a5xutbutvbvg3h4y2k4',
            'artistId': ['Apoecs6off3y6k4h5nvqqos4b5e'],
            'albumArtist': 'Amorphis',
            'durationMillis': '308000',
            'composer': '',
            'genre': 'Metal',
            'trackNumber': 2,
            'discNumber': 1,
            'trackAvailableForPurchase': True,
            'trackType': '7',
            'albumAvailableForPurchase': True
        }

        :param song_id: The songds storeId
        :return: A dict with the above information
        """
        self.is_authenticated()
        return self.api.get_track_info(song_id)

    def get_song_url(self, song_id):
        self.is_authenticated()
        res = self.api.get_stream_url(song_id)
        return res

    def download_song(self, song_id):
        """
        Download the song from the storeId.

        :param song_id: the 'storeId' of the specific song
        """
        url = self.get_song_url(song_id)
        song_file_path = "{}/{}.mp3".format(IBCMusicClient.SONG_DIR, song_id)
        if os.path.isfile(song_file_path):
            raise errors.SongAlreadyDownloadedException(
                "The song '{}' has already been downloaded and cached".format(
                    song_file_path), 8002)
        # This need to not use subprocessing
        command = ['wget', url, '-O', song_file_path]
        res = check_output(command)
        lines = res.decode().split('\n')
        error_lines = [line for line in lines if 'failed' in line]

        if len(error_lines) > 0:
            # We have an error
            raise errors.CannotDownloadSongError(
                "Could not download the given song. {}".format(
                    str(error_lines)), 1003)
Example #28
0
class Gmusic(object):
    """Class to handle Google Music-related functionality"""
    def __init__(self, bot):
        """ init """
        self.bot = bot
        self.mob = Mobileclient()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def find_playlists(self, searchterm):
        """ find all playlists that have a name containing 'searchterm' """
        all_plists = self.get_all_playlists()
        all_matches = all_plists
        all_terms = searchterm.split(' ')
        for term in all_terms:
            all_matches = [
                p for p in all_matches
                if p['name'].lower().find(term.lower()) != -1
            ]
        return all_matches
Example #29
0
try:
    jfile = open(hidden_vals)
except:
    print(
        'Need a file named ajsonhidden_vals.json in the current working directory with login information.'
    )
    sys.exit()

jstr = jfile.read()
jdata = json.loads(jstr)
gaccount = jdata['Gmusic login']['account']
gapi = jdata['Gmusic login']['api_key']
api.login(gaccount, gapi, Mobileclient.FROM_MAC_ADDRESS)
# => True

print(api.is_authenticated())


def gettracks(artistId, existing_nids):
    recentalbum = []
    try:
        results = api.get_artist_info(artistId,
                                      include_albums=True,
                                      max_top_tracks=20,
                                      max_rel_artist=5)
        albums = results['albums']
        for a in albums:
            if (str(a['year']) == '2017'):
                recentalbum.append(a)
    except Exception as e:
        print('Couldnt get an album')
                   oauth_credentials=credentials_filepath)
except Exception as e:
    valid_devices = e.valid_device_ids

#Complete the login process just using the first returned id, or this machine's MAC address if no id is returned.
if len(valid_devices) > 0:
    mc.oauth_login(device_id=valid_devices[0],
                   oauth_credentials=credentials_filepath)
else:
    print(
        "No device ids found, attempting to use this machine's MAC address...")
    mc.oauth_login(device_id=Mobileclient.FROM_MAC_ADDRESS,
                   oauth_credentials=credentials_filepath)

#Ensure the device is is authenticated (it probably is, since we were just able to login, but can't hurt to be explicit)
if mc.is_authenticated():
    print("Connected Successfully!")
else:
    print(
        "Could not connect to Play Music, authentication failure. Exiting...")
    exit(1)

#Ensure the device/account actually has a google play subscription and is able to play/download/etc content
if mc.is_subscribed:
    print("This account DOES have a Play Music subscription!")
else:
    print("This account deos NOT have a Play Music subscription! Exiting...")
    exit(1)

#Get a list of the songs already in the account's library so we can compare songs we're looking for to it and ensure we don't add multiples of songs
owned_songs = mc.get_all_songs()
Example #31
0
class Session(object):
    def __init__(self):
        self.api = None
        self.user = None
        self.lib_albums = {}
        self.lib_artists = {}
        self.lib_tracks = {}
        self.lib_playlists = {}
        self.lib_updatetime = 0
        self.sitdata = []
        self.sitbyid = {}
        self.sitdataupdtime = 0
        
    def dmpdata(self, who, data):
        uplog("%s: %s" % (who, json.dumps(data, indent=4)))

    # Look for an Android device id in the registered devices.
    def find_device_id(self, data):
        for entry in data:
            if "type" in entry and entry["type"] == u"ANDROID":
                # Get rid of 0x
                id = entry["id"][2:]
                uplog("Using deviceid %s" % id)
                return id
        return None
    
    def login(self, username, password, deviceid=None):
        self.api = Mobileclient(debug_logging=False)

        if deviceid is None:
            logged_in = self.api.login(username, password,
                                       Mobileclient.FROM_MAC_ADDRESS)
            if logged_in:
                # Try to re-login with a valid deviceid
                data = self.api.get_registered_devices()
                #self.dmpdata("registered devices", data)
                deviceid = self.find_device_id(data)
                if deviceid:
                    logged_in = self.login(username, password, deviceid)
        else:
            logged_in = self.api.login(username, password, deviceid)

        isauth = self.api.is_authenticated()
        #uplog("login: Logged in: %s. Auth ok: %s" % (logged_in, isauth))
        return logged_in

    def _get_user_library(self):
        now = time.time()
        if now - self.lib_updatetime < 300:
            return
        if self.lib_updatetime == 0:
            data = self.api.get_all_songs()
            #self.dmpdata("all_songs", data)
        else:
            data = self.api.get_all_songs(updated_after=datetime.datetime.fromtimestamp(self.lib_updatetime))
            #self.dmpdata("all_songs_since_update", data)
        self.lib_updatetime = now
        tracks = [_parse_track(t) for t in data]
        self.lib_tracks.update(dict([(t.id, t) for t in tracks]))
        for track in tracks:
            # We would like to use the album id here, but gmusic
            # associates the tracks with any compilations after
            # uploading (does not use the metadata apparently), so
            # that we can't (we would end up with multiple
            # albums). OTOH, the album name is correct (so seems to
            # come from the metadata). What we should do is test the
            # album ids for one album with a matching title, but we're
            # not sure to succeed. So at this point, the album id we
            # end up storing could be for a different albums, and we
            # should have a special library-local get_album_tracks
            self.lib_albums[track.album.name] = track.album
            self.lib_artists[track.artist.id] = track.artist
            
    def get_user_albums(self):
        self._get_user_library()
        return self.lib_albums.values()

    def get_user_artists(self):
        self._get_user_library()
        return self.lib_artists.values()

    def get_user_playlists(self):
        pldata = self.api.get_all_playlists()
        #self.dmpdata("playlists", pldata)
        return [_parse_playlist(pl) for pl in pldata]

    def get_user_playlist_tracks(self, playlist_id):
        self._get_user_library()
        # Unfortunately gmusic does not offer incremental updates for
        # playlists.  This means we must download all playlist data any
        # time we want an update.  Playlists include track information
        # for gmusic songs, so if a user has a lot of playlists this
        # can take some time.
        # For now, we only load the playlists one time for performance purposes
        if len(self.lib_playlists) == 0:
            data = self.api.get_all_user_playlist_contents()
            self.lib_playlists = dict([(pl['id'], pl) for pl in data])
        tracks = []
        if playlist_id in self.lib_playlists:
            for entry in self.lib_playlists[playlist_id]['tracks']:
                if entry['deleted']:
                    continue
                if entry['source'] == u'1':
                    tracks.append(self.lib_tracks[entry['trackId']])
                elif 'track' in entry:
                    tracks.append(_parse_track(entry['track']) )
        return tracks

    def create_station_for_genre(self, genre_id):
        id = self.api.create_station("station"+genre_id, genre_id=genre_id)
        return id

    def get_user_stations(self):
        data = self.api.get_all_stations()
        # parse_playlist works fine for stations
        stations = [_parse_playlist(d) for d in data]
        return stations

    def delete_user_station(self, id):
        self.api.delete_stations(id)

    # not working right now
    def listen_now(self):
        print("api.get_listen_now_items()", file=sys.stderr)
        ret = {'albums' : [], 'stations' : []}
        try:
            data = self.api.get_listen_now_items()
        except Exception as err:
            print("api.get_listen_now_items failed: %s" % err, file=sys.stderr)
            data = None

        # listen_now entries are not like normal albums or stations,
        # and need special parsing. I could not make obvious sense of
        # the station-like listen_now entries, so left them aside for
        # now. Maybe should use create_station on the artist id?
        if data:
            ret['albums'] = [_parse_ln_album(a['album']) \
                             for a in data if 'album' in a]
            #ret['stations'] = [_parse_ln_station(d['radio_station']) \
            #                   for d in data if 'radio_station' in d]
        else:
            print("listen_now: no items returned !", file=sys.stderr)
        print("get_listen_now_items: returning %d albums and %d stations" %\
              (len(ret['albums']), len(ret['stations'])), file=sys.stderr)
        return ret

    def get_situation_content(self, id = None):
        ret = {'situations' : [], 'stations' : []}
        now = time.time()
        if id is None and now - self.sitdataupdtime > 300:
            self.sitbyid = {}
            self.sitdata = self.api.get_listen_now_situations()
            self.sitdataupdtime = now

        # Root is special, it's a list of situations
        if id is None:
            ret['situations'] = [self._parse_situation(s) \
                                 for s in self.sitdata]
            return ret
        
        # not root
        if id not in self.sitbyid:
            print("get_situation_content: %s unknown" % id, file=sys.stderr)
            return ret

        situation = self.sitbyid[id]
        #self.dmpdata("situation", situation)
        if 'situations' in situation:
            ret['situations'] = [self._parse_situation(s) \
                                 for s in situation['situations']]
        if 'stations' in situation:
            ret['stations'] = [_parse_situation_station(s) \
                               for s in situation['stations']]

        return ret

    def _parse_situation(self, data):
        self.sitbyid[data['id']] = data
        return Playlist(id=data['id'], name=data['title'])
        
    def create_curated_and_get_tracks(self, id):
        sid = self.api.create_station("station"+id, curated_station_id=id)
        print("create_curated: sid %s"%sid, file=sys.stderr)
        tracks = [_parse_track(t) for t in self.api.get_station_tracks(sid)]
        #print("curated tracks: %s"%tracks, file=sys.stderr)
        self.api.delete_stations(sid)
        return tracks
    
    def get_station_tracks(self, id):
        return [_parse_track(t) for t in self.api.get_station_tracks(id)]
    
    def get_media_url(self, song_id, quality=u'med'):
        url = self.api.get_stream_url(song_id, quality=quality)
        print("get_media_url got: %s" % url, file=sys.stderr)
        return url

    def get_album_tracks(self, album_id):
        data = self.api.get_album_info(album_id, include_tracks=True)
        album = _parse_album(data)
        return [_parse_track(t, album) for t in data['tracks']]

    def get_promoted_tracks(self):
        data = self.api.get_promoted_songs()
        #self.dmpdata("promoted_tracks", data)
        return [_parse_track(t) for t in data]

    def get_genres(self, parent=None):
        data = self.api.get_genres(parent_genre_id=parent)
        return [_parse_genre(g) for g in data]
                
    def get_artist_info(self, artist_id, doRelated=False):
        ret = {"albums" : [], "toptracks" : [], "related" : []} 
        # Happens,some library tracks have no artistId entry
        if artist_id is None or artist_id == 'None':
            uplog("get_artist_albums: artist_id is None")
            return ret
        else:
            uplog("get_artist_albums: artist_id %s" % artist_id)

        maxrel = 20 if doRelated else 0
        maxtop = 0 if doRelated else 10
        incalbs = False if doRelated else True
        data = self.api.get_artist_info(artist_id, include_albums=incalbs,
                                        max_top_tracks=maxtop,
                                        max_rel_artist=maxrel)
        #self.dmpdata("artist_info", data)
        if 'albums' in data:
            ret["albums"] = [_parse_album(alb) for alb in data['albums']]
        if 'topTracks' in data:
            ret["toptracks"] = [_parse_track(t) for t in data['topTracks']]
        if 'related_artists' in data:
            ret["related"] = [_parse_artist(a) for a in data['related_artists']]
        return ret

    def get_artist_related(self, artist_id):
        data = self.get_artist_info(artist_id, doRelated=True)
        return data["related"]
    
    def search(self, query):
        data = self.api.search(query, max_results=50)
        #self.dmpdata("Search", data)

        tr = [_parse_track(i['track']) for i in data['song_hits']]
        ar = [_parse_artist(i['artist']) for i in data['artist_hits']]
        al = [_parse_album(i['album']) for i in data['album_hits']]
        #self.dmpdata("Search playlists", data['playlist_hits'])
        try:
            pl = [_parse_splaylist(i) for i in data['playlist_hits']]
        except:
            pl = []
        return SearchResult(artists=ar, albums=al, playlists=pl, tracks=tr)
Example #32
0
class GoogleMusic(object):
    def __init__(self):
        self.webclient = Webclient()
        self.mobileclient = Mobileclient()

    def is_authenticated(self):
        if self.webclient.is_authenticated():
            if self.mobileclient.is_authenticated():
                return True

        return False

    def login(self, username, password):
        if not self.is_authenticated():
            try:
                self.mobileclient.login(username, password)
                self.webclient.login(username, password)
            except:
                raise Exception('Couldn\'t log into Google Music')

    def search(self, query, kind):
        if self.is_authenticated():
            results = self.mobileclient.search_all_access(query)[kind + '_hits']

            return results

    def get_track(self, store_id):
        return self.mobileclient.get_track_info(store_id)

    def save_stream(self, track, destination):
        if self.is_authenticated():
            with open(destination, 'w+b') as stream_file:
                urls = self.webclient.get_stream_urls(track.get('storeId'))

                if len(urls) == 1:
                    stream_file.write(self.webclient.session._rsession.get(urls[0]).content)

                range_pairs = [[int(s) for s in val.split('-')]
                               for url in urls
                               for key, val in parse_qsl(urlparse(url)[4])
                               if key == 'range']

                for url, (start, end) in zip(urls, range_pairs):
                    stream_file.truncate(start)
                    stream_file.seek(0, 2)
                    audio = self.webclient.session._rsession.get(url).content
                    stream_file.write(audio)

            tag = easyid3.EasyID3()
            tag['title'] = track.get('title').__str__()
            tag['artist'] = track.get('artist').__str__()
            tag['album'] = track.get('album').__str__()
            tag['date'] = track.get('year').__str__()
            tag['discnumber'] = track.get('discNumber').__str__()
            tag['tracknumber'] = track.get('trackNumber').__str__()
            tag['performer'] = track.get('albumArtist').__str__()
            tag.save(destination)

            tag = mp3.MP3(destination)
            tag.tags.add(
                id3.APIC(3, 'image/jpeg', 3, 'Front cover', urllib.urlopen(track.get('albumArtRef')[0].get('url')).read())
            )
            tag.save()
Example #33
0
class GMusicSession(object):
    def __init__(self):
        super(GMusicSession, self).__init__()
        logger.info('Mopidy uses Google Music')
        self.api = Mobileclient()

    def login(self, username, password, deviceid):
        if self.api.is_authenticated():
            self.api.logout()
        try:
            self.api.login(username, password)
        except CallFailure as error:
            logger.error(u'Failed to login as "%s": %s', username, error)
        if self.api.is_authenticated():
            if deviceid is None:
                self.deviceid = self.get_deviceid(username, password)
            else:
                self.deviceid = deviceid
        else:
            return False

    def logout(self):
        if self.api.is_authenticated():
            return self.api.logout()
        else:
            return True

    def get_all_songs(self):
        if self.api.is_authenticated():
            return self.api.get_all_songs()
        else:
            return {}

    def get_stream_url(self, song_id):
        if self.api.is_authenticated():
            try:
                return self.api.get_stream_url(song_id, self.deviceid)
            except CallFailure as error:
                logger.error(u'Failed to lookup "%s": %s', song_id, error)

    def get_all_user_playlist_contents(self):
        if self.api.is_authenticated():
            return self.api.get_all_user_playlist_contents()
        else:
            return {}

    def get_shared_playlist_contents(self, shareToken):
        if self.api.is_authenticated():
            return self.api.get_shared_playlist_contents(shareToken)
        else:
            return {}

    def get_all_playlists(self):
        if self.api.is_authenticated():
            return self.api.get_all_playlists()
        else:
            return {}

    def get_deviceid(self, username, password):
        logger.warning(u'No mobile device ID configured. '
                       u'Trying to detect one.')
        webapi = Webclient(validate=False)
        webapi.login(username, password)
        devices = webapi.get_registered_devices()
        deviceid = None
        for device in devices:
            if device['type'] == 'PHONE' and device['id'][0:2] == u'0x':
                # Omit the '0x' prefix
                deviceid = device['id'][2:]
                break
        webapi.logout()
        if deviceid is None:
            logger.error(u'No valid mobile device ID found. '
                         u'Playing songs will not work.')
        else:
            logger.info(u'Using mobile device ID %s', deviceid)
        return deviceid

    def get_track_info(self, store_track_id):
        if self.api.is_authenticated():
            try:
                return self.api.get_track_info(store_track_id)
            except CallFailure as error:
                logger.error(u'Failed to get All Access track info: %s', error)

    def get_album_info(self, albumid, include_tracks=True):
        if self.api.is_authenticated():
            try:
                return self.api.get_album_info(albumid, include_tracks)
            except CallFailure as error:
                logger.error(u'Failed to get All Access album info: %s', error)
Example #34
0
from mutagen.mp3 import MP3
import mutagen.id3

EasyID3.RegisterTextKey("albumartist", "TPE2")
EasyID3.RegisterTextKey("media", "TMED")

r_albumID = 'Bmzku73mo3yicub2vnes43wv52y'

api = Mobileclient()
try:
    api.login(gMusicLogin.getUser(), gMusicLogin.getPass(),
              Mobileclient.FROM_MAC_ADDRESS)
except:
    sys.exit("Login Failed")

while api.is_authenticated() == False:
    time.sleep(.1)


def removeNonASCII(text):
    return ''.join(i for i in text if ord(i) < 128)


def runMainBody():

    r_album = api.get_album_info(r_albumID)

    w_Album = {}
    w_Album['name'] = r_album['name']
    print(w_Album['name'])
    w_Album['songs'] = []
Example #35
0
def main():
    global player
    global api

    parser = OptionParser()
    parser.add_option("-p", "--playlist", dest="playlist", help="Playlist (Name or ID)")
    parser.add_option("-t", "--track", dest="track", help="Track (Name or ID)")
    parser.add_option("-l", "--listen", action="store_true", dest="listen", help="Start listening")
    parser.add_option("-c", "--continue", action="store_true", dest="cont", help="Continue playlist after track")
    parser.add_option("-s", "--shuffle", action="store_true", dest="shuffle", help="Randomize playlist")

    (opts, args) = parser.parse_args()

    config = ConfigParser.RawConfigParser()
    directory = os.path.dirname(os.path.realpath(sys.argv[0]))
    config.read(directory + '/.gmusicpy')
    username = config.get('gmusic', 'username')
    password = config.get('gmusic', 'password')

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

    if not api.is_authenticated():
        print "Bad username/password"
        return

    id = 0

    try:
        if(opts.playlist):
            playlists = api.get_all_user_playlist_contents()
            playlist = findPlaylist(opts.playlist, playlists)
            
            if(playlist is None):
                print 'Playlist not found'
                return

            if(opts.track):
                item = findTrack(opts.track, playlist)

                if(item is None):
                    print 'Track not found'
                    return

                track = item['track']
                track['trackId'] = item['trackId']
                tracklist.append(track)

            else:
                for item in playlist['tracks']:
                    track = item['track']
                    track['trackId'] = item['trackId']
                    tracklist.append(track)

            if(opts.shuffle):
                shuffle(tracklist)

            if(opts.listen):
                track = tracklist.pop(0)
                printTrack("", track)
                url = api.get_stream_url(track['trackId'])
                player = play(url)
            else:
                for track in tracklist:
                    printTrack(id, track)
                    id = id + 1

        else:
            playlists = api.get_all_playlists()
            for playlist in playlists:
                print str(id) + ' ' + playlist['name']
                id = id + 1

        while(True):
            if player == None:
                break
            if isinstance(player, subprocess.Popen) and player.poll() != None:
                if(len(tracklist) > 0):
                    track = tracklist.pop(0)
                    printTrack("", track)
                    url = api.get_stream_url(track['trackId'])
                    player = play(url)
                else:
                    break;
            sleep(0.2)

    finally:
        if isinstance(player, subprocess.Popen):
            player.terminate()
        api.logout()
Example #36
0
class GMusicSession(object):

    def __init__(self):
        super(GMusicSession, self).__init__()
        logger.info('Mopidy uses Google Music')
        self.api = Mobileclient()

    def login(self, username, password, deviceid):
        if self.api.is_authenticated():
            self.api.logout()
        try:
            self.api.login(username, password)
        except CallFailure as error:
            logger.error(u'Failed to login as "%s": %s', username, error)
        if self.api.is_authenticated():
            if deviceid is None:
                self.deviceid = self.get_deviceid(username, password)
            else:
                self.deviceid = deviceid
        else:
            return False

    def logout(self):
        if self.api.is_authenticated():
            return self.api.logout()
        else:
            return True

    def get_all_songs(self):
        if self.api.is_authenticated():
            return self.api.get_all_songs()
        else:
            return {}

    def get_stream_url(self, song_id):
        if self.api.is_authenticated():
            try:
                return self.api.get_stream_url(song_id, self.deviceid)
            except CallFailure as error:
                logger.error(u'Failed to lookup "%s": %s', song_id, error)

    def get_all_playlist_contents(self):
        if self.api.is_authenticated():
            return self.api.get_all_user_playlist_contents()
        else:
            return {}

    def get_shared_playlist_contents(self, shareToken):
        if self.api.is_authenticated():
            return self.api.get_shared_playlist_contents(shareToken)
        else:
            return {}

    def get_all_playlists(self):
        if self.api.is_authenticated():
            return self.api.get_all_playlists()
        else:
            return {}

    def get_deviceid(self, username, password):
        logger.warning(u'No mobile device ID configured. '
                       u'Trying to detect one.')
        webapi = Webclient(validate=False)
        webapi.login(username, password)
        devices = webapi.get_registered_devices()
        deviceid = None
        for device in devices:
            if device['type'] == 'PHONE' and device['id'][0:2] == u'0x':
                # Omit the '0x' prefix
                deviceid = device['id'][2:]
                break
        webapi.logout()
        if deviceid is None:
            logger.error(u'No valid mobile device ID found. '
                         u'Playing songs will not work.')
        else:
            logger.info(u'Using mobile device ID %s', deviceid)
        return deviceid

    def get_track_info(self, store_track_id):
        if self.api.is_authenticated():
            try:
                return self.api.get_track_info(store_track_id)
            except CallFailure as error:
                logger.error(u'Failed to get All Access track info: %s', error)

    def get_album_info(self, albumid, include_tracks=True):
        if self.api.is_authenticated():
            try:
                return self.api.get_album_info(albumid, include_tracks)
            except CallFailure as error:
                logger.error(u'Failed to get All Access album info: %s', error)
Example #37
0
class GoogleMusicLogin():
    def __init__(self):
        import requests
        from requests.packages.urllib3.exceptions import InsecureRequestWarning
        from requests.packages.urllib3.exceptions import InsecurePlatformWarning
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
        self.gmusicapi = Mobileclient(debug_logging=False, validate=False, verify_ssl=False)

    def checkCookie(self):
        # Remove cookie data if it is older then 7 days
        if utils.addon.getSetting('cookie-date') != None and len(utils.addon.getSetting('cookie-date')) > 0:
            import time
            if (datetime.now() - datetime(*time.strptime(utils.addon.getSetting('cookie-date'), '%Y-%m-%d %H:%M:%S.%f')[0:6])).days >= 7:
                self.clearCookie()

    def checkCredentials(self):
        if not utils.addon.getSetting('username'):
            utils.addon.openSettings()
        if utils.addon.getSetting('password') and utils.addon.getSetting('password') != '**encoded**':
            import base64
            utils.addon.setSetting('encpassword',base64.b64encode(utils.addon.getSetting('password')))
            utils.addon.setSetting('password','**encoded**')

    def getApi(self):
        return self.gmusicapi

    def getStreamUrl(self,song_id):
        # retrieve registered device
        device_id = self.getDevice()
        # retrieve stream quality from settings
        quality = { '0':'hi','1':'med','2':'low' } [utils.addon.getSetting('quality')]
        utils.log("getStreamUrl songid: %s device: %s quality: %s"%(song_id, device_id, quality))

        return self.gmusicapi.get_stream_url(song_id, device_id, quality)

    def getDevice(self):
        return utils.addon.getSetting('device_id')

    def initDevice(self):
        device_id = self.getDevice()

        if not device_id:
            utils.log('Trying to fetch the device_id')
            self.login(True)
            try:
                devices = self.gmusicapi.get_registered_devices()
                if len(devices) == 10:
                    utils.log("WARNING: 10 devices already registered!")
                utils.log(repr(devices))
                for device in devices:
                    if device["type"] in ("ANDROID","PHONE","IOS"):
                        device_id = str(device["id"])
                        break
            except:
                pass

            if device_id:
                if device_id.lower().startswith('0x'): device_id = device_id[2:]
                utils.addon.setSetting('device_id', device_id)
                utils.log('Found device_id: '+device_id)
            else:
                #utils.log('No device found, using default.')
                #device_id = "333c60412226c96f"
                raise Exception('No devices found, registered mobile device required!')

    def clearCookie(self):
        utils.addon.setSetting('logged_in-mobile', "")
        utils.addon.setSetting('authtoken-mobile', "")
        utils.addon.setSetting('device_id', "")

    def logout(self):
        self.gmusicapi.logout()

    def login(self, nocache=False):
        if not utils.addon.getSetting('logged_in-mobile') or nocache:
            import base64

            utils.log('Logging in')
            self.checkCredentials()
            username = utils.addon.getSetting('username')
            password = base64.b64decode(utils.addon.getSetting('encpassword'))

            try:
                self.gmusicapi.login(username, password, utils.addon.getSetting('device_id'))
                if not self.gmusicapi.is_authenticated():
                    self.gmusicapi.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
            except Exception as e:
                utils.log(repr(e))

            if not self.gmusicapi.is_authenticated():
                utils.log("Login failed")
                utils.addon.setSetting('logged_in-mobile', "")
                self.language = utils.addon.getLocalizedString
                dialog = xbmcgui.Dialog()
                dialog.ok(self.language(30101), self.language(30102))
                #utils.addon.openSettings()
                raise
            else:
                utils.log("Login succeeded")
                utils.addon.setSetting('logged_in-mobile', "1")
                utils.addon.setSetting('authtoken-mobile', self.gmusicapi.session._authtoken)
                utils.addon.setSetting('cookie-date', str(datetime.now()))
        else:

            utils.log("Loading auth from cache")
            self.gmusicapi.session._authtoken = utils.addon.getSetting('authtoken-mobile')
            self.gmusicapi.session.is_authenticated = True
Example #38
0
class Downloader:

	def __init__( self , username1=None ,  password1=None , baseDirectory=None , pickleLIBFilePath=None ):

		self.api = Mobileclient()
		if username1 is not None:
			if password1 is not None:
				self.login( username1 , password1 )

		if self.isLoggedIn() == True:
			print("Logged In")
		else:
			raise Exception


		# Setup Default Save Location
		if baseDirectory is not None:
			self.homeDIR = baseDirectory
			self.libDIR = os.path.join( self.homeDIR , 'GMusicLocalLibraryPOOL' )
		else:
			self.homeDIR = os.path.expanduser("~")
			self.libDIR = os.path.join( self.homeDIR , 'GMusicLocalLibraryPOOL' )
		

		if not os.path.exists(self.libDIR):
			os.makedirs(self.libDIR)


		self.stations = {}
		self.workingPlaylistOBJ = {}
		self.needToDownloadSongs = None	

		self.Full = True

		#self.playlists = None
		self.localLibrary = None
		#self.initializePlaylists()
		if pickleLIBFilePath is not None:
			self.initializeLocalLibrary(pickleLIBFilePath)
		else:
			self.initializeLocalLibrary()


	def isLoggedIn(self):

		x = self.api.is_authenticated()
		return x

	def login(self , userN , passW ):

		self.api.login( userN , passW , Mobileclient.FROM_MAC_ADDRESS )

	def initializePlaylists(self):

		try:
			self.playlists = pickle.load( open( libDIR + "libPlaylists.p" , "rb" ) )
		except:
			print("Recreating Playlists Save File")
			self.playlists = {}
			playlists['EDM'] = []
			playlists['Relaxing'] = []
			playlists['EDM'].append('4b40425b-2e11-388f-aeed-ea736b88662c')
			pickle.dump( playlists , open( libDIR + "libPlaylists.p" , "wb" ) )

	def initializeLocalLibrary(self , pickleLIBFilePath=None):

		defaultPath2 = os.path.join( self.libDIR , "libDatabasePOOL.p" )
		
		if pickleLIBFilePath is not None:
			defaultPath2 = pickleLIBFilePath

		print("DefaultPath .p file = " + defaultPath2)
		
		try:
			self.localLibrary = pickle.load( open( defaultPath2  , "rb" ) )
			print("Loaded libDatabasePOOL.p")
		except:
			self.localLibrary = {}
			pickle.dump( self.localLibrary , open( defaultPath2 , "wb" ) )
			print("Recreated LibraryPOOL Save File")

		print( "LocalLibary Size = " + str( len( self.localLibrary ) ) )

	def getMyStations(self):

		stations = self.api.get_all_stations()
		for x in stations:
			self.stations[x['id']] = x['name']

	def printAvailableStations(self):

		for x in self.stations:
			print( str(x) + " = " + self.stations[x] )

	def downloadStationToPOOL( self , stationID ):

		rawPlaylist = self.api.get_station_tracks( stationID , 25 )

		self.needToDownloadSongs = {}

		for x in rawPlaylist:
			if x['nid'] in self.localLibrary:
				print("Already in LibraryPOOL")
			else:
				self.Full = False
				print( str(x['nid']) + " == Not in library ... need to download" )
				self.needToDownloadSongs[x['nid']] = { 'stationID': stationID , 'trackName': x['title'] , 'artistName': x['artist'] , 'albumID': x['albumId'] , 'artURL': x['albumArtRef'][0]['url'] }
				

		p1 = threading.Thread( target=self.getMP3FromSongIDS , args=( stationID , ) )
		p1.start()
		p1.join()

		if self.Full == False:
			self.Full = True
			print( "LocalLibary Size = " + str( len( self.localLibrary ) ) )
			self.downloadStationToPOOL( stationID )

	def getMP3FromSongIDS( self , stationID ):
		
		a1 = 1
		for x in self.needToDownloadSongs:

			self.saveMP3ToLibraryPOOL( x , self.needToDownloadSongs[x]['trackName'] , self.needToDownloadSongs[x]['artistName'] , stationID )
			self.localLibrary[x] = self.needToDownloadSongs[x]
			pickle.dump( self.localLibrary , open( os.path.join( self.libDIR , "libDatabasePOOL.p" ) , "wb" ) )
			print("added [" + str(a1) + " of " + str(len(self.needToDownloadSongs)) + "] songs to localLibrary")
			a1 = a1 + 1
			
	def saveMP3ToLibraryPOOL( self , songID , name , artist , stationID ):

		albumName = self.stations[stationID]
		
		wURL = self.api.get_stream_url( songID , self.api.android_id , 'hi' )
		fN = os.path.join( self.libDIR , songID + ".mp3" )

		response1 = requests.get( wURL , stream=True )
		with open( fN , 'wb' ) as f:
			for data in tqdm( response1.iter_content(chunk_size=524288) ):
				f.write(data)		


		m3 = MP3( fN , ID3=EasyID3 )
		m3.add_tags( ID3=EasyID3 )
		m3["title"] = name
		m3['artist'] = artist
		m3['album'] = albumName
		m3['organization'] = stationID 
		m3.save()

	def extractSinglePlaylistFromPOOL( self , stationID , destinationDIR , onlyCopyNotExtract=False ):

		if not os.path.exists(destinationDIR):
			os.makedirs(destinationDIR)

		if onlyCopyNotExtract == True:
			for key , value in self.localLibrary.items():
				try:
					if value['stationID'] == stationID:
						#print( "found --> " + self.localLibrary[key]['trackName'] + " in ... " + str(stationID) )
						fN = str(key) + ".mp3" 
						shutil.copy( os.path.join( self.libDIR , fN ) , os.path.join( destinationDIR , fN ) )
				except:
					pass		

		else:
			for key , value in self.localLibrary.items():
				try:
					if value['stationID'] == stationID:
						#print( "found --> " + self.localLibrary[key]['trackName'] + " in ... " + str(stationID) )
						fN = str(key) + ".mp3" 
						shutil.move( os.path.join( self.libDIR , fN ) , os.path.join( destinationDIR , fN ) )
				except:
					pass
import gMusicLogin

from tqdm import tqdm
import sys , os , time , requests

from mutagen.easyid3 import EasyID3
from mutagen.mp3 import MP3
import mutagen.id3

api = Mobileclient()
try:
	api.login( gMusicLogin.getUser() , gMusicLogin.getPass() , Mobileclient.FROM_MAC_ADDRESS )		
except:
	sys.exit("Login Failed")

while api.is_authenticated() == False:
	time.sleep(.1)

wPlaylists = None

def removeNonASCII(text):
    return ''.join(i for i in text if ord(i)<128)

def getPlaylists():
	global wPlaylists
	wPlaylists = api.get_all_playlists()
	for idx , x in enumerate( wPlaylists ):
		x['name'] = removeNonASCII( x['name'] )
		print( str( idx ) + " = " + x['name'] )

def getSelection():
Example #40
0
def main():
    if len(sys.argv) != 3:
        print_help()
        sys.exit(1)
    else:
        username = sys.argv[1]
        path = sys.argv[2]
    password = getpass.getpass()

    pp = pprint.PrettyPrinter(indent=4)

    local_list = get_local_dirs(path)

    mob = Mobileclient()
    mob.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
    if not mob.is_authenticated():
        sys.exit(1)

    mmw = MusicManagerWrapper(enable_logging=True)
    mmw.login()

    if not mmw.is_authenticated:
        sys.exit()

    total_items = 0
    partial_accepted_items = 0
    partial_rejected_items = 0
    partial_manual_items = 0
    exact_items = 0
    no_items = 0

    ACCEPT_RATIO = 0.33
    REJECT_RATIO = 0.66

    matched_albums = []
    unmatched_albums = []
    manual_albums = []

    for item in local_list:
        search_artist = item['artist']
        for search_album in item['albums']:
            total_items += 1
            albums = search_for_artist_and_album(mob, search_artist, search_album)
            sorted_albums = sorted(albums, key=lambda k:k[2])

            if len(sorted_albums) > 0:
                (artist, album, ratio, album_id) = sorted_albums[0]

                if ratio > 0:
                    if ratio < ACCEPT_RATIO:
                        partial_accepted_items += 1
                        partial_description = 'Partial Match (Accepted)'
                        matched_albums.append((artist, album, album_id))
                    elif ratio > REJECT_RATIO:
                        partial_rejected_items += 1
                        partial_description = 'Partial Match (Rejected)'
                        unmatched_albums.append((search_artist, search_album))
                    else:
                        partial_manual_items += 1
                        partial_description = 'Partial Match (Manual)'
                        manual_albums.append((search_artist, search_album, artist, album, album_id))
                    print_partial(partial_description, ratio, artist, album, search_artist, search_album)
                else:
                    exact_items += 1
                    print("{0: <30}: Artist: {1}, Album: {2}".format('Exact Match', artist, album))
                    matched_albums.append((artist, album, album_id))
            else:
                no_items += 1
                print("{0: <30}: Artist: {1}, Album: {2}".format('No Match', search_artist, search_album))
                unmatched_albums.append((search_artist, search_album))

    print_summary(total_items, partial_accepted_items, partial_rejected_items, partial_manual_items, exact_items, no_items)

    if (confirmation_dialog("Ok to proceed? (y/n)")):
        (manual_matched, manual_unmatched) = process_manual_albums(manual_albums)
        matched_albums += manual_matched
        unmatched_albums += manual_unmatched
        add_matched_albums_to_library(mob, matched_albums)
        upload_unmatched_albums_to_library(mmw, path, unmatched_albums)
Example #41
0
    print "found " + str(len(thumbsDownSongs)) + " dupe songs"

    #tracks = playlist['tracks']
    #find_and_remove_dups(api, tracks)


# Setup the gmusicapi
api = Mobileclient()
api.__init__()

# Check to see if OAuth credentials available, ask user to setup if not
try:
    api.oauth_login(Mobileclient.FROM_MAC_ADDRESS)
    #api.perform_oauth()
except:
    print "No OAuth credentials found! Please setup in the following screen!"
    api.perform_oauth()
    api.oauth_login(Mobileclient.FROM_MAC_ADDRESS
                    )  # If it fails here, it wasn't meant to be

# Then, move on to doing all the work
if api.is_authenticated():
    print "Successfully logged in. Finding duplicates in playlists"
    dedupeSongs()
    api.logout()
else:
    print "Not logged in! Exiting..."
    exit(1)

print "Script has finished successfully!"
Example #42
0
class GoogleMusicLogin():
    def __init__(self):
        import requests
        from requests.packages.urllib3.exceptions import InsecureRequestWarning
        from requests.packages.urllib3.exceptions import InsecurePlatformWarning
        from requests.packages.urllib3.exceptions import SNIMissingWarning
        requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
        requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
        requests.packages.urllib3.disable_warnings(SNIMissingWarning)
        self.gmusicapi = Mobileclient(debug_logging=False, validate=False, verify_ssl=False)
        #self.gmusicapi._session_class.lang = xbmc.getLanguage(xbmc.ISO_639_1, True)
        #utils.log(repr(xbmc.getLanguage(xbmc.ISO_639_1, True)))

    def checkCookie(self):
        # Remove cookie data if it is older then 7 days
        if utils.addon.getSetting('cookie-time'):
            import time
            if time.time() - float(utils.addon.getSetting('cookie-time')) > 3600*24*7:
                self.clearCookie()

    def checkCredentials(self):
        if not utils.addon.getSetting('username'):
            utils.addon.openSettings()
        if utils.addon.getSetting('password') and utils.addon.getSetting('password') != '**encoded**':
            import base64
            utils.addon.setSetting('encpassword',base64.b64encode(utils.addon.getSetting('password')))
            utils.addon.setSetting('password','**encoded**')

    def getApi(self):
        return self.gmusicapi

    def getStreamUrl(self, song_id, session_token, wentry_id):
        # retrieve registered device
        device_id = self.getDevice()
        # retrieve stream quality from settings
        quality = { '0':'hi','1':'med','2':'low' } [utils.addon.getSetting('quality')]
        utils.log("getStreamUrl songid: %s device: %s quality: %s"%(song_id, device_id, quality))

        return self.gmusicapi.get_stream_url(song_id, device_id, quality, session_token, wentry_id)

    def getDevice(self):
        return utils.addon.getSetting('device_id')

    def initDevice(self):
        device_id = self.getDevice()

        if not device_id:
            utils.log('Trying to fetch the device_id')
            self.login()
            try:
                devices = self.gmusicapi.get_registered_devices()
                if len(devices) == 10:
                    utils.log("WARNING: 10 devices already registered!")
                utils.log('Devices: '+repr(devices))
                for device in devices:
                    if device["type"] in ("ANDROID","PHONE","IOS"):
                        device_id = str(device["id"])
                        break
            except Exception as e:
                utils.log("ERROR: "+repr(e))

            if device_id:
                if device_id.lower().startswith('0x'): device_id = device_id[2:]
                utils.addon.setSetting('device_id', device_id)
                utils.log('Found device_id: '+device_id)
            else:
                utils.log('No Android device found in account')
                #self.language = utils.addon.getLocalizedString
                #dialog = xbmcgui.Dialog()
                #dialog.ok("", self.language(30111))

    def clearCookie(self):
        utils.addon.setSetting('logged_in-mobile', "")
        utils.addon.setSetting('authtoken-mobile', "")
        utils.addon.setSetting('device_id', "")
        utils.addon.setSetting('subscriber', "0")

    def logout(self):
        self.gmusicapi.logout()

    def login(self, nocache=False):
        if not utils.addon.getSetting('logged_in-mobile') or nocache:
            import base64

            utils.log('Logging in')
            self.checkCredentials()
            username = utils.addon.getSetting('username')
            password = base64.b64decode(utils.addon.getSetting('encpassword'))

            try:
                self.gmusicapi.login(username, password, self.getDevice() )
            except: pass
            if not self.gmusicapi.is_authenticated():
                try:
                    utils.log("Login in with device_id failed, trying with MAC")
                    self.gmusicapi.login(username, password, Mobileclient.FROM_MAC_ADDRESS)
                except Exception as e:
                    utils.log("ERROR: "+repr(e))

            if not self.gmusicapi.is_authenticated():
                utils.log("Login failed")
                utils.addon.setSetting('logged_in-mobile', "")
                self.language = utils.addon.getLocalizedString
                dialog = xbmcgui.Dialog()
                dialog.ok(self.language(30101), self.language(30102))
                raise
            else:
                utils.log("Login succeeded. Device id: "+self.gmusicapi.android_id)
                utils.addon.setSetting('device_id', self.gmusicapi.android_id)
                utils.addon.setSetting('logged_in-mobile', "1")
                utils.addon.setSetting('authtoken-mobile', self.gmusicapi.session._authtoken)
                import time
                utils.addon.setSetting('cookie-time', str(time.time()))
                utils.addon.setSetting('subscriber','1' if self.gmusicapi.is_subscribed else '0')

        else:

            utils.log("Loading auth from cache")
            self.gmusicapi.session._authtoken = utils.addon.getSetting('authtoken-mobile')
            self.gmusicapi.session.is_authenticated = True
Example #43
0
logHndFile.setFormatter(logFormatter)
logger.addHandler(logHndFile)

logHndScreen = logging.StreamHandler(stream=sys.stdout)
logHndScreen.setLevel(logging.ERROR)
if args.verbose:
    logHndScreen.setLevel(logging.DEBUG)
logHndScreen.setFormatter(logFormatter)
logger.addHandler(logHndScreen)

logger.info("gmusicapi log: " + utils.log_filepath)

gpm = Mobileclient()
gpm.oauth_login(Mobileclient.FROM_MAC_ADDRESS)

if not gpm.is_authenticated():
    logger.error("Login failed")
    exit()

# Connect to MySQL
# Mark all playlist entries as unprocessed
db = pymysql.connect(
    host=config.db["hostname"],
    user=config.db["username"],
    password=config.db["password"],
    db=config.db["database"],
    autocommit=True
)

cursor = db.cursor()
    print "USAGE:"
    print "./add_last_songs_to_top_of_playlist.py 'PLAYLIST NAME' NUMBER_SONGS"
    print
    print "example: ./add_last_songs_to_top_of_playlist.py 'Ultimate Everything' 5"
    print "     will move the last 5 songs in 'Ultimate Everything' to the top of the playlist."
    exit(0)
else:
    playlist_name = sys.argv[1]
    num_songs = sys.argv[2]

# Setup the gmusicapi
api = Mobileclient()
api.__init__()


# Check to see if OAuth credentials available, ask user to setup if not
try:
    api.oauth_login(Mobileclient.FROM_MAC_ADDRESS)
except:
    print "No OAuth credentials found! Please setup in the following screen!"
    api.perform_oauth()
    api.oauth_login(Mobileclient.FROM_MAC_ADDRESS) # If it fails here, it wasn't meant to be

# Then, move on to doing all the work
if api.is_authenticated():
    print "Successfully logged in. Moving " + num_songs + " tracks to top of playlist"
    playlists = api.get_all_user_playlist_contents()
    tracks = get_playlist_tracks(playlist_name, playlists)
    move_songs_to_top(api, tracks, int(num_songs))

print "Script completed successfully!"