prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  plugins.vkplay: vkplay.live has moved to another domain (live.vkplay.ru)
  ### 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.7.2
  
  ### Description
  
  https://vk.com/wall-212496568_91026
  
  yesterday, vkplay live changed its domain. if you specify the old domain in the link to the stream, then everything still works, but on the site itself there are links to a new domain, to which the existing plugin does not respond.
  
  I just tried to change the updated part of the domain in the plugin code (vkplay.live -> live.vkplay.ru ), and everything seems to be working well. It's a bit difficult for me to create a pull request, but here's the corrected plugin on gist:
  https://gist.github.com/oexlkinq/eef0a260dddad473c5febafd91b980d9
  
  the old domain is also listed in the documentation (https://streamlink.github.io/plugins.html#vkplay)
  
  ### Debug log
  
  ```text
  streamlink https://live.vkplay.ru/ruwarface 720p --loglevel=debug
  [cli][debug] OS:         Linux-6.8.1-arch1-1-x86_64-with-glibc2.39
  [cli][debug] Python:     3.11.8
  [cli][debug] OpenSSL:    OpenSSL 3.2.1 30 Jan 2024
  [cli][debug] Streamlink: 6.7.2
  [cli][debug] Dependencies:
  [cli][debug]  certifi: 2024.2.2
  [cli][debug]  exceptiongroup: 1.2.0
  [cli][debug]  isodate: 0.6.1
  [cli][debug]  lxml: 5.1.0
  [cli][debug]  pycountry: 23.12.11
  [cli][debug]  pycryptodome: 3.20.0
  [cli][debug]  PySocks: 1.7.1
  [cli][debug]  requests: 2.31.0
  [cli][debug]  trio: 0.25.0
  [cli][debug]  trio-websocket: 0.11.1
  [cli][debug]  typing-extensions: 4.10.0
  [cli][debug]  urllib3: 1.26.18
  [cli][debug]  websocket-client: 1.7.0
  [cli][debug] Arguments:
  [cli][debug]  url=https://live.vkplay.ru/ruwarface
  [cli][debug]  stream=['720p']
  [cli][debug]  --loglevel=debug
  error: No plugin can handle URL: https://live.vkplay.ru/ruwarface
  ```
  
  
  --- 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/vkplay.py`
  Content:
  ```
  1 """
  2 $description Russian live-streaming platform for gaming and esports, owned by VKontakte.
  3 $url vkplay.live
  4 $type live
  5 $metadata id
  6 $metadata author
  7 $metadata category
  8 $metadata title
  9 """
  10 
  11 import logging
  12 import re
  13 
  14 from streamlink.plugin import Plugin, pluginmatcher
  15 from streamlink.plugin.api import validate
  16 from streamlink.stream.hls import HLSStream
  17 
  18 
  19 log = logging.getLogger(__name__)
  20 
  21 
  22 @pluginmatcher(re.compile(
  23     r"https?://vkplay\.live/(?P<channel_name>\w+)/?$",
  24 ))
  25 class VKplay(Plugin):
  26     API_URL = "https://api.vkplay.live/v1"
  27 
  28     def _get_streams(self):
  29         self.author = self.match.group("channel_name")
  30         log.debug(f"Channel name: {self.author}")
  31 
  32         data = self.session.http.get(
  33             f"{self.API_URL}/blog/{self.author}/public_video_stream",
  34             headers={"Referer": self.url},
  35             acceptable_status=(200, 404),
  36             schema=validate.Schema(
  37                 validate.parse_json(),
  38                 validate.any(
  39                     validate.all(
  40                         {"error": str, "error_description": str},
  41                         validate.get("error_description"),
  42                     ),
  43                     validate.all(
  44                         {
  45                             validate.optional("category"): validate.all(
  46                                 {
  47                                     "title": str,
  48                                 },
  49                                 validate.get("title"),
  50                             ),
  51                             "title": str,
  52                             "data": validate.any(
  53                                 [
  54                                     validate.all(
  55                                         {
  56                                             "vid": str,
  57                                             "playerUrls": [
  58                                                 validate.all(
  59                                                     {
  60                                                         "type": str,
  61                                                         "url": validate.any("", validate.url()),
  62                                                     },
  63                                                     validate.union_get("type", "url"),
  64                                                 ),
  65                                             ],
  66                                         },
  67                                         validate.union_get("vid", "playerUrls"),
  68                                     ),
  69                                 ],
  70                                 [],
  71                             ),
  72                         },
  73                         validate.union_get(
  74                             "category",
  75                             "title",
  76                             ("data", 0),
  77                         ),
  78                     ),
  79                 ),
  80             ),
  81         )
  82         if isinstance(data, str):
  83             log.error(data)
  84             return
  85 
  86         self.category, self.title, streamdata = data
  87         if not streamdata:
  88             return
  89 
  90         self.id, streams = streamdata
  91 
  92         for streamtype, streamurl in streams:
  93             if streamurl and streamtype == "live_hls":
  94                 return HLSStream.parse_variant_playlist(self.session, streamurl)
  95 
  96 
  97 __plugin__ = VKplay
  98
  ```
  --- 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/vkplay.py b/src/streamlink/plugins/vkplay.py
  --- a/src/streamlink/plugins/vkplay.py
  +++ b/src/streamlink/plugins/vkplay.py
  @@ -1,6 +1,6 @@
   """
   $description Russian live-streaming platform for gaming and esports, owned by VKontakte.
  -$url vkplay.live
  +$url live.vkplay.ru
   $type live
   $metadata id
   $metadata author
  @@ -20,13 +20,13 @@
   
   
   @pluginmatcher(re.compile(
  -    r"https?://vkplay\.live/(?P<channel_name>\w+)/?$",
  +    r"https?://(?:live\.vkplay\.ru|vkplay\.live)/(?P<channel_name>\w+)/?$",
   ))
   class VKplay(Plugin):
  -    API_URL = "https://api.vkplay.live/v1"
  +    API_URL = "https://api.live.vkplay.ru/v1"
   
       def _get_streams(self):
  -        self.author = self.match.group("channel_name")
  +        self.author = self.match["channel_name"]
           log.debug(f"Channel name: {self.author}")
   
           data = self.session.http.get(
  
verification_info: {"golden_diff": "diff --git a/src/streamlink/plugins/vkplay.py b/src/streamlink/plugins/vkplay.py\n--- a/src/streamlink/plugins/vkplay.py\n+++ b/src/streamlink/plugins/vkplay.py\n@@ -1,6 +1,6 @@\n \"\"\"\n $description Russian live-streaming platform for gaming and esports, owned by VKontakte.\n-$url vkplay.live\n+$url live.vkplay.ru\n $type live\n $metadata id\n $metadata author\n@@ -20,13 +20,13 @@\n \n \n @pluginmatcher(re.compile(\n-    r\"https?://vkplay\\.live/(?P<channel_name>\\w+)/?$\",\n+    r\"https?://(?:live\\.vkplay\\.ru|vkplay\\.live)/(?P<channel_name>\\w+)/?$\",\n ))\n class VKplay(Plugin):\n-    API_URL = \"https://api.vkplay.live/v1\"\n+    API_URL = \"https://api.live.vkplay.ru/v1\"\n \n     def _get_streams(self):\n-        self.author = self.match.group(\"channel_name\")\n+        self.author = self.match[\"channel_name\"]\n         log.debug(f\"Channel name: {self.author}\")\n \n         data = self.session.http.get(\n", "issue": "plugins.vkplay: vkplay.live has moved to another domain (live.vkplay.ru)\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.7.2\n\n### Description\n\nhttps://vk.com/wall-212496568_91026\r\n\r\nyesterday, vkplay live changed its domain. if you specify the old domain in the link to the stream, then everything still works, but on the site itself there are links to a new domain, to which the existing plugin does not respond.\r\n\r\nI just tried to change the updated part of the domain in the plugin code (vkplay.live -> live.vkplay.ru ), and everything seems to be working well. It's a bit difficult for me to create a pull request, but here's the corrected plugin on gist:\r\nhttps://gist.github.com/oexlkinq/eef0a260dddad473c5febafd91b980d9\r\n\r\nthe old domain is also listed in the documentation (https://streamlink.github.io/plugins.html#vkplay)\n\n### Debug log\n\n```text\nstreamlink https://live.vkplay.ru/ruwarface 720p --loglevel=debug\r\n[cli][debug] OS:         Linux-6.8.1-arch1-1-x86_64-with-glibc2.39\r\n[cli][debug] Python:     3.11.8\r\n[cli][debug] OpenSSL:    OpenSSL 3.2.1 30 Jan 2024\r\n[cli][debug] Streamlink: 6.7.2\r\n[cli][debug] Dependencies:\r\n[cli][debug]  certifi: 2024.2.2\r\n[cli][debug]  exceptiongroup: 1.2.0\r\n[cli][debug]  isodate: 0.6.1\r\n[cli][debug]  lxml: 5.1.0\r\n[cli][debug]  pycountry: 23.12.11\r\n[cli][debug]  pycryptodome: 3.20.0\r\n[cli][debug]  PySocks: 1.7.1\r\n[cli][debug]  requests: 2.31.0\r\n[cli][debug]  trio: 0.25.0\r\n[cli][debug]  trio-websocket: 0.11.1\r\n[cli][debug]  typing-extensions: 4.10.0\r\n[cli][debug]  urllib3: 1.26.18\r\n[cli][debug]  websocket-client: 1.7.0\r\n[cli][debug] Arguments:\r\n[cli][debug]  url=https://live.vkplay.ru/ruwarface\r\n[cli][debug]  stream=['720p']\r\n[cli][debug]  --loglevel=debug\r\nerror: No plugin can handle URL: https://live.vkplay.ru/ruwarface\n```\n\n", "before_files": [{"content": "\"\"\"\n$description Russian live-streaming platform for gaming and esports, owned by VKontakte.\n$url vkplay.live\n$type live\n$metadata id\n$metadata author\n$metadata category\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?://vkplay\\.live/(?P<channel_name>\\w+)/?$\",\n))\nclass VKplay(Plugin):\n    API_URL = \"https://api.vkplay.live/v1\"\n\n    def _get_streams(self):\n        self.author = self.match.group(\"channel_name\")\n        log.debug(f\"Channel name: {self.author}\")\n\n        data = self.session.http.get(\n            f\"{self.API_URL}/blog/{self.author}/public_video_stream\",\n            headers={\"Referer\": self.url},\n            acceptable_status=(200, 404),\n            schema=validate.Schema(\n                validate.parse_json(),\n                validate.any(\n                    validate.all(\n                        {\"error\": str, \"error_description\": str},\n                        validate.get(\"error_description\"),\n                    ),\n                    validate.all(\n                        {\n                            validate.optional(\"category\"): validate.all(\n                                {\n                                    \"title\": str,\n                                },\n                                validate.get(\"title\"),\n                            ),\n                            \"title\": str,\n                            \"data\": validate.any(\n                                [\n                                    validate.all(\n                                        {\n                                            \"vid\": str,\n                                            \"playerUrls\": [\n                                                validate.all(\n                                                    {\n                                                        \"type\": str,\n                                                        \"url\": validate.any(\"\", validate.url()),\n                                                    },\n                                                    validate.union_get(\"type\", \"url\"),\n                                                ),\n                                            ],\n                                        },\n                                        validate.union_get(\"vid\", \"playerUrls\"),\n                                    ),\n                                ],\n                                [],\n                            ),\n                        },\n                        validate.union_get(\n                            \"category\",\n                            \"title\",\n                            (\"data\", 0),\n                        ),\n                    ),\n                ),\n            ),\n        )\n        if isinstance(data, str):\n            log.error(data)\n            return\n\n        self.category, self.title, streamdata = data\n        if not streamdata:\n            return\n\n        self.id, streams = streamdata\n\n        for streamtype, streamurl in streams:\n            if streamurl and streamtype == \"live_hls\":\n                return HLSStream.parse_variant_playlist(self.session, streamurl)\n\n\n__plugin__ = VKplay\n", "path": "src/streamlink/plugins/vkplay.py"}], "after_files": [{"content": "\"\"\"\n$description Russian live-streaming platform for gaming and esports, owned by VKontakte.\n$url live.vkplay.ru\n$type live\n$metadata id\n$metadata author\n$metadata category\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?://(?:live\\.vkplay\\.ru|vkplay\\.live)/(?P<channel_name>\\w+)/?$\",\n))\nclass VKplay(Plugin):\n    API_URL = \"https://api.live.vkplay.ru/v1\"\n\n    def _get_streams(self):\n        self.author = self.match[\"channel_name\"]\n        log.debug(f\"Channel name: {self.author}\")\n\n        data = self.session.http.get(\n            f\"{self.API_URL}/blog/{self.author}/public_video_stream\",\n            headers={\"Referer\": self.url},\n            acceptable_status=(200, 404),\n            schema=validate.Schema(\n                validate.parse_json(),\n                validate.any(\n                    validate.all(\n                        {\"error\": str, \"error_description\": str},\n                        validate.get(\"error_description\"),\n                    ),\n                    validate.all(\n                        {\n                            validate.optional(\"category\"): validate.all(\n                                {\n                                    \"title\": str,\n                                },\n                                validate.get(\"title\"),\n                            ),\n                            \"title\": str,\n                            \"data\": validate.any(\n                                [\n                                    validate.all(\n                                        {\n                                            \"vid\": str,\n                                            \"playerUrls\": [\n                                                validate.all(\n                                                    {\n                                                        \"type\": str,\n                                                        \"url\": validate.any(\"\", validate.url()),\n                                                    },\n                                                    validate.union_get(\"type\", \"url\"),\n                                                ),\n                                            ],\n                                        },\n                                        validate.union_get(\"vid\", \"playerUrls\"),\n                                    ),\n                                ],\n                                [],\n                            ),\n                        },\n                        validate.union_get(\n                            \"category\",\n                            \"title\",\n                            (\"data\", 0),\n                        ),\n                    ),\n                ),\n            ),\n        )\n        if isinstance(data, str):\n            log.error(data)\n            return\n\n        self.category, self.title, streamdata = data\n        if not streamdata:\n            return\n\n        self.id, streams = streamdata\n\n        for streamtype, streamurl in streams:\n            if streamurl and streamtype == \"live_hls\":\n                return HLSStream.parse_variant_playlist(self.session, streamurl)\n\n\n__plugin__ = VKplay\n", "path": "src/streamlink/plugins/vkplay.py"}]}