Repository: streamlink/streamlink

Issue:
Now News Live (News and Live channel)
## Plugin Request

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a plugin request and I have read the contribution guidelines and plugin request requirements.


### Description

<!-- Explain the plugin and site as clearly as you can. What is the site about? Who runs it? What content does it provide? What value does it bring to Streamlink? Etc. -->
One of a local television station from Hong Kong which currently only accessible via Internet streaming or paid cable subscription. Now News is one of a few disinterested news channel which provide fare perspective reports compared to major aired television in Hong Kong.

### Example stream URLs

<!-- Example URLs for streams are required. Plugin requests which do not have example URLs will be closed. -->

1. https://news.now.com/home/live331a
2. https://news.now.com/home/live


### Additional comments, screenshots, etc.
![chrome_2019-08-18_20-27-07](https://user-images.githubusercontent.com/771955/63224427-92c4d700-c1f6-11e9-8010-500d19f97187.png)


[Love Streamlink? Please consider supporting our collective. Thanks!](https://opencollective.com/streamlink/donate)


Comments:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2e239ac0..d024fba0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,97 @@
 # Changelog
 
+## streamlink 1.2.0 (2019-08-18)
+
+Here are the changes for this month's release
+
+- Multiple plugin fixes
+- Fixed single hyphen params at the beginning of --player-args (#2333)
+- `--http-proxy` will set the default value of `--https-proxy` to same as `--http-proxy`. (#2536)
+- DASH Streams will handle headers correctly (#2545)
+- the timestamp for FFMPEGMuxer streams will start with zero (#2559)
+
+
+```text
+Davi Guimarães <davi.guimaraesleite@gmail.com> (1):
+      plugins.cubetv: base url changes (#2430)
+
+Forrest <gravyboat@users.noreply.github.com> (1):
+      Add a sponsor button (#2478)
+
+Jiting <jiting@jtcat.com> (1):
+      plugin.youtube: bug fix for YouTube live streams check
+
+Juan Ramirez <jramirez@encompass.tv> (2):
+      Invalid use of console.logger in CLI
+      Too many arguments for logging format string
+
+Mohamed El Morabity <melmorabity@fedoraproject.org> (9):
+      plugins.vimeo: new plugin for Vimeo streams
+      plugins.vimeo: add subtitle support for vimeo plugin
+      plugins.vimeo: fix alphabetical order in plugin matrix
+      Use class parameter instead of class name in class method
+      [plugins.bfmtv] Fix player regex
+      [plugins.idf1] Update for new website layout
+      plugins.gulli: enable HTTPS support
+      plugins.gulli: fix live stream fetching
+      plugins.tvrplus: fix for new website layout
+
+Mohamed El Morabity <melmorabity@users.noreply.github.com> (1):
+      plugins.clubbingtv: new plugin for Clubbing TV website (#2569)
+
+Viktor Kálmán <kviktor@users.noreply.github.com> (1):
+      plugins.mediaklikk: update broken plugin (#2401)
+
+Vladimir Stavrinov <vstavrinov@gmail.com> (2):
+      plugins.live_russia_tv: adjust to site changes (#2523)
+      plugins.oneplusone: fix site changes (#2425)
+
+YuuichiMizuoka <32476209+YuuichiMizuoka@users.noreply.github.com> (1):
+      add login posibility for pixiv using sessionid and devicetoken
+
+aqxa1 <asheldon55@gmail.com> (1):
+      Handle keyboard interrupts in can_handle_url checks (#2318)
+
+back-to <backto@protonmail.ch> (12):
+      cli.argparser: Fix single hyphen params at the beginning of --player-args
+      plugins.reuters: New Plugin
+      plugins: Removed rte and tvcatchup
+      utils.__init__: remove cElementTree, it's just an alias for ElementTree
+      plugins.teamliquid: New domain, fix stream_weight
+      plugins.vimeo: Fixed DASH Livestreams
+      plugin.api.useragents: update CHROME and FIREFOX User-Agent
+      ffmpegmux: use -start_at_zero with -copyts
+      plugins.youtube: fixed reason msg, updated _url_re
+      plugins.TV1Channel: Fixed new livestream iframe
+      plugins.npo: removed due to DRM
+      plugins.lrt: fixed livestreams
+
+bastimeyer <mail@bastimeyer.de> (1):
+      plugins.welt: fix plugin
+
+beardypig <beardypig@protonmail.com> (13):
+      plugins.bbciplayer: small change to where the VPID is extracted from (#2376)
+      plugins.goodgame: fix for debug logging error
+      plugins.cdnbg: fix for bstv url
+      plugins.ustvnow: updated to handle new auth, and site design
+      plugin.schoolism: bug fix for videos with subtitles (#2524)
+      stream.dash: use the stream args in the writer and worker
+      session: default https-proxy to the same as http-proxy, can be overridden
+      plugins.beattv: partial fix for the be-at.tv streams
+      tests: test the behaviour of setting http-proxy and https-proxy
+      plugins.twitch: support for different clips URL
+      plugins.wwenetwork: support for new site
+      plugins.ustreamtv: add support for proxying WebSocket connections
+      plugins.wwenetwork: update for small page/api change
+
+skulblakka <pascal.romahn@mailbox.org> (1):
+      plugins.DLive: New Plugin for dlive.tv (#2419)
+
+ssaqua <ssaqua@users.noreply.github.com> (1):
+      plugins.linelive: new plugin for LINE LIVE (live.line.me) (#2574)
+```
+
+
 ## streamlink 1.1.1 (2019-04-02)
 
 This is just a small patch release which fixes a build/deploy issue with the new special wheels for Windows on PyPI. (#2392)
diff --git a/docs/plugin_matrix.rst b/docs/plugin_matrix.rst
index 802f5a90..c69c7f37 100644
--- a/docs/plugin_matrix.rst
+++ b/docs/plugin_matrix.rst
@@ -125,6 +125,7 @@ nbc                     nbc.com              No    Yes   Streams are geo-restric
 nbcsports               nbcsports.com        No    Yes   Streams maybe be geo-restricted to USA. Authentication is not supported.
 nhkworld                nhk.or.jp/nhkworld   Yes   No
 nos                     nos.nl               Yes   Yes   Streams may be geo-restricted to Netherlands.
+nownews                 news.now.com         Yes   No
 nrk                     - tv.nrk.no          Yes   Yes   Streams may be geo-restricted to Norway.
                         - radio.nrk.no
 ntv                     ntv.ru               Yes   No
diff --git a/src/streamlink/plugins/bbciplayer.py b/src/streamlink/plugins/bbciplayer.py
index a4c4f7da..68ccef88 100644
--- a/src/streamlink/plugins/bbciplayer.py
+++ b/src/streamlink/plugins/bbciplayer.py
@@ -34,11 +34,8 @@ class BBCiPlayer(Plugin):
     tvip_re = re.compile(r'channel"\s*:\s*{\s*"id"\s*:\s*"(\w+?)"')
     tvip_master_re = re.compile(r'event_master_brand=(\w+?)&')
     account_locals_re = re.compile(r'window.bbcAccount.locals\s*=\s*({.*?});')
-    swf_url = "http://emp.bbci.co.uk/emp/SMPf/1.18.3/StandardMediaPlayerChromelessFlash.swf"
-    hash = base64.b64decode(
-        b"N2RmZjc2NzFkMGM2OTdmZWRiMWQ5MDVkOWExMjE3MTk5MzhiOTJiZg==")
-    api_url = ("http://open.live.bbc.co.uk/mediaselector/6/select/"
-               "version/2.0/mediaset/{platform}/vpid/{vpid}/format/json/atk/{vpid_hash}/asn/1/")
+    hash = base64.b64decode(b"N2RmZjc2NzFkMGM2OTdmZWRiMWQ5MDVkOWExMjE3MTk5MzhiOTJiZg==")
+    api_url = "https://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/{platform}/vpid/{vpid}/format/json/atk/{vpid_hash}/asn/1/"
     platforms = ("pc", "iptv-all")
     session_url = "https://session.bbc.com/session"
     auth_url = "https://account.bbc.com/signin"
diff --git a/src/streamlink/plugins/nownews.py b/src/streamlink/plugins/nownews.py
new file mode 100644
index 00000000..02bd76de
--- /dev/null
+++ b/src/streamlink/plugins/nownews.py
@@ -0,0 +1,49 @@
+import logging
+import re
+import json
+
+from streamlink.plugin import Plugin
+from streamlink.stream import HLSStream
+
+log = logging.getLogger(__name__)
+
+
+class NowNews(Plugin):
+    _url_re = re.compile(r"https?://news.now.com/home/live")
+    epg_re = re.compile(r'''epg.getEPG\("(\d+)"\);''')
+    api_url = "https://hkt-mobile-api.nowtv.now.com/09/1/getLiveURL"
+    backup_332_api = "https://d7lz7jwg8uwgn.cloudfront.net/apps_resource/news/live.json"
+    backup_332_stream = "https://d3i3yn6xwv1jpw.cloudfront.net/live/now332/playlist.m3u8"
+
+    @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)
+        m = self.epg_re.search(res.text)
+        channel_id = m and m.group(1)
+        if channel_id:
+            log.debug("Channel ID: {0}".format(channel_id))
+
+            if channel_id == "332":
+                # there is a special backup stream for channel 332
+                bk_res = self.session.http.get(self.backup_332_api)
+                bk_data = self.session.http.json(bk_res)
+                if bk_data and bk_data["backup"]:
+                    log.info("Using backup stream for channel 332")
+                    return HLSStream.parse_variant_playlist(self.session, self.backup_332_stream)
+
+            api_res = self.session.http.post(self.api_url,
+                                             headers={"Content-Type": 'application/json'},
+                                             data=json.dumps(dict(channelno=channel_id,
+                                                                  mode="prod",
+                                                                  audioCode="",
+                                                                  format="HLS",
+                                                                  callerReferenceNo="20140702122500")))
+            data = self.session.http.json(api_res)
+            for stream_url in data.get("asset", {}).get("hls", {}).get("adaptive", []):
+                return HLSStream.parse_variant_playlist(self.session, stream_url)
+
+
+__plugin__ = NowNews


Test patch:
diff --git a/tests/plugins/test_nownews.py b/tests/plugins/test_nownews.py
new file mode 100644
index 00000000..583aa0eb
--- /dev/null
+++ b/tests/plugins/test_nownews.py
@@ -0,0 +1,27 @@
+import unittest
+
+import pytest
+
+from streamlink.plugins.nownews import NowNews
+
+
+class TestPluginNowNews:
+    valid_urls = [
+        ("https://news.now.com/home/live",),
+        ("http://news.now.com/home/live",),
+        ("https://news.now.com/home/live331a",),
+        ("http://news.now.com/home/live331a",)
+    ]
+    invalid_urls = [
+        ("https://news.now.com/home/local",),
+        ("http://media.now.com.hk/",),
+        ("https://www.youtube.com",)
+    ]
+
+    @pytest.mark.parametrize(["url"], valid_urls)
+    def test_can_handle_url(self, url):
+        assert NowNews.can_handle_url(url), "url should be handled"
+
+    @pytest.mark.parametrize(["url"], invalid_urls)
+    def test_can_handle_url_negative(self, url):
+        assert not NowNews.can_handle_url(url), "url should not be handled"