Thank you for your interest in contributing to HazeWorldBot! 🌿
We welcome contributions from the community. Whether it's bug fixes, new features, documentation improvements, or performance optimizations, your help is appreciated!
Before contributing, make sure you have:
- Python 3.8+ installed
- Git for version control
- A Discord Bot Token for testing
- Familiarity with discord.py and async/await patterns
-
Fork the Repository
git clone https://github.com/yourusername/HazeWorldBot.git cd HazeWorldBot -
Create a Virtual Environment
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install Dependencies
pip install -r requirements.txt pip install ruff # For code formatting and linting -
Configure Environment
- Copy
.env.exampleto.env - Add your test bot token and configuration
- Update
Config.pywith your test server IDs
- Copy
Always work on a separate branch:
git checkout -b feature/your-feature-name
# or
git checkout -b fix/bug-description- Follow the existing code style and patterns
- Use async/await throughout (no blocking calls)
- Add comments for complex logic
- Update docstrings for new functions/classes
We use ruff for code formatting and linting:
# Format your code
ruff format .
# Check for issues
ruff check .
# Auto-fix issues
ruff check --fix .- Test in a development Discord server
- Ensure all commands work as expected
- Verify permissions and error handling
- Check that no existing functionality breaks
Use clear, descriptive commit messages:
git commit -m "feat: add new leaderboard category"
git commit -m "fix: resolve ticket deletion issue"
git commit -m "docs: update command reference"Commit Message Conventions:
feat:- New featuresfix:- Bug fixesdocs:- Documentation changesrefactor:- Code refactoringperf:- Performance improvementstest:- Adding testschore:- Maintenance tasks
git push origin feature/your-feature-nameThen open a Pull Request on GitHub with:
- Clear title describing the change
- Description of what was changed and why
- Testing steps for reviewers to verify
- PEP 8 compliance (enforced by ruff)
- Type hints for function parameters and return values
- Descriptive variable names (no single-letter variables except in loops)
- Docstrings for all public functions and classes
HazeWorldBot/
├── Cogs/ # Feature modules (one Cog per feature)
├── Utils/ # Shared utilities (Logger, Embeds, Cache)
├── Data/ # JSON data storage (gitignored)
├── Config.py # Central configuration
└── Main.py # Bot entry point
- Always use async/await for I/O operations
- Use
asyncio.gather()for parallel operations - Don't use
time.sleep()- useasyncio.sleep()instead - Handle async context managers properly (
async with)
try:
# Your code
await some_async_operation()
except discord.Forbidden:
Logger.error("Missing permissions")
except Exception as e:
Logger.error(f"Unexpected error: {e}")- Defer interactions for long-running operations
- Use embeds for rich responses
- Implement proper permission checks
- Add autocomplete for slash commands where applicable
- Use views and modals for interactive UI
IMPORTANT: Avoid Code Duplication Between Prefix and Slash Commands
Both prefix commands (!command) and slash commands (/command) should share the same logic through helper functions.
❌ Bad Example (Code Duplication):
@commands.command(name="example")
async def example_prefix(self, ctx: commands.Context):
# Logic here...
embed = discord.Embed(title="Example", description="Result")
await ctx.send(embed=embed)
@app_commands.command(name="example")
async def example_slash(self, interaction: discord.Interaction):
# Same logic duplicated...
embed = discord.Embed(title="Example", description="Result")
await interaction.response.send_message(embed=embed)✅ Good Example (Shared Helper Function):
async def handle_example(self, user: discord.User) -> discord.Embed:
"""Shared logic for both prefix and slash commands."""
# Core logic here...
embed = discord.Embed(title="Example", description="Result")
return embed
@commands.command(name="example")
async def example_prefix(self, ctx: commands.Context):
embed = await self.handle_example(ctx.author)
await ctx.send(embed=embed)
@app_commands.command(name="example")
async def example_slash(self, interaction: discord.Interaction):
embed = await self.handle_example(interaction.user)
await interaction.response.send_message(embed=embed)Benefits:
- Single source of truth for command logic
- Easier to maintain and test
- Consistent behavior across prefix and slash commands
- Reduces bugs from code duplication
See Examples:
TodoList.py:handle_todo_update()andhandle_todo_show()Profile.py: Shared profile generation logicLeaderboard.py: Shared leaderboard generation
- Bug fixes - Always welcome!
- Performance improvements - Especially caching and optimization
- Documentation - README, docstrings, comments
- Error handling - Better error messages and recovery
- New leaderboard categories
- Additional moderation tools
- Enhanced ticket system features
- More Rocket League integrations
- Improved logging and monitoring
- Open an issue to discuss the feature
- Get feedback on the approach
- Ensure it aligns with the bot's purpose
- Commands work with both
/and!prefix - Permissions are correctly enforced
- Error messages are user-friendly
- Embeds display correctly
- No console errors or warnings
- Data is properly saved/loaded
Create a test Discord server with:
- Admin, moderator, and member roles
- Test channels for tickets, welcomes, etc.
- Multiple test users/accounts
- Questions? Open an issue with the
questionlabel - Bug reports? Use the bug report template
- Feature requests? Use the feature request template
- Be respectful and constructive
- Help others learn and improve
- Focus on what's best for the community
- Accept constructive criticism gracefully
By contributing, you agree that your contributions will be licensed under the same MIT License that covers the project.
Thank you for contributing to HazeWorldBot! 🌿💖