def update_all_central_callback(request): """ Callback after authentication. Parses out the request token verification. Then finishes the request by getting an auth token. """ if not "ACCESS_TOKEN" in request.session: finish_auth(request) exercises = get_api_resource(request, "/api/v1/user/exercises") videos = get_api_resource(request, "/api/v1/user/videos") # Save videos video_logs = [] for video in videos: youtube_id = video.get('video', {}).get('youtube_id', "") # Only save videos with progress if not video.get('seconds_watched', None): continue # Only save video logs for videos that we recognize. if youtube_id not in ID2SLUG_MAP: logging.warn("Skipping unknown video %s" % youtube_id) continue try: video_logs.append({ "youtube_id": youtube_id, "total_seconds_watched": video['seconds_watched'], "points": VideoLog.calc_points(video['seconds_watched'], video['duration']), "complete": video['completed'], "completion_timestamp": convert_ka_date(video['last_watched']) if video['completed'] else None, }) logging.debug("Got video log for %s: %s" % (youtube_id, video_logs[-1])) except KeyError: # logging.error( "Could not save video log for data with missing values: %s" % video) # Save exercises exercise_logs = [] for exercise in exercises: # Only save exercises that have any progress. if not exercise.get('last_done', None): continue # Only save video logs for videos that we recognize. slug = exercise.get('exercise', "") if slug not in NODE_CACHE['Exercise']: logging.warn("Skipping unknown video %s" % slug) continue try: completed = exercise['streak'] >= 10 basepoints = NODE_CACHE['Exercise'][slug]['basepoints'] exercise_logs.append({ "exercise_id": slug, "streak_progress": min(100, 100 * exercise['streak'] / 10), # duplicates logic elsewhere "attempts": exercise['total_done'], "points": ExerciseLog.calc_points( basepoints, ncorrect=exercise['streak'], add_randomness=False ), # no randomness when importing from KA "complete": completed, "attempts_before_completion": exercise['total_done'] if not exercise['practiced'] else None, #can't figure this out if they practiced after mastery. "completion_timestamp": convert_ka_date(exercise['proficient_date']) if completed else None, }) logging.debug("Got exercise log for %s: %s" % (slug, exercise_logs[-1])) except KeyError: logging.error( "Could not save exercise log for data with missing values: %s" % exercise) # POST the data back to the distributed server dthandler = lambda obj: obj.isoformat() if isinstance( obj, datetime.datetime) else None logging.debug("POST'ing to %s" % request.session["distributed_callback_url"]) response = requests.post( request.session["distributed_callback_url"], cookies={"csrftoken": request.session["distributed_csrf_token"]}, data={ "csrfmiddlewaretoken": request.session["distributed_csrf_token"], "video_logs": json.dumps(video_logs, default=dthandler), "exercise_logs": json.dumps(exercise_logs, default=dthandler), "user_id": request.session["distributed_user_id"], }) logging.debug("Response (%d): %s" % (response.status_code, response.content)) message = json.loads(response.content) # If something broke on the distribute d server, we are SCREWED. # For now, just show the error to users. # # Ultimately, we have a message, would like to share with the distributed server. # if response.status_code != 200: # return HttpResponseServerError(response.content) return HttpResponseRedirect( request.session["distributed_redirect_url"] + "?message_type=%s&message=%s&message_id=id_khanload" % (message.keys()[0], message.values()[0]))
def update_all_central_callback(request): """ Callback after authentication. Parses out the request token verification. Then finishes the request by getting an auth token. """ if not "ACCESS_TOKEN" in request.session: finish_auth(request) exercises = get_api_resource(request, "/api/v1/user/exercises") videos = get_api_resource(request, "/api/v1/user/videos") node_cache = get_node_cache() # Collate videos video_logs = [] for video in videos: # Assume that KA videos are all english-language, not dubbed (for now) video_id = youtube_id = video.get('video', {}).get('youtube_id', "") # Only save videos with progress if not video.get('seconds_watched', None): continue # Only save video logs for videos that we recognize. if video_id not in node_cache["Video"]: logging.warn("Skipping unknown video %s" % video_id) continue try: video_logs.append({ "video_id": video_id, "youtube_id": youtube_id, "total_seconds_watched": video['seconds_watched'], "points": VideoLog.calc_points(video['seconds_watched'], video['duration']), "complete": video['completed'], "completion_timestamp": convert_ka_date(video['last_watched']) if video['completed'] else None, }) logging.debug("Got video log for %s: %s" % (video_id, video_logs[-1])) except KeyError: # logging.error( "Could not save video log for data with missing values: %s" % video) # Collate exercises exercise_logs = [] for exercise in exercises: # Only save exercises that have any progress. if not exercise.get('last_done', None): continue # Only save video logs for videos that we recognize. slug = exercise.get('exercise', "") if slug not in node_cache['Exercise']: logging.warn("Skipping unknown video %s" % slug) continue try: completed = exercise['streak'] >= 10 basepoints = node_cache['Exercise'][slug][0]['basepoints'] exercise_logs.append({ "exercise_id": slug, "streak_progress": min(100, 100 * exercise['streak'] / 10), # duplicates logic elsewhere "attempts": exercise['total_done'], "points": ExerciseLog.calc_points( basepoints, ncorrect=exercise['streak'], add_randomness=False ), # no randomness when importing from KA "complete": completed, "attempts_before_completion": exercise['total_done'] if not exercise['practiced'] else None, #can't figure this out if they practiced after mastery. "completion_timestamp": convert_ka_date(exercise['proficient_date']) if completed else None, }) logging.debug("Got exercise log for %s: %s" % (slug, exercise_logs[-1])) except KeyError: logging.error( "Could not save exercise log for data with missing values: %s" % exercise) # POST the data back to the distributed server try: dthandler = lambda obj: obj.isoformat() if isinstance( obj, datetime.datetime) else None logging.debug("POST'ing to %s" % request.session["distributed_callback_url"]) response = requests.post( request.session["distributed_callback_url"], cookies={"csrftoken": request.session["distributed_csrf_token"]}, data={ "csrfmiddlewaretoken": request.session["distributed_csrf_token"], "video_logs": json.dumps(video_logs, default=dthandler), "exercise_logs": json.dumps(exercise_logs, default=dthandler), "user_id": request.session["distributed_user_id"], }) logging.debug("Response (%d): %s" % (response.status_code, response.content)) except requests.exceptions.ConnectionError as e: return HttpResponseRedirect( set_query_params( request.session["distributed_redirect_url"], { "message_type": "error", "message": _("Could not connect to your KA Lite installation to share Khan Academy data." ), "message_id": "id_khanload", })) except Exception as e: return HttpResponseRedirect( set_query_params( request.session["distributed_redirect_url"], { "message_type": "error", "message": _("Failure to send data to your KA Lite installation: %s") % e, "message_id": "id_khanload", })) try: json_response = json.loads(response.content) if not isinstance(json_response, dict) or len(json_response) != 1: # Could not validate the message is a single key-value pair raise Exception( _("Unexpected response format from your KA Lite installation.") ) message_type = json_response.keys()[0] message = json_response.values()[0] except ValueError as e: message_type = "error" message = unicode(e) except Exception as e: message_type = "error" message = _("Loading json object: %s") % e # If something broke on the distribute d server, we are SCREWED. # For now, just show the error to users. # # Ultimately, we have a message, would like to share with the distributed server. # if response.status_code != 200: # return HttpResponseServerError(response.content) return HttpResponseRedirect( set_query_params( request.session["distributed_redirect_url"], { "message_type": message_type, "message": message, "message_id": "id_khanload", }))
def update_all_central_callback(request): """ Callback after authentication. Parses out the request token verification. Then finishes the request by getting an auth token. """ if not "ACCESS_TOKEN" in request.session: finish_auth(request) exercises = get_api_resource(request, "/api/v1/user/exercises") videos = get_api_resource(request, "/api/v1/user/videos") node_cache = get_node_cache() # Collate videos video_logs = [] for video in videos: # Assume that KA videos are all english-language, not dubbed (for now) video_id = youtube_id = video.get('video', {}).get('youtube_id', "") # Only save videos with progress if not video.get('seconds_watched', None): continue # Only save video logs for videos that we recognize. if video_id not in node_cache["Video"]: logging.warn("Skipping unknown video %s" % video_id) continue try: video_logs.append({ "video_id": video_id, "youtube_id": youtube_id, "total_seconds_watched": video['seconds_watched'], "points": VideoLog.calc_points(video['seconds_watched'], video['duration']), "complete": video['completed'], "completion_timestamp": convert_ka_date(video['last_watched']) if video['completed'] else None, }) logging.debug("Got video log for %s: %s" % (video_id, video_logs[-1])) except KeyError: # logging.error("Could not save video log for data with missing values: %s" % video) # Collate exercises exercise_logs = [] for exercise in exercises: # Only save exercises that have any progress. if not exercise.get('last_done', None): continue # Only save video logs for videos that we recognize. slug = exercise.get('exercise', "") if slug not in node_cache['Exercise']: logging.warn("Skipping unknown video %s" % slug) continue try: completed = exercise['streak'] >= 10 basepoints = node_cache['Exercise'][slug][0]['basepoints'] exercise_logs.append({ "exercise_id": slug, "streak_progress": min(100, 100 * exercise['streak']/10), # duplicates logic elsewhere "attempts": exercise['total_done'], "points": ExerciseLog.calc_points(basepoints, ncorrect=exercise['streak'], add_randomness=False), # no randomness when importing from KA "complete": completed, "attempts_before_completion": exercise['total_done'] if not exercise['practiced'] else None, #can't figure this out if they practiced after mastery. "completion_timestamp": convert_ka_date(exercise['proficient_date']) if completed else None, }) logging.debug("Got exercise log for %s: %s" % (slug, exercise_logs[-1])) except KeyError: logging.error("Could not save exercise log for data with missing values: %s" % exercise) # POST the data back to the distributed server try: dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None logging.debug("POST'ing to %s" % request.session["distributed_callback_url"]) response = requests.post( request.session["distributed_callback_url"], cookies={ "csrftoken": request.session["distributed_csrf_token"] }, data = { "csrfmiddlewaretoken": request.session["distributed_csrf_token"], "video_logs": json.dumps(video_logs, default=dthandler), "exercise_logs": json.dumps(exercise_logs, default=dthandler), "user_id": request.session["distributed_user_id"], } ) logging.debug("Response (%d): %s" % (response.status_code, response.content)) except requests.exceptions.ConnectionError as e: return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], { "message_type": "error", "message": _("Could not connect to your KA Lite installation to share Khan Academy data."), "message_id": "id_khanload", })) except Exception as e: return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], { "message_type": "error", "message": _("Failure to send data to your KA Lite installation: %s") % e, "message_id": "id_khanload", })) try: json_response = json.loads(response.content) if not isinstance(json_response, dict) or len(json_response) != 1: # Could not validate the message is a single key-value pair raise Exception(_("Unexpected response format from your KA Lite installation.")) message_type = json_response.keys()[0] message = json_response.values()[0] except ValueError as e: message_type = "error" message = unicode(e) except Exception as e: message_type = "error" message = _("Loading json object: %s") % e # If something broke on the distribute d server, we are SCREWED. # For now, just show the error to users. # # Ultimately, we have a message, would like to share with the distributed server. # if response.status_code != 200: # return HttpResponseServerError(response.content) return HttpResponseRedirect(set_query_params(request.session["distributed_redirect_url"], { "message_type": message_type, "message": message, "message_id": "id_khanload", }))
def update_all_central_callback(request): """ Callback after authentication. Parses out the request token verification. Then finishes the request by getting an auth token. """ if not "ACCESS_TOKEN" in request.session: finish_auth(request) exercises = get_api_resource(request, "/api/v1/user/exercises") videos = get_api_resource(request, "/api/v1/user/videos") # Save videos video_logs = [] for video in videos: youtube_id =video.get('video', {}).get('youtube_id', "") # Only save videos with progress if not video.get('seconds_watched', None): continue # Only save video logs for videos that we recognize. if youtube_id not in ID2SLUG_MAP: logging.warn("Skipping unknown video %s" % youtube_id) continue try: video_logs.append({ "youtube_id": youtube_id, "total_seconds_watched": video['seconds_watched'], "points": VideoLog.calc_points(video['seconds_watched'], video['duration']), "complete": video['completed'], "completion_timestamp": convert_ka_date(video['last_watched']) if video['completed'] else None, }) logging.debug("Got video log for %s: %s" % (youtube_id, video_logs[-1])) except KeyError: # logging.error("Could not save video log for data with missing values: %s" % video) # Save exercises exercise_logs = [] for exercise in exercises: # Only save exercises that have any progress. if not exercise.get('last_done', None): continue # Only save video logs for videos that we recognize. slug = exercise.get('exercise', "") if slug not in NODE_CACHE['Exercise']: logging.warn("Skipping unknown video %s" % slug) continue try: completed = exercise['streak'] >= 10 basepoints = NODE_CACHE['Exercise'][slug]['basepoints'] exercise_logs.append({ "exercise_id": slug, "streak_progress": min(100, 100 * exercise['streak']/10), # duplicates logic elsewhere "attempts": exercise['total_done'], "points": ExerciseLog.calc_points(basepoints, ncorrect=exercise['streak'], add_randomness=False), # no randomness when importing from KA "complete": completed, "attempts_before_completion": exercise['total_done'] if not exercise['practiced'] else None, #can't figure this out if they practiced after mastery. "completion_timestamp": convert_ka_date(exercise['proficient_date']) if completed else None, }) logging.debug("Got exercise log for %s: %s" % (slug, exercise_logs[-1])) except KeyError: logging.error("Could not save exercise log for data with missing values: %s" % exercise) # POST the data back to the distributed server dthandler = lambda obj: obj.isoformat() if isinstance(obj, datetime.datetime) else None logging.debug("POST'ing to %s" % request.session["distributed_callback_url"]) response = requests.post( request.session["distributed_callback_url"], cookies={ "csrftoken": request.session["distributed_csrf_token"] }, data = { "csrfmiddlewaretoken": request.session["distributed_csrf_token"], "video_logs": json.dumps(video_logs, default=dthandler), "exercise_logs": json.dumps(exercise_logs, default=dthandler), "user_id": request.session["distributed_user_id"], } ) logging.debug("Response (%d): %s" % (response.status_code, response.content)) message = json.loads(response.content) # If something broke on the distribute d server, we are SCREWED. # For now, just show the error to users. # # Ultimately, we have a message, would like to share with the distributed server. # if response.status_code != 200: # return HttpResponseServerError(response.content) return HttpResponseRedirect(request.session["distributed_redirect_url"] + "?message_type=%s&message=%s&message_id=id_khanload" % (message.keys()[0], message.values()[0]))