wttr.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. # SPDX-License-Identifier: AGPL-3.0-or-later
  2. # lint: pylint
  3. """wttr.in (weather forecast service)"""
  4. from json import loads
  5. from urllib.parse import quote
  6. from flask_babel import gettext
  7. about = {
  8. "website": "https://wttr.in",
  9. "wikidata_id": "Q107586666",
  10. "official_api_documentation": "https://github.com/chubin/wttr.in#json-output",
  11. "use_official_api": True,
  12. "require_api_key": False,
  13. "results": "JSON",
  14. }
  15. categories = ["others"]
  16. url = "https://wttr.in/{query}?format=j1&lang={lang}"
  17. def get_weather_condition_key(lang):
  18. if lang == "en":
  19. return "weatherDesc"
  20. return "lang_" + lang.lower()
  21. def generate_day_table(day):
  22. res = ""
  23. res += f"<tr><td>{gettext('Average temp.')}</td><td>{day['avgtempC']}°C / {day['avgtempF']}°F</td></tr>"
  24. res += f"<tr><td>{gettext('Min temp.')}</td><td>{day['mintempC']}°C / {day['mintempF']}°F</td></tr>"
  25. res += f"<tr><td>{gettext('Max temp.')}</td><td>{day['maxtempC']}°C / {day['maxtempF']}°F</td></tr>"
  26. res += f"<tr><td>{gettext('UV index')}</td><td>{day['uvIndex']}</td></tr>"
  27. res += f"<tr><td>{gettext('Sunrise')}</td><td>{day['astronomy'][0]['sunrise']}</td></tr>"
  28. res += f"<tr><td>{gettext('Sunset')}</td><td>{day['astronomy'][0]['sunset']}</td></tr>"
  29. return res
  30. def generate_condition_table(condition, lang, current=False):
  31. res = ""
  32. if current:
  33. key = "temp_"
  34. else:
  35. key = "temp"
  36. res += (
  37. f"<tr><td><b>{gettext('Condition')}</b></td>"
  38. f"<td><b>{condition[get_weather_condition_key(lang)][0]['value']}</b></td></tr>"
  39. )
  40. res += (
  41. f"<tr><td><b>{gettext('Temperature')}</b></td>"
  42. f"<td><b>{condition[key+'C']}°C / {condition[key+'F']}°F</b></td></tr>"
  43. )
  44. res += (
  45. f"<tr><td>{gettext('Feels like')}</td><td>{condition['FeelsLikeC']}°C / {condition['FeelsLikeF']}°F</td></tr>"
  46. )
  47. res += (
  48. f"<tr><td>{gettext('Wind')}</td><td>{condition['winddir16Point']} — "
  49. f"{condition['windspeedKmph']} km/h / {condition['windspeedMiles']} mph</td></tr>"
  50. )
  51. res += (
  52. f"<tr><td>{gettext('Visibility')}</td><td>{condition['visibility']} km / {condition['visibilityMiles']} mi</td>"
  53. )
  54. res += f"<tr><td>{gettext('Humidity')}</td><td>{condition['humidity']}%</td></tr>"
  55. return res
  56. def request(query, params):
  57. if query.replace('/', '') in [":help", ":bash.function", ":translation"]:
  58. return None
  59. if params["language"] == "all":
  60. params["language"] = "en"
  61. else:
  62. params["language"] = params["language"].split("-")[0]
  63. params["url"] = url.format(query=quote(query), lang=params["language"])
  64. params["raise_for_httperror"] = False
  65. return params
  66. def response(resp):
  67. results = []
  68. if resp.status_code == 404:
  69. return []
  70. result = loads(resp.text)
  71. current = result["current_condition"][0]
  72. location = result['nearest_area'][0]
  73. forecast_indices = {3: gettext('Morning'), 4: gettext('Noon'), 6: gettext('Evening'), 7: gettext('Night')}
  74. title = f"{location['areaName'][0]['value']}, {location['region'][0]['value']}"
  75. infobox = f"<h3>{gettext('Current condition')}</h3><table><tbody>"
  76. infobox += generate_condition_table(current, resp.search_params['language'], True)
  77. infobox += "</tbody></table>"
  78. for day in result["weather"]:
  79. infobox += f"<h3>{day['date']}</h3>"
  80. infobox += "<table><tbody>"
  81. infobox += generate_day_table(day)
  82. infobox += "</tbody></table>"
  83. infobox += "<table><tbody>"
  84. for time in forecast_indices.items():
  85. infobox += f"<tr><td rowspan=\"7\"><b>{time[1]}</b></td></tr>"
  86. infobox += generate_condition_table(day['hourly'][time[0]], resp.search_params['language'])
  87. infobox += "</tbody></table>"
  88. results.append(
  89. {
  90. "infobox": title,
  91. "content": infobox,
  92. }
  93. )
  94. return results