Petbot/modules/base_module.py
megaproxy e17705dc63 Implement comprehensive team management and fix critical bugs
Team Management Features:
- Added 6 new IRC commands: \!teamlist, \!activeteam, \!teamname, \!teamswap, \!heal, \!verifyteamswap
- \!teamlist shows teams with pet names in format "Team name - pet1 - pet2 - pet3"
- \!teamname redirects to web interface for secure PIN-based renaming
- \!teamswap enables team switching with PIN verification via IRC
- \!activeteam displays current team with health status indicators
- \!heal command with 1-hour cooldown for pet health restoration

Critical Bug Fixes:
- Fixed \!teamlist SQL binding error - handled new team data format correctly
- Fixed \!wild command duplicates - now shows unique species types only
- Removed all debug print statements and implemented proper logging
- Fixed data format inconsistencies in team management system

Production Improvements:
- Added logging infrastructure to BaseModule and core components
- Converted 45+ print statements to professional logging calls
- Database query optimization with DISTINCT for spawn deduplication
- Enhanced error handling and user feedback messages

Cross-platform Integration:
- Seamless sync between IRC commands and web interface
- PIN authentication leverages existing secure infrastructure
- Team operations maintain consistency across all interfaces

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-01 15:53:26 +00:00

62 lines
No EOL
2.2 KiB
Python

#!/usr/bin/env python3
"""Base module class for PetBot command modules"""
import asyncio
import logging
from abc import ABC, abstractmethod
class BaseModule(ABC):
"""Base class for all PetBot modules"""
def __init__(self, bot, database, game_engine):
self.bot = bot
self.database = database
self.game_engine = game_engine
self.logger = logging.getLogger(self.__class__.__name__)
@staticmethod
def normalize_input(user_input):
"""Normalize user input by converting to lowercase for case-insensitive command processing"""
if isinstance(user_input, str):
return user_input.lower()
elif isinstance(user_input, list):
return [item.lower() if isinstance(item, str) else item for item in user_input]
return user_input
@abstractmethod
def get_commands(self):
"""Return list of commands this module handles"""
pass
@abstractmethod
async def handle_command(self, channel, nickname, command, args):
"""Handle a command for this module"""
pass
def send_message(self, target, message):
"""Send message through the bot"""
# Use sync wrapper if available (new bot), otherwise fallback to old method
if hasattr(self.bot, 'send_message_sync'):
self.bot.send_message_sync(target, message)
else:
self.bot.send_message(target, message)
def send_pm(self, nickname, message):
"""Send private message to user"""
# Use sync wrapper if available (new bot), otherwise fallback to old method
if hasattr(self.bot, 'send_message_sync'):
self.bot.send_message_sync(nickname, message)
else:
self.bot.send_message(nickname, message)
async def get_player(self, nickname):
"""Get player from database"""
return await self.database.get_player(nickname)
async def require_player(self, channel, nickname):
"""Get player or send start message if not found"""
player = await self.get_player(nickname)
if not player:
self.send_message(channel, f"{nickname}: Use !start to begin your journey first!")
return None
return player