def exercise_handler(request, exercise, prev=None, next=None, **related_videos): """ Display an exercise """ lang = request.session[settings.LANGUAGE_COOKIE_NAME] exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises") exercise_file = exercise["slug"] + ".html" exercise_template = exercise_file exercise_localized_template = os.path.join(lang, exercise_file) # Get the language codes for exercise teplates that exist exercise_path = partial(lambda lang, slug, eroot: os.path.join(eroot, lang, slug + ".html"), slug=exercise["slug"], eroot=exercise_root) code_filter = partial(lambda lang, eroot, epath: os.path.isdir(os.path.join(eroot, lang)) and os.path.exists(epath(lang)), eroot=exercise_root, epath=exercise_path) available_langs = set(["en"] + [lang_code for lang_code in os.listdir(exercise_root) if code_filter(lang_code)]) # Return the best available exercise template exercise_lang = select_best_available_language(request.language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = exercise_path(exercise_lang)[(len(exercise_root) + 1):] context = { "exercise": exercise, "title": exercise["title"], "exercise_template": exercise_template, "exercise_lang": exercise_lang, "related_videos": [v for v in related_videos.values() if v["available"]], "prev": prev, "next": next, } return context
def exercise_handler(request, exercise, prev=None, next=None, **related_videos): """ Display an exercise """ lang = request.session[settings.LANGUAGE_COOKIE_NAME] exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises") exercise_file = exercise["slug"] + ".html" exercise_template = exercise_file exercise_localized_template = os.path.join(lang, exercise_file) # Get the language codes for exercise teplates that exist exercise_path = partial(lambda lang, slug, eroot: os.path.join(eroot, lang, slug + ".html"), slug=exercise["slug"], eroot=exercise_root) code_filter = partial(lambda lang, eroot, epath: os.path.isdir(os.path.join(eroot, lang)) and os.path.exists(epath(lang)), eroot=exercise_root, epath=exercise_path) available_langs = set(["en"] + [lang_code for lang_code in os.listdir(exercise_root) if code_filter(lang_code)]) # Return the best available exercise template exercise_lang = select_best_available_language(request.language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = exercise_path(exercise_lang)[(len(exercise_root) + 1):] context = { "exercise": exercise, "title": exercise["title"], "exercise_template": exercise_template, "exercise_lang": exercise_lang, "related_videos": [v for v in related_videos.values() if v["available"]], "prev": prev, "next": next, } return context
def video_handler(request, video, format="mp4", prev=None, next=None): if not video["available"]: if request.is_admin: # TODO(bcipolli): add a link, with querystring args that auto-checks this video in the topic tree messages.warning(request, _("This video was not found! You can download it by going to the Update page.")) elif request.is_logged_in: messages.warning(request, _("This video was not found! Please contact your teacher or an admin to have it downloaded.")) elif not request.is_logged_in: messages.warning(request, _("This video was not found! You must login as an admin/teacher to download the video.")) # Fallback mechanism available_urls = dict([(lang, avail) for lang, avail in video["availability"].iteritems() if avail["on_disk"]]) if video["available"] and not available_urls: vid_lang = "en" messages.success(request, "Got video content from %s" % video["availability"]["en"]["stream"]) else: vid_lang = select_best_available_language(request.language, available_codes=available_urls.keys()) context = { "video": video, "title": video["title"], "num_videos_available": len(video["availability"]), "selected_language": vid_lang, "video_urls": video["availability"].get(vid_lang), "subtitle_urls": video["availability"].get(vid_lang, {}).get("subtitles"), "prev": prev, "next": next, "backup_vids_available": bool(settings.BACKUP_VIDEO_SOURCE), } return context
def video_handler(request, video, format="mp4", prev=None, next=None): if not video["available"]: if request.is_admin: # TODO(bcipolli): add a link, with querystring args that auto-checks this video in the topic tree messages.warning(request, _("This video was not found! You can download it by going to the Update page.")) elif request.is_logged_in: messages.warning(request, _("This video was not found! Please contact your teacher or an admin to have it downloaded.")) elif not request.is_logged_in: messages.warning(request, _("This video was not found! You must login as an admin/teacher to download the video.")) # Fallback mechanism available_urls = dict([(lang, avail) for lang, avail in video["availability"].iteritems() if avail["on_disk"]]) if video["available"] and not available_urls: vid_lang = "en" messages.success(request, "Got video content from %s" % video["availability"]["en"]["stream"]) else: vid_lang = select_best_available_language(request.language, available_codes=available_urls.keys()) context = { "video": video, "title": video["title"], "num_videos_available": len(video["availability"]), "selected_language": vid_lang, "video_urls": video["availability"].get(vid_lang), "subtitle_urls": video["availability"].get(vid_lang, {}).get("subtitles"), "prev": prev, "next": next, "backup_vids_available": bool(settings.BACKUP_VIDEO_SOURCE), } return context
def get_content_data(request, content_id=None): content_cache = get_content_cache() content = content_cache.get(content_id, None) if not content: return None content_lang = i18n.select_best_available_language( request.language, available_codes=content.get("languages", [])) or "" urls = content.get("lang_data_" + content_lang, None) if not urls: if request.is_admin: # TODO(bcipolli): add a link, with querystring args that auto-checks this content in the topic tree messages.warning( request, _("This content was not found! You can download it by going to the Update page." )) elif request.is_logged_in: messages.warning( request, _("This content was not found! Please contact your teacher or an admin to have it downloaded." )) elif not request.is_logged_in: messages.warning( request, _("This content was not found! You must login as an admin/teacher to download the content." )) content = content.copy() content["content_urls"] = urls content["selected_language"] = content_lang content["title"] = _(content["title"]) content["description"] = _(content.get("description", "")) return content
def get_exercise_data(request, exercise_id=None): exercise = get_exercise_cache().get(exercise_id, None) if not exercise: return None exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH) exercise_file = exercise["slug"] + ".html" exercise_template = exercise_file # Get the language codes for exercise templates that exist exercise_path = partial( lambda lang, slug, eroot: os.path.join(eroot, lang, slug + ".html"), slug=exercise["slug"], eroot=exercise_root) code_filter = partial(lambda lang, eroot, epath: os.path.isdir( os.path.join(eroot, lang)) and os.path.exists(epath(lang)), eroot=exercise_root, epath=exercise_path) available_langs = set(["en"] + [ lang_code for lang_code in os.listdir(exercise_root) if code_filter(lang_code) ]) # Return the best available exercise template exercise_lang = i18n.select_best_available_language( request.language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = exercise_path(exercise_lang)[(len(exercise_root) + 1):] exercise["lang"] = exercise_lang exercise["template"] = exercise_template return exercise
def get_content_cache(force=False, annotate=False, language=None): if not language: language = django_settings.LANGUAGE_CODE global CONTENT if CONTENT is None: CONTENT = {} if CONTENT.get(language) is None: content = None if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: content = softload_sqlite_cache(settings.CONTENT_CACHE_FILEPATH) if content: CONTENT[language] = content return CONTENT[language] else: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: call_command("create_content_db") content = softload_sqlite_cache(settings.CONTENT_CACHE_FILEPATH) else: content = softload_json(settings.CONTENT_FILEPATH, logger=logging.debug, raises=False) CONTENT[language] = content annotate = True if annotate: # Loop through all content items and put thumbnail urls, content urls, # and subtitle urls on the content dictionary, and list all languages # that the content is available in. try: contents_folder = os.listdir(django_settings.CONTENT_ROOT) except OSError: contents_folder = [] subtitle_langs = {} if os.path.exists(i18n.get_srt_path()): for (dirpath, dirnames, filenames) in os.walk(i18n.get_srt_path()): # Only both looking at files that are inside a 'subtitles' directory if os.path.basename(dirpath) == "subtitles": lc = os.path.basename(os.path.dirname(dirpath)) for filename in filenames: if filename in subtitle_langs: subtitle_langs[filename].append(lc) else: subtitle_langs[filename] = [lc] for key, content in CONTENT[language].iteritems(): default_thumbnail = create_thumbnail_url(content.get("id")) dubmap = i18n.get_id2oklang_map(content.get("id")) if dubmap: content_lang = i18n.select_best_available_language(language, available_codes=dubmap.keys()) or "" if content_lang: dubbed_id = dubmap.get(content_lang) format = content.get("format", "") if (dubbed_id + "." + format) in contents_folder: content["available"] = True thumbnail = create_thumbnail_url(dubbed_id) or default_thumbnail content["content_urls"] = { "stream": django_settings.CONTENT_URL + dubmap.get(content_lang) + "." + format, "stream_type": "{kind}/{format}".format(kind=content.get("kind", "").lower(), format=format), "thumbnail": thumbnail, } elif django_settings.BACKUP_VIDEO_SOURCE: content["available"] = True content["content_urls"] = { "stream": django_settings.BACKUP_VIDEO_SOURCE.format(youtube_id=dubbed_id, video_format=format), "stream_type": "{kind}/{format}".format(kind=content.get("kind", "").lower(), format=format), "thumbnail": django_settings.BACKUP_VIDEO_SOURCE.format(youtube_id=dubbed_id, video_format="png"), } else: content["available"] = False else: content["available"] = False else: content["available"] = False # Get list of subtitle language codes currently available subtitle_lang_codes = subtitle_langs.get("{id}.srt".format(id=content.get("id")), []) # Generate subtitle URLs for any subtitles that do exist for this content item subtitle_urls = [{ "code": lc, "url": django_settings.STATIC_URL + "srt/{code}/subtitles/{id}.srt".format(code=lc, id=content.get("id")), "name": i18n.get_language_name(lc) } for lc in subtitle_lang_codes] # Sort all subtitle URLs by language code content["subtitle_urls"] = sorted(subtitle_urls, key=lambda x: x.get("code", "")) with i18n.translate_block(language): content["selected_language"] = content_lang content["title"] = _(content["title"]) content["description"] = _(content.get("description")) if content.get("description") else "" CONTENT[language][key] = content if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: CONTENT[language].commit() except IOError as e: logging.warn("Annotated content cache file failed in saving with error {e}".format(e=e)) return CONTENT[language]
def get_exercise_cache(force=False, language=None): if not language: language = django_settings.LANGUAGE_CODE global EXERCISES if EXERCISES is None: EXERCISES = {} if EXERCISES.get(language) is None: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: exercises = softload_json( cache_file_path("exercises_{0}.json".format(language)), logger=logging.debug, raises=False ) if exercises: EXERCISES[language] = exercises return EXERCISES[language] EXERCISES[language] = softload_json(settings.EXERCISES_FILEPATH, logger=logging.debug, raises=False) # English-language exercises live in application space, translations in user space if language == "en": exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises") else: exercise_root = i18n.get_localized_exercise_dirpath(language) if os.path.exists(exercise_root): try: exercise_templates = os.listdir(exercise_root) except OSError: exercise_templates = [] else: exercise_templates = [] for exercise in EXERCISES[language].values(): exercise_file = exercise["name"] + ".html" exercise_template = exercise_file exercise_lang = "en" # The central server doesn't have an assessment item database if django_settings.CENTRAL_SERVER: available = False elif exercise.get("uses_assessment_items", False): available = False items = [] for item in exercise.get("all_assessment_items", []): item = json.loads(item) if get_assessment_item_data(request=None, assessment_item_id=item.get("id")): items.append(item) available = True exercise["all_assessment_items"] = items else: available = exercise_template in exercise_templates # Get the language codes for exercise templates that exist # Try to minimize the number of os.path.exists calls (since they're a bottleneck) by using the same # precedence rules in i18n.select_best_available_languages available_langs = set(["en"] + [language] * available) # Return the best available exercise template exercise_lang = i18n.select_best_available_language(language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = os.path.join(exercise_lang, exercise_file) with i18n.translate_block(language): exercise["available"] = available exercise["lang"] = exercise_lang exercise["template"] = exercise_template exercise["title"] = _(exercise.get("title", "")) exercise["description"] = _(exercise.get("description", "")) if exercise.get("description") else "" if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: with open(cache_file_path("exercises_{0}.json".format(language)), "w") as f: json.dump(EXERCISES[language], f) except IOError as e: logging.warn("Annotated exercise cache file failed in saving with error {e}".format(e=e)) return EXERCISES[language]
def get_content_cache(force=False, annotate=False, language=settings.LANGUAGE_CODE): global CONTENT, CONTENT_FILEPATH if CONTENT is None: CONTENT = {} if CONTENT.get(language) is None: CONTENT[language] = softload_json(CONTENT_FILEPATH, logger=logging.debug, raises=False) annotate = True if annotate: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: content = softload_json(CONTENT_FILEPATH + "_" + language + ".cache", logger=logging.debug, raises=False) if content: CONTENT[language] = content return CONTENT[language] # Loop through all content items and put thumbnail urls, content urls, # and subtitle urls on the content dictionary, and list all languages # that the content is available in. for content in CONTENT[language].values(): default_thumbnail = create_thumbnail_url(content.get("id")) dubmap = i18n.get_id2oklang_map(content.get("id")) if dubmap: content_lang = i18n.select_best_available_language(language, available_codes=dubmap.keys()) or "" if content_lang: dubbed_id = dubmap.get(content_lang) format = content.get("format", "") if is_content_on_disk(dubbed_id, format): content["available"] = True thumbnail = create_thumbnail_url(dubbed_id) or default_thumbnail content["content_urls"] = { "stream": settings.CONTENT_URL + dubmap.get(content_lang) + "." + format, "stream_type": "{kind}/{format}".format(kind=content.get("kind", "").lower(), format=format), "thumbnail": thumbnail, } else: content["available"] = False else: content["available"] = False else: content["available"] = False # Get list of subtitle language codes currently available subtitle_lang_codes = [] if not os.path.exists(i18n.get_srt_path()) else [lc for lc in os.listdir(i18n.get_srt_path()) if os.path.exists(i18n.get_srt_path(lc, content.get("id")))] # Generate subtitle URLs for any subtitles that do exist for this content item subtitle_urls = [{ "code": lc, "url": settings.STATIC_URL + "srt/{code}/subtitles/{id}.srt".format(code=lc, id=content.get("id")), "name": i18n.get_language_name(lc) } for lc in subtitle_lang_codes if os.path.exists(i18n.get_srt_path(lc, content.get("id")))] # Sort all subtitle URLs by language code content["subtitle_urls"] = sorted(subtitle_urls, key=lambda x: x.get("code", "")) with i18n.translate_block(content_lang): content["selected_language"] = content_lang content["title"] = _(content["title"]) content["description"] = _(content.get("description", "")) if content.get("description") else "" if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: with open(CONTENT_FILEPATH + "_" + language + ".cache", "w") as f: json.dump(CONTENT[language], f) except IOError as e: logging.warn("Annotated content cache file failed in saving with error {e}".format(e=e)) return CONTENT[language]
def get_exercise_cache(force=False, language=settings.LANGUAGE_CODE): global EXERCISES, EXERCISES_FILEPATH if EXERCISES is None: EXERCISES = {} if EXERCISES.get(language) is None: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: exercises = softload_json(EXERCISES_FILEPATH + "_" + language + ".cache", logger=logging.debug, raises=False) if exercises: EXERCISES[language] = exercises return EXERCISES[language] EXERCISES[language] = softload_json(EXERCISES_FILEPATH, logger=logging.debug, raises=False) exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises") if os.path.exists(exercise_root): exercise_templates = os.listdir(exercise_root) else: exercise_templates = [] assessmentitems = get_assessment_item_cache() TEMPLATE_FILE_PATH = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises", "%s") for exercise in EXERCISES[language].values(): exercise_file = exercise["name"] + ".html" exercise_template = exercise_file exercise_lang = "en" if exercise.get("uses_assessment_items", False): available = False items = [] for item in exercise.get("all_assessment_items","[]"): item = json.loads(item) if assessmentitems.get(item.get("id")): items.append(item) available = True exercise["all_assessment_items"] = items else: available = os.path.isfile(TEMPLATE_FILE_PATH % exercise_template) # Get the language codes for exercise templates that exist available_langs = set(["en"] + [lang_code for lang_code in exercise_templates if os.path.exists(os.path.join(exercise_root, lang_code, exercise_file))]) # Return the best available exercise template exercise_lang = i18n.select_best_available_language(language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = os.path.join(exercise_lang, exercise_file) with i18n.translate_block(language): exercise["available"] = available exercise["lang"] = exercise_lang exercise["template"] = exercise_template exercise["title"] = _(exercise.get("title", "")) exercise["description"] = _(exercise.get("description", "")) if exercise.get("description") else "" if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: with open(EXERCISES_FILEPATH + "_" + language + ".cache", "w") as f: json.dump(EXERCISES[language], f) except IOError as e: logging.warn("Annotated exercise cache file failed in saving with error {e}".format(e=e)) return EXERCISES[language]
def get_content_cache(force=False, annotate=False, language=settings.LANGUAGE_CODE): global CONTENT, CONTENT_FILEPATH if CONTENT is None: CONTENT = {} if CONTENT.get(language) is None: CONTENT[language] = softload_json(CONTENT_FILEPATH, logger=logging.debug, raises=False) annotate = True if annotate: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: content = softload_json(CONTENT_FILEPATH + "_" + language + ".cache", logger=logging.debug, raises=False) if content: CONTENT[language] = content return CONTENT[language] # Loop through all content items and put thumbnail urls, content urls, # and subtitle urls on the content dictionary, and list all languages # that the content is available in. for content in CONTENT[language].values(): default_thumbnail = create_thumbnail_url(content.get("id")) dubmap = i18n.get_id2oklang_map(content.get("id")) if dubmap: content_lang = i18n.select_best_available_language(language, available_codes=dubmap.keys()) or "" if content_lang: dubbed_id = dubmap.get(content_lang) format = content.get("format", "") if is_content_on_disk(dubbed_id, format): content["available"] = True thumbnail = create_thumbnail_url(dubbed_id) or default_thumbnail content["content_urls"] = { "stream": settings.CONTENT_URL + dubmap.get(content_lang) + "." + format, "stream_type": "{kind}/{format}".format(kind=content.get("kind", "").lower(), format=format), "thumbnail": thumbnail, } elif settings.BACKUP_VIDEO_SOURCE: content["available"] = True content["content_urls"] = { "stream": settings.BACKUP_VIDEO_SOURCE.format(youtube_id=dubbed_id, video_format=format), "stream_type": "{kind}/{format}".format(kind=content.get("kind", "").lower(), format=format), "thumbnail": settings.BACKUP_VIDEO_SOURCE.format(youtube_id=dubbed_id, video_format="png"), } else: content["available"] = False else: content["available"] = False else: content["available"] = False # Get list of subtitle language codes currently available subtitle_lang_codes = [] if not os.path.exists(i18n.get_srt_path()) else [lc for lc in os.listdir(i18n.get_srt_path()) if os.path.exists(i18n.get_srt_path(lc, content.get("id")))] # Generate subtitle URLs for any subtitles that do exist for this content item subtitle_urls = [{ "code": lc, "url": settings.STATIC_URL + "srt/{code}/subtitles/{id}.srt".format(code=lc, id=content.get("id")), "name": i18n.get_language_name(lc) } for lc in subtitle_lang_codes if os.path.exists(i18n.get_srt_path(lc, content.get("id")))] # Sort all subtitle URLs by language code content["subtitle_urls"] = sorted(subtitle_urls, key=lambda x: x.get("code", "")) with i18n.translate_block(content_lang): content["selected_language"] = content_lang content["title"] = _(content["title"]) content["description"] = _(content.get("description", "")) if content.get("description") else "" if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: with open(CONTENT_FILEPATH + "_" + language + ".cache", "w") as f: json.dump(CONTENT[language], f) except IOError as e: logging.warn("Annotated content cache file failed in saving with error {e}".format(e=e)) return CONTENT[language]
def get_exercise_cache(force=False, language=settings.LANGUAGE_CODE): global EXERCISES, EXERCISES_FILEPATH if EXERCISES is None: EXERCISES = {} if EXERCISES.get(language) is None: if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP and not force: exercises = softload_json(EXERCISES_FILEPATH + "_" + language + ".cache", logger=logging.debug, raises=False) if exercises: EXERCISES[language] = exercises return EXERCISES[language] EXERCISES[language] = softload_json(EXERCISES_FILEPATH, logger=logging.debug, raises=False) exercise_root = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises") if os.path.exists(exercise_root): exercise_templates = os.listdir(exercise_root) else: exercise_templates = [] assessmentitems = get_assessment_item_cache() TEMPLATE_FILE_PATH = os.path.join(settings.KHAN_EXERCISES_DIRPATH, "exercises", "%s") for exercise in EXERCISES[language].values(): exercise_file = exercise["name"] + ".html" exercise_template = exercise_file exercise_lang = "en" if exercise.get("uses_assessment_items", False): available = False items = [] for item in exercise.get("all_assessment_items","[]"): item = json.loads(item) if assessmentitems.get(item.get("id")): items.append(item) available = True exercise["all_assessment_items"] = items else: available = os.path.isfile(TEMPLATE_FILE_PATH % exercise_template) # Get the language codes for exercise templates that exist available_langs = set(["en"] + [lang_code for lang_code in exercise_templates if os.path.exists(os.path.join(exercise_root, lang_code, exercise_file))]) # Return the best available exercise template exercise_lang = i18n.select_best_available_language(language, available_codes=available_langs) if exercise_lang == "en": exercise_template = exercise_file else: exercise_template = os.path.join(exercise_lang, exercise_file) with i18n.translate_block(language): exercise["available"] = available exercise["lang"] = exercise_lang exercise["template"] = exercise_template exercise["title"] = _(exercise.get("title", "")) exercise["description"] = _(exercise.get("description", "")) if exercise.get("description") else "" if settings.DO_NOT_RELOAD_CONTENT_CACHE_AT_STARTUP: try: with open(EXERCISES_FILEPATH + "_" + language + ".cache", "w") as f: json.dump(EXERCISES[language], f) except IOError as e: logging.warn("Annotated exercise cache file failed in saving with error {e}".format(e=e)) return EXERCISES[language]