Implement pet nicknames system - database, IRC command, validation
🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
4de0c1a124
commit
3098be7f36
3 changed files with 101 additions and 2 deletions
|
|
@ -32,6 +32,37 @@
|
|||
|
||||
## 🔄 Current Todo List
|
||||
|
||||
### Planned Next Features (In Priority Order)
|
||||
|
||||
#### Phase 1: Pet Nicknames System
|
||||
- [ ] **Database Schema** - Add nickname column to player_pets table
|
||||
- [ ] **IRC Commands** - Add !nickname <pet_id> <name> command
|
||||
- [ ] **Web Interface** - Display nicknames on player profiles
|
||||
- [ ] **Validation** - Ensure appropriate nickname length/content limits
|
||||
|
||||
#### Phase 2: Team Builder Tool (Secure PIN System)
|
||||
- [ ] **Web Team Editor** - Interface for modifying pet teams
|
||||
- [ ] **PIN Generation** - Create unique verification codes for each request
|
||||
- [ ] **Temporary Storage** - Hold pending team changes until PIN validation
|
||||
- [ ] **IRC PIN Delivery** - PM verification codes to players
|
||||
- [ ] **PIN Validation** - Web form to enter and confirm codes
|
||||
- [ ] **Database Updates** - Apply team changes only after successful PIN verification
|
||||
- [ ] **Security Cleanup** - Clear expired PINs and pending requests
|
||||
|
||||
**Secure Technical Flow:**
|
||||
```
|
||||
Web: Save Team → Generate PIN → Store Pending Changes → IRC: PM PIN
|
||||
↓
|
||||
Web: Enter PIN → Validate PIN → Apply Database Changes → Clear Request
|
||||
```
|
||||
*Critical: No database changes until PIN verification succeeds*
|
||||
|
||||
#### Phase 3: Auto-Battle Mode
|
||||
- [ ] **Auto-Battle Logic** - Automated pet combat in current location
|
||||
- [ ] **PM Notifications** - Send results to player via private message
|
||||
- [ ] **Flood Control** - 5-second delays between battles, wins/losses only
|
||||
- [ ] **Stop Mechanism** - Commands to start/stop auto-battle mode
|
||||
|
||||
### Low Priority
|
||||
- [ ] **Enhanced Petdex Filtering** - Add search by type, evolution chains, rarity filters
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class PetManagement(BaseModule):
|
|||
"""Handles team, pets, and future pet management commands"""
|
||||
|
||||
def get_commands(self):
|
||||
return ["team", "pets", "activate", "deactivate", "swap"]
|
||||
return ["team", "pets", "activate", "deactivate", "swap", "nickname"]
|
||||
|
||||
async def handle_command(self, channel, nickname, command, args):
|
||||
if command == "team":
|
||||
|
|
@ -20,6 +20,8 @@ class PetManagement(BaseModule):
|
|||
await self.cmd_deactivate(channel, nickname, args)
|
||||
elif command == "swap":
|
||||
await self.cmd_swap(channel, nickname, args)
|
||||
elif command == "nickname":
|
||||
await self.cmd_nickname(channel, nickname, args)
|
||||
|
||||
async def cmd_team(self, channel, nickname):
|
||||
"""Show active pets (channel display)"""
|
||||
|
|
@ -158,4 +160,28 @@ class PetManagement(BaseModule):
|
|||
self.send_message(channel, f"{nickname}: Pet swap completed!")
|
||||
else:
|
||||
self.send_pm(nickname, f"❌ {result['error']}")
|
||||
self.send_message(channel, f"{nickname}: Pet swap failed - check PM for details!")
|
||||
self.send_message(channel, f"{nickname}: Pet swap failed - check PM for details!")
|
||||
|
||||
async def cmd_nickname(self, channel, nickname, args):
|
||||
"""Set a nickname for a pet"""
|
||||
if len(args) < 2:
|
||||
self.send_message(channel, f"{nickname}: Usage: !nickname <pet> <new_nickname>")
|
||||
self.send_message(channel, f"Example: !nickname Charmander Flamey")
|
||||
return
|
||||
|
||||
player = await self.require_player(channel, nickname)
|
||||
if not player:
|
||||
return
|
||||
|
||||
# Split args into pet identifier and new nickname
|
||||
pet_identifier = args[0]
|
||||
new_nickname = " ".join(args[1:])
|
||||
|
||||
result = await self.database.set_pet_nickname(player["id"], pet_identifier, new_nickname)
|
||||
|
||||
if result["success"]:
|
||||
old_name = result["old_name"]
|
||||
new_name = result["new_nickname"]
|
||||
self.send_message(channel, f"✨ {nickname}: {old_name} is now nicknamed '{new_name}'!")
|
||||
else:
|
||||
self.send_message(channel, f"❌ {nickname}: {result['error']}")
|
||||
|
|
@ -1316,4 +1316,46 @@ class Database:
|
|||
"total_encounters": total_encounters,
|
||||
"total_species": total_species,
|
||||
"completion_percentage": round(completion_percentage, 1)
|
||||
}
|
||||
|
||||
async def set_pet_nickname(self, player_id: int, pet_identifier: str, nickname: str) -> Dict:
|
||||
"""Set a nickname for a pet. Returns result dict."""
|
||||
# Validate nickname
|
||||
if not nickname.strip():
|
||||
return {"success": False, "error": "Nickname cannot be empty"}
|
||||
|
||||
nickname = nickname.strip()
|
||||
if len(nickname) > 20:
|
||||
return {"success": False, "error": "Nickname must be 20 characters or less"}
|
||||
|
||||
# Basic content validation
|
||||
if any(char in nickname for char in ['<', '>', '&', '"', "'"]):
|
||||
return {"success": False, "error": "Nickname contains invalid characters"}
|
||||
|
||||
async with aiosqlite.connect(self.db_path) as db:
|
||||
db.row_factory = aiosqlite.Row
|
||||
|
||||
# Find pet by current nickname or species name
|
||||
cursor = await db.execute("""
|
||||
SELECT p.*, ps.name as species_name
|
||||
FROM pets p
|
||||
JOIN pet_species ps ON p.species_id = ps.id
|
||||
WHERE p.player_id = ?
|
||||
AND (p.nickname = ? OR ps.name = ?)
|
||||
LIMIT 1
|
||||
""", (player_id, pet_identifier, pet_identifier))
|
||||
|
||||
pet = await cursor.fetchone()
|
||||
if not pet:
|
||||
return {"success": False, "error": f"Pet '{pet_identifier}' not found"}
|
||||
|
||||
# Update nickname
|
||||
await db.execute("UPDATE pets SET nickname = ? WHERE id = ?", (nickname, pet["id"]))
|
||||
await db.commit()
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"pet": dict(pet),
|
||||
"old_name": pet["nickname"] or pet["species_name"],
|
||||
"new_nickname": nickname
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue