rustycord 0.1.5

A fast, lightweight, and feature-rich Discord bot library written in Rust.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
# 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

```rust
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
```rust
use rustycord::Client;

let client = Client::new();
```

### Client with Custom Configuration
```rust
use rustycord::Client;

let client = Client::builder()
    .user_agent("MyBot/1.0")
    .timeout(std::time::Duration::from_secs(30))
    .build();
```

## Authentication

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

## Message Operations

### Send Message
```rust
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
```rust
let edited_message = client.edit_message(
    "channel_id",
    "message_id", 
    "Updated message content"
).await?;
```

### Delete Message
```rust
client.delete_message("channel_id", "message_id").await?;
```

### Get Message
```rust
let message = client.get_message("channel_id", "message_id").await?;
println!("Message: {}", message.content);
```

### Get Channel Messages
```rust
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
```rust
let channel = client.get_channel("channel_id").await?;
println!("Channel name: {}", channel.name.unwrap_or("Unknown".to_string()));
```

### Create Channel
```rust
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
```rust
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
```rust
client.delete_channel("channel_id").await?;
```

## Guild Operations

### Get Guild
```rust
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
```rust
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
```rust
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
```rust
let member = client.get_guild_member("guild_id", "user_id").await?;
println!("Member: {}", member.user.username);
```

## User Operations

### Get User
```rust
let user = client.get_user("user_id").await?;
println!("Username: {}", user.username);
println!("Discriminator: {}", user.discriminator);
```

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

## Role Operations

### Get Guild Roles
```rust
let roles = client.get_guild_roles("guild_id").await?;
for role in roles {
    println!("Role: {} ({})", role.name, role.id);
}
```

### Create Role
```rust
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
```rust
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
```rust
client.delete_guild_role("guild_id", "role_id").await?;
```

### Add Role to Member
```rust
client.add_guild_member_role("guild_id", "user_id", "role_id").await?;
```

### Remove Role from Member
```rust
client.remove_guild_member_role("guild_id", "user_id", "role_id").await?;
```

## Reaction Operations

### Add Reaction
```rust
// 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
```rust
// 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
```rust
let users = client.get_reactions("channel_id", "message_id", "👍").await?;
for user in users {
    println!("User who reacted: {}", user.username);
}
```

## Error Handling

### Client Errors
```rust
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
```rust
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
```rust
use rustycord::client::ClientBuilder;

let client = ClientBuilder::new()
    .header("X-Custom-Header", "value")
    .build();
```

### Proxy Support
```rust
let client = ClientBuilder::new()
    .proxy("http://proxy.example.com:8080")
    .build();
```

### Timeout Configuration
```rust
let client = ClientBuilder::new()
    .timeout(std::time::Duration::from_secs(60))
    .connect_timeout(std::time::Duration::from_secs(10))
    .build();
```

## Async Patterns

### Concurrent Requests
```rust
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
```rust
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
```rust
#[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
```rust
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
```rust
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]../user-guide/bot-basics.md - Using the client with bots
- [Message Handler Example]../examples/message-handler.md - Client usage in handlers
- [Error Handling Guide]../user-guide/error-handling.md - Handling client errors