Merge pull request #205 from miaowware/fix-typing

Added/fixed/removed typing managers
This commit is contained in:
0x5c 2020-02-25 20:57:07 -05:00 committed by GitHub
commit f6ed8430b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 216 additions and 224 deletions

View File

@ -7,6 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [Unreleased] ## [Unreleased]
### Fixed ### Fixed
- Fixed issue where HamStudy questions with images would cause an error. - Fixed issue where HamStudy questions with images would cause an error.
- Added/fixed/removed typing indicators in numerous commands.
## [2.2.1] - 2020-02-20 ## [2.2.1] - 2020-02-20

View File

@ -39,18 +39,17 @@ class FunCog(commands.Cog):
@commands.command(name="funetics", aliases=["fun"], category=cmn.cat.fun) @commands.command(name="funetics", aliases=["fun"], category=cmn.cat.fun)
async def _funetics_lookup(self, ctx: commands.Context, *, msg: str): async def _funetics_lookup(self, ctx: commands.Context, *, msg: str):
"""Generates fun/wacky phonetics for a word or phrase.""" """Generates fun/wacky phonetics for a word or phrase."""
with ctx.typing(): result = ""
result = "" for char in msg.lower():
for char in msg.lower(): if char.isalpha():
if char.isalpha(): result += random.choice([word for word in self.words if word[0] == char])
result += random.choice([word for word in self.words if word[0] == char]) else:
else: result += char
result += char result += " "
result += " " embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"Funetics for {msg}"
embed.title = f"Funetics for {msg}" embed.description = result.title()
embed.description = result.title() embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)

View File

@ -23,93 +23,91 @@ class GridCog(commands.Cog):
async def _grid_sq_lookup(self, ctx: commands.Context, lat: str, lon: str): async def _grid_sq_lookup(self, ctx: commands.Context, lat: str, lon: str):
("""Calculates the grid square for latitude and longitude coordinates, """ ("""Calculates the grid square for latitude and longitude coordinates, """
"""with negative being latitude South and longitude West.""") """with negative being latitude South and longitude West.""")
with ctx.typing(): grid = "**"
grid = "**" latf = float(lat) + 90
latf = float(lat) + 90 lonf = float(lon) + 180
lonf = float(lon) + 180 if 0 <= latf <= 180 and 0 <= lonf <= 360:
if 0 <= latf <= 180 and 0 <= lonf <= 360: grid += chr(ord("A") + int(lonf / 20))
grid += chr(ord("A") + int(lonf / 20)) grid += chr(ord("A") + int(latf / 10))
grid += chr(ord("A") + int(latf / 10)) grid += chr(ord("0") + int((lonf % 20)/2))
grid += chr(ord("0") + int((lonf % 20)/2)) grid += chr(ord("0") + int((latf % 10)/1))
grid += chr(ord("0") + int((latf % 10)/1)) grid += chr(ord("a") + int((lonf - (int(lonf/2)*2)) / (5/60)))
grid += chr(ord("a") + int((lonf - (int(lonf/2)*2)) / (5/60))) grid += chr(ord("a") + int((latf - (int(latf/1)*1)) / (2.5/60)))
grid += chr(ord("a") + int((latf - (int(latf/1)*1)) / (2.5/60))) grid += "**"
grid += "**" embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"Maidenhead Grid Locator for {float(lat):.6f}, {float(lon):.6f}"
embed.title = f"Maidenhead Grid Locator for {float(lat):.6f}, {float(lon):.6f}" embed.description = grid
embed.description = grid embed.colour = cmn.colours.good
embed.colour = cmn.colours.good else:
else: embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"Error generating grid square for {lat}, {lon}."
embed.title = f"Error generating grid square for {lat}, {lon}." embed.description = """Coordinates out of range.
embed.description = """Coordinates out of range. The valid ranges are:
The valid ranges are: - Latitude: `-90` to `+90`
- Latitude: `-90` to `+90` - Longitude: `-180` to `+180`"""
- Longitude: `-180` to `+180`""" embed.colour = cmn.colours.bad
embed.colour = cmn.colours.bad
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="ungrid", aliases=["loc"], category=cmn.cat.maps) @commands.command(name="ungrid", aliases=["loc"], category=cmn.cat.maps)
async def _location_lookup(self, ctx: commands.Context, grid: str, grid2: str = None): async def _location_lookup(self, ctx: commands.Context, grid: str, grid2: str = None):
"""Calculates the latitude and longitude for the center of a grid square. """Calculates the latitude and longitude for the center of a grid square.
If two grid squares are given, the distance and azimuth between them is calculated.""" If two grid squares are given, the distance and azimuth between them is calculated."""
with ctx.typing(): if grid2 is None or grid2 == "":
if grid2 is None or grid2 == "": try:
try: grid = grid.upper()
grid = grid.upper() loc = get_coords(grid)
loc = get_coords(grid)
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
embed.title = f"Latitude and Longitude for {grid}" embed.title = f"Latitude and Longitude for {grid}"
embed.colour = cmn.colours.good embed.colour = cmn.colours.good
if len(grid) >= 6: if len(grid) >= 6:
embed.description = f"**{loc[0]:.5f}, {loc[1]:.5f}**" embed.description = f"**{loc[0]:.5f}, {loc[1]:.5f}**"
embed.url = f"https://www.openstreetmap.org/#map=13/{loc[0]:.5f}/{loc[1]:.5f}" embed.url = f"https://www.openstreetmap.org/#map=13/{loc[0]:.5f}/{loc[1]:.5f}"
else: else:
embed.description = f"**{loc[0]:.1f}, {loc[1]:.1f}**" embed.description = f"**{loc[0]:.1f}, {loc[1]:.1f}**"
embed.url = f"https://www.openstreetmap.org/#map=10/{loc[0]:.1f}/{loc[1]:.1f}" embed.url = f"https://www.openstreetmap.org/#map=10/{loc[0]:.1f}/{loc[1]:.1f}"
except Exception as e: except Exception as e:
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
embed.title = f"Error generating latitude and longitude for grid {grid}." embed.title = f"Error generating latitude and longitude for grid {grid}."
embed.description = str(e) embed.description = str(e)
embed.colour = cmn.colours.bad embed.colour = cmn.colours.bad
else: else:
radius = 6371 radius = 6371
try: try:
grid = grid.upper() grid = grid.upper()
grid2 = grid2.upper() grid2 = grid2.upper()
loc = get_coords(grid) loc = get_coords(grid)
loc2 = get_coords(grid2) loc2 = get_coords(grid2)
# Haversine formula # Haversine formula
d_lat = math.radians(loc2[0] - loc[0]) d_lat = math.radians(loc2[0] - loc[0])
d_lon = math.radians(loc2[1] - loc[1]) d_lon = math.radians(loc2[1] - loc[1])
a = (math.sin(d_lat/2) ** 2 a = (math.sin(d_lat/2) ** 2
+ math.cos(math.radians(loc[0])) + math.cos(math.radians(loc[0]))
* math.cos(math.radians(loc2[0])) * math.cos(math.radians(loc2[0]))
* math.sin(d_lon/2) ** 2) * math.sin(d_lon/2) ** 2)
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a))
d = radius * c d = radius * c
d_mi = 0.6213712 * d d_mi = 0.6213712 * d
# Bearing # Bearing
y_dist = math.sin(math.radians(loc2[1]-loc[1])) * math.cos(math.radians(loc2[0])) y_dist = math.sin(math.radians(loc2[1]-loc[1])) * math.cos(math.radians(loc2[0]))
x_dist = (math.cos(math.radians(loc[0])) x_dist = (math.cos(math.radians(loc[0]))
* math.sin(math.radians(loc2[0])) * math.sin(math.radians(loc2[0]))
- math.sin(math.radians(loc[0])) - math.sin(math.radians(loc[0]))
* math.cos(math.radians(loc2[0])) * math.cos(math.radians(loc2[0]))
* math.cos(math.radians(loc2[1] - loc[1]))) * math.cos(math.radians(loc2[1] - loc[1])))
bearing = (math.degrees(math.atan2(y_dist, x_dist)) + 360) % 360 bearing = (math.degrees(math.atan2(y_dist, x_dist)) + 360) % 360
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
embed.title = f"Great Circle Distance and Bearing from {grid} to {grid2}" embed.title = f"Great Circle Distance and Bearing from {grid} to {grid2}"
embed.description = f"**Distance:** {d:.1f} km ({d_mi:.1f} mi)\n**Bearing:** {bearing:.1f}°" embed.description = f"**Distance:** {d:.1f} km ({d_mi:.1f} mi)\n**Bearing:** {bearing:.1f}°"
embed.colour = cmn.colours.good embed.colour = cmn.colours.good
except Exception as e: except Exception as e:
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
embed.title = f"Error generating great circle distance and bearing from {grid} and {grid2}." embed.title = f"Error generating great circle distance and bearing from {grid} and {grid2}."
embed.description = str(e) embed.description = str(e)
embed.colour = cmn.colours.bad embed.colour = cmn.colours.bad
await ctx.send(embed=embed) await ctx.send(embed=embed)

View File

@ -25,45 +25,42 @@ class HamCog(commands.Cog):
@commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref) @commands.command(name="qcode", aliases=["q"], category=cmn.cat.ref)
async def _qcode_lookup(self, ctx: commands.Context, qcode: str): async def _qcode_lookup(self, ctx: commands.Context, qcode: str):
"""Looks up the meaning of a Q Code.""" """Looks up the meaning of a Q Code."""
with ctx.typing(): qcode = qcode.upper()
qcode = qcode.upper() embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) if qcode in qcodes.qcodes:
if qcode in qcodes.qcodes: embed.title = qcode
embed.title = qcode embed.description = qcodes.qcodes[qcode]
embed.description = qcodes.qcodes[qcode] embed.colour = cmn.colours.good
embed.colour = cmn.colours.good else:
else: embed.title = f"Q Code {qcode} not found"
embed.title = f"Q Code {qcode} not found" embed.colour = cmn.colours.bad
embed.colour = cmn.colours.bad
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="phonetics", aliases=["ph", "phoneticize", "phoneticise", "phone"], category=cmn.cat.ref) @commands.command(name="phonetics", aliases=["ph", "phoneticize", "phoneticise", "phone"], category=cmn.cat.ref)
async def _phonetics_lookup(self, ctx: commands.Context, *, msg: str): async def _phonetics_lookup(self, ctx: commands.Context, *, msg: str):
"""Returns NATO phonetics for a word or phrase.""" """Returns NATO phonetics for a word or phrase."""
with ctx.typing(): result = ""
result = "" for char in msg.lower():
for char in msg.lower(): if char.isalpha():
if char.isalpha(): result += phonetics.phonetics[char]
result += phonetics.phonetics[char] else:
else: result += char
result += char result += " "
result += " " embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"Phonetics for {msg}"
embed.title = f"Phonetics for {msg}" embed.description = result.title()
embed.description = result.title() embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="utc", aliases=["z"], category=cmn.cat.ref) @commands.command(name="utc", aliases=["z"], category=cmn.cat.ref)
async def _utc_lookup(self, ctx: commands.Context): async def _utc_lookup(self, ctx: commands.Context):
"""Returns the current time in UTC.""" """Returns the current time in UTC."""
with ctx.typing(): now = datetime.utcnow()
now = datetime.utcnow() result = "**" + now.strftime("%Y-%m-%d %H:%M") + "Z**"
result = "**" + now.strftime("%Y-%m-%d %H:%M") + "Z**" embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = "The current time is:"
embed.title = "The current time is:" embed.description = result
embed.description = result embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref) @commands.command(name="prefixes", aliases=["vanity", "pfx", "vanities", "prefix"], category=cmn.cat.ref)

View File

@ -40,30 +40,29 @@ class LookupCog(commands.Cog):
@commands.command(name="dxcc", aliases=["dx"], category=cmn.cat.lookup) @commands.command(name="dxcc", aliases=["dx"], category=cmn.cat.lookup)
async def _dxcc_lookup(self, ctx: commands.Context, query: str): async def _dxcc_lookup(self, ctx: commands.Context, query: str):
"""Gets DXCC info about a callsign prefix.""" """Gets DXCC info about a callsign prefix."""
with ctx.typing(): query = query.upper()
query = query.upper() full_query = query
full_query = query embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = "DXCC Info for "
embed.title = "DXCC Info for " embed.description = f"*Last Updated: {self.cty.formatted_version}*"
embed.description = f"*Last Updated: {self.cty.formatted_version}*" embed.colour = cmn.colours.bad
embed.colour = cmn.colours.bad while query:
while query: if query in self.cty.keys():
if query in self.cty.keys(): data = self.cty[query]
data = self.cty[query] embed.add_field(name="Entity", value=data["entity"])
embed.add_field(name="Entity", value=data["entity"]) embed.add_field(name="CQ Zone", value=data["cq"])
embed.add_field(name="CQ Zone", value=data["cq"]) embed.add_field(name="ITU Zone", value=data["itu"])
embed.add_field(name="ITU Zone", value=data["itu"]) embed.add_field(name="Continent", value=data["continent"])
embed.add_field(name="Continent", value=data["continent"]) embed.add_field(name="Time Zone",
embed.add_field(name="Time Zone", value=f"+{data['tz']}" if data["tz"] > 0 else str(data["tz"]))
value=f"+{data['tz']}" if data["tz"] > 0 else str(data["tz"])) embed.title += query
embed.title += query embed.colour = cmn.colours.good
embed.colour = cmn.colours.good break
break
else:
query = query[:-1]
else: else:
embed.title += full_query + " not found" query = query[:-1]
embed.colour = cmn.colours.bad else:
embed.title += full_query + " not found"
embed.colour = cmn.colours.bad
await ctx.send(embed=embed) await ctx.send(embed=embed)
@tasks.loop(hours=24) @tasks.loop(hours=24)

View File

@ -21,61 +21,58 @@ class MorseCog(commands.Cog):
@commands.command(name="morse", aliases=["cw"], category=cmn.cat.ref) @commands.command(name="morse", aliases=["cw"], category=cmn.cat.ref)
async def _morse(self, ctx: commands.Context, *, msg: str): async def _morse(self, ctx: commands.Context, *, msg: str):
"""Converts ASCII to international morse code.""" """Converts ASCII to international morse code."""
with ctx.typing(): result = ""
result = "" for char in msg.upper():
for char in msg.upper(): try:
try: result += morse.morse[char]
result += morse.morse[char] except KeyError:
except KeyError: result += "<?>"
result += "<?>" result += " "
result += " " embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"Morse Code for {msg}"
embed.title = f"Morse Code for {msg}" embed.description = "**" + result + "**"
embed.description = "**" + result + "**" embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="unmorse", aliases=["demorse", "uncw", "decw"], category=cmn.cat.ref) @commands.command(name="unmorse", aliases=["demorse", "uncw", "decw"], category=cmn.cat.ref)
async def _unmorse(self, ctx: commands.Context, *, msg: str): async def _unmorse(self, ctx: commands.Context, *, msg: str):
"""Converts international morse code to ASCII.""" """Converts international morse code to ASCII."""
with ctx.typing(): result = ""
result = "" msg0 = msg
msg0 = msg msg = msg.split("/")
msg = msg.split("/") msg = [m.split() for m in msg]
msg = [m.split() for m in msg] for word in msg:
for word in msg: for char in word:
for char in word: try:
try: result += morse.ascii[char]
result += morse.ascii[char] except KeyError:
except KeyError: result += "<?>"
result += "<?>" result += " "
result += " " embed = cmn.embed_factory(ctx)
embed = cmn.embed_factory(ctx) embed.title = f"ASCII for {msg0}"
embed.title = f"ASCII for {msg0}" embed.description = result
embed.description = result embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)
@commands.command(name="cwweight", aliases=["weight", "cww"], category=cmn.cat.ref) @commands.command(name="cwweight", aliases=["weight", "cww"], category=cmn.cat.ref)
async def _weight(self, ctx: commands.Context, *, msg: str): async def _weight(self, ctx: commands.Context, *, msg: str):
"""Calculates the CW weight of a callsign or message.""" """Calculates the CW weight of a callsign or message."""
embed = cmn.embed_factory(ctx) embed = cmn.embed_factory(ctx)
with ctx.typing(): msg = msg.upper()
msg = msg.upper() weight = 0
weight = 0 for char in msg:
for char in msg: try:
try: cw_char = morse.morse[char].replace("-", "==")
cw_char = morse.morse[char].replace("-", "==") weight += len(cw_char) * 2 + 2
weight += len(cw_char) * 2 + 2 except KeyError:
except KeyError: embed.title = "Error in calculation of CW weight"
embed.title = "Error in calculation of CW weight" embed.description = f"Unknown character `{char}` in message"
embed.description = f"Unknown character `{char}` in message" embed.colour = cmn.colours.bad
embed.colour = cmn.colours.bad await ctx.send(embed=embed)
await ctx.send(embed=embed) return
return embed.title = f"CW Weight of {msg}"
embed.title = f"CW Weight of {msg}" embed.description = f"The CW weight is **{weight}**"
embed.description = f"The CW weight is **{weight}**" embed.colour = cmn.colours.good
embed.colour = cmn.colours.good
await ctx.send(embed=embed) await ctx.send(embed=embed)

View File

@ -36,50 +36,51 @@ class QRZCog(commands.Cog):
await ctx.send(f"http://qrz.com/db/{callsign}") await ctx.send(f"http://qrz.com/db/{callsign}")
return return
try: async with ctx.typing():
await qrz_test_session(self.key, self.session) try:
except ConnectionError: await qrz_test_session(self.key, self.session)
await self.get_session() except ConnectionError:
url = f"http://xmldata.qrz.com/xml/current/?s={self.key};callsign={callsign}"
async with self.session.get(url) as resp:
if resp.status != 200:
raise ConnectionError(f"Unable to connect to QRZ (HTTP Error {resp.status})")
with BytesIO(await resp.read()) as resp_file:
resp_xml = etree.parse(resp_file).getroot()
resp_xml_session = resp_xml.xpath("/x:QRZDatabase/x:Session", namespaces={"x": "http://xmldata.qrz.com"})
resp_session = {el.tag.split("}")[1]: el.text for el in resp_xml_session[0].getiterator()}
if "Error" in resp_session:
if "Session Timeout" in resp_session["Error"]:
await self.get_session() await self.get_session()
await self._qrz_lookup(ctx, callsign)
return
if "Not found" in resp_session["Error"]:
embed = cmn.embed_factory(ctx)
embed.title = f"QRZ Data for {callsign.upper()}"
embed.colour = cmn.colours.bad
embed.description = "No data found!"
await ctx.send(embed=embed)
return
raise ValueError(resp_session["Error"])
resp_xml_data = resp_xml.xpath("/x:QRZDatabase/x:Callsign", namespaces={"x": "http://xmldata.qrz.com"}) url = f"http://xmldata.qrz.com/xml/current/?s={self.key};callsign={callsign}"
resp_data = {el.tag.split("}")[1]: el.text for el in resp_xml_data[0].getiterator()} async with self.session.get(url) as resp:
if resp.status != 200:
raise ConnectionError(f"Unable to connect to QRZ (HTTP Error {resp.status})")
with BytesIO(await resp.read()) as resp_file:
resp_xml = etree.parse(resp_file).getroot()
embed = cmn.embed_factory(ctx) resp_xml_session = resp_xml.xpath("/x:QRZDatabase/x:Session", namespaces={"x": "http://xmldata.qrz.com"})
embed.title = f"QRZ Data for {resp_data['call']}" resp_session = {el.tag.split("}")[1]: el.text for el in resp_xml_session[0].getiterator()}
embed.colour = cmn.colours.good if "Error" in resp_session:
embed.url = f"http://www.qrz.com/db/{resp_data['call']}" if "Session Timeout" in resp_session["Error"]:
if "image" in resp_data: await self.get_session()
embed.set_thumbnail(url=resp_data["image"]) await self._qrz_lookup(ctx, callsign)
return
if "Not found" in resp_session["Error"]:
embed = cmn.embed_factory(ctx)
embed.title = f"QRZ Data for {callsign.upper()}"
embed.colour = cmn.colours.bad
embed.description = "No data found!"
await ctx.send(embed=embed)
return
raise ValueError(resp_session["Error"])
data = qrz_process_info(resp_data) resp_xml_data = resp_xml.xpath("/x:QRZDatabase/x:Callsign", namespaces={"x": "http://xmldata.qrz.com"})
resp_data = {el.tag.split("}")[1]: el.text for el in resp_xml_data[0].getiterator()}
for title, val in data.items(): embed = cmn.embed_factory(ctx)
if val is not None: embed.title = f"QRZ Data for {resp_data['call']}"
embed.add_field(name=title, value=val, inline=True) embed.colour = cmn.colours.good
await ctx.send(embed=embed) embed.url = f"http://www.qrz.com/db/{resp_data['call']}"
if "image" in resp_data:
embed.set_thumbnail(url=resp_data["image"])
data = qrz_process_info(resp_data)
for title, val in data.items():
if val is not None:
embed.add_field(name=title, value=val, inline=True)
await ctx.send(embed=embed)
async def get_session(self): async def get_session(self):
"""Session creation and caching.""" """Session creation and caching."""