We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
plugins.huya: 403 Client Error: Forbidden for url
### 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.5.1

### Description

please forgive me, my english so bad and  it's hard to understand all these rules, im newbie inpython, I don’t know, this has already been asked and I read the answer that this is not a streamlink problem, but maybe you can help me



### Debug log

```text
C:\Users\matebeats>streamlink.exe https://www.huya.com/sbwfz best
[cli][info] Found matching plugin huya for URL https://www.huya.com/sbwfz
[cli][info] Available streams: source_hw (worst, best)
[cli][info] Opening stream: source_hw (http)
[cli][info] Starting player: D:\matebeats\soft\media\VLC\vlc.exe
[cli][error] Try 1/1: Could not open stream <HTTPStream ['http', 'https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct']> (Could not open stream: Unable to open URL: https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct (403 Client Error: Forbidden for url: https://7b232e9a7ece13f936b4e19cb1594132.livehwc3.cn/hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?cdn_redirect_domain=14769ccad573a2388a716f2ade587c96.livehwc3.cn&cdn_redirect=true&wsTime=65a9468d&ctype=huya_live&fs=bgct&policy=6&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&wsSecret=79ab95ca0c616135da585dba0e2373ef&cdn_redirect_tag=1705592487))
error: Could not open stream <HTTPStream ['http', 'https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct']>, tried 1 times, exiting
```


--- 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/huya.py`
Content:
```
1 """
2 $description Chinese live-streaming platform for live video game broadcasts and individual live streams.
3 $url huya.com
4 $type live
5 $metadata id
6 $metadata author
7 $metadata title
8 """
9 
10 import base64
11 import logging
12 import re
13 from html import unescape as html_unescape
14 from typing import Dict
15 
16 from streamlink.plugin import Plugin, pluginmatcher
17 from streamlink.plugin.api import validate
18 from streamlink.stream.http import HTTPStream
19 from streamlink.utils.url import update_scheme
20 
21 
22 log = logging.getLogger(__name__)
23 
24 
25 @pluginmatcher(re.compile(
26     r"https?://(?:www\.)?huya\.com/(?P<channel>[^/]+)",
27 ))
28 class Huya(Plugin):
29     QUALITY_WEIGHTS: Dict[str, int] = {}
30 
31     @classmethod
32     def stream_weight(cls, key):
33         weight = cls.QUALITY_WEIGHTS.get(key)
34         if weight:
35             return weight, "huya"
36 
37         return super().stream_weight(key)
38 
39     def _get_streams(self):
40         data = self.session.http.get(self.url, schema=validate.Schema(
41             validate.parse_html(),
42             validate.xml_xpath_string(".//script[contains(text(),'var hyPlayerConfig = {')][1]/text()"),
43             validate.none_or_all(
44                 re.compile(r"""(?P<q>"?)stream(?P=q)\s*:\s*(?:"(?P<base64>.+?)"|(?P<json>\{.+?})\s*}\s*;)"""),
45             ),
46             validate.none_or_all(
47                 validate.any(
48                     validate.all(
49                         validate.get("base64"),
50                         str,
51                         validate.transform(base64.b64decode),
52                     ),
53                     validate.all(
54                         validate.get("json"),
55                         str,
56                     ),
57                 ),
58                 validate.parse_json(),
59                 {
60                     "data": [{
61                         "gameLiveInfo": {
62                             "liveId": str,
63                             "nick": str,
64                             "roomName": str,
65                         },
66                         "gameStreamInfoList": [validate.all(
67                             {
68                                 "sCdnType": str,
69                                 "iPCPriorityRate": int,
70                                 "sStreamName": str,
71                                 "sFlvUrl": str,
72                                 "sFlvUrlSuffix": str,
73                                 "sFlvAntiCode": validate.all(str, validate.transform(html_unescape)),
74                             },
75                             validate.union_get(
76                                 "sCdnType",
77                                 "iPCPriorityRate",
78                                 "sStreamName",
79                                 "sFlvUrl",
80                                 "sFlvUrlSuffix",
81                                 "sFlvAntiCode",
82                             )),
83                         ],
84                     }],
85                 },
86                 validate.get(("data", 0)),
87                 validate.union_get(
88                     ("gameLiveInfo", "liveId"),
89                     ("gameLiveInfo", "nick"),
90                     ("gameLiveInfo", "roomName"),
91                     "gameStreamInfoList",
92                 ),
93             ),
94         ))
95         if not data:
96             return
97 
98         self.id, self.author, self.title, streamdata = data
99 
100         for cdntype, priority, streamname, flvurl, suffix, anticode in streamdata:
101             url = update_scheme("https://", f"{flvurl}/{streamname}.{suffix}?{anticode}")
102             if self.session.http.head(url, raise_for_status=False).status_code >= 400:
103                 continue
104 
105             name = f"source_{cdntype.lower()}"
106             self.QUALITY_WEIGHTS[name] = priority
107             yield name, HTTPStream(self.session, url)
108 
109         log.debug(f"QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}")
110 
111 
112 __plugin__ = Huya
113
```
--- 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()

```

diff --git a/src/streamlink/plugins/huya.py b/src/streamlink/plugins/huya.py
--- a/src/streamlink/plugins/huya.py
+++ b/src/streamlink/plugins/huya.py
@@ -12,22 +12,28 @@
 import re
 from html import unescape as html_unescape
 from typing import Dict
+from urllib.parse import parse_qsl
 
 from streamlink.plugin import Plugin, pluginmatcher
 from streamlink.plugin.api import validate
 from streamlink.stream.http import HTTPStream
-from streamlink.utils.url import update_scheme
+from streamlink.utils.url import update_qsd, update_scheme
 
 
 log = logging.getLogger(__name__)
 
 
 @pluginmatcher(re.compile(
-    r"https?://(?:www\.)?huya\.com/(?P<channel>[^/]+)",
+    r"https?://(?:www\.)?huya\.com/(?P<channel>[^/?]+)",
 ))
 class Huya(Plugin):
     QUALITY_WEIGHTS: Dict[str, int] = {}
 
+    _QUALITY_WEIGHTS_OVERRIDE = {
+        "source_hy": -1000,  # SSLCertVerificationError
+    }
+    _STREAM_URL_QUERYSTRING_PARAMS = "wsSecret", "wsTime"
+
     @classmethod
     def stream_weight(cls, key):
         weight = cls.QUALITY_WEIGHTS.get(key)
@@ -97,13 +103,18 @@
 
         self.id, self.author, self.title, streamdata = data
 
+        self.session.http.headers.update({
+            "Origin": "https://www.huya.com",
+            "Referer": "https://www.huya.com/",
+        })
+
         for cdntype, priority, streamname, flvurl, suffix, anticode in streamdata:
-            url = update_scheme("https://", f"{flvurl}/{streamname}.{suffix}?{anticode}")
-            if self.session.http.head(url, raise_for_status=False).status_code >= 400:
-                continue
+            qs = {k: v for k, v in dict(parse_qsl(anticode)).items() if k in self._STREAM_URL_QUERYSTRING_PARAMS}
+            url = update_scheme("https://", f"{flvurl}/{streamname}.{suffix}")
+            url = update_qsd(url, qs)
 
             name = f"source_{cdntype.lower()}"
-            self.QUALITY_WEIGHTS[name] = priority
+            self.QUALITY_WEIGHTS[name] = self._QUALITY_WEIGHTS_OVERRIDE.get(name, priority)
             yield name, HTTPStream(self.session, url)
 
         log.debug(f"QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}")

{"golden_diff": "diff --git a/src/streamlink/plugins/huya.py b/src/streamlink/plugins/huya.py\n--- a/src/streamlink/plugins/huya.py\n+++ b/src/streamlink/plugins/huya.py\n@@ -12,22 +12,28 @@\n import re\n from html import unescape as html_unescape\n from typing import Dict\n+from urllib.parse import parse_qsl\n \n from streamlink.plugin import Plugin, pluginmatcher\n from streamlink.plugin.api import validate\n from streamlink.stream.http import HTTPStream\n-from streamlink.utils.url import update_scheme\n+from streamlink.utils.url import update_qsd, update_scheme\n \n \n log = logging.getLogger(__name__)\n \n \n @pluginmatcher(re.compile(\n-    r\"https?://(?:www\\.)?huya\\.com/(?P<channel>[^/]+)\",\n+    r\"https?://(?:www\\.)?huya\\.com/(?P<channel>[^/?]+)\",\n ))\n class Huya(Plugin):\n     QUALITY_WEIGHTS: Dict[str, int] = {}\n \n+    _QUALITY_WEIGHTS_OVERRIDE = {\n+        \"source_hy\": -1000,  # SSLCertVerificationError\n+    }\n+    _STREAM_URL_QUERYSTRING_PARAMS = \"wsSecret\", \"wsTime\"\n+\n     @classmethod\n     def stream_weight(cls, key):\n         weight = cls.QUALITY_WEIGHTS.get(key)\n@@ -97,13 +103,18 @@\n \n         self.id, self.author, self.title, streamdata = data\n \n+        self.session.http.headers.update({\n+            \"Origin\": \"https://www.huya.com\",\n+            \"Referer\": \"https://www.huya.com/\",\n+        })\n+\n         for cdntype, priority, streamname, flvurl, suffix, anticode in streamdata:\n-            url = update_scheme(\"https://\", f\"{flvurl}/{streamname}.{suffix}?{anticode}\")\n-            if self.session.http.head(url, raise_for_status=False).status_code >= 400:\n-                continue\n+            qs = {k: v for k, v in dict(parse_qsl(anticode)).items() if k in self._STREAM_URL_QUERYSTRING_PARAMS}\n+            url = update_scheme(\"https://\", f\"{flvurl}/{streamname}.{suffix}\")\n+            url = update_qsd(url, qs)\n \n             name = f\"source_{cdntype.lower()}\"\n-            self.QUALITY_WEIGHTS[name] = priority\n+            self.QUALITY_WEIGHTS[name] = self._QUALITY_WEIGHTS_OVERRIDE.get(name, priority)\n             yield name, HTTPStream(self.session, url)\n \n         log.debug(f\"QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}\")\n", "issue": "plugins.huya: 403 Client Error: Forbidden for url\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.5.1\n\n### Description\n\nplease forgive me, my english so bad and  it's hard to understand all these rules, im newbie inpython, I don\u2019t know, this has already been asked and I read the answer that this is not a streamlink problem, but maybe you can help me\r\n\r\n\n\n### Debug log\n\n```text\nC:\\Users\\matebeats>streamlink.exe https://www.huya.com/sbwfz best\r\n[cli][info] Found matching plugin huya for URL https://www.huya.com/sbwfz\r\n[cli][info] Available streams: source_hw (worst, best)\r\n[cli][info] Opening stream: source_hw (http)\r\n[cli][info] Starting player: D:\\matebeats\\soft\\media\\VLC\\vlc.exe\r\n[cli][error] Try 1/1: Could not open stream <HTTPStream ['http', 'https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct']> (Could not open stream: Unable to open URL: https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct (403 Client Error: Forbidden for url: https://7b232e9a7ece13f936b4e19cb1594132.livehwc3.cn/hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?cdn_redirect_domain=14769ccad573a2388a716f2ade587c96.livehwc3.cn&cdn_redirect=true&wsTime=65a9468d&ctype=huya_live&fs=bgct&policy=6&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&wsSecret=79ab95ca0c616135da585dba0e2373ef&cdn_redirect_tag=1705592487))\r\nerror: Could not open stream <HTTPStream ['http', 'https://hw.flv.huya.com/src/70165683-70165683-301359313786503168-140454822-10057-A-0-1.flv?wsSecret=79ab95ca0c616135da585dba0e2373ef&wsTime=65a9468d&fm=RFdxOEJjSjNoNkRKdDZUWV8kMF8kMV8kMl8kMw%3D%3D&ctype=huya_live&fs=bgct']>, tried 1 times, exiting\n```\n\n", "before_files": [{"content": "\"\"\"\n$description Chinese live-streaming platform for live video game broadcasts and individual live streams.\n$url huya.com\n$type live\n$metadata id\n$metadata author\n$metadata title\n\"\"\"\n\nimport base64\nimport logging\nimport re\nfrom html import unescape as html_unescape\nfrom typing import Dict\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.http import HTTPStream\nfrom streamlink.utils.url import update_scheme\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"https?://(?:www\\.)?huya\\.com/(?P<channel>[^/]+)\",\n))\nclass Huya(Plugin):\n    QUALITY_WEIGHTS: Dict[str, int] = {}\n\n    @classmethod\n    def stream_weight(cls, key):\n        weight = cls.QUALITY_WEIGHTS.get(key)\n        if weight:\n            return weight, \"huya\"\n\n        return super().stream_weight(key)\n\n    def _get_streams(self):\n        data = self.session.http.get(self.url, schema=validate.Schema(\n            validate.parse_html(),\n            validate.xml_xpath_string(\".//script[contains(text(),'var hyPlayerConfig = {')][1]/text()\"),\n            validate.none_or_all(\n                re.compile(r\"\"\"(?P<q>\"?)stream(?P=q)\\s*:\\s*(?:\"(?P<base64>.+?)\"|(?P<json>\\{.+?})\\s*}\\s*;)\"\"\"),\n            ),\n            validate.none_or_all(\n                validate.any(\n                    validate.all(\n                        validate.get(\"base64\"),\n                        str,\n                        validate.transform(base64.b64decode),\n                    ),\n                    validate.all(\n                        validate.get(\"json\"),\n                        str,\n                    ),\n                ),\n                validate.parse_json(),\n                {\n                    \"data\": [{\n                        \"gameLiveInfo\": {\n                            \"liveId\": str,\n                            \"nick\": str,\n                            \"roomName\": str,\n                        },\n                        \"gameStreamInfoList\": [validate.all(\n                            {\n                                \"sCdnType\": str,\n                                \"iPCPriorityRate\": int,\n                                \"sStreamName\": str,\n                                \"sFlvUrl\": str,\n                                \"sFlvUrlSuffix\": str,\n                                \"sFlvAntiCode\": validate.all(str, validate.transform(html_unescape)),\n                            },\n                            validate.union_get(\n                                \"sCdnType\",\n                                \"iPCPriorityRate\",\n                                \"sStreamName\",\n                                \"sFlvUrl\",\n                                \"sFlvUrlSuffix\",\n                                \"sFlvAntiCode\",\n                            )),\n                        ],\n                    }],\n                },\n                validate.get((\"data\", 0)),\n                validate.union_get(\n                    (\"gameLiveInfo\", \"liveId\"),\n                    (\"gameLiveInfo\", \"nick\"),\n                    (\"gameLiveInfo\", \"roomName\"),\n                    \"gameStreamInfoList\",\n                ),\n            ),\n        ))\n        if not data:\n            return\n\n        self.id, self.author, self.title, streamdata = data\n\n        for cdntype, priority, streamname, flvurl, suffix, anticode in streamdata:\n            url = update_scheme(\"https://\", f\"{flvurl}/{streamname}.{suffix}?{anticode}\")\n            if self.session.http.head(url, raise_for_status=False).status_code >= 400:\n                continue\n\n            name = f\"source_{cdntype.lower()}\"\n            self.QUALITY_WEIGHTS[name] = priority\n            yield name, HTTPStream(self.session, url)\n\n        log.debug(f\"QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}\")\n\n\n__plugin__ = Huya\n", "path": "src/streamlink/plugins/huya.py"}], "after_files": [{"content": "\"\"\"\n$description Chinese live-streaming platform for live video game broadcasts and individual live streams.\n$url huya.com\n$type live\n$metadata id\n$metadata author\n$metadata title\n\"\"\"\n\nimport base64\nimport logging\nimport re\nfrom html import unescape as html_unescape\nfrom typing import Dict\nfrom urllib.parse import parse_qsl\n\nfrom streamlink.plugin import Plugin, pluginmatcher\nfrom streamlink.plugin.api import validate\nfrom streamlink.stream.http import HTTPStream\nfrom streamlink.utils.url import update_qsd, update_scheme\n\n\nlog = logging.getLogger(__name__)\n\n\n@pluginmatcher(re.compile(\n    r\"https?://(?:www\\.)?huya\\.com/(?P<channel>[^/?]+)\",\n))\nclass Huya(Plugin):\n    QUALITY_WEIGHTS: Dict[str, int] = {}\n\n    _QUALITY_WEIGHTS_OVERRIDE = {\n        \"source_hy\": -1000,  # SSLCertVerificationError\n    }\n    _STREAM_URL_QUERYSTRING_PARAMS = \"wsSecret\", \"wsTime\"\n\n    @classmethod\n    def stream_weight(cls, key):\n        weight = cls.QUALITY_WEIGHTS.get(key)\n        if weight:\n            return weight, \"huya\"\n\n        return super().stream_weight(key)\n\n    def _get_streams(self):\n        data = self.session.http.get(self.url, schema=validate.Schema(\n            validate.parse_html(),\n            validate.xml_xpath_string(\".//script[contains(text(),'var hyPlayerConfig = {')][1]/text()\"),\n            validate.none_or_all(\n                re.compile(r\"\"\"(?P<q>\"?)stream(?P=q)\\s*:\\s*(?:\"(?P<base64>.+?)\"|(?P<json>\\{.+?})\\s*}\\s*;)\"\"\"),\n            ),\n            validate.none_or_all(\n                validate.any(\n                    validate.all(\n                        validate.get(\"base64\"),\n                        str,\n                        validate.transform(base64.b64decode),\n                    ),\n                    validate.all(\n                        validate.get(\"json\"),\n                        str,\n                    ),\n                ),\n                validate.parse_json(),\n                {\n                    \"data\": [{\n                        \"gameLiveInfo\": {\n                            \"liveId\": str,\n                            \"nick\": str,\n                            \"roomName\": str,\n                        },\n                        \"gameStreamInfoList\": [validate.all(\n                            {\n                                \"sCdnType\": str,\n                                \"iPCPriorityRate\": int,\n                                \"sStreamName\": str,\n                                \"sFlvUrl\": str,\n                                \"sFlvUrlSuffix\": str,\n                                \"sFlvAntiCode\": validate.all(str, validate.transform(html_unescape)),\n                            },\n                            validate.union_get(\n                                \"sCdnType\",\n                                \"iPCPriorityRate\",\n                                \"sStreamName\",\n                                \"sFlvUrl\",\n                                \"sFlvUrlSuffix\",\n                                \"sFlvAntiCode\",\n                            )),\n                        ],\n                    }],\n                },\n                validate.get((\"data\", 0)),\n                validate.union_get(\n                    (\"gameLiveInfo\", \"liveId\"),\n                    (\"gameLiveInfo\", \"nick\"),\n                    (\"gameLiveInfo\", \"roomName\"),\n                    \"gameStreamInfoList\",\n                ),\n            ),\n        ))\n        if not data:\n            return\n\n        self.id, self.author, self.title, streamdata = data\n\n        self.session.http.headers.update({\n            \"Origin\": \"https://www.huya.com\",\n            \"Referer\": \"https://www.huya.com/\",\n        })\n\n        for cdntype, priority, streamname, flvurl, suffix, anticode in streamdata:\n            qs = {k: v for k, v in dict(parse_qsl(anticode)).items() if k in self._STREAM_URL_QUERYSTRING_PARAMS}\n            url = update_scheme(\"https://\", f\"{flvurl}/{streamname}.{suffix}\")\n            url = update_qsd(url, qs)\n\n            name = f\"source_{cdntype.lower()}\"\n            self.QUALITY_WEIGHTS[name] = self._QUALITY_WEIGHTS_OVERRIDE.get(name, priority)\n            yield name, HTTPStream(self.session, url)\n\n        log.debug(f\"QUALITY_WEIGHTS: {self.QUALITY_WEIGHTS!r}\")\n\n\n__plugin__ = Huya\n", "path": "src/streamlink/plugins/huya.py"}]}