Repository: streamlink/streamlink

Issue:
Using Xtreme Codes Panel doesnt work anymore
## Plugin Issue


- [x] This is a plugin issue and I have read the contribution guidelines.


### Description

I am trying to open a stream on Xtreme Codes panel as it worked no problem late last year but now it does not work. Works great on VLC. Below is what i am seeing.


### Reproduction steps / Explicit stream URLs to test

1. I run the below command to open the stream;
```
streamlink --player-external-http-port 1234 --player-external-http --bbciplayer-username MYUSERNAME --bbciplayer-password MYPASSWORD  www.bbc.co.uk/iplayer/live/bbcone best & disown
```



### Log output

```
root@vps642372:~# streamlink --player-external-http-port 1234 --player-external-http --bbciplayer-username 'USER' --bbciplayer-password 'PASS'  www.bbc.co.uk/iplayer/live/bbcone best --player-no-close & disown
[1] 3919
root@vps642372:~# [cli][info] streamlink is running as root! Be careful!
[cli][info] Found matching plugin bbciplayer for URL www.bbc.co.uk/iplayer/live/bbcone
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
[cli][info] Available streams: 288p_dash, 396p_dash, 540p_dash, 288p_dash_alt, 396p_dash_alt, 540p_dash_alt, 288p_dash_alt2, 396p_dash_alt2, 540p_dash_alt2, 352k_alt2 (worst), 352k_alt, 352k, 544k_alt2, 544k_alt, 544k, 216p_alt2, 216p_alt, 216p, 288p_alt2, 288p_alt, 288p, 942k_alt2, 942k_alt, 942k, 396p_alt2, 396p_alt, 396p, 540p_alt2, 540p_alt, 540p, 1700k_alt2, 1700k_alt, 1700k (best)
[cli][info] Starting server, access with one of:
[cli][info]  http://127.0.0.1:1234/
[cli][info]  http://127.0.1.1:1234/
[cli][info]  http://MYIPADDRESS:1234/
[cli][info] Got HTTP request from Xtream-Codes IPTV Panel Pro
[cli][info] Opening stream: 1700k (hds)
[cli][info] HTTP connection closed
[cli][info] Stream ended
[cli][info] Got HTTP request from Xtream-Codes IPTV Panel Pro
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
[cli][info] Closing currently open stream...
Traceback (most recent call last):
  File "/usr/bin/streamlink", line 11, in <module>
    load_entry_point('streamlink==0.14.2', 'console_scripts', 'streamlink')()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 1002, in main
    handle_url()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 553, in handle_url
    handle_stream(plugin, streams, stream_name)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 397, in handle_stream
    port=args.player_external_http_port)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 179, in output_stream_http
    streams = initial_streams or fetch_streams(plugin)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 413, in fetch_streams
    sorting_excludes=args.stream_sorting_excludes)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 431, in get_streams
    return self.streams(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 339, in streams
    ostreams = list(ostreams)
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 224, in _get_streams
    if not self.login(self.url):
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 197, in login
    http_nonce = self._extract_nonce(session_res)
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 118, in _extract_nonce
    final_url = urlparse(last_redirect_query['goto'])
KeyError: 'goto'
```



Discussion:
```
root@vps642372:~# streamlink ... best --player-no-close & disown
[1] 3919
```

remove the `& disown` it breaks the streamlink line

---

use `--loglevel debug` for the **Log output**

---

try hls `540p` instead of hds `1700k (best)`
thank you for the reply. I have done what you said and below is the output.

```
root@vps642372:~# streamlink --player-external-http-port 1234 --player-external-http --bbciplayer-username USER --bbciplayer-password PASS  www.bbc.co.uk/iplayer/live/bbcone 540p --loglevel debug
[cli][info] streamlink is running as root! Be careful!
[cli][debug] OS:         Linux-4.15.0-43-generic-x86_64-with-Ubuntu-18.04-bionic
[cli][debug] Python:     3.6.7
[cli][debug] Streamlink: 0.14.2
[cli][debug] Requests(2.18.4), Socks(1.6.5), Websocket(0.44.0)
[cli][info] Found matching plugin bbciplayer for URL www.bbc.co.uk/iplayer/live/bbcone
[cli][debug] Plugin specific arguments:
[cli][debug]  --bbciplayer-username=USER (username)
[cli][debug]  --bbciplayer-password=******** (password)
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
[plugin.bbciplayer][debug] Loading stream for live channel: bbcone
[plugin.bbciplayer][debug] Looking for  tvip on http://www.bbc.co.uk/iplayer/live/bbcone
[plugin.bbciplayer][debug] Found TVIP: bbc_one_london
[plugin.bbciplayer][debug] Info API request: http://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/pc/vpid/bbc_one_london/format/json/atk/78ca5063d64bb5b308d1d87f737b610aa2db0f3f/asn/1/
[plugin.bbciplayer][debug] Info API request: http://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/iptv-all/vpid/bbc_one_london/format/json/atk/78ca5063d64bb5b308d1d87f737b610aa2db0f3f/asn/1/
[plugin.bbciplayer][debug] 4 hds streams
[plugin.bbciplayer][debug]   OK:   http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_one_london.f4m
[plugin.bbciplayer][debug]   OK:   https://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/aks/bbc_one_london.f4m
[plugin.bbciplayer][debug]   OK:   http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/llnw/bbc_one_london.f4m
[plugin.bbciplayer][debug]   OK:   https://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/llnws/bbc_one_london.f4m
[plugin.bbciplayer][debug] 8 dash streams
[plugin.bbciplayer][debug]   OK:   http://vs-dash-uk-live.bbcfmt.hs.llnwd.net/pool_902/live/bbc_one_london/bbc_one_london.isml/pc_hd_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   https://vs-dash-uk-live.akamaized.net/pool_902/live/bbc_one_london/bbc_one_london.isml/iptv_sdlow_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   http://vs-dash-uk-live.akamaized.net/pool_902/live/bbc_one_london/bbc_one_london.isml/pc_hd_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   http://vs-dash-uk-live.bbcfmt.hs.llnwd.net/pool_902/live/bbc_one_london/bbc_one_london.isml/iptv_sdlow_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   https://vs-dash-uk-live.akamaized.net/pool_902/live/bbc_one_london/bbc_one_london.isml/pc_hd_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   http://vs-dash-uk-live.akamaized.net/pool_902/live/bbc_one_london/bbc_one_london.isml/iptv_sdlow_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   https://vs-dash-uk-live.bbcfmt.hs.llnwd.net/pool_902/live/bbc_one_london/bbc_one_london.isml/pc_hd_abr_v2_dash.mpd
[plugin.bbciplayer][debug]   OK:   https://vs-dash-uk-live.bbcfmt.hs.llnwd.net/pool_902/live/bbc_one_london/bbc_one_london.isml/iptv_sdlow_abr_v2_dash.mpd
[plugin.bbciplayer][debug] 4 hls streams
[plugin.bbciplayer][debug]   OK:   https://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_tv/aks/bbc_one_london.m3u8
[plugin.bbciplayer][debug]   OK:   https://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_tv/llnws/bbc_one_london.m3u8
[plugin.bbciplayer][debug]   OK:   http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_tv/llnw/bbc_one_london.m3u8
[plugin.bbciplayer][debug]   OK:   http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_tv/ak/bbc_one_london.m3u8
[cli][info] Available streams: 288p_dash, 396p_dash, 540p_dash, 288p_dash_alt, 396p_dash_alt, 540p_dash_alt, 288p_dash_alt2, 396p_dash_alt2, 540p_dash_alt2, 352k_alt2 (worst), 352k_alt, 352k, 544k_alt2, 544k_alt, 544k, 216p_alt2, 216p_alt, 216p, 288p_alt2, 288p_alt, 288p, 942k_alt2, 942k_alt, 942k, 396p_alt2, 396p_alt, 396p, 540p_alt2, 540p_alt, 540p, 1700k_alt2, 1700k_alt, 1700k (best)
[cli][info] Starting server, access with one of:
[cli][info]  http://127.0.0.1:1234/
[cli][info]  http://127.0.1.1:1234/
[cli][info]  http://MYIPADDRESS:1234/
[cli][info] Got HTTP request from Xtream-Codes IPTV Panel Pro
[cli][info] Opening stream: 540p (hls)
[stream.hls][debug] Reloading playlist
[stream.hls][debug] First Sequence: 201671571; Last Sequence: 201672508
[stream.hls][debug] Start offset: 0; Duration: None; Start Sequence: 201672506; End Sequence: None
[stream.hls][debug] Adding segment 201672506 to queue
[cli][debug] Pre-buffering 8192 bytes
[stream.hls][debug] Adding segment 201672507 to queue
[stream.hls][debug] Adding segment 201672508 to queue
[stream.hls][debug] Download of segment 201672506 complete
[cli][debug] Writing stream to player
[stream.hls][debug] Download of segment 201672507 complete
[stream.hls][debug] Download of segment 201672508 complete
[cli][info] HTTP connection closed
[stream.segmented][debug] Closing worker thread
[stream.segmented][debug] Closing writer thread
[stream.segmented][debug] Closing writer thread
[cli][info] Stream ended
[cli][info] Got HTTP request from Xtream-Codes IPTV Panel Pro
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
[cli][info] Closing currently open stream...
Traceback (most recent call last):
  File "/usr/bin/streamlink", line 11, in <module>
    load_entry_point('streamlink==0.14.2', 'console_scripts', 'streamlink')()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 1002, in main
    handle_url()
  File "/usr/share/streamlink/streamlink_cli/main.py", line 553, in handle_url
    handle_stream(plugin, streams, stream_name)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 397, in handle_stream
    port=args.player_external_http_port)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 179, in output_stream_http
    streams = initial_streams or fetch_streams(plugin)
  File "/usr/share/streamlink/streamlink_cli/main.py", line 413, in fetch_streams
    sorting_excludes=args.stream_sorting_excludes)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 431, in get_streams
    return self.streams(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/streamlink/plugin/plugin.py", line 339, in streams
    ostreams = list(ostreams)
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 224, in _get_streams
    if not self.login(self.url):
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 197, in login
    http_nonce = self._extract_nonce(session_res)
  File "/usr/lib/python3/dist-packages/streamlink/plugins/bbciplayer.py", line 118, in _extract_nonce
    final_url = urlparse(last_redirect_query['goto'])
KeyError: 'goto'
```
Seems to be caused by the multiple requests that `Xtreme Codes Panel` makes when connecting to an HTTP source. 
is there a way to fix this at all as it did work last year?

Resolving patch:
diff --git a/src/streamlink/plugins/bbciplayer.py b/src/streamlink/plugins/bbciplayer.py
--- a/src/streamlink/plugins/bbciplayer.py
+++ b/src/streamlink/plugins/bbciplayer.py
@@ -187,13 +187,20 @@ def login(self, ptrt_url):
         :return: Whether authentication was successful
         :rtype: bool
         """
+        def auth_check(res):
+            return ptrt_url in ([h.url for h in res.history] + [res.url])
+
+        # make the session request to get the correct cookies
         session_res = self.session.http.get(
             self.session_url,
             params=dict(ptrt=ptrt_url)
         )
 
-        http_nonce = self._extract_nonce(session_res)
+        if auth_check(session_res):
+            log.debug("Already authenticated, skipping authentication")
+            return True
 
+        http_nonce = self._extract_nonce(session_res)
         res = self.session.http.post(
             self.auth_url,
             params=dict(
@@ -208,7 +215,7 @@ def login(self, ptrt_url):
             ),
             headers={"Referer": self.url})
 
-        return len(res.history) != 0
+        return auth_check(res)
 
     def _get_streams(self):
         if not self.get_option("username"):


Test patch:
diff --git a/tests/plugins/test_bbciplayer.py b/tests/plugins/test_bbciplayer.py
--- a/tests/plugins/test_bbciplayer.py
+++ b/tests/plugins/test_bbciplayer.py
@@ -1,5 +1,4 @@
 import json
-import logging
 import unittest
 
 from requests import Response, Request