Repository: streamlink/streamlink

Issue:
plugin rerquest for mjunoon
https://www.mjunoon.tv/

streamlink https://www.mjunoon.tv/a-tv-live
[cli][info] streamlink is running as root! Be careful!
error: No plugin can handle URL: https://www.mjunoon.tv/a-tv-live



Discussion:
live streeams
https://www.mjunoon.tv/urdu-1-live

https://www.mjunoon.tv/filmazia-live

https://www.mjunoon.tv/aruj-live

and more vod stream

https://www.mjunoon.tv/watch/tonight-with-jasmeen-21june2018-kanwar-dilshad-amjad-shoaib-khawaja-fareed-u913yoexxyg

https://www.mjunoon.tv/watch/tax-aur-aap-ep-28-10-feb-2017-opnbtxuuzxu

anything else required lett me know
some details about the website, it looks **legal** to me.

> mjunoon: Powered by Convex Interactive ...
https://www.mjunoon.tv/about-us

> Watch licensed Live TV & Radio channels for Free.
https://play.google.com/store/apps/details?id=com.convex.mjunoon.TV&hl=en_US

> PEMRA (Pakistan Electronic Media Regulatory Authority)
Grants Mobile TV License to Convex Interactive
https://propakistani.pk/2016/04/01/pemra-grants-mobile-tv-license-to-convex-interactive/

yeah its hundred percent legal

Resolving patch:
diff --git a/src/streamlink/plugins/mjunoon.py b/src/streamlink/plugins/mjunoon.py
new file mode 100644
--- /dev/null
+++ b/src/streamlink/plugins/mjunoon.py
@@ -0,0 +1,34 @@
+import logging
+import re
+
+from streamlink.compat import urlparse, parse_qsl
+from streamlink.plugin import Plugin
+from streamlink.plugin.api.utils import itertags
+from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
+
+
+class Mjunoon(Plugin):
+    url_re = re.compile(r"""https?://(?:www.)?mjunoon.tv/""", re.VERBOSE)
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls.url_re.match(url) is not None
+
+    def _get_streams(self):
+        res = self.session.http.get(self.url)
+        for script in itertags(res.text, 'script'):
+            if script.attributes.get("id") == "playerScript":
+                log.debug("Found the playerScript script tag")
+                urlparts = urlparse(script.attributes.get("src"))
+                i = 0
+
+                for key, url in parse_qsl(urlparts.query):
+                    if key == "streamUrl":
+                        i += 1
+                        for s in HLSStream.parse_variant_playlist(self.session, url, params=dict(id=i), verify=False).items():
+                            yield s
+
+
+__plugin__ = Mjunoon


Test patch:
diff --git a/tests/test_plugin_mjunoon.py b/tests/test_plugin_mjunoon.py
new file mode 100644
--- /dev/null
+++ b/tests/test_plugin_mjunoon.py
@@ -0,0 +1,36 @@
+import unittest
+import requests_mock
+
+from streamlink import Streamlink
+from tests.mock import patch, Mock, ANY, call
+from streamlink.plugins.mjunoon import Mjunoon
+
+
+class TestPluginMixer(unittest.TestCase):
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(Mjunoon.can_handle_url('https://mjunoon.tv/news-live'))
+        self.assertTrue(Mjunoon.can_handle_url('http://mjunoon.tv/watch/some-long-vod-name23456'))
+        self.assertTrue(Mjunoon.can_handle_url('https://www.mjunoon.tv/other-live'))
+        self.assertTrue(Mjunoon.can_handle_url('https://www.mjunoon.tv/watch/something-else-2321'))
+
+    def test_can_handle_url_negative(self):
+        # shouldn't match
+        self.assertFalse(Mjunoon.can_handle_url('https://mjunoon.com'))
+
+    @patch('streamlink.plugins.mjunoon.HLSStream.parse_variant_playlist')
+    def test_get_streams(self, parse_variant_playlist):
+        session = Streamlink()
+        Mjunoon.bind(session, "test")
+        script_text = """
+        <script id="playerScript"  src="playerAssets/js/player.js?v=2.2&streamUrl=https://vod.mjunoon.tv:8181/live/41/41.m3u8&streamUrl=https://vod.mjunoon.tv:8181/live/17/17.m3u8"></script>
+        """
+        parse_variant_playlist.items.return_value = [("test", Mock())]
+        with requests_mock.Mocker() as rmock:
+            rmock.get("https://mjunoon.tv/news-live", text=script_text)
+            plugin = Mjunoon("https://mjunoon.tv/news-live")
+            _ = list(plugin.streams())
+            self.assertSequenceEqual(
+                [call(ANY, "https://vod.mjunoon.tv:8181/live/41/41.m3u8", params=dict(id=1), verify=False),
+                 call(ANY, "https://vod.mjunoon.tv:8181/live/17/17.m3u8", params=dict(id=2), verify=False)],
+                [parse_variant_playlist.mock_calls[0], parse_variant_playlist.mock_calls[3]])