prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  plugins.artetv: error: Unable to validate response text: ValidationError(dict):
  ### 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.0
  
  ### Description
  
  I  fix this issue 
  ```
  by adding '**API_HLS_NG**'     in line 51  of file 
  `/usr/lib/python3.11/site-packages/streamlink/plugins/artetv.py`
  like  this :
  ```
  ![image](https://github.com/streamlink/streamlink/assets/19744191/b78f47ba-67b2-439b-b336-85bef7e4615a)
  link/streamlink/assets/19744191/b78f47ba-67b2-439b-b336-85bef7e4615a)
  
  ### Debug log
  
  ```text
  error: Unable to validate response text: ValidationError(dict):
    Unable to validate value of key 'data'
    Context(dict):
      Unable to validate value of key 'attributes'
      Context(dict):
        Unable to validate value of key 'streams'
        Context(AnySchema):
          ValidationError(AnySchema):
          ValidationError(AnySchema):
            ValidationError(dict):
              Unable to validate value of key 'protocol'
              Context(AnySchema):
                ValidationError(equality):
                  'API_HLS_NG' does not equal 'HLS'
                ValidationError(equality):
                  'API_HLS_NG' does not equal 'HLS_NG'
  ```
  
  
  </issue>
  <code>
  [start of src/streamlink/plugins/artetv.py]
  1 """
  2 $description European public service channel promoting culture, including magazine shows, concerts and documentaries.
  3 $url arte.tv
  4 $type live, vod
  5 $metadata title
  6 """
  7 
  8 import logging
  9 import re
  10 from operator import itemgetter
  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(r"""
  21     https?://(?:\w+\.)?arte\.tv/(?:guide/)?
  22     (?P<language>[a-z]{2})/
  23     (?:
  24         (?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+
  25         |
  26         (?:direct|live)
  27     )
  28 """, re.VERBOSE))
  29 class ArteTV(Plugin):
  30     API_URL = "https://api.arte.tv/api/player/v2/config/{0}/{1}"
  31     API_TOKEN = "MzYyZDYyYmM1Y2Q3ZWRlZWFjMmIyZjZjNTRiMGY4MzY4NzBhOWQ5YjE4MGQ1NGFiODJmOTFlZDQwN2FkOTZjMQ"
  32 
  33     def _get_streams(self):
  34         language = self.match.group("language")
  35         video_id = self.match.group("video_id")
  36 
  37         json_url = self.API_URL.format(language, video_id or "LIVE")
  38         headers = {
  39             "Authorization": f"Bearer {self.API_TOKEN}",
  40         }
  41         streams, metadata = self.session.http.get(json_url, headers=headers, schema=validate.Schema(
  42             validate.parse_json(),
  43             {"data": {"attributes": {
  44                 "streams": validate.any(
  45                     [],
  46                     [
  47                         validate.all(
  48                             {
  49                                 "url": validate.url(),
  50                                 "slot": int,
  51                                 "protocol": validate.any("HLS", "HLS_NG"),
  52                             },
  53                             validate.union_get("slot", "protocol", "url"),
  54                         ),
  55                     ],
  56                 ),
  57                 "metadata": {
  58                     "title": str,
  59                     "subtitle": validate.any(None, str),
  60                 },
  61             }}},
  62             validate.get(("data", "attributes")),
  63             validate.union_get("streams", "metadata"),
  64         ))
  65 
  66         if not streams:
  67             return
  68 
  69         self.title = f"{metadata['title']} - {metadata['subtitle']}" if metadata["subtitle"] else metadata["title"]
  70 
  71         for _slot, _protocol, url in sorted(streams, key=itemgetter(0)):
  72             return HLSStream.parse_variant_playlist(self.session, url)
  73 
  74 
  75 __plugin__ = ArteTV
  76
  [end of src/streamlink/plugins/artetv.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/src/streamlink/plugins/artetv.py b/src/streamlink/plugins/artetv.py
  --- a/src/streamlink/plugins/artetv.py
  +++ b/src/streamlink/plugins/artetv.py
  @@ -2,6 +2,7 @@
   $description European public service channel promoting culture, including magazine shows, concerts and documentaries.
   $url arte.tv
   $type live, vod
  +$metadata id
   $metadata title
   """
   
  @@ -17,38 +18,41 @@
   log = logging.getLogger(__name__)
   
   
  -@pluginmatcher(re.compile(r"""
  -    https?://(?:\w+\.)?arte\.tv/(?:guide/)?
  -    (?P<language>[a-z]{2})/
  -    (?:
  -        (?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+
  -        |
  -        (?:direct|live)
  -    )
  -""", re.VERBOSE))
  +@pluginmatcher(
  +    name="live",
  +    pattern=re.compile(
  +        r"https?://(?:\w+\.)?arte\.tv/(?P<language>[a-z]{2})/(?:direct|live)/?",
  +    ),
  +)
  +@pluginmatcher(
  +    name="vod",
  +    pattern=re.compile(
  +        r"https?://(?:\w+\.)?arte\.tv/(?:guide/)?(?P<language>[a-z]{2})/(?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+",
  +    ),
  +)
   class ArteTV(Plugin):
  -    API_URL = "https://api.arte.tv/api/player/v2/config/{0}/{1}"
  -    API_TOKEN = "MzYyZDYyYmM1Y2Q3ZWRlZWFjMmIyZjZjNTRiMGY4MzY4NzBhOWQ5YjE4MGQ1NGFiODJmOTFlZDQwN2FkOTZjMQ"
  +    API_URL = "https://api.arte.tv/api/player/v2/config/{language}/{id}"
   
       def _get_streams(self):
  -        language = self.match.group("language")
  -        video_id = self.match.group("video_id")
  +        self.id = self.match["video_id"] if self.matches["vod"] else "LIVE"
   
  -        json_url = self.API_URL.format(language, video_id or "LIVE")
  -        headers = {
  -            "Authorization": f"Bearer {self.API_TOKEN}",
  -        }
  -        streams, metadata = self.session.http.get(json_url, headers=headers, schema=validate.Schema(
  +        json_url = self.API_URL.format(
  +            language=self.match["language"],
  +            id=self.id,
  +        )
  +        streams, metadata = self.session.http.get(json_url, schema=validate.Schema(
               validate.parse_json(),
  -            {"data": {"attributes": {
  +            {"data": {"attributes": dict}},
  +            validate.get(("data", "attributes")),
  +            {
                   "streams": validate.any(
                       [],
                       [
                           validate.all(
                               {
  -                                "url": validate.url(),
                                   "slot": int,
  -                                "protocol": validate.any("HLS", "HLS_NG"),
  +                                "protocol": str,
  +                                "url": validate.url(),
                               },
                               validate.union_get("slot", "protocol", "url"),
                           ),
  @@ -58,17 +62,15 @@
                       "title": str,
                       "subtitle": validate.any(None, str),
                   },
  -            }}},
  -            validate.get(("data", "attributes")),
  +            },
               validate.union_get("streams", "metadata"),
           ))
   
  -        if not streams:
  -            return
  -
           self.title = f"{metadata['title']} - {metadata['subtitle']}" if metadata["subtitle"] else metadata["title"]
   
  -        for _slot, _protocol, url in sorted(streams, key=itemgetter(0)):
  +        for _slot, protocol, url in sorted(streams, key=itemgetter(0)):
  +            if "HLS" not in protocol:
  +                continue
               return HLSStream.parse_variant_playlist(self.session, url)
  
verification_info: {"golden_diff": "diff --git a/src/streamlink/plugins/artetv.py b/src/streamlink/plugins/artetv.py\n--- a/src/streamlink/plugins/artetv.py\n+++ b/src/streamlink/plugins/artetv.py\n@@ -2,6 +2,7 @@\n $description European public service channel promoting culture, including magazine shows, concerts and documentaries.\n $url arte.tv\n $type live, vod\n+$metadata id\n $metadata title\n \"\"\"\n \n@@ -17,38 +18,41 @@\n log = logging.getLogger(__name__)\n \n \n-@pluginmatcher(re.compile(r\"\"\"\n-    https?://(?:\\w+\\.)?arte\\.tv/(?:guide/)?\n-    (?P<language>[a-z]{2})/\n-    (?:\n-        (?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+\n-        |\n-        (?:direct|live)\n-    )\n-\"\"\", re.VERBOSE))\n+@pluginmatcher(\n+    name=\"live\",\n+    pattern=re.compile(\n+        r\"https?://(?:\\w+\\.)?arte\\.tv/(?P<language>[a-z]{2})/(?:direct|live)/?\",\n+    ),\n+)\n+@pluginmatcher(\n+    name=\"vod\",\n+    pattern=re.compile(\n+        r\"https?://(?:\\w+\\.)?arte\\.tv/(?:guide/)?(?P<language>[a-z]{2})/(?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+\",\n+    ),\n+)\n class ArteTV(Plugin):\n-    API_URL = \"https://api.arte.tv/api/player/v2/config/{0}/{1}\"\n-    API_TOKEN = \"MzYyZDYyYmM1Y2Q3ZWRlZWFjMmIyZjZjNTRiMGY4MzY4NzBhOWQ5YjE4MGQ1NGFiODJmOTFlZDQwN2FkOTZjMQ\"\n+    API_URL = \"https://api.arte.tv/api/player/v2/config/{language}/{id}\"\n \n     def _get_streams(self):\n-        language = self.match.group(\"language\")\n-        video_id = self.match.group(\"video_id\")\n+        self.id = self.match[\"video_id\"] if self.matches[\"vod\"] else \"LIVE\"\n \n-        json_url = self.API_URL.format(language, video_id or \"LIVE\")\n-        headers = {\n-            \"Authorization\": f\"Bearer {self.API_TOKEN}\",\n-        }\n-        streams, metadata = self.session.http.get(json_url, headers=headers, schema=validate.Schema(\n+        json_url = self.API_URL.format(\n+            language=self.match[\"language\"],\n+            id=self.id,\n+        )\n+        streams, metadata = self.session.http.get(json_url, schema=validate.Schema(\n             validate.parse_json(),\n-            {\"data\": {\"attributes\": {\n+            {\"data\": {\"attributes\": dict}},\n+            validate.get((\"data\", \"attributes\")),\n+            {\n                 \"streams\": validate.any(\n                     [],\n                     [\n                         validate.all(\n                             {\n-                                \"url\": validate.url(),\n                                 \"slot\": int,\n-                                \"protocol\": validate.any(\"HLS\", \"HLS_NG\"),\n+                                \"protocol\": str,\n+                                \"url\": validate.url(),\n                             },\n                             validate.union_get(\"slot\", \"protocol\", \"url\"),\n                         ),\n@@ -58,17 +62,15 @@\n                     \"title\": str,\n                     \"subtitle\": validate.any(None, str),\n                 },\n-            }}},\n-            validate.get((\"data\", \"attributes\")),\n+            },\n             validate.union_get(\"streams\", \"metadata\"),\n         ))\n \n-        if not streams:\n-            return\n-\n         self.title = f\"{metadata['title']} - {metadata['subtitle']}\" if metadata[\"subtitle\"] else metadata[\"title\"]\n \n-        for _slot, _protocol, url in sorted(streams, key=itemgetter(0)):\n+        for _slot, protocol, url in sorted(streams, key=itemgetter(0)):\n+            if \"HLS\" not in protocol:\n+                continue\n             return HLSStream.parse_variant_playlist(self.session, url)\n", "issue": "plugins.artetv: error: Unable to validate response text: ValidationError(dict):\n### Checklist\r\n\r\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)\r\n- [X] [I have read the contribution guidelines](https://github.com/streamlink/streamlink/blob/master/CONTRIBUTING.md#contributing-to-streamlink)\r\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)\r\n- [X] [I have checked the commit log of the master branch](https://github.com/streamlink/streamlink/commits/master)\r\n\r\n### Streamlink version\r\nstreamlink 6.5.0\r\n\r\n### Description\r\n\r\nI  fix this issue \r\n```\r\nby adding '**API_HLS_NG**'     in line 51  of file \r\n`/usr/lib/python3.11/site-packages/streamlink/plugins/artetv.py`\r\nlike  this :\r\n```\r\n![image](https://github.com/streamlink/streamlink/assets/19744191/b78f47ba-67b2-439b-b336-85bef7e4615a)\r\nlink/streamlink/assets/19744191/b78f47ba-67b2-439b-b336-85bef7e4615a)\r\n\r\n### Debug log\r\n\r\n```text\r\nerror: Unable to validate response text: ValidationError(dict):\r\n  Unable to validate value of key 'data'\r\n  Context(dict):\r\n    Unable to validate value of key 'attributes'\r\n    Context(dict):\r\n      Unable to validate value of key 'streams'\r\n      Context(AnySchema):\r\n        ValidationError(AnySchema):\r\n        ValidationError(AnySchema):\r\n          ValidationError(dict):\r\n            Unable to validate value of key 'protocol'\r\n            Context(AnySchema):\r\n              ValidationError(equality):\r\n                'API_HLS_NG' does not equal 'HLS'\r\n              ValidationError(equality):\r\n                'API_HLS_NG' does not equal 'HLS_NG'\r\n```\r\n\n", "before_files": [{"content": "\"\"\"\n$description European public service channel promoting culture, including magazine shows, concerts and documentaries.\n$url arte.tv\n$type live, vod\n$metadata title\n\"\"\"\n\nimport logging\nimport re\nfrom operator import itemgetter\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(r\"\"\"\n    https?://(?:\\w+\\.)?arte\\.tv/(?:guide/)?\n    (?P<language>[a-z]{2})/\n    (?:\n        (?:videos/)?(?P<video_id>(?!RC-|videos)[^/]+?)/.+\n        |\n        (?:direct|live)\n    )\n\"\"\", re.VERBOSE))\nclass ArteTV(Plugin):\n    API_URL = \"https://api.arte.tv/api/player/v2/config/{0}/{1}\"\n    API_TOKEN = \"MzYyZDYyYmM1Y2Q3ZWRlZWFjMmIyZjZjNTRiMGY4MzY4NzBhOWQ5YjE4MGQ1NGFiODJmOTFlZDQwN2FkOTZjMQ\"\n\n    def _get_streams(self):\n        language = self.match.group(\"language\")\n        video_id = self.match.group(\"video_id\")\n\n        json_url = self.API_URL.format(language, video_id or \"LIVE\")\n        headers = {\n            \"Authorization\": f\"Bearer {self.API_TOKEN}\",\n        }\n        streams, metadata = self.session.http.get(json_url, headers=headers, schema=validate.Schema(\n            validate.parse_json(),\n            {\"data\": {\"attributes\": {\n                \"streams\": validate.any(\n                    [],\n                    [\n                        validate.all(\n                            {\n                                \"url\": validate.url(),\n                                \"slot\": int,\n                                \"protocol\": validate.any(\"HLS\", \"HLS_NG\"),\n                            },\n                            validate.union_get(\"slot\", \"protocol\", \"url\"),\n                        ),\n                    ],\n                ),\n                \"metadata\": {\n                    \"title\": str,\n                    \"subtitle\": validate.any(None, str),\n                },\n            }}},\n            validate.get((\"data\", \"attributes\")),\n            validate.union_get(\"streams\", \"metadata\"),\n        ))\n\n        if not streams:\n            return\n\n        self.title = f\"{metadata['title']} - {metadata['subtitle']}\" if metadata[\"subtitle\"] else metadata[\"title\"]\n\n        for _slot, _protocol, url in sorted(streams, key=itemgetter(0)):\n            return HLSStream.parse_variant_playlist(self.session, url)\n\n\n__plugin__ = ArteTV\n", "path": "src/streamlink/plugins/artetv.py"}]}