prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  plugins.pandalive: HTTP status 400 on API call
  ### Checklist
  
  - [X] This is a [plugin issue](https://streamlink.github.io/plugins.html) and not [a different kind of issue](https://github.com/streamlink/streamlink/issues/new/choose)
  - [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
  
  streamlink 6.2.0
  
  ### Description
  
  the livestreams can't resolved on pandalive
  it was always resolved 400 Client Error 
  
  ### Debug log
  
  ```text
  C:\Users\Jerry>C:\APP\Streamlink\bin\streamlink.exe https://www.pandalive.co.kr/live/play/pocet00 --loglevel=debug
  [session][debug] Plugin pandalive is being overridden by C:\Users\Jerry\AppData\Roaming\streamlink\plugins\pandalive.py
  [cli][debug] OS:         Windows 10
  [cli][debug] Python:     3.11.5
  [cli][debug] OpenSSL:    OpenSSL 3.0.9 30 May 2023
  [cli][debug] Streamlink: 6.2.0
  [cli][debug] Dependencies:
  [cli][debug]  certifi: 2023.7.22
  [cli][debug]  isodate: 0.6.1
  [cli][debug]  lxml: 4.9.3
  [cli][debug]  pycountry: 22.3.5
  [cli][debug]  pycryptodome: 3.18.0
  [cli][debug]  PySocks: 1.7.1
  [cli][debug]  requests: 2.31.0
  [cli][debug]  trio: 0.22.2
  [cli][debug]  trio-websocket: 0.10.4
  [cli][debug]  typing-extensions: 4.7.1
  [cli][debug]  urllib3: 2.0.4
  [cli][debug]  websocket-client: 1.6.3
  [cli][debug] Arguments:
  [cli][debug]  url=https://www.pandalive.co.kr/live/play/pocet00
  [cli][debug]  --loglevel=debug
  [cli][debug]  --ffmpeg-ffmpeg=C:\APP\Streamlink\ffmpeg\ffmpeg.exe
  [cli][info] Found matching plugin pandalive for URL https://www.pandalive.co.kr/live/play/pocet00
  [plugins.pandalive][debug] Media code: pocet00
  error: Unable to open URL: https://api.pandalive.co.kr/v1/live/play (400 Client Error: Bad Request for url: https://api.pandalive.co.kr/v1/live/play)
  ```
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `src/streamlink/plugins/pandalive.py`
  Content:
  ```
  1 """
  2 $description South Korean live-streaming platform for individual live streams.
  3 $url pandalive.co.kr
  4 $type live
  5 $metadata author
  6 $metadata title
  7 """
  8 
  9 import logging
  10 import re
  11 
  12 from streamlink.plugin import Plugin, pluginmatcher
  13 from streamlink.plugin.api import validate
  14 from streamlink.stream.hls import HLSStream
  15 
  16 
  17 log = logging.getLogger(__name__)
  18 
  19 
  20 @pluginmatcher(re.compile(
  21     r"https?://(?:www\.)?pandalive\.co\.kr/",
  22 ))
  23 class Pandalive(Plugin):
  24     def _get_streams(self):
  25         media_code = self.session.http.get(self.url, schema=validate.Schema(
  26             re.compile(r"""routePath:\s*(?P<q>["'])(\\u002F|/)live(\\u002F|/)play(\\u002F|/)(?P<id>.+?)(?P=q)"""),
  27             validate.any(None, validate.get("id")),
  28         ))
  29 
  30         if not media_code:
  31             return
  32 
  33         log.debug(f"Media code: {media_code}")
  34 
  35         json = self.session.http.post(
  36             "https://api.pandalive.co.kr/v1/live/play",
  37             data={
  38                 "action": "watch",
  39                 "userId": media_code,
  40             },
  41             schema=validate.Schema(
  42                 validate.parse_json(),
  43                 validate.any(
  44                     {
  45                         "media": {
  46                             "title": str,
  47                             "userId": str,
  48                             "userNick": str,
  49                             "isPw": bool,
  50                             "isLive": bool,
  51                             "liveType": str,
  52                         },
  53                         "PlayList": {
  54                             validate.optional("hls"): [{
  55                                 "url": validate.url(),
  56                             }],
  57                             validate.optional("hls2"): [{
  58                                 "url": validate.url(),
  59                             }],
  60                             validate.optional("hls3"): [{
  61                                 "url": validate.url(),
  62                             }],
  63                         },
  64                         "result": bool,
  65                         "message": str,
  66                     },
  67                     {
  68                         "result": bool,
  69                         "message": str,
  70                     },
  71                 ),
  72             ),
  73         )
  74 
  75         if not json["result"]:
  76             log.error(json["message"])
  77             return
  78 
  79         if not json["media"]["isLive"]:
  80             log.error("The broadcast has ended")
  81             return
  82 
  83         if json["media"]["isPw"]:
  84             log.error("The broadcast is password protected")
  85             return
  86 
  87         log.info(f"Broadcast type: {json['media']['liveType']}")
  88 
  89         self.author = f"{json['media']['userNick']} ({json['media']['userId']})"
  90         self.title = f"{json['media']['title']}"
  91 
  92         playlist = json["PlayList"]
  93         for key in ("hls", "hls2", "hls3"):
  94             # use the first available HLS stream
  95             if key in playlist and playlist[key]:
  96                 # all stream qualities share the same URL, so just use the first one
  97                 return HLSStream.parse_variant_playlist(self.session, playlist[key][0]["url"])
  98 
  99 
  100 __plugin__ = Pandalive
  101
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/src/streamlink/plugins/pandalive.py b/src/streamlink/plugins/pandalive.py
  --- a/src/streamlink/plugins/pandalive.py
  +++ b/src/streamlink/plugins/pandalive.py
  @@ -18,7 +18,7 @@
   
   
   @pluginmatcher(re.compile(
  -    r"https?://(?:www\.)?pandalive\.co\.kr/",
  +    r"https?://(?:www\.)?pandalive\.co\.kr/live/play/[^/]+",
   ))
   class Pandalive(Plugin):
       def _get_streams(self):
  @@ -34,10 +34,14 @@
   
           json = self.session.http.post(
               "https://api.pandalive.co.kr/v1/live/play",
  +            headers={
  +                "Referer": self.url,
  +            },
               data={
                   "action": "watch",
                   "userId": media_code,
               },
  +            acceptable_status=(200, 400),
               schema=validate.Schema(
                   validate.parse_json(),
                   validate.any(
  
verification_info: {"golden_diff": "diff --git a/src/streamlink/plugins/pandalive.py b/src/streamlink/plugins/pandalive.py\n--- a/src/streamlink/plugins/pandalive.py\n+++ b/src/streamlink/plugins/pandalive.py\n@@ -18,7 +18,7 @@\n \n \n @pluginmatcher(re.compile(\n-    r\"https?://(?:www\\.)?pandalive\\.co\\.kr/\",\n+    r\"https?://(?:www\\.)?pandalive\\.co\\.kr/live/play/[^/]+\",\n ))\n class Pandalive(Plugin):\n     def _get_streams(self):\n@@ -34,10 +34,14 @@\n \n         json = self.session.http.post(\n             \"https://api.pandalive.co.kr/v1/live/play\",\n+            headers={\n+                \"Referer\": self.url,\n+            },\n             data={\n                 \"action\": \"watch\",\n                 \"userId\": media_code,\n             },\n+            acceptable_status=(200, 400),\n             schema=validate.Schema(\n                 validate.parse_json(),\n                 validate.any(\n", "issue": "plugins.pandalive: HTTP status 400 on API call\n### Checklist\n\n- [X] This is a [plugin issue](https://streamlink.github.io/plugins.html) and not [a different kind of issue](https://github.com/streamlink/streamlink/issues/new/choose)\n- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)\n- [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)\n- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)\n\n### Streamlink version\n\nstreamlink 6.2.0\n\n### Description\n\nthe livestreams can't resolved on pandalive\r\nit was always resolved 400 Client Error \n\n### Debug log\n\n```text\nC:\\Users\\Jerry>C:\\APP\\Streamlink\\bin\\streamlink.exe https://www.pandalive.co.kr/live/play/pocet00 --loglevel=debug\r\n[session][debug] Plugin pandalive is being overridden by C:\\Users\\Jerry\\AppData\\Roaming\\streamlink\\plugins\\pandalive.py\r\n[cli][debug] OS:         Windows 10\r\n[cli][debug] Python:     3.11.5\r\n[cli][debug] OpenSSL:    OpenSSL 3.0.9 30 May 2023\r\n[cli][debug] Streamlink: 6.2.0\r\n[cli][debug] Dependencies:\r\n[cli][debug]  certifi: 2023.7.22\r\n[cli][debug]  isodate: 0.6.1\r\n[cli][debug]  lxml: 4.9.3\r\n[cli][debug]  pycountry: 22.3.5\r\n[cli][debug]  pycryptodome: 3.18.0\r\n[cli][debug]  PySocks: 1.7.1\r\n[cli][debug]  requests: 2.31.0\r\n[cli][debug]  trio: 0.22.2\r\n[cli][debug]  trio-websocket: 0.10.4\r\n[cli][debug]  typing-extensions: 4.7.1\r\n[cli][debug]  urllib3: 2.0.4\r\n[cli][debug]  websocket-client: 1.6.3\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://www.pandalive.co.kr/live/play/pocet00\r\n[cli][debug]  --loglevel=debug\r\n[cli][debug]  --ffmpeg-ffmpeg=C:\\APP\\Streamlink\\ffmpeg\\ffmpeg.exe\r\n[cli][info] Found matching plugin pandalive for URL https://www.pandalive.co.kr/live/play/pocet00\r\n[plugins.pandalive][debug] Media code: pocet00\r\nerror: Unable to open URL: https://api.pandalive.co.kr/v1/live/play (400 Client Error: Bad Request for url: https://api.pandalive.co.kr/v1/live/play)\n```\n\n", "before_files": [{"content": "\"\"\"\n$description South Korean live-streaming platform for individual live streams.\n$url pandalive.co.kr\n$type live\n$metadata author\n$metadata title\n\"\"\"\n\nimport logging\nimport re\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"https?://(?:www\\.)?pandalive\\.co\\.kr/\",\n))\nclass Pandalive(Plugin):\n    def _get_streams(self):\n        media_code = self.session.http.get(self.url, schema=validate.Schema(\n            re.compile(r\"\"\"routePath:\\s*(?P<q>[\"'])(\\\\u002F|/)live(\\\\u002F|/)play(\\\\u002F|/)(?P<id>.+?)(?P=q)\"\"\"),\n            validate.any(None, validate.get(\"id\")),\n        ))\n\n        if not media_code:\n            return\n\n        log.debug(f\"Media code: {media_code}\")\n\n        json = self.session.http.post(\n            \"https://api.pandalive.co.kr/v1/live/play\",\n            data={\n                \"action\": \"watch\",\n                \"userId\": media_code,\n            },\n            schema=validate.Schema(\n                validate.parse_json(),\n                validate.any(\n                    {\n                        \"media\": {\n                            \"title\": str,\n                            \"userId\": str,\n                            \"userNick\": str,\n                            \"isPw\": bool,\n                            \"isLive\": bool,\n                            \"liveType\": str,\n                        },\n                        \"PlayList\": {\n                            validate.optional(\"hls\"): [{\n                                \"url\": validate.url(),\n                            }],\n                            validate.optional(\"hls2\"): [{\n                                \"url\": validate.url(),\n                            }],\n                            validate.optional(\"hls3\"): [{\n                                \"url\": validate.url(),\n                            }],\n                        },\n                        \"result\": bool,\n                        \"message\": str,\n                    },\n                    {\n                        \"result\": bool,\n                        \"message\": str,\n                    },\n                ),\n            ),\n        )\n\n        if not json[\"result\"]:\n            log.error(json[\"message\"])\n            return\n\n        if not json[\"media\"][\"isLive\"]:\n            log.error(\"The broadcast has ended\")\n            return\n\n        if json[\"media\"][\"isPw\"]:\n            log.error(\"The broadcast is password protected\")\n            return\n\n        log.info(f\"Broadcast type: {json['media']['liveType']}\")\n\n        self.author = f\"{json['media']['userNick']} ({json['media']['userId']})\"\n        self.title = f\"{json['media']['title']}\"\n\n        playlist = json[\"PlayList\"]\n        for key in (\"hls\", \"hls2\", \"hls3\"):\n            # use the first available HLS stream\n            if key in playlist and playlist[key]:\n                # all stream qualities share the same URL, so just use the first one\n                return HLSStream.parse_variant_playlist(self.session, playlist[key][0][\"url\"])\n\n\n__plugin__ = Pandalive\n", "path": "src/streamlink/plugins/pandalive.py"}], "after_files": [{"content": "\"\"\"\n$description South Korean live-streaming platform for individual live streams.\n$url pandalive.co.kr\n$type live\n$metadata author\n$metadata title\n\"\"\"\n\nimport logging\nimport re\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.hls import HLSStream\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"https?://(?:www\\.)?pandalive\\.co\\.kr/live/play/[^/]+\",\n))\nclass Pandalive(Plugin):\n    def _get_streams(self):\n        media_code = self.session.http.get(self.url, schema=validate.Schema(\n            re.compile(r\"\"\"routePath:\\s*(?P<q>[\"'])(\\\\u002F|/)live(\\\\u002F|/)play(\\\\u002F|/)(?P<id>.+?)(?P=q)\"\"\"),\n            validate.any(None, validate.get(\"id\")),\n        ))\n\n        if not media_code:\n            return\n\n        log.debug(f\"Media code: {media_code}\")\n\n        json = self.session.http.post(\n            \"https://api.pandalive.co.kr/v1/live/play\",\n            headers={\n                \"Referer\": self.url,\n            },\n            data={\n                \"action\": \"watch\",\n                \"userId\": media_code,\n            },\n            acceptable_status=(200, 400),\n            schema=validate.Schema(\n                validate.parse_json(),\n                validate.any(\n                    {\n                        \"media\": {\n                            \"title\": str,\n                            \"userId\": str,\n                            \"userNick\": str,\n                            \"isPw\": bool,\n                            \"isLive\": bool,\n                            \"liveType\": str,\n                        },\n                        \"PlayList\": {\n                            validate.optional(\"hls\"): [{\n                                \"url\": validate.url(),\n                            }],\n                            validate.optional(\"hls2\"): [{\n                                \"url\": validate.url(),\n                            }],\n                            validate.optional(\"hls3\"): [{\n                                \"url\": validate.url(),\n                            }],\n                        },\n                        \"result\": bool,\n                        \"message\": str,\n                    },\n                    {\n                        \"result\": bool,\n                        \"message\": str,\n                    },\n                ),\n            ),\n        )\n\n        if not json[\"result\"]:\n            log.error(json[\"message\"])\n            return\n\n        if not json[\"media\"][\"isLive\"]:\n            log.error(\"The broadcast has ended\")\n            return\n\n        if json[\"media\"][\"isPw\"]:\n            log.error(\"The broadcast is password protected\")\n            return\n\n        log.info(f\"Broadcast type: {json['media']['liveType']}\")\n\n        self.author = f\"{json['media']['userNick']} ({json['media']['userId']})\"\n        self.title = f\"{json['media']['title']}\"\n\n        playlist = json[\"PlayList\"]\n        for key in (\"hls\", \"hls2\", \"hls3\"):\n            # use the first available HLS stream\n            if key in playlist and playlist[key]:\n                # all stream qualities share the same URL, so just use the first one\n                return HLSStream.parse_variant_playlist(self.session, playlist[key][0][\"url\"])\n\n\n__plugin__ = Pandalive\n", "path": "src/streamlink/plugins/pandalive.py"}]}