prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  [FEATURE REQUEST] language filtering and safe search with odysee
  **Is your feature request related to a problem? Please describe.**
  No
  
  **Describe the solution you'd like**
  We can use, for example, language=de in the search URL. en, de-DE, and en-US also seem to work. There is no list of supported languages afaik, we just need to try things out one by one.
  
  for safe search Moderate/Strict we should use nsfw=false in the URL
  
  **Additional context**
  The information that you need for this is here: https://github.com/searx/searx/issues/2504
  
  
  ----
  Related
  
  - https://github.com/searxng/searxng/pull/2656
  - https://github.com/searxng/searxng/issues/590
  - [lbr command line](https://gitlab.com/gardenappl/lbt/-/blob/main/lbt?ref_type=heads)
  - [LBRY SDK ](https://github.com/lbryio/lbry-sdk/)
  
  
  --- 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/odysee.py`
  Content:
  ```
  1 # SPDX-License-Identifier: AGPL-3.0-or-later
  2 # lint: pylint
  3 """Odysee_ is a decentralised video hosting platform.
  4 
  5 .. _Odysee: https://github.com/OdyseeTeam/odysee-frontend
  6 """
  7 
  8 import time
  9 from urllib.parse import urlencode
  10 from datetime import datetime
  11 
  12 # Engine metadata
  13 about = {
  14     "website": "https://odysee.com/",
  15     "wikidata_id": "Q102046570",
  16     "official_api_documentation": None,
  17     "use_official_api": False,
  18     "require_api_key": False,
  19     "results": "JSON",
  20 }
  21 
  22 # Engine configuration
  23 paging = True
  24 results_per_page = 20
  25 categories = ['videos']
  26 
  27 # Search URL (Note: lighthouse.lbry.com/search works too, and may be faster at times)
  28 base_url = "https://lighthouse.odysee.tv/search"
  29 
  30 
  31 def request(query, params):
  32     start_index = (params["pageno"] - 1) * results_per_page
  33     query_params = {
  34         "s": query,
  35         "size": results_per_page,
  36         "from": start_index,
  37         "include": "channel,thumbnail_url,title,description,duration,release_time",
  38         "mediaType": "video",
  39     }
  40 
  41     params["url"] = f"{base_url}?{urlencode(query_params)}"
  42     return params
  43 
  44 
  45 # Format the video duration
  46 def format_duration(duration):
  47     seconds = int(duration)
  48     length = time.gmtime(seconds)
  49     if length.tm_hour:
  50         return time.strftime("%H:%M:%S", length)
  51     return time.strftime("%M:%S", length)
  52 
  53 
  54 def response(resp):
  55     data = resp.json()
  56     results = []
  57 
  58     for item in data:
  59         name = item["name"]
  60         claim_id = item["claimId"]
  61         title = item["title"]
  62         thumbnail_url = item["thumbnail_url"]
  63         description = item["description"] or ""
  64         channel = item["channel"]
  65         release_time = item["release_time"]
  66         duration = item["duration"]
  67 
  68         release_date = datetime.strptime(release_time.split("T")[0], "%Y-%m-%d")
  69         formatted_date = datetime.utcfromtimestamp(release_date.timestamp())
  70 
  71         url = f"https://odysee.com/{name}:{claim_id}"
  72         iframe_url = f"https://odysee.com/$/embed/{name}:{claim_id}"
  73         odysee_thumbnail = f"https://thumbnails.odycdn.com/optimize/s:390:0/quality:85/plain/{thumbnail_url}"
  74         formatted_duration = format_duration(duration)
  75 
  76         results.append(
  77             {
  78                 "title": title,
  79                 "url": url,
  80                 "content": description,
  81                 "author": channel,
  82                 "publishedDate": formatted_date,
  83                 "length": formatted_duration,
  84                 "thumbnail": odysee_thumbnail,
  85                 "iframe_src": iframe_url,
  86                 "template": "videos.html",
  87             }
  88         )
  89 
  90     return results
  91
  ```
  --- 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/odysee.py b/searx/engines/odysee.py
  --- a/searx/engines/odysee.py
  +++ b/searx/engines/odysee.py
  @@ -9,6 +9,14 @@
   from urllib.parse import urlencode
   from datetime import datetime
   
  +import babel
  +
  +from searx.network import get
  +from searx.locales import language_tag
  +from searx.enginelib.traits import EngineTraits
  +
  +traits: EngineTraits
  +
   # Engine metadata
   about = {
       "website": "https://odysee.com/",
  @@ -21,6 +29,7 @@
   
   # Engine configuration
   paging = True
  +time_range_support = True
   results_per_page = 20
   categories = ['videos']
   
  @@ -29,6 +38,13 @@
   
   
   def request(query, params):
  +    time_range_dict = {
  +        "day": "today",
  +        "week": "thisweek",
  +        "month": "thismonth",
  +        "year": "thisyear",
  +    }
  +
       start_index = (params["pageno"] - 1) * results_per_page
       query_params = {
           "s": query,
  @@ -38,6 +54,13 @@
           "mediaType": "video",
       }
   
  +    lang = traits.get_language(params['searxng_locale'], None)
  +    if lang is not None:
  +        query_params['language'] = lang
  +
  +    if params['time_range'] in time_range_dict:
  +        query_params['time_filter'] = time_range_dict[params['time_range']]
  +
       params["url"] = f"{base_url}?{urlencode(query_params)}"
       return params
   
  @@ -88,3 +111,35 @@
           )
   
       return results
  +
  +
  +def fetch_traits(engine_traits: EngineTraits):
  +    """
  +    Fetch languages from Odysee's source code.
  +    """
  +
  +    resp = get(
  +        'https://raw.githubusercontent.com/OdyseeTeam/odysee-frontend/master/ui/constants/supported_browser_languages.js',  # pylint: disable=line-too-long
  +        timeout=60,
  +    )
  +
  +    if not resp.ok:
  +        print("ERROR: can't determine languages from Odysee")
  +        return
  +
  +    for line in resp.text.split("\n")[1:-4]:
  +        lang_tag = line.strip().split(": ")[0].replace("'", "")
  +
  +        try:
  +            sxng_tag = language_tag(babel.Locale.parse(lang_tag, sep="-"))
  +        except babel.UnknownLocaleError:
  +            print("ERROR: %s is unknown by babel" % lang_tag)
  +            continue
  +
  +        conflict = engine_traits.languages.get(sxng_tag)
  +        if conflict:
  +            if conflict != lang_tag:
  +                print("CONFLICT: babel %s --> %s, %s" % (sxng_tag, conflict, lang_tag))
  +            continue
  +
  +        engine_traits.languages[sxng_tag] = lang_tag
  
verification_info: {"golden_diff": "diff --git a/searx/engines/odysee.py b/searx/engines/odysee.py\n--- a/searx/engines/odysee.py\n+++ b/searx/engines/odysee.py\n@@ -9,6 +9,14 @@\n from urllib.parse import urlencode\n from datetime import datetime\n \n+import babel\n+\n+from searx.network import get\n+from searx.locales import language_tag\n+from searx.enginelib.traits import EngineTraits\n+\n+traits: EngineTraits\n+\n # Engine metadata\n about = {\n     \"website\": \"https://odysee.com/\",\n@@ -21,6 +29,7 @@\n \n # Engine configuration\n paging = True\n+time_range_support = True\n results_per_page = 20\n categories = ['videos']\n \n@@ -29,6 +38,13 @@\n \n \n def request(query, params):\n+    time_range_dict = {\n+        \"day\": \"today\",\n+        \"week\": \"thisweek\",\n+        \"month\": \"thismonth\",\n+        \"year\": \"thisyear\",\n+    }\n+\n     start_index = (params[\"pageno\"] - 1) * results_per_page\n     query_params = {\n         \"s\": query,\n@@ -38,6 +54,13 @@\n         \"mediaType\": \"video\",\n     }\n \n+    lang = traits.get_language(params['searxng_locale'], None)\n+    if lang is not None:\n+        query_params['language'] = lang\n+\n+    if params['time_range'] in time_range_dict:\n+        query_params['time_filter'] = time_range_dict[params['time_range']]\n+\n     params[\"url\"] = f\"{base_url}?{urlencode(query_params)}\"\n     return params\n \n@@ -88,3 +111,35 @@\n         )\n \n     return results\n+\n+\n+def fetch_traits(engine_traits: EngineTraits):\n+    \"\"\"\n+    Fetch languages from Odysee's source code.\n+    \"\"\"\n+\n+    resp = get(\n+        'https://raw.githubusercontent.com/OdyseeTeam/odysee-frontend/master/ui/constants/supported_browser_languages.js',  # pylint: disable=line-too-long\n+        timeout=60,\n+    )\n+\n+    if not resp.ok:\n+        print(\"ERROR: can't determine languages from Odysee\")\n+        return\n+\n+    for line in resp.text.split(\"\\n\")[1:-4]:\n+        lang_tag = line.strip().split(\": \")[0].replace(\"'\", \"\")\n+\n+        try:\n+            sxng_tag = language_tag(babel.Locale.parse(lang_tag, sep=\"-\"))\n+        except babel.UnknownLocaleError:\n+            print(\"ERROR: %s is unknown by babel\" % lang_tag)\n+            continue\n+\n+        conflict = engine_traits.languages.get(sxng_tag)\n+        if conflict:\n+            if conflict != lang_tag:\n+                print(\"CONFLICT: babel %s --> %s, %s\" % (sxng_tag, conflict, lang_tag))\n+            continue\n+\n+        engine_traits.languages[sxng_tag] = lang_tag\n", "issue": "[FEATURE REQUEST] language filtering and safe search with odysee\n**Is your feature request related to a problem? Please describe.**\r\nNo\r\n\r\n**Describe the solution you'd like**\r\nWe can use, for example, language=de in the search URL. en, de-DE, and en-US also seem to work. There is no list of supported languages afaik, we just need to try things out one by one.\r\n\r\nfor safe search Moderate/Strict we should use nsfw=false in the URL\r\n\r\n**Additional context**\r\nThe information that you need for this is here: https://github.com/searx/searx/issues/2504\r\n\r\n\r\n----\r\nRelated\r\n\r\n- https://github.com/searxng/searxng/pull/2656\r\n- https://github.com/searxng/searxng/issues/590\r\n- [lbr command line](https://gitlab.com/gardenappl/lbt/-/blob/main/lbt?ref_type=heads)\r\n- [LBRY SDK ](https://github.com/lbryio/lbry-sdk/)\r\n\n", "before_files": [{"content": "# SPDX-License-Identifier: AGPL-3.0-or-later\n# lint: pylint\n\"\"\"Odysee_ is a decentralised video hosting platform.\n\n.. _Odysee: https://github.com/OdyseeTeam/odysee-frontend\n\"\"\"\n\nimport time\nfrom urllib.parse import urlencode\nfrom datetime import datetime\n\n# Engine metadata\nabout = {\n    \"website\": \"https://odysee.com/\",\n    \"wikidata_id\": \"Q102046570\",\n    \"official_api_documentation\": None,\n    \"use_official_api\": False,\n    \"require_api_key\": False,\n    \"results\": \"JSON\",\n}\n\n# Engine configuration\npaging = True\nresults_per_page = 20\ncategories = ['videos']\n\n# Search URL (Note: lighthouse.lbry.com/search works too, and may be faster at times)\nbase_url = \"https://lighthouse.odysee.tv/search\"\n\n\ndef request(query, params):\n    start_index = (params[\"pageno\"] - 1) * results_per_page\n    query_params = {\n        \"s\": query,\n        \"size\": results_per_page,\n        \"from\": start_index,\n        \"include\": \"channel,thumbnail_url,title,description,duration,release_time\",\n        \"mediaType\": \"video\",\n    }\n\n    params[\"url\"] = f\"{base_url}?{urlencode(query_params)}\"\n    return params\n\n\n# Format the video duration\ndef format_duration(duration):\n    seconds = int(duration)\n    length = time.gmtime(seconds)\n    if length.tm_hour:\n        return time.strftime(\"%H:%M:%S\", length)\n    return time.strftime(\"%M:%S\", length)\n\n\ndef response(resp):\n    data = resp.json()\n    results = []\n\n    for item in data:\n        name = item[\"name\"]\n        claim_id = item[\"claimId\"]\n        title = item[\"title\"]\n        thumbnail_url = item[\"thumbnail_url\"]\n        description = item[\"description\"] or \"\"\n        channel = item[\"channel\"]\n        release_time = item[\"release_time\"]\n        duration = item[\"duration\"]\n\n        release_date = datetime.strptime(release_time.split(\"T\")[0], \"%Y-%m-%d\")\n        formatted_date = datetime.utcfromtimestamp(release_date.timestamp())\n\n        url = f\"https://odysee.com/{name}:{claim_id}\"\n        iframe_url = f\"https://odysee.com/$/embed/{name}:{claim_id}\"\n        odysee_thumbnail = f\"https://thumbnails.odycdn.com/optimize/s:390:0/quality:85/plain/{thumbnail_url}\"\n        formatted_duration = format_duration(duration)\n\n        results.append(\n            {\n                \"title\": title,\n                \"url\": url,\n                \"content\": description,\n                \"author\": channel,\n                \"publishedDate\": formatted_date,\n                \"length\": formatted_duration,\n                \"thumbnail\": odysee_thumbnail,\n                \"iframe_src\": iframe_url,\n                \"template\": \"videos.html\",\n            }\n        )\n\n    return results\n", "path": "searx/engines/odysee.py"}], "after_files": [{"content": "# SPDX-License-Identifier: AGPL-3.0-or-later\n# lint: pylint\n\"\"\"Odysee_ is a decentralised video hosting platform.\n\n.. _Odysee: https://github.com/OdyseeTeam/odysee-frontend\n\"\"\"\n\nimport time\nfrom urllib.parse import urlencode\nfrom datetime import datetime\n\nimport babel\n\nfrom searx.network import get\nfrom searx.locales import language_tag\nfrom searx.enginelib.traits import EngineTraits\n\ntraits: EngineTraits\n\n# Engine metadata\nabout = {\n    \"website\": \"https://odysee.com/\",\n    \"wikidata_id\": \"Q102046570\",\n    \"official_api_documentation\": None,\n    \"use_official_api\": False,\n    \"require_api_key\": False,\n    \"results\": \"JSON\",\n}\n\n# Engine configuration\npaging = True\ntime_range_support = True\nresults_per_page = 20\ncategories = ['videos']\n\n# Search URL (Note: lighthouse.lbry.com/search works too, and may be faster at times)\nbase_url = \"https://lighthouse.odysee.tv/search\"\n\n\ndef request(query, params):\n    time_range_dict = {\n        \"day\": \"today\",\n        \"week\": \"thisweek\",\n        \"month\": \"thismonth\",\n        \"year\": \"thisyear\",\n    }\n\n    start_index = (params[\"pageno\"] - 1) * results_per_page\n    query_params = {\n        \"s\": query,\n        \"size\": results_per_page,\n        \"from\": start_index,\n        \"include\": \"channel,thumbnail_url,title,description,duration,release_time\",\n        \"mediaType\": \"video\",\n    }\n\n    lang = traits.get_language(params['searxng_locale'], None)\n    if lang is not None:\n        query_params['language'] = lang\n\n    if params['time_range'] in time_range_dict:\n        query_params['time_filter'] = time_range_dict[params['time_range']]\n\n    params[\"url\"] = f\"{base_url}?{urlencode(query_params)}\"\n    return params\n\n\n# Format the video duration\ndef format_duration(duration):\n    seconds = int(duration)\n    length = time.gmtime(seconds)\n    if length.tm_hour:\n        return time.strftime(\"%H:%M:%S\", length)\n    return time.strftime(\"%M:%S\", length)\n\n\ndef response(resp):\n    data = resp.json()\n    results = []\n\n    for item in data:\n        name = item[\"name\"]\n        claim_id = item[\"claimId\"]\n        title = item[\"title\"]\n        thumbnail_url = item[\"thumbnail_url\"]\n        description = item[\"description\"] or \"\"\n        channel = item[\"channel\"]\n        release_time = item[\"release_time\"]\n        duration = item[\"duration\"]\n\n        release_date = datetime.strptime(release_time.split(\"T\")[0], \"%Y-%m-%d\")\n        formatted_date = datetime.utcfromtimestamp(release_date.timestamp())\n\n        url = f\"https://odysee.com/{name}:{claim_id}\"\n        iframe_url = f\"https://odysee.com/$/embed/{name}:{claim_id}\"\n        odysee_thumbnail = f\"https://thumbnails.odycdn.com/optimize/s:390:0/quality:85/plain/{thumbnail_url}\"\n        formatted_duration = format_duration(duration)\n\n        results.append(\n            {\n                \"title\": title,\n                \"url\": url,\n                \"content\": description,\n                \"author\": channel,\n                \"publishedDate\": formatted_date,\n                \"length\": formatted_duration,\n                \"thumbnail\": odysee_thumbnail,\n                \"iframe_src\": iframe_url,\n                \"template\": \"videos.html\",\n            }\n        )\n\n    return results\n\n\ndef fetch_traits(engine_traits: EngineTraits):\n    \"\"\"\n    Fetch languages from Odysee's source code.\n    \"\"\"\n\n    resp = get(\n        'https://raw.githubusercontent.com/OdyseeTeam/odysee-frontend/master/ui/constants/supported_browser_languages.js',  # pylint: disable=line-too-long\n        timeout=60,\n    )\n\n    if not resp.ok:\n        print(\"ERROR: can't determine languages from Odysee\")\n        return\n\n    for line in resp.text.split(\"\\n\")[1:-4]:\n        lang_tag = line.strip().split(\": \")[0].replace(\"'\", \"\")\n\n        try:\n            sxng_tag = language_tag(babel.Locale.parse(lang_tag, sep=\"-\"))\n        except babel.UnknownLocaleError:\n            print(\"ERROR: %s is unknown by babel\" % lang_tag)\n            continue\n\n        conflict = engine_traits.languages.get(sxng_tag)\n        if conflict:\n            if conflict != lang_tag:\n                print(\"CONFLICT: babel %s --> %s, %s\" % (sxng_tag, conflict, lang_tag))\n            continue\n\n        engine_traits.languages[sxng_tag] = lang_tag\n", "path": "searx/engines/odysee.py"}]}