From 0a10e7d202803264495132e0c66eda8f4a48c166 Mon Sep 17 00:00:00 2001 From: angcast Date: Fri, 1 Oct 2021 16:11:12 -0400 Subject: [PATCH 1/7] Added short video clips file to backend --- backend/app/analysis/short_video_clips.py | 4 ++++ frontend/package-lock.json | 27 +++++++++++++++++++++++ frontend/package.json | 3 ++- frontend/scripts/start.js | 12 ++++++++++ frontend/src/testingAPI.js | 11 +++++++++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 backend/app/analysis/short_video_clips.py create mode 100644 frontend/src/testingAPI.js diff --git a/backend/app/analysis/short_video_clips.py b/backend/app/analysis/short_video_clips.py new file mode 100644 index 0000000..0c5a6f4 --- /dev/null +++ b/backend/app/analysis/short_video_clips.py @@ -0,0 +1,4 @@ +""" +Helper functions used to get information of videos from Youtube URLs such as its +transcript and title +""" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 47dc9e6..673dc10 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12722,6 +12722,11 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "striptags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/striptags/-/striptags-3.2.0.tgz", + "integrity": "sha512-g45ZOGzHDMe2bdYMdIvdAfCQkCTDMGBazSw1ypMowwGIee7ZQ5dU0rBJ8Jqgl+jAKIv4dbeE1jscZq9wid1Tkw==" + }, "style-loader": { "version": "0.23.1", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", @@ -14207,6 +14212,28 @@ "camelcase": "^5.0.0", "decamelize": "^1.2.0" } + }, + "youtube-captions-scraper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/youtube-captions-scraper/-/youtube-captions-scraper-1.0.3.tgz", + "integrity": "sha512-mQeNIHPY9iBsCcoUgCRV/5eEv9eJQhWxl2Wc8W/qBZIiw/6AlcRXbuldJvwKjF4SqDmkBxoxuGlBsOcMJYhLbg==", + "requires": { + "axios": "^0.17.1", + "he": "^1.1.1", + "lodash": "^4.17.4", + "striptags": "^3.1.0" + }, + "dependencies": { + "axios": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.17.1.tgz", + "integrity": "sha1-LY4+XQvb1zJ/kbyBT1xXZg+Bgk0=", + "requires": { + "follow-redirects": "^1.2.5", + "is-buffer": "^1.1.5" + } + } + } } } } diff --git a/frontend/package.json b/frontend/package.json index 54f2193..4cca06f 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -64,7 +64,8 @@ "webpack-bundle-tracker": "^0.4.2-beta", "webpack-dev-server": "^3.11.0", "webpack-manifest-plugin": "2.0.4", - "workbox-webpack-plugin": "4.2.0" + "workbox-webpack-plugin": "4.2.0", + "youtube-captions-scraper": "^1.0.3" }, "scripts": { "start": "node scripts/start.js", diff --git a/frontend/scripts/start.js b/frontend/scripts/start.js index 4792a57..b3b35d6 100644 --- a/frontend/scripts/start.js +++ b/frontend/scripts/start.js @@ -143,3 +143,15 @@ checkBrowsers(paths.appPath, isInteractive) } process.exit(1); }); + +console.log("hello!"); + +var getSubtitles = require('youtube-captions-scraper').getSubtitles; + +console.log("hello!"); +getSubtitles({ + videoID: 'jdi0Iq9NBqQ', // youtube video id + lang: 'en' // default: `en` +}).then(function(captions) { + console.log(captions); +}); diff --git a/frontend/src/testingAPI.js b/frontend/src/testingAPI.js new file mode 100644 index 0000000..32dfa61 --- /dev/null +++ b/frontend/src/testingAPI.js @@ -0,0 +1,11 @@ +console.log("hello!"); + +var getSubtitles = require('youtube-captions-scraper').getSubtitles; + +console.log("hello!"); +getSubtitles({ + videoID: 'ebDYuyomWEw', // youtube video id + lang: 'en' // default: `en` +}).then(function(captions) { + console.log(captions); +}); From d3557919430df6119cb6e2da951692cbd2239d3f Mon Sep 17 00:00:00 2001 From: angcast Date: Fri, 1 Oct 2021 16:14:33 -0400 Subject: [PATCH 2/7] Fixed spec --- backend/app/analysis/short_video_clips.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/app/analysis/short_video_clips.py b/backend/app/analysis/short_video_clips.py index 0c5a6f4..518ce22 100644 --- a/backend/app/analysis/short_video_clips.py +++ b/backend/app/analysis/short_video_clips.py @@ -1,4 +1,4 @@ """ -Helper functions used to get information of videos from Youtube URLs such as its +Helper functions used to get information of videos from URLs such as its transcript and title -""" +""" \ No newline at end of file From be68f282db96591009842515502741a0b16a4522 Mon Sep 17 00:00:00 2001 From: angcast Date: Fri, 8 Oct 2021 02:44:49 -0400 Subject: [PATCH 3/7] deleted script from start.js and added short video clips view folder --- frontend/scripts/start.js | 12 ------------ frontend/src/shortVideoClipsView.js | 0 2 files changed, 12 deletions(-) create mode 100644 frontend/src/shortVideoClipsView.js diff --git a/frontend/scripts/start.js b/frontend/scripts/start.js index b3b35d6..4792a57 100644 --- a/frontend/scripts/start.js +++ b/frontend/scripts/start.js @@ -143,15 +143,3 @@ checkBrowsers(paths.appPath, isInteractive) } process.exit(1); }); - -console.log("hello!"); - -var getSubtitles = require('youtube-captions-scraper').getSubtitles; - -console.log("hello!"); -getSubtitles({ - videoID: 'jdi0Iq9NBqQ', // youtube video id - lang: 'en' // default: `en` -}).then(function(captions) { - console.log(captions); -}); diff --git a/frontend/src/shortVideoClipsView.js b/frontend/src/shortVideoClipsView.js new file mode 100644 index 0000000..e69de29 From 2aeaf16663bb96d1d45c7725afd12c542f9f89bb Mon Sep 17 00:00:00 2001 From: angcast Date: Fri, 8 Oct 2021 03:00:38 -0400 Subject: [PATCH 4/7] Changed folder structure to use views and components folder --- frontend/src/{UILibrary => components}/components.js | 0 .../src/{UILibrary => components}/components.test.js | 0 frontend/src/{UILibrary => components}/navbar.js | 0 frontend/src/{UILibrary => components}/styles.scss | 10 +++++----- frontend/src/shortVideoClipsView.js | 0 frontend/src/testingAPI.js | 11 ----------- .../src/{anagramView => views/anagram}/anagramView.js | 0 .../{anagramView => views/anagram}/anagramView.scss | 0 .../{crosswordView => views/crossword}/crossword.js | 0 .../crossword}/crosswordView.js | 0 .../crossword}/crosswordView.scss | 0 frontend/src/{ => views}/flashcard/flashcardView.js | 0 frontend/src/{ => views}/flashcard/flashcardView.scss | 0 .../instructor}/instructorView.js | 0 .../instructor}/instructorView.scss | 0 .../pictureBook}/pictureBookView.js | 0 .../pictureBook}/pictureBookView.scss | 0 frontend/src/{quizView => views/quiz}/allQuizView.js | 0 frontend/src/{quizView => views/quiz}/quizView.css | 0 .../src/{quizView => views/quiz}/quizView.css.map | 0 frontend/src/{quizView => views/quiz}/quizView.js | 0 frontend/src/{quizView => views/quiz}/quizView.scss | 0 .../responseQuiz}/responseAllQuizView.js | 0 .../responseQuiz}/responseQuizView.js | 0 .../responseQuiz}/responseQuizView.scss | 0 25 files changed, 5 insertions(+), 16 deletions(-) rename frontend/src/{UILibrary => components}/components.js (100%) rename frontend/src/{UILibrary => components}/components.test.js (100%) rename frontend/src/{UILibrary => components}/navbar.js (100%) rename frontend/src/{UILibrary => components}/styles.scss (79%) delete mode 100644 frontend/src/shortVideoClipsView.js delete mode 100644 frontend/src/testingAPI.js rename frontend/src/{anagramView => views/anagram}/anagramView.js (100%) rename frontend/src/{anagramView => views/anagram}/anagramView.scss (100%) rename frontend/src/{crosswordView => views/crossword}/crossword.js (100%) rename frontend/src/{crosswordView => views/crossword}/crosswordView.js (100%) rename frontend/src/{crosswordView => views/crossword}/crosswordView.scss (100%) rename frontend/src/{ => views}/flashcard/flashcardView.js (100%) rename frontend/src/{ => views}/flashcard/flashcardView.scss (100%) rename frontend/src/{instructorView => views/instructor}/instructorView.js (100%) rename frontend/src/{instructorView => views/instructor}/instructorView.scss (100%) rename frontend/src/{pictureBookView => views/pictureBook}/pictureBookView.js (100%) rename frontend/src/{pictureBookView => views/pictureBook}/pictureBookView.scss (100%) rename frontend/src/{quizView => views/quiz}/allQuizView.js (100%) rename frontend/src/{quizView => views/quiz}/quizView.css (100%) rename frontend/src/{quizView => views/quiz}/quizView.css.map (100%) rename frontend/src/{quizView => views/quiz}/quizView.js (100%) rename frontend/src/{quizView => views/quiz}/quizView.scss (100%) rename frontend/src/{responseQuizView => views/responseQuiz}/responseAllQuizView.js (100%) rename frontend/src/{responseQuizView => views/responseQuiz}/responseQuizView.js (100%) rename frontend/src/{responseQuizView => views/responseQuiz}/responseQuizView.scss (100%) diff --git a/frontend/src/UILibrary/components.js b/frontend/src/components/components.js similarity index 100% rename from frontend/src/UILibrary/components.js rename to frontend/src/components/components.js diff --git a/frontend/src/UILibrary/components.test.js b/frontend/src/components/components.test.js similarity index 100% rename from frontend/src/UILibrary/components.test.js rename to frontend/src/components/components.test.js diff --git a/frontend/src/UILibrary/navbar.js b/frontend/src/components/navbar.js similarity index 100% rename from frontend/src/UILibrary/navbar.js rename to frontend/src/components/navbar.js diff --git a/frontend/src/UILibrary/styles.scss b/frontend/src/components/styles.scss similarity index 79% rename from frontend/src/UILibrary/styles.scss rename to frontend/src/components/styles.scss index cdd7353..9e61d70 100644 --- a/frontend/src/UILibrary/styles.scss +++ b/frontend/src/components/styles.scss @@ -3,11 +3,11 @@ */ @import "../../node_modules/bootstrap/scss/bootstrap"; @import '../index/index'; -@import '../anagramView/anagramView'; -@import '../crosswordView/crosswordView'; -@import '../instructorView/instructorView'; -@import '../flashcard/flashcardView'; -@import '../pictureBookView/pictureBookView'; +@import '../views/anagram/anagramView'; +@import '../views/crossword/crosswordView'; +@import '../views/instructor/instructorView'; +@import '../views/flashcard/flashcardView'; +@import '../views/pictureBook/pictureBookView'; html { position: relative; diff --git a/frontend/src/shortVideoClipsView.js b/frontend/src/shortVideoClipsView.js deleted file mode 100644 index e69de29..0000000 diff --git a/frontend/src/testingAPI.js b/frontend/src/testingAPI.js deleted file mode 100644 index 32dfa61..0000000 --- a/frontend/src/testingAPI.js +++ /dev/null @@ -1,11 +0,0 @@ -console.log("hello!"); - -var getSubtitles = require('youtube-captions-scraper').getSubtitles; - -console.log("hello!"); -getSubtitles({ - videoID: 'ebDYuyomWEw', // youtube video id - lang: 'en' // default: `en` -}).then(function(captions) { - console.log(captions); -}); diff --git a/frontend/src/anagramView/anagramView.js b/frontend/src/views/anagram/anagramView.js similarity index 100% rename from frontend/src/anagramView/anagramView.js rename to frontend/src/views/anagram/anagramView.js diff --git a/frontend/src/anagramView/anagramView.scss b/frontend/src/views/anagram/anagramView.scss similarity index 100% rename from frontend/src/anagramView/anagramView.scss rename to frontend/src/views/anagram/anagramView.scss diff --git a/frontend/src/crosswordView/crossword.js b/frontend/src/views/crossword/crossword.js similarity index 100% rename from frontend/src/crosswordView/crossword.js rename to frontend/src/views/crossword/crossword.js diff --git a/frontend/src/crosswordView/crosswordView.js b/frontend/src/views/crossword/crosswordView.js similarity index 100% rename from frontend/src/crosswordView/crosswordView.js rename to frontend/src/views/crossword/crosswordView.js diff --git a/frontend/src/crosswordView/crosswordView.scss b/frontend/src/views/crossword/crosswordView.scss similarity index 100% rename from frontend/src/crosswordView/crosswordView.scss rename to frontend/src/views/crossword/crosswordView.scss diff --git a/frontend/src/flashcard/flashcardView.js b/frontend/src/views/flashcard/flashcardView.js similarity index 100% rename from frontend/src/flashcard/flashcardView.js rename to frontend/src/views/flashcard/flashcardView.js diff --git a/frontend/src/flashcard/flashcardView.scss b/frontend/src/views/flashcard/flashcardView.scss similarity index 100% rename from frontend/src/flashcard/flashcardView.scss rename to frontend/src/views/flashcard/flashcardView.scss diff --git a/frontend/src/instructorView/instructorView.js b/frontend/src/views/instructor/instructorView.js similarity index 100% rename from frontend/src/instructorView/instructorView.js rename to frontend/src/views/instructor/instructorView.js diff --git a/frontend/src/instructorView/instructorView.scss b/frontend/src/views/instructor/instructorView.scss similarity index 100% rename from frontend/src/instructorView/instructorView.scss rename to frontend/src/views/instructor/instructorView.scss diff --git a/frontend/src/pictureBookView/pictureBookView.js b/frontend/src/views/pictureBook/pictureBookView.js similarity index 100% rename from frontend/src/pictureBookView/pictureBookView.js rename to frontend/src/views/pictureBook/pictureBookView.js diff --git a/frontend/src/pictureBookView/pictureBookView.scss b/frontend/src/views/pictureBook/pictureBookView.scss similarity index 100% rename from frontend/src/pictureBookView/pictureBookView.scss rename to frontend/src/views/pictureBook/pictureBookView.scss diff --git a/frontend/src/quizView/allQuizView.js b/frontend/src/views/quiz/allQuizView.js similarity index 100% rename from frontend/src/quizView/allQuizView.js rename to frontend/src/views/quiz/allQuizView.js diff --git a/frontend/src/quizView/quizView.css b/frontend/src/views/quiz/quizView.css similarity index 100% rename from frontend/src/quizView/quizView.css rename to frontend/src/views/quiz/quizView.css diff --git a/frontend/src/quizView/quizView.css.map b/frontend/src/views/quiz/quizView.css.map similarity index 100% rename from frontend/src/quizView/quizView.css.map rename to frontend/src/views/quiz/quizView.css.map diff --git a/frontend/src/quizView/quizView.js b/frontend/src/views/quiz/quizView.js similarity index 100% rename from frontend/src/quizView/quizView.js rename to frontend/src/views/quiz/quizView.js diff --git a/frontend/src/quizView/quizView.scss b/frontend/src/views/quiz/quizView.scss similarity index 100% rename from frontend/src/quizView/quizView.scss rename to frontend/src/views/quiz/quizView.scss diff --git a/frontend/src/responseQuizView/responseAllQuizView.js b/frontend/src/views/responseQuiz/responseAllQuizView.js similarity index 100% rename from frontend/src/responseQuizView/responseAllQuizView.js rename to frontend/src/views/responseQuiz/responseAllQuizView.js diff --git a/frontend/src/responseQuizView/responseQuizView.js b/frontend/src/views/responseQuiz/responseQuizView.js similarity index 100% rename from frontend/src/responseQuizView/responseQuizView.js rename to frontend/src/views/responseQuiz/responseQuizView.js diff --git a/frontend/src/responseQuizView/responseQuizView.scss b/frontend/src/views/responseQuiz/responseQuizView.scss similarity index 100% rename from frontend/src/responseQuizView/responseQuizView.scss rename to frontend/src/views/responseQuiz/responseQuizView.scss From a01b812ba4a53e014ede7eed61cce9e37f62cfc7 Mon Sep 17 00:00:00 2001 From: angcast Date: Fri, 8 Oct 2021 03:05:17 -0400 Subject: [PATCH 5/7] Added all the hierarchy changes --- frontend/src/app.js | 20 +++++++++---------- frontend/src/index/index.js | 2 +- frontend/src/views/anagram/anagramView.js | 2 +- frontend/src/views/crossword/crosswordView.js | 2 +- frontend/src/views/flashcard/flashcardView.js | 2 +- .../src/views/instructor/instructorView.js | 4 ++-- .../src/views/pictureBook/pictureBookView.js | 2 +- frontend/src/views/quiz/allQuizView.js | 2 +- frontend/src/views/quiz/quizView.css | 2 +- frontend/src/views/quiz/quizView.js | 2 +- .../views/responseQuiz/responseAllQuizView.js | 2 +- .../views/responseQuiz/responseQuizView.js | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/frontend/src/app.js b/frontend/src/app.js index 291eddd..4606f46 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -8,18 +8,18 @@ import ReactDOM from 'react-dom'; import 'bootstrap/dist/css/bootstrap.min.css'; import { IndexView } from './index/index'; -import { QuizView } from './quizView/quizView'; -import { AnagramView } from './anagramView/anagramView'; -import { InstructorView } from './instructorView/instructorView'; -import { FlashcardView } from './flashcard/flashcardView'; -import { AllQuizView } from './quizView/allQuizView'; -import { PictureBookView } from './pictureBookView/pictureBookView'; -import { CrosswordView } from './crosswordView/crosswordView'; -import { ResponseAllQuizView } from './responseQuizView/responseAllQuizView'; -import { ResponseQuizView } from './responseQuizView/responseQuizView'; +import { QuizView } from './views/quiz/quizView'; +import { AnagramView } from './views/anagram/anagramView'; +import { InstructorView } from './views/instructor/instructorView'; +import { FlashcardView } from './views/flashcard/flashcardView'; +import { AllQuizView } from './views/quiz/allQuizView'; +import { PictureBookView } from './views/pictureBook/pictureBookView'; +import { CrosswordView } from './views/crossword/crosswordView'; +import { ResponseAllQuizView } from './views/responseQuiz/responseAllQuizView'; +import { ResponseQuizView } from './views/responseQuiz/responseQuizView'; // Import all styles -import './UILibrary/styles.scss'; +import './components/styles.scss'; window.app_modules = { React, // Make React accessible from the base template diff --git a/frontend/src/index/index.js b/frontend/src/index/index.js index 917091b..55b8102 100644 --- a/frontend/src/index/index.js +++ b/frontend/src/index/index.js @@ -1,6 +1,6 @@ import React from 'react'; import * as PropTypes from 'prop-types'; -import { Navbar, Footer } from '../UILibrary/components'; +import { Navbar, Footer } from '../components/components'; // Functions to use to generate links for different formats diff --git a/frontend/src/views/anagram/anagramView.js b/frontend/src/views/anagram/anagramView.js index daed788..7fd0129 100644 --- a/frontend/src/views/anagram/anagramView.js +++ b/frontend/src/views/anagram/anagramView.js @@ -3,7 +3,7 @@ import ReactTooltipDefaultExport from 'react-tooltip'; import Confetti from 'react-dom-confetti'; import * as PropTypes from 'prop-types'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; const CONFETTI_CONFIG = { angle: 90, diff --git a/frontend/src/views/crossword/crosswordView.js b/frontend/src/views/crossword/crosswordView.js index 17972f9..5ace598 100644 --- a/frontend/src/views/crossword/crosswordView.js +++ b/frontend/src/views/crossword/crosswordView.js @@ -1,7 +1,7 @@ import React from 'react'; import * as PropTypes from 'prop-types'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; import Crossword from './crossword'; // Given a word and the clue that it is part of, remove the word from the clue diff --git a/frontend/src/views/flashcard/flashcardView.js b/frontend/src/views/flashcard/flashcardView.js index 3d0cd5a..38f43af 100644 --- a/frontend/src/views/flashcard/flashcardView.js +++ b/frontend/src/views/flashcard/flashcardView.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import * as PropTypes from 'prop-types'; -import { Footer, Navbar, LoadingPage } from '../UILibrary/components'; +import { Footer, Navbar, LoadingPage } from '../../components/components'; const capitalize = (word) => { return word.charAt(0).toUpperCase() + word.slice(1); diff --git a/frontend/src/views/instructor/instructorView.js b/frontend/src/views/instructor/instructorView.js index def3763..007ea51 100644 --- a/frontend/src/views/instructor/instructorView.js +++ b/frontend/src/views/instructor/instructorView.js @@ -1,8 +1,8 @@ import React from 'react'; import * as PropTypes from 'prop-types'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; -import { capitalize, getCookie } from '../common'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; +import { capitalize, getCookie } from '../../common'; class Module extends React.Component { render() { diff --git a/frontend/src/views/pictureBook/pictureBookView.js b/frontend/src/views/pictureBook/pictureBookView.js index c0c2e7e..bb91c4b 100644 --- a/frontend/src/views/pictureBook/pictureBookView.js +++ b/frontend/src/views/pictureBook/pictureBookView.js @@ -1,7 +1,7 @@ import React from 'react'; import * as PropTypes from 'prop-types'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; const capitalize = (word) => { return word.charAt(0).toUpperCase() + word.slice(1); diff --git a/frontend/src/views/quiz/allQuizView.js b/frontend/src/views/quiz/allQuizView.js index a8bb693..5b5c15c 100644 --- a/frontend/src/views/quiz/allQuizView.js +++ b/frontend/src/views/quiz/allQuizView.js @@ -3,7 +3,7 @@ import './quizView.scss'; // import ReactTooltipDefaultExport from 'react-tooltip'; // import * as PropTypes from 'prop-types'; import { Button } from 'react-bootstrap'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; export class AllQuizView extends React.Component { constructor(props) { diff --git a/frontend/src/views/quiz/quizView.css b/frontend/src/views/quiz/quizView.css index 9686a32..7639a96 100644 --- a/frontend/src/views/quiz/quizView.css +++ b/frontend/src/views/quiz/quizView.css @@ -21,4 +21,4 @@ border: none; } -/*# sourceMappingURL=quizView.css.map */ +/*# sourceMappingURL=quiz.css.map */ diff --git a/frontend/src/views/quiz/quizView.js b/frontend/src/views/quiz/quizView.js index ee646e6..b0a15e8 100644 --- a/frontend/src/views/quiz/quizView.js +++ b/frontend/src/views/quiz/quizView.js @@ -8,7 +8,7 @@ import { ToggleButtonGroup, } from 'react-bootstrap'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; export class QuizView extends React.Component { diff --git a/frontend/src/views/responseQuiz/responseAllQuizView.js b/frontend/src/views/responseQuiz/responseAllQuizView.js index 8437b67..c1fb6f9 100644 --- a/frontend/src/views/responseQuiz/responseAllQuizView.js +++ b/frontend/src/views/responseQuiz/responseAllQuizView.js @@ -3,7 +3,7 @@ import './responseQuizView.scss'; // import ReactTooltipDefaultExport from 'react-tooltip'; // import * as PropTypes from 'prop-types'; import { Button } from 'react-bootstrap'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; export class ResponseAllQuizView extends React.Component { constructor(props) { diff --git a/frontend/src/views/responseQuiz/responseQuizView.js b/frontend/src/views/responseQuiz/responseQuizView.js index ec3e57b..354a173 100644 --- a/frontend/src/views/responseQuiz/responseQuizView.js +++ b/frontend/src/views/responseQuiz/responseQuizView.js @@ -10,7 +10,7 @@ import { ToggleButtonGroup, } from 'react-bootstrap'; -import { Navbar, Footer, LoadingPage } from '../UILibrary/components'; +import { Navbar, Footer, LoadingPage } from '../../components/components'; // This dictionary maps specific error types to their respective error message. const ERROR_DESCRIPTIONS = { From 376b1eb1d3d873c74977a6e61094bccec2c0f233 Mon Sep 17 00:00:00 2001 From: Raxel Gutierrez Date: Fri, 29 Oct 2021 15:13:59 -0400 Subject: [PATCH 6/7] Add helper functions for video transcript information retrieval --- backend/app/analysis/short_video_clips.py | 94 ++++++++++++++++++++++- requirements.txt | 6 +- 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/backend/app/analysis/short_video_clips.py b/backend/app/analysis/short_video_clips.py index 518ce22..627cb16 100644 --- a/backend/app/analysis/short_video_clips.py +++ b/backend/app/analysis/short_video_clips.py @@ -1,4 +1,96 @@ """ Helper functions used to get information of videos from URLs such as its transcript and title -""" \ No newline at end of file +""" +import isodate +import os +import time + +import googleapiclient.discovery +from youtube_transcript_api import YouTubeTranscriptApi + +api_service_name = "youtube" +api_version = "v3" +DEVELOPER_KEY = "AIzaSyCwwNqx7_HiX_KvxOGckFI9JxMy7LqdK2s" + +youtube = googleapiclient.discovery.build( + api_service_name, api_version, developerKey = DEVELOPER_KEY) + +def get_video_data(video_id): + """ + Given an id of a video, gets its title and transcript in an interval format + + :param video_id: ID of video + :return: A dictionary with title and transcript of video with ID video_id + """ + transcript = YouTubeTranscriptApi.get_transcript(video_id) + request = youtube.videos().list( + id=video_id, + part="snippet,contentDetails", + fields="items/snippet/title,items/contentDetails/duration", + ) + response_data = request.execute()['items'][0] + title = response_data['snippet']['title'] + duration = response_data['contentDetails']['duration'] + + timedelta_dur = isodate.parse_duration(duration) + dur_seconds = int(timedelta_dur.total_seconds()) + end_timestamp = timestamp_format(dur_seconds) + + return { + 'title': title, + 'transcript': transcript_intervals_format(transcript, end_timestamp), + } + + +def create_transcript_snippet(start, end, text): + """ + Generate a snippet given the start, end, and text of a transcript interval + + :param start: Start time of transcript interval + :param end: End time of transcript interval + :param text: Text content of transcript interval + :return: A dictionary with the start/end times and text content of transcript interval + """ + return { + 'start': start, + 'end': end, + 'text': text, + } + + +def transcript_intervals_format(transcript, end_timestamp): + """ + Given a video transcript and last timestamp, format transcript content into intervals + + :param transcript: Video transcript + :param end_timestamp: Last timestamp on video + :return: List of dictionaries that represent an interval of video transcript + """ + intervals = [] + for i in range(len(transcript)-1): + start, end = round(transcript[i]['start']), round(transcript[i+1]['start']) + text = transcript[i]['text'] + snippet = create_transcript_snippet( + timestamp_format(start), timestamp_format(end), text + ) + intervals.append(snippet) + + # Add final interval through YouTube API call because duration is + # not accurate from captions transcript through the "dur" attribute + prev_end = intervals[-1]['end'] + end_text = transcript[-1]['text'] + end_snippet = create_transcript_snippet(prev_end, end_timestamp, end_text) + intervals.append(end_snippet) + + return intervals + + +def timestamp_format(duration): + """ + Given a duration in seconds, formats time to MM:SS + + :param duration: duration of + :return: String of time duration formatted as MM:SS + """ + return time.strftime('%M:%S', time.gmtime(duration)) diff --git a/requirements.txt b/requirements.txt index b46fd03..5ecbd3f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,8 +9,10 @@ django-cors-headers==3.6.0 django-webpack-loader==0.7.0 djangorestframework==3.12.2 futures==3.1.1 +google-api-python-client==2.27.0 goslate==1.5.1 idna==2.10 +isodate==0.6.0 joblib==1.0.1 nltk==3.5 PyDictionary==2.0.1 @@ -18,8 +20,8 @@ pyspellchecker==0.6.1 pytz==2020.5 regex==2020.11.13 requests==2.25.1 +similar-sounding-words==0.1.2 soupsieve==2.2 sqlparse==0.4.1 tqdm==4.58.0 -urllib3==1.26.3 -similar-sounding-words==0.1.2 +youtube-transcript-api==0.4.1 From c2c88479f0f898cf79451f0de85d2a8e92102471 Mon Sep 17 00:00:00 2001 From: Raxel Gutierrez Date: Fri, 29 Oct 2021 15:16:48 -0400 Subject: [PATCH 7/7] Add get_video_data endpoint --- backend/app/views.py | 8 ++++++++ backend/config/urls.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/backend/app/views.py b/backend/app/views.py index ed23e05..1394cf1 100644 --- a/backend/app/views.py +++ b/backend/app/views.py @@ -34,6 +34,8 @@ ) from .quiz_creation.conjugation_quiz import get_quiz_sentences +from .analysis.short_video_clips import get_video_data + @api_view(['GET']) def all_text(request): @@ -243,3 +245,9 @@ def get_response_quiz_data(request, text_id): raise Http404 from text_not_exist res = get_quiz_questions(text_obj.content) return Response(res) + +@api_view(['GET']) +def get_video_transcript(request, video_id): + transcript = get_video_data(video_id) + return Response(transcript) + diff --git a/backend/config/urls.py b/backend/config/urls.py index fbdab93..4c0dd75 100644 --- a/backend/config/urls.py +++ b/backend/config/urls.py @@ -29,6 +29,7 @@ get_crossword, get_quiz_data, text, get_response_quiz_data, + get_video_transcript, ) @@ -61,6 +62,7 @@ def react_view_path(route, component_name): path('api/text/', text), path('api/get_picturebook_prompt//', get_picturebook_prompt), path('api/get_picturebook_data', get_picturebook_data), + path('api/get_video_transcript/', get_video_transcript), # View paths react_view_path('', 'IndexView'),