Skip to content

Commit cf2283f

Browse files
authored
Make ClientBuilder directly accept boxed handler types (#3431)
Rather than having the `ClientBuilder` accept `impl Into<Arc<H>> where H: HandlerTrait`, directly accept the corresponding `Arc<dyn HandlerTrait>`. This allows accepting non-concrete handler types (f.e. if constructed by a function that returns `Arc<dyn HandlerTrait>` already) and fixes type inference failures when passing an `Arc<H>` rather than `H`. This affects the setters for `EventHandler`, `RawEventHandler`, `Framework`, and `VoiceGatewayManager`. `Framework` is in a bit of a weird spot because it is only put in an `Arc` after `Framework::init` has been called, so a `&mut` can be taken to it for that call, so this PR has `ClientBuilder` accept `Box<dyn Framework>` for it. Most of the commit diff is related to fixing examples.
1 parent 088cf9a commit cf2283f

File tree

17 files changed

+99
-64
lines changed

17 files changed

+99
-64
lines changed

README.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,37 +43,45 @@ docs.
4343
A basic ping-pong bot looks like:
4444

4545
```rust
46-
use std::env;
46+
use std::sync::Arc;
4747

4848
use serenity::async_trait;
49-
use serenity::model::channel::Message;
49+
use serenity::gateway::client::FullEvent;
5050
use serenity::prelude::*;
5151

5252
struct Handler;
5353

5454
#[async_trait]
5555
impl EventHandler for Handler {
56-
async fn message(&self, ctx: &Context, msg: &Message) {
57-
if msg.content == "!ping" {
58-
if let Err(why) = msg.channel_id.say(&ctx.http, "Pong!").await {
59-
println!("Error sending message: {why:?}");
60-
}
56+
async fn dispatch(&self, ctx: &Context, event: &FullEvent) {
57+
match event {
58+
FullEvent::Message {
59+
new_message, ..
60+
} => {
61+
if new_message.content == "!ping" {
62+
if let Err(why) = new_message.channel_id.say(&ctx.http, "Pong!").await {
63+
println!("Error sending message: {why:?}");
64+
}
65+
}
66+
},
67+
_ => {},
6168
}
6269
}
6370
}
6471

6572
#[tokio::main]
6673
async fn main() {
6774
// Login with a bot token from the environment
68-
let token = env::var("DISCORD_TOKEN").expect("Expected a token in the environment");
75+
let token =
76+
Token::from_env("DISCORD_TOKEN").expect("Expected a valid token in the environment");
6977
// Set gateway intents, which decides what events the bot will be notified about
7078
let intents = GatewayIntents::GUILD_MESSAGES
7179
| GatewayIntents::DIRECT_MESSAGES
7280
| GatewayIntents::MESSAGE_CONTENT;
7381

7482
// Create a new instance of the Client, logging in as a bot.
75-
let mut client = Client::builder(&token, intents)
76-
.event_handler(Handler)
83+
let mut client = Client::builder(token, intents)
84+
.event_handler(Arc::new(Handler))
7785
.await
7886
.expect("Error creating client");
7987

examples/e01_basic_ping_bot/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use serenity::async_trait;
24
use serenity::gateway::client::FullEvent;
35
use serenity::prelude::*;
@@ -54,8 +56,10 @@ async fn main() {
5456

5557
// Create a new instance of the Client, logging in as a bot. This will automatically prepend
5658
// your bot token with "Bot ", which is a requirement by Discord for bot users.
57-
let mut client =
58-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
59+
let mut client = Client::builder(token, intents)
60+
.event_handler(Arc::new(Handler))
61+
.await
62+
.expect("Err creating client");
5963

6064
// Finally, start a single shard, and start listening to events.
6165
//

examples/e02_transparent_guild_sharding/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![expect(clippy::collapsible_if)]
2+
use std::sync::Arc;
3+
24
use serenity::async_trait;
35
use serenity::gateway::client::FullEvent;
46
use serenity::prelude::*;
@@ -51,8 +53,10 @@ async fn main() {
5153
let intents = GatewayIntents::GUILD_MESSAGES
5254
| GatewayIntents::DIRECT_MESSAGES
5355
| GatewayIntents::MESSAGE_CONTENT;
54-
let mut client =
55-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
56+
let mut client = Client::builder(token, intents)
57+
.event_handler(Arc::new(Handler))
58+
.await
59+
.expect("Err creating client");
5660

5761
// The total number of shards to use. The "current shard number" of a shard - that is, the
5862
// shard it is assigned to - is indexed at 0, while the total shard count is indexed at 1.

examples/e03_struct_utilities/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use serenity::async_trait;
24
use serenity::builder::CreateMessage;
35
use serenity::gateway::client::FullEvent;
@@ -47,8 +49,10 @@ async fn main() {
4749
let intents = GatewayIntents::GUILD_MESSAGES
4850
| GatewayIntents::DIRECT_MESSAGES
4951
| GatewayIntents::MESSAGE_CONTENT;
50-
let mut client =
51-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
52+
let mut client = Client::builder(token, intents)
53+
.event_handler(Arc::new(Handler))
54+
.await
55+
.expect("Err creating client");
5256

5357
if let Err(why) = client.start().await {
5458
println!("Client error: {why:?}");

examples/e04_message_builder/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use serenity::async_trait;
24
use serenity::gateway::client::FullEvent;
35
use serenity::prelude::*;
@@ -56,8 +58,10 @@ async fn main() {
5658
let intents = GatewayIntents::GUILD_MESSAGES
5759
| GatewayIntents::DIRECT_MESSAGES
5860
| GatewayIntents::MESSAGE_CONTENT;
59-
let mut client =
60-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
61+
let mut client = Client::builder(token, intents)
62+
.event_handler(Arc::new(Handler))
63+
.await
64+
.expect("Err creating client");
6165

6266
if let Err(why) = client.start().await {
6367
println!("Client error: {why:?}");

examples/e05_sample_bot_structure/src/main.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod commands;
22

33
use std::env;
4+
use std::sync::Arc;
45

56
use serenity::async_trait;
67
use serenity::builder::{CreateInteractionResponse, CreateInteractionResponseMessage};
@@ -94,7 +95,7 @@ async fn main() {
9495

9596
// Build our client.
9697
let mut client = Client::builder(token, GatewayIntents::empty())
97-
.event_handler(Handler)
98+
.event_handler(Arc::new(Handler))
9899
.await
99100
.expect("Error creating client");
100101

examples/e06_env_logging/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use serenity::async_trait;
24
use serenity::prelude::*;
35
use tracing::{debug, error, info, instrument};
@@ -50,8 +52,10 @@ async fn main() {
5052
| GatewayIntents::DIRECT_MESSAGES
5153
| GatewayIntents::MESSAGE_CONTENT;
5254

53-
let mut client =
54-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
55+
let mut client = Client::builder(token, intents)
56+
.event_handler(Arc::new(Handler))
57+
.await
58+
.expect("Err creating client");
5559

5660
if let Err(why) = client.start().await {
5761
error!("Client error: {:?}", why);

examples/e07_shard_manager/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
//! Note that it may take a minute or more for a latency to be recorded or to update, depending on
2020
//! how often Discord tells the client to send a heartbeat.
2121
#![expect(clippy::collapsible_if)]
22+
use std::sync::Arc;
2223
use std::time::Duration;
2324

2425
use serenity::async_trait;
@@ -54,8 +55,10 @@ async fn main() {
5455
let intents = GatewayIntents::GUILD_MESSAGES
5556
| GatewayIntents::DIRECT_MESSAGES
5657
| GatewayIntents::MESSAGE_CONTENT;
57-
let mut client =
58-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
58+
let mut client = Client::builder(token, intents)
59+
.event_handler(Arc::new(Handler))
60+
.await
61+
.expect("Err creating client");
5962

6063
// Here we get a DashMap of of the shards' status that we move into a new thread.
6164
let runners = client.shard_manager.runners.clone();

examples/e08_create_message_builder/src/main.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::sync::Arc;
2+
13
use serenity::async_trait;
24
use serenity::builder::{CreateAttachment, CreateEmbed, CreateEmbedFooter, CreateMessage};
35
use serenity::gateway::client::FullEvent;
@@ -62,8 +64,10 @@ async fn main() {
6264
let intents = GatewayIntents::GUILD_MESSAGES
6365
| GatewayIntents::DIRECT_MESSAGES
6466
| GatewayIntents::MESSAGE_CONTENT;
65-
let mut client =
66-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
67+
let mut client = Client::builder(token, intents)
68+
.event_handler(Arc::new(Handler))
69+
.await
70+
.expect("Err creating client");
6771

6872
if let Err(why) = client.start().await {
6973
println!("Client error: {why:?}");

examples/e09_collectors/src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! This example will showcase the beauty of collectors. They allow to await messages or reactions
22
//! from a user in the middle of a control flow, one being a command.
33
use std::collections::HashSet;
4+
use std::sync::Arc;
45
use std::time::Duration;
56

67
use serenity::async_trait;
@@ -163,8 +164,10 @@ async fn main() {
163164
| GatewayIntents::MESSAGE_CONTENT
164165
| GatewayIntents::GUILD_MESSAGE_REACTIONS;
165166

166-
let mut client =
167-
Client::builder(token, intents).event_handler(Handler).await.expect("Err creating client");
167+
let mut client = Client::builder(token, intents)
168+
.event_handler(Arc::new(Handler))
169+
.await
170+
.expect("Err creating client");
168171

169172
if let Err(why) = client.start().await {
170173
println!("Client error: {why:?}");

0 commit comments

Comments
 (0)