Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,30 @@ This Discord bot engages in voice conversations with users. It joins a voice cha
```

## Running the Bot
Once the dependencies are installed and the configuration is set, you can run the bot using:
```bash
python discord_bot.py
```
Ensure your terminal is in the same directory as `discord_bot.py`.

There are two main ways to run the bot:

**1. Using the startup script (recommended for Linux/macOS):**

Make the script executable (only needs to be done once):
```bash
chmod +x run_bot.sh
```
Then run the script:
```bash
./run_bot.sh
```
Alternatively, you can run it directly with bash:
```bash
bash run_bot.sh
```

**2. Directly with Python:**

You can also run the bot directly using Python (ensure you are in the project's root directory and use `python3` as specified in the `run_bot.sh` script):
```bash
python3 discord_bot.py
```

## Usage / Commands
- **`!join`**: The bot will join the voice channel you are currently in and initiate "conversation mode." It will listen for your speech for 10 seconds, process it, get a response from Character AI, speak it back, and then listen to you again.
Expand Down
28 changes: 19 additions & 9 deletions discord_bot.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import os
os.system("pip install discord.py")
os.system("pip install SpeechRecognition")
import discord
from discord.ext import commands
import asyncio
Expand All @@ -11,7 +14,7 @@
CAI_TOKEN = "8041baf6512c863ffe65eea49a071e4f0287f149" # Your Character AI client token
CAI_CHARACTER_ID = "vOPdHXLGkA_7tamhZGhijCC29nk8W1xphYbm81qfSH4" # The ID of the Character AI character you want to interact with
CAI_VOICE_ID = "453c0918-82d5-40ab-b42c-517a322ee5e5" # The specific voice ID for the Character AI character's speech
BOT_TOKEN = input("BOT TOKEN: ")
BOT_TOKEN = input("BOT TOKEN:")
# --- Global Variables ---
cai_client = None # Global client for PyCharacterAI, initialized in on_ready()
conversation_mode_status = {} # Dictionary to manage conversation mode state per guild
Expand Down Expand Up @@ -235,11 +238,14 @@ async def start_recording(
# Start listening for audio.
# `voice_client.listen()` takes the sink and an `after` callback.
# The `after` callback (`finished_recording_callback`) is triggered when `voice_client.stop_listening()` is called.
# We pass `guild`, `user_to_record`, and `text_channel_for_responses` as `*cb_args` (callback arguments)
# so that `finished_recording_callback` receives the necessary context for its operations.
voice_client.listen(sink_instance,
after=lambda sink_obj, *cb_args: bot.loop.create_task(finished_recording_callback(sink_obj, *cb_args)),
guild, user_to_record, text_channel_for_responses)
# We pass `guild`, `user_to_record`, and `text_channel_for_responses` as positional arguments to listen(),
# which then passes them to the `after` callback.
voice_client.listen(sink_instance,
guild,
user_to_record,
text_channel_for_responses,
after=lambda sink_param, guild_param, user_param, channel_param: bot.loop.create_task(finished_recording_callback(sink_param, guild_param, user_param, channel_param))
)

await text_channel_for_responses.send(f"Listening to {user_to_record.mention} for 10 seconds...")
await asyncio.sleep(10) # Record audio for a fixed duration of 10 seconds.
Expand Down Expand Up @@ -403,9 +409,13 @@ async def record(ctx: commands.Context):
sink_instance = discord.sinks.WaveSink() # Create a new sink for this recording session.
try:
# Pass guild, author, and channel to the callback via listen's *args for context.
ctx.voice_client.listen(sink_instance,
after=lambda sink, *args: bot.loop.create_task(finished_recording_callback(sink, *args)),
ctx.guild, ctx.author, ctx.channel)
# Corrected: Positional arguments must come before keyword arguments.
ctx.voice_client.listen(sink_instance,
ctx.guild,
ctx.author,
ctx.channel,
after=lambda sink_param, guild_param, user_param, channel_param: bot.loop.create_task(finished_recording_callback(sink_param, guild_param, user_param, channel_param))
)
await asyncio.sleep(10) # Record for 10 seconds.
except Exception as e:
print(f"Error starting manual recording listener: {e}")
Expand Down
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
discord.py
SpeechRecognition
websockets==15.0.1
# PyCharacterAI is a local module, not from PyPI, but its dependencies like curl-cffi might be needed if installing from scratch.
# Pocketsphinx was installed as a dependency of SpeechRecognition for offline STT capabilities.
# SoundDevice was installed as a dependency of Pocketsphinx.
Expand Down
12 changes: 12 additions & 0 deletions run_bot.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
echo "Starting the Discord Character AI Bot..."

# It's good practice to ensure the bot runs from the script's directory
# in case it relies on relative paths for configs or assets in the future.
# SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
# cd "$SCRIPT_DIR"

# Assuming discord_bot.py is in the same directory as run_bot.sh
python3 discord_bot.py

echo "Discord Character AI Bot has stopped."