summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBnyro <bnyro@tutanota.com>2025-04-24 17:28:16 +0200
committerMarkus Heiser <markus.heiser@darmarIT.de>2025-05-31 20:34:59 +0200
commitd70f0a3321b32816c0f277b4be9a43e4f1074b39 (patch)
tree9b59c2058e41296a3cffa4c70cf1611e185e8145
parent37d851fb23935166ac7714a83c7273ce712bece0 (diff)
[feat] result types: add weather result answerer and template
-rw-r--r--searx/result_types/__init__.py5
-rw-r--r--searx/result_types/answer.py54
-rw-r--r--searx/templates/simple/answer/weather.html67
3 files changed, 123 insertions, 3 deletions
diff --git a/searx/result_types/__init__.py b/searx/result_types/__init__.py
index e9a115ec3..8a82cf8d4 100644
--- a/searx/result_types/__init__.py
+++ b/searx/result_types/__init__.py
@@ -13,14 +13,14 @@
from __future__ import annotations
-__all__ = ["Result", "MainResult", "KeyValue", "EngineResults", "AnswerSet", "Answer", "Translations"]
+__all__ = ["Result", "MainResult", "KeyValue", "EngineResults", "AnswerSet", "Answer", "Translations", "Weather"]
import abc
from searx import enginelib
from ._base import Result, MainResult, LegacyResult
-from .answer import AnswerSet, Answer, Translations
+from .answer import AnswerSet, Answer, Translations, Weather
from .keyvalue import KeyValue
@@ -35,6 +35,7 @@ class ResultList(list, abc.ABC):
MainResult = MainResult
Result = Result
Translations = Translations
+ Weather = Weather
# for backward compatibility
LegacyResult = LegacyResult
diff --git a/searx/result_types/answer.py b/searx/result_types/answer.py
index a9f580e0e..d5793fac3 100644
--- a/searx/result_types/answer.py
+++ b/searx/result_types/answer.py
@@ -18,6 +18,10 @@ template.
:members:
:show-inheritance:
+.. autoclass:: Weather
+ :members:
+ :show-inheritance:
+
.. autoclass:: AnswerSet
:members:
:show-inheritance:
@@ -26,7 +30,7 @@ template.
from __future__ import annotations
-__all__ = ["AnswerSet", "Answer", "Translations"]
+__all__ = ["AnswerSet", "Answer", "Translations", "Weather"]
import msgspec
@@ -143,3 +147,51 @@ class Translations(BaseAnswer, kw_only=True):
synonyms: list[str] = []
"""List of synonyms for the requested translation."""
+
+
+class Weather(BaseAnswer, kw_only=True):
+ """Answer type for weather data."""
+
+ template: str = "answer/weather.html"
+ """The template is located at :origin:`answer/weather.html
+ <searx/templates/simple/answer/weather.html>`"""
+
+ location: str
+ """The geo-location the weather data is from (e.g. `Berlin, Germany`)."""
+
+ current: Weather.DataItem
+ """Current weather at ``location``."""
+
+ forecasts: list[Weather.DataItem] = []
+ """Weather forecasts for ``location``."""
+
+ def __post_init__(self):
+ if not self.location:
+ raise ValueError("Weather answer is missing a location")
+
+ class DataItem(msgspec.Struct, kw_only=True):
+ """A container for weather data such as temperature, humidity, ..."""
+
+ time: str | None = None
+ """Time of the forecast - not needed for the current weather."""
+
+ condition: str
+ """Weather condition, e.g. `cloudy`, `rainy`, `sunny` ..."""
+
+ temperature: str
+ """Temperature string, e.g. `17°C`"""
+
+ feelsLike: str | None = None
+ """Felt temperature string, should be formatted like ``temperature``"""
+
+ humidity: str | None = None
+ """Humidity percentage string, e.g. `60%`"""
+
+ pressure: str | None = None
+ """Pressure string, e.g. `1030hPa`"""
+
+ wind: str | None = None
+ """Information about the wind, e.g. `W, 231°, 10 m/s`"""
+
+ attributes: dict[str] = []
+ """Key-Value dict of additional weather attributes that are not available above"""
diff --git a/searx/templates/simple/answer/weather.html b/searx/templates/simple/answer/weather.html
new file mode 100644
index 000000000..4cea9b683
--- /dev/null
+++ b/searx/templates/simple/answer/weather.html
@@ -0,0 +1,67 @@
+{% macro show_weather_data(data) %}
+ <table>
+ <tbody>
+ {%- if data.condition -%}
+ <tr>
+ <td>{{ _("Condition") }}</td>
+ <td>{{ data.condition }}</td>
+ </tr>
+ {%- endif -%}
+ {%- if data.temperature -%}
+ <tr>
+ <td>{{ _("Temperature") }}</td>
+ <td>{{ data.temperature }}</td>
+ </tr>
+ {%- endif -%}
+ {%- if data.feelsLike -%}
+ <tr>
+ <td>{{ _("Feels Like") }}</td>
+ <td>{{ data.feelsLike }}</td>
+ </tr>
+ {%- endif -%}
+ {%- if data.wind -%}
+ <tr>
+ <td>{{ _("Wind") }}</td>
+ <td>{{ data.wind }}</td>
+ </tr>
+ {%- endif -%}
+ {%- if data.humidity -%}
+ <tr>
+ <td>{{ _("Humidity") }}</td>
+ <td>{{ data.humidity }}</td>
+ </tr>
+ {%- endif -%}
+ {%- if data.pressure -%}
+ <tr>
+ <td>{{ _("Pressure") }}</td>
+ <td>{{ data.pressure }}</td>
+ </tr>
+ {%- endif -%}
+ <tr>
+ {%- for name, value in data.attributes.items() -%}
+ <tr>
+ <td>{{ name }}</td>
+ <td>{{ value }}</td>
+ </tr>
+ {%- endfor -%}
+ </tbody>
+ </table>
+{% endmacro %}
+
+<details class="answer-weather">
+ <summary>It's currently {{ answer.current.condition }}, {{ answer.current.temperature }} in {{ answer.location }}</summary>
+ <div>
+ <h2 class="title">{{ answer.location }}</h2>
+ <h3>{{ _("Current condition") }}</h3>
+ {{ show_weather_data(answer.current) }}
+
+ {%- if answer.forecasts -%}
+ <div class="answer-weather-forecasts">
+ {%- for forecast in answer.forecasts -%}
+ <h3>{{ forecast.time }}</h3>
+ {{ show_weather_data(forecast) }}
+ {%- endfor -%}
+ </div>
+ {%- endif -%}
+ </div>
+</details>