Removed video url import from youtube, which is not needed any more given the /api/meeting/session/video/url API endpoint. This also prevents duplicate video URLs.
- Legacy-Id: 15424
This commit is contained in:
parent
caa3ec98b4
commit
fcbbe08eba
|
@ -35,8 +35,7 @@ class CustomApiTestCase(TestCase):
|
||||||
# Using mock to patch the import functions in ietf.meeting.views, where
|
# Using mock to patch the import functions in ietf.meeting.views, where
|
||||||
# api_import_recordings() are using them:
|
# api_import_recordings() are using them:
|
||||||
@patch('ietf.meeting.views.import_audio_files')
|
@patch('ietf.meeting.views.import_audio_files')
|
||||||
@patch('ietf.meeting.views.import_youtube_video_urls')
|
def test_notify_meeting_import_audio_files(self, mock_import_audio):
|
||||||
def test_notify_meeting_import_audio_files(self, mock_import_youtube, mock_import_audio):
|
|
||||||
meeting = make_meeting_test_data()
|
meeting = make_meeting_test_data()
|
||||||
client = Client(Accept='application/json')
|
client = Client(Accept='application/json')
|
||||||
# try invalid method GET
|
# try invalid method GET
|
||||||
|
|
|
@ -61,7 +61,7 @@ from ietf.meeting.helpers import send_interim_announcement_request
|
||||||
from ietf.meeting.utils import finalize
|
from ietf.meeting.utils import finalize
|
||||||
from ietf.secr.proceedings.utils import handle_upload_file
|
from ietf.secr.proceedings.utils import handle_upload_file
|
||||||
from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files,
|
from ietf.secr.proceedings.proc_utils import (get_progress_stats, post_process, import_audio_files,
|
||||||
import_youtube_video_urls, create_recording)
|
create_recording)
|
||||||
from ietf.utils.decorators import require_api_key
|
from ietf.utils.decorators import require_api_key
|
||||||
from ietf.utils.mail import send_mail_message, send_mail_text
|
from ietf.utils.mail import send_mail_message, send_mail_text
|
||||||
from ietf.utils.pipe import pipe
|
from ietf.utils.pipe import pipe
|
||||||
|
@ -2183,7 +2183,6 @@ def api_import_recordings(request, number):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
meeting = get_meeting(number)
|
meeting = get_meeting(number)
|
||||||
import_audio_files(meeting)
|
import_audio_files(meeting)
|
||||||
import_youtube_video_urls(meeting)
|
|
||||||
return HttpResponse(status=201)
|
return HttpResponse(status=201)
|
||||||
else:
|
else:
|
||||||
return HttpResponse(status=405)
|
return HttpResponse(status=405)
|
||||||
|
|
|
@ -4,7 +4,6 @@ proc_utils.py
|
||||||
This module contains all the functions for generating static proceedings pages
|
This module contains all the functions for generating static proceedings pages
|
||||||
'''
|
'''
|
||||||
import datetime
|
import datetime
|
||||||
import httplib2
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -12,7 +11,6 @@ from urllib import urlencode
|
||||||
|
|
||||||
import debug # pyflakes:ignore
|
import debug # pyflakes:ignore
|
||||||
|
|
||||||
from apiclient.discovery import build
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
|
@ -27,52 +25,6 @@ AUDIO_FILE_RE = re.compile(r'ietf(?P<number>[\d]+)-(?P<room>.*)-(?P<time>[\d]{8}
|
||||||
VIDEO_TITLE_RE = re.compile(r'IETF(?P<number>[\d]+)-(?P<name>.*)-(?P<date>\d{8})-(?P<time>\d{4})')
|
VIDEO_TITLE_RE = re.compile(r'IETF(?P<number>[\d]+)-(?P<name>.*)-(?P<date>\d{8})-(?P<time>\d{4})')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def import_youtube_video_urls(meeting, http=httplib2.Http()):
|
|
||||||
'''Create Document and set external_url for session videos'''
|
|
||||||
youtube = build(settings.YOUTUBE_API_SERVICE_NAME, settings.YOUTUBE_API_VERSION,
|
|
||||||
developerKey=settings.YOUTUBE_API_KEY, http=http)
|
|
||||||
playlistid = get_youtube_playlistid(youtube, 'IETF' + meeting.number)
|
|
||||||
if playlistid is None:
|
|
||||||
return None
|
|
||||||
for video in get_youtube_videos(youtube, playlistid):
|
|
||||||
match = VIDEO_TITLE_RE.match(video['title'])
|
|
||||||
if match:
|
|
||||||
session = _get_session(**match.groupdict())
|
|
||||||
if session:
|
|
||||||
url = video['url']
|
|
||||||
get_or_create_recording_document(url,session)
|
|
||||||
|
|
||||||
def get_youtube_playlistid(youtube, title, http=httplib2.Http()):
|
|
||||||
'''Returns the youtube playlistId matching title string, a string'''
|
|
||||||
request = youtube.search().list(
|
|
||||||
q=title,
|
|
||||||
part='id,snippet',
|
|
||||||
channelId=settings.YOUTUBE_IETF_CHANNEL_ID,
|
|
||||||
type='playlist',
|
|
||||||
maxResults=1
|
|
||||||
)
|
|
||||||
search_response = request.execute(http=http)
|
|
||||||
|
|
||||||
try:
|
|
||||||
playlistid = search_response['items'][0]['id']['playlistId']
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
return None
|
|
||||||
return playlistid
|
|
||||||
|
|
||||||
def get_youtube_videos(youtube, playlistid, http=httplib2.Http()):
|
|
||||||
'''Returns list of dictionaries with title, urls keys'''
|
|
||||||
videos = []
|
|
||||||
kwargs = dict(part="snippet",playlistId=playlistid,maxResults=50)
|
|
||||||
playlistitems = youtube.playlistItems()
|
|
||||||
request = playlistitems.list(**kwargs)
|
|
||||||
# handle pagination
|
|
||||||
while request is not None:
|
|
||||||
playlistitems_doc = request.execute(http=http)
|
|
||||||
videos.extend(_get_urls_from_json(playlistitems_doc))
|
|
||||||
request = playlistitems.list_next(request, playlistitems_doc)
|
|
||||||
return videos
|
|
||||||
|
|
||||||
def _get_session(number,name,date,time):
|
def _get_session(number,name,date,time):
|
||||||
'''Lookup session using data from video title'''
|
'''Lookup session using data from video title'''
|
||||||
meeting = Meeting.objects.get(number=number)
|
meeting = Meeting.objects.get(number=number)
|
||||||
|
|
|
@ -2,9 +2,6 @@ import debug # pyflakes:ignore
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
from apiclient.discovery import build
|
|
||||||
from apiclient.http import HttpMock
|
|
||||||
from mock import patch
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
@ -21,7 +18,6 @@ from ietf.utils.mail import outbox
|
||||||
from ietf.secr.proceedings.proc_utils import (import_audio_files,
|
from ietf.secr.proceedings.proc_utils import (import_audio_files,
|
||||||
get_timeslot_for_filename, normalize_room_name, send_audio_import_warning,
|
get_timeslot_for_filename, normalize_room_name, send_audio_import_warning,
|
||||||
get_or_create_recording_document, create_recording, get_next_sequence,
|
get_or_create_recording_document, create_recording, get_next_sequence,
|
||||||
get_youtube_playlistid, get_youtube_videos, import_youtube_video_urls,
|
|
||||||
_get_session, _get_urls_from_json)
|
_get_session, _get_urls_from_json)
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,47 +39,6 @@ class ProceedingsTestCase(TestCase):
|
||||||
|
|
||||||
|
|
||||||
class VideoRecordingTestCase(TestCase):
|
class VideoRecordingTestCase(TestCase):
|
||||||
@patch('ietf.secr.proceedings.proc_utils.get_youtube_videos')
|
|
||||||
@patch('ietf.secr.proceedings.proc_utils.get_youtube_playlistid')
|
|
||||||
def test_import_youtube_video_urls(self, mock_playlistid, mock_videos):
|
|
||||||
meeting = make_meeting_test_data()
|
|
||||||
session = Session.objects.filter(meeting=meeting, group__acronym='mars').first()
|
|
||||||
title = self._get_video_title_for_session(session)
|
|
||||||
url = 'https://youtube.com?v=test'
|
|
||||||
mock_playlistid.return_value = 'PLC86T-6ZTP5g87jdxNqdWV5475U-yEE8M'
|
|
||||||
mock_videos.return_value = [{'title':title,'url':url}]
|
|
||||||
discovery = os.path.join(settings.BASE_DIR, "../test/data/youtube-discovery.json")
|
|
||||||
http = HttpMock(discovery, {'status': '200'})
|
|
||||||
import_youtube_video_urls(meeting=meeting, http=http)
|
|
||||||
doc = Document.objects.get(external_url=url)
|
|
||||||
self.assertTrue(doc in session.materials.all())
|
|
||||||
|
|
||||||
def _get_video_title_for_session(self, session):
|
|
||||||
'''Returns the youtube video title of a session recording given session'''
|
|
||||||
timeslot = session.official_timeslotassignment().timeslot
|
|
||||||
return "{prefix}-{group}-{date}".format(
|
|
||||||
prefix=session.meeting.type.slug + session.meeting.number,
|
|
||||||
group=session.group.acronym,
|
|
||||||
date=timeslot.time.strftime('%Y%m%d-%H%M')).upper()
|
|
||||||
|
|
||||||
def test_get_youtube_playlistid(self):
|
|
||||||
discovery = os.path.join(settings.BASE_DIR, "../test/data/youtube-discovery.json")
|
|
||||||
http = HttpMock(discovery, {'status': '200'})
|
|
||||||
youtube = build(settings.YOUTUBE_API_SERVICE_NAME, settings.YOUTUBE_API_VERSION,
|
|
||||||
developerKey='',http=http)
|
|
||||||
path = os.path.join(settings.BASE_DIR, "../test/data/youtube-playlistid.json")
|
|
||||||
http = HttpMock(path, {'status': '200'})
|
|
||||||
self.assertEqual(get_youtube_playlistid(youtube, 'IETF98', http=http),'PLC86T-test')
|
|
||||||
|
|
||||||
def test_get_youtube_videos(self):
|
|
||||||
discovery = os.path.join(settings.BASE_DIR, "../test/data/youtube-discovery.json")
|
|
||||||
http = HttpMock(discovery, {'status': '200'})
|
|
||||||
youtube = build(settings.YOUTUBE_API_SERVICE_NAME, settings.YOUTUBE_API_VERSION,
|
|
||||||
developerKey='',http=http)
|
|
||||||
path = os.path.join(settings.BASE_DIR, "../test/data/youtube-playlistitems.json")
|
|
||||||
http = HttpMock(path, {'status': '200'})
|
|
||||||
videos = get_youtube_videos(youtube, 'PLC86T', http=http)
|
|
||||||
self.assertEqual(len(videos),2)
|
|
||||||
|
|
||||||
def test_get_session(self):
|
def test_get_session(self):
|
||||||
meeting = make_meeting_test_data()
|
meeting = make_meeting_test_data()
|
||||||
|
|
Loading…
Reference in a new issue