Repository: streamlink/streamlink

Issue:
[bug] CDNBG - multiple issues
## Bug Report
1. BITelevision should be removed from the plugin and/or wiki/info pages, as it no longer exists.
2. Inlife.bg shouldn't be listed as supported under CDNbg.
3. Tvbulgare.bg should be listed as supported in inlife.bg's place (latter shares the former's stream)
4. Mu-vi.tv gives an error.
5. CDNBG should cover VTK - the national military channel
6. Kanal3's livestream is not found.
7. CDNBG should cover Cherno More - the regional channel for Varna, Bulgaria.

### Reproduction steps / Explicit stream URLs to test
1. https://bitelevision.com/ is not a thing anymore.
2. Inlife.bg can't be opened and shouldn't be listed - it is a 'media partner' that restreams https://tvbulgare.bg/, which could be put in as a replacement for it.
3. https://tvbulgare.bg/ - No playable streams found.
4. http://mu-vi.tv/LiveStreams/pages/Live.aspx - Error: Unable to open URL.
5. https://www.armymedia.bg/
6. https://kanal3.bg/live
7. https://www.chernomore.bg/


Discussion:
> gives an error

post a debug log for each of them, as the **plugin issue** template asks you to do
@bastimeyer My bad, here are the logs:
1. https://hastebin.com/oleticofab.md
2. https://hastebin.com/oxosufawad.md
3. https://hastebin.com/piwugiroto.md
4. https://hastebin.com/hotisuqoxu.md
5. https://hastebin.com/inikusovuq.md
6. https://hastebin.com/duwibiyapi.md
7. https://hastebin.com/equyidaloq.md

Edit: Added 6 & 7.
Inlife.bg, tvbulgare.bg and kanal3 are on cdn.netbadgers.com now, so I assume they have a static URL like the other channels in those other issues :) 
I cannot get http://mu-vi.tv/LiveStreams/pages/Live.aspx to work in my browser, does it work for you? 

Resolving patch:
diff --git a/src/streamlink/plugins/cdnbg.py b/src/streamlink/plugins/cdnbg.py
--- a/src/streamlink/plugins/cdnbg.py
+++ b/src/streamlink/plugins/cdnbg.py
@@ -15,16 +15,15 @@ class CDNBG(Plugin):
     url_re = re.compile(r"""
         https?://(?:www\.)?(?:
             tv\.bnt\.bg/\w+(?:/\w+)?|
-            bitelevision\.com/live|
             nova\.bg/live|
-            kanal3\.bg/live|
             bgonair\.bg/tvonline|
-            inlife\.bg|
             mmtvmusic\.com/live|
             mu-vi\.tv/LiveStreams/pages/Live\.aspx|
-            videochanel\.bstv\.bg|
             live\.bstv\.bg|
-            bloombergtv.bg/video
+            bloombergtv.bg/video|
+            armymedia.bg|
+            chernomore.bg|
+            i.cdn.bg/live/
         )/?
     """, re.VERBOSE)
     iframe_re = re.compile(r"iframe .*?src=\"((?:https?(?::|&#58;))?//(?:\w+\.)?cdn.bg/live[^\"]+)\"", re.DOTALL)
@@ -44,23 +43,26 @@ class CDNBG(Plugin):
     def can_handle_url(cls, url):
         return cls.url_re.match(url) is not None
 
-    def find_iframe(self, res):
-        p = urlparse(self.url)
-        for url in self.iframe_re.findall(res.text):
-            if "googletagmanager" not in url:
-                url = url.replace("&#58;", ":")
-                if url.startswith("//"):
-                    return "{0}:{1}".format(p.scheme, url)
+    def find_iframe(self, url):
+        self.session.http.headers.update({"User-Agent": useragents.CHROME})
+        res = self.session.http.get(self.url)
+        p = urlparse(url)
+        for iframe_url in self.iframe_re.findall(res.text):
+            if "googletagmanager" not in iframe_url:
+                log.debug("Found iframe: {0}", iframe_url)
+                iframe_url = iframe_url.replace("&#58;", ":")
+                if iframe_url.startswith("//"):
+                    return "{0}:{1}".format(p.scheme, iframe_url)
                 else:
-                    return url
+                    return iframe_url
 
     def _get_streams(self):
-        self.session.http.headers.update({"User-Agent": useragents.CHROME})
-        res = self.session.http.get(self.url)
-        iframe_url = self.find_iframe(res)
+        if "i.cdn.bg/live/" in self.url:
+            iframe_url = self.url
+        else:
+            iframe_url = self.find_iframe(self.url)
 
         if iframe_url:
-            log.debug("Found iframe: {0}", iframe_url)
             res = self.session.http.get(iframe_url, headers={"Referer": self.url})
             stream_url = update_scheme(self.url, self.stream_schema.validate(res.text))
             log.warning("SSL Verification disabled.")


Test patch:
diff --git a/tests/plugins/test_cdnbg.py b/tests/plugins/test_cdnbg.py
--- a/tests/plugins/test_cdnbg.py
+++ b/tests/plugins/test_cdnbg.py
@@ -1,32 +1,40 @@
-import unittest
+import pytest
 
 from streamlink.plugins.cdnbg import CDNBG
 
+valid_urls = [
+    ("http://bgonair.bg/tvonline",),
+    ("http://bgonair.bg/tvonline/",),
+    ("http://www.nova.bg/live",),
+    ("http://nova.bg/live",),
+    ("http://tv.bnt.bg/bnt1",),
+    ("http://tv.bnt.bg/bnt2",),
+    ("http://tv.bnt.bg/bnt3",),
+    ("http://tv.bnt.bg/bnt4",),
+    ("https://mmtvmusic.com/live/",),
+    ("http://mu-vi.tv/LiveStreams/pages/Live.aspx",),
+    ("http://live.bstv.bg/",),
+    ("https://www.bloombergtv.bg/video",),
+    ("https://i.cdn.bg/live/xfr3453g0d",)
 
-class TestPluginCDNBG(unittest.TestCase):
-    def test_can_handle_url(self):
-        # should match
-        self.assertTrue(CDNBG.can_handle_url("http://bgonair.bg/tvonline"))
-        self.assertTrue(CDNBG.can_handle_url("http://bgonair.bg/tvonline/"))
-        self.assertTrue(CDNBG.can_handle_url("http://bitelevision.com/live"))
-        self.assertTrue(CDNBG.can_handle_url("http://www.kanal3.bg/live"))
-        self.assertTrue(CDNBG.can_handle_url("http://www.nova.bg/live"))
-        self.assertTrue(CDNBG.can_handle_url("http://nova.bg/live"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bntworld/"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt1/hd/"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt1/hd"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt1/16x9/"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt1/16x9"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt2/16x9/"))
-        self.assertTrue(CDNBG.can_handle_url("http://tv.bnt.bg/bnt2/16x9"))
-        self.assertTrue(CDNBG.can_handle_url("http://inlife.bg/"))
-        self.assertTrue(CDNBG.can_handle_url("https://mmtvmusic.com/live/"))
-        self.assertTrue(CDNBG.can_handle_url("http://mu-vi.tv/LiveStreams/pages/Live.aspx"))
-        self.assertTrue(CDNBG.can_handle_url("http://videochanel.bstv.bg/"))
-        self.assertTrue(CDNBG.can_handle_url("http://live.bstv.bg/"))
-        self.assertTrue(CDNBG.can_handle_url("https://www.bloombergtv.bg/video"))
+]
+invalid_urls = [
+    ("http://www.tvcatchup.com/",),
+    ("http://www.youtube.com/",),
+    ("https://www.tvevropa.com",),
+    ("http://www.kanal3.bg/live",),
+    ("http://inlife.bg/",),
+    ("http://videochanel.bstv.bg",),
+    ("http://video.bstv.bg/",),
+    ("http://bitelevision.com/live",)
+]
 
-        # shouldn't match
-        self.assertFalse(CDNBG.can_handle_url("http://www.tvcatchup.com/"))
-        self.assertFalse(CDNBG.can_handle_url("http://www.youtube.com/"))
-        self.assertFalse(CDNBG.can_handle_url("https://www.tvevropa.com"))
+
+@pytest.mark.parametrize(["url"], valid_urls)
+def test_can_handle_url(url):
+    assert CDNBG.can_handle_url(url), "url should be handled"
+
+
+@pytest.mark.parametrize(["url"], invalid_urls)
+def test_can_handle_url_negative(url):
+    assert not CDNBG.can_handle_url(url), "url should not be handled"