Files
meshcore-bot/modules/commands/moon_command.py
agessaman d2abc49048 feat: Enhance command documentation and usage information
- Updated the `generate_html` function to include detailed command usage information, including syntax, examples, and parameters for better user guidance.
- Added CSS styles for improved presentation of command usage and parameters in the generated website documentation.
- Enhanced command classes with structured documentation fields, allowing for consistent and informative command descriptions across the platform.
2026-01-15 20:04:58 -08:00

185 lines
7.3 KiB
Python

#!/usr/bin/env python3
"""
Moon Command - Provides moon phase and position information
"""
from .base_command import BaseCommand
from ..solar_conditions import get_moon
from ..models import MeshMessage
class MoonCommand(BaseCommand):
"""Command to get moon information"""
# Plugin metadata
name = "moon"
keywords = ['moon']
description = "Get moon phase, rise/set times and position"
category = "solar"
# Documentation
short_description = "Get moon phase and rise/set times"
usage = "moon"
examples = ["moon"]
def __init__(self, bot):
"""Initialize the moon command.
Args:
bot: The bot instance.
"""
super().__init__(bot)
self.moon_enabled = self.get_config_value('Moon_Command', 'enabled', fallback=True, value_type='bool')
def can_execute(self, message: MeshMessage) -> bool:
"""Check if this command can be executed with the given message.
Args:
message: The message triggering the command.
Returns:
bool: True if command is enabled and checks pass, False otherwise.
"""
if not self.moon_enabled:
return False
return super().can_execute(message)
async def execute(self, message: MeshMessage) -> bool:
"""Execute the moon command.
Args:
message: The message triggering the command.
Returns:
bool: True if executed successfully, False otherwise.
"""
try:
# Get moon information using default location
moon_info = get_moon()
# Format the response to be more compact and readable
response = self._format_moon_response(moon_info)
# Use the unified send_response method
await self.send_response(message, response)
return True
except Exception as e:
error_msg = self.translate('commands.moon.error', error=str(e))
await self.send_response(message, error_msg)
return False
def _translate_phase_name(self, phase_name: str) -> str:
"""Translate English phase name to localized version.
Args:
phase_name: The English phase name (e.g., 'New Moon').
Returns:
str: The translated phase name, or original if not found.
"""
# Map English phase names (with or without emoji) to translation keys
phase_mapping = {
'New Moon': 'new_moon',
'Waxing Crescent': 'waxing_crescent',
'First Quarter': 'first_quarter',
'Waxing Gibbous': 'waxing_gibbous',
'Full Moon': 'full_moon',
'Waning Gibbous': 'waning_gibbous',
'Last Quarter': 'last_quarter',
'Waning Crescent': 'waning_crescent'
}
# Remove emoji if present (they're in the translation)
phase_clean = phase_name
for emoji in ['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘']:
phase_clean = phase_clean.replace(emoji, '').strip()
# Find matching translation key
for english_name, translation_key in phase_mapping.items():
if english_name in phase_clean:
translated = self.translate(f'commands.moon.phases.{translation_key}')
# If translation found (not just the key), return it
if translated != f'commands.moon.phases.{translation_key}':
return translated
# Fallback: return original if no translation found
return phase_name
def _format_moon_response(self, moon_info: str) -> str:
"""Format moon information to be more compact and readable.
Args:
moon_info: The raw moon info string.
Returns:
str: The formatted response string.
"""
try:
# Parse the moon info string to extract key information
lines = moon_info.split('\n')
moon_data = {}
for line in lines:
if ':' in line:
key, value = line.split(':', 1)
moon_data[key.strip()] = value.strip()
# Create a more compact format while keeping essential details
if 'MoonRise' in moon_data and 'Set' in moon_data and 'Phase' in moon_data:
# Keep day info but make it more compact
rise_info = moon_data['MoonRise'] # e.g., "Thu 04 06:47PM"
set_info = moon_data['Set'] # e.g., "Fri 05 03:43AM"
# Extract phase and illumination
phase_info = moon_data.get('Phase', self.translate('commands.moon.unknown_phase'))
if '@:' in phase_info:
phase, illum = phase_info.split('@:')
phase = phase.strip()
illum = illum.strip()
# Translate the phase name
phase = self._translate_phase_name(phase)
else:
phase = phase_info
phase = self._translate_phase_name(phase)
illum = self.translate('commands.moon.unknown_illum')
# Add next full and new moon dates (compact format)
if 'FullMoon' in moon_data and 'NewMoon' in moon_data:
full_moon = moon_data['FullMoon'] # e.g., "Sun Sep 07 11:08AM"
new_moon = moon_data['NewMoon'] # e.g., "Sun Sep 21 12:54PM"
# Extract just the essential date/time parts
full_parts = full_moon.split()
new_parts = new_moon.split()
if len(full_parts) >= 3 and len(new_parts) >= 3:
# Format: "Sep 07 11:08AM" and "Sep 21 12:54PM"
full_compact = f"{full_parts[1]} {full_parts[2]} {full_parts[3]}"
new_compact = f"{new_parts[1]} {new_parts[2]} {new_parts[3]}"
# Create compact response with full/new moon dates
return self.translate('commands.moon.format_with_dates',
phase=phase, illum=illum,
rise=rise_info, set=set_info,
full=full_compact, new=new_compact)
# Create compact response without full/new moon dates
return self.translate('commands.moon.format',
phase=phase, illum=illum,
rise=rise_info, set=set_info)
else:
# Fallback to original format if parsing fails
return self.translate('commands.moon.fallback', info=moon_info)
except Exception as e:
# Fallback to original format if formatting fails
return self.translate('commands.moon.fallback', info=moon_info)
def get_help_text(self) -> str:
"""Get help text for this command.
Returns:
str: The help text for this command.
"""
return self.description