.oO SearXNG Developer Documentation Oo.
Loading...
Searching...
No Matches
open_meteo.py
Go to the documentation of this file.
1# SPDX-License-Identifier: AGPL-3.0-or-later
2"""Open Meteo (weather)"""
3
4from urllib.parse import urlencode, quote_plus
5from datetime import datetime
6from flask_babel import gettext
7
8from searx.network import get
9from searx.exceptions import SearxEngineAPIException
10
11about = {
12 "website": 'https://open-meteo.com',
13 "wikidata_id": None,
14 "official_api_documentation": 'https://open-meteo.com/en/docs',
15 "use_official_api": True,
16 "require_api_key": False,
17 "results": "JSON",
18}
19
20categories = ["weather"]
21
22geo_url = "https://geocoding-api.open-meteo.com"
23api_url = "https://api.open-meteo.com"
24
25data_of_interest = "temperature_2m,relative_humidity_2m,apparent_temperature,cloud_cover,pressure_msl,wind_speed_10m,wind_direction_10m" # pylint: disable=line-too-long
26
27
28def request(query, params):
29 location_url = f"{geo_url}/v1/search?name={quote_plus(query)}"
30
31 resp = get(location_url)
32 if resp.status_code != 200:
33 raise SearxEngineAPIException("invalid geo location response code")
34
35 json_locations = resp.json().get("results", [])
36 if len(json_locations) == 0:
37 raise SearxEngineAPIException("location not found")
38
39 location = json_locations[0]
40 args = {
41 'latitude': location['latitude'],
42 'longitude': location['longitude'],
43 'timeformat': 'unixtime',
44 'format': 'json',
45 'current': data_of_interest,
46 'forecast_days': 7,
47 'hourly': data_of_interest,
48 }
49
50 params['url'] = f"{api_url}/v1/forecast?{urlencode(args)}"
51
52 return params
53
54
55def c_to_f(temperature):
56 return "%.2f" % ((temperature * 1.8) + 32)
57
58
59def get_direction(degrees):
60 if degrees < 45 or degrees >= 315:
61 return "N"
62
63 if 45 <= degrees < 135:
64 return "O"
65
66 if 135 <= degrees < 225:
67 return "S"
68
69 return "W"
70
71
73 res = ""
74
75 res += (
76 f"<tr><td><b>{gettext('Temperature')}</b></td>"
77 f"<td><b>{condition['temperature_2m']}°C / {c_to_f(condition['temperature_2m'])}°F</b></td></tr>"
78 )
79
80 res += (
81 f"<tr><td>{gettext('Feels like')}</td><td>{condition['apparent_temperature']}°C / "
82 f"{c_to_f(condition['apparent_temperature'])}°F</td></tr>"
83 )
84
85 res += (
86 f"<tr><td>{gettext('Wind')}</td><td>{get_direction(condition['wind_direction_10m'])}, "
87 f"{condition['wind_direction_10m']}° — "
88 f"{condition['wind_speed_10m']} km/h</td></tr>"
89 )
90
91 res += f"<tr><td>{gettext('Cloud cover')}</td><td>{condition['cloud_cover']}%</td>"
92
93 res += f"<tr><td>{gettext('Humidity')}</td><td>{condition['relative_humidity_2m']}%</td></tr>"
94
95 res += f"<tr><td>{gettext('Pressure')}</td><td>{condition['pressure_msl']}hPa</td></tr>"
96
97 return res
98
99
100def response(resp):
101 data = resp.json()
102
103 table_content = generate_condition_table(data['current'])
104
105 infobox = f"<table><tbody>{table_content}</tbody></table>"
106
107 for index, time in enumerate(data['hourly']['time']):
108 hourly_data = {}
109
110 for key in data_of_interest.split(","):
111 hourly_data[key] = data['hourly'][key][index]
112
113 table_content = generate_condition_table(hourly_data)
114
115 infobox += f"<h3>{datetime.utcfromtimestamp(time).strftime('%Y-%m-%d %H:%M')}</h3>"
116 infobox += f"<table><tbody>{table_content}</tbody></table>"
117
118 return [{'infobox': 'Open Meteo', 'content': infobox}]
generate_condition_table(condition)
Definition open_meteo.py:72
request(query, params)
Definition open_meteo.py:28