Client API Reference¶
Complete reference for the rustycord Client API.
Overview¶
The Client
struct is the core HTTP client for interacting with the Discord REST API. It handles authentication, rate limiting, and provides methods for all Discord API endpoints.
Client Structure¶
use rustycord::client::Client;
use rustycord::models::{User, Message, Guild, Channel};
pub struct Client {
token: String,
base_url: String,
user_agent: String,
http_client: reqwest::Client,
}
Creating a Client¶
Basic Client¶
Client with Custom Configuration¶
use rustycord::Client;
let client = Client::builder()
.user_agent("MyBot/1.0")
.timeout(std::time::Duration::from_secs(30))
.build();
Authentication¶
Login¶
use rustycord::models::UserResponse;
let mut client = Client::new();
let user_response: UserResponse = client.login(token).await?;
println!("Logged in as: {}", user_response.username);
println!("Bot ID: {}", user_response.id);
Get Current User¶
Message Operations¶
Send Message¶
use rustycord::models::CreateMessage;
// Simple text message
let message = client.send_message("channel_id", "Hello, world!").await?;
// Message with embed
let embed = rustycord::embeds::Embed::new()
.title("Test Embed")
.description("This is a test embed")
.color(0x00ff00);
let create_message = CreateMessage::new()
.content("Message with embed")
.embed(embed);
let message = client.send_message_with_options("channel_id", create_message).await?;
Edit Message¶
let edited_message = client.edit_message(
"channel_id",
"message_id",
"Updated message content"
).await?;
Delete Message¶
Get Message¶
let message = client.get_message("channel_id", "message_id").await?;
println!("Message: {}", message.content);
Get Channel Messages¶
use rustycord::models::GetMessagesOptions;
// Get last 10 messages
let messages = client.get_channel_messages("channel_id", None).await?;
// Get messages with options
let options = GetMessagesOptions::new()
.limit(50)
.before("message_id");
let messages = client.get_channel_messages("channel_id", Some(options)).await?;
Channel Operations¶
Get Channel¶
let channel = client.get_channel("channel_id").await?;
println!("Channel name: {}", channel.name.unwrap_or("Unknown".to_string()));
Create Channel¶
use rustycord::models::{CreateChannel, ChannelType};
let create_channel = CreateChannel::new()
.name("new-channel")
.channel_type(ChannelType::GuildText)
.topic("Channel topic");
let channel = client.create_guild_channel("guild_id", create_channel).await?;
Modify Channel¶
use rustycord::models::ModifyChannel;
let modify_channel = ModifyChannel::new()
.name("updated-channel-name")
.topic("Updated topic");
let channel = client.modify_channel("channel_id", modify_channel).await?;
Delete Channel¶
Guild Operations¶
Get Guild¶
let guild = client.get_guild("guild_id").await?;
println!("Guild name: {}", guild.name);
println!("Member count: {}", guild.member_count.unwrap_or(0));
Get Guild Channels¶
let channels = client.get_guild_channels("guild_id").await?;
for channel in channels {
println!("Channel: {}", channel.name.unwrap_or("Unknown".to_string()));
}
Get Guild Members¶
use rustycord::models::GetGuildMembersOptions;
// Get all members (paginated)
let members = client.get_guild_members("guild_id", None).await?;
// Get members with options
let options = GetGuildMembersOptions::new()
.limit(100)
.after("user_id");
let members = client.get_guild_members("guild_id", Some(options)).await?;
Get Guild Member¶
let member = client.get_guild_member("guild_id", "user_id").await?;
println!("Member: {}", member.user.username);
User Operations¶
Get User¶
let user = client.get_user("user_id").await?;
println!("Username: {}", user.username);
println!("Discriminator: {}", user.discriminator);
Create DM Channel¶
Role Operations¶
Get Guild Roles¶
let roles = client.get_guild_roles("guild_id").await?;
for role in roles {
println!("Role: {} ({})", role.name, role.id);
}
Create Role¶
use rustycord::models::CreateRole;
let create_role = CreateRole::new()
.name("New Role")
.color(0xff0000)
.hoist(true)
.mentionable(true);
let role = client.create_guild_role("guild_id", create_role).await?;
Modify Role¶
use rustycord::models::ModifyRole;
let modify_role = ModifyRole::new()
.name("Updated Role")
.color(0x00ff00);
let role = client.modify_guild_role("guild_id", "role_id", modify_role).await?;
Delete Role¶
Add Role to Member¶
Remove Role from Member¶
Reaction Operations¶
Add Reaction¶
// Unicode emoji
client.create_reaction("channel_id", "message_id", "👍").await?;
// Custom emoji
client.create_reaction("channel_id", "message_id", "custom_emoji:123456789").await?;
Remove Reaction¶
// Remove own reaction
client.delete_own_reaction("channel_id", "message_id", "👍").await?;
// Remove user's reaction
client.delete_user_reaction("channel_id", "message_id", "👍", "user_id").await?;
// Remove all reactions
client.delete_all_reactions("channel_id", "message_id").await?;
Get Reactions¶
let users = client.get_reactions("channel_id", "message_id", "👍").await?;
for user in users {
println!("User who reacted: {}", user.username);
}
Error Handling¶
Client Errors¶
use rustycord::client::{ClientError, ClientResult};
match client.send_message("channel_id", "Hello").await {
Ok(message) => println!("Message sent: {}", message.id),
Err(ClientError::Http(status, body)) => {
eprintln!("HTTP Error {}: {}", status, body);
},
Err(ClientError::RateLimit(retry_after)) => {
eprintln!("Rate limited. Retry after: {}s", retry_after);
},
Err(ClientError::Network(e)) => {
eprintln!("Network error: {}", e);
},
Err(ClientError::Json(e)) => {
eprintln!("JSON parsing error: {}", e);
},
}
Rate Limiting¶
use rustycord::client::RateLimitInfo;
// The client automatically handles rate limits, but you can check status
let rate_limit_info = client.get_rate_limit_info("endpoint").await?;
println!("Remaining requests: {}", rate_limit_info.remaining);
println!("Reset time: {}", rate_limit_info.reset_after);
Advanced Usage¶
Custom HTTP Headers¶
use rustycord::client::ClientBuilder;
let client = ClientBuilder::new()
.header("X-Custom-Header", "value")
.build();
Proxy Support¶
Timeout Configuration¶
let client = ClientBuilder::new()
.timeout(std::time::Duration::from_secs(60))
.connect_timeout(std::time::Duration::from_secs(10))
.build();
Async Patterns¶
Concurrent Requests¶
use futures::future::join_all;
let message_futures = vec![
client.send_message("channel1", "Hello 1"),
client.send_message("channel2", "Hello 2"),
client.send_message("channel3", "Hello 3"),
];
let results = join_all(message_futures).await;
for result in results {
match result {
Ok(message) => println!("Sent message: {}", message.id),
Err(e) => eprintln!("Failed to send message: {}", e),
}
}
Stream Processing¶
use futures::stream::{self, StreamExt};
let channel_ids = vec!["channel1", "channel2", "channel3"];
let client = std::sync::Arc::new(client);
let results: Vec<_> = stream::iter(channel_ids)
.map(|channel_id| {
let client = client.clone();
async move {
client.get_channel_messages(channel_id, None).await
}
})
.buffer_unordered(3) // Process up to 3 requests concurrently
.collect()
.await;
Testing¶
Mock Client¶
#[cfg(test)]
mod tests {
use super::*;
use rustycord::client::MockClient;
#[tokio::test]
async fn test_send_message() {
let mut mock_client = MockClient::new();
mock_client
.expect_send_message()
.with("channel_id", "Hello")
.returning(|_, _| Ok(Message::default()));
let result = mock_client.send_message("channel_id", "Hello").await;
assert!(result.is_ok());
}
}
Examples¶
Bot Initialization with Client¶
use rustycord::{Client, Bot};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let token = std::env::var("DISCORD_TOKEN")?;
// Create and configure client
let mut client = Client::new();
let user_response = client.login(token).await?;
println!("Bot logged in as: {}", user_response.username);
// Use client directly or with Bot
let mut bot = Bot::with_client(client);
bot.start().await?;
Ok(())
}
Message Processing Pipeline¶
async fn process_messages(client: &Client, channel_id: &str) -> Result<(), Box<dyn std::error::Error>> {
// Get recent messages
let messages = client.get_channel_messages(channel_id, None).await?;
// Process each message
for message in messages {
if message.content.contains("spam") {
// Delete spam message
client.delete_message(channel_id, &message.id).await?;
// Send warning to user
let dm_channel = client.create_dm(&message.author.id).await?;
client.send_message(&dm_channel.id, "Please don't spam!").await?;
}
}
Ok(())
}
API Reference Summary¶
Method | Description | Returns |
---|---|---|
Client::new() |
Create new client | Client |
client.login(token) |
Authenticate with Discord | UserResponse |
client.send_message(channel, content) |
Send text message | Message |
client.get_channel(id) |
Get channel info | Channel |
client.get_guild(id) |
Get guild info | Guild |
client.get_user(id) |
Get user info | User |
client.create_reaction(channel, message, emoji) |
Add reaction | () |
client.get_guild_members(guild, options) |
Get guild members | Vec<Member> |
Rate Limits¶
The Discord API has rate limits that the client automatically handles:
- Global Rate Limit: 50 requests per second
- Per-Route Rate Limits: Vary by endpoint
- Per-Guild Rate Limits: Apply to guild-specific operations
The client will automatically retry requests that hit rate limits with appropriate backoff.
Related Documentation¶
- Bot Basics - Using the client with bots
- Message Handler Example - Client usage in handlers
- Error Handling Guide - Handling client errors