From df4f31810368aa6b679c2d7a5874900cc431d42c Mon Sep 17 00:00:00 2001 From: ta Date: Wed, 31 Aug 2022 17:29:32 +0700 Subject: [PATCH] [mod] add duckduckgo weather engine --- searx/engines/duckduckgo_weather.py | 121 ++++++++++++++++++++++++++++ searx/searxng.msg | 1 + searx/settings.yml | 5 ++ 3 files changed, 127 insertions(+) create mode 100644 searx/engines/duckduckgo_weather.py diff --git a/searx/engines/duckduckgo_weather.py b/searx/engines/duckduckgo_weather.py new file mode 100644 index 000000000..78f131dd4 --- /dev/null +++ b/searx/engines/duckduckgo_weather.py @@ -0,0 +1,121 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +# lint: pylint +"""DuckDuckGo Weather""" + +from json import loads +from urllib.parse import quote + +from datetime import datetime + +about = { + "website": 'https://duckduckgo.com/', + "wikidata_id": 'Q12805', + "official_api_documentation": None, + "use_official_api": True, + "require_api_key": False, + "results": "JSON", +} + +categories = ["weather"] + +url = "https://duckduckgo.com/js/spice/forecast/{query}/{lang}" + + +def request(query, params): + params["url"] = url.format(query=quote(query), lang=params['language'].split('-')[0]) + + return params + + +def f_to_c(temperature): + return "%.2f" % ((temperature - 32) / 1.8) + + +def response(resp): + results = [] + + if resp.text.strip() == "ddg_spice_forecast();": + return [] + + result = loads(resp.text[resp.text.find('{') : resp.text.rfind('}') + 1]) + + current = result["currently"] + + forecast_data = [] + last_date = None + current_data = {} + + for time in result['hourly']['data']: + current_time = datetime.fromtimestamp(time['time']) + + if last_date != current_time.date(): + if last_date is not None: + forecast_data.append(current_data) + + today = next( + day + for day in result['daily']['data'] + if datetime.fromtimestamp(day['time']).date() == current_time.date() + ) + + current_data = { + 'date': current_time.strftime('%Y-%m-%d'), + 'metric': { + 'min_temp': f_to_c(today['temperatureLow']), + 'max_temp': f_to_c(today['temperatureHigh']), + }, + 'uv_index': today['uvIndex'], + 'sunrise': datetime.fromtimestamp(today['sunriseTime']).strftime('%H:%M'), + 'sunset': datetime.fromtimestamp(today['sunsetTime']).strftime('%H:%M'), + 'forecast': [], + } + + current_data['forecast'].append( + { + 'time': current_time.strftime('%H:%M'), + 'metric': { + 'temperature': f_to_c(time['temperature']), + 'feels_like': f_to_c(time['apparentTemperature']), + 'wind_speed': '%.2f' % (time['windSpeed'] * 1.6093440006147), + 'visibility': time['visibility'], + }, + 'imperial': { + 'temperature': time['temperature'], + 'feels_like': time['apparentTemperature'], + 'wind_speed': time['windSpeed'], + }, + 'condition': time['summary'], + 'wind_direction': time['windBearing'], + 'humidity': time['humidity'] * 100, + } + ) + + last_date = current_time.date() + + forecast_data.append(current_data) + + results.append( + { + 'template': 'weather.html', + 'location': result['flags']['ddg-location'], + 'currently': { + 'metric': { + 'temperature': f_to_c(current['temperature']), + 'feels_like': f_to_c(current['apparentTemperature']), + 'wind_speed': '%.2f' % (current['windSpeed'] * 1.6093440006147), + 'visibility': current['visibility'], + }, + 'imperial': { + 'temperature': current['temperature'], + 'feels_like': current['apparentTemperature'], + 'wind_speed': current['windSpeed'], + }, + 'condition': current['summary'], + 'wind_direction': current['windBearing'], + 'humidity': current['humidity'] * 100, + }, + 'forecast': forecast_data, + } + ) + + return results diff --git a/searx/searxng.msg b/searx/searxng.msg index 3b876f96d..09aba9058 100644 --- a/searx/searxng.msg +++ b/searx/searxng.msg @@ -31,6 +31,7 @@ CATEGORY_NAMES = { 'MAP': 'map', 'ONIONS': 'onions', 'SCIENCE': 'science', + 'WEATHER': 'weather', } CATEGORY_GROUPS = { diff --git a/searx/settings.yml b/searx/settings.yml index 197d7f949..f5523793a 100644 --- a/searx/settings.yml +++ b/searx/settings.yml @@ -553,6 +553,11 @@ engines: timeout: 3.0 disabled: true + - name: duckduckgo weather + engine: duckduckgo_weather + shortcut: ddw + disabled: true + - name: apple maps engine: apple_maps shortcut: apm