Simplified DuckHunt bot with customizable messages and colors
This commit is contained in:
87
src/utils.py
87
src/utils.py
@@ -3,7 +3,83 @@ Utility functions for DuckHunt Bot
|
||||
"""
|
||||
|
||||
import re
|
||||
from typing import Optional
|
||||
import json
|
||||
import os
|
||||
from typing import Optional, Tuple, List, Dict, Any
|
||||
|
||||
|
||||
class MessageManager:
|
||||
"""Manages customizable IRC messages with color support"""
|
||||
|
||||
def __init__(self, messages_file: str = "messages.json"):
|
||||
self.messages_file = messages_file
|
||||
self.messages = {}
|
||||
self.load_messages()
|
||||
|
||||
def load_messages(self):
|
||||
"""Load messages from JSON file"""
|
||||
try:
|
||||
if os.path.exists(self.messages_file):
|
||||
with open(self.messages_file, 'r', encoding='utf-8') as f:
|
||||
self.messages = json.load(f)
|
||||
else:
|
||||
# Fallback messages if file doesn't exist
|
||||
self.messages = self._get_default_messages()
|
||||
except Exception as e:
|
||||
print(f"Error loading messages: {e}, using defaults")
|
||||
self.messages = self._get_default_messages()
|
||||
|
||||
def _get_default_messages(self) -> Dict[str, str]:
|
||||
"""Default fallback messages without colors"""
|
||||
return {
|
||||
"duck_spawn": "・゜゜・。。・゜゜\\_o< QUACK! A duck has appeared! Type !bang to shoot it!",
|
||||
"duck_flies_away": "The duck flies away. ·°'`'°-.,¸¸.·°'`",
|
||||
"bang_hit": "{nick} > *BANG* You shot the duck! [+{xp_gained} xp] [Total ducks: {ducks_shot}]",
|
||||
"bang_miss": "{nick} > *BANG* You missed the duck!",
|
||||
"bang_no_duck": "{nick} > *BANG* What did you shoot at? There is no duck in the area... [GUN CONFISCATED]",
|
||||
"bang_no_ammo": "{nick} > *click* You're out of ammo! Use !reload",
|
||||
"bang_not_armed": "{nick} > You are not armed.",
|
||||
"reload_success": "{nick} > *click* Reloaded! [Ammo: {ammo}/{max_ammo}] [Chargers: {chargers}]",
|
||||
"reload_already_loaded": "{nick} > Your gun is already loaded!",
|
||||
"reload_no_chargers": "{nick} > You're out of chargers!",
|
||||
"reload_not_armed": "{nick} > You are not armed.",
|
||||
"shop_display": "DuckHunt Shop: {items} | You have {xp} XP",
|
||||
"shop_item_format": "({id}) {name} - {price} XP",
|
||||
"help_header": "DuckHunt Commands:",
|
||||
"help_user_commands": "!bang - Shoot at ducks | !reload - Reload your gun | !shop - View the shop",
|
||||
"help_help_command": "!duckhelp - Show this help",
|
||||
"help_admin_commands": "Admin: !rearm <player> | !disarm <player> | !ignore <player> | !unignore <player> | !ducklaunch",
|
||||
"admin_rearm_player": "[ADMIN] {target} has been rearmed by {admin}",
|
||||
"admin_rearm_all": "[ADMIN] All players have been rearmed by {admin}",
|
||||
"admin_disarm": "[ADMIN] {target} has been disarmed by {admin}",
|
||||
"admin_ignore": "[ADMIN] {target} is now ignored by {admin}",
|
||||
"admin_unignore": "[ADMIN] {target} is no longer ignored by {admin}",
|
||||
"admin_ducklaunch": "[ADMIN] A duck has been launched by {admin}",
|
||||
"admin_ducklaunch_not_enabled": "[ADMIN] This channel is not enabled for duckhunt",
|
||||
"usage_rearm": "Usage: !rearm <player>",
|
||||
"usage_disarm": "Usage: !disarm <player>",
|
||||
"usage_ignore": "Usage: !ignore <player>",
|
||||
"usage_unignore": "Usage: !unignore <player>"
|
||||
}
|
||||
|
||||
def get(self, key: str, **kwargs) -> str:
|
||||
"""Get a formatted message by key"""
|
||||
if key not in self.messages:
|
||||
return f"[Missing message: {key}]"
|
||||
|
||||
message = self.messages[key]
|
||||
|
||||
# Format with provided variables
|
||||
try:
|
||||
return message.format(**kwargs)
|
||||
except KeyError as e:
|
||||
return f"[Message format error: {e}]"
|
||||
except Exception as e:
|
||||
return f"[Message error: {e}]"
|
||||
|
||||
def reload(self):
|
||||
"""Reload messages from file"""
|
||||
self.load_messages()
|
||||
|
||||
|
||||
class InputValidator:
|
||||
@@ -46,12 +122,17 @@ class InputValidator:
|
||||
return sanitized[:500]
|
||||
|
||||
|
||||
def parse_message(line):
|
||||
def parse_irc_message(line: str) -> Tuple[str, str, List[str], str]:
|
||||
"""Parse IRC message format"""
|
||||
prefix = ''
|
||||
trailing = ''
|
||||
if line.startswith(':'):
|
||||
prefix, line = line[1:].split(' ', 1)
|
||||
if ' ' in line[1:]:
|
||||
prefix, line = line[1:].split(' ', 1)
|
||||
else:
|
||||
# Handle malformed IRC line with no space after prefix
|
||||
prefix = line[1:]
|
||||
line = ''
|
||||
if ' :' in line:
|
||||
line, trailing = line.split(' :', 1)
|
||||
parts = line.split()
|
||||
|
||||
Reference in New Issue
Block a user