From eb041477dc4fe46ab4e45b4a54d399908f270532 Mon Sep 17 00:00:00 2001 From: ComputerTech312 Date: Wed, 24 Sep 2025 20:33:23 +0100 Subject: [PATCH] Add comprehensive documentation and fix authentication config paths - Add detailed README.md with installation, usage, and development guide - Add CONFIG.md with complete configuration documentation - Update connection and SASL authentication to use nested config paths - Fix server password and SASL username/password config access - Add config validation test script (test_config.py) - Clean up config.json (removed invalid JSON comments) - Improve error handling for config arrays and null values --- CONFIG.md | 127 +++++++++++++ README.md | 201 ++++++++++++++++++++ config.json | 8 +- src/__pycache__/duckhuntbot.cpython-312.pyc | Bin 44517 -> 44739 bytes src/__pycache__/sasl.cpython-312.pyc | Bin 11033 -> 10990 bytes src/duckhuntbot.py | 28 +-- src/sasl.py | 8 +- test_config.py | 56 ++++++ 8 files changed, 409 insertions(+), 19 deletions(-) create mode 100644 CONFIG.md create mode 100644 README.md create mode 100644 test_config.py diff --git a/CONFIG.md b/CONFIG.md new file mode 100644 index 0000000..a57f682 --- /dev/null +++ b/CONFIG.md @@ -0,0 +1,127 @@ +# DuckHunt Bot Configuration Guide + +This document explains all configuration options in `config.json`. + +## ๐Ÿ“ก IRC Connection Settings (`connection`) + +| Setting | Description | Example | +|---------|-------------|---------| +| `server` | IRC server hostname | `"irc.rizon.net"` | +| `port` | IRC server port | `6697` (SSL) or `6667` (non-SSL) | +| `nick` | Bot's nickname on IRC | `"DuckHunt"` | +| `channels` | List of channels to auto-join | `["#channel1", "#channel2"]` | +| `ssl` | Use SSL/TLS encryption | `true` (recommended) | +| `password` | Server password (I-Line auth) | Change if server requires auth | +| `max_retries` | Connection retry attempts | `3` | +| `retry_delay` | Seconds between retries | `5` | +| `timeout` | Connection timeout in seconds | `30` | + +## ๐Ÿ” SASL Authentication (`sasl`) + +SASL is used for NickServ authentication on connect. + +| Setting | Description | Example | +|---------|-------------|---------| +| `enabled` | Enable SASL authentication | `false` | +| `username` | Registered nickname | `"your_registered_nick"` | +| `password` | NickServ password | `"your_nickserv_password"` | + +**Note:** Change `password` from the default if enabling SASL! + +## ๐Ÿ‘‘ Bot Administration (`admins`) + +Array of IRC nicknames with admin privileges. + +```json +"admins": ["peorth", "computertech", "colby"] +``` + +## ๐Ÿฆ† Duck Spawning (`duck_spawning`) + +| Setting | Description | Default | +|---------|-------------|---------| +| `spawn_min` | Minimum seconds between spawns | `10` | +| `spawn_max` | Maximum seconds between spawns | `30` | +| `timeout` | Global fallback timeout | `60` | +| `rearm_on_duck_shot` | Auto-rearm guns when duck shot | `true` | + +## ๐ŸŽฏ Duck Types (`duck_types`) + +### Normal Ducks (`normal`) +- `xp`: XP reward (default: `10`) +- `timeout`: Seconds before flying away (default: `60`) + +### Golden Ducks (`golden`) +- `chance`: Spawn probability (default: `0.15` = 15%) +- `min_hp`: Minimum hit points (default: `3`) +- `max_hp`: Maximum hit points (default: `5`) +- `xp`: XP reward (default: `15`) +- `timeout`: Seconds before flying away (default: `60`) + +### Fast Ducks (`fast`) +- `chance`: Spawn probability (default: `0.25` = 25%) +- `timeout`: Seconds before flying away (default: `20`) +- `xp`: XP reward (default: `12`) + +**Note:** Chances are decimal percentages (0.15 = 15%, 0.25 = 25%) + +## ๐Ÿ‘ค New Player Defaults (`player_defaults`) + +Starting values for new players: + +| Setting | Description | Default | +|---------|-------------|---------| +| `accuracy` | Starting accuracy percentage (0-100) | `75` | +| `magazines` | Starting number of magazines | `3` | +| `bullets_per_magazine` | Bullets per magazine | `6` | +| `jam_chance` | Gun jam percentage (0-100) | `15` | +| `xp` | Starting XP (also currency) | `0` | + +## ๐ŸŽฎ Game Mechanics (`gameplay`) + +| Setting | Description | Default | +|---------|-------------|---------| +| `befriend_success_rate` | Base befriend chance (%) | `75` | +| `befriend_xp` | XP from befriending | `5` | +| `accuracy_gain_on_hit` | Accuracy boost per hit | `1` | +| `accuracy_loss_on_miss` | Accuracy loss per miss | `2` | +| `min_accuracy` | Minimum accuracy limit | `10` | +| `max_accuracy` | Maximum accuracy limit | `100` | +| `min_befriend_success_rate` | Min befriend rate | `5` | +| `max_befriend_success_rate` | Max befriend rate | `95` | + +## ๐Ÿ”ง Feature Toggles (`features`) + +| Setting | Description | Default | +|---------|-------------|---------| +| `shop_enabled` | Enable shop system | `true` | +| `inventory_enabled` | Enable inventory system | `true` | +| `auto_rearm_enabled` | Enable auto gun rearming | `true` | + +## โš–๏ธ System Limits (`limits`) + +| Setting | Description | Default | +|---------|-------------|---------| +| `max_inventory_items` | Max items per player | `20` | +| `max_temp_effects` | Max temporary effects | `20` | + +--- + +## ๐Ÿ”ง Configuration Access + +The bot uses dot notation to access nested settings: + +```python +# Examples: +server = bot.get_config('connection.server') +normal_xp = bot.get_config('duck_types.normal.xp') +player_accuracy = bot.get_config('player_defaults.accuracy') +``` + +## ๐Ÿ“ Tips + +1. **Percentages:** Most percentage values use 0-100 scale, but spawn chances use 0.0-1.0 decimals +2. **Authentication:** Set real passwords when using server auth or SASL +3. **Balance:** Adjust XP rewards and duck spawn rates to balance gameplay +4. **Testing:** Change one setting at a time to test effects +5. **Backup:** Keep a backup of working config before major changes \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a2ecee6 --- /dev/null +++ b/README.md @@ -0,0 +1,201 @@ +# ๐Ÿฆ† DuckHunt IRC Bot + +A feature-rich IRC bot that brings the classic duck hunting game to your IRC channels. Players can shoot, befriend, and collect various types of ducks while managing their equipment and competing for high scores. + +## โœจ Features + +- ๐Ÿฆ† **Multiple Duck Types**: Normal, Golden (high HP), and Fast (quick timeout) ducks +- ๐ŸŽฏ **Accuracy System**: Dynamic accuracy that improves with hits and degrades with misses +- ๐Ÿ”ซ **Weapon Management**: Magazines, bullets, and gun jamming mechanics +- ๐Ÿ›’ **Shop System**: Buy equipment and items with XP (currency) +- ๐ŸŽ’ **Inventory System**: Collect and use various items (bread, grease, sights, etc.) +- ๐Ÿ‘ฅ **Player Statistics**: Track shots, hits, misses, and best times +- ๐Ÿ”ง **Fully Configurable**: Every game parameter can be customized via config +- ๐Ÿ” **Authentication**: Support for both server passwords and SASL/NickServ auth +- ๐Ÿ“Š **Admin Commands**: Comprehensive bot management and player administration + +## ๐Ÿš€ Quick Start + +### Prerequisites + +- Python 3.8+ +- Virtual environment (recommended) + +### Installation + +1. **Clone the repository:** + ```bash + git clone https://github.com/your-username/duckhunt-bot.git + cd duckhunt-bot + ``` + +2. **Set up virtual environment:** + ```bash + python -m venv .venv + source .venv/bin/activate # Linux/Mac + # or + .venv\Scripts\activate # Windows + ``` + +3. **Install dependencies:** + ```bash + pip install -r requirements.txt + ``` + +4. **Configure the bot:** + - Copy `config.json.example` to `config.json` (if available) + - Edit `config.json` with your IRC server settings + - See [CONFIG.md](CONFIG.md) for detailed configuration guide + +5. **Run the bot:** + ```bash + python duckhunt.py + ``` + +## โš™๏ธ Configuration + +The bot uses a nested JSON configuration system. Key settings include: + +### Connection Settings +```json +{ + "connection": { + "server": "irc.your-server.net", + "port": 6697, + "nick": "DuckHunt", + "channels": ["#your-channel"], + "ssl": true + } +} +``` + +### Duck Types & Rewards +```json +{ + "duck_types": { + "normal": { "xp": 10, "timeout": 60 }, + "golden": { "chance": 0.15, "min_hp": 3, "max_hp": 5, "xp": 15 }, + "fast": { "chance": 0.25, "timeout": 20, "xp": 12 } + } +} +``` + +**๐Ÿ“– See [CONFIG.md](CONFIG.md) for complete configuration documentation.** + +## ๐ŸŽฎ Game Commands + +### Player Commands +- `!shoot` - Shoot at a duck +- `!reload` - Reload your weapon +- `!befriend` - Try to befriend a duck +- `!stats [player]` - View player statistics +- `!shop` - View the shop +- `!buy ` - Purchase an item +- `!inventory` - Check your inventory +- `!use ` - Use an item from inventory + +### Admin Commands +- `!spawn` - Manually spawn a duck +- `!give ` - Give items to players +- `!setstat ` - Modify player stats +- `!reload_config` - Reload configuration without restart + +## ๐Ÿฆ† Duck Types + +| Type | Spawn Rate | HP | Timeout | XP Reward | +|------|------------|----|---------|-----------| +| Normal | 60% | 1 | 60s | 10 | +| Golden | 15% | 3-5 | 60s | 15 | +| Fast | 25% | 1 | 20s | 12 | + +## ๐Ÿ›’ Shop Items + +- **Bread** - Attracts more ducks +- **Gun Grease** - Reduces jam chance +- **Sight** - Improves accuracy +- **Silencer** - Enables stealth shooting +- **Explosive Ammo** - Extra damage +- **Lucky Charm** - Increases rewards +- **Duck Detector** - Reveals duck locations + +## ๐Ÿ“ Project Structure + +``` +duckhunt/ +โ”œโ”€โ”€ duckhunt.py # Main bot entry point +โ”œโ”€โ”€ config.json # Bot configuration +โ”œโ”€โ”€ CONFIG.md # Configuration documentation +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ duckhuntbot.py # Core bot IRC functionality +โ”‚ โ”œโ”€โ”€ game.py # Duck game mechanics +โ”‚ โ”œโ”€โ”€ db.py # Player database management +โ”‚ โ”œโ”€โ”€ shop.py # Shop system +โ”‚ โ”œโ”€โ”€ levels.py # Player leveling system +โ”‚ โ”œโ”€โ”€ sasl.py # SASL authentication +โ”‚ โ””โ”€โ”€ utils.py # Utility functions +โ”œโ”€โ”€ shop.json # Shop item definitions +โ”œโ”€โ”€ levels.json # Level progression data +โ”œโ”€โ”€ messages.json # Bot response messages +โ””โ”€โ”€ duckhunt.json # Player database +``` + +## ๐Ÿ”ง Development + +### Adding New Features + +The bot is designed with modularity in mind: + +1. **Game mechanics** are in `src/game.py` +2. **IRC functionality** is in `src/duckhuntbot.py` +3. **Database operations** are in `src/db.py` +4. **Configuration** uses dot notation: `bot.get_config('duck_types.normal.xp')` + +### Testing Configuration + +Use the built-in config tester: +```bash +python test_config.py +``` + +## ๐Ÿ› ๏ธ Troubleshooting + +### Common Issues + +1. **Connection fails**: Check server, port, and SSL settings in config +2. **SASL authentication fails**: Verify username/password and ensure nick is registered +3. **Bot doesn't respond**: Check channel permissions and admin list +4. **Config errors**: Validate JSON syntax and see CONFIG.md for proper values + +### Debug Mode + +Enable detailed logging by setting log level in the code or add verbose output. + +## ๐Ÿค Contributing + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Make your changes +4. Add tests if applicable +5. Commit your changes (`git commit -m 'Add amazing feature'`) +6. Push to the branch (`git push origin feature/amazing-feature`) +7. Open a Pull Request + +## ๐Ÿ“ License + +This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. + +## ๐Ÿ™ Acknowledgments + +- Inspired by classic IRC duck hunting bots +- Built with Python's asyncio for modern async IRC handling +- Thanks to all contributors and testers + +## ๐Ÿ“ž Support + +- ๐Ÿ“– **Documentation**: See [CONFIG.md](CONFIG.md) for configuration help +- ๐Ÿ› **Issues**: Report bugs via GitHub Issues +- ๐Ÿ’ฌ **Discussion**: Join our IRC channel for help and discussion + +--- + +**Happy Duck Hunting!** ๐Ÿฆ†๐Ÿ”ซ \ No newline at end of file diff --git a/config.json b/config.json index 73a8e3a..7b9ca3e 100644 --- a/config.json +++ b/config.json @@ -36,12 +36,12 @@ "min_hp": 3, "max_hp": 5, "xp": 15, - "timeout": 50 + "timeout": 60 }, "fast": { "chance": 0.25, "timeout": 20, - "xp": 20 + "xp": 12 } }, @@ -49,7 +49,7 @@ "accuracy": 75, "magazines": 3, "bullets_per_magazine": 6, - "jam_chance": 5, + "jam_chance": 15, "xp": 0 }, @@ -72,6 +72,6 @@ "limits": { "max_inventory_items": 20, - "max_temp_effects": 5 + "max_temp_effects": 20 } } \ No newline at end of file diff --git a/src/__pycache__/duckhuntbot.cpython-312.pyc b/src/__pycache__/duckhuntbot.cpython-312.pyc index b9f6ff8624fb55dd488f982b8eebedcffddfd645..21c0762662c43b0b5a6b8392ed1fe42125f304a8 100644 GIT binary patch delta 7262 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 INO2wi2k!nERsaA1 delta 6965 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 S`kt*w*kmRdV*(;YJ^l|43A=9q diff --git a/src/__pycache__/sasl.cpython-312.pyc b/src/__pycache__/sasl.cpython-312.pyc index 8961ac100d2d0d8941c2423a6daa2c7b264f1315..b8767e6c31653ccc5aea29a737af62f201217fc6 100644 GIT binary patch delta 1192 zcmZuwOH30{6rI6Ai?6-!6_m10tc09M66pJ@0bN-zd73PK$^L#ehiqg}PD`7aBJtxGj?%el2-v^)1 z%fWZL^W$jeQ{Q#s`pL0dWIrM7N7WWVb7?&LO@akgm~!k9P1M|vTu9`&!a2po#k_^% z@?qCBsTc-scfqakph+7vPeHrNDV`o%=sn)soh`FeE8VCY>Tp`uIdKiEZxxJRGr+w%|%OGq8nBL+h>jbH!aAekphd>ptK9X_E9~Vvc`29$A!{z zw3UvkhL+aj$W}yJ!RpKRkzg)fKF=ThPa<1Vt*b^NW!j>Z*7dOsonWCo09jZ>B$PW{ z@lA*pb6`1Vb#_TlUw3!>#D%jRwy5dD6G>Xn2Iak5aY(0KTZHyZstC@GX^cITYoMtQ z@*NL3%7&`<5QWWFzm6A^2Y_mOS7$jA+fUmums7HSt*&s{Oc~B9^Gj(&PXhoB4u>rz z%uELML1XCI%N|FnpzOQIL7_nbOOL|;&0c?r$T0tV1wggh0bU!LZSsZFHy NR`_{8*By4|`U9B77Cis} delta 1219 zcmZuwOHUI~6rS6eVTMPoyr%>rh42_OwB@0Ypr!^e0MXvVd%p9XdmgtxhZirqKe^p` z9Q!6-ei`+yyYC@aB_fYdD{_%vsMO;!xK}RVIqoh$%Y)C$Yr?K?mJ176mgBN4FU~qj zK1Y*?&sBvS&4{c?2Q)dm8ckpsq(dip_cX()xr0;~3JncV!H(DoD(PlqB%y1)R8HAC zHX})$3Z@YqryP~ZM^{xbAJ->wKFfd$06Ywchxdg9mO)R%@KNTVIZ?}u8F88qNyFKL z4Q*7jZ>!orY9)1l)JlxZ__b7Yd^BZF`pF<4KvQInS1xXrRX!P87+Wq|Daw?cn9tuV zuX!@JFtp#k|<7U#L1ijFjQzaEyRTfqS zXR^43%qq34mSyF!jJimx&tGtyh4xauGthpgmMqI9ul1Vld+yYE1xbl*El%+N7q-~4L0dJ5k9jK!8 zi<+R&2$c=0{NH&G?wLj4A+lZnxe)3+G&%CEp`Sg0hQ?T-v+aX2@~rVZ<9_g7veOtW zyz!4Vr1miWf!fyX1+E&vc|#3godgI1TmZNNFa&T7;3hzr!77I;`}UtN~=D%-WK>l9rZA=x1<@yl(0cfcXu|%ocF~ diff --git a/src/duckhuntbot.py b/src/duckhuntbot.py index 4dca482..659877d 100644 --- a/src/duckhuntbot.py +++ b/src/duckhuntbot.py @@ -32,7 +32,8 @@ class DuckHuntBot: self.sasl_handler = SASLHandler(self, config) - self.admins = [admin.lower() for admin in self.config.get('admins', ['colby'])] + admins_list = self.get_config('admins', ['colby']) or ['colby'] + self.admins = [admin.lower() for admin in admins_list] # Initialize shop manager shop_file = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'shop.json') @@ -103,24 +104,26 @@ class DuckHuntBot: for attempt in range(max_retries): try: ssl_context = None - if self.config.get('ssl', False): + if self.get_config('connection.ssl', False): ssl_context = ssl.create_default_context() # Add SSL context configuration for better compatibility ssl_context.check_hostname = False ssl_context.verify_mode = ssl.CERT_NONE - self.logger.info(f"Attempting to connect to {self.config['server']}:{self.config['port']} (attempt {attempt + 1}/{max_retries})") + server = self.get_config('connection.server', 'irc.libera.chat') + port = self.get_config('connection.port', 6667) + self.logger.info(f"Attempting to connect to {server}:{port} (attempt {attempt + 1}/{max_retries})") self.reader, self.writer = await asyncio.wait_for( asyncio.open_connection( - self.config['server'], - self.config['port'], + server, + port, ssl=ssl_context ), timeout=self.get_config('connection.timeout', 30) or 30.0 # Connection timeout from config ) - self.logger.info(f"โœ… Successfully connected to {self.config['server']}:{self.config['port']}") + self.logger.info(f"โœ… Successfully connected to {server}:{port}") return except asyncio.TimeoutError: @@ -183,11 +186,13 @@ class DuckHuntBot: async def register_user(self): """Register user with IRC server""" - if self.config.get('password'): - self.send_raw(f"PASS {self.config['password']}") + password = self.get_config('connection.password') + if password and password != "your_iline_password_here": + self.send_raw(f"PASS {password}") - self.send_raw(f"NICK {self.config['nick']}") - self.send_raw(f"USER {self.config['nick']} 0 * :{self.config['nick']}") + nick = self.get_config('connection.nick', 'DuckHunt') + self.send_raw(f"NICK {nick}") + self.send_raw(f"USER {nick} 0 * :{nick}") async def handle_message(self, prefix, command, params, trailing): """Handle incoming IRC messages with comprehensive error handling""" @@ -227,7 +232,8 @@ class DuckHuntBot: self.logger.info("Successfully registered with IRC server") # Join channels - for channel in self.config.get('channels', []): + channels = self.get_config('connection.channels', []) or [] + for channel in channels: try: self.send_raw(f"JOIN {channel}") self.channels_joined.add(channel) diff --git a/src/sasl.py b/src/sasl.py index 19cf36c..36a5f88 100644 --- a/src/sasl.py +++ b/src/sasl.py @@ -14,10 +14,10 @@ class SASLHandler: def __init__(self, bot, config): self.bot = bot self.logger = setup_logger("SASL") - sasl_config = config.get("sasl", {}) - self.enabled = sasl_config.get("enabled", False) - self.username = sasl_config.get("username", config.get("nick", "")) - self.password = sasl_config.get("password", "") + # Use bot's get_config method for nested config access + self.enabled = bot.get_config("sasl.enabled", False) + self.username = bot.get_config("sasl.username", bot.get_config("connection.nick", "")) + self.password = bot.get_config("sasl.password", "") self.authenticated = False self.cap_negotiating = False diff --git a/test_config.py b/test_config.py new file mode 100644 index 0000000..912fdd9 --- /dev/null +++ b/test_config.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import json +import os + +def test_config(): + """Test the config structure and values""" + config_path = 'config.json' + + if not os.path.exists(config_path): + print("โŒ Config file not found") + return + + with open(config_path, 'r') as f: + config = json.load(f) + + print("๐Ÿงช Testing configuration structure...") + + # Test connection settings + connection = config.get('connection', {}) + print(f"๐ŸŒ Server: {connection.get('server')}") + print(f"๐Ÿ”Œ Port: {connection.get('port')}") + print(f"๐Ÿค– Nick: {connection.get('nick')}") + print(f"๐Ÿ”’ SSL: {connection.get('ssl')}") + + # Check if password is set (not default) + password = connection.get('password') + password_set = password and password != "your_iline_password_here" + print(f"๐Ÿ”‘ Password configured: {'Yes' if password_set else 'No (default placeholder)'}") + + # Test SASL settings + sasl = config.get('sasl', {}) + print(f"๐Ÿ” SASL enabled: {sasl.get('enabled')}") + print(f"๐Ÿ‘ค SASL username: {sasl.get('username')}") + + # Check if SASL password is set (not default) + sasl_password = sasl.get('password') + sasl_password_set = sasl_password and sasl_password != "duckhunt//789//" + print(f"๐Ÿ—๏ธ SASL password configured: {'Yes' if sasl_password_set else 'No (default placeholder)'}") + + # Test channels + channels = connection.get('channels', []) + print(f"๐Ÿ“บ Channels to join: {channels}") + + print("\nโœ… Configuration structure looks good!") + + if not password_set: + print("โš ๏ธ Warning: Server password is still set to placeholder value") + print(" Update 'connection.password' if your server requires authentication") + + if sasl.get('enabled') and not sasl_password_set: + print("โš ๏ธ Warning: SASL is enabled but password is still placeholder") + print(" Update 'sasl.password' with your actual NickServ password") + +if __name__ == "__main__": + test_config() \ No newline at end of file