.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
wttr.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2"""wttr.in (weather forecast service)"""
3
4from urllib.parse import quote
5from datetime import datetime
6
7from searx.result_types import EngineResults, WeatherAnswer
8from searx import weather
9
10about = {
11 "website": "https://wttr.in",
12 "wikidata_id": "Q107586666",
13 "official_api_documentation": "https://github.com/chubin/wttr.in#json-output",
14 "use_official_api": True,
15 "require_api_key": False,
16 "results": "JSON",
17}
18
19categories = ["weather"]
20
21url = "https://wttr.in/{query}?format=j1&lang={lang}"
22
23# adapted from https://github.com/chubin/wttr.in/blob/master/lib/constants.py
24WWO_TO_CONDITION: dict[str, weather.WeatherConditionType] = {
25 "113": "clear sky",
26 "116": "partly cloudy",
27 "119": "cloudy",
28 "122": "fair",
29 "143": "fair",
30 "176": "light rain showers",
31 "179": "light snow showers",
32 "182": "light sleet showers",
33 "185": "light sleet",
34 "200": "rain and thunder",
35 "227": "light snow",
36 "230": "heavy snow",
37 "248": "fog",
38 "260": "fog",
39 "263": "light rain showers",
40 "266": "light rain showers",
41 "281": "light sleet showers",
42 "284": "light snow showers",
43 "293": "light rain showers",
44 "296": "light rain",
45 "299": "rain showers",
46 "302": "rain",
47 "305": "heavy rain showers",
48 "308": "heavy rain",
49 "311": "light sleet",
50 "314": "sleet",
51 "317": "light sleet",
52 "320": "heavy sleet",
53 "323": "light snow showers",
54 "326": "light snow showers",
55 "329": "heavy snow showers",
56 "332": "heavy snow",
57 "335": "heavy snow showers",
58 "338": "heavy snow",
59 "350": "light sleet",
60 "353": "light rain showers",
61 "356": "heavy rain showers",
62 "359": "heavy rain",
63 "362": "light sleet showers",
64 "365": "sleet showers",
65 "368": "light snow showers",
66 "371": "heavy snow showers",
67 "374": "light sleet showers",
68 "377": "heavy sleet",
69 "386": "rain showers and thunder",
70 "389": "heavy rain showers and thunder",
71 "392": "snow showers and thunder",
72 "395": "heavy snow showers",
73}
74
75
76def request(query, params):
77 params["url"] = url.format(query=quote(query), lang=params["language"])
78 params["raise_for_httperror"] = False
79
80 return params
81
82
83def _weather_data(location: weather.GeoLocation, data: dict):
84 # the naming between different data objects is inconsitent, thus temp_C and
85 # tempC are possible
86 tempC: float = data.get("temp_C") or data.get("tempC") # type: ignore
87
88 return WeatherAnswer.Item(
89 location=location,
90 temperature=weather.Temperature(unit="°C", value=tempC),
91 condition=WWO_TO_CONDITION[data["weatherCode"]],
92 feels_like=weather.Temperature(unit="°C", value=data["FeelsLikeC"]),
93 wind_from=weather.Compass(int(data["winddirDegree"])),
94 wind_speed=weather.WindSpeed(data["windspeedKmph"], unit="km/h"),
95 pressure=weather.Pressure(data["pressure"], unit="hPa"),
96 humidity=weather.RelativeHumidity(data["humidity"]),
97 cloud_cover=data["cloudcover"],
98 )
99
100
101def response(resp):
102 res = EngineResults()
103
104 if resp.status_code == 404:
105 return res
106
107 json_data = resp.json()
108 geoloc = weather.GeoLocation.by_query(resp.search_params["query"])
109
110 weather_answer = WeatherAnswer(
111 current=_weather_data(geoloc, json_data["current_condition"][0]),
112 service="wttr.in",
113 )
114
115 for day in json_data["weather"]:
116 date = datetime.fromisoformat(day["date"])
117 time_slot_len = 24 // len(day["hourly"])
118 for index, forecast in enumerate(day["hourly"]):
119 forecast_data = _weather_data(geoloc, forecast)
120 forecast_data.datetime = weather.DateTime(date.replace(hour=index * time_slot_len + 1))
121 weather_answer.forecasts.append(forecast_data)
122
123 res.add(weather_answer)
124 return res
_weather_data(weather.GeoLocation location, dict data)
Definition wttr.py:83
request(query, params)
Definition wttr.py:76