duckduckgo_weather.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # lint: pylint
  3. """DuckDuckGo Weather"""
  4. from json import loads
  5. from urllib.parse import quote
  6. from datetime import datetime
  7. from flask_babel import gettext
  8. about = {
  9. "website": 'https://duckduckgo.com/',
  10. "wikidata_id": 'Q12805',
  11. "official_api_documentation": None,
  12. "use_official_api": True,
  13. "require_api_key": False,
  14. "results": "JSON",
  15. }
  16. categories = ["others"]
  17. url = "https://duckduckgo.com/js/spice/forecast/{query}/{lang}"
  18. def generate_condition_table(condition):
  19. res = ""
  20. res += f"<tr><td><b>{gettext('Condition')}</b></td>" f"<td><b>{condition['summary']}</b></td></tr>"
  21. res += (
  22. f"<tr><td><b>{gettext('Temperature')}</b></td>"
  23. f"<td><b>{f_to_c(condition['temperature'])}°C / {condition['temperature']}°F</b></td></tr>"
  24. )
  25. res += (
  26. f"<tr><td>{gettext('Feels like')}</td><td>{f_to_c(condition['apparentTemperature'])}°C / "
  27. f"{condition['apparentTemperature']}°F</td></tr>"
  28. )
  29. res += (
  30. f"<tr><td>{gettext('Wind')}</td><td>{condition['windBearing']}° — "
  31. f"{(condition['windSpeed'] * 1.6093440006147):.2f} km/h / {condition['windSpeed']} mph</td></tr>"
  32. )
  33. res += f"<tr><td>{gettext('Visibility')}</td><td>{condition['visibility']} km</td>"
  34. res += f"<tr><td>{gettext('Humidity')}</td><td>{(condition['humidity'] * 100):.1f}%</td></tr>"
  35. return res
  36. def generate_day_table(day):
  37. res = ""
  38. res += (
  39. f"<tr><td>{gettext('Min temp.')}</td><td>{f_to_c(day['temperatureLow'])}°C / "
  40. f"{day['temperatureLow']}°F</td></tr>"
  41. )
  42. res += (
  43. f"<tr><td>{gettext('Max temp.')}</td><td>{f_to_c(day['temperatureHigh'])}°C / "
  44. f"{day['temperatureHigh']}°F</td></tr>"
  45. )
  46. res += f"<tr><td>{gettext('UV index')}</td><td>{day['uvIndex']}</td></tr>"
  47. res += (
  48. f"<tr><td>{gettext('Sunrise')}</td><td>{datetime.fromtimestamp(day['sunriseTime']).strftime('%H:%M')}</td></tr>"
  49. )
  50. res += (
  51. f"<tr><td>{gettext('Sunset')}</td><td>{datetime.fromtimestamp(day['sunsetTime']).strftime('%H:%M')}</td></tr>"
  52. )
  53. return res
  54. def request(query, params):
  55. params["url"] = url.format(query=quote(query), lang=params['language'].split('-')[0])
  56. return params
  57. def f_to_c(temperature):
  58. return "%.2f" % ((temperature - 32) / 1.8)
  59. def response(resp):
  60. results = []
  61. if resp.text.strip() == "ddg_spice_forecast();":
  62. return []
  63. result = loads(resp.text[resp.text.find('\n') + 1 : resp.text.rfind('\n') - 2])
  64. current = result["currently"]
  65. title = result['flags']['ddg-location']
  66. infobox = f"<h3>{gettext('Current condition')}</h3><table><tbody>"
  67. infobox += generate_condition_table(current)
  68. infobox += "</tbody></table>"
  69. last_date = None
  70. for time in result['hourly']['data']:
  71. current_time = datetime.fromtimestamp(time['time'])
  72. if last_date != current_time.date():
  73. if last_date is not None:
  74. infobox += "</tbody></table>"
  75. infobox += f"<h3>{current_time.strftime('%Y-%m-%d')}</h3>"
  76. infobox += "<table><tbody>"
  77. for day in result['daily']['data']:
  78. if datetime.fromtimestamp(day['time']).date() == current_time.date():
  79. infobox += generate_day_table(day)
  80. infobox += "</tbody></table><table><tbody>"
  81. last_date = current_time.date()
  82. infobox += f"<tr><td rowspan=\"7\"><b>{current_time.strftime('%H:%M')}</b></td></tr>"
  83. infobox += generate_condition_table(time)
  84. infobox += "</tbody></table>"
  85. results.append(
  86. {
  87. "infobox": title,
  88. "content": infobox,
  89. }
  90. )
  91. return results