diff options
| author | Zeyla Hellyer <[email protected]> | 2017-05-23 10:15:26 -0700 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2017-05-23 10:15:26 -0700 |
| commit | 8c0aeacadb93d3b56fb98beb882eaef1f79cd652 (patch) | |
| tree | 7c1d26addbf15537c6f69a6ac9623276002b155a /src/client | |
| parent | Fix {Invite,RichInvite}::url tests (diff) | |
| download | serenity-8c0aeacadb93d3b56fb98beb882eaef1f79cd652.tar.xz serenity-8c0aeacadb93d3b56fb98beb882eaef1f79cd652.zip | |
Add more examples and improve some others
Add examples to some functions, and update some of the old examples to
use the `?` operator instead of unwrapping.
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/context.rs | 166 | ||||
| -rw-r--r-- | src/client/mod.rs | 313 |
2 files changed, 453 insertions, 26 deletions
diff --git a/src/client/context.rs b/src/client/context.rs index 22216b1..9cb76b7 100644 --- a/src/client/context.rs +++ b/src/client/context.rs @@ -74,8 +74,16 @@ impl Context { /// /// Change the current user's username: /// - /// ```rust,ignore - /// context.edit_profile(|p| p.username("Hakase")); + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// # + /// # client.on_message(|ctx, msg| { + /// # if msg.content == "!changename" { + /// ctx.edit_profile(|p| p.username("Hakase")); + /// # } + /// # }); /// ``` #[cfg(feature="builder")] pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> { @@ -105,7 +113,22 @@ impl Context { } /// Sets the current user as being [`Online`]. This maintains the current - /// game and `afk` setting. + /// game. + /// + /// # Examples + /// + /// Set the current user to being online on the shard: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// client.on_message(|ctx, msg| { + /// if msg.content == "!online" { + /// ctx.online(); + /// } + /// }); + /// ``` /// /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online pub fn online(&self) { @@ -113,7 +136,22 @@ impl Context { } /// Sets the current user as being [`Idle`]. This maintains the current - /// game and `afk` setting. + /// game. + /// + /// # Examples + /// + /// Set the current user to being idle on the shard: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// client.on_message(|ctx, msg| { + /// if msg.content == "!idle" { + /// ctx.idle(); + /// } + /// }); + /// ``` /// /// [`Idle`]: ../model/enum.OnlineStatus.html#variant.Idle pub fn idle(&self) { @@ -121,7 +159,22 @@ impl Context { } /// Sets the current user as being [`DoNotDisturb`]. This maintains the - /// current game and `afk` setting. + /// current game. + /// + /// # Examples + /// + /// Set the current user to being Do Not Disturb on the shard: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// client.on_message(|ctx, msg| { + /// if msg.content == "!dnd" { + /// ctx.dnd(); + /// } + /// }); + /// ``` /// /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb pub fn dnd(&self) { @@ -129,18 +182,47 @@ impl Context { } /// Sets the current user as being [`Invisible`]. This maintains the current - /// game and `afk` setting. + /// game. /// + /// # Examples + /// + /// Set the current user to being invisible on the shard when an + /// [`Event::Ready`] is received: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// client.on_ready(|ctx, _| { + /// ctx.invisible(); + /// }); + /// ``` + /// + /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready /// [`Invisible`]: ../model/enum.OnlineStatus.html#variant.Invisible pub fn invisible(&self) { self.shard.lock().unwrap().set_status(OnlineStatus::Invisible); } - /// "Resets" the current user's presence, by setting the game to `None`, - /// the online status to [`Online`], and `afk` to `false`. + /// "Resets" the current user's presence, by setting the game to `None` and + /// the online status to [`Online`]. /// /// Use [`set_presence`] for fine-grained control over individual details. /// + /// # Examples + /// + /// Reset the presence when an [`Event::Resumed`] is received: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// client.on_resume(|ctx, _| { + /// ctx.reset_presence(); + /// }); + /// ``` + /// + /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online /// [`set_presence`]: #method.set_presence pub fn reset_presence(&self) { @@ -149,19 +231,29 @@ impl Context { .set_presence(None, OnlineStatus::Online, false) } - /// Sets the current game, defaulting to an online status of [`Online`], and - /// setting `afk` to `false`. + /// Sets the current game, defaulting to an online status of [`Online`]. /// /// # Examples /// - /// Set the current user as playing "Heroes of the Storm": + /// Create a command named `~setgame` that accepts a name of a game to be + /// playing: /// - /// ```rust,ignore + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// # /// use serenity::model::Game; /// - /// // assuming you are in a context + /// client.on_message(|ctx, msg| { + /// let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>(); + /// + /// if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" { + /// return; + /// } /// - /// context.set_game(Game::playing("Heroes of the Storm")); + /// ctx.set_game(Game::playing(*unsafe { args.get_unchecked(1) })); + /// }); /// ``` /// /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online @@ -180,6 +272,21 @@ impl Context { /// /// **Note**: Maximum length is 128. /// + /// # Examples + /// + /// When an [`Event::Ready`] is received, set the game name to `"test"`: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// # + /// client.on_ready(|ctx, _| { + /// ctx.set_game_name("test"); + /// }); + /// ``` + /// + /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready /// [`GameType`]: ../model/enum.GameType.html /// [`Online`]: ../model/enum.OnlineStatus.html#variant.Online /// [`OnlineStatus`]: ../model/enum.OnlineStatus.html @@ -202,29 +309,38 @@ impl Context { /// /// # Examples /// - /// Setting the current user as having no game, being [`Idle`], - /// and setting `afk` to `true`: + /// Setting the current user as having no game and being [`Idle`]: /// - /// ```rust,ignore + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// # + /// # client.on_ready(|ctx, _| { + /// # /// use serenity::model::OnlineStatus; /// - /// // assuming you are in a context - /// - /// context.set_game(None, OnlineStatus::Idle, true); + /// ctx.set_presence(None, OnlineStatus::Idle, false); + /// # }); /// ``` /// - /// Setting the current user as playing "Heroes of the Storm", being - /// [`DoNotDisturb`], and setting `afk` to `false`: + /// Setting the current user as playing `"Heroes of the Storm"`, while being + /// [`DoNotDisturb`]: /// /// ```rust,ignore + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// # + /// # client.on_ready(|ctx, _| { + /// # /// use serenity::model::{Game, OnlineStatus}; /// - /// // assuming you are in a context - /// /// let game = Game::playing("Heroes of the Storm"); /// let status = OnlineStatus::DoNotDisturb; /// - /// context.set_game(Some(game), status, false); + /// context.set_presence(Some(game), status, false); + /// # }); /// ``` /// /// [`DoNotDisturb`]: ../model/enum.OnlineStatus.html#variant.DoNotDisturb diff --git a/src/client/mod.rs b/src/client/mod.rs index 1ba555a..bdaa2aa 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -105,9 +105,61 @@ pub struct Client { /// In the meaning of a context, this data can be accessed through /// [`Context::data`]. /// + /// # Examples + /// + /// Create a `MessageEventCounter` to track the following events: + /// + /// - [`Event::MessageCreate`] + /// - [`Event::MessageDelete`] + /// - [`Event::MessageDeleteBulk`] + /// - [`Event::MessageUpdate`] + /// + /// ```rust,ignore + /// extern crate serenity; + /// extern crate typemap; + /// + /// use serenity::Client; + /// use std::collections::HashMap; + /// use std::env; + /// use typemap::Key; + /// + /// struct MessageEventCounter; + /// + /// impl Key for MessageEventCounter { + /// type Value = HashMap<String, u64>; + /// } + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN").unwrap()); + /// + /// { + /// let mut data = client.data.lock().unwrap(); + /// data.insert::<MessageEventCounter>(HashMap::default()); + /// } + /// + /// macro_rules! reg { + /// ($ctx:ident $name:expr) => { + /// { + /// let mut data = $ctx.data.lock().unwrap(); + /// let counter = data.get_mut::<MessageEventCounter>().unwrap(); + /// let entry = counter.entry($name).or_insert(0); + /// *entry += 1; + /// } + /// }; + /// } + /// + /// client.on_message(|ctx, _| reg!(ctx "MessageCreate")); + /// client.on_message_delete(|ctx, _| reg!(ctx "MessageDelete")); + /// client.on_message_delete_bulk(|ctx, _| reg!(ctx "MessageDeleteBulk")); + /// client.on_message_update(|ctx, _| reg!(ctx "MessageUpdate")); + /// ``` + /// /// Refer to [example 05] for an example on using the `data` field. /// /// [`Context::data`]: struct.Context.html#method.data + /// [`Event::MessageCreate`]: ../model/event/enum.Event.html#variant.MessageCreate + /// [`Event::MessageDelete`]: ../model/event/enum.Event.html#variant.MessageDelete + /// [`Event::MessageDeleteBulk`]: ../model/event/enum.Event.html#variant.MessageDeleteBulk + /// [`Event::MessageUpdate`]: ../model/event/enum.Event.html#variant.MessageUpdate /// [example 05]: https://github.com/zeyla/serenity/tree/master/examples/05_command_framework pub data: Arc<Mutex<ShareMap>>, /// A vector of all active shards that have received their [`Event::Ready`] @@ -137,6 +189,27 @@ impl Client { /// /// 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: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let token = env::var("DISCORD_TOKEN")?; + /// let client = Client::login(&token); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` pub fn login(bot_token: &str) -> Self { let token = if bot_token.starts_with("Bot ") { bot_token.to_owned() @@ -154,6 +227,32 @@ impl Client { /// See the [framework module-level documentation][framework docs] for more /// information on usage. /// + /// # Examples + /// + /// Create a simple framework that responds to a `~ping` command: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// client.with_framework(|f| f + /// .configure(|c| c.prefix("~")) + /// .command("ping", |c| c.exec_str("Pong!"))); + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// + /// Refer to the documentation for the `framework` module for more in-depth + /// information. + /// /// [`on_message`]: #method.on_message /// [framework docs]: ../framework/index.html #[cfg(feature="framework")] @@ -174,6 +273,30 @@ impl Client { /// Refer to the [Gateway documentation][gateway docs] for more information /// on effectively using sharding. /// + /// # Examples + /// + /// Starting a Client with only 1 shard, out of 1 total: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::client::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start() { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// /// [gateway docs]: gateway/index.html#sharding pub fn start(&mut self) -> Result<()> { self.start_connection(None, http::get_gateway()?.url) @@ -191,6 +314,30 @@ impl Client { /// Refer to the [Gateway documentation][gateway docs] for more information /// on effectively using sharding. /// + /// # Examples + /// + /// Start as many shards as needed using autosharding: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start_autosharded() { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// /// [gateway docs]: gateway/index.html#sharding pub fn start_autosharded(&mut self) -> Result<()> { let mut res = http::get_bot_gateway()?; @@ -216,6 +363,55 @@ impl Client { /// Refer to the [Gateway documentation][gateway docs] for more information /// on effectively using sharding. /// + /// # Examples + /// + /// Start shard 3 of 5: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start_shard(3, 5) { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// + /// Start shard 0 of 1 (you may also be interested in [`start`] or + /// [`start_autosharded`]): + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start_shard(0, 1) { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// + /// [`start`]: #method.start + /// [`start_autosharded`]: #method.start_autosharded /// [gateway docs]: gateway/index.html#sharding pub fn start_shard(&mut self, shard: u64, shards: u64) -> Result<()> { self.start_connection(Some([shard, shard, shards]), http::get_gateway()?.url) @@ -233,8 +429,32 @@ impl Client { /// Refer to the [Gateway documentation][gateway docs] for more information /// on effectively using sharding. /// + /// # Examples + /// + /// Start all of 8 shards: + /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start_shards(8) { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// /// [`start_shard`]: #method.start_shard - /// [`start_shard_range`]: #method.start_shards + /// [`start_shard_range`]: #method.start_shard_range /// [Gateway docs]: gateway/index.html#sharding pub fn start_shards(&mut self, total_shards: u64) -> Result<()> { self.start_connection(Some([0, total_shards - 1, total_shards]), http::get_gateway()?.url) @@ -267,6 +487,26 @@ impl Client { /// let _ = client.start_shard_range([4, 7], 10); /// ``` /// + /// ```rust,no_run + /// # use std::error::Error; + /// # + /// # fn try_main() -> Result<(), Box<Error>> { + /// use serenity::Client; + /// use std::env; + /// + /// let mut client = Client::login(&env::var("DISCORD_TOKEN")?); + /// + /// if let Err(why) = client.start_shard_range([4, 7], 10) { + /// println!("Err with client: {:?}", why); + /// } + /// # Ok(()) + /// # } + /// # + /// # fn main() { + /// # try_main().unwrap(); + /// # } + /// ``` + /// /// [`start_shard`]: #method.start_shard /// [`start_shards`]: #method.start_shards /// [Gateway docs]: gateway/index.html#sharding @@ -276,6 +516,26 @@ impl Client { /// Attaches a handler for when a [`ChannelCreate`] is received. /// + /// # Examples + /// + /// If the channel is a guild channel, send `"first"` to the channel when + /// one is created: + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// use serenity::model::Channel; + /// + /// client.on_channel_create(|ctx, channel| { + /// if let Channel::Guild(ch) = channel { + /// if let Err(why) = ch.read().unwrap().say("first") { + /// println!("Err sending first message: {:?}", why); + /// } + /// } + /// }); + /// ``` + /// /// [`ChannelCreate`]: ../model/event/enum.Event.html#variant.ChannelCreate pub fn on_channel_create<F>(&mut self, handler: F) where F: Fn(Context, Channel) + Send + Sync + 'static { @@ -286,6 +546,34 @@ impl Client { /// Attaches a handler for when a [`ChannelDelete`] is received. /// + /// # Examples + /// + /// If the channel is a guild channel, send the name of the channel to the + /// guild's default channel. + /// + /// ```rust,no_run + /// # use serenity::Client; + /// # + /// # let mut client = Client::login(""); + /// use serenity::model::{Channel, ChannelId}; + /// + /// client.on_channel_delete(|ctx, channel| { + /// if let Channel::Guild(channel) = channel { + /// let (content, default_channel_id) = { + /// let reader = channel.read().unwrap(); + /// let content = format!("A channel named '{}' was deleted.", reader.name); + /// let id = ChannelId(reader.guild_id.0); + /// + /// (content, id) + /// }; + /// + /// if let Err(why) = default_channel_id.say(&content) { + /// println!("Err sending message to default channel: {:?}", why); + /// } + /// } + /// }); + /// ``` + /// /// [`ChannelDelete`]: ../model/event/enum.Event.html#variant.ChannelDelete pub fn on_channel_delete<F>(&mut self, handler: F) where F: Fn(Context, Channel) + Send + Sync + 'static { @@ -1127,6 +1415,29 @@ fn login(token: String) -> Client { /// - The second part of the token is at least 6 characters long; /// - The token does not contain any whitespace prior to or after the token. /// +/// # Examples +/// +/// Validate that a token is valid and that a number of invalid tokens are +/// actually invalid: +/// +/// ```rust,no_run +/// use serenity::client::validate_token; +/// +/// // ensure a valid token is in fact valid: +/// assert!(validate_token("Mjg4NzYwMjQxMzYzODc3ODg4.C_ikow.j3VupLBuE1QWZng3TMGH0z_UAwg").is_ok()); +/// +/// // "cat" isn't a valid token: +/// assert!(validate_token("cat").is_err()); +/// +/// // tokens must have three parts, separated by periods (this is still +/// // actually an invalid token): +/// assert!(validate_token("aaa.abcdefgh.bbb").is_ok()); +/// +/// // the second part must be _at least_ 6 characters long: +/// assert!(validate_token("a.abcdef.b").is_ok()); +/// assert!(validate_token("a.abcde.b").is_err()); +/// ``` +/// /// # Errors /// /// Returns a [`ClientError::InvalidToken`] when one of the above checks fail. |