123 lines
4.4 KiB
Rust
123 lines
4.4 KiB
Rust
// src/main.rs
|
|
|
|
// Declare the modules used in this crate
|
|
mod handler;
|
|
mod state;
|
|
mod commands;
|
|
mod lavalink_handler;
|
|
mod utils;
|
|
|
|
// Import necessary types from our modules
|
|
use handler::Handler;
|
|
use state::BotState;
|
|
use lavalink_handler::MyLavalinkEventHandlerRs;
|
|
|
|
// Import necessary types from external crates
|
|
use serenity::client::Client;
|
|
use serenity::prelude::GatewayIntents; // Needed to subscribe to events
|
|
use lavalink_rs::LavalinkClient;
|
|
use tokio::sync::Mutex;
|
|
use tracing::{error, info, instrument};
|
|
use std::sync::Arc; // For shared ownership
|
|
use std::env; // To read environment variables
|
|
|
|
// The entry point of the application
|
|
#[tokio::main]
|
|
#[instrument] // Adds tracing to the main function
|
|
async fn main() {
|
|
// Initialize tracing for logging output
|
|
tracing_subscriber::fmt()
|
|
.with_max_level(tracing::Level::INFO) // Set logging level
|
|
.init();
|
|
|
|
// Load environment variables from .env file
|
|
dotenv::dotenv().ok();
|
|
|
|
// Get credentials from environment variables
|
|
let token = env::var("DISCORD_TOKEN").expect("DISCORD_TOKEN not set");
|
|
let lavalink_host = env::var("LAVALINK_HOST")
|
|
.expect("LAVALINK_HOST not set");
|
|
let lavalink_port = env::var("LAVALINK_PORT")
|
|
.expect("LAVALINK_PORT not set")
|
|
.parse::<u16>()
|
|
.expect("Invalid LAVALINK_PORT");
|
|
let lavalink_password = env::var("LAVALINK_PASSWORD")
|
|
.expect("LAVALINK_PASSWORD not set");
|
|
|
|
// Define the gateway intents needed for the bot
|
|
// GUILDS: To receive guild information for commands and cache
|
|
// GUILD_VOICE_STATES: Crucial for receiving voice state updates
|
|
let intents = GatewayIntents::GUILDS | GatewayIntents::GUILD_VOICE_STATES;
|
|
|
|
// Build the Serenity client. Need the await here because of the async builder.
|
|
let mut serenity_client = Client::builder(&token, intents)
|
|
.await
|
|
.expect("Error creating serenity client");
|
|
|
|
// Clone the Arc<Http> client from Serenity. We need this to be able to send
|
|
// HTTP requests (like sending messages) from places that don't have the full Context,
|
|
// such as the Lavalink event handler.
|
|
let http = serenity_client.cache_and_http.http.clone();
|
|
|
|
// Get the bot's user ID from the cache. This is needed to initialize the Lavalink client.
|
|
let bot_user_id = serenity_client
|
|
.cache_and_http
|
|
.cache
|
|
.current_user_id()
|
|
.await
|
|
.expect("Failed to get bot user ID from cache");
|
|
|
|
// Create the Lavalink client builder
|
|
let mut lavalink_client_builder = LavalinkClient::builder(bot_user_id);
|
|
|
|
// Set Lavalink node details
|
|
lavalink_client_builder
|
|
.set_host(lavalink_host)
|
|
.set_port(lavalink_port)
|
|
.set_password(lavalink_password);
|
|
|
|
// Create and set the custom Lavalink event handler, passing the http client
|
|
let lavalink_event_handler = Arc::new(MyLavalinkEventHandlerRs {
|
|
http: http.clone() // Clone Http again for the lavalink event handler
|
|
});
|
|
lavalink_client_builder.set_event_handler(lavalink_event_handler);
|
|
|
|
// Build the Lavalink client
|
|
let lavalink_client = lavalink_client_builder.build();
|
|
|
|
// Create and store the shared state (BotState)
|
|
let bot_state = Arc::new(Mutex::new(BotState {
|
|
lavalink: lavalink_client.clone(), // Clone lavalink client for the handler struct
|
|
http: http, // Store the Http client clone in the state
|
|
// announcement_channels: Mutex::new(HashMap::new()), // Optional: for announcements
|
|
}));
|
|
|
|
// Set the Serenity event handler, passing the shared state
|
|
serenity_client.event_handler(Handler { state: bot_state });
|
|
|
|
// Spawn the lavalink-rs client's main run task. This task will manage the
|
|
// WebSocket connection to the Lavalink server and process its events.
|
|
let lavalink_task = tokio::spawn(async move {
|
|
info!("Starting lavalink-rs client task...");
|
|
if let Err(why) = lavalink_client.run().await {
|
|
error!("Lavalink client task error: {:?}", why);
|
|
}
|
|
info!("Lavalink client task stopped.");
|
|
});
|
|
|
|
|
|
// Start the Serenity client gateway. This connects the bot to Discord
|
|
// and begins receiving events. This call is blocking until the client stops.
|
|
info!("Starting serenity client gateway...");
|
|
if let Err(why) = serenity_client.start().await {
|
|
error!("Serenity client gateway error: {:?}", why);
|
|
}
|
|
info!("Serenity client gateway stopped.");
|
|
|
|
|
|
// Wait for the lavalink task to finish.
|
|
// In a real bot, this task should ideally never finish unless there's a critical error.
|
|
let _ = lavalink_task.await;
|
|
|
|
info!("Bot shut down.");
|
|
} |