Repository: streamlink/streamlink
Pull request #1782 (2018-06-12 16:38:28)

plugins.cnews : separate CNEWS data from CanalPlus plugin.
Changes in the CanalPlus plugin would be too ugly and complex, so I split plugin and move the CNEWS part in a new plugin.

BZHDeveloper: @beardypig : fixed :+1: 
codecov[bot]: # [Codecov](https://codecov.io/gh/streamlink/streamlink/pull/1782?src=pr&el=h1) Report
> Merging [#1782](https://codecov.io/gh/streamlink/streamlink/pull/1782?src=pr&el=desc) into [master](https://codecov.io/gh/streamlink/streamlink/commit/3136f9688d555bc1c66692ea35e81f21cb4df65f?src=pr&el=desc) will **increase** coverage by `0.02%`.
> The diff coverage is `70.58%`.


```diff
@@            Coverage Diff             @@
##           master    #1782      +/-   ##
==========================================
+ Coverage   49.95%   49.97%   +0.02%     
==========================================
  Files         232      233       +1     
  Lines       13843    13860      +17     
==========================================
+ Hits         6915     6927      +12     
- Misses       6928     6933       +5
```

beardypig: @BZHDeveloper can you rebase with master? 
BZHDeveloper: done
beardypig: @gravyboat this is good to merge, if you wanna do the honours. 

Patch:
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index a122186d..e567d934 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -43,8 +43,7 @@ btsports                sport.bt.com         Yes   Yes   Requires subscription a
 btv                     btv.bg               Yes   No    Requires login, and geo-restricted to Bulgaria.
 cam4                    cam4.com             Yes   No
 camsoda                 camsoda.com          Yes   No
-canalplus               - mycanal.fr         No    Yes   Streams may be geo-restricted to France.
-                        - cnews.fr
+canalplus               mycanal.fr           No    Yes   Streams may be geo-restricted to France.
 cdnbg                   - tv.bnt.bg          Yes   No    Streams may be geo-restricted to Bulgaria.
                         - bgonair.bg
                         - kanal3.bg
@@ -57,6 +56,7 @@ cinergroup              - showtv.com.tr      Yes   No
                         - showmax.com.tr
                         - showturk.com.tr
                         - bloomberght.com
+cnews                   cnews.fr             Yes   Yes
 crunchyroll             crunchyroll.com      --    Yes
 cybergame               cybergame.tv         Yes   Yes
 dailymotion             dailymotion.com      Yes   Yes
diff --git a/src/streamlink/plugins/canalplus.py b/src/streamlink/plugins/canalplus.py
index b0c4bb23..8279ce0b 100644
--- a/src/streamlink/plugins/canalplus.py
+++ b/src/streamlink/plugins/canalplus.py
@@ -13,10 +13,9 @@ class CanalPlus(Plugin):
     SECRET = 'pqzerjlsmdkjfoiuerhsdlfknaes'
 
     _url_re = re.compile(r'''
-        (https|http)://
+        https?://
         (
-            www.mycanal.fr/(.*)/(.*)/p/(?P<video_id>[0-9]+) |
-            www\.cnews\.fr/.+
+            www.mycanal.fr/(.*)/(.*)/p/(?P<video_id>[0-9]+)
         )
 ''', re.VERBOSE)
     _video_id_re = re.compile(r'(\bdata-video="|<meta property="og:video" content=".+?&videoId=)(?P<video_id>[0-9]+)"')
diff --git a/src/streamlink/plugins/cnews.py b/src/streamlink/plugins/cnews.py
new file mode 100644
index 00000000..824d4d3f
--- /dev/null
+++ b/src/streamlink/plugins/cnews.py
@@ -0,0 +1,24 @@
+import re
+
+from streamlink.plugin import Plugin
+from streamlink.plugin.api import http, useragents
+
+
+class CNEWS(Plugin):
+    _url_re = re.compile(r'https?://www.cnews.fr/[^ ]+')
+    _embed_video_url_re = re.compile(r'class="dm-video-embed_video" src="(?P<dm_url>.*)"')
+    _embed_live_url_re = re.compile(r'class="wrapper-live-player main-live-player"><iframe src="(?P<dm_url>.*)"')
+
+    @classmethod
+    def can_handle_url(cls, url):
+        return cls._url_re.match(url)
+
+    def _get_streams(self):
+        # Retrieve URL page and search for Dailymotion URL
+        res = http.get(self.url, headers={'User-Agent': useragents.CHROME})
+        match = self._embed_live_url_re.search(res.text) or self._embed_video_url_re.search(res.text)
+        if match is not None:
+            return self.session.streams(match.group('dm_url'))
+
+
+__plugin__ = CNEWS


Test patch:
diff --git a/tests/test_plugin_canalplus.py b/tests/test_plugin_canalplus.py
index 62daf272..30646c58 100644
--- a/tests/test_plugin_canalplus.py
+++ b/tests/test_plugin_canalplus.py
@@ -10,10 +10,10 @@ class TestPluginCanalPlus(unittest.TestCase):
         self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/sport/infosport-laurey-et-claudia/p/1473752"))
         self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/docus-infos/ses-debuts-a-madrid-extrait-le-k-benzema/p/1469050"))
         self.assertTrue(CanalPlus.can_handle_url("https://www.mycanal.fr/d8-docs-mags/au-revoir-johnny-hallyday-le-doc/p/1473054"))
-        self.assertTrue(CanalPlus.can_handle_url("http://www.cnews.fr/direct"))
-        self.assertTrue(CanalPlus.can_handle_url("http://www.cnews.fr/politique/video/des-electeurs-toujours-autant-indecis-174769"))
-        self.assertTrue(CanalPlus.can_handle_url("http://www.cnews.fr/magazines/plus-de-recul/de-recul-du-14042017-174594"))
         # shouldn't match
+        self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/direct"))
+        self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/politique/video/des-electeurs-toujours-autant-indecis-174769"))
+        self.assertFalse(CanalPlus.can_handle_url("http://www.cnews.fr/magazines/plus-de-recul/de-recul-du-14042017-174594"))
         self.assertFalse(CanalPlus.can_handle_url("http://www.canalplus.fr/"))
         self.assertFalse(CanalPlus.can_handle_url("http://www.c8.fr/"))
         self.assertFalse(CanalPlus.can_handle_url("http://replay.c8.fr/"))
diff --git a/tests/test_plugin_cnews.py b/tests/test_plugin_cnews.py
new file mode 100644
index 00000000..c7bdfd9f
--- /dev/null
+++ b/tests/test_plugin_cnews.py
@@ -0,0 +1,16 @@
+import unittest
+
+from streamlink.plugins.cnews import CNEWS
+
+
+class TestPluginCNEWS(unittest.TestCase):
+    def test_can_handle_url(self):
+        # should match
+        self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/le-direct"))
+        self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/direct"))
+        self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/emission/2018-06-12/meteo-du-12062018-784730"))
+        self.assertTrue(CNEWS.can_handle_url("http://www.cnews.fr/emission/2018-06-12/le-journal-des-faits-divers-du-12062018-784704"))
+        # shouldn't match
+        self.assertFalse(CNEWS.can_handle_url("http://www.cnews.fr/"))
+        self.assertFalse(CNEWS.can_handle_url("http://www.tvcatchup.com/"))
+        self.assertFalse(CNEWS.can_handle_url("http://www.youtube.com/"))