-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsunsetrise.py
107 lines (94 loc) · 4.62 KB
/
sunsetrise.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
import datetime
import discord
import geopy
import httpx
import logging
import pytz
from geopy.geocoders import Nominatim
from timezonefinder import TimezoneFinder
from typing import Any, Dict, Optional, Tuple, Union
from redbot.core import app_commands, commands
log = logging.getLogger('red.sunsetrise')
class Sunsetrise(commands.Cog):
"""Carl's Sunsetrise Cog"""
sun_png = 'https://i.cssnr.com/r/fegjfYprbh.png'
moon_png = 'https://i.cssnr.com/r/gkwT2d78cD.png'
def __init__(self, bot):
self.bot = bot
self.gl = Nominatim(user_agent=self.__cog_name__)
self.tf = TimezoneFinder()
async def cog_load(self):
log.info('%s: Cog Load Start', self.__cog_name__)
log.info('%s: Cog Load Finish', self.__cog_name__)
async def cog_unload(self):
log.info('%s: Cog Unload', self.__cog_name__)
@commands.hybrid_command(name='sun', aliases=['sunset', 'sunrise'],
description='Get Sun Data for <location>')
@commands.guild_only()
@app_commands.describe(location='Location to get SUn Data for')
async def sun_command(self, ctx: commands.Context, *, location: str):
"""Get Sun Data for <location>"""
geo = self.gl.geocode(location)
if not geo or not geo.latitude or not geo.longitude:
return await ctx.send(f'⛔ Error getting Lat/Lon Data for: {location}')
tz = self.tf.timezone_at(lat=geo.latitude, lng=geo.longitude)
timezone = pytz.timezone(tz)
current_time_utc = datetime.datetime.now(pytz.UTC)
current_time = current_time_utc.astimezone(timezone)
data = await self.get_sun_data(geo.latitude, geo.longitude,
date=current_time.strftime('%Y-%m-%d'))
if data['status'] != 'OK':
content = (f'⛔ Error getting Sun Data for: {location}\n'
f'Lat: `{geo.latitude}` Lon: `{geo.longitude}`')
return await ctx.send(content)
embed = discord.Embed(
title=geo.raw['display_name'],
url=self.geohack_url_from_geo(geo),
timestamp=datetime.datetime.now(),
)
sunrise_utc = datetime.datetime.fromisoformat(data['results']['sunrise'])
sunrise = sunrise_utc.astimezone(timezone)
sunset_utc = datetime.datetime.fromisoformat(data['results']['sunset'])
sunset = sunset_utc.astimezone(timezone)
solar_noon_utc = datetime.datetime.fromisoformat(data['results']['solar_noon'])
solar_noon = solar_noon_utc.astimezone(timezone)
duration = datetime.timedelta(seconds=int(data['results']['day_length']))
if sunrise < current_time < sunset:
embed.colour = discord.Colour.orange()
embed.set_thumbnail(url=self.sun_png)
icon = '🌞'
else:
embed.colour = discord.Colour.dark_blue()
embed.set_thumbnail(url=self.moon_png)
icon = '🌚'
embed.add_field(name='Sunrise', value=sunrise.strftime('%I:%M:%S %p'))
embed.add_field(name='Noon', value=solar_noon.strftime('%I:%M:%S %p'))
embed.add_field(name='Sunset', value=sunset.strftime('%I:%M:%S %p'))
embed.add_field(name='Day Length', value=str(duration))
embed.add_field(name='Local Time', value=current_time.strftime('%I:%M:%S %p'))
embed.add_field(name='Time Zone', value=tz)
embed.set_author(name=f'Lat: {geo.latitude} / Lon: {geo.longitude}')
content = f"{icon} **{location}**"
await ctx.send(content=content, embed=embed)
@staticmethod
async def get_sun_data(lat: float, lon: float, **kwargs) -> Dict[str, Any]:
_params = {'lat': lat, 'lng': lon, 'formatted': 0}
if kwargs:
_params.update(kwargs)
url = "https://api.sunrise-sunset.org/json"
async with httpx.AsyncClient() as client:
r = await client.get(url, params=_params)
r.raise_for_status()
return r.json()
def geohack_url_from_geo(self, geo: geopy.location.Location, name: Optional[str] = None) -> str:
name = name.replace(' ', '_') if name else geo.raw['display_name'].replace(' ', '_')
dn, mn, sn = self.dd2dms(geo.latitude)
dw, mw, sw = self.dd2dms(geo.longitude)
params = f"{dn}_{mn}_{sn}_N_{dw}_{mw}_{sw}_W_scale:500000"
return f"https://geohack.toolforge.org/geohack.php?pagename={name}¶ms={params}"
@staticmethod
def dd2dms(dd: Union[float, int]) -> Tuple[int, int, int]:
mult = -1 if dd < 0 else 1
mnt, sec = divmod(abs(dd)*3600, 60)
deg, mnt = divmod(mnt, 60)
return abs(mult*deg), abs(mult*mnt), abs(mult*sec)