prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  searx_extra/update/update_languages.py : crash on peertube engine
  The URL https://peer.tube/api/v1/videos/languages doesn't exist anymore:
  https://github.com/searxng/searxng/blob/ee83c99d2b40efaaf4f3e6635e7a43f7731cb128/searx/engines/peertube.py#L24-L25
  
  See also https://framagit.org/framasoft/peertube/search-index/-/tree/master/server/controllers/api
  
  ----
  
  See https://framagit.org/framasoft/peertube/search-index/-/blob/master/client/src/views/Search.vue#L644-667
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `searx/engines/peertube.py`
  Content:
  ```
  1 # SPDX-License-Identifier: AGPL-3.0-or-later
  2 """
  3  peertube (Videos)
  4 """
  5 
  6 from json import loads
  7 from datetime import datetime
  8 from urllib.parse import urlencode
  9 from searx.utils import html_to_text
  10 
  11 # about
  12 about = {
  13     "website": 'https://joinpeertube.org',
  14     "wikidata_id": 'Q50938515',
  15     "official_api_documentation": 'https://docs.joinpeertube.org/api-rest-reference.html',
  16     "use_official_api": True,
  17     "require_api_key": False,
  18     "results": 'JSON',
  19 }
  20 
  21 # engine dependent config
  22 categories = ["videos"]
  23 paging = True
  24 base_url = "https://peer.tube"
  25 supported_languages_url = base_url + "/api/v1/videos/languages"
  26 
  27 
  28 # do search-request
  29 def request(query, params):
  30     sanitized_url = base_url.rstrip("/")
  31     pageno = (params["pageno"] - 1) * 15
  32     search_url = sanitized_url + "/api/v1/search/videos/?pageno={pageno}&{query}"
  33     query_dict = {"search": query}
  34     language = params["language"].split("-")[0]
  35     # pylint: disable=undefined-variable
  36     if "all" != language and language in supported_languages:
  37         query_dict["languageOneOf"] = language
  38     params["url"] = search_url.format(
  39         query=urlencode(query_dict), pageno=pageno
  40     )
  41     return params
  42 
  43 
  44 def _get_offset_from_pageno(pageno):
  45     return (pageno - 1) * 15 + 1
  46 
  47 
  48 # get response from search-request
  49 def response(resp):
  50     sanitized_url = base_url.rstrip("/")
  51     results = []
  52 
  53     search_res = loads(resp.text)
  54 
  55     embedded_url = (
  56         '<iframe width="560" height="315" sandbox="allow-same-origin allow-scripts allow-popups" '
  57         + 'src="'
  58         + sanitized_url
  59         + '{embed_path}" frameborder="0" allowfullscreen></iframe>'
  60     )
  61     # return empty array if there are no results
  62     if "data" not in search_res:
  63         return []
  64 
  65     # parse results
  66     for res in search_res["data"]:
  67         title = res["name"]
  68         url = sanitized_url + "/videos/watch/" + res["uuid"]
  69         description = res["description"]
  70         if description:
  71             content = html_to_text(res["description"])
  72         else:
  73             content = ""
  74         thumbnail = sanitized_url + res["thumbnailPath"]
  75         publishedDate = datetime.strptime(res["publishedAt"], "%Y-%m-%dT%H:%M:%S.%fZ")
  76         embedded = embedded_url.format(embed_path=res["embedPath"])
  77 
  78         results.append(
  79             {
  80                 "template": "videos.html",
  81                 "url": url,
  82                 "title": title,
  83                 "content": content,
  84                 "publishedDate": publishedDate,
  85                 "embedded": embedded,
  86                 "thumbnail": thumbnail,
  87             }
  88         )
  89 
  90     # return results
  91     return results
  92 
  93 
  94 def _fetch_supported_languages(resp):
  95     peertube_languages = list(loads(resp.text).keys())
  96     return peertube_languages
  97
  ```
  --- 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/searx/engines/peertube.py b/searx/engines/peertube.py
  --- a/searx/engines/peertube.py
  +++ b/searx/engines/peertube.py
  @@ -22,7 +22,9 @@
   categories = ["videos"]
   paging = True
   base_url = "https://peer.tube"
  -supported_languages_url = base_url + "/api/v1/videos/languages"
  +supported_languages_url = (
  +    'https://framagit.org/framasoft/peertube/search-index/-/raw/master/client/src/views/Search.vue'
  +)
   
   
   # do search-request
  @@ -92,5 +94,9 @@
   
   
   def _fetch_supported_languages(resp):
  -    peertube_languages = list(loads(resp.text).keys())
  +    import re
  +
  +    # https://docs.python.org/3/howto/regex.html#greedy-versus-non-greedy
  +    videolanguages = re.search(r"videoLanguages \(\) \{(.*?)\]", resp.text, re.DOTALL)
  +    peertube_languages = [m.group(1) for m in re.finditer(r"\{ id: '([a-z]+)', label:", videolanguages.group(1))]
       return peertube_languages
  
verification_info: {"golden_diff": "diff --git a/searx/engines/peertube.py b/searx/engines/peertube.py\n--- a/searx/engines/peertube.py\n+++ b/searx/engines/peertube.py\n@@ -22,7 +22,9 @@\n categories = [\"videos\"]\n paging = True\n base_url = \"https://peer.tube\"\n-supported_languages_url = base_url + \"/api/v1/videos/languages\"\n+supported_languages_url = (\n+    'https://framagit.org/framasoft/peertube/search-index/-/raw/master/client/src/views/Search.vue'\n+)\n \n \n # do search-request\n@@ -92,5 +94,9 @@\n \n \n def _fetch_supported_languages(resp):\n-    peertube_languages = list(loads(resp.text).keys())\n+    import re\n+\n+    # https://docs.python.org/3/howto/regex.html#greedy-versus-non-greedy\n+    videolanguages = re.search(r\"videoLanguages \\(\\) \\{(.*?)\\]\", resp.text, re.DOTALL)\n+    peertube_languages = [m.group(1) for m in re.finditer(r\"\\{ id: '([a-z]+)', label:\", videolanguages.group(1))]\n     return peertube_languages\n", "issue": "searx_extra/update/update_languages.py : crash on peertube engine\nThe URL https://peer.tube/api/v1/videos/languages doesn't exist anymore:\r\nhttps://github.com/searxng/searxng/blob/ee83c99d2b40efaaf4f3e6635e7a43f7731cb128/searx/engines/peertube.py#L24-L25\r\n\r\nSee also https://framagit.org/framasoft/peertube/search-index/-/tree/master/server/controllers/api\r\n\r\n----\r\n\r\nSee https://framagit.org/framasoft/peertube/search-index/-/blob/master/client/src/views/Search.vue#L644-667\n", "before_files": [{"content": "# SPDX-License-Identifier: AGPL-3.0-or-later\n\"\"\"\n peertube (Videos)\n\"\"\"\n\nfrom json import loads\nfrom datetime import datetime\nfrom urllib.parse import urlencode\nfrom searx.utils import html_to_text\n\n# about\nabout = {\n    \"website\": 'https://joinpeertube.org',\n    \"wikidata_id\": 'Q50938515',\n    \"official_api_documentation\": 'https://docs.joinpeertube.org/api-rest-reference.html',\n    \"use_official_api\": True,\n    \"require_api_key\": False,\n    \"results\": 'JSON',\n}\n\n# engine dependent config\ncategories = [\"videos\"]\npaging = True\nbase_url = \"https://peer.tube\"\nsupported_languages_url = base_url + \"/api/v1/videos/languages\"\n\n\n# do search-request\ndef request(query, params):\n    sanitized_url = base_url.rstrip(\"/\")\n    pageno = (params[\"pageno\"] - 1) * 15\n    search_url = sanitized_url + \"/api/v1/search/videos/?pageno={pageno}&{query}\"\n    query_dict = {\"search\": query}\n    language = params[\"language\"].split(\"-\")[0]\n    # pylint: disable=undefined-variable\n    if \"all\" != language and language in supported_languages:\n        query_dict[\"languageOneOf\"] = language\n    params[\"url\"] = search_url.format(\n        query=urlencode(query_dict), pageno=pageno\n    )\n    return params\n\n\ndef _get_offset_from_pageno(pageno):\n    return (pageno - 1) * 15 + 1\n\n\n# get response from search-request\ndef response(resp):\n    sanitized_url = base_url.rstrip(\"/\")\n    results = []\n\n    search_res = loads(resp.text)\n\n    embedded_url = (\n        '<iframe width=\"560\" height=\"315\" sandbox=\"allow-same-origin allow-scripts allow-popups\" '\n        + 'src=\"'\n        + sanitized_url\n        + '{embed_path}\" frameborder=\"0\" allowfullscreen></iframe>'\n    )\n    # return empty array if there are no results\n    if \"data\" not in search_res:\n        return []\n\n    # parse results\n    for res in search_res[\"data\"]:\n        title = res[\"name\"]\n        url = sanitized_url + \"/videos/watch/\" + res[\"uuid\"]\n        description = res[\"description\"]\n        if description:\n            content = html_to_text(res[\"description\"])\n        else:\n            content = \"\"\n        thumbnail = sanitized_url + res[\"thumbnailPath\"]\n        publishedDate = datetime.strptime(res[\"publishedAt\"], \"%Y-%m-%dT%H:%M:%S.%fZ\")\n        embedded = embedded_url.format(embed_path=res[\"embedPath\"])\n\n        results.append(\n            {\n                \"template\": \"videos.html\",\n                \"url\": url,\n                \"title\": title,\n                \"content\": content,\n                \"publishedDate\": publishedDate,\n                \"embedded\": embedded,\n                \"thumbnail\": thumbnail,\n            }\n        )\n\n    # return results\n    return results\n\n\ndef _fetch_supported_languages(resp):\n    peertube_languages = list(loads(resp.text).keys())\n    return peertube_languages\n", "path": "searx/engines/peertube.py"}], "after_files": [{"content": "# SPDX-License-Identifier: AGPL-3.0-or-later\n\"\"\"\n peertube (Videos)\n\"\"\"\n\nfrom json import loads\nfrom datetime import datetime\nfrom urllib.parse import urlencode\nfrom searx.utils import html_to_text\n\n# about\nabout = {\n    \"website\": 'https://joinpeertube.org',\n    \"wikidata_id\": 'Q50938515',\n    \"official_api_documentation\": 'https://docs.joinpeertube.org/api-rest-reference.html',\n    \"use_official_api\": True,\n    \"require_api_key\": False,\n    \"results\": 'JSON',\n}\n\n# engine dependent config\ncategories = [\"videos\"]\npaging = True\nbase_url = \"https://peer.tube\"\nsupported_languages_url = (\n    'https://framagit.org/framasoft/peertube/search-index/-/raw/master/client/src/views/Search.vue'\n)\n\n\n# do search-request\ndef request(query, params):\n    sanitized_url = base_url.rstrip(\"/\")\n    pageno = (params[\"pageno\"] - 1) * 15\n    search_url = sanitized_url + \"/api/v1/search/videos/?pageno={pageno}&{query}\"\n    query_dict = {\"search\": query}\n    language = params[\"language\"].split(\"-\")[0]\n    # pylint: disable=undefined-variable\n    if \"all\" != language and language in supported_languages:\n        query_dict[\"languageOneOf\"] = language\n    params[\"url\"] = search_url.format(\n        query=urlencode(query_dict), pageno=pageno\n    )\n    return params\n\n\ndef _get_offset_from_pageno(pageno):\n    return (pageno - 1) * 15 + 1\n\n\n# get response from search-request\ndef response(resp):\n    sanitized_url = base_url.rstrip(\"/\")\n    results = []\n\n    search_res = loads(resp.text)\n\n    embedded_url = (\n        '<iframe width=\"560\" height=\"315\" sandbox=\"allow-same-origin allow-scripts allow-popups\" '\n        + 'src=\"'\n        + sanitized_url\n        + '{embed_path}\" frameborder=\"0\" allowfullscreen></iframe>'\n    )\n    # return empty array if there are no results\n    if \"data\" not in search_res:\n        return []\n\n    # parse results\n    for res in search_res[\"data\"]:\n        title = res[\"name\"]\n        url = sanitized_url + \"/videos/watch/\" + res[\"uuid\"]\n        description = res[\"description\"]\n        if description:\n            content = html_to_text(res[\"description\"])\n        else:\n            content = \"\"\n        thumbnail = sanitized_url + res[\"thumbnailPath\"]\n        publishedDate = datetime.strptime(res[\"publishedAt\"], \"%Y-%m-%dT%H:%M:%S.%fZ\")\n        embedded = embedded_url.format(embed_path=res[\"embedPath\"])\n\n        results.append(\n            {\n                \"template\": \"videos.html\",\n                \"url\": url,\n                \"title\": title,\n                \"content\": content,\n                \"publishedDate\": publishedDate,\n                \"embedded\": embedded,\n                \"thumbnail\": thumbnail,\n            }\n        )\n\n    # return results\n    return results\n\n\ndef _fetch_supported_languages(resp):\n    import re\n\n    # https://docs.python.org/3/howto/regex.html#greedy-versus-non-greedy\n    videolanguages = re.search(r\"videoLanguages \\(\\) \\{(.*?)\\]\", resp.text, re.DOTALL)\n    peertube_languages = [m.group(1) for m in re.finditer(r\"\\{ id: '([a-z]+)', label:\", videolanguages.group(1))]\n    return peertube_languages\n", "path": "searx/engines/peertube.py"}]}