From 8ff6e774642ae6de44dd0964a5ca46a4aca5fefd Mon Sep 17 00:00:00 2001 From: 4njru Date: Tue, 23 Jul 2024 12:38:52 -0400 Subject: [PATCH] Map input parsing and checking moved to utils; embed and image size tweaks --- crimsobot/bot.py | 7 ++++++- crimsobot/cogs/utilities.py | 40 ++++++++++-------------------------- crimsobot/exceptions.py | 3 ++- crimsobot/utils/astronomy.py | 37 +++++++++++++++++++++++++-------- 4 files changed, 48 insertions(+), 39 deletions(-) diff --git a/crimsobot/bot.py b/crimsobot/bot.py index dc75cc55..a603518e 100644 --- a/crimsobot/bot.py +++ b/crimsobot/bot.py @@ -10,7 +10,7 @@ from crimsobot.context import CrimsoContext from crimsobot.data.img import CAPTION_RULES, IMAGE_RULES from crimsobot.exceptions import (BadCaption, LocationNotFound, NoImageFound, NoMatchingTarotCard, - NotDirectMessage, StrictInputFailed) + NotDirectMessage, StrictInputFailed, ZoomNotValid) from crimsobot.help_command import PaginatedHelpCommand from crimsobot.models.ban import Ban from crimsobot.utils import markov as m, tools as c @@ -149,6 +149,11 @@ async def on_command_error(self, ctx: commands.Context, error: Exception) -> Non traceback_needed = False msg_to_user = f'Location **{error.original.location}** not found.' + if isinstance(error.original, ZoomNotValid): + error_type = '**not good with zoom**' + traceback_needed = False + msg_to_user = f'Zoom level **{error.original.zoom}** not good!' + if isinstance(error.original, NoImageFound): error_type = '**NO IMAGE**' traceback_needed = False diff --git a/crimsobot/cogs/utilities.py b/crimsobot/cogs/utilities.py index 254047ef..d18ebfca 100644 --- a/crimsobot/cogs/utilities.py +++ b/crimsobot/cogs/utilities.py @@ -8,7 +8,7 @@ from discord.ext import commands from crimsobot.bot import CrimsoBOT -from crimsobot.exceptions import LocationNotFound, ZoomNotValid +from crimsobot.exceptions import LocationNotFound from crimsobot.utils import astronomy, image as imagetools, tools as c log = logging.getLogger(__name__) @@ -273,39 +273,21 @@ async def iss(self, ctx: commands.Context, *, location: str) -> None: async def get_map(self, ctx: commands.Context, *, location: str) -> None: """Get a map of a location using its name. You can also specify a zoom level 1-22. - 1 is zoomed out the most; 10 is the default. + 1 is zoomed out the most; 12 is the default. + Just use a semicolon between location and zoom! Example usage: >map hell; 14 """ - # parse user input - try: - location, zoom = location.split(';', 1) - except ValueError: # no zoom provided - zoom = '10' # currently type str; will be converted later - - # bounce API query for shitty or spammy zoom levels - try: - zoom_int = int(zoom) - except ValueError: - raise ZoomNotValid(zoom) - - if not 1 <= zoom_int <= 22: - raise ZoomNotValid(zoom) - # send to geocoder and map URL maker - location = location.upper() - lat, lon, map_url = astronomy.whereis(location, zoom_int) - - if map_url is not None: - embed = c.crimbed( - title=f'Map of {location}', - descr=None, - footer=f'{lat}°, {lon}°' - ) - embed.set_image(url=map_url) - else: - raise LocationNotFound(location) + loc, zoom, lat, lon, map_url = astronomy.whereis(location) + + embed = c.crimbed( + title=f'Map of {loc}', + descr=None, + footer=f'{lat}°, {lon}° · Zoom level: {zoom}', + image_url=map_url, + ) await ctx.send(embed=embed) diff --git a/crimsobot/exceptions.py b/crimsobot/exceptions.py index d366945c..a3ea83b9 100644 --- a/crimsobot/exceptions.py +++ b/crimsobot/exceptions.py @@ -16,7 +16,8 @@ def __init__(self, location: str) -> None: class ZoomNotValid(Exception): - pass + def __init__(self, zoom: str) -> None: + self.zoom = zoom class NotDirectMessage(Exception): diff --git a/crimsobot/utils/astronomy.py b/crimsobot/utils/astronomy.py index 16a941b0..5c427c65 100644 --- a/crimsobot/utils/astronomy.py +++ b/crimsobot/utils/astronomy.py @@ -10,6 +10,7 @@ from timezonefinder import TimezoneFinder from config import TOMTOM_API_KEY +from crimsobot.exceptions import LocationNotFound, ZoomNotValid ISSPass = namedtuple( @@ -92,23 +93,43 @@ def format_passes(passes: List[ISSPass]) -> str: return tabulate.tabulate(passes, headers=headers) -def whereis(query: str, zoom: int) -> Tuple[Optional[float], Optional[float], Optional[str]]: +def whereis(query: str) -> Tuple[str, int, float, float, str]: + """Find a location by name using the Nomanatim geocoder and return a map URL using the TomTom API. + """ + + # parse user input + try: + location_str, zoom = query.split(';', 1) + except ValueError: # no zoom provided + location_str = query + zoom = '12' # currently type str; will be converted later + + # bounce API query for shitty or spammy zoom levels + try: + zoom_int = int(zoom) + except ValueError: + raise ZoomNotValid(zoom) + + if not 1 <= zoom_int <= 22: + raise ZoomNotValid(zoom) + # Nomanatim geocoder - location = where_are_you(query) + location = where_are_you(location_str.upper()) # return None if no location found if not location: - return None, None, None + raise LocationNotFound(location_str) - lat = round(location.latitude, 6) - lon = round(location.longitude, 6) + lat = round(location.latitude, 5) + lon = round(location.longitude, 5) # now the URL! url_template = ( 'https://api.tomtom.com/map/1/staticimage?' 'layer=basic&style=night&format=png&' - 'key={}&zoom={}¢er={},{}&width=1036&height=1036&language=NGT' + 'key={}&zoom={}¢er={},{}' # variable input goes here! + '&width=600&height=600&language=NGT' ) - url = url_template.format(TOMTOM_API_KEY, zoom, lon, lat) + url = url_template.format(TOMTOM_API_KEY, zoom_int, lon, lat) - return lat, lon, url + return location_str, zoom_int, lat, lon, url