[][src]Struct serenity::client::Client

pub struct Client {
    pub data: Arc<RwLock<ShareMap>>,
    pub shard_manager: Arc<Mutex<ShardManager>>,
    pub threadpool: ThreadPool,
    pub voice_manager: Arc<Mutex<ClientVoiceManager>>,
    pub ws_uri: Arc<Mutex<String>>,
    pub cache_and_http: Arc<CacheAndHttp>,
    // some fields omitted
}

The Client is the way to be able to start sending authenticated requests over the REST API, as well as initializing a WebSocket connection through Shards. Refer to the documentation on using sharding for more information.

Event Handlers

Event handlers can be configured. For example, the event handler EventHandler::message will be dispatched to whenever a Event::MessageCreate is received over the connection.

Note that you do not need to manually handle events, as they are handled internally and then dispatched to your event handlers.

Examples

Creating a Client instance and adding a handler on every message receive, acting as a "ping-pong" bot is simple:

use serenity::prelude::*;
use serenity::model::prelude::*;
use serenity::Client;

struct Handler;

impl EventHandler for Handler {
    fn message(&self, context: Context, msg: Message) {
        if msg.content == "!ping" {
            let _ = msg.channel_id.say(&context, "Pong!");
        }
    }
}

let mut client = Client::new("my token here", Handler).expect("Could not create new client.");

client.start().expect("Could not start client.");

Fields

data: Arc<RwLock<ShareMap>>

A ShareMap which requires types to be Send + Sync. This is a map that can be safely shared across contexts.

The purpose of the data field is to be accessible and persistent across contexts; that is, data can be modified by one context, and will persist through the future and be accessible through other contexts. This is useful for anything that should "live" through the program: counters, database connections, custom user caches, etc.

In the meaning of a context, this data can be accessed through Context::data.

Examples

Create a MessageEventCounter to track the following events:

This example is not tested
// Of note, this imports `typemap`'s `Key` as `TypeMapKey`.
use serenity::prelude::*;
use serenity::model::*;
use std::collections::HashMap;
use std::env;

struct MessageEventCounter;

impl TypeMapKey for MessageEventCounter {
    type Value = HashMap<String, u64>;
}

fn reg<S>(ctx: Context, name: S)
  where S: Into<std::string::String>
{
    let mut data = ctx.data.write();
    let counter = data.get_mut::<MessageEventCounter>().unwrap();
    let entry = counter.entry(name.into()).or_insert(0);
    *entry += 1;
}

struct Handler;

impl EventHandler for Handler {
    fn message(&self, ctx: Context, _: Message) { reg(ctx, "MessageCreate") }
    fn message_delete(&self, ctx: Context, _: ChannelId, _: MessageId) {
        reg(ctx, "MessageDelete") }
    fn message_delete_bulk(&self, ctx: Context, _: ChannelId, _: Vec<MessageId>) {
        reg(ctx, "MessageDeleteBulk") }
    fn message_update(&self, ctx: Context, _: MessageUpdateEvent) {
        reg(ctx, "MessageUpdate") }
}


let mut client = Client::new(&env::var("DISCORD_TOKEN").expect("Could not find token."), Handler)
    .expect("Could not create client.");

{
    let mut data = client.data.write();
    data.insert::<MessageEventCounter>(HashMap::default());
}

client.start().expect("Could not start client.");

Refer to example 05 for an example on using the data field.

shard_manager: Arc<Mutex<ShardManager>>

A HashMap of all shards instantiated by the Client.

The key is the shard ID and the value is the shard itself.

Examples

If you call client.start_shard(3, 5), this HashMap will only ever contain a single key of 3, as that's the only Shard the client is responsible for.

If you call client.start_shards(10), this HashMap will contain keys 0 through 9, one for each shard handled by the client.

Printing the number of shards currently instantiated by the client every 5 seconds:



struct Handler;

impl EventHandler for Handler { }

let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler)?;

let shard_manager = client.shard_manager.clone();

thread::spawn(move || {
    loop {
        println!("Shard count instantiated: {}",
                 shard_manager.lock().shards_instantiated().len());

        thread::sleep(Duration::from_millis(5000));
    }
});

Shutting down all connections after one minute of operation:

use serenity::client::{Client, EventHandler};
use std::time::Duration;
use std::{env, thread};

struct Handler;

impl EventHandler for Handler { }

let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler)?;

// Create a clone of the `Arc` containing the shard manager.
let shard_manager = client.shard_manager.clone();

// Create a thread which will sleep for 60 seconds and then have the
// shard manager shutdown.
thread::spawn(move || {
    thread::sleep(Duration::from_secs(60));

    shard_manager.lock().shutdown_all();

    println!("Shutdown shard manager!");
});

println!("Client shutdown: {:?}", client.start());
threadpool: ThreadPool

The threadpool shared by all shards.

Defaults to 5 threads, which should suffice small bots. Consider increasing this number as your bot grows.

voice_manager: Arc<Mutex<ClientVoiceManager>>

The voice manager for the client.

This is an ergonomic structure for interfacing over shards' voice connections.

ws_uri: Arc<Mutex<String>>

URI that the client's shards will use to connect to the gateway.

This is likely not important for production usage and is, at best, used for debugging.

This is wrapped in an Arc<Mutex<T>> so all shards will have an updated value available.

cache_and_http: Arc<CacheAndHttp>

Implementations

impl Client[src]

pub fn new<H: EventHandler + 'static>(
    token: impl AsRef<str>,
    handler: H
) -> Result<Self>
[src]

Creates a Client for a bot user.

Discord has a requirement of prefixing bot tokens with "Bot ", which this function will automatically do for you if not already included.

Examples

Create a Client, using a token from an environment variable:

struct Handler;

impl EventHandler for Handler {}
use serenity::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let client = Client::new(&token, Handler)?;

pub fn new_with_handlers<H, RH>(
    token: impl AsRef<str>,
    handler: Option<H>,
    raw_handler: Option<RH>
) -> Result<Self> where
    H: EventHandler + 'static,
    RH: RawEventHandler + 'static, 
[src]

👎 Deprecated since 0.8.0:

Replaced by new_with_extras.

Creates a client with an optional Handler. If you pass None, events are never parsed, but they can be received by registering a RawHandler.

pub fn new_with_cache_update_timeout<H>(
    token: impl AsRef<str>,
    handler: H,
    duration: Option<Duration>
) -> Result<Self> where
    H: EventHandler + 'static, 
[src]

👎 Deprecated since 0.8.0:

Replaced by new_with_extras.

Creates a Client for a bot user and sets a cache update timeout. If set to some duration, updating the cache will try to claim a write-lock for given duration and skip received event but also issue a deadlock-warning upon failure. If duration is set to None, updating the cache will try to claim a write-lock until success and potentially deadlock.

pub fn new_with_extras(
    token: impl AsRef<str>,
    f: impl FnOnce(&mut Extras) -> &mut Extras
) -> Result<Self>
[src]

Creates a client with extra configuration.

pub fn with_framework<F: Framework + Send + 'static>(&mut self, f: F)[src]

Sets a framework to be used with the client. All message events will be passed through the framework after being passed to the message event handler.

See the framework module-level documentation for more information on usage.

Examples

Create a simple framework that responds to a ~ping command:

struct Handler;

impl EventHandler for Handler {}

use std::env;

use serenity::framework::StandardFramework;
use serenity::client::{Client, Context};
use serenity::model::channel::Message;
use serenity::framework::standard::{CommandResult, macros::{group, command}};

#[command]
fn ping(ctx: &mut Context, msg: &Message) -> CommandResult {
    msg.channel_id.say(&ctx.http, "Pong!")?;
    Ok(())
}

// Commands must be intermediately handled through groups.
#[group("pingpong")]
#[commands(ping)]
struct PingPong;

let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler)?;
client.with_framework(StandardFramework::new()
    .configure(|c| c.prefix("~"))
    // The macros generate instances of command and group structs, which reside as `static` variables.
    // Hence the uppercase name, and the suffix for distinguishment.
    .group(&PINGPONG_GROUP));

Using your own framework:

This example is not tested
use serenity::Framework;
use serenity::client::Context;
use serenity::model::*;
use tokio_core::reactor::Handle;
use std::collections::HashMap;


struct MyFramework {
    commands: HashMap<String, Box<Fn(Message, Vec<String>)>>,
}

impl Framework for MyFramework {
    fn dispatch(&mut self, _: Context, msg: Message, tokio_handle: &Handle) {
        let args = msg.content.split_whitespace();
        let command = match args.advance() {
            Some(command) => {
                if !command.starts_with('*') { return; }
                command
            },
            None => return,
        };

        let command = match self.commands.get(&command) {
            Some(command) => command, None => return,
        };

        tokio_handle.spawn_fn(move || { (command)(msg, args); Ok() });
    }
}

struct Handler;

impl EventHandler for Handler {}

use serenity::Client;
use std::env;

let mut client = Client::new(&token, Handler).unwrap();
client.with_framework(MyFramework { commands: {
    let mut map = HashMap::new();
    map.insert("ping".to_string(), Box::new(|msg, _| msg.channel_id.say("pong!")));
    map
}});

Refer to the documentation for the framework module for more in-depth information.

pub fn start(&mut self) -> Result<()>[src]

Establish the connection and start listening for events.

This will start receiving events in a loop and start dispatching the events to your registered handlers.

Note that this should be used only for users and for bots which are in less than 2500 guilds. If you have a reason for sharding and/or are in more than 2500 guilds, use one of these depending on your use case:

Refer to the Gateway documentation for more information on effectively using sharding.

Examples

Starting a Client with only 1 shard, out of 1 total:

struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let mut client = Client::new(&token, Handler).unwrap();

if let Err(why) = client.start() {
    println!("Err with client: {:?}", why);
}

pub fn start_autosharded(&mut self) -> Result<()>[src]

Establish the connection(s) and start listening for events.

This will start receiving events in a loop and start dispatching the events to your registered handlers.

This will retrieve an automatically determined number of shards to use from the API - determined by Discord - and then open a number of shards equivalent to that amount.

Refer to the Gateway documentation for more information on effectively using sharding.

Examples

Start as many shards as needed using autosharding:

struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let mut client = Client::new(&token, Handler).unwrap();

if let Err(why) = client.start_autosharded() {
    println!("Err with client: {:?}", why);
}

Errors

Returns a ClientError::Shutdown when all shards have shutdown due to an error.

pub fn start_shard(&mut self, shard: u64, shards: u64) -> Result<()>[src]

Establish a sharded connection and start listening for events.

This will start receiving events and dispatch them to your registered handlers.

This will create a single shard by ID. If using one shard per process, you will need to start other processes with the other shard IDs in some way.

Refer to the Gateway documentation for more information on effectively using sharding.

Examples

Start shard 3 of 5:

struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let mut client = Client::new(&token, Handler).unwrap();

if let Err(why) = client.start_shard(3, 5) {
    println!("Err with client: {:?}", why);
}

Start shard 0 of 1 (you may also be interested in start or start_autosharded):

struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let mut client = Client::new(&env::var("DISCORD_TOKEN")?, Handler)?;

if let Err(why) = client.start_shard(0, 1) {
    println!("Err with client: {:?}", why);
}

Errors

Returns a ClientError::Shutdown when all shards have shutdown due to an error.

pub fn start_shards(&mut self, total_shards: u64) -> Result<()>[src]

Establish sharded connections and start listening for events.

This will start receiving events and dispatch them to your registered handlers.

This will create and handle all shards within this single process. If you only need to start a single shard within the process, or a range of shards, use start_shard or start_shard_range, respectively.

Refer to the Gateway documentation for more information on effectively using sharding.

Examples

Start all of 8 shards:

struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let mut client = Client::new(&token, Handler).unwrap();

if let Err(why) = client.start_shards(8) {
    println!("Err with client: {:?}", why);
}

Errors

Returns a ClientError::Shutdown when all shards have shutdown due to an error.

pub fn start_shard_range(
    &mut self,
    range: [u64; 2],
    total_shards: u64
) -> Result<()>
[src]

Establish a range of sharded connections and start listening for events.

This will start receiving events and dispatch them to your registered handlers.

This will create and handle all shards within a given range within this single process. If you only need to start a single shard within the process, or all shards within the process, use start_shard or start_shards, respectively.

Refer to the Gateway documentation for more information on effectively using sharding.

Examples

For a bot using a total of 10 shards, initialize shards 4 through 7:

struct Handler;

impl EventHandler for Handler {}
use serenity::Client;
use std::env;

let token = env::var("DISCORD_TOKEN").unwrap();
let mut client = Client::new(&token, Handler).unwrap();

let _ = client.start_shard_range([4, 7], 10);
struct Handler;

impl EventHandler for Handler {}
use serenity::client::Client;
use std::env;

let token = env::var("DISCORD_TOKEN")?;
let mut client = Client::new(&token, Handler).unwrap();

if let Err(why) = client.start_shard_range([4, 7], 10) {
    println!("Err with client: {:?}", why);
}

Errors

Returns a ClientError::Shutdown when all shards have shutdown due to an error.

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Same<T> for T

type Output = T

Should always be Self

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> UnsafeAny for T where
    T: Any

impl<V, T> VZip<V> for T where
    V: MultiLane<T>,