aboutsummaryrefslogtreecommitdiff
path: root/src/client
diff options
context:
space:
mode:
authorZeyla Hellyer <[email protected]>2017-05-23 10:15:26 -0700
committerZeyla Hellyer <[email protected]>2017-05-23 10:15:26 -0700
commit8c0aeacadb93d3b56fb98beb882eaef1f79cd652 (patch)
tree7c1d26addbf15537c6f69a6ac9623276002b155a /src/client
parentFix {Invite,RichInvite}::url tests (diff)
downloadserenity-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.rs166
-rw-r--r--src/client/mod.rs313
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.