const useErrorBoundary = () => { const [error, setError] = React.useState(null); const ErrorBoundary = ({ children }) => { if (error) { return } return children; }; const throwError = (message) => { setError(new Error(message)); }; return { ErrorBoundary, throwError }; }; class App extends React.Component { setState() { const params = new Proxy(new URLSearchParams(window.location.search), { get: (searchParams, prop) => searchParams.get(prop), }); this.videoUrl = params.video_url; if (this.videoUrl) { this.loggedIn = true; } else { this.loggedIn = false; } } componentWillMount() { this.setState(); } render() { if (this.loggedIn) { return ; } return ; } } function getVideoComponent(video_id, seconds) { if (video_id == null) { return "" } var video_source = video_id.split("_") if (video_source[0] == 'vk') { var user_id = video_source[1] var video_id = video_source[2] var vk_url = "https://vk.com/video_ext.php?oid=" + user_id + "&id=" + video_id + "&hd=2&js_api=1" return () } if (video_source[0] == 'youtube') { return ; } } function Home() { const [url, setUrl] = React.useState(""); const { ErrorBoundary, throwError } = useErrorBoundary(); function sendUrl() { event.preventDefault(); createTask(url) } function handleChange(event) { setUrl(event.target.value) } function createTask(url_s) { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: url_s }) }; fetch('/v1/tasks', requestOptions).then(response => { if (!response.ok) { if (response.status == 400) { throwError("Неправильный формат ссылки"); } return Promise.reject(response); } return response.json(); }).then(data => { var searchParams = new URLSearchParams(window.location.search); searchParams.set("video_url", url_s); window.location.search = searchParams.toString(); }).catch(error => { if (typeof error.json === "function") { error .json() .then(jsonError => { if (jsonError.state == 6) { throwError(jsonError.result) } console.error("Json error from API"); console.error(jsonError); }) .catch(genericError => { console.error("Generic error from API"); console.error(error.statusText); }); } else { console.error("Fetch error"); console.error(error); } }); } return (

СОKPAT

«Сократ: краткий пересказ видео — просто и эффективно».



) } function MainPage({ videoUrl }) { const [task, setTask] = React.useState({}); const [taskID, setTaskID] = React.useState(); React.useEffect(() => { const fetchAPI = async (videoUrl) => { const requestOptions = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: videoUrl }) }; await fetch('/v1/tasks', requestOptions).then(response => { if (!response.ok) { return Promise.reject(response); } return response.json(); }).then(data => { setTaskID(data.task_id) fetchTaskUntilSucceeded(data.task_id, 1000) }).catch(error => { if (typeof error.json === "function") { error .json() .then(jsonError => { console.error("Json error from API"); console.error(jsonError); }) .catch(genericError => { console.error("Generic error from API"); console.error(error.statusText); }); } else { console.error("Fetch error"); console.error(error); } }); }; fetchAPI(videoUrl); }, []); function logout() { window.history.pushState({}, document.title, window.location.pathname); location.reload(); } function fetchTaskUntilSucceeded(taskID, retries) { if (retries <= 0) { throw new Error("No more retries") } const requestOptions = { method: 'GET', headers: { 'Content-Type': 'application/json' } }; fetch("/v1/tasks/" + taskID, requestOptions).then((res) => { if (!res.ok) { console.error('Error fetching task', res); return; } return res.json(); }).then((result) => { if (result === undefined) { setTimeout(() => fetchTaskUntilSucceeded(taskID, retries - 1), 5000); return; } setTask(result.task); if (result.task.state < 4) { setTimeout(() => fetchTaskUntilSucceeded(taskID, retries - 1), 5000); } }); } return (
); } function Header() { const [user, setUser] = React.useState(""); const [userAuthenticated, setUserAuthenticated] = React.useState(false); const [isLoading, setIsLoading] = React.useState(false); React.useEffect(() => { const fetchData = async () => { fetch("/auth/info/") .then(resp => resp.json()) .then(data => { console.log(data); setUserAuthenticated(data.is_authenticated); if (data.is_authenticated == true) { setUser(data.display_name); } setIsLoading(false); }) .catch(err => { console.log("error", err); setIsLoading(false); }); }; fetchData(); }, []); let userMarkup; if (isLoading) { userMarkup = (
); } else { if (userAuthenticated) { userMarkup = ( ); } else { userMarkup = ( Войти ); } } return (
{userMarkup}
); } function Task({ task }) { const [seconds, setSeconds] = React.useState(0); function getTaskState(task) { switch (task.state) { case 0: return "Скачиваем ..." case 1: return "Распознаём ..." case 2: return "Пытаемся понять что распознали ..." case 3: return "Разобрались, резюмируем ..." case 6: if (task.result == "error downloading video: nonretriable\nwrong video type") { return "Пока что мы не умеем обрабатывать трансляции 😿" } if (task.result == "error downloading video: nonretriable\nvideo is too long") { return "Пока что мы не умеем работать с видео длиннее 4 часов 😿" } return "Что-то пошло не так 😿" default: return "Готово!" } } function setVideoSeconds(seconds) { setSeconds(seconds) document.getElementById("youtube-player").scrollIntoView({ behavior: 'smooth' }) } return (
{task.url &&
{getVideoComponent(task.video_id, seconds)} {!([4, 5].includes(task.state)) &&
{getTaskState(task)}
}
}
{[4, 5].includes(task.state) &&

{task .summarization .topics .map(summarization => { setVideoSeconds(summarization.first_message_id) }} />)}
} {task.state >= 2 && task.state < 6 &&

{task .transcription .map(transcription => )}
}
) } function Transcription({ transcription }) { return (
{transcription.message_id}: {transcription.text}
) } function Summarization({ summarization, onTimestampClick }) { function toTimestamp(seconds) { return new Date(seconds * 1000) .toISOString() .slice(11, 19); } return (
) } function Questions({ task_id }) { const [question, setQuestion] = React.useState(''); const [questions, setQuestions] = React.useState([]); const [isLoading, setIsLoading] = React.useState(false); function sendQuestion() { if (question != '') { event.preventDefault(); setQuestions(prevState => ([ ...prevState, { "message_id": 0, "message_dt": new Date(), "content": question, "role": "user" } ])) serverQuestionRequest(task_id, question); setQuestion('') } } function fetchAnswersUntilSucceeded(task_id, message_id, question_uuid, retries) { let url = '/v1/tasks/' + task_id + '/questions/' + message_id + '/?question_uuid=' + question_uuid if (retries <= 0) { throw new Error("No more retries") } fetch(url).then(res => { if (res.status == 200) { return res .json() .then(result => { setIsLoading(false) setQuestions(prevState => ([ ...prevState, result[1] ])) }, error => { console.error(error) }) } if ([202, 500].includes(res.status)) { setTimeout(() => { return fetchAnswersUntilSucceeded(task_id, message_id, question_uuid, retries - 1); }, 5000); return; } setIsLoading(false); setQuestions(prevState => ([ ...prevState, { "message_id": 0, "message_dt": new Date(), "content": "Что-то пошло не так", "role": "warning" } ])) }) } function serverQuestionRequest(task_id, question_s) { const requestOptions = { mode: 'no-cors', method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8' }, body: JSON.stringify({ question: question_s }) } let url = '/v1/tasks/' + task_id + '/questions' fetch(url, requestOptions) .then(res => { if (res.status == 200) { res .json() .then(result => { setIsLoading(true); fetchAnswersUntilSucceeded(task_id, result.message_id, result.question_uuid, 30); }, error => { setIsLoading(false); console.error(error); }); return; } if (res.status == 409) { setQuestions(prevState => ([ ...prevState, { "message_id": 0, "message_dt": new Date(), "content": "Что-то пошло не так, попробуйте еще раз", "role": "warning" } ])); return; } setQuestions(prevState => ([ ...prevState, { "message_id": 0, "message_dt": new Date(), "content": "Что-то пошло не так", "role": "warning" } ])); return; }) } return (
{questions.length > 0 && questions.map(q => )} {isLoading &&
Сократ печатает
}
setQuestion(e.target.value)} name="question" className="col-md-11" />
) } function YoutubeEmbed({ embedId, seconds }) { let link = "https://www.youtube.com/embed/" + embedId if (seconds > 0) { link = link + "?version=3&loop=1&enablejsapi=1&autoplay=1&start=" + seconds } return (