def construct_channel(self, *args, **kwargs): channel = self.get_channel(**kwargs) videos_topic = TopicNode(source_id="/wiki/Category:Articles_containing_video_clips", title="Articles containing video clips") channel.add_child(videos_topic) thumbnail_url = 'https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/A_Is_for_Atom_1953.webm/220px--A_Is_for_Atom_1953.webm.jpg' page = download_wikipedia_page('/wiki/Category:Articles_containing_video_clips', thumbnail_url, 'A Is for Atom') videos_topic.add_child(page) video_url = 'https://upload.wikimedia.org/wikipedia/commons/e/ee/A_Is_for_Atom_1953.webm' video_file = VideoFile(path=video_url) video_node = VideoNode(title='A Is for Atom 1953', source_id='A_Is_for_Atom_1953.webm', files=[video_file], license=licenses.PublicDomainLicense()) subtitle_url = 'https://commons.wikimedia.org/w/api.php?action=timedtext&title=File%3AA_Is_for_Atom_1953.webm&lang={}&trackformat=srt' subtitle_languages = [ 'en', 'es', ] for lang in subtitle_languages: subtitle_file = SubtitleFile(path=subtitle_url.format(lang), language=lang, subtitlesformat='srt') video_node.add_file(subtitle_file) videos_topic.add_child(video_node) return channel
def video_invalid_files(video_data, document_file): args_data = get_content_node_args(video_data) contentnode_kwargs = get_content_node_kwargs(video_data) contentnode_kwargs['files'] = [] # clear files becuse added one above video = VideoNode(*args_data, **contentnode_kwargs) video.add_file(document_file) return video
def make_video_node(title, video_url, video_language='en', ffmpeg_settings=None): """ Create a VideoNode from video_url. Assumes title is unique within containin topic. """ content_node = VideoNode(source_id=title, title=title, author='Sikana', description='', language=getlang(video_language).id, license=get_license( licenses.CC_BY_NC_ND, copyright_holder='Sikana Education'), thumbnail=None, derive_thumbnail=True, files=[ VideoFile( path=video_url, language=getlang(video_language).id, ffmpeg_settings=ffmpeg_settings, ) ]) return content_node
def vimeoNode(url): r = requests.get(url).text # grabs request of the URL #Get video title bs = bs4.BeautifulSoup(r, "html.parser") videoTitle = bs.find_all('title', limit=1) #videoTitle includes html tags, stripping them newTitle = str(re.sub('<.*?>', '', str(videoTitle))) #May have to delete if there are brackets in title newTitle = newTitle.replace("]", '') newTitle = newTitle.replace("[", '') #Create Video Node video_node = VideoNode( source_id=url, # set to url title=str(newTitle), license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), language=getlang('en').id, derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ WebVideoFile(web_url=url, language='en'), ]) #Return Video Node return video_node
def video(video_file, video_data, channel): args_data = get_content_node_args(video_data) contentnode_kwargs = get_content_node_kwargs(video_data) video = VideoNode(*args_data, **contentnode_kwargs) video.add_file(video_file) channel.add_child(video) video_data['files'].append(video_file) # save it so we can compare later return video
def test_invalid_mp4_fails(self, invalid_video_file): node = VideoNode('video-src-id', "Document", licenses.PUBLIC_DOMAIN, thumbnail=None) node.add_file(invalid_video_file) config.THUMBNAILS = True filenames = node.process_files()
def get_video_node(self, path, thumbnail=None): video_file = VideoFile(path, language='en') video_node = VideoNode('vid-src-id', "Video", licenses.PUBLIC_DOMAIN, thumbnail=thumbnail) video_node.add_file(video_file) return video_node
def get_video_node(url): wvf = WebVideoFile(url, high_resolution=False) info = youtube_info(url) # {id, title} node = VideoNode(source_id=info['id'], title=info['title'], license=CC_BY_NC_ND, copyright_holder="Mathplanet", files=[wvf]) return node, wvf.get_filename()
def test_generate_thumbnail_from_video(self, video_file): node = VideoNode('vid-src-id', "Video", licenses.PUBLIC_DOMAIN, thumbnail=None) node.add_file(video_file) config.THUMBNAILS = True filenames = node.process_files() assert len(filenames) == 2, 'expected two filenames' self.check_has_thumbnail(node)
def download_videos(topic, language): scraped_video_urls_path = os.path.join(DOWNLOADS_FOLDER, 'scraped_video_urls.json') with open(scraped_video_urls_path) as f: scraped_video_urls = json.load(f) video_urls_list = scraped_video_urls[language]['urls'] video_descriptions_list = scraped_video_urls[language]['descriptions'] nodes = [] for video_num, video_url in enumerate(video_urls_list): ydl_options = { 'outtmpl': f'downloads/videos/{video_num}_{language}.%(ext)s', # uses output templates, see documentation 'writethumbnail': False, 'no_warnings': True, 'continuedl': False, 'restrictfilenames': True, 'quiet': False, 'format': "bestvideo[height<=480][ext=mp4]+bestaudio[ext=m4a]/best[height<=480][ext=mp4]", # Note the format specification is important so we get mp4 and not taller than 480 } with youtube_dl.YoutubeDL(ydl_options) as ydl: try: ydl.add_default_info_extractors() vinfo = ydl.extract_info(video_url, download=True) except (youtube_dl.utils.DownloadError, youtube_dl.utils.ContentTooShortError, youtube_dl.utils.ExtractorError) as e: print('error_occured') ext_p1 = vinfo['requested_formats'][0]['format_id'] ext_p2 = vinfo['requested_formats'][0]['ext'] video_path = f'downloads/videos/{video_num}_{language}.f{ext_p1}.{ext_p2}' video_node = VideoNode( source_id=vinfo['webpage_url'], title=vinfo['title'], description=video_descriptions_list[video_num], # aggregator=LE, thumbnail=vinfo['thumbnail'], license=get_license('CC BY', copyright_holder='NC-SA 4.0'), # role=roles.COACH, files=[VideoFile(path=video_path, language=language)]) topic.add_child(video_node) return topic
def test_non_existent_mp4_fails(self): node = VideoNode('video-src-id', "Video", licenses.PUBLIC_DOMAIN, thumbnail=None) non_existent_path = 'does/not/exist.mp4' document_file = VideoFile(non_existent_path, language='en') node.add_file(document_file) config.THUMBNAILS = True filenames = node.process_files() assert filenames == [None], 'expected one None (the non existent mp4)' assert len(config.FAILED_FILES) == 1, 'expected one failed file'
def video_node(video, subtitle, data): if subtitle: files = [video, subtitle] else: files = [video] return VideoNode( source_id=data['link'], title=data['link'], license=licenses.CC_BY_NC_SA, copyright_holder="JFK Center for the Performing Arts", files=files, )
def test_multiple_subs_can_be_added(video_file): """ Baseline check to make sure we're not dropping subtitle files on validate. """ assert os.path.exists("tests/testcontent/testsubtitles_ar.srt") video_node = VideoNode('vid-src-id', "Video", licenses.PUBLIC_DOMAIN) video_node.add_file(video_file) sub1 = SubtitleFile("tests/testcontent/testsubtitles_ar.srt", language='en') video_node.add_file(sub1) sub2 = SubtitleFile("tests/testcontent/testsubtitles_ar.srt", language='ar') video_node.add_file(sub2) video_node.validate() sub_files = [f for f in video_node.files if isinstance(f, SubtitleFile)] assert len(sub_files) == 2, 'Missing subtitles files!'
def video_node(video, title): v = video.decode('utf-8') if v in done_nodes: return None done_nodes.append(v) files = [VideoFile(video.decode('utf-8'))] return VideoNode( source_id="video " + video.decode('utf-8'), title=title, license=LICENCE, copyright_holder="nashmi.net", files=files, )
def test_duplicate_language_codes_fixed_by_validate(video_file): """ Video nodes should have at most one subtitle file for a particular lang code. """ assert os.path.exists("tests/testcontent/testsubtitles_ar.srt") video_node = VideoNode('vid-src-id', "Video", licenses.PUBLIC_DOMAIN) video_node.add_file(video_file) sub1 = SubtitleFile("tests/testcontent/testsubtitles_ar.srt", language='ar') video_node.add_file(sub1) # now let's add file with a duplicate language code... sub2 = SubtitleFile("tests/testcontent/testsubtitles_ar.srt", language='ar') video_node.add_file(sub2) video_node.validate() sub_files = [f for f in video_node.files if isinstance(f, SubtitleFile)] assert len(sub_files) == 1, 'Duplicate subtitles files not removed!'
def include_video_topic(topic_node, video_data, lang_obj): # Include video details to the parent topic node video = video_data create_id = uuid.uuid4().hex[:12].lower() video_source_id = str( video.uid) # For YouTube imports, set source_id to the youtube_id video_node = VideoNode(source_id=video_source_id, title=clean_video_title(video.title, lang_obj), description=video.description, author=ARVIND, thumbnail=video.thumbnail, license=get_license("CC BY-NC", copyright_holder=ARVIND), files=[ YouTubeVideoFile(youtube_id=video.uid, language=video.language) ]) topic_node.add_child(video_node)
def videoAssignment(material): video_node = VideoNode( source_id=material["youtubeVideo"] ["id"], # usually set source_id to youtube_id title=material["youtubeVideo"]["title"], license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), language=getlang('en').id, derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ YouTubeVideoFile(youtube_id=material["youtubeVideo"]["id"], high_resolution=False, language='en'), YouTubeSubtitleFile(youtube_id=material["youtubeVideo"]["id"], language='en') ]) return video_node
def make_youtube_video(tubeid, name, _id): video_file = YouTubeVideoFile(youtube_id = tubeid, language=getlang('en').code, high_resolution=False) if video_file is None: print ("No video.") return None subtitle_file = YouTubeSubtitleFile(youtube_id = tubeid, language=getlang('en').code) if not isinstance(_id, str): print (_id, type(_id)) content_node = VideoNode( source_id= str(_id), title= name, #author='First Last (author\'s name)', #description='Put file description here', language=getlang('en').code, license=LICENCE, files=[video_file, subtitle_file], ) return content_node
def get_contents(parent, path): doc = get_page(path) try: menu_row = doc.find('div', {'id': 'row-exu'}) except Exception as e: LOGGER.error('get_contents: %s : %s' % (e, doc)) return for content in menu_row.find_all('div', {'class': 'col-md-3'}): try: title = content.find('div', {'class': 'txtline'}).get_text() thumbnail = content.find('a').find('img')['src'] thumbnail = get_absolute_path(thumbnail) main_file, master_file, source_id = get_content_link(content) LOGGER.info(' content: %s: %s' % (source_id, title)) if main_file.endswith('mp4'): video = VideoNode(title=title, source_id=source_id, license=licenses.PUBLIC_DOMAIN, thumbnail=thumbnail, files=[VideoFile(main_file)]) parent.add_child(video) elif main_file.endswith('pdf'): pdf = DocumentNode(title=title, source_id=source_id, license=licenses.PUBLIC_DOMAIN, thumbnail=thumbnail, files=[DocumentFile(main_file)]) parent.add_child(pdf) elif main_file.endswith('html') and master_file.endswith('zip'): zippath = get_zip_file(master_file, main_file) if zippath: html5app = HTML5AppNode( title=title, source_id=source_id, license=licenses.PUBLIC_DOMAIN, thumbnail=thumbnail, files=[HTMLZipFile(zippath)], ) parent.add_child(html5app) else: LOGGER.error('Content not supported: %s, %s' % (main_file, master_file)) except Exception as e: LOGGER.error('get_contents: %s : %s' % (e, content))
def include_video_topic(topic_node, video_data, lang_obj): # Include video details to the parent topic node video_id = video_data.uid video_source_id = 'arvind-video-{0}'.format(video_id) video_node = VideoNode(source_id=video_source_id, title=clean_video_title(video_data.title, lang_obj), description=video_data.description, author=ARVIND, thumbnail=video_data.thumbnail, license=get_license("CC BY-NC", copyright_holder=ARVIND), files=[ YouTubeVideoFile( youtube_id=video_id, language=video_data.language, high_resolution=False, ) ]) topic_node.add_child(video_node)
def build_burmese_video_topics(topic): """ """ video_data = download_videos(LANG_CODE_MY) if not video_data: print('==> Download of Videos FAILED!') return False for i, video in enumerate(video_data): filepath = video.filepath video_node = VideoNode( source_id=video.uid, title=video.title, description=video.description, aggregator=LE, thumbnail=video.thumbnail, license=get_license("CC BY-NC-SA", copyright_holder=POINTB), role=roles.COACH, files=[VideoFile(path=filepath, language=LANG_CODE_MY)]) topic.add_child(video_node) return topic
def youtubeNode(url): #Picking out youtube video ID from URL url_data = urlparse(url) query = urlparse.parse_qs(url_data.query) videoID = query["v"][0] r = requests.get(url).text # grabs request of the URL #Get video title bs = bs4.BeautifulSoup(r, "html.parser") videoTitle = bs.find_all('title', limit=1) #videoTitle includes html tags, stripping them newTitle = str(re.sub('<.*?>', '', str(videoTitle))) #May have to delete if there are brackets in title newTitle = newTitle.replace("]", '') newTitle = newTitle.replace("[", '') #Create Video Node video_node = VideoNode( source_id=videoID, # usually set source_id to youtube_id title=str(newTitle), license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), language=getlang('en').id, derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ YouTubeVideoFile(youtube_id=videoID, high_resolution=False, language='en'), YouTubeSubtitleFile(youtube_id=videoID, language='en') ]) #Return Video Node return video_node
def build_english_video_topics(topic): """ """ video_data = download_videos(LANG_CODE_EN) if not video_data: print('==> Download of Videos FAILED!') return False # NOTE(cpauya: VideoNode constructor has no argument for language code? for i, video in enumerate(video_data): filepath = video.filepath title = video.title.replace('(English Language)', '').strip() video_node = VideoNode( source_id=video.uid, title=title, description=video.description, aggregator=LE, thumbnail=video.thumbnail, license=get_license("CC BY-NC-SA", copyright_holder=POINTB), role=roles.COACH, files=[VideoFile(path=filepath, language=LANG_CODE_EN)]) topic.add_child(video_node) return topic
def add_lesson_video(self, lesson, url, title, course_title, module_title): LOGGER.info("Adding video for the course {}...".format(lesson.title)) # resp = downloader.make_request(url, cookies=self.cookies).content.decode("utf-8") file_path = "files/{}/{}/{}/{}-video.txt".format( course_title, module_title, lesson.title, title) with open(file_path, "r") as resp: page = BeautifulSoup(resp, "html.parser") video_id = page.find( "div", {"youtube-api": "lesson.youtubeApi"})["video-id"] source_id = "{}-video".format(lesson.source_id) video_file = YouTubeVideoFile(youtube_id=video_id, high_resolution=True, language=CHANNEL_LANGUAGE) video_node = VideoNode( source_id=source_id, title=title, license=CC_BY_NC_SALicense( copyright_holder="Google Garage Digital"), language=CHANNEL_LANGUAGE, files=[video_file], ) # Add subtitles for the video info = ydl.extract_info(video_id, download=False) subtitle_languages = info["subtitles"].keys() for lang_code in subtitle_languages: if is_youtube_subtitle_file_supported_language(lang_code): video_node.add_file( YouTubeSubtitleFile(youtube_id=video_id, language=lang_code)) else: LOGGER.info('Unsupported subtitle language code:', lang_code) lesson.add_child(video_node)
def construct_channel(self, *args, **kwargs): """ This method is reponsible for creating a `ChannelNode` object and populating it with `TopicNode` and `ContentNode` children. """ # Create channel ######################################################################## channel = self.get_channel(*args, **kwargs) # uses self.channel_info # Create topics to add to your channel ######################################################################## # Here we are creating a topic named 'Example Topic' exampletopic = TopicNode(source_id="topic-1", title="Example Topic") # TODO: Create your topic here # Now we are adding 'Example Topic' to our channel channel.add_child(exampletopic) # TODO: Add your topic to channel here # You can also add subtopics to topics # Here we are creating a subtopic named 'Example Subtopic' examplesubtopic = TopicNode(source_id="topic-1a", title="Example Subtopic") # TODO: Create your subtopic here # Now we are adding 'Example Subtopic' to our 'Example Topic' exampletopic.add_child(examplesubtopic) # TODO: Add your subtopic to your topic here # Content # You can add documents (pdfs and ePubs), videos, audios, and other content ######################################################################## # let's create a document file called 'Example PDF' document_file = DocumentFile( path="http://www.pdf995.com/samples/pdf.pdf") examplepdf = DocumentNode(title="Example PDF", source_id="example-pdf", files=[document_file], license=get_license(licenses.PUBLIC_DOMAIN)) # TODO: Create your pdf file here (use any url to a .pdf file) # We are also going to add a video file called 'Example Video' video_file = VideoFile( path= "https://ia600209.us.archive.org/27/items/RiceChef/Rice Chef.mp4") fancy_license = get_license( licenses.SPECIAL_PERMISSIONS, description='Special license for ricecooker fans only.', copyright_holder='The chef video makers') examplevideo = VideoNode(title="Example Video", source_id="example-video", files=[video_file], license=fancy_license) # TODO: Create your video file here (use any url to a .mp4 file) # Finally, we are creating an audio file called 'Example Audio' audio_file = AudioFile( path= "https://ia802508.us.archive.org/5/items/testmp3testfile/mpthreetest.mp3" ) exampleaudio = AudioNode(title="Example Audio", source_id="example-audio", files=[audio_file], license=get_license(licenses.PUBLIC_DOMAIN)) # TODO: Create your audio file here (use any url to a .mp3 file) # Now that we have our files, let's add them to our channel channel.add_child(examplepdf) # Adding 'Example PDF' to your channel exampletopic.add_child( examplevideo) # Adding 'Example Video' to 'Example Topic' examplesubtopic.add_child( exampleaudio) # Adding 'Example Audio' to 'Example Subtopic' # TODO: Add your pdf file to your channel # TODO: Add your video file to your topic # TODO: Add your audio file to your subtopic # the `construct_channel` method returns a ChannelNode that will be # processed by the ricecooker framework return channel
def create_node(node, assessment_dict, subtitle_path, vtt_videos, base_path, lite_version, lang_code): kind = node.get('kind') # Exercise node creation if kind == 'Exercise': child_node = ExerciseNode( source_id=node['id'], title=node['title'], exercise_data={ 'mastery_model': node.get('suggested_completion_criteria') }, description='' if node.get("description") is None else node.get( "description", '')[:400], license=licenses.ALL_RIGHTS_RESERVED, thumbnail=node.get('image_url_256'), ) # build exercise urls for previews full_path = base_path + node.get('path').strip('khan') slug = full_path.split('/')[-2] full_path = full_path.replace(slug, 'e') + slug # attach Perseus questions to Exercises for item in node['all_assessment_items']: # we replace all references to assessment images with the local file path to the image for match in re.finditer(FILE_URL_REGEX, assessment_dict[item['id']]["item_data"]): file_path = str(match.group(0)).replace('\\', '') file_path = file_path.replace(REPLACE_STRING, IMAGE_DL_LOCATION) assessment_dict[item['id']]["item_data"] = re.sub( FILE_URL_REGEX, file_path, assessment_dict[item['id']]["item_data"], 1) question = PerseusQuestion( id=item['id'], raw_data=assessment_dict[item['id']]['item_data'], source_url=full_path if not lite_version else None, ) child_node.add_question(question) # Topic node creation elif kind == 'Topic': child_node = TopicNode( source_id=node["id"], title=node["title"], description='' if node.get("description") is None else node.get( "description", '')[:400]) # Video node creation elif kind == 'Video': # standard download url for KA videos download_url = "https://cdn.kastatic.org/KA-youtube-converted/{0}.mp4/{1}.mp4".format( node['youtube_id'], node['youtube_id']) files = [VideoFile(download_url)] if node['youtube_id'] in vtt_videos: files.append( SubtitleFile(subtitle_path + '/{}.vtt'.format(node['youtube_id']), language=getlang(lang_code))) child_node = VideoNode( source_id=node["id"], title=node["title"], description='' if node.get("description") is None else node.get( "description", '')[:400], files=files, thumbnail=node.get('image_url'), license=licenses.CC_BY_NC_SA) else: # unknown content file format return None return child_node
def download_sim(self, topic, sim, keywords, language): """ Download, zip, and add a node for a sim, as well as any associated video. """ localized_sim = sim["localizedSimulations"][0] print("\tProcessing sim:", localized_sim["title"]) dst = tempfile.mkdtemp() download_file( localized_sim["downloadUrl"], dst, filename="index.html", request_fn=sess.get, middleware_callbacks=[process_sim_html], ) zippath = create_predictable_zip(dst) authors = re.sub(" \(.*?\)", "", sim["credits"]["designTeam"]) authors = re.sub("<br\/?>", ", ", authors) title = localized_sim["title"] if language == "ar": if title in ARABIC_NAME_CATEGORY: title = ARABIC_NAME_CATEGORY[title] if title in SIM_TYPO: title = SIM_TYPO[title] # create a node for the sim simnode = HTML5AppNode( source_id="sim-%d" % localized_sim["id"], files=[HTMLZipFile(zippath)], title=title, description=sim["description"][language][:200], license=CC_BYLicense( "PhET Interactive Simulations, University of Colorado Boulder" ), # author=authors, # tags=[keywords[topic] for topic in sim["topicIds"]], thumbnail=sim["media"]["thumbnailUrl"], language=getlang(language), ) # if there's a video, extract it and put it in the topic right before the sim videos = sim["media"]["vimeoFiles"] if videos: video_url = [v for v in videos if v.get("height") == 540][0]["link"] videonode = VideoNode( source_id="video-%d" % localized_sim["id"], files=[VideoFile(video_url)], title="Video: %s" % localized_sim["title"], license=CC_BYLicense( "PhET Interactive Simulations, University of Colorado Boulder" ), thumbnail=sim["media"]["thumbnailUrl"], ) topic.add_child(videonode) # add the sim node into the topic topic.add_child(simnode)
def create_content_nodes(self, channel): """ This function uses the methods `add_child` and `add_file` to build the hierarchy of topic nodes (nested folder structure) and content nodes. Every content node is associated with one or more files. """ content_nodes_folder = TopicNode( source_id='uniqid001', title='Content Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) channel.add_child(content_nodes_folder) # AUDIO audio_nodes_folder = TopicNode( source_id='uniqid002', title='Audio Files Folder', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(audio_nodes_folder) audio_node = AudioNode( source_id='uniqid003', title='Whale sounds', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail=None, files=[], ) audio_nodes_folder.add_child(audio_node) audio_file = AudioFile( path= './content/ricecooker-channel-files/Whale_sounds.mp3', # note path can also be a URL language=getlang('en').id) audio_node.add_file(audio_file) # DOCUMENTS documents_folder = TopicNode( source_id='uniqid004', title='Document Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(documents_folder) document_node = DocumentNode( source_id='uniqid005', title= 'The Supreme Court\u2019s Ruling in Brown vs. Board of Education', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail=None, files=[ DocumentFile( path= './content/ricecooker-channel-files/brown-vs-board-of-education.pdf', language=getlang('en').id) ]) documents_folder.add_child(document_node) # HTML5 APPS html5apps_folder = TopicNode( source_id='uniqid006', title='HTML5App Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(html5apps_folder) html5_node = HTML5AppNode( source_id='uniqid007', title='HTMLWeb capabilities test', author='First Last (author\'s name)', description= 'Tests different HTML/JS capabilities. What capabilities are allowed and disallowed by the sandboxed iframe used to render HTML5App nodes on Kolibri.', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail='./content/ricecooker-channel-files/html5_tests.jpg', files=[ HTMLZipFile( path='./content/ricecooker-channel-files/html5_tests.zip', language=getlang('en').id) ]) html5apps_folder.add_child(html5_node) html5_node2 = HTML5AppNode( source_id='uniqid008', title='Sample Vue.js app', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail='./content/ricecooker-channel-files/html5_vuejs.jpg', files=[ HTMLZipFile( path='./content/ricecooker-channel-files/html5_vuejs.zip', language=getlang('en').id) ]) html5apps_folder.add_child(html5_node2) # VIDEOS videos_folder = TopicNode( source_id='uniqid009', title='Video Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(videos_folder) video_node = VideoNode( source_id='uniqid010', title='Wave particle duality explained in 2 mins', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ VideoFile( path= './content/ricecooker-channel-files/Wave_particle_duality.mp4', language=getlang('en').id) ]) videos_folder.add_child(video_node) youtube_id = 'VJyk81HmcZQ' video_node2 = VideoNode( source_id=youtube_id, # usually set source_id to youtube_id title='Estimating division that results in non whole numbers', author='Sal Khan', description='Video description would go here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Khan Academy'), derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ YouTubeVideoFile(youtube_id=youtube_id, high_resolution=False, language='en'), YouTubeSubtitleFile(youtube_id=youtube_id, language='ko') ]) videos_folder.add_child(video_node2)
def create_content_nodes(self, channel): """ This function uses the methods `add_child` and `add_file` to build the hierarchy of topic nodes and content nodes. Every content node is associated with the underlying file node. """ content_nodes_folder = TopicNode( source_id='121232ms', title='Content Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) channel.add_child(content_nodes_folder) # AUDIO audio_nodes_folder = TopicNode( source_id='138iuh23iu', title='Audio Files', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(audio_nodes_folder) audio_node = AudioNode( source_id='940ac8ff', title='Whale sounds', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail=None, files=[], ) audio_nodes_folder.add_child(audio_node) audio_file = AudioFile( path='./content/ricecooker-channel-files/Whale_sounds.mp3', language=getlang('en').id) audio_node.add_file(audio_file) # DOCUMENTS documents_folder = TopicNode( source_id='asanlksnaklsn', title='Document Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(documents_folder) document_node = DocumentNode( source_id='80b7136f', title= 'The Supreme Court\u2019s Ruling in Brown vs. Board of Education', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail=None, files=[ DocumentFile( path= './content/ricecooker-channel-files/commonlit_the-supreme-court-s-ruling-in-brown-vs-board-of-education_student.pdf', language=getlang('en').id) ]) documents_folder.add_child(document_node) # HTML5 APPS html5apps_folder = TopicNode( source_id='asasa331', title='HTML5App Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(html5apps_folder) html5_node_a = HTML5AppNode( source_id='302723b4', title='Sample React app', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail='./content/ricecooker-channel-files/html5_react.jpg', files=[ HTMLZipFile( path='./content/ricecooker-channel-files/html5_react.zip', language=getlang('en').id) ]) html5apps_folder.add_child(html5_node_a) html5_node_b = HTML5AppNode( source_id='3f91184e', title='Sample Vue.js app', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail='./content/ricecooker-channel-files/html5_vuejs.jpg', files=[ HTMLZipFile( path='./content/ricecooker-channel-files/html5_vuejs.zip', language=getlang('en').id) ]) html5apps_folder.add_child(html5_node_b) html5_node_c = HTML5AppNode( source_id='0aec4296', title='Sample wget-scraped web content', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), thumbnail= './content/ricecooker-channel-files/html5_wget_scraped.jpg', files=[ HTMLZipFile( path= './content/ricecooker-channel-files/html5_wget_scraped.zip', language=getlang('en').id) ]) html5apps_folder.add_child(html5_node_c) # VIDEOS videos_folder = TopicNode( source_id='121213m3m3', title='Video Nodes', description='Put folder description here', author=None, language=getlang('en').id, thumbnail=None, ) content_nodes_folder.add_child(videos_folder) video_node = VideoNode( source_id='9e355995', title='Wave particle duality explained in 2 mins', author='First Last (author\'s name)', description='Put file description here', language=getlang('en').id, license=get_license(licenses.CC_BY, copyright_holder='Copyright holder name'), derive_thumbnail=True, # video-specicig flag thumbnail=None, files=[ VideoFile( path= './content/ricecooker-channel-files/Wave_particle_duality.mp4', language=getlang('en').id) ]) videos_folder.add_child(video_node)
def build_tree(parent_node,root_folder): #check ini file if not os.path.exists(os.path.join(root_folder,'metadata.ini')): raise FileNotFoundException("Missing 'metadata.ini' configuration file in {0}".format([root_folder])) content_config = ini_to_json(os.path.join(root_folder,'metadata.ini')) #loop directory for file in os.listdir(root_folder): # separate file name from ext file_name, ext = parse_file_name(file) #check to see is file exists in metadata.ini file if not content_config.get( file_name ): if ext != 'ini': warnings.warn("File {} has no configuration in {}... SKIPPED".format(file,os.path.join(root_folder,'metadata.ini'))) #if file is a directory, create TOPIC node and step into dir elif os.path.isdir(os.path.join(root_folder,file)) and file != '.' and file != '..': topic = TopicNode( source_id = content_config[file_name]["__name__"], title = content_config[file_name]["title"], author = content_config[file_name].get("author"), description = content_config[file_name].get("description"), thumbnail = content_config[file_name].get("thumbnail"), ) parent_node.add_child(topic) build_tree(topic,os.path.join(root_folder,file)) elif ext == "mp4": #in VIDEO: child = VideoNode( source_id = content_config[file_name]["__name__"], title = content_config[file_name]["title"], license = content_config[file_name].get("license"), author = content_config[file_name].get("author"), description = content_config[file_name].get("description"), derive_thumbnail= True, # video-specific data thumbnail = content_config[file_name].get("thumbnail"), ) add_files(child, [os.path.join(root_folder,file)] + (content_config[file_name].get("files") or [])) parent_node.add_child(child) elif ext == "mp3": #in AUDIO: child = AudioNode( source_id = content_config[file_name]["__name__"], title = content_config[file_name]["title"], license = content_config[file_name].get("license"), author = content_config[file_name].get("author"), description = content_config[file_name].get("description"), thumbnail = content_config[file_name].get("thumbnail"), ) add_files(child, [os.path.join(root_folder,file)] + (content_config[file_name].get("files") or [])) parent_node.add_child(child) elif ext == "pdf": #in DOCUMENT: child = DocumentNode( source_id = content_config[file_name]["__name__"], title = content_config[file_name]["title"], license = content_config[file_name].get("license"), author = content_config[file_name].get("author"), description = content_config[file_name].get("description"), thumbnail = content_config[file_name].get("thumbnail"), ) add_files(child, [os.path.join(root_folder,file)] + (content_config[file_name].get("files") or [])) parent_node.add_child(child) else: continue