diff --git a/src/core/__builtins__.py b/src/core/__builtins__.py index 7265b88..f6c101f 100644 --- a/src/core/__builtins__.py +++ b/src/core/__builtins__.py @@ -113,6 +113,9 @@ from core.utils.shellfm.windows.controller import WindowController # Get file window_controllers = {} processes = {} +def _get_sse_id(): + return session["win_controller_id"] + def _get_view(): controller = None try: @@ -200,5 +203,6 @@ def _kill_stream(process): builtins.get_view = _get_view +builtins.get_sse_id = _get_sse_id builtins.get_stream = _get_stream builtins.kill_stream = _kill_stream diff --git a/src/core/routes/Routes.py b/src/core/routes/Routes.py index f802d51..23b2526 100644 --- a/src/core/routes/Routes.py +++ b/src/core/routes/Routes.py @@ -1,9 +1,10 @@ # Python imports import os -# import subprocess +import requests import uuid # Lib imports +from flask import make_response from flask import redirect from flask import request from flask import render_template @@ -23,9 +24,19 @@ from core import oidc def home(): if request.method == 'GET': view = get_view() + sse_id = get_sse_id() _dot_dots = view.get_dot_dots() _current_directory = view.get_current_directory() - return render_template('pages/index.html', current_directory = _current_directory, dot_dots = _dot_dots) + + response = make_response( + render_template( + 'pages/index.html', + current_directory = _current_directory, + dot_dots = _dot_dots + ) + ) + response.set_cookie('sse_id', sse_id, secure=True, httponly = False) + return response return render_template('error.html', title = 'Error!', message = 'Must use GET request type...') @@ -90,40 +101,15 @@ def file_manager_action(_type, _hash = None): return send_from_directory(directory=folder, filename=file) if _type == "remux": - # NOTE: Need to actually implimint a websocket to communicate back to client that remux has completed. - # As is, the remux thread hangs until completion and client tries waiting until server reaches connection timeout. - # I.E....this is stupid but for now works better than nothing - good_result = view.remux_video(_hash, fpath) - if not good_result: - msg = "Remuxing: Remux failed or took too long; please, refresh the page and try again..." - return json_message.create("warning", msg) - - return '{"path":"static/remuxs/' + _hash + '.mp4"}' + remux_video(get_sse_id(), _hash, fpath, view) + msg = "Remuxing: Remux process has started..." + return json_message.create("success", msg) if _type == "stream": - process = get_stream() - if process: - if not kill_stream(process): - msg = "Couldn't stop an existing stream!" - return json_message.create("danger", msg) + setup_stream(get_sse_id(), _hash, fpath) + msg = "Streaming: Streaming process is being setup..." + return json_message.create("success", msg) - _sub_uuid = uuid.uuid4().hex - _video_path = fpath - _stub = f"{_hash}{_sub_uuid}" - _rtsp_path = f"rtsp://www.{app_name.lower()}.com:8554/{_stub}" - _rtmp_path = f"rtmp://www.{app_name.lower()}.com:1935/{_stub}" - _hls_path = f"http://www.{app_name.lower()}.com:8888/{_stub}/" - _webrtc_path = f"http://www.{app_name.lower()}.com:8889/{_stub}/" - - _stream_target = _rtsp_path - - stream = get_stream(_video_path, _stream_target) - if stream.poll(): - msg = "Streaming: Setting up stream failed! Please try again..." - return json_message.create("danger", msg) - - _stream_target = _rtmp_path - return {"stream": _stream_target} # NOTE: Positionally protecting actions further down that are privlidged # Be aware of ordering! @@ -142,6 +128,50 @@ def file_manager_action(_type, _hash = None): return json_message.create("success", msg) +@daemon_threaded +def remux_video(sse_id, hash, path, view): + link = f"https://www.webfm.com/sse/{sse_id}" + body = '{"path":"static/remuxs/' + hash + '.mp4"}' + + good_result = view.remux_video(hash, path) + if not good_result: + body = json_message.create("warning", "Remuxing: Remux failed...") + + requests.post(link, data=body, timeout=10) + + +# @daemon_threaded +def setup_stream(sse_id, hash, path): + link = f"https://www.webfm.com/sse/{sse_id}" + _sub_uuid = uuid.uuid4().hex + _video_path = path + _stub = f"{hash}{_sub_uuid}" + _rtsp_path = f"rtsp://www.{app_name.lower()}.com:8554/{_stub}" + _rtmp_path = f"rtmp://www.{app_name.lower()}.com:1935/{_stub}" + _hls_path = f"http://www.{app_name.lower()}.com:8888/{_stub}/" + _webrtc_path = f"http://www.{app_name.lower()}.com:8889/{_stub}/" + _stream_target = _rtsp_path + body = '{"stream":"' + _stream_target + '"}' + + process = get_stream() + if process: + if not kill_stream(process): + msg = "Couldn't stop an existing stream!" + body = json_message.create("danger", msg) + requests.post(link, data=body, timeout=10) + return + + stream = get_stream(_video_path, _stream_target) + if stream.poll(): + msg = "Streaming: Setting up stream failed! Please try again..." + body = json_message.create("danger", msg) + requests.post(link, data=body, timeout=10) + return + + requests.post(link, data=body, timeout=10) + + + @app.route('/api/stop-current-stream', methods=['GET', 'POST']) def stop_current_stream(): type = "success" diff --git a/src/core/static/js/webfm/sse.js b/src/core/static/js/webfm/sse.js index 24e2af6..63ad838 100644 --- a/src/core/static/js/webfm/sse.js +++ b/src/core/static/js/webfm/sse.js @@ -1,25 +1,32 @@ -const publishURL = `https://www.webfm.com/sse/1234/sse`; -const subscribeURL = `https://www.webfm.com/sse/1234/sse`; +const sse_id = getCookie("sse_id"); +const publishURL = `https://www.webfm.com/sse/${sse_id}/sse`; +const subscribeURL = publishURL; const eventSource = new EventSource(subscribeURL); -// Publish button -// document.getElementById("publishButton").onclick = () => { -// fetch(publishURL, { -// method: 'POST', // works with PUT as well, though that sends an OPTIONS request too! -// body: `It is ${new Date().toString()}. This is a test.` -// }) -// }; // ---- Incoming events ---- // -// eventSource.onopen = () => { -// console.log(e); +// eventSource.onopen = (eve) => { +// console.log(eve); // }; -eventSource.onerror = (e) => { - console.log(e); +eventSource.onerror = (eve) => { + console.log(publishURL); + console.log(eve); }; -eventSource.onmessage = (e) => { - console.log(e.data); +eventSource.onmessage = (eve) => { + try { + const data = JSON.parse(eve.data); + const sse_msg = JSON.parse(data.message); + if (sse_msg.hasOwnProperty('path') || sse_msg.hasOwnProperty('stream')) { + const target = (sse_msg.path) ? sse_msg.path : sse_msg.stream; + handleMedia(target); + return; + } else if (sse_msg.hasOwnProperty('message')) { + displayMessage(sse_msg.message.text, sse_msg.message.type); + } + } catch (e) { + console.log(e); + } }; diff --git a/src/core/static/js/webfm/ui-logic.js b/src/core/static/js/webfm/ui-logic.js index 0922eae..7e84401 100644 --- a/src/core/static/js/webfm/ui-logic.js +++ b/src/core/static/js/webfm/ui-logic.js @@ -83,8 +83,9 @@ const showFile = async (title, hash, extension, type, target=null) => { await fetchData("api/stop-current-stream"); if (type === "video" || type === "stream") { - isStream = (type === "stream") - setupVideo(hash, extension, isStream); + isStream = (type === "stream") ? true : false; + target = (type === "stream") ? "stream" : "remux"; + setupVideo(hash, extension, isStream, target); setSelectedActiveMedia(target); } else if (type === "trailer") { launchTrailer(hash); @@ -102,53 +103,36 @@ const launchTrailer = (link) => { modal.show(); } -const setupVideo = async (hash, extension, isStream=false) => { +const setupVideo = async (hash, extension, isStream, target="remux") => { document.getElementById("video_container").style.display = ""; - const title = document.getElementById("selectedFile").innerText; - let modal = new bootstrap.Modal(document.getElementById('file-view-modal'), { keyboard: false }); - video_path = "api/file-manager-action/files/" + hash; - console.log("Using default path..."); + video_path = `api/file-manager-action/files/${hash}`; clearSelectedActiveMedia(); try { - if ((/\.(avi|mkv|wmv|flv|f4v|mov|m4v|mpg|mpeg|mp4|webm|mp3|flac|ogg)$/i).test(extension)) { - if ((/\.(avi|mkv|wmv|flv|f4v)$/i).test(extension)) { - if (isStream) { - data = await fetchData( "api/file-manager-action/stream/" + hash ); - if (data.hasOwnProperty('stream')) { - console.log("Transfering to stream path..."); - video_path = data.stream; - } - } else { - data = await fetchData( "api/file-manager-action/remux/" + hash ); - if (data.hasOwnProperty('path')) { - console.log("Transfering to remux path..."); - video_path = data.path; - } - } - - if (data.hasOwnProperty('path') === null && - data.hasOwnProperty('stream') === null) { - displayMessage(data.message.text, data.message.type); - return; - } - } else if ((/\.(flv|mov|m4v|mpg|mpeg)$/i).test(extension)) { - modal.hide(); - openWithLocalProgram(hash, extension); - return; - } + if (!isStream && !(/\.(avi|mkv|wmv|flv|f4v|mov|m4v|mpg|mpeg)$/i).test(extension)) { + handleMedia(video_path); + return; } + if (!isStream && (/\.(mov|m4v|mpg|mpeg)$/i).test(extension)) { + const msg = "Media Error: Please open mov|m4v|mpg|mpeg media locally or try streaming it..." + displayMessage(msg, "warning", 5); + return; + } - const fTitle = document.getElementById("selectedFile").innerText; - loadMediaToPlayer(title, video_path); - modal.show(); + const data = await fetchData(`api/file-manager-action/${target}/${hash}`); + displayMessage(data.message.text, data.message.type, 5); } catch (e) { video.style.display = "none"; console.log(e); } } +const handleMedia = async (video_path) => { + const title = document.getElementById("selectedFile").innerText; + loadMediaToPlayer(title, video_path); +} + const setupFile = async (hash, extension) => { let viewer = null; let type = "local"; diff --git a/src/core/static/js/webfm/video-events.js b/src/core/static/js/webfm/video-events.js index 130215d..7626843 100644 --- a/src/core/static/js/webfm/video-events.js +++ b/src/core/static/js/webfm/video-events.js @@ -134,6 +134,8 @@ const togglePlaylistMode = (elm) => { } const loadMediaToPlayer = (title = "", video_path = "") => { + const modal = new bootstrap.Modal(document.getElementById('file-view-modal'), { keyboard: false }); + if(/Android/i.test(navigator.userAgent)) { player.setMedia(video_path).play() } else { @@ -154,6 +156,8 @@ const loadMediaToPlayer = (title = "", video_path = "") => { poster: "static/imgs/icons/loading.gif" }).jPlayer("play"); } + + modal.show(); } const doPlayOrFullscreen = (node) => {