diff options
| author | Bnyro <bnyro@tutanota.com> | 2025-04-24 17:28:16 +0200 |
|---|---|---|
| committer | Markus Heiser <markus.heiser@darmarIT.de> | 2025-05-31 20:34:59 +0200 |
| commit | d70f0a3321b32816c0f277b4be9a43e4f1074b39 (patch) | |
| tree | 9b59c2058e41296a3cffa4c70cf1611e185e8145 | |
| parent | 37d851fb23935166ac7714a83c7273ce712bece0 (diff) | |
[feat] result types: add weather result answerer and template
| -rw-r--r-- | searx/result_types/__init__.py | 5 | ||||
| -rw-r--r-- | searx/result_types/answer.py | 54 | ||||
| -rw-r--r-- | searx/templates/simple/answer/weather.html | 67 |
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> |