mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-05-14 19:35:18 +00:00
feat: Refactor geocoding and country/state handling in commands
- Updated utility functions to improve country name validation, ensuring accurate identification of country names and US states. - Enhanced geocoding logic in multiple command classes to handle default state and country configurations more effectively. - Modified error messages to reflect the correct region based on user input, improving user experience. - Added short usage descriptions for satellite pass commands in multiple languages, enhancing internationalization support.
This commit is contained in:
@@ -62,7 +62,7 @@ class GlobalWxCommand(BaseCommand):
|
||||
self.wxsim_parser = None
|
||||
|
||||
# Get default state and country from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='')
|
||||
self.default_country = self.bot.config.get('Weather', 'default_country', fallback='US')
|
||||
|
||||
# Get unit preferences from config
|
||||
|
||||
@@ -48,8 +48,9 @@ class AqiCommand(BaseCommand):
|
||||
self.aqi_enabled = self.get_config_value('Aqi_Command', 'enabled', fallback=True, value_type='bool')
|
||||
self.url_timeout = 10 # seconds
|
||||
|
||||
# Get default state from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
# Get default state and country from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='')
|
||||
self.default_country = self.bot.config.get('Weather', 'default_country', fallback='US')
|
||||
|
||||
# Get timezone from config
|
||||
self.timezone = self.bot.config.get('Bot', 'timezone', fallback='America/Los_Angeles')
|
||||
@@ -95,7 +96,8 @@ class AqiCommand(BaseCommand):
|
||||
}
|
||||
|
||||
def get_help_text(self) -> str:
|
||||
return f"Usage: aqi <city|neighborhood|city country|lat,lon|help> - Get AQI for city/neighborhood in {self.default_state}, international cities, coordinates, or pollutant help"
|
||||
region = self.default_state or self.default_country
|
||||
return f"Usage: aqi <city|neighborhood|city country|lat,lon|help> - Get AQI for city/neighborhood in {region}, international cities, coordinates, or pollutant help"
|
||||
|
||||
def can_execute(self, message: MeshMessage) -> bool:
|
||||
"""Check if this command can be executed with the given message.
|
||||
@@ -475,7 +477,8 @@ class AqiCommand(BaseCommand):
|
||||
if ',' in location and any(country in location.lower() for country in ['canada', 'mexico', 'uk', 'france', 'germany', 'italy', 'spain', 'australia', 'japan', 'china', 'india', 'brazil', 'uae', 'russia', 'korea', 'thailand', 'singapore', 'egypt', 'turkey']):
|
||||
return f"Could not find city '{location}'"
|
||||
else:
|
||||
return f"Could not find city '{location}' in {self.default_state}"
|
||||
region = self.default_state or self.default_country
|
||||
return f"Could not find city '{location}' in {region}"
|
||||
|
||||
# Check if the found city is in a different state than default
|
||||
actual_city = location
|
||||
@@ -528,7 +531,7 @@ class AqiCommand(BaseCommand):
|
||||
if location_type == "city" and address_info:
|
||||
# Always try to include city name if there's space
|
||||
# Use abbreviate_location to shorten long location strings (e.g., "United States of America" -> "USA")
|
||||
full_location = f"{actual_city}, {actual_state}"
|
||||
full_location = f"{actual_city}, {actual_state}" if actual_state else actual_city
|
||||
city_display = abbreviate_location(full_location, max_length=30)
|
||||
|
||||
# Check if we have space for the city name
|
||||
@@ -588,7 +591,7 @@ class AqiCommand(BaseCommand):
|
||||
actual_state = "USA"
|
||||
|
||||
# Use abbreviate_location to shorten long location strings (e.g., "United States of America" -> "USA")
|
||||
full_location = f"{actual_city}, {actual_state}"
|
||||
full_location = f"{actual_city}, {actual_state}" if actual_state else actual_city
|
||||
city_display = abbreviate_location(full_location, max_length=30)
|
||||
|
||||
# Check if we have space for the city name
|
||||
|
||||
@@ -72,9 +72,8 @@ class SatpassCommand(BaseCommand):
|
||||
# Check if user provided a satellite number
|
||||
content = message.content.strip()
|
||||
if content == 'satpass':
|
||||
# No satellite specified, show help
|
||||
help_text = self._get_help_text()
|
||||
await self.send_response(message, help_text)
|
||||
# No satellite specified, show short usage (fits message length limit)
|
||||
await self.send_response(message, self.translate('commands.satpass.usage_short'))
|
||||
return True
|
||||
|
||||
# Extract satellite identifier from command
|
||||
@@ -113,44 +112,6 @@ class SatpassCommand(BaseCommand):
|
||||
await self.send_response(message, error_msg)
|
||||
return False
|
||||
|
||||
def _get_help_text(self) -> str:
|
||||
"""Get detailed help text with shortcuts.
|
||||
|
||||
Returns:
|
||||
str: Detailed help text including shortcuts.
|
||||
"""
|
||||
shortcuts_text = self.translate('commands.satpass.help_header')
|
||||
|
||||
# Group shortcuts by category for better organization
|
||||
weather_sats = ['noaa15', 'noaa18', 'noaa19', 'metop-a', 'metop-b', 'metop-c', 'goes16', 'goes17', 'goes18']
|
||||
space_stations = ['iss', 'tiangong', 'tiangong1', 'tiangong2']
|
||||
telescopes = ['hst', 'hubble']
|
||||
other = ['starlink']
|
||||
|
||||
# Add weather satellites
|
||||
shortcuts_text += self.translate('commands.satpass.category_weather')
|
||||
weather_list = [f"{name} ({self.SATELLITE_SHORTCUTS[name]})" for name in weather_sats if name in self.SATELLITE_SHORTCUTS]
|
||||
shortcuts_text += ", ".join(weather_list) + "\n"
|
||||
|
||||
# Add space stations
|
||||
shortcuts_text += self.translate('commands.satpass.category_stations')
|
||||
station_list = [f"{name} ({self.SATELLITE_SHORTCUTS[name]})" for name in space_stations if name in self.SATELLITE_SHORTCUTS]
|
||||
shortcuts_text += ", ".join(station_list) + "\n"
|
||||
|
||||
# Add telescopes
|
||||
shortcuts_text += self.translate('commands.satpass.category_telescopes')
|
||||
telescope_list = [f"{name} ({self.SATELLITE_SHORTCUTS[name]})" for name in telescopes if name in self.SATELLITE_SHORTCUTS]
|
||||
shortcuts_text += ", ".join(telescope_list) + "\n"
|
||||
|
||||
# Add other satellites
|
||||
shortcuts_text += self.translate('commands.satpass.category_other')
|
||||
other_list = [f"{name} ({self.SATELLITE_SHORTCUTS[name]})" for name in other if name in self.SATELLITE_SHORTCUTS]
|
||||
shortcuts_text += ", ".join(other_list) + "\n"
|
||||
|
||||
shortcuts_text += self.translate('commands.satpass.examples')
|
||||
|
||||
return shortcuts_text
|
||||
|
||||
def get_help_text(self) -> str:
|
||||
"""Get help text for this command.
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class SolarforecastCommand(BaseCommand):
|
||||
self.forecast_cache = {}
|
||||
|
||||
# Get default state from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='')
|
||||
|
||||
# Initialize geocoder (will use rate-limited helpers for actual calls)
|
||||
self.geolocator = get_nominatim_geocoder()
|
||||
|
||||
@@ -90,8 +90,9 @@ class WxCommand(BaseCommand):
|
||||
self.use_metric = False # Use imperial units by default
|
||||
self.zulu_time = False # Use local time by default
|
||||
|
||||
# Get default state from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
# Get default state and country from config for city disambiguation
|
||||
self.default_state = self.bot.config.get('Weather', 'default_state', fallback='')
|
||||
self.default_country = self.bot.config.get('Weather', 'default_country', fallback='US')
|
||||
|
||||
# Initialize geocoder (will use rate-limited helpers for actual calls)
|
||||
# Keep geolocator for backwards compatibility, but prefer rate-limited helpers
|
||||
@@ -572,7 +573,8 @@ class WxCommand(BaseCommand):
|
||||
else:
|
||||
lat, lon = result
|
||||
if lat is None or lon is None:
|
||||
await self.send_response(message, self.translate('commands.wx.no_location_city', location=location, state=self.default_state))
|
||||
region = self.default_state or self.default_country
|
||||
await self.send_response(message, self.translate('commands.wx.no_location_city', location=location, state=region))
|
||||
return True
|
||||
|
||||
# Get and display full alert list
|
||||
@@ -667,11 +669,12 @@ class WxCommand(BaseCommand):
|
||||
address_info = None
|
||||
|
||||
if lat is None or lon is None:
|
||||
return self.translate('commands.wx.no_location_city', location=location, state=self.default_state)
|
||||
region = self.default_state or self.default_country
|
||||
return self.translate('commands.wx.no_location_city', location=location, state=region)
|
||||
|
||||
# Check if the found city is in a different state than default
|
||||
actual_city = location
|
||||
actual_state = self.default_state
|
||||
actual_state = self.default_state or self.default_country
|
||||
if address_info:
|
||||
# Try to get the best city name from various address fields
|
||||
actual_city = (address_info.get('city') or
|
||||
@@ -715,7 +718,7 @@ class WxCommand(BaseCommand):
|
||||
actual_state != default_state_full)
|
||||
# Always show location if using companion location, or if state is different
|
||||
if using_companion_location or states_different:
|
||||
location_prefix = f"{actual_city}, {actual_state}: "
|
||||
location_prefix = f"{actual_city}, {actual_state}: " if actual_state else f"{actual_city}: "
|
||||
elif location_type == "zipcode" and using_companion_location:
|
||||
# For zipcode with companion location, try to get city name from reverse geocoding
|
||||
location_str = self._coordinates_to_location_string(lat, lon)
|
||||
|
||||
+79
-71
@@ -499,21 +499,23 @@ def is_country_name(text: str) -> bool:
|
||||
Returns:
|
||||
bool: True if text appears to be a country name
|
||||
"""
|
||||
if not text or len(text) <= 2:
|
||||
if not text:
|
||||
return False
|
||||
|
||||
if PYCOUNTRY_AVAILABLE:
|
||||
iso_code, _ = normalize_country_name(text)
|
||||
return iso_code is not None
|
||||
if iso_code is not None:
|
||||
return True
|
||||
|
||||
# Fallback: if it's longer than 2 chars and not a common US state, assume country
|
||||
if US_AVAILABLE:
|
||||
state_abbr, _ = normalize_us_state(text)
|
||||
if state_abbr:
|
||||
return False # It's a US state, not a country
|
||||
|
||||
# If longer than 2 chars and not a US state, likely a country
|
||||
return len(text) > 2
|
||||
if len(text) <= 2:
|
||||
return False # Unknown 2-char (not a known country or US state)
|
||||
|
||||
return len(text) > 2 # Longer text, assume country
|
||||
|
||||
|
||||
def is_us_state(text: str) -> bool:
|
||||
@@ -801,7 +803,7 @@ async def geocode_city(bot: Any, city: str, default_state: str = None,
|
||||
try:
|
||||
# Get defaults from config if not provided
|
||||
if default_state is None:
|
||||
default_state = bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
default_state = bot.config.get('Weather', 'default_state', fallback='')
|
||||
if default_country is None:
|
||||
default_country = bot.config.get('Weather', 'default_country', fallback='US')
|
||||
|
||||
@@ -845,9 +847,10 @@ async def geocode_city(bot: Any, city: str, default_state: str = None,
|
||||
else:
|
||||
country_name = second_part
|
||||
|
||||
# Handle major cities with multiple locations (prioritize major cities)
|
||||
# Handle major cities with multiple locations (prioritize major cities).
|
||||
# Skip when user specified a country (e.g. "Paris, FR") so we honor their choice.
|
||||
major_city_queries = get_major_city_queries(city_clean, state_abbr)
|
||||
if major_city_queries:
|
||||
if major_city_queries and not country_name:
|
||||
# Try major city options first
|
||||
for major_city_query in major_city_queries:
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(major_city_query)
|
||||
@@ -1017,38 +1020,40 @@ async def geocode_city(bot: Any, city: str, default_state: str = None,
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
# Try with default state (fallback for US cities when no country specified)
|
||||
cache_query = f"{city_clean}, {default_state}, {default_country}"
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(cache_query)
|
||||
if cached_lat and cached_lon:
|
||||
lat, lon = cached_lat, cached_lon
|
||||
else:
|
||||
location = await rate_limited_nominatim_geocode(bot, cache_query, timeout=timeout)
|
||||
if location:
|
||||
bot.db_manager.cache_geocoding(cache_query, location.latitude, location.longitude)
|
||||
lat, lon = location.latitude, location.longitude
|
||||
# Try with default state (fallback for US cities when no country specified).
|
||||
# Skip when default_state is empty (e.g. non-US default_country or key unset).
|
||||
if default_state and default_state.strip():
|
||||
cache_query = f"{city_clean}, {default_state}, {default_country}"
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(cache_query)
|
||||
if cached_lat and cached_lon:
|
||||
lat, lon = cached_lat, cached_lon
|
||||
else:
|
||||
lat, lon = None, None
|
||||
|
||||
if lat and lon:
|
||||
address_info = None
|
||||
if include_address_info:
|
||||
# Check cache for reverse geocoding result
|
||||
reverse_cache_key = f"reverse_{lat}_{lon}"
|
||||
cached_address = bot.db_manager.get_cached_json(reverse_cache_key, "geolocation")
|
||||
if cached_address:
|
||||
address_info = cached_address
|
||||
location = await rate_limited_nominatim_geocode(bot, cache_query, timeout=timeout)
|
||||
if location:
|
||||
bot.db_manager.cache_geocoding(cache_query, location.latitude, location.longitude)
|
||||
lat, lon = location.latitude, location.longitude
|
||||
else:
|
||||
try:
|
||||
reverse_location = await rate_limited_nominatim_reverse(bot, f"{lat}, {lon}", timeout=timeout)
|
||||
if reverse_location:
|
||||
address_info = reverse_location.raw.get('address', {})
|
||||
# Cache the reverse geocoding result
|
||||
bot.db_manager.cache_json(reverse_cache_key, address_info, "geolocation", cache_hours=720)
|
||||
except:
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
lat, lon = None, None
|
||||
|
||||
if lat and lon:
|
||||
address_info = None
|
||||
if include_address_info:
|
||||
# Check cache for reverse geocoding result
|
||||
reverse_cache_key = f"reverse_{lat}_{lon}"
|
||||
cached_address = bot.db_manager.get_cached_json(reverse_cache_key, "geolocation")
|
||||
if cached_address:
|
||||
address_info = cached_address
|
||||
else:
|
||||
try:
|
||||
reverse_location = await rate_limited_nominatim_reverse(bot, f"{lat}, {lon}", timeout=timeout)
|
||||
if reverse_location:
|
||||
address_info = reverse_location.raw.get('address', {})
|
||||
# Cache the reverse geocoding result
|
||||
bot.db_manager.cache_json(reverse_cache_key, address_info, "geolocation", cache_hours=720)
|
||||
except:
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
# Try without state
|
||||
location = await rate_limited_nominatim_geocode(bot, f"{city_clean}, {default_country}", timeout=timeout)
|
||||
if location:
|
||||
@@ -1102,7 +1107,7 @@ def geocode_city_sync(bot: Any, city: str, default_state: str = None,
|
||||
try:
|
||||
# Get defaults from config if not provided
|
||||
if default_state is None:
|
||||
default_state = bot.config.get('Weather', 'default_state', fallback='WA')
|
||||
default_state = bot.config.get('Weather', 'default_state', fallback='')
|
||||
if default_country is None:
|
||||
default_country = bot.config.get('Weather', 'default_country', fallback='US')
|
||||
|
||||
@@ -1147,9 +1152,10 @@ def geocode_city_sync(bot: Any, city: str, default_state: str = None,
|
||||
else:
|
||||
country_name = second_part
|
||||
|
||||
# Handle major cities with multiple locations (prioritize major cities)
|
||||
# Handle major cities with multiple locations (prioritize major cities).
|
||||
# Skip when user specified a country (e.g. "Paris, FR") so we honor their choice.
|
||||
major_city_queries = get_major_city_queries(city_clean, state_abbr)
|
||||
if major_city_queries:
|
||||
if major_city_queries and not country_name:
|
||||
# Try major city options first
|
||||
for major_city_query in major_city_queries:
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(major_city_query)
|
||||
@@ -1314,38 +1320,40 @@ def geocode_city_sync(bot: Any, city: str, default_state: str = None,
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
# Try with default state (fallback for US cities when no country specified)
|
||||
cache_query = f"{city_clean}, {default_state}, {default_country}"
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(cache_query)
|
||||
if cached_lat and cached_lon:
|
||||
lat, lon = cached_lat, cached_lon
|
||||
else:
|
||||
location = rate_limited_nominatim_geocode_sync(bot, cache_query, timeout=timeout)
|
||||
if location:
|
||||
bot.db_manager.cache_geocoding(cache_query, location.latitude, location.longitude)
|
||||
lat, lon = location.latitude, location.longitude
|
||||
# Try with default state (fallback for US cities when no country specified).
|
||||
# Skip when default_state is empty (e.g. non-US default_country or key unset).
|
||||
if default_state and default_state.strip():
|
||||
cache_query = f"{city_clean}, {default_state}, {default_country}"
|
||||
cached_lat, cached_lon = bot.db_manager.get_cached_geocoding(cache_query)
|
||||
if cached_lat and cached_lon:
|
||||
lat, lon = cached_lat, cached_lon
|
||||
else:
|
||||
lat, lon = None, None
|
||||
|
||||
if lat and lon:
|
||||
address_info = None
|
||||
if include_address_info:
|
||||
# Check cache for reverse geocoding result
|
||||
reverse_cache_key = f"reverse_{lat}_{lon}"
|
||||
cached_address = bot.db_manager.get_cached_json(reverse_cache_key, "geolocation")
|
||||
if cached_address:
|
||||
address_info = cached_address
|
||||
location = rate_limited_nominatim_geocode_sync(bot, cache_query, timeout=timeout)
|
||||
if location:
|
||||
bot.db_manager.cache_geocoding(cache_query, location.latitude, location.longitude)
|
||||
lat, lon = location.latitude, location.longitude
|
||||
else:
|
||||
try:
|
||||
reverse_location = rate_limited_nominatim_reverse_sync(bot, f"{lat}, {lon}", timeout=timeout)
|
||||
if reverse_location:
|
||||
address_info = reverse_location.raw.get('address', {})
|
||||
# Cache the reverse geocoding result
|
||||
bot.db_manager.cache_json(reverse_cache_key, address_info, "geolocation", cache_hours=720)
|
||||
except:
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
lat, lon = None, None
|
||||
|
||||
if lat and lon:
|
||||
address_info = None
|
||||
if include_address_info:
|
||||
# Check cache for reverse geocoding result
|
||||
reverse_cache_key = f"reverse_{lat}_{lon}"
|
||||
cached_address = bot.db_manager.get_cached_json(reverse_cache_key, "geolocation")
|
||||
if cached_address:
|
||||
address_info = cached_address
|
||||
else:
|
||||
try:
|
||||
reverse_location = rate_limited_nominatim_reverse_sync(bot, f"{lat}, {lon}", timeout=timeout)
|
||||
if reverse_location:
|
||||
address_info = reverse_location.raw.get('address', {})
|
||||
# Cache the reverse geocoding result
|
||||
bot.db_manager.cache_json(reverse_cache_key, address_info, "geolocation", cache_hours=720)
|
||||
except:
|
||||
address_info = {}
|
||||
return lat, lon, address_info
|
||||
|
||||
# Try without state
|
||||
location = rate_limited_nominatim_geocode_sync(bot, f"{city_clean}, {default_country}", timeout=timeout)
|
||||
if location:
|
||||
|
||||
@@ -514,6 +514,7 @@
|
||||
"header": "🛰️ Satellitenvorbeiflug:\n{pass_info}",
|
||||
"error": "Fehler beim Abruf der Satellitenvorbeiflug-Info: {error}",
|
||||
"no_satellite": "Bitte NORAD-Nummer oder Kürzel angeben. Beispiel: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visuell]. Z.B.: satpass iss, satpass 25544. help satpass für Kürzel.",
|
||||
"help_header": "🛰️ Satellitenvorbeiflug-Info\n\nVerwendung: satpass <NORAD_Nummer_oder_Kürzel>\n\nKürzel:\n",
|
||||
"category_weather": "🌤️ Wetter: ",
|
||||
"category_stations": "🚀 Stationen: ",
|
||||
|
||||
@@ -494,6 +494,7 @@
|
||||
"header": "🛰️ Satellite Pass:\n{pass_info}",
|
||||
"error": "Error getting satellite pass info: {error}",
|
||||
"no_satellite": "Please provide a satellite NORAD number or shortcut. Example: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visual]. Ex: satpass iss, satpass 25544. help satpass for shortcuts.",
|
||||
"help_header": "🛰️ Satellite Pass Info\n\nUsage: satpass <NORAD_number_or_shortcut>\n\nShortcuts:\n",
|
||||
"category_weather": "🌤️ Weather: ",
|
||||
"category_stations": "🚀 Stations: ",
|
||||
|
||||
@@ -437,6 +437,7 @@
|
||||
"header": "🛰️ Satellite Pass:\n{pass_info}",
|
||||
"error": "Error getting satellite pass info: {error}",
|
||||
"no_satellite": "Please provide a satellite NORAD number or shortcut. Example: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visual]. Ex: satpass iss, satpass 25544. help satpass for shortcuts.",
|
||||
"help_header": "🛰️ Satellite Pass Info\n\nUsage: satpass <NORAD_number_or_shortcut>\n\nShortcuts:\n",
|
||||
"category_weather": "🌤️ Weather: ",
|
||||
"category_stations": "🚀 Stations: ",
|
||||
|
||||
@@ -370,6 +370,7 @@
|
||||
"header": "🛰️ Paso de Satélite:\n{pass_info}",
|
||||
"error": "Error al obtener información de paso de satélite: {error}",
|
||||
"no_satellite": "Por favor proporciona un número NORAD de satélite o atajo. Ejemplo: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visual]. Ej: satpass iss, satpass 25544. help satpass para atajos.",
|
||||
"help_header": "🛰️ Info de Paso de Satélite\n\nUso: satpass <número_NORAD_o_atajo>\n\nAtajos:\n",
|
||||
"category_weather": "🌤️ Clima: ",
|
||||
"category_stations": "🚀 Estaciones: ",
|
||||
|
||||
@@ -566,6 +566,7 @@
|
||||
"header": "🛰️ Passage de satellite :\n{pass_info}",
|
||||
"error": "Erreur lors de l'obtention des infos de passage : {error}",
|
||||
"no_satellite": "Veuillez fournir un numéro NORAD ou un raccourci de satellite. Exemple : satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visuel]. Ex : satpass iss, satpass 25544. help satpass pour les raccourcis.",
|
||||
"help_header": "🛰️ Infos de passage de satellite\n\nUtilisation : satpass <numéro_NORAD_ou_raccourci>\n\nRaccourcis :\n",
|
||||
"category_weather": "🌤️ Météo : ",
|
||||
"category_stations": "🚀 Stations : ",
|
||||
|
||||
@@ -494,6 +494,7 @@
|
||||
"header": "🛰️ Passage satellite:\n{pass_info}",
|
||||
"error": "Erreur infos passage satellite: {error}",
|
||||
"no_satellite": "Fournissez numéro NORAD satellite ou raccourci. Ex: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visuel]. Ex: satpass iss, satpass 25544. help satpass pour raccourcis.",
|
||||
"help_header": "🛰️ Infos passage satellite\n\nUsage: satpass <numéro_NORAD_ou_raccourci>\n\nRaccourcis:\n",
|
||||
"category_weather": "🌤️ Météo: ",
|
||||
"category_stations": "🚀 Stations: ",
|
||||
|
||||
@@ -494,6 +494,7 @@
|
||||
"header": "🛰️ Satellietpassage:\n{pass_info}",
|
||||
"error": "Fout bij ophalen satellietpassage-info: {error}",
|
||||
"no_satellite": "Geef een NORAD-nummer of snelkoppeling op. Voorbeeld: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visueel]. Bijv: satpass iss, satpass 25544. help satpass voor snelkoppelingen.",
|
||||
"help_header": "🛰️ Satellietpassage info\n\nGebruik: satpass <NORAD_nummer_of_snelkoppeling>\n\nSnelkoppelingen:\n",
|
||||
"category_weather": "🌤️ Weer: ",
|
||||
"category_stations": "🚀 Stations: ",
|
||||
|
||||
@@ -491,6 +491,7 @@
|
||||
"header": "🛰️ Passagem de Satélite:\n{pass_info}",
|
||||
"error": "Erro ao pegar info de passagem: {error}",
|
||||
"no_satellite": "Manda o número NORAD ou atalho do satélite. Ex: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visual]. Ex: satpass iss, satpass 25544. help satpass pra atalhos.",
|
||||
"help_header": "🛰️ Info Passagem Satélite\n\nUso: satpass <número_NORAD_ou_atalho>\n\nAtalhos:\n",
|
||||
"category_weather": "🌤️ Meteorológicos: ",
|
||||
"category_stations": "🚀 Estações: ",
|
||||
|
||||
@@ -490,6 +490,7 @@
|
||||
"header": "🛰️ Passagem de Satélite:\n{pass_info}",
|
||||
"error": "Erro ao obter info de passagem: {error}",
|
||||
"no_satellite": "Por favor forneça número NORAD ou atalho do satélite. Exemplo: satpass iss",
|
||||
"usage_short": "🛰️ satpass <sat|NORAD> [visual]. Ex: satpass iss, satpass 25544. help satpass para atalhos.",
|
||||
"help_header": "🛰️ Info Passagem Satélite\n\nUso: satpass <número_NORAD_ou_atalho>\n\nAtalhos:\n",
|
||||
"category_weather": "🌤️ Meteorológicos: ",
|
||||
"category_stations": "🚀 Estações: ",
|
||||
|
||||
Reference in New Issue
Block a user