Implement case-insensitive command processing across all bot modules
Added normalize_input() function to BaseModule for consistent lowercase conversion of user input. Updated all command modules to use normalization for commands, arguments, pet names, location names, gym names, and item names. Players can now use any capitalization for commands and arguments. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
39ba55832d
commit
8e9ff2960f
8 changed files with 93 additions and 16 deletions
|
|
@ -12,6 +12,15 @@ class BaseModule(ABC):
|
||||||
self.database = database
|
self.database = database
|
||||||
self.game_engine = game_engine
|
self.game_engine = game_engine
|
||||||
|
|
||||||
|
@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
|
@abstractmethod
|
||||||
def get_commands(self):
|
def get_commands(self):
|
||||||
"""Return list of commands this module handles"""
|
"""Return list of commands this module handles"""
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ class BattleSystem(BaseModule):
|
||||||
if not player:
|
if not player:
|
||||||
return
|
return
|
||||||
|
|
||||||
move_name = " ".join(args).title() # Normalize to Title Case
|
move_name = " ".join(self.normalize_input(args)).title() # Normalize to Title Case
|
||||||
result = await self.game_engine.battle_engine.execute_battle_turn(player["id"], move_name)
|
result = await self.game_engine.battle_engine.execute_battle_turn(player["id"], move_name)
|
||||||
|
|
||||||
if "error" in result:
|
if "error" in result:
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class Exploration(BaseModule):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Handle various input formats and normalize location names
|
# Handle various input formats and normalize location names
|
||||||
destination_input = " ".join(args).lower()
|
destination_input = self.normalize_input(" ".join(args))
|
||||||
|
|
||||||
# Map common variations to exact location names
|
# Map common variations to exact location names
|
||||||
location_mappings = {
|
location_mappings = {
|
||||||
|
|
@ -82,7 +82,7 @@ class Exploration(BaseModule):
|
||||||
destination = location_mappings.get(destination_input)
|
destination = location_mappings.get(destination_input)
|
||||||
if not destination:
|
if not destination:
|
||||||
# Fall back to title case if no mapping found
|
# Fall back to title case if no mapping found
|
||||||
destination = " ".join(args).title()
|
destination = " ".join(self.normalize_input(args)).title()
|
||||||
|
|
||||||
location = await self.database.get_location_by_name(destination)
|
location = await self.database.get_location_by_name(destination)
|
||||||
|
|
||||||
|
|
@ -171,7 +171,7 @@ class Exploration(BaseModule):
|
||||||
|
|
||||||
if args:
|
if args:
|
||||||
# Specific location requested
|
# Specific location requested
|
||||||
location_name = " ".join(args).title()
|
location_name = " ".join(self.normalize_input(args)).title()
|
||||||
else:
|
else:
|
||||||
# Default to current location
|
# Default to current location
|
||||||
current_location = await self.database.get_player_location(player["id"])
|
current_location = await self.database.get_player_location(player["id"])
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ class GymBattles(BaseModule):
|
||||||
if command == "gym":
|
if command == "gym":
|
||||||
if not args:
|
if not args:
|
||||||
await self.cmd_gym_list(channel, nickname)
|
await self.cmd_gym_list(channel, nickname)
|
||||||
elif args[0] == "list":
|
elif self.normalize_input(args[0]) == "list":
|
||||||
await self.cmd_gym_list_all(channel, nickname)
|
await self.cmd_gym_list_all(channel, nickname)
|
||||||
elif args[0] == "challenge":
|
elif self.normalize_input(args[0]) == "challenge":
|
||||||
await self.cmd_gym_challenge(channel, nickname, args[1:])
|
await self.cmd_gym_challenge(channel, nickname, args[1:])
|
||||||
elif args[0] == "info":
|
elif self.normalize_input(args[0]) == "info":
|
||||||
await self.cmd_gym_info(channel, nickname, args[1:])
|
await self.cmd_gym_info(channel, nickname, args[1:])
|
||||||
elif args[0] == "status":
|
elif self.normalize_input(args[0]) == "status":
|
||||||
await self.cmd_gym_status(channel, nickname)
|
await self.cmd_gym_status(channel, nickname)
|
||||||
else:
|
else:
|
||||||
await self.cmd_gym_list(channel, nickname)
|
await self.cmd_gym_list(channel, nickname)
|
||||||
|
|
@ -111,7 +111,7 @@ class GymBattles(BaseModule):
|
||||||
self.send_message(channel, f"{nickname}: You are not in a valid location! Use !travel to go somewhere first.")
|
self.send_message(channel, f"{nickname}: You are not in a valid location! Use !travel to go somewhere first.")
|
||||||
return
|
return
|
||||||
|
|
||||||
gym_name = " ".join(args).strip('"')
|
gym_name = " ".join(self.normalize_input(args)).strip('"')
|
||||||
|
|
||||||
# Look for gym in player's current location (case-insensitive)
|
# Look for gym in player's current location (case-insensitive)
|
||||||
gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"])
|
gym = await self.database.get_gym_by_name_in_location(gym_name, location["id"])
|
||||||
|
|
@ -266,7 +266,7 @@ class GymBattles(BaseModule):
|
||||||
if not player:
|
if not player:
|
||||||
return
|
return
|
||||||
|
|
||||||
gym_name = " ".join(args).strip('"')
|
gym_name = " ".join(self.normalize_input(args)).strip('"')
|
||||||
|
|
||||||
# First try to find gym in player's current location
|
# First try to find gym in player's current location
|
||||||
location = await self.database.get_player_location(player["id"])
|
location = await self.database.get_player_location(player["id"])
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ class Inventory(BaseModule):
|
||||||
if not player:
|
if not player:
|
||||||
return
|
return
|
||||||
|
|
||||||
item_name = " ".join(args)
|
item_name = " ".join(self.normalize_input(args))
|
||||||
result = await self.database.use_item(player["id"], item_name)
|
result = await self.database.use_item(player["id"], item_name)
|
||||||
|
|
||||||
if not result["success"]:
|
if not result["success"]:
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class PetManagement(BaseModule):
|
||||||
if not player:
|
if not player:
|
||||||
return
|
return
|
||||||
|
|
||||||
pet_name = " ".join(args)
|
pet_name = " ".join(self.normalize_input(args))
|
||||||
result = await self.database.activate_pet(player["id"], pet_name)
|
result = await self.database.activate_pet(player["id"], pet_name)
|
||||||
|
|
||||||
if result["success"]:
|
if result["success"]:
|
||||||
|
|
@ -112,7 +112,7 @@ class PetManagement(BaseModule):
|
||||||
if not player:
|
if not player:
|
||||||
return
|
return
|
||||||
|
|
||||||
pet_name = " ".join(args)
|
pet_name = " ".join(self.normalize_input(args))
|
||||||
result = await self.database.deactivate_pet(player["id"], pet_name)
|
result = await self.database.deactivate_pet(player["id"], pet_name)
|
||||||
|
|
||||||
if result["success"]:
|
if result["success"]:
|
||||||
|
|
@ -174,7 +174,7 @@ class PetManagement(BaseModule):
|
||||||
return
|
return
|
||||||
|
|
||||||
# Split args into pet identifier and new nickname
|
# Split args into pet identifier and new nickname
|
||||||
pet_identifier = args[0]
|
pet_identifier = self.normalize_input(args[0])
|
||||||
new_nickname = " ".join(args[1:])
|
new_nickname = " ".join(args[1:])
|
||||||
|
|
||||||
result = await self.database.set_pet_nickname(player["id"], pet_identifier, new_nickname)
|
result = await self.database.set_pet_nickname(player["id"], pet_identifier, new_nickname)
|
||||||
|
|
|
||||||
|
|
@ -303,12 +303,14 @@ class PetBotDebug:
|
||||||
self.handle_command(channel, nickname, message)
|
self.handle_command(channel, nickname, message)
|
||||||
|
|
||||||
def handle_command(self, channel, nickname, message):
|
def handle_command(self, channel, nickname, message):
|
||||||
|
from modules.base_module import BaseModule
|
||||||
|
|
||||||
command_parts = message[1:].split()
|
command_parts = message[1:].split()
|
||||||
if not command_parts:
|
if not command_parts:
|
||||||
return
|
return
|
||||||
|
|
||||||
command = command_parts[0].lower()
|
command = BaseModule.normalize_input(command_parts[0])
|
||||||
args = command_parts[1:]
|
args = BaseModule.normalize_input(command_parts[1:])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if command in self.command_map:
|
if command in self.command_map:
|
||||||
|
|
|
||||||
66
webserver.py
66
webserver.py
|
|
@ -822,6 +822,32 @@ class PetBotRequestHandler(BaseHTTPRequestHandler):
|
||||||
border: 1px solid var(--border-color);
|
border: 1px solid var(--border-color);
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
.hidden-spawn {{
|
||||||
|
display: none;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.more-button {{
|
||||||
|
background: var(--gradient-primary) !important;
|
||||||
|
color: white !important;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.more-button:hover {{
|
||||||
|
transform: scale(1.05);
|
||||||
|
}}
|
||||||
|
|
||||||
|
.less-button {{
|
||||||
|
background: #ff6b6b !important;
|
||||||
|
color: white !important;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}}
|
||||||
|
|
||||||
|
.less-button:hover {{
|
||||||
|
transform: scale(1.05);
|
||||||
|
}}
|
||||||
|
|
||||||
.info-section {{
|
.info-section {{
|
||||||
background: var(--bg-secondary);
|
background: var(--bg-secondary);
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
|
|
@ -862,6 +888,46 @@ class PetBotRequestHandler(BaseHTTPRequestHandler):
|
||||||
💡 Use <code>!wild <location></code> in #petz to see what pets spawn in a specific area
|
💡 Use <code>!wild <location></code> in #petz to see what pets spawn in a specific area
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleSpawns(locationId) {{
|
||||||
|
const hiddenSpawns = document.querySelectorAll(`#hidden-${{locationId}}`);
|
||||||
|
const moreButton = document.querySelector(`[onclick="toggleSpawns(${{locationId}})"]`);
|
||||||
|
|
||||||
|
if (!moreButton) return;
|
||||||
|
|
||||||
|
const isHidden = hiddenSpawns[0] && hiddenSpawns[0].style.display === 'none' || hiddenSpawns[0] && hiddenSpawns[0].classList.contains('hidden-spawn');
|
||||||
|
|
||||||
|
if (isHidden) {{
|
||||||
|
// Show hidden spawns
|
||||||
|
hiddenSpawns.forEach(spawn => {{
|
||||||
|
spawn.classList.remove('hidden-spawn');
|
||||||
|
spawn.style.display = 'inline-block';
|
||||||
|
}});
|
||||||
|
moreButton.textContent = 'Show less';
|
||||||
|
moreButton.className = 'spawn-badge less-button';
|
||||||
|
moreButton.setAttribute('onclick', `hideSpawns(${{locationId}})`);
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
|
||||||
|
function hideSpawns(locationId) {{
|
||||||
|
const hiddenSpawns = document.querySelectorAll(`#hidden-${{locationId}}`);
|
||||||
|
const lessButton = document.querySelector(`[onclick="hideSpawns(${{locationId}})"]`);
|
||||||
|
|
||||||
|
if (!lessButton) return;
|
||||||
|
|
||||||
|
// Hide spawns again
|
||||||
|
hiddenSpawns.forEach(spawn => {{
|
||||||
|
spawn.classList.add('hidden-spawn');
|
||||||
|
spawn.style.display = 'none';
|
||||||
|
}});
|
||||||
|
|
||||||
|
const hiddenCount = hiddenSpawns.length;
|
||||||
|
lessButton.textContent = `+${{hiddenCount}} more`;
|
||||||
|
lessButton.className = 'spawn-badge more-button';
|
||||||
|
lessButton.setAttribute('onclick', `toggleSpawns(${{locationId}})`);
|
||||||
|
}}
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>"""
|
</html>"""
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue