Repository: streamlink/streamlink

Issue:
[plugn request] lrt.lt
### Checklist

- [ ] This is a bug report.
- [ ] This is a feature request.
- [x] This is a plugin (improvement) request.
- [x] I have read the contribution guidelines.

### Description

Would it be possible to add a plugin for the Lithuanian National Television? Video streams are located [here](https://www.lrt.lt/mediateka/tiesiogiai/lrt-televizija), [here](https://www.lrt.lt/mediateka/tiesiogiai/lrt-kultura) and [here](https://www.lrt.lt/mediateka/tiesiogiai/lrt-lituanica).

Thanks.

Comments:

Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index e6cd82c6..13134a95 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -113,6 +113,7 @@ liveedu                 - liveedu.tv         Yes   --    Some streams require a
                         - livecoding.tv
 liveme                  liveme.com           Yes   --
 livestream              new.livestream.com   Yes   --
+lrt                     lrt.lt               Yes   No
 media_ccc_de            - media.ccc.de       Yes   Yes   Only mp4 and HLS are supported.
                         - streaming... [4]_
 mediaklikk              mediaklikk.hu        Yes   No    Streams may be geo-restricted to Hungary.
diff --git a/src/streamlink/plugins/lrt.py b/src/streamlink/plugins/lrt.py
new file mode 100644
index 00000000..2ab41b49
--- /dev/null
+++ b/src/streamlink/plugins/lrt.py
@@ -0,0 +1,43 @@
+import logging
+import re
+from functools import partial
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http
+from streamlink.stream import HLSStream
+from streamlink.utils import parse_json
+from streamlink.compat import urlparse
+
+log = logging.getLogger(__name__)
+
+
+class LRT(Plugin):
+    _url_re = re.compile(r"https?://(?:www\.)?lrt.lt/mediateka/.")
+    _source_re = re.compile(r'sources\s*:\s*(\[{.*?}\]),', re.DOTALL | re.IGNORECASE)
+    js_to_json = partial(re.compile(r'(?!<")(\w+)\s*:\s*(["\']|\d?\.?\d+,|true|false|\[|{)').sub, r'"\1":\2')
+
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url)
+
+    def _get_streams(self):
+        page = http.get(self.url)
+        m = self._source_re.search(page.text)
+        if m:
+            params = ""
+            data = m.group(1)
+            log.debug("Source data: {0}".format(data))
+            if "location.hash.substring" in data:
+                log.debug("Removing hash substring addition")
+                data = re.sub(r"\s*\+\s*location.hash.substring\(\d+\)", "", data)
+                params = urlparse(self.url).fragment
+            data = self.js_to_json(data)
+            for stream in parse_json(data):
+                for s in HLSStream.parse_variant_playlist(self.session, stream['file'], params=params).items():
+                    yield s
+        else:
+            log.debug("No match for sources regex")
+
+
+__plugin__ = LRT


Test patch:
diff --git a/tests/test_plugin_lrt.py b/tests/test_plugin_lrt.py
new file mode 100644
index 00000000..c7d4476c
--- /dev/null
+++ b/tests/test_plugin_lrt.py
@@ -0,0 +1,24 @@
+import unittest
+
+from streamlink.plugins.lrt import LRT
+
+
+class TestPluginLRT(unittest.TestCase):
+    def test_can_handle_url(self):
+        should_match = [
+            "https://www.lrt.lt/mediateka/tiesiogiai/lrt-televizija",
+            "https://www.lrt.lt/mediateka/tiesiogiai/lrt-kultura",
+            "https://www.lrt.lt/mediateka/tiesiogiai/lrt-lituanica"
+            "https://www.lrt.lt/mediateka/irasas/1013694276/savanoriai-tures-galimybe-pamatyti-popieziu-is-arciau#wowzaplaystart=1511000&wowzaplayduration=168000"
+        ]
+        for url in should_match:
+            self.assertTrue(LRT.can_handle_url(url))
+
+    def test_can_handle_url_negative(self):
+        should_not_match = [
+            "https://www.lrt.lt",
+            "https://www.youtube.com",
+
+        ]
+        for url in should_not_match:
+            self.assertFalse(LRT.can_handle_url(url))