diff --git a/cms/djangoapps/contentstore/video_storage_handlers.py b/cms/djangoapps/contentstore/video_storage_handlers.py
index b84d7f0f7c31..6827b295b0a8 100644
--- a/cms/djangoapps/contentstore/video_storage_handlers.py
+++ b/cms/djangoapps/contentstore/video_storage_handlers.py
@@ -42,6 +42,7 @@
update_video_status
)
from fs.osfs import OSFS
+from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from path import Path as path
from pytz import UTC
@@ -960,3 +961,32 @@ def _update_pagination_context(request):
request.session['VIDEOS_PER_PAGE'] = videos_per_page
return JsonResponse()
+
+
+def get_course_youtube_edx_video_ids(course_id):
+ """
+ Get a list of youtube edx_video_ids
+ """
+ error_msg = "Invalid course_key: '%s'." % course_id
+ try:
+ course_key = CourseKey.from_string(course_id)
+ course = modulestore().get_course(course_key)
+ except InvalidKeyError:
+ return JsonResponse({'error': error_msg}, status=500)
+ blocks = []
+ block_yt_field = 'youtube_id_1_0'
+ block_edx_id_field = 'edx_video_id'
+ if hasattr(course, 'get_children'):
+ for section in course.get_children():
+ for subsection in section.get_children():
+ for vertical in subsection.get_children():
+ for block in vertical.get_children():
+ blocks.append(block)
+
+ edx_video_ids = []
+ for block in blocks:
+ if hasattr(block, block_yt_field) and getattr(block, block_yt_field):
+ if getattr(block, block_edx_id_field):
+ edx_video_ids.append(getattr(block, block_edx_id_field))
+
+ return JsonResponse({'edx_video_ids': edx_video_ids}, status=200)
diff --git a/cms/djangoapps/contentstore/views/tests/test_videos.py b/cms/djangoapps/contentstore/views/tests/test_videos.py
index 5d96e6797d9d..2d17229f59c1 100644
--- a/cms/djangoapps/contentstore/views/tests/test_videos.py
+++ b/cms/djangoapps/contentstore/views/tests/test_videos.py
@@ -12,6 +12,7 @@
from unittest.mock import Mock, patch
import dateutil.parser
+from common.djangoapps.student.tests.factories import UserFactory
import ddt
import pytz
from django.test import TestCase
@@ -37,6 +38,8 @@
ENABLE_DEVSTACK_VIDEO_UPLOADS,
)
from openedx.core.djangoapps.waffle_utils.models import WaffleFlagCourseOverrideModel
+from xmodule.modulestore.django import modulestore
+from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
from ..videos import (
@@ -1662,3 +1665,82 @@ def test_storage_bucket(self):
self.assertIn("https://vem_test_bucket.s3.amazonaws.com:443/test_root/", upload_url)
self.assertIn(edx_video_id, upload_url)
+
+
+class CourseYoutubeEdxVideoIds(ModuleStoreTestCase):
+ """
+ This test checks youtube videos in a course
+ """
+ VIEW_NAME = 'youtube_edx_video_ids'
+
+ def setUp(self):
+ super().setUp()
+ self.course = CourseFactory.create()
+ self.course_with_no_youtube_videos = CourseFactory.create()
+ self.store = modulestore()
+ self.user = UserFactory()
+ self.client.login(username=self.user.username, password='Password1234')
+
+ def get_url_for_course_key(self, course_key, kwargs=None):
+ """Return video handler URL for the given course"""
+ return reverse_course_url(self.VIEW_NAME, course_key, kwargs) # lint-amnesty, pylint: disable=no-member
+
+ def test_course_with_youtube_videos(self):
+ course_key = self.course.id
+
+ with self.store.bulk_operations(course_key):
+ chapter_loc = self.store.create_child(
+ self.user.id, self.course.location, 'chapter', 'test_chapter'
+ ).location
+ seq_loc = self.store.create_child(
+ self.user.id, chapter_loc, 'sequential', 'test_seq'
+ ).location
+ vert_loc = self.store.create_child(self.user.id, seq_loc, 'vertical', 'test_vert').location
+ self.store.create_child(
+ self.user.id,
+ vert_loc,
+ 'problem',
+ 'test_problem',
+ fields={"data": "Test"}
+ )
+ self.store.create_child(
+ self.user.id, vert_loc, 'video', fields={
+ "youtube_is_available": False,
+ "name": "sample_video",
+ "edx_video_id": "youtube_193_84709099",
+ }
+ )
+
+ response = self.client.get(self.get_url_for_course_key(course_key))
+ self.assertEqual(response.status_code, 200)
+
+ edx_video_ids = json.loads(response.content.decode('utf-8'))['edx_video_ids']
+ self.assertEqual(len(edx_video_ids), 1)
+
+ def test_course_with_no_youtube_videos(self):
+ course_key = self.course_with_no_youtube_videos.id
+
+ with self.store.bulk_operations(course_key):
+ chapter_loc = self.store.create_child(
+ self.user.id, self.course_with_no_youtube_videos.location, 'chapter', 'test_chapter'
+ ).location
+ seq_loc = self.store.create_child(
+ self.user.id, chapter_loc, 'sequential', 'test_seq'
+ ).location
+ vert_loc = self.store.create_child(self.user.id, seq_loc, 'vertical', 'test_vert').location
+ self.store.create_child(
+ self.user.id, vert_loc, 'problem', 'test_problem', fields={"data": "Test"}
+ )
+ self.store.create_child(
+ self.user.id, vert_loc, 'video', fields={
+ "youtube_id_1_0": None,
+ "name": "sample_video",
+ "edx_video_id": "no_youtube_193_84709099",
+ }
+ )
+
+ response = self.client.get(self.get_url_for_course_key(course_key))
+
+ edx_video_ids = json.loads(response.content.decode('utf-8'))['edx_video_ids']
+ self.assertEqual(response.status_code, 200)
+ self.assertEqual(len(edx_video_ids), 0)
diff --git a/cms/djangoapps/contentstore/views/videos.py b/cms/djangoapps/contentstore/views/videos.py
index e1bdfa1cde1c..2eac141b9c9e 100644
--- a/cms/djangoapps/contentstore/views/videos.py
+++ b/cms/djangoapps/contentstore/views/videos.py
@@ -27,6 +27,7 @@
storage_service_key as storage_service_key_source_function,
send_video_status_update as send_video_status_update_source_function,
is_status_update_request as is_status_update_request_source_function,
+ get_course_youtube_edx_video_ids,
)
from common.djangoapps.util.json_request import expect_json
@@ -41,6 +42,7 @@
'get_video_features',
'transcript_preferences_handler',
'generate_video_upload_link_handler',
+ 'get_course_youtube_edx_videos_ids',
]
LOGGER = logging.getLogger(__name__)
@@ -236,3 +238,18 @@ def is_status_update_request(request_data):
Exposes helper method without breaking existing bindings/dependencies
"""
return is_status_update_request_source_function(request_data)
+
+
+@api_view(['GET'])
+@view_auth_classes()
+@require_GET
+def get_course_youtube_edx_videos_ids(request, course_key_string):
+ """
+ Get an object containing course videos.
+ **Example Request**
+ GET /api/contentstore/v1/videos/youtube_ids{course_id}
+ **Response Values**
+ If the request is successful, an HTTP 200 "OK" response is returned.
+ The HTTP 200 response contains a list of youtube edx_video_ids for a given course.
+ """
+ return get_course_youtube_edx_video_ids(course_key_string)
diff --git a/cms/urls.py b/cms/urls.py
index e21d07083eea..1c5f191b2728 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -194,6 +194,8 @@
path('api/val/v0/', include('edxval.urls')),
path('api/tasks/v0/', include('user_tasks.urls')),
path('accessibility', contentstore_views.accessibility, name='accessibility'),
+ re_path(fr'api/youtube/courses/{COURSELIKE_KEY_PATTERN}/edx-video-ids$',
+ contentstore_views.get_course_youtube_edx_videos_ids, name='youtube_edx_video_ids'),
]
if not settings.DISABLE_DEPRECATED_SIGNIN_URL: