diff --git a/README.md b/README.md index fda32fd..dbe4556 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/discord_bot.py b/discord_bot.py index 1a0733b..15dfd09 100644 --- a/discord_bot.py +++ b/discord_bot.py @@ -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 @@ -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 @@ -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. @@ -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}") diff --git a/requirements.txt b/requirements.txt index 8813026..e8fa802 100644 --- a/requirements.txt +++ b/requirements.txt @@ -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. diff --git a/run_bot.sh b/run_bot.sh new file mode 100644 index 0000000..d9aa5c1 --- /dev/null +++ b/run_bot.sh @@ -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."