Пример #1
0
def save_exercise_log(request):
    """
    Receives an exercise_id and relevant data,
    saves it to the currently authorized user.
    """

    # Form does all data validation, including of the exercise_id
    form = ExerciseLogForm(data=simplejson.loads(request.raw_post_data))
    if not form.is_valid():
        raise Exception(form.errors)
    data = form.data

    # More robust extraction of previous object
    user = request.session["facility_user"]
    (exerciselog, was_created) = ExerciseLog.get_or_initialize(
        user=user, exercise_id=data["exercise_id"])
    previously_complete = exerciselog.complete

    exerciselog.attempts = data[
        "attempts"]  # don't increment, because we fail to save some requests
    exerciselog.streak_progress = data["streak_progress"]
    exerciselog.points = data["points"]
    exerciselog.language = data.get("language") or request.language

    try:
        exerciselog.full_clean()
        exerciselog.save()
    except ValidationError as e:
        return JsonResponseMessageError(
            _("Could not save ExerciseLog") + u": %s" % e)

    if "points" in request.session:
        del request.session["points"]  # will be recomputed when needed

    # Special message if you've just completed.
    #   NOTE: it's important to check this AFTER calling save() above.
    if not previously_complete and exerciselog.complete:
        exercise = get_node_cache("Exercise").get(data["exercise_id"],
                                                  [None])[0]
        junk, next_exercise = get_neighbor_nodes(
            exercise, neighbor_kind="Exercise") if exercise else None
        if not next_exercise:
            return JsonResponseMessageSuccess(
                _("You have mastered this exercise and this topic!"))
        else:
            return JsonResponseMessageSuccess(
                _("You have mastered this exercise!  Please continue on to <a href='%(href)s'>%(title)s</a>"
                  ) % {
                      "href": next_exercise["path"],
                      "title": _(next_exercise["title"]),
                  })

    # Return no message in release mode; "data saved" message in debug mode.
    return JsonResponse({})
Пример #2
0
def update_all_distributed_callback(request):
    """
    """

    if request.method != "POST":
        raise PermissionDenied("Only POST allowed to this URL endpoint.")

    videos = json.loads(request.POST["video_logs"])
    exercises = json.loads(request.POST["exercise_logs"])
    user = FacilityUser.objects.get(id=request.POST["user_id"])
    node_cache = get_node_cache()
    # Save videos
    n_videos_uploaded = 0
    for video in videos:
        video_id = video['video_id']
        youtube_id = video['youtube_id']

        # 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:
            (vl, _) = VideoLog.get_or_initialize(user=user, video_id=video_id)  # has to be that video_id, could be any youtube_id
            for key,val in video.iteritems():
                setattr(vl, key, val)
            logging.debug("Saving video log for %s: %s" % (video_id, vl))
            vl.save()
            n_videos_uploaded += 1
        except KeyError:  #
            logging.error("Could not save video log for data with missing values: %s" % video)
        except Exception as e:
            error_message = _("Unexpected error importing videos: %(err_msg)s") % {"err_msg": e}
            return JsonResponseMessageError(error_message)

    # Save exercises
    n_exercises_uploaded = 0
    for exercise in exercises:
        # Only save video logs for videos that we recognize.
        if exercise['exercise_id'] not in node_cache['Exercise']:
            logging.warn("Skipping unknown video %s" % exercise['exercise_id'])
            continue

        try:
            (el, _) = ExerciseLog.get_or_initialize(user=user, exercise_id=exercise["exercise_id"])
            for key,val in exercise.iteritems():
                setattr(el, key, val)
            logging.debug("Saving exercise log for %s: %s" % (exercise['exercise_id'], el))
            el.save()
            n_exercises_uploaded += 1
        except KeyError:
            logging.error("Could not save exercise log for data with missing values: %s" % exercise)
        except Exception as e:
            error_message = _("Unexpected error importing exercises: %(err_msg)s") % {"err_msg": e}
            return JsonResponseMessageError(error_message)

    return JsonResponseMessageSuccess(_("Uploaded %(num_exercises)d exercises and %(num_videos)d videos") % {
        "num_exercises": n_exercises_uploaded,
        "num_videos": n_videos_uploaded,
    })
Пример #3
0
def delete_users(request):
    users = simplejson.loads(request.raw_post_data or "{}").get("users", [])
    users_to_delete = FacilityUser.objects.filter(id__in=users)
    users_to_delete.delete()
    return JsonResponseMessageSuccess(
        _("Deleted %(num_users)d users successfully.") %
        {"num_users": users_to_delete.count()})
Пример #4
0
def retry_video_download(request):
    """
    Clear any video still accidentally marked as in-progress, and restart the download job.
    """
    VideoFile.objects.filter(download_in_progress=True).update(download_in_progress=False, percent_complete=0)
    force_job("videodownload", _("Download Videos"), locale=request.language)

    return JsonResponseMessageSuccess(_("Launched video download process successfully."))
Пример #5
0
def cancel_update_progress(request, process_log):
    """
    API endpoint for getting progress data on downloads.
    """
    process_log.cancel_requested = True
    process_log.save()

    return JsonResponseMessageSuccess(_("Cancelled update progress successfully."))
Пример #6
0
def group_delete(request, group_id=None):
    groups = [group_id] if group_id else simplejson.loads(
        request.body or "{}").get("groups", [])
    groups_to_delete = FacilityGroup.objects.filter(id__in=groups)
    count = groups_to_delete.count()
    groups_to_delete.soft_delete()
    return JsonResponseMessageSuccess(
        _("Deleted %(num_groups)d group(s) successfully.") %
        {"num_groups": count})
Пример #7
0
def start_update_kalite(request):
    try:
        data = json.loads(request.raw_post_data)
        mechanism = data['mechanism']
    except KeyError:
        raise KeyError(_("You did not select a valid choice for an update mechanism."))

    call_command_async('update', mechanism, old_server_pid=os.getpid(), in_proc=True)

    return JsonResponseMessageSuccess(_("Launched software update process successfully."))
Пример #8
0
def start_languagepack_download(request):
    if not request.POST:
        raise Exception(_("Must call API endpoint with POST verb."));

    data = json.loads(request.raw_post_data)  # Django has some weird post processing into request.POST, so use raw_post_data
    lang_code = lcode_to_ietf(data['lang'])

    force_job('languagepackdownload', _("Language pack download"), lang_code=lang_code, locale=request.language)

    return JsonResponseMessageSuccess(_("Started language pack download for language %(lang_code)s successfully.") % {"lang_code": lang_code})
Пример #9
0
def cancel_video_download(request):

    # clear all download in progress flags, to make sure new downloads will go through
    VideoFile.objects.all().update(download_in_progress=False)

    # unflag all video downloads
    VideoFile.objects.filter(flagged_for_download=True).update(cancel_download=True, flagged_for_download=False, download_in_progress=False)

    force_job("videodownload", stop=True, locale=request.language)

    return JsonResponseMessageSuccess(_("Cancelled video download process successfully."))
Пример #10
0
def facility_delete(request, facility_id=None):
    if not request.is_django_user:
        raise PermissionDenied("Teachers cannot delete facilities.")

    if request.method != 'POST':
        return JsonResponseMessageError(_("Method is not allowed."))

    facility_id = facility_id or simplejson.loads(request.body or "{}").get("facility_id")
    fac = get_object_or_404(Facility, id=facility_id)

    fac.soft_delete()
    return JsonResponseMessageSuccess(_("Deleted facility %(facility_name)s successfully.") % {"facility_name": fac.name})
Пример #11
0
def facility_delete(request, facility_id=None):
    if not request.is_django_user:
        raise PermissionDenied("Teachers cannot delete facilities.")

    facility_id = facility_id or simplejson.loads(request.raw_post_data
                                                  or "{}").get("facility_id")
    fac = get_object_or_404(Facility, id=facility_id)
    if not fac.is_deletable():
        return JsonResponseMessageError(
            _("Facility %(facility_name)s is not deletable.") %
            {"facility_name": fac.name})

    fac.delete()
    return JsonResponseMessageSuccess(
        _("Deleted facility %(facility_name)s successfully.") %
        {"facility_name": fac.name})
Пример #12
0
def move_to_group(request):
    users = simplejson.loads(request.body or "{}").get("users", [])
    group_id = simplejson.loads(request.body or "{}").get("group", "")
    group_update = get_object_or_None(FacilityGroup, id=group_id)
    users_to_move = FacilityUser.objects.filter(id__in=users)
    for user in users_to_move:  # can't do update for syncedmodel
        user.group = group_update
        user.save()
    if group_update:
        group_name = group_update.name
    else:
        group_name = group_id
    return JsonResponseMessageSuccess(_("Moved %(num_users)d users to group %(group_name)s successfully.") % {
        "num_users": users_to_move.count(),
        "group_name": group_name,
    })
Пример #13
0
def delete_videos(request):
    """
    API endpoint for deleting videos.
    """
    youtube_ids = simplejson.loads(request.raw_post_data or "{}").get("youtube_ids", [])
    num_deleted = 0

    for id in youtube_ids:
        # Delete the file on disk
        delete_downloaded_files(id)

        # Delete the file in the database
        found_videos = VideoFile.objects.filter(youtube_id=id)
        num_deleted += found_videos.count()
        found_videos.delete()

    return JsonResponseMessageSuccess(_("Deleted %(num_videos)s video(s) successfully.") % {"num_videos": num_deleted})
Пример #14
0
def start_update_kalite(request):
    try:
        data = json.loads(request.body)
        mechanism = data['mechanism']
    except KeyError:
        raise KeyError(
            _("You did not select a valid choice for an update mechanism."))

    # Clear any preexisting logs
    if UpdateProgressLog.objects.count():
        UpdateProgressLog.objects.all().delete()

    call_command_async('update',
                       mechanism,
                       old_server_pid=os.getpid(),
                       in_proc=True)

    return JsonResponseMessageSuccess(
        _("Launched software update process successfully."))
Пример #15
0
def start_video_download(request):
    """
    API endpoint for launching the videodownload job.
    """
    youtube_ids = OrderedSet(simplejson.loads(request.raw_post_data or "{}").get("youtube_ids", []))

    # One query per video (slow)
    video_files_to_create = [id for id in youtube_ids if not get_object_or_None(VideoFile, youtube_id=id)]

    # OK to do bulk_create; cache invalidation triggered via save download
    for lang_code, lang_youtube_ids in divide_videos_by_language(video_files_to_create).iteritems():
        VideoFile.objects.bulk_create([VideoFile(youtube_id=id, flagged_for_download=True, language=lang_code) for id in lang_youtube_ids])

    # OK to update all, since we're not setting all props above.
    # One query per chunk
    for chunk in break_into_chunks(youtube_ids):
        video_files_needing_model_update = VideoFile.objects.filter(download_in_progress=False, youtube_id__in=chunk).exclude(percent_complete=100)
        video_files_needing_model_update.update(percent_complete=0, cancel_download=False, flagged_for_download=True)

    force_job("videodownload", _("Download Videos"), locale=request.language)

    return JsonResponseMessageSuccess(_("Launched video download process successfully."))