-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathweather_cog.py
161 lines (137 loc) · 5.76 KB
/
weather_cog.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
from timezonefinder import TimezoneFinder
from pytz import timezone
from datetime import datetime
from discord.ext.commands import Cog, hybrid_command
from requests import get
from discord import Embed
from string import capwords
from lib.config_required import cog_config_required
@cog_config_required("openweather", "api_key", "Generate yours [here](https://openweathermap.org/api)")
class WeatherCog(Cog, name="Weather", description="get current weather information from a city"):
"""A cog that retrieves current weather information for a given city."""
OPENWEATHER_BASE_URL = "https://api.openweathermap.org/data/2.5/"
def __init__(self, bot):
self.bot = bot
self.api_key = self.required_config
@staticmethod
def get_timezone(data: any) -> datetime:
"""Get the timezone for the given city.
:param data: The weather data to get the timezone for.
:type data: Any | None
:return: The timezone based on Longitude and Latitude.
:rtype: datetime.tzinfo
"""
longitude = float(data["coord"]['lon'])
latitude = float(data["coord"]['lat'])
timezone_finder = TimezoneFinder()
result = timezone_finder.timezone_at(
lng=longitude,
lat=latitude)
return datetime.now(timezone(str(result)))
@staticmethod
def kelvin_to_celsius(kelvin: float) -> float:
"""Convert a temperature in Kelvin to Celsius.
:param kelvin: The temperature in Kelvin.
:type kelvin: float
:return: The temperature in Celsius.
:rtype: float
"""
return kelvin - 273.15
@staticmethod
def kelvin_to_fahrenheit(kelvin: float) -> float:
"""Convert a temperature in Kelvin to fahrenheit.
:param kelvin: The temperature in Kelvin.
:type kelvin: float
:return: The temperature in fahrenheit.
:rtype: float
"""
return kelvin * 1.8 - 459.67
async def get_weather(self, city: str):
"""Retrieve weather information for the specified city.
:param city: The name of the city to retrieve weather information for
:type city: str
:return: A dictionary containing the weather information, or None if the city was not found
:rtype: dict
"""
# complete_url to retreive weather info
response = get(f"{self.OPENWEATHER_BASE_URL}/weather?appid={self.api_key}&q={city}")
# code 200 means the city is found otherwise, city is not found
if response.status_code == 200:
return response.json()
return None
@hybrid_command(name='weather', help='Show weather information in your city', usage="{city}")
async def weather(self, ctx, *, city_input: str):
"""Display weather information for the specified city.
:param ctx: the Discord context for the command
:type ctx: Context
:param city_input: The name of the city to display weather information for
:type city_input: str
:return: This function sends an embed message to the Discord channel
"""
if ctx.interaction:
await ctx.interaction.response.defer()
city = capwords(city_input)
data_weather = await self.get_weather(city)
timezone_city = self.get_timezone(data_weather)
# Now data_weather contains lists of data
# from the city inputer by the user
if data_weather:
icon_id = data_weather["weather"][0]["icon"]
main = data_weather["main"]
visibility = data_weather['visibility']
current_temperature = main["temp"]
fahrenheit = self.kelvin_to_fahrenheit(int(current_temperature))
celsius = self.kelvin_to_celsius(int(current_temperature))
feels_like = main["feels_like"]
feels_like_fahrenheit = self.kelvin_to_fahrenheit(int(feels_like))
feels_like_celsius = self.kelvin_to_celsius(int(feels_like))
current_pressure = main["pressure"]
current_humidity = main["humidity"]
forcast = data_weather["weather"]
weather_description = forcast[0]["description"]
embed = Embed(
color=self.bot.default_color,
title=city,
description=timezone_city.strftime('%m/%d/%Y %H:%M'),
)
embed.set_image(
url=f'https://openweathermap.org/img/wn/{icon_id}@2x.png'
)
embed.add_field(
name="Description",
value=capwords(weather_description),
inline=False
)
embed.add_field(
name="Visibility",
value=f"{visibility}m | {round(visibility * 3.280839895)}ft",
inline=False
)
embed.add_field(
name="Temperature",
value=f"{round(fahrenheit, 2)}°F | {round(celsius, 2)}°C",
inline=False
)
embed.add_field(
name="Feels Like",
value=f"{round(feels_like_fahrenheit, 2)}°F | {round(feels_like_celsius, 2)}°C",
inline=False
)
embed.add_field(
name="Atmospheric Pressure",
value=f"{current_pressure} hPa",
inline=False
)
embed.add_field(
name="Humidity",
value=f"{current_humidity}%",
inline=False
)
else:
embed = Embed(
color=self.bot.default_color,
description=f"{city} No Found!",
)
await ctx.send(embed=embed)
async def setup(bot):
await bot.add_cog(WeatherCog(bot))