Repository: streamlink/streamlink

Issue:
plugins.ustvnow: pluginmatcher URL update needed
### Checklist

- [X] This is a plugin issue and not a different kind of issue
- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)
- [X] [I have checked the list of open and recently closed plugin issues](https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22)
- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)

### Streamlink version

Latest build from the master branch

### Description

You need to replace the search template in ustvnow.py plugin with the one below.

```
@pluginmatcher(re.compile(                                                                                                                                     
    r"https?://(?:www\.)?ustvnow\.com/channel/live/(?P<chname>\w+)",                                                                                           
))
```
What is in the code now - does not work due to changes that have occurred on the site www.ustvnow.com

### Debug log

```text
The log cannot be retrieved because changes must be made to the template of the link it "serves"
```



Discussion:
Is this issue being worked on? Its been over half a year.
Yes, I use it exactly with the changes I made and published on GitHub... I can give you the log if you need it.

1 марта 2024, 04:32:14, от "MajinLugia" ***@***.***>:


Is this issue being worked on? Its been over half a year.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you authored the thread.Message ID: ***@***.***>

--=-2v/3N8OZEl8eGrYBGi6O
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: base64

PGh0bWw+PGJvZHk+PHNwYW4gc3R5bGU9ImRpc3BsYXk6YmxvY2s7IiBjbGFzcz0ieGZtXzExNzE5
NTM1Ij48ZGl2PjxzcGFuIHN0eWxlPSJmb250LWZhbWlseTpBcmlhbDtmb250LXNpemU6MTJwdDts
aW5lLWhlaWdodDoxNHB0OyI+WWVzLCBJIHVzZSBpdCBleGFjdGx5IHdpdGggdGhlIGNoYW5nZXMg
SSBtYWRlIGFuZCBwdWJsaXNoZWQgb24gR2l0SHViLi4uIEkgY2FuIGdpdmUgeW91IHRoZSBsb2cg
aWYgeW91IG5lZWQgaXQuIDwvc3Bhbj48L2Rpdj4NCjxkaXY+PGJyLz48L2Rpdj4NCjxkaXY+PGk+
PHNwYW4gc3R5bGU9ImZvbnQtc2l6ZToxMHB0O2xpbmUtaGVpZ2h0OjEycHQ7Ij48c3BhbiBzdHls
ZT0iZm9udC1mYW1pbHk6QXJpYWw7Ij4xINC80LDRgNGC0LAgMjAyNCwgMDQ6MzI6MTQsINC+0YIN
CiAgICAiTWFqaW5MdWdpYSIgJmx0Ozwvc3Bhbj48YSBocmVmPSJtYWlsdG86bm90aWZpY2F0aW9u
c0BnaXRodWIuY29tIiB0YXJnZXQ9Il9ibGFuayI+PHNwYW4gc3R5bGU9ImZvbnQtZmFtaWx5OkFy
aWFsOyI+bm90aWZpY2F0aW9uc0BnaXRodWIuY29tPC9zcGFuPjwvYT48c3BhbiBzdHlsZT0iZm9u
dC1mYW1pbHk6QXJpYWw7Ij4mZ3Q7Og0KPC9zcGFuPjwvc3Bhbj48L2k+PC9kaXY+DQo8ZGl2Pjxi
ci8+PC9kaXY+DQo8YmxvY2txdW90ZSBzdHlsZT0iYm9yZGVyLWxlZnQ6MXB4IHNvbGlkICNjY2Nj
Y2M7bWFyZ2luOjBweCAwcHggMHB4IDAuOGV4O3BhZGRpbmctbGVmdDoxZXg7Ij4NCjxkaXYgc3R5
bGU9ImRpc3BsYXk6YmxvY2s7Ij4NCjxkaXY+PC9kaXY+DQo8ZGl2PklzIHRoaXMgaXNzdWUgYmVp
bmcgd29ya2VkIG9uPyBJdHMgYmVlbiBvdmVyIGhhbGYgYSB5ZWFyLjwvZGl2Pg0KPGRpdj48c3Bh
biBzdHlsZT0iZm9udC1zaXplOnNtYWxsO2NvbG9yOiM2NjY7Ij7igJQ8YnIvPlJlcGx5IHRvIHRo
aXMgZW1haWwgZGlyZWN0bHksIDxhIGhyZWY9Imh0dHBzOi8vZ2l0aHViLmNvbS9zdHJlYW1saW5r
L3N0cmVhbWxpbmsvaXNzdWVzLzU0MzEjaXNzdWVjb21tZW50LTE5NzIzNDc3ODEiIHRhcmdldD0i
X2JsYW5rIiByZWw9Im5vcmVmZXJyZXIgbm9vcGVuZXIiPnZpZXcgaXQgb24gR2l0SHViPC9hPiwg
b3IgPGEgaHJlZj0iaHR0cHM6Ly9naXRodWIuY29tL25vdGlmaWNhdGlvbnMvdW5zdWJzY3JpYmUt
YXV0aC9BRU1UQUlMRUlRU1NBQUJCTzZJSEVOM1lWN1NDM0FWQ05GU002QUFBQUFBMkZMVzdCV1ZI
STJEU01WUVdJWDNMTVY0M09TTFRPTjJXS1EzUE5WV1dLM1RVSE1ZVFNOWlNHTTJET05aWUdFIiB0
YXJnZXQ9Il9ibGFuayIgcmVsPSJub3JlZmVycmVyIG5vb3BlbmVyIj51bnN1YnNjcmliZTwvYT4u
PGJyLz5Zb3UgYXJlIHJlY2VpdmluZyB0aGlzIGJlY2F1c2UgeW91IGF1dGhvcmVkIHRoZSB0aHJl
YWQuPGltZyBzcmM9Imh0dHBzOi8vZ2l0aHViLmNvbS9ub3RpZmljYXRpb25zL2JlYWNvbi9BRU1U
QUlPSEwzV0E2NlEyVlNXVVRETFlWN1NDM0E1Q05GU002QUFBQUFBMkZMVzdCV1dHRzMzTk5WU1c0
NUM3T1I0WEFaTk1KRlpYRzVMRklOWFcyM0xGTloyS1VZM1BOVldXSzNUVUw1VVdKVFRWUjZSWUsu
Z2lmIiBoZWlnaHQ9IjEiIHdpZHRoPSIxIiBhbHQ9IiIvPjwvc3Bhbj48c3BhbiBzdHlsZT0iZm9u
dC1zaXplOjA7Y29sb3I6dHJhbnNwYXJlbnQ7ZGlzcGxheTpub25lO292ZXJmbG93OmhpZGRlbjt3
aWR0aDowO2hlaWdodDowO21heC13aWR0aDowO21heC1oZWlnaHQ6MDsiPk1lc3NhZ2UgSUQ6ICZs
dDtzdHJlYW1saW5rL3N0cmVhbWxpbmsvaXNzdWVzLzU0MzEvMTk3MjM0Nzc4MUBnaXRodWIuY29t
Jmd0Ozwvc3Bhbj48L2Rpdj4NCjwvZGl2Pg0KPC9ibG9ja3F1b3RlPjwvc3Bhbj48L2JvZHk+PC9o
dG1sPg0K

--=-2v/3N8OZEl8eGrYBGi6O--

[streamlinkproxy][info] Request from: 127.0.0.1 - GET /https://www.ustvnow.com/channel/live/best_ever_tv?ustvnow-username=XXXX@XXXt&ustvnow-password=XXXX HTTP/1.1 200 -
[plugins.ustvnow][debug] Trying to login...
[plugins.ustvnow][debug] Getting new session token
[plugins.ustvnow][debug] New token: 5f175fe2-5b3c-42a5-8b63-18d9ad45506a
[utils.l10n][debug] Language code: en_GB
[streamlinkproxy][debug] USTVNOW plugin found sreams: ['216p', '360p', '540p', '720p', '1080p']
[stream.hls][debug] Reloading playlist
[stream.hls][debug] First Sequence: 3797465; Last Sequence: 3797470
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 3797468; End Sequence: None
[stream.hls][debug] Adding segment 3797468 to queue
[stream.hls][debug] Adding segment 3797469 to queue
[stream.hls][debug] Adding segment 3797470 to queue
[stream.hls][debug] Writing segment 3797468 to output
[stream.hls][debug] Segment 3797468 complete
[stream.hls][debug] Writing segment 3797469 to output
[stream.hls][debug] Segment 3797469 complete
[stream.hls][debug] Writing segment 3797470 to output
[stream.hls][debug] Segment 3797470 complete
[stream.hls][debug] Reloading playlist
If you want this fixed, then please open a pull request with the necessary changes and provide a full debug log without using third party tools, so we can see that you're running Streamlink from the commit of the pull request. This site requires a paid account, so this obviously won't fix itself.

- https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#pull-requests
- https://streamlink.github.io/developing.html



Patch:
diff --git a/src/streamlink/plugins/ustvnow.py b/src/streamlink/plugins/ustvnow.py
index b14e8005f05..0b4ea1848cd 100644
--- a/src/streamlink/plugins/ustvnow.py
+++ b/src/streamlink/plugins/ustvnow.py
@@ -21,7 +21,7 @@
 
 
 @pluginmatcher(re.compile(
-    r"https?://(?:www\.)?ustvnow\.com/live/(?P<scode>\w+)/-(?P<id>\d+)",
+    r"https?://(?:www\.)?ustvnow\.com/channel/live/(?P<chname>\w+)",
 ))
 @pluginargument(
     "username",
@@ -96,11 +96,6 @@ def box_id(self):
         return self.cache.get("box_id")
 
     def get_token(self):
-        """
-        Get the token for USTVNow
-        :return: a valid token
-        """
-
         if not self._token:
             log.debug("Getting new session token")
             res = self.session.http.get(self._token_url, params={
@@ -114,13 +109,13 @@ def get_token(self):
             })
 
             data = res.json()
-            if data["status"]:
-                self._token = data["response"]["sessionId"]
-                log.debug("New token: {}".format(self._token))
-            else:
+            if not data["status"]:
                 log.error("Token acquisition failed: {details} ({detail})".format(**data["error"]))
                 raise PluginError("could not obtain token")
 
+            self._token = data["response"]["sessionId"]
+            log.debug(f"New token: {self._token}")
+
         return self._token
 
     def api_request(self, path, data, metadata=None):
@@ -153,21 +148,20 @@ def login(self, username, password):
         return resp["data"]["status"]
 
     def _get_streams(self):
-        """
-        Finds the streams from ustvnow.com.
-        """
-        if self.login(self.get_option("username"), self.get_option("password")):
-            path = urlparse(self.url).path.strip("/")
-            resp = self.api_request("send", {"path": path}, {"request": "page/stream"})
-            if resp["data"]["status"]:
-                for stream in resp["data"]["response"]["streams"]:
-                    if stream["keys"]["licenseKey"]:
-                        log.warning("Stream possibly protected by DRM")
-                    yield from HLSStream.parse_variant_playlist(self.session, stream["url"]).items()
-            else:
-                log.error("Could not find any streams: {code}: {message}".format(**resp["data"]["error"]))
-        else:
+        if not self.login(self.get_option("username"), self.get_option("password")):
             log.error("Failed to login, check username and password")
+            return
+
+        path = urlparse(self.url).path.strip("/")
+        resp = self.api_request("send", {"path": path}, {"request": "page/stream"})
+        if not resp["data"]["status"]:
+            log.error("Could not find any streams: {code}: {message}".format(**resp["data"]["error"]))
+            return
+
+        for stream in resp["data"]["response"]["streams"]:
+            if stream["keys"]["licenseKey"]:
+                log.warning("Stream possibly protected by DRM")
+            yield from HLSStream.parse_variant_playlist(self.session, stream["url"]).items()
 
 
 __plugin__ = USTVNow


Test patch:
diff --git a/tests/plugins/test_ustvnow.py b/tests/plugins/test_ustvnow.py
index 7a3d8a9875d..626a2dc7fd3 100644
--- a/tests/plugins/test_ustvnow.py
+++ b/tests/plugins/test_ustvnow.py
@@ -6,7 +6,7 @@ class TestPluginCanHandleUrlUSTVNow(PluginCanHandleUrl):
     __plugin__ = USTVNow
 
     should_match = [
-        "http://www.ustvnow.com/live/foo/-65",
+        "https://www.ustvnow.com/channel/live/cbs",
     ]