Repository: streamlink/streamlink

Issue:
BT sports plugin does not find playable streams
<!--
Thanks for reporting a plugin issue!
USE THE TEMPLATE. Otherwise your plugin issue may be rejected.

First, see the contribution guidelines:
https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink

Also check the list of open and closed plugin issues:
https://github.com/streamlink/streamlink/issues?q=is%3Aissue+label%3A%22plugin+issue%22

Please see the text preview to avoid unnecessary formatting errors.
-->


## Plugin Issue

<!-- Replace [ ] with [x] in order to check the box -->
- [x] This is a plugin issue and I have read the contribution guidelines.


### Description

<!-- Explain the plugin issue as thoroughly as you can. -->
The plugin doesn't find any playable streams.

### Reproduction steps / Explicit stream URLs to test

<!-- How can we reproduce this? Please note the exact steps below using the list format supplied. If you need more steps please add them. -->

1. https://sport.bt.com/btsportplayer/live-streaming-01363980987389?leId=1364293056880
2. https://sport.bt.com/btsportplayer/live-streaming-01363980987389?leId=1364293057384
3. ...


### Log output

<!--
TEXT LOG OUTPUT IS REQUIRED for a plugin issue!
Use the `--loglevel debug` parameter and avoid using parameters which suppress log output.
https://streamlink.github.io/cli.html#cmdoption-l

Make sure to **remove usernames and passwords**
You can copy the output to https://gist.github.com/ or paste it below.
-->

```
C:\Users\>streamlink --btsports-email EMAIL --btsports-password PASSWORD https://sport.bt.co
m/btsportplayer/live-streaming-01363980987389?leId=1364293057384 --loglevel debug
[cli][debug] OS:         Windows 10
[cli][debug] Python:     3.5.2
[cli][debug] Streamlink: 0.14.2
[cli][debug] Requests(2.19.1), Socks(1.6.7), Websocket(0.48.0)
[cli][info] Found matching plugin btsports for URL https://sport.bt.com/btsportplayer/live-streaming-01363980987389?leId
=1364293057384
[cli][debug] Plugin specific arguments:
[cli][debug]  --btsports-email=........@tiscali.co.uk (email)
[cli][debug]  --btsports-password=******** (password)
[plugin.btsports][debug] Logging in as ..........@tiscali.co.uk
[plugin.btsports][debug] Redirected to: https://home.bt.com/s/assets/pages/login-interstitial.html?TARGET=https%253A%2F%
2Fsport.bt.com%2Fbtsportplayer%2Flive-streaming-01363980987389%253FleId%253D1364293057384
error: No playable streams found on this URL: https://sport.bt.com/btsportplayer/live-streaming-01363980987389?leId=1364
293057384
```


### Additional comments, screenshots, etc.
the links are for Champions League replay matches
should give multiple options for streams.


[Love Streamlink? Please consider supporting our collective. Thanks!](https://opencollective.com/streamlink/donate)



Discussion:
Looks like the login process may have changed (a possibly more). I don't have an account, I borrowed some credentials to develop the plugin. Unfortunately without a username/password I cannot debug it properly. 
you can use my login to have a look :)
where can i send it to?

Resolving patch:
diff --git a/src/streamlink/plugins/btsports.py b/src/streamlink/plugins/btsports.py
--- a/src/streamlink/plugins/btsports.py
+++ b/src/streamlink/plugins/btsports.py
@@ -1,12 +1,15 @@
-import re
 import time
+
+import logging
+import re
 from uuid import uuid4
 
 from streamlink.compat import quote
 from streamlink.plugin import Plugin, PluginArguments, PluginArgument
 from streamlink.plugin.api import useragents
 from streamlink.stream import HLSStream
-from streamlink.utils import url_equal
+
+log = logging.getLogger(__name__)
 
 
 class BTSports(Plugin):
@@ -47,25 +50,23 @@ def can_handle_url(cls, url):
         return cls.url_re.match(url) is not None
 
     def login(self, username, password):
-        self.logger.debug("Logging in as {0}".format(username))
+        log.debug("Logging in as {0}".format(username))
 
-        redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?redirectURL={0}".format(quote(self.url))
+        redirect_to = "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport&redirectURL={0}".format(quote(self.url))
         data = {
             "cookieExpp": "30",
             "Switch": "yes",
             "SMPostLoginUrl": "/appsyouraccount/secure/postlogin",
-            "loginforward": "https://home.bt.com/ss/Satellite/secure/loginforward",
+            "loginforward": "https://home.bt.com/ss/Satellite/secure/loginforward?view=btsport",
             "smauthreason": "0",
             "TARGET": redirect_to,
             "USER": username,
             "PASSWORD": password}
-
         res = self.session.http.post(self.login_url, data=data)
 
-        self.logger.debug("Redirected to: {0}".format(res.url))
-
+        log.debug("Redirected to: {0}".format(res.url))
 
-        if url_equal(res.url, self.url, ignore_scheme=True):
+        if "loginerror" not in res.text:
             self.logger.debug("Login successful, getting SAML token")
             res = self.session.http.get("https://samlfed.bt.com/sportgetfedwebhls?bt.cid={0}".format(self.acid()))
             d = self.saml_re.search(res.text)
@@ -81,7 +82,8 @@ def login(self, username, password):
                     self.logger.error("Failed to login: {0} - {1}".format(fed_json['errorDescription'],
                                                                           fed_json['message']))
                 return success
-        return False
+        else:
+            return False
 
     def device_id(self):
         device_id = self.cache.get("device_id") or str(uuid4())
@@ -108,19 +110,23 @@ def _get_cdn(self, channel_id, channel_type="LIVE"):
     def _get_streams(self):
         if self.options.get("email") and self.options.get("password"):
             if self.login(self.options.get("email"), self.options.get("password")):
-                self.logger.debug("Logged in and authenticated with BT Sports.")
+                log.debug("Logged in and authenticated with BT Sports.")
 
                 res = self.session.http.get(self.url)
                 m = self.content_re.findall(res.text)
                 if m:
                     info = dict(m)
                     data = self._get_cdn(info.get("ID"), info.get("TYPE"))
+                    log.debug("CDN respsonse: {0}".format(data))
                     if data['resultCode'] == 'OK':
                         return HLSStream.parse_variant_playlist(self.session, data['resultObj']['src'])
                     else:
-                        self.logger.error("Failed to get stream with error: {0} - {1}".format(data['errorDescription'],
+                        log.error("Failed to get stream with error: {0} - {1}".format(data['errorDescription'],
                                                                                               data['message']))
+            else:
+                log.error("Login failed.")
         else:
-            self.logger.error("A username and password is required to use BT Sports")
+            log.error("A username and password is required to use BT Sports")
+
 
 __plugin__ = BTSports


Test patch: