stream-bot/README.md
Joey Yakimowich-Payne c43cb5e0ce Controller configs
2025-05-16 09:22:03 -06:00

515 lines
No EOL
19 KiB
Markdown

# Twitch Chat Interaction Bot
A simple Python bot that connects to Twitch chat and performs actions based on user commands.
## Features
- Easy connection to Twitch chat via IRC
- Command-based interaction system
- Simple API for adding custom commands
- Example commands included
- Queue system for asynchronous command processing
- Robust authentication handling with token management
- Advanced features (optional):
- Interactive polls and voting system
- Timer system for scheduled messages
- Points system for viewers
- Sound effects (Windows only)
- Game control (optional):
- Control games via Twitch chat
- Direct control mode for immediate actions
- Voting mode for democratic game control
- User stats tracking for game commands
- Streamer override mode for exclusive control
- Multiple input methods:
- Keyboard and mouse simulation
- Virtual Xbox controller emulation (Windows only)
## Requirements
- Python 3.6+
- Socket library (included in Python standard library)
- Requests library (`pip install requests`) for Twitch authentication
- For keyboard/mouse control: pynput library (`pip install pynput`)
- For Xbox controller emulation: vgamepad library (`pip install vgamepad`) - Windows only
- For queue functionality: huey library (`pip install huey`)
## Setup
1. Clone this repository:
```
git clone https://github.com/yourusername/stream-interact.git
cd stream-interact
```
2. Install dependencies:
```
pip install -r requirements.txt
```
3. Set up your Twitch API credentials:
- Go to [https://dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps)
- Create a new application (or use an existing one)
- Generate a client secret
- Note your client ID and client secret
- Run the setup script to generate authentication tokens:
```
python scripts/setup_twitch_auth.py
```
- For detailed authentication setup instructions, see [Authentication Setup Guide](docs/twitch_auth_setup.md)
4. Set your environment variables:
```
# On Windows
set TWITCH_USERNAME=your_bot_username
set TWITCH_CLIENT_ID=your_client_id
set TWITCH_CLIENT_SECRET=your_client_secret
set TWITCH_CHANNEL=your_channel_name
set TWITCH_ADMIN_USERS=bot_username,mod_username
# On Linux/Mac
export TWITCH_USERNAME=your_bot_username
export TWITCH_CLIENT_ID=your_client_id
export TWITCH_CLIENT_SECRET=your_client_secret
export TWITCH_CHANNEL=your_channel_name
export TWITCH_ADMIN_USERS=bot_username,mod_username
```
Alternatively, you can edit the `main.py` file and set these values directly.
5. Configuration file:
You can also create a `default_config.json` file in the root directory with the following structure:
```json
{
"admin_users": ["bot_username", "mod_username"],
"cooldown": 2.0,
"game_mode": "direct",
"input_type": "keyboard",
"use_queue": false,
"token_cache_file": "data/cache/token_cache.json",
"features": {
"advanced": false,
"game_control": false
}
}
```
6. Run the bot:
```
# Basic functionality
python main.py
# With advanced features
python main.py --advanced
# With game control (keyboard & mouse, direct mode)
python main.py --game-control
# With game control (Xbox controller, direct mode)
python main.py --game-control --input-type controller
# With game control (voting mode)
python main.py --game-control --game-mode vote
# With game control (Xbox controller, voting mode)
python main.py --game-control --game-mode vote --input-type controller
# With both advanced features and game control
python main.py --advanced --game-control
# Customize cooldown time (in seconds)
python main.py --game-control --cooldown 5.0
# With queue system for processing commands
python main.py --use-queue
# With additional admin users
python main.py --admin-users bot_username,mod_username
# With custom config file
python main.py --config my_config.json
```
## Admin Users
Admin users have the same permissions as the channel owner. This is useful if:
- You have a separate bot account that will be used on your channel
- You want to give moderators special privileges
- You're running the bot for another streamer
Admin users can:
- Stop the bot with !stop
- Check token status with !token
- Take control of the game with !takeover
- Start and end voting with !startvote and !endvote
- End polls with !endpoll
- Give points to users with !give
Admin users can be configured in three ways (in order of priority):
1. Command line: `--admin-users bot_username,mod_username`
2. Environment variable: `TWITCH_ADMIN_USERS=bot_username,mod_username`
3. Config file: `"admin_users": ["bot_username", "mod_username"]` in default_config.json
## Basic Commands
The bot comes with several example commands:
- `!hello` - The bot will say hello back to the user
- `!dice [sides]` - Roll a dice with the specified number of sides (default: 6)
- `!echo [message]` - The bot will echo back the provided message
- `!8ball` - Ask the Magic 8-Ball a question and get a random answer
## Advanced Features
When running with the `--advanced` flag, these additional commands become available:
### Voting System
- `!poll "Question" "Option1" "Option2" ["Option3"...]` - Start a new poll
- `!vote <number>` - Vote in the active poll
- `!endpoll` - End the active poll and show results
### Timer System
- `!timer <seconds> <message>` - Set a timer to send a message after specified seconds
### Points System
- `!points [@user]` - Check points for yourself or another user
- `!give <user> <points>` - Give points to a user (channel owner only)
### Sound Effects (Windows only)
- `!sound <sound_name>` - Play a sound effect
- Add .wav files to the `sounds` directory to use this feature
### Queue System
For high-volume chats or intensive commands, you can use the queue system:
```
# Start the bot with queue enabled
python main.py --use-queue
# Start a consumer in a separate terminal to process tasks
python -m huey.bin.huey_consumer src.queue.server.huey
```
For detailed documentation on the queue system, see [Queue System Guide](docs/queue.md)
## Game Control
The game control feature allows Twitch chat to control a game via keyboard/mouse inputs or a virtual Xbox controller.
### General Commands
- `!gamehelp` - Show available game control commands
- `!gamestats [@user]` - Check game control stats for a user
### Keyboard & Mouse Mode
When using keyboard & mouse mode (`--input-type keyboard`), the following commands are available:
- `!up` - Press W key (move up/forward)
- `!down` - Press S key (move down/backward)
- `!left` - Press A key (move left)
- `!right` - Press D key (move right)
- `!jump` - Press Space bar (jump)
- `!attack` - Press left mouse button (attack)
- `!interact` - Press E key (interact)
- `!inventory` - Press I key (inventory)
- `!skill1` - Press 1 key (skill 1)
- `!skill2` - Press 2 key (skill 2)
- `!skill3` - Press 3 key (skill 3)
- `!ultimate` - Press R key (ultimate ability)
### Xbox Controller Mode (Windows only)
When using controller mode (`--input-type controller`), the following commands are available:
- Movement:
- `!up` - Move left stick up (forward)
- `!down` - Move left stick down (backward)
- `!left` - Move left stick left
- `!right` - Move left stick right
- Camera:
- `!look_up` - Move right stick up
- `!look_down` - Move right stick down
- `!look_left` - Move right stick left
- `!look_right` - Move right stick right
- Action Buttons:
- `!jump` - Press A button
- `!action` - Press B button
- `!interact` - Press X button
- `!menu` - Press Y button
- Shoulder Buttons & Triggers:
- `!block` - Press left shoulder (LB)
- `!attack` - Press right shoulder (RB)
- `!aim` - Press left trigger (LT)
- `!shoot` - Press right trigger (RT)
- D-pad:
- `!item1` - Press D-pad up
- `!item2` - Press D-pad right
- `!item3` - Press D-pad down
- `!item4` - Press D-pad left
- Menu Buttons:
- `!start` - Press start button
- `!select` - Press select/back button
### Direct Mode
In direct mode, commands are executed immediately when received. Each user has a cooldown between commands to prevent spam.
### Vote Mode
In vote mode, commands are collected through voting:
- `!startvote [seconds]` - Start a vote session (streamer only)
- `!vote <command>` - Vote for a specific command
- `!endvote` - End the current vote session (streamer only)
After the voting period, the command with the most votes is executed.
### Streamer Override Mode
The streamer override feature allows the channel owner to take exclusive control of the game when needed:
- `!takeover` - Channel owner takes exclusive control (only their commands will work)
- `!givecontrol` - Return control to the chat (viewers can use commands again)
When streamer override is active:
- Only the channel owner's commands will be executed
- The channel owner bypasses all cooldowns that apply to viewers
- If there's an active vote, it will be cancelled
- Viewers cannot start new votes until the streamer gives control back
#### Controller Redirection
When using controller mode (`--input-type controller`), the streamer override feature includes physical controller redirection:
- When `!takeover` is used, the streamer's physical controller inputs are automatically redirected to the virtual controller
- This allows the streamer to directly control the game using their own controller during takeover
- The redirection ends automatically when `!givecontrol` is used
- Requires a physical controller to be connected to the PC running the bot
Requirements for controller redirection:
- pygame library (`pip install pygame`)
- A physical controller connected to the PC
- Windows operating system (due to vgamepad dependency)
This feature is particularly useful when the streamer needs to:
- Quickly navigate a challenging section of a game
- Demonstrate something specific to viewers
- Override the chat's decisions temporarily
### Customizing Game Controls
You can customize the key/button mappings in the code:
- For keyboard/mouse controls, edit the keyboard commands in `game_control.py`
- For Xbox controller, edit the controller commands in `game_control.py`
## Adding Custom Commands
You can easily add your own commands by creating a handler function and registering it with the bot:
```python
def my_custom_command(username, args, bot):
# Do something interesting
bot.send_message(f"@{username}, your command was processed!")
# In main.py
bot.register_command("mycommand", my_custom_command)
```
Users can then trigger this command by typing `!mycommand` in the Twitch chat.
## Advanced Usage
You can extend the TwitchBot class to add more functionality, such as:
- User permission levels
- Cooldowns for commands
- Custom events (subscriptions, follows, etc.)
- Integration with other APIs
### Queue System
For high-traffic channels or resource-intensive commands, the queue system allows you to process messages and commands asynchronously:
- Moves command execution to a background process
- Prevents the bot from getting overwhelmed during high activity
- Allows for distributed processing across multiple machines
- Provides statistics and monitoring capabilities
See [Queue System Documentation](docs/queue.md) for detailed setup and usage instructions.
## Authentication
The bot uses Twitch's Client Credentials Grant Flow for authentication:
1. Create a Twitch application at [dev.twitch.tv/console/apps](https://dev.twitch.tv/console/apps)
2. Get your Client ID and generate a Client Secret
3. Set these as environment variables:
```
TWITCH_CLIENT_ID=your_client_id
TWITCH_CLIENT_SECRET=your_client_secret
```
4. Run the authentication setup script:
```
python scripts/setup_twitch_auth.py
```
This will guide you through the authentication process and store your tokens.
For detailed authentication setup instructions, see [Authentication Setup Guide](docs/twitch_auth_setup.md)
### Token Management
The bot uses a token cache file to minimize API requests. When you run the bot:
1. It checks for a cached token in `twitch_token_cache.json`
2. If a valid cached token exists, it uses that token
3. If no valid token is found, it requests a new one from Twitch
4. The new token is saved to the cache file for future use
The token cache can be configured with these options:
```
# Use a custom token cache location
python main.py --token-cache /path/to/your/cache.json
# Check token status while the bot is running (channel owner only)
!token
```
## Game Control Configuration (`data/config/game_controls.json`)
The `data/config/game_controls.json` file allows you to define custom game control schemes for different games. This enables the bot to adapt its input commands (keyboard or controller) based on the game currently being played.
### Structure
The JSON file has the following main structure:
```json
{
"default_game": "YourDefaultGameName",
"games": {
"YourDefaultGameName": {
// Configuration for YourDefaultGameName
},
"AnotherGameName": {
// Configuration for AnotherGameName
}
// ... more game configurations
}
}
```
- `"default_game"`: (String) Specifies the name of the game configuration that will be loaded by default when the bot starts. The command names from this game's configuration will be registered at startup.
- `"games"`: (Object) A dictionary where each key is a unique game name (e.g., "Apex Legends", "Minecraft", "MyCustomGame"). Each game name maps to an object containing its specific control configuration.
### Game Configuration Structure
Each game entry within the `"games"` object has the following structure:
```json
"GameName": {
"description": "A brief description of this game or control scheme.",
"keyboard": {
// Keyboard control mappings for GameName
},
"controller": {
// Controller control mappings for GameName
}
}
```
- `"description"`: (String) A human-readable description for this game configuration (e.g., "Apex Legends - Standard Controls", "Dark Souls - Fat Roll Setup"). This description is shown in `!gamehelp`.
- `"keyboard"`: (Object) Contains mappings for keyboard-based commands.
- `"controller"`: (Object) Contains mappings for virtual gamepad-based commands.
### Control Mapping Structure (Keyboard & Controller)
Inside both the `"keyboard"` and `"controller"` objects, you define individual control commands. The **keys** in these objects are the **actual command strings** users will type in Twitch chat (without the `!` prefix). For example, if you define `"w": {...}`, users will type `!w`.
Each command mapping has the following structure:
```json
"command_user_types": {
"action_type": "type_of_action_to_perform",
"params": {
// Parameters specific to the action_type
},
"description": "What this command does in this specific game (e.g., 'Move Forward', 'Jump', 'Primary Attack')."
}
```
- `"command_user_types"`: (String) The command string the user types (e.g., `"w"`, `"space"`, `"mouse_left"`, `"a_button"`, `"ls_up"`).
- `"action_type"`: (String) Defines the kind of input to simulate. This corresponds to methods available in `KeyboardController` or `VirtualController`.
- **Common Keyboard `action_type` values:**
- `"press_key"`: Simulates pressing a keyboard key.
- `params`: `{ "key": "key_name" }` (e.g., `"w"`, `"space"`, `"shift"`, `"ctrl"`, `"1"`)
- `"press_mouse_button"`: Simulates a mouse button press.
- `params`: `{ "button": "button_name" }` (e.g., `"left"`, `"right"`, `"middle"`)
- **Common Controller `action_type` values:**
- `"press_button"`: Simulates pressing a gamepad button.
- `params`: `{ "button_name": "name_of_button" }` (e.g., `"a"`, `"b"`, `"x"`, `"y"`, `"left_shoulder"`, `"right_shoulder"`, `"left_thumb"`, `"right_thumb"`, `"start"`, `"back"`)
- `"press_trigger"`: Simulates pressing a gamepad trigger.
- `params`: `{ "trigger_name": "left_or_right" }` (e.g., `"left"`, `"right"`)
- `"move_left_stick"` / `"move_right_stick"`: Simulates moving an analog stick.
- `params`: `{ "direction": "up/down/left/right" }` (e.g., `"up"`)
- *Note: For more precise stick control, the `VirtualController` might support direct x/y values in the future, which would require different params.*
- `"press_dpad"`: Simulates pressing a D-Pad direction.
- `params`: `{ "direction": "up/down/left/right" }`
- `"params"`: (Object) A dictionary of parameters required by the specified `action_type`. The keys and values within `params` depend directly on what the underlying controller methods (`KeyboardController` or `VirtualController` methods) expect.
- An optional `"duration"` (float, in seconds) can often be included in `params` to specify how long a key/button should be held. If omitted, a short default (e.g., 0.1 seconds) is typically used.
- `"description"`: (String) This is crucial. It explains what the command does in the context of *this specific game*. This description is shown to users via the `!gamehelp` command.
### Example Snippet
```json
{
"default_game": "ExampleFPS",
"games": {
"ExampleFPS": {
"description": "Standard FPS Controls",
"keyboard": {
"w": {"action_type": "press_key", "params": {"key": "w"}, "description": "Move Forward"},
"s": {"action_type": "press_key", "params": {"key": "s"}, "description": "Move Backward"},
"mouse_left": {"action_type": "press_mouse_button", "params": {"button": "left"}, "description": "Fire Weapon"}
},
"controller": {
"ls_up": {"action_type": "move_left_stick", "params": {"direction": "up"}, "description": "Move Forward (L-Stick)"},
"rt": {"action_type": "press_trigger", "params": {"trigger_name": "right"}, "description": "Fire Weapon (RT)"},
"a": {"action_type": "press_button", "params": {"button_name": "a"}, "description": "Jump (A Button)"}
}
},
"RacingSim": {
"description": "Basic Racing Controls",
"keyboard": {
"w": {"action_type": "press_key", "params": {"key": "w", "duration": 0.5}, "description": "Accelerate"},
"s": {"action_type": "press_key", "params": {"key": "s", "duration": 0.3}, "description": "Brake/Reverse"}
},
"controller": {
"rt": {"action_type": "press_trigger", "params": {"trigger_name": "right"}, "description": "Accelerate (RT)"},
"lt": {"action_type": "press_trigger", "params": {"trigger_name": "left"}, "description": "Brake/Reverse (LT)"}
}
}
}
}
```
### Activating a Game Configuration
- At startup, the commands defined in the `keyboard` and `controller` sections of the `default_game` are registered. Their descriptions (from the JSON) are used.
- An admin can change the active game configuration at any time using the `!setgame <GameName>` command (e.g., `!setgame RacingSim`).
- Once the game is switched:
- The `!gamehelp` command will display the controls for the newly activated game.
- When users type a command (e.g., `!w`), the bot will execute the action defined for `"w"` in the *currently active game's* configuration. If `"w"` is not defined for the active game, it will be treated as an unknown command for that game.
This system allows for a highly flexible and game-adaptive control scheme managed entirely through the `game_controls.json` file.
## License
This project is open source and available under the MIT License.