Exemplo n.º 1
0
def submit_listen():
    """
    Submit listens to the server. A user token (found on https://listenbrainz.org/user/import ) must
    be provided in the Authorization header!

    For complete details on the format of the JSON to be POSTed to this endpoint, see :ref:`json-doc`.

    :reqheader Authorization: Token <user token>
    :statuscode 200: listen(s) accepted.
    :statuscode 400: invalid JSON sent, see error message for details.
    :statuscode 401: invalid authorization. See error message for details.
    :resheader Content-Type: *application/json*
    """
    user = _validate_auth_header()

    raw_data = request.get_data()
    try:
        data = ujson.loads(raw_data.decode("utf-8"))
    except ValueError as e:
        log_raise_400("Cannot parse JSON document: %s" % e, raw_data)

    try:
        payload = data['payload']
        if len(payload) == 0:
            return "success"

        if len(raw_data) > len(payload) * MAX_LISTEN_SIZE:
            log_raise_400(
                "JSON document is too large. In aggregate, listens may not "
                "be larger than %d characters." % MAX_LISTEN_SIZE, payload)

        if data['listen_type'] not in ('playing_now', 'single', 'import'):
            log_raise_400("JSON document requires a valid listen_type key.",
                          payload)

        listen_type = _get_listen_type(data['listen_type'])
        if (listen_type == LISTEN_TYPE_SINGLE or listen_type
                == LISTEN_TYPE_PLAYING_NOW) and len(payload) > 1:
            log_raise_400(
                "JSON document contains more than listen for a single/playing_now. "
                "It should contain only one.", payload)
    except KeyError:
        log_raise_400("Invalid JSON document submitted.", raw_data)

    # validate listens to make sure json is okay
    for listen in payload:
        validate_listen(listen, listen_type)

    try:
        insert_payload(payload,
                       user,
                       listen_type=_get_listen_type(data['listen_type']))
    except Exception, e:
        raise InternalServerError("Something went wrong. Please try again.")
Exemplo n.º 2
0
def submit_listen():
    """
    Submit listens to the server. A user token (found on https://listenbrainz.org/user/import ) must
    be provided in the Authorization header!

    For complete details on the format of the JSON to be POSTed to this endpoint, see :ref:`json-doc`.

    :reqheader Authorization: token <user token>
    :statuscode 200: listen(s) accepted.
    :statuscode 400: invalid JSON sent, see error message for details.
    :statuscode 401: invalid authorization. See error message for details.
    :resheader Content-Type: *application/json*
    """
    user = _validate_auth_header()

    raw_data = request.get_data()
    try:
        data = ujson.loads(raw_data.decode("utf-8"))
    except ValueError as e:
        log_raise_400("Cannot parse JSON document: %s" % e, raw_data)

    try:
        payload = data['payload']
        if len(payload) == 0:
            return "success"

        if len(raw_data) > len(payload) * MAX_LISTEN_SIZE:
            log_raise_400("JSON document is too large. In aggregate, listens may not "
                           "be larger than %d characters." % MAX_LISTEN_SIZE, payload)

        if data['listen_type'] not in ('playing_now', 'single', 'import'):
            log_raise_400("JSON document requires a valid listen_type key.", payload)

        listen_type = data['listen_type']
        if (listen_type == LISTEN_TYPE_SINGLE or listen_type == LISTEN_TYPE_PLAYING_NOW) and len(payload) > 1:
            _log_raise_400("JSON document contains more than listen for a single/playing_now. "
                           "It should contain only one.", payload)
    except KeyError:
        log_raise_400("Invalid JSON document submitted.", raw_data)

    try:
        insert_payload(payload, user["id"], listen_type=data['listen_type'])
    except Exception, e:
        raise InternalServerError("Something went wrong. Please try again.")
Exemplo n.º 3
0
def record_listens(request, data):
    """ Submit the listen in the lastfm format to be inserted in db.
        Accepts listens for both track.updateNowPlaying and track.scrobble methods.
    """
    output_format = data.get('format', 'xml')
    try:
        sk, api_key = data['sk'], data['api_key']
    except KeyError:
        raise InvalidAPIUsage(
            CompatError.INVALID_PARAMETERS,
            output_format=output_format)  # Invalid parameters

    session = Session.load(sk, api_key)
    if not session:
        if not Token.is_valid_api_key(api_key):
            raise InvalidAPIUsage(
                CompatError.INVALID_API_KEY,
                output_format=output_format)  # Invalid API_KEY
        raise InvalidAPIUsage(
            CompatError.INVALID_SESSION_KEY,
            output_format=output_format)  # Invalid Session KEY

    lookup = defaultdict(dict)
    for key, value in data.items():
        if key in ["sk", "token", "api_key", "method", "api_sig"]:
            continue
        matches = re.match('(.*)\[(\d+)\]', key)
        if matches:
            key = matches.group(1)
            number = matches.group(2)
        else:
            number = 0
        lookup[number][key] = value

    if request.form['method'].lower() == 'track.updatenowplaying':
        for i, listen in lookup.iteritems():
            if 'timestamp' not in listen:
                listen['timestamp'] = calendar.timegm(
                    datetime.now().utctimetuple())

    # Convert to native payload then submit 'em after validation.
    listen_type, native_payload = _to_native_api(lookup, data['method'],
                                                 output_format)
    for listen in native_payload:
        validate_listen(listen, listen_type)
    augmented_listens = insert_payload(native_payload,
                                       session.user,
                                       listen_type=listen_type)

    # With corrections than the original submitted listen.
    doc, tag, text = Doc().tagtext()
    with tag('lfm', status='ok'):
        with tag('nowplaying' if listen_type ==
                 'playing_now' else 'scrobbles'):

            for origL, augL in zip(lookup.values(), augmented_listens):
                corr = defaultdict(lambda: '0')

                track = augL['track_metadata']['track_name']
                if origL['track'] != augL['track_metadata']['track_name']:
                    corr['track'] = '1'

                artist = augL['track_metadata']['artist_name']
                if origL['artist'] != augL['track_metadata']['artist_name']:
                    corr['artist'] = '1'

                ts = augL['listened_at']

                albumArtist = artist
                if origL.get('albumArtist', origL['artist']) != artist:
                    corr['albumArtist'] = '1'

                album = augL['track_metadata'].get('release_name', '')
                if origL.get('album', '') != album:
                    corr['album'] = '1'

                with tag('scrobble'):
                    with tag('track', corrected=corr['track']):
                        text(track)
                    with tag('artist', corrected=corr['artist']):
                        text(artist)
                    with tag('album', corrected=corr['album']):
                        text(album)
                    with tag('albumArtist', corrected=corr['albumArtist']):
                        text(albumArtist)
                    with tag('timestamp'):
                        text(ts)
                    with tag('ignoredMessage', code="0"):
                        text('')

    return format_response(
        '<?xml version="1.0" encoding="utf-8"?>\n' +
        yattag.indent(doc.getvalue()), output_format)
Exemplo n.º 4
0
def record_listens(request, data):
    """ Submit the listen in the lastfm format to be inserted in db.
        Accepts listens for both track.updateNowPlaying and track.scrobble methods.
    """
    output_format = data.get('format', 'xml')
    try:
        sk, api_key = data['sk'], data['api_key']
    except KeyError:
        raise InvalidAPIUsage(6, output_format=output_format)       # Invalid parameters

    session = Session.load(sk, api_key)
    if not session:
        if not Token.is_valid_api_key(api_key):
            raise InvalidAPIUsage(10, output_format=output_format)   # Invalid API_KEY
        raise InvalidAPIUsage(9, output_format=output_format)        # Invalid Session KEY

    lookup = defaultdict(dict)
    for key, value in data.items():
        if key == "sk" or key == "token" or key == "api_key" or key == "method":
            continue
        matches = re.match('(.*)\[(\d+)\]', key)
        if matches:
            key = matches.group(1)
            number = matches.group(2)
        else:
            number = 0
        lookup[number][key] = value

    if request.form['method'].lower() == 'track.updatenowplaying':
        for i, listen in lookup.iteritems():
            if 'timestamp' not in listen:
                listen['timestamp'] = calendar.timegm(datetime.now().utctimetuple())

    # Convert to native payload then submit 'em.
    listen_type, native_payload = _to_native_api(lookup, data['method'], output_format)
    augmented_listens = insert_payload(native_payload, str(session.user.id), listen_type=listen_type)

    # With corrections than the original submitted listen.
    doc, tag, text = Doc().tagtext()
    with tag('lfm', status='ok'):
        with tag('nowplaying' if listen_type == 'playing_now' else 'scrobbles'):

            for origL, augL in zip(lookup.values(), augmented_listens):
                corr = defaultdict(lambda: '0')

                track = augL['track_metadata']['track_name']
                if origL['track'] != augL['track_metadata']['track_name']:
                    corr['track'] = '1'

                artist = augL['track_metadata']['artist_name']
                if origL['artist'] != augL['track_metadata']['artist_name']:
                    corr['artist'] = '1'

                ts = augL['listened_at']

                albumArtist = artist
                if origL.get('albumArtist', origL['artist']) != artist:
                    corr['albumArtist'] = '1'

                # TODO: Add the album part
                album = ""

                with tag('scrobble'):
                    with tag('track', corrected=corr['track']):
                        text(track)
                    with tag('artist', corrected=corr['artist']):
                        text(artist)
                    with tag('album', corrected=corr['album']):
                        text(album)
                    with tag('albumArtist', corrected=corr['albumArtist']):
                        text(albumArtist)
                    with tag('timestamp'):
                        text(ts)
                    with tag('ignoredMessage', code="0"):
                        text('')

    return format_response('<?xml version="1.0" encoding="utf-8"?>\n' + yattag.indent(doc.getvalue()),
                           output_format)