Example #1
0
 def makeListItem(self, replaceItems=False):
     colorItem = getSetting('item_default_color')
     colorPl = getSetting('item_section_color')
     label = self.get_label()
     image = self.get_image()
     owner = self.get_owner()
     url = self.make_url()
     if not self.is_my_playlist:
         label = '%s - %s' % (color(colorItem, owner), label)
     if self.b_is_current:
         fmt = getSetting('playlist_current_format')
         label = fmt % (color(colorPl, label))
     item = xbmcgui.ListItem(label,
                             owner,
                             image,
                             image,
                             url)
     if not item:
         warn(self, "Error: Cannot make xbmc list item")
         return None
     item.setPath(url)
     ctxMenu = contextMenu()
     self.attach_context_menu(item, ctxMenu)
     item.addContextMenuItems(ctxMenu.getTuples(), replaceItems)
     return item
Example #2
0
def get_checked_parameters():
    """Parse parameters passed to xbmc plugin as sys.argv
    """
    d = dog()
    rparam = {}
    if len(sys.argv) <= 1:
        return rparam
    paramstring = sys.argv[2]
    if len(paramstring) >= 2:
        params = sys.argv[2]
        cleanedparams = params.replace('?', '')
        if (params[len(params) - 1] == '/'):
            params = params[0:len(params) - 2]
        pairsofparams = cleanedparams.split('&')

        for i in range(len(pairsofparams)):
            splitparams = {}
            splitparams = pairsofparams[i].split('=')
            if (len(splitparams)) == 2:
                if d.kv_is_ok(splitparams[0], splitparams[1]):
                    rparam[splitparams[0]] = splitparams[1]
                else:
                    warn('[DOG]', "--- Invalid key: %s / value: %s" %
                         (splitparams[0], splitparams[1]))
    return rparam
Example #3
0
 def remove(self):
     name = self.get_parameter('query')
     if name == 'qobuz.com':
         return False
     if not name:
         return False
     user = self.get_user_data()
     if not user:
         return False
     friends = user['player_settings']
     if not 'friends' in friends:
         notifyH('Qobuz', "You don't have friend",
                 'icon-error-256')
         warn(self, "No friends in user/player_settings")
         return False
     friends = friends['friends']
     if not name in friends:
         notifyH('Qobuz', "You're not friend with %s" % (name),
                 'icon-error-256')
         warn(self, "Friend " + repr(name) + " not in friends data")
         return False
     del friends[friends.index(name)]
     newdata = {'friends': friends}
     if not api.user_update(player_settings=json.dumps(newdata)):
         notifyH('Qobuz', 'Friend %s added' % (name))
         notifyH('Qobuz', "Cannot updata friend's list...",
                 'icon-error-256')
         return False
     notifyH('Qobuz', 'Friend %s removed' % (name))
     self.delete_cache()
     executeBuiltin(containerRefresh())
     return True
Example #4
0
 def __add_pagination(self, data):
     '''build_down helper: Add pagination data when needed
     '''
     if not data:
         return False
     items = None
     need_pagination = False
     for p in _paginated:
         if p not in data or data[p] is None:
             warn(self, 'No pagination data')
             continue
         items = data[p]
         if 'limit' not in items or 'total' not in items:
             continue
         if items['limit'] is None:
             continue
         if items['total'] > (items['offset'] + items['limit']):
             need_pagination = True
             break
     if need_pagination is False:
         return False
     url = self.make_url(offset=items['offset'] + items['limit'])
     self.pagination_next = url
     self.pagination_total = items['total']
     self.pagination_offset = items['offset']
     self.pagination_limit = items['limit']
     self.pagination_next_offset = items['offset'] + items['limit']
     return True
Example #5
0
 def _add_tracks(self, playlist_id, nodes):
     if len(nodes) < 1:
         warn(self, 'Empty list...')
         return False
     step = 50
     start = 0
     numtracks = len(nodes)
     if numtracks > 1000:
         notify_error('Qobuz', 'Max tracks per playlist reached (1000)'
                      '\nSkipping %s tracks' % (numtracks - 1000))
         numtracks = 1000
     while start < numtracks:
         if (start + step) > numtracks:
             step = numtracks - start
         str_tracks = ''
         info(self, "Adding tracks start: %s, end: %s" %
              (start, start + step))
         for i in range(start, start + step):
             node = nodes[i]
             if node.nt != Flag.TRACK:
                 warn(self, "Not a Node_track node")
                 continue
             str_tracks += '%s,' % (str(node.nid))
         if not api.playlist_addTracks(
                 playlist_id=playlist_id, track_ids=str_tracks):
             return False
         start += step
     return True
Example #6
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     data = api.get('/album/get', album_id=self.nid)
     if not data:
         warn(self, "Cannot fetch product data")
         return False
     self.data = data
     return True
Example #7
0
 def scan(self):
     import sys
     from qobuz.node.flag import Flag
     """Building tree when using Xbmc library scanning
     feature
     """
     from qobuz.gui.directory import Directory
     if not self.set_root_node():
         warn(self, "Cannot set root node ('%s')" % (str(
             self.node_type)))
         return False
     handle = qobuz.boot.handle
     Dir = Directory(self.root, self.nodes, withProgress=False)
     Dir.handle = int(sys.argv[1])
     Dir.asList = False
     Dir.asLocalURL = True
     if self.root.nt & Flag.TRACK:
         self.root.fetch(None, None, Flag.TRACK, Flag.NONE)
         Dir.add_node(self.root)
     else:
         self.root.populating(Dir, self.depth,
                              self.whiteFlag, self.blackFlag)
     Dir.set_content(self.root.content_type)
     Dir.end_of_directory()
     notifyH('Scanning results', str(Dir.total_put) +
             ' items where scanned', mstime=3000)
     return True
Example #8
0
 def to_s(cls, flag):
     if not flag:
         warn(cls, "Missing flag parameter")
         return ''
     flag = int(flag)
     if flag & cls.TRACK == cls.TRACK:
         return "track"
     elif flag & cls.PLAYLIST == cls.PLAYLIST:
         return "playlist"
     elif flag & cls.USERPLAYLISTS == cls.USERPLAYLISTS:
         return "user_playlists"
     elif flag & cls.RECOMMENDATION == cls.RECOMMENDATION:
         return "recommendation"
     elif flag & cls.ROOT == cls.ROOT:
         return "root"
     elif flag & cls.ALBUM == cls.ALBUM:
         return "album"
     elif flag & cls.PURCHASES == cls.PURCHASES:
         return "purchases"
     elif flag & cls.PURCHASE == cls.PURCHASE:
         return "purchase"
     elif flag & cls.FAVORITES == cls.FAVORITES:
         return "favorites"
     elif flag & cls.FAVORITE == cls.FAVORITE:
         return "favorite"
     elif flag & cls.SEARCH == cls.SEARCH:
         return "search"
     elif flag & cls.ARTIST == cls.ARTIST:
         return "artist"
     elif flag & cls.SIMILAR_ARTIST == cls.SIMILAR_ARTIST:
         return "similar_artist"
     elif flag & cls.FRIEND == cls.FRIEND:
         return "friend"
     elif flag & cls.FRIENDS == cls.FRIENDS:
         return "friends"
     elif flag & cls.GENRE == cls.GENRE:
         return "genre"
     elif flag & cls.LABEL == cls.LABEL:
         return "label"
     elif flag & cls.NODE == cls.NODE:
         return "inode"
     elif flag & cls.STOPBUILD == cls.STOPBUILD:
         return "stop_build_down"
     elif flag & cls.ARTICLES == cls.ARTICLES:
         return "articles"
     elif flag & cls.ARTICLE == cls.ARTICLE:
         return "article"
     elif flag & cls.PUBLIC_PLAYLISTS == cls.PUBLIC_PLAYLISTS:
         return "public_playlists"
     elif flag & cls.ARTICLE_RUBRICS == cls.ARTICLE_RUBRICS:
         return "article_rubrics"
     elif flag & cls.ALBUMS_BY_ARTIST == cls.ALBUMS_BY_ARTIST:
         return "albums_by_artist"
     elif flag & cls.COLLECTION == cls.COLLECTION:
         return "collection"
     elif flag & cls.COLLECTIONS == cls.COLLECTIONS:
         return "collections"
     else:
         raise QobuzXbmcError(
             who=cls, what='invalid_flag', additional=repr(flag))
Example #9
0
 def mkdir(self, path):
     if not os.path.isdir(path):
         try:
             os.makedirs(path)
         except:
             warn("Cannot create directory: " + path)
             exit(2)
         info(self, "Directory created: " + path)
Example #10
0
 def get_streaming_url(self):
     data = self.__getFileUrl()
     if not data:
         return None
     if 'url' not in data:
         warn(self, "streaming_url, no url returned\n"
              "API Error: %s" % (api.error))
         return None
     return data['url']
Example #11
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     limit = getSetting('pagination_limit')
     data = api.get('/artist/getSimilarArtist', artist_id=self.nid,
                    limit=limit, offset=self.offset, extra='albums')
     if not data:
         warn(self, "Cannot fetch albums for artist: " + self.get_label())
         return False
     self.data = data
     return True
Example #12
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     limit = getSetting('pagination_limit')
     data = api.get('/artist/get', artist_id=self.nid, limit=limit,
                    offset=self.offset, extra='albums')
     if not data:
         warn(self, "Build-down: Cannot fetch artist data")
         return False
     self.data = data
     return True
Example #13
0
 def get_playlist_storage(self):
     if self.playlist_storage is not None:
         return self.playlist_storage
     if api.user_id is None or self.nid is None:
         warn(self, 'Missing user_id: {user_id} or nid: {nid}',
              user_id=api.user_id, nid=self.nid)
         return None
     self.playlist_storage = _Storage(self._get_playlist_storage_filename())
     return self.playlist_storage
Example #14
0
 def get_year(self):
     import time
     date = self.get_property('released_at', default=None)
     year = 0
     try:
         year = time.strftime("%Y", time.localtime(date))
     except Exception:
         warn(self, 'Invalid date format %s', date)
     return year
Example #15
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     limit = getSetting('pagination_limit')
     data = api.get('/purchase/getUserPurchases', limit=limit,
                    offset=self.offset, user_id=api.user_id)
     if not data:
         warn(self, "Cannot fetch purchases data")
         return False
     self.data = data
     return True
Example #16
0
 def set_as_current(self, playlist_id=None):
     if not playlist_id:
         playlist_id = self.nid
     if not playlist_id:
         warn(self, 'Cannot set current playlist without id')
         return False
     userdata = self.get_user_storage()
     userdata['current_playlist'] = int(playlist_id)
     return userdata.sync()
Example #17
0
 def close(self):
     """Close our progress dialog
     """
     if not self.is_enable:
         return True
     try:
         return super(Progress, self).close()
     except:
         warn(self, "Cannot close progress bar")
         return False
Example #18
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     limit = getSetting('pagination_limit', asInt=True)
     data = api.get('/playlist/get', playlist_id=self.nid,
                    offset=self.offset, limit=limit, extra='tracks')
     if not data:
         warn(self, "Build-down: Cannot fetch playlist data")
         return False
     self.data = data
     self.get_image() # Buld thumbnail if neeeded
     return True
Example #19
0
 def item_add_playing_property(self, item):
     """ We add this information only when playing item because it require
     us to fetch data from Qobuz
     """
     mime = self.get_mimetype()
     if not mime:
         warn(self, "Cannot set item streaming url")
         return False
     item.setProperty('mimetype', mime)
     item.setPath(self.get_streaming_url())
     return True
Example #20
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     limit = getSetting('pagination_limit')
     data = api.get('/playlist/getUserPlaylists',
                    limit=limit,
                    offset=self.offset,
                    user_id=api.user_id)
     if data is None:
         warn(self, "Build-down: Cannot fetch user playlists data")
         return False
     self.data = data
     return True
Example #21
0
 def iscanceled(self):
     """Return true if our dialog has been canceled by user
     """
     if not self.is_enable:
         return False
     bs = True
     try:
         bs = super(Progress, self).iscanceled()
     except:
         warn(self, 'Cannot cancel progress...')
         return True
     return bs
Example #22
0
 def update_line1(self, line):
     """Only updating line1
     """
     if not line or line == self.line1:
         return False
     self.line1 = line
     try:
         return self.update(self.percent, self.line1, self.line2,
                            self.line3)
     except:
         warn(self, "Cannot update line1 progress bar")
         return False
Example #23
0
 def get_year(self):
     import time
     date = self.get_property('album/released_at', default=None)
     if date is None:
         if self.parent is not None and self.parent.nt & Flag.ALBUM:
             return self.parent.get_year()
     year = 0
     try:
         year = time.strftime("%Y", time.localtime(date))
     except Exception as e:
         warn(self, 'Invalid date format %s', date)
     return year
Example #24
0
 def __init__(self, parent, params):
     super(Node_album, self).__init__(parent, params)
     self.nt = Flag.ALBUM
     self.image = getImage('album')
     self.content_type = 'songs'
     self.is_special_purchase = False
     self.imageDefaultSize = 'large'
     self.label = 'Album'
     self.offset = self.get_parameter('offset') or 0
     try:
         self.imageDefaultSize = getSetting('image_default_size')
     except Exception as e:
         warn(self, 'Cannot set image default size, Error: {}', e)
Example #25
0
 def populate(self, Dir, lvl, whiteFlag, blackFlag):
     wanted = ['albums', 'tracks']
     if self.search_type != 'all':
         wanted = [self.search_type]
     ret = False
     for kind in wanted:
         method = '_populate_%s' % kind
         if not hasattr(self, method):
             warn(self, "No method named %s" % method)
             continue
         if getattr(self, method)(Dir, lvl, whiteFlag, blackFlag):
             ret = True
     return ret
Example #26
0
 def populate(self, Dir, lvl, whiteFlag, blackFlag):
     data = api.get('/playlist/getUserPlaylists', username=self.name)
     if not data:
         warn(self, "No friend data")
         return False
     if lvl != -1:
         self.add_child(getNode(Flag.FRIENDS, self.parameters))
     for pl in data['playlists']['items']:
         node = getNode(Flag.PLAYLIST)
         node.data = pl
         if node.get_owner() == self.label:
             self.nid = node.get_owner_id()
         self.add_child(node)
     return True
Example #27
0
 def create(self, line1, line2='', line3=''):
     """Create our progress dialog
     """
     self.line1 = line1
     self.line2 = line2
     self.line3 = line3
     if not self.is_enable:
         return True
     self.started_on = time.time()
     try:
         return super(Progress, self).create(line1, line2, line3)
     except:
         warn(self, "Cannot create progress bar")
         return False
     return True
Example #28
0
 def fetch(self, Dir, lvl, whiteFlag, blackFlag):
     if self.genre_type is  None or self.genre_id is None:
         return True
     offset = self.offset or 0
     limit = getSetting('pagination_limit')
     data = api.get('/album/getFeatured',
                    type=RECOS_TYPE_IDS[int(self.genre_type)],
                    genre_id=self.genre_id,
                    limit=10,
                    offset=offset)
     if data is None:
         warn(self, 'Cannot fetch data for recommendation')
         return False
     self.data = data
     return True
Example #29
0
 def __getFileUrl(self):
     hires = getSetting('hires_enabled', asBool=True)
     format_id = 6 if getSetting('streamtype') == 'flac' else 5
     if hires and self.get_hires():
         format_id = 27
     if self.get_property('purchased') or self.get_parameter('purchased') == '1' or self.purchased:
         intent = "download"
     else:
         intent = "stream"
     data = api.get('/track/getFileUrl', format_id=format_id,
                    track_id=self.nid, user_id=api.user_id, intent=intent)
     if not data:
         warn(self, "Cannot get stream type for track (network problem?)")
         return None
     return data
Example #30
0
 def populate(self, Dir, lvl, whiteFlag, blackFlag):
     if self.method is not None:
         return True
     ret = False
     all_kind = ('artists', 'albums', 'tracks')
     search_for = (self.search_type, )
     if self.search_type is None:
         search_for = all_kind
     for kind in search_for:
         method = '_populate_%s' % kind
         if not hasattr(self, method):
             warn(self, 'No method named %s' % method)
             continue
         if getattr(self, method)(Dir, lvl, whiteFlag, blackFlag):
             ret = True
     return ret
Example #31
0
 def track_resportStreamingEnd(self, track_id, duration):
     duration = math.floor(int(duration))
     if duration < 5:
         info(self, 'Duration lesser than 5s, abort reporting')
         return None
     # @todo ???
     user_auth_token = ''  # @UnusedVariable
     try:
         user_auth_token = self.user_auth_token  # @UnusedVariable
     except:
         warn(self, 'No authentification token')
         return None
     params = {
         'user_id': self.user_id,
         'track_id': track_id,
         'duration': duration
     }
     return self._api_request(params, '/track/reportStreamingEnd')
Example #32
0
    def _api_request(self, params, uri, **opt):
        '''Qobuz API HTTP get request
            Arguments:
            params:    parameters dictionary
            uri   :    service/method
            opt   :    Optionnal named parameters
                        - noToken=True/False

            Return None if something went wrong
            Return raw data from qobuz on success as dictionary

            * on error you can check error and status_code

            Example:

                ret = api._api_request({'username':'******',
                                  'password':'******'},
                                 'user/login', noToken=True)
                print 'Error: %s [%s]' % (api.error, api.status_code)

            This should produce something like:
            Error: [200]
            Error: Bad Request [400]
        '''
        self.statTotalRequest += 1
        self.error = ''
        self.status_code = None
        url = self._baseUrl + uri
        useToken = False if (opt and 'noToken' in opt) else True
        headers = {}
        if useToken and self.user_auth_token:
            headers['x-user-auth-token'] = self.user_auth_token
        headers['x-app-id'] = self.appid
        '''DEBUG'''
        import copy
        _copy_params = copy.deepcopy(params)
        if 'password' in _copy_params:
            _copy_params['password'] = '******'
        info(self, 'URI {} POST PARAMS: {} HEADERS: {}', uri,
             str(_copy_params), str(headers))
        '''END / DEBUG'''
        r = None
        try:
            r = self.session.post(url, data=params, headers=headers)
        except:
            self.error = 'Post request fail'
            warn(self, self.error)
            return None
        self.status_code = int(r.status_code)
        if self.status_code != 200:
            self.error = self._api_error_string(r, url, _copy_params)
            warn(self, self.error)
            return None
        if not r.content:
            self.error = 'Request return no content'
            warn(self, self.error)
            return None
        self.statContentSizeTotal += sys.getsizeof(r.content)
        '''Retry get if connexion fail'''
        try:
            response_json = r.json()
        except Exception as e:
            warn(self, 'Json loads failed to load... retrying!\n{}', repr(e))
            try:
                response_json = r.json()
            except:
                self.error = "Failed to load json two times...abort"
                warn(self, self.error)
                return None
        status = None
        try:
            status = response_json['status']
        except:
            pass
        if status == 'error':
            self.error = self._api_error_string(r, url, _copy_params,
                                                response_json)
            warn(self, self.error)
            return None
        return response_json