def get_recent_listens_for_user_list(user_list): """ Fetch the most recent listens for a comma separated list of users. Take care to properly HTTP escape user names that contain commas! :statuscode 200: Fetched listens successfully. :statuscode 400: Your user list was incomplete or otherwise invalid. :resheader Content-Type: *application/json* """ limit = _parse_int_arg("limit", 2) users = parse_user_list(user_list) if not len(users): raise APIBadRequest("user_list is empty or invalid.") db_conn = webserver.create_influx(current_app) listens = db_conn.fetch_recent_listens_for_users(users, limit=limit) listen_data = [] for listen in listens: listen_data.append(listen.to_api()) return jsonify({ 'payload': { 'user_list': user_list, 'count': len(listen_data), 'listens': listen_data, } })
def export_data(): """ Exporting the data to json """ if request.method == "POST": db_conn = webserver.create_influx(current_app) filename = current_user.musicbrainz_id + "_lb-" + datetime.today().strftime('%Y-%m-%d') + ".json" # fetch all listens for the user from listenstore by making repeated queries to # listenstore until we get all the data to_ts = int(time()) listens = [] while True: batch = db_conn.fetch_listens(current_user.musicbrainz_id, to_ts=to_ts, limit=EXPORT_FETCH_COUNT) if not batch: break listens.extend(batch) to_ts = batch[-1].ts_since_epoch # new to_ts will the the timestamp of the last listen fetched # Fetch output and convert it into dict with keys as indexes output = [] for index, obj in enumerate(listens): dic = obj.data dic['timestamp'] = obj.ts_since_epoch dic['release_msid'] = None if obj.release_msid is None else str(obj.release_msid) dic['artist_msid'] = None if obj.artist_msid is None else str(obj.artist_msid) dic['recording_msid'] = None if obj.recording_msid is None else str(obj.recording_msid) output.append(dic) response = make_response(ujson.dumps(output)) response.headers["Content-Disposition"] = "attachment; filename=" + filename response.headers['Content-Type'] = 'application/json; charset=utf-8' response.mimetype = "text/json" return response else: return render_template("user/export.html", user=current_user)
def get_listens(user_name): """ Get listens for user ``user_name``. The format for the JSON returned is defined in our :ref:`json-doc`. If none of the optional arguments are given, this endpoint will return the :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` most recent listens. The optional ``max_ts`` and ``min_ts`` UNIX epoch timestamps control at which point in time to start returning listens. You may specify max_ts or min_ts, but not both in one call. Listens are always returned in descending timestamp order. :param max_ts: If you specify a ``max_ts`` timestamp, listens with listened_at less than (but not including) this value will be returned. :param min_ts: If you specify a ``min_ts`` timestamp, listens with listened_at greater than (but not including) this value will be returned. :param count: Optional, number of listens to return. Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` . Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET` :statuscode 200: Yay, you have data! :resheader Content-Type: *application/json* """ current_time = int(time.time()) max_ts = _parse_int_arg("max_ts") min_ts = _parse_int_arg("min_ts") # if no max given, use now() if max_ts and min_ts: log_raise_400("You may only specify max_ts or min_ts, not both.") # If none are given, start with now and go down if max_ts == None and min_ts == None: max_ts = current_time db_conn = webserver.create_influx(current_app) listens = db_conn.fetch_listens( user_name, limit=min(_parse_int_arg("count", DEFAULT_ITEMS_PER_GET), MAX_ITEMS_PER_GET), from_ts=min_ts, to_ts=max_ts, ) listen_data = [] for listen in listens: listen_data.append(listen.to_api()) latest_listen = db_conn.fetch_listens( user_name, limit=1, to_ts=current_time, ) latest_listen_ts = latest_listen[0].ts_since_epoch if len( latest_listen) > 0 else 0 if min_ts: listen_data = listen_data[::-1] return jsonify({ 'payload': { 'user_id': user_name, 'count': len(listen_data), 'listens': listen_data, 'latest_listen_ts': latest_listen_ts, } })
def fetch_listens(musicbrainz_id, to_ts): """ Fetch all listens for the user from listenstore by making repeated queries to listenstore until we get all the data. Returns a generator that streams the results. """ db_conn = webserver.create_influx(current_app) while True: batch = db_conn.fetch_listens(current_user.musicbrainz_id, to_ts=to_ts, limit=EXPORT_FETCH_COUNT) if not batch: break yield from batch to_ts = batch[ -1].ts_since_epoch # new to_ts will be the the timestamp of the last listen fetched
def get_listens(user_name): """ Get listens for user ``user_name``. The format for the JSON returned is defined in our :ref:`json-doc`. If none of the optional arguments are given, this endpoint will return the :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` most recent listens. The optional ``max_ts`` and ``min_ts`` UNIX epoch timestamps control at which point in time to start returning listens. You may specify max_ts or min_ts, but not both in one call. Listens are always returned in descending timestamp order. :param max_ts: If you specify a ``max_ts`` timestamp, listens with listened_at less than (but not including) this value will be returned. :param min_ts: If you specify a ``min_ts`` timestamp, listens with listened_at greater than (but not including) this value will be returned. :param count: Optional, number of listens to return. Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` . Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET` :statuscode 200: Yay, you have data! :resheader Content-Type: *application/json* """ max_ts = _parse_int_arg("max_ts") min_ts = _parse_int_arg("min_ts") # if no max given, use now() if max_ts and min_ts: log_raise_400("You may only specify max_ts or min_ts, not both.") # If none are given, start with now and go down if max_ts == None and min_ts == None: max_ts = int(time.time()) db_conn = webserver.create_influx(current_app) listens = db_conn.fetch_listens( user_name, limit=min(_parse_int_arg("count", DEFAULT_ITEMS_PER_GET), MAX_ITEMS_PER_GET), from_ts=min_ts, to_ts=max_ts, ) listen_data = [] for listen in listens: listen_data.append(listen.to_api()) if min_ts: listen_data = listen_data[::-1] return jsonify({'payload': { 'user_id': user_name, 'count': len(listen_data), 'listens': listen_data, }})
def export_data(): """ Exporting the data to json """ if request.method == "POST": db_conn = webserver.create_influx(current_app) filename = current_user.musicbrainz_id + "_lb-" + datetime.today( ).strftime('%Y-%m-%d') + ".json" # Build a generator that streams the json response. We never load all # listens into memory at once, and we can start serving the response # immediately. to_ts = int(time()) listens = fetch_listens(current_user.musicbrainz_id, to_ts) output = stream_json_array(listen.to_api() for listen in listens) response = Response(stream_with_context(output)) response.headers[ "Content-Disposition"] = "attachment; filename=" + filename response.headers['Content-Type'] = 'application/json; charset=utf-8' response.mimetype = "text/json" return response else: return render_template("user/export.html", user=current_user)