Skip to content

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

use rustycord::Client;

let client = Client::new();

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

let current_user = client.get_current_user().await?;
println!("Current user: {:#?}", 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

client.delete_message("channel_id", "message_id").await?;

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

client.delete_channel("channel_id").await?;

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

let dm_channel = client.create_dm("user_id").await?;
println!("DM Channel ID: {}", dm_channel.id);

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

client.delete_guild_role("guild_id", "role_id").await?;

Add Role to Member

client.add_guild_member_role("guild_id", "user_id", "role_id").await?;

Remove Role from Member

client.remove_guild_member_role("guild_id", "user_id", "role_id").await?;

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

let client = ClientBuilder::new()
    .proxy("http://proxy.example.com:8080")
    .build();

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.