diff --git a/web2py/applications/smc/controllers/lms.py b/web2py/applications/smc/controllers/lms.py index 791bbd8d..cdc22089 100644 --- a/web2py/applications/smc/controllers/lms.py +++ b/web2py/applications/smc/controllers/lms.py @@ -32,6 +32,35 @@ def test(): return locals() +# Fetch quiz questions and pack them up into an encrypted package +def get_quiz_questions_for_student(): + response.view = 'generic.json' + ret = dict() + # Get the param - student, course_id, quiz_id, auth_key + student_user = request.args(0) + try: + course_id = int(request.args(1)) + quiz_id = int(request.args(2)) + except: + ret["msg"] = "Invalid parameters!" + return ret + auth_key = request.args(3) + if course_id is None or quiz_id is None or auth_key is None: + ret["msg"] = "ERROR - Invalid input data!" + return ret + + # do API calls + # is this student in this course? + course_list = Canvas.get_courses_for_student(student_user) + if not course_id in course_list: + ret["msg"] = "ERROR - Not enrolled in that course! " + str(student_user) + "/" + str(course_id) + return ret + + # Get the questions for this quiz + quiz_questions = Canvas.get_question_payload_for_quiz(course_id, quiz_id, auth_key) + #print(quiz_questions) + return json.dumps(quiz_questions) + #@auth.requires_membership("Administrators") #@auth.requires(auth.has_membership('Faculty') or auth.has_membership('Administrators')) @auth.requires_permission("credential") diff --git a/web2py/applications/smc/controllers/media.py b/web2py/applications/smc/controllers/media.py index 0c81201e..c7235bb8 100644 --- a/web2py/applications/smc/controllers/media.py +++ b/web2py/applications/smc/controllers/media.py @@ -14,6 +14,94 @@ from pytube import YouTube +def media_list(): + response.view = "default.json" + ret = list() + + search_term = request.vars.get("search_term") + if search_term is None or search_term == "": + return dumps(ret) + + print("Search Term: " + search_term) + + # Get media files.... + query = ( + (db.media_files.category.contains(search_term)) | + (db.media_files.tags.contains(search_term)) + ) + + rows = db(query).select() + for row in rows: + item = dict() + item["file_type"] = "media" + item["media_guid"] = row.media_guid + item["title"] = row.title + item["tags"] = row.tags + item["category"] = row.category + file_list = list() + + prefix = row.media_guid[:2] + "/" + base_url = URL('static', 'media') + "/" + prefix + + + file_list.append( + base_url + row.media_guid + ".poster.png" + ) + + file_list.append( + base_url + row.media_guid + ".thumb.png" + ) + + file_list.append( + base_url + row.media_guid + ".json" + ) + + file_list.append( + base_url + row.media_guid + ".mp4" + ) + + vtt_files = get_media_captions_list(row.media_guid) + for v_file in vtt_files: + file_list.append( + base_url + row.media_guid + "_" + v_file + ".vtt" + ) + + item["files"] = file_list + + ret.append(item) + + # Get document files + query = ( + (db.document_files.category.contains(search_term)) | + (db.document_files.tags.contains(search_term)) + ) + + rows = db(query).select() + for row in rows: + item = dict() + item["file_type"] = "document" + item["document_guid"] = row.document_guid + item["title"] = row.title + item["tags"] = row.tags + item["category"] = row.category + file_list = list() + + prefix = row.document_guid[:2] + "/" + base_url = URL('static', 'documents') + "/" + prefix + + file_list.append( + base_url + row.document_guid + ) + file_list.append( + base_url + row.document_guid + ".json" + ) + + item["files"] = file_list + + ret.append(item) + + return dumps(ret) + def index(): ret = start_process_videos() diff --git a/web2py/applications/smc/modules/ednet/canvas.py b/web2py/applications/smc/modules/ednet/canvas.py index 9093e58b..f193aaa8 100644 --- a/web2py/applications/smc/modules/ednet/canvas.py +++ b/web2py/applications/smc/modules/ednet/canvas.py @@ -829,6 +829,51 @@ def GetQueryStringFromDictionary(params=None): ret += key + "=" + v return ret + @staticmethod + def get_courses_for_student(student): + Canvas.Init() + api = "/api/v1/users/sis_login_id:" + student + "/courses" + + p = dict() + p["per_page"] = 200000 + + course_list = dict() + + current_enrollment = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api, params=p) + + if current_enrollment is None: + print("Error pulling canvas enrollment - " + str(api)) + return course_list + + # Save next_url in case there are more pages to get + next_url = Canvas._api_next + + for c in current_enrollment: + if 'id' in c and 'name' in c: + course_list[c['id']] = c['name'] + else: + course_list["ERROR"] = "ERR (" + str(student) + ") - Is this user in canvas? SIS_LOGIN_ID doesn't match." + + # Keep grabbing more until we run out of pages + while next_url != '': + # Strip off server name + api = next_url.replace(Canvas._canvas_server_url, "") + current_enrollment = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api) # don't send params, params=p) + if current_enrollment is None: + print("Error pulling canvas enrollment - " + str(api)) + return course_list + + next_url = Canvas._api_next + + for c in current_enrollment: + if 'id' in c and 'name' in c: + course_list[c['id']] = c['name'] + else: + course_list["ERROR"] = "ERR (" + str(student) + ") - Is this user in canvas? SIS_LOGIN_ID doesn't match." + + return course_list @staticmethod def get_courses_for_faculty(faculty): @@ -1049,6 +1094,87 @@ def get_quiz_list_for_course(course_id): return quiz_bodies + @staticmethod + def get_question_payload_for_quiz(course_id, quiz_id, user_auth_key): + payload = list() + + # Get the list of questions for this quiz + Canvas.Init() + api = "/api/v1/courses/" + str(course_id) + "/quizzes/" + str(quiz_id) + "/questions" + + p = dict() + p["per_page"] = 50 + + next_url = "" + question_objects = dict() + + question_list = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api, params=p) + if question_list is None: + print("Error pulling question list - " + str(api)) + return payload + + # If there are more pages, _api_next should have the link to the next page + next_url = Canvas._api_next + # print("Next URL: " + next_url) + + for q in question_list: + question_objects[q['id']] = q + + while next_url != '': + # Calls to get more results (and strip off https://canvas.ed/) + api = next_url.replace(Canvas._canvas_server_url, "") + # print("Next API: " + api) + question_list = Canvas.APICall(Canvas._canvas_server_url, Canvas._canvas_access_token, + api) # Note - don't send params, they are in the api url + if question_list is None: + print("Error pulling question list - " + str(api)) + break + + # If there are more pages, _api_next should have the link to the next page + next_url = Canvas._api_next + # print("Next URL: " + next_url) + + for q in question_list: + # print("P: " + str(p)) + question_objects[q['id']] = q + + # We have the questions, process them and put them in the payload + for qid in question_objects: + # payload question + q = question_objects[qid] + question_id = q["id"] + quizz_id = q['quiz_id'] + pq = dict() + pq["id"] = question_id + pq["course_id"] = course_id + pq["quiz_id"] = q["quiz_id"] + pq["position"] = q["position"] + pq["question_type"] = q["question_type"] + pq["quiz_group_id"] = q["quiz_group_id"] + + payload_token = str(uuid.uuid4()).replace("-","") + pq["payload_token"] = payload_token + + json_str = json.dumps(q) + # Build the payload_hash + h = hashlib.sha256() + h.update(user_auth_key.encode()) + h.update(str(course_id).encode()) + h.update(str(quiz_id).encode()) + h.update(str(question_id).encode()) + h.update(payload_token.encode()) + + enc_key = h.hexdigest() + + # Encrypt the payload + pl = Util.encrypt(json_str, enc_key) + pq["question_payload"] = pl.decode() + payload.append(pq) + + return payload + + @staticmethod def get_quiz_questions_for_quiz(course_id, quiz_id): Canvas.Init()