diff --git a/web/__init__.py b/web/__init__.py index 3464a6d..de27672 100644 --- a/web/__init__.py +++ b/web/__init__.py @@ -1,5 +1,6 @@ from .webwatch_html import Watch_HTML +from .webwatch_api import WebWatch_Tuner class Plugin_OBJ(): @@ -9,3 +10,4 @@ class Plugin_OBJ(): self.plugin_utils = plugin_utils self.webwatch_html = Watch_HTML(fhdhr, plugin_utils) + self.webwatch_api = WebWatch_Tuner(fhdhr, plugin_utils) diff --git a/web/webwatch_api.py b/web/webwatch_api.py new file mode 100644 index 0000000..f167e67 --- /dev/null +++ b/web/webwatch_api.py @@ -0,0 +1,124 @@ +from flask import Response, request, redirect, abort, stream_with_context, session +import urllib.parse + +from fHDHR.exceptions import TunerError + + +class WebWatch_Tuner(): + endpoints = ["/api/webwatch"] + endpoint_name = "api_webwatch" + endpoint_methods = ["GET", "POST"] + + def __init__(self, fhdhr, plugin_utils): + self.fhdhr = fhdhr + + def __call__(self, *args): + return self.get(*args) + + def get(self, *args): + + client_address = request.remote_addr + + accessed_url = request.args.get('accessed', default=request.url, type=str) + + method = request.args.get('method', default="stream", type=str) + + redirect_url = request.args.get('redirect', default=None, type=str) + + origin_methods = self.fhdhr.origins.valid_origins + origin = request.args.get('origin', default=None, type=str) + if origin and origin not in origin_methods: + return "%s Invalid channels origin" % origin + + if method == "stream": + + channel_number = request.args.get('channel', None, type=str) + if not channel_number: + return "Missing Channel" + + if origin: + + if str(channel_number) in [str(x) for x in self.fhdhr.device.channels.get_channel_list("number", origin)]: + chan_obj = self.fhdhr.device.channels.get_channel_obj("number", channel_number, origin) + elif str(channel_number) in [str(x) for x in self.fhdhr.device.channels.get_channel_list("id", origin)]: + chan_obj = self.fhdhr.device.channels.get_channel_obj("id", channel_number, origin) + else: + response = Response("Not Found", status=404) + response.headers["X-fHDHR-Error"] = "801 - Unknown Channel" + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + abort(response) + + else: + + if str(channel_number) in [str(x) for x in self.fhdhr.device.channels.get_channel_list("id")]: + chan_obj = self.fhdhr.device.channels.get_channel_obj("id", channel_number) + else: + response = Response("Not Found", status=404) + response.headers["X-fHDHR-Error"] = "801 - Unknown Channel" + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + abort(response) + + if not chan_obj.dict["enabled"]: + response = Response("Service Unavailable", status=503) + response.headers["X-fHDHR-Error"] = str("806 - Tune Failed") + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + abort(response) + + origin = chan_obj.origin + channel_number = chan_obj.number + + duration = request.args.get('duration', default=0, type=int) + + stream_args = { + "channel": channel_number, + "origin": origin, + "method": "webwatch", + "duration": duration, + "origin_quality": self.fhdhr.config.dict["streaming"]["origin_quality"], + "transcode_quality": self.fhdhr.config.dict["streaming"]["transcode_quality"], + "accessed": accessed_url, + "client": client_address, + "client_id": session["session_id"] + } + + try: + tunernum = self.fhdhr.device.tuners.first_available(origin, channel_number) + except TunerError as e: + self.fhdhr.logger.info("A %s stream request for channel %s was rejected due to %s" + % (stream_args["method"], str(stream_args["channel"]), str(e))) + response = Response("Service Unavailable", status=503) + response.headers["X-fHDHR-Error"] = str(e) + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + abort(response) + + tuner = self.fhdhr.device.tuners.tuners[origin][str(tunernum)] + + try: + stream_args = self.fhdhr.device.tuners.get_stream_info(stream_args) + except TunerError as e: + self.fhdhr.logger.info("A %s stream request for %s channel %s was rejected due to %s" + % (origin, stream_args["method"], str(stream_args["channel"]), str(e))) + response = Response("Service Unavailable", status=503) + response.headers["X-fHDHR-Error"] = str(e) + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + tuner.close() + abort(response) + + self.fhdhr.logger.info("%s Tuner #%s to be used for stream." % (origin, tunernum)) + tuner.set_status(stream_args) + session["tuner_used"] = tunernum + + try: + stream = tuner.get_stream(stream_args, tuner) + except TunerError as e: + response.headers["X-fHDHR-Error"] = str(e) + self.fhdhr.logger.error(response.headers["X-fHDHR-Error"]) + tuner.close() + abort(response) + + return Response(stream_with_context(stream.get()), mimetype="video/mp4") + + if redirect_url: + return redirect("%s?retmessage=%s" % (redirect_url, urllib.parse.quote("%s Success" % method))) + else: + return "%s Success" % method diff --git a/web/webwatch_html.py b/web/webwatch_html.py index 05012c0..57405b0 100644 --- a/web/webwatch_html.py +++ b/web/webwatch_html.py @@ -27,6 +27,6 @@ class Watch_HTML(): origin = self.fhdhr.origins.valid_origins[0] channel_id = [x["id"] for x in self.fhdhr.device.channels.get_channels(origin)][0] - watch_url = '%s/api/tuners?method=stream&channel=%s&origin=%s&stream_method=webwatch' % (base_url, channel_id, origin) + watch_url = '%s/api/webwatch?method=stream&channel=%s&origin=%s' % (base_url, channel_id, origin) return render_template_string(self.template.getvalue(), request=request, session=session, fhdhr=self.fhdhr, watch_url=watch_url)