aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build.rs2
-rw-r--r--definitions/structs/bot_application.yml2
-rw-r--r--definitions/structs/current_user.yml2
-rw-r--r--examples/01_basic_ping_bot/Cargo.toml7
-rw-r--r--examples/01_basic_ping_bot/src/main.rs (renamed from examples/01_basic_ping_bot.rs)0
-rw-r--r--examples/02_transparent_guild_sharding/Cargo.toml7
-rw-r--r--examples/02_transparent_guild_sharding/src/main.rs (renamed from examples/02_transparent_guild_sharding.rs)0
-rw-r--r--examples/03_struct_utilities/Cargo.toml7
-rw-r--r--examples/03_struct_utilities/src/main.rs (renamed from examples/03_struct_utilities.rs)18
-rw-r--r--examples/04_message_builder/Cargo.toml7
-rw-r--r--examples/04_message_builder/src/main.rs (renamed from examples/04_message_builder.rs)0
-rw-r--r--examples/05_user_login/Cargo.toml7
-rw-r--r--examples/05_user_login/src/main.rs (renamed from examples/05_user_login.rs)0
-rw-r--r--examples/06_command_framework/Cargo.toml7
-rw-r--r--examples/06_command_framework/src/main.rs (renamed from examples/06_command_framework.rs)18
-rw-r--r--examples/07_voice/Cargo.toml7
-rw-r--r--examples/07_voice/src/main.rs (renamed from examples/07_voice.rs)29
-rw-r--r--src/client/context.rs48
-rw-r--r--src/client/gateway/prep.rs21
-rw-r--r--src/client/gateway/shard.rs10
-rw-r--r--src/client/mod.rs2
-rw-r--r--src/client/rest/mod.rs8
-rw-r--r--src/constants.rs177
-rw-r--r--src/error.rs17
-rw-r--r--src/ext/cache/mod.rs150
-rw-r--r--src/ext/framework/command.rs15
-rw-r--r--src/ext/framework/mod.rs32
-rw-r--r--src/ext/voice/audio.rs2
-rw-r--r--src/ext/voice/connection.rs18
-rw-r--r--src/ext/voice/threading.rs8
-rw-r--r--src/internal/ws_impl.rs25
-rw-r--r--src/lib.rs2
-rw-r--r--src/model/channel.rs13
-rw-r--r--src/model/event.rs149
-rw-r--r--src/model/gateway.rs4
-rw-r--r--src/model/guild.rs16
-rw-r--r--src/model/user.rs8
-rw-r--r--src/model/utils.rs21
-rw-r--r--src/model/voice.rs91
-rw-r--r--src/utils/builder/create_embed.rs36
-rw-r--r--src/utils/builder/mod.rs1
-rw-r--r--src/utils/macros.rs11
-rw-r--r--src/utils/mod.rs54
43 files changed, 389 insertions, 670 deletions
diff --git a/build.rs b/build.rs
index de4cbe0..20871d2 100644
--- a/build.rs
+++ b/build.rs
@@ -296,7 +296,7 @@ impl {0} {{
pub fn decode(value: Value) -> Result<{0}> {{
let mut map = try!(into_map(value));
- missing!(map, {0} {{", name);
+ Ok({0} {{", name);
let decoding = doc["decode"].as_bool().unwrap_or(true);
diff --git a/definitions/structs/bot_application.yml b/definitions/structs/bot_application.yml
index 2eb7a66..a1da049 100644
--- a/definitions/structs/bot_application.yml
+++ b/definitions/structs/bot_application.yml
@@ -15,7 +15,7 @@ fields:
description: "Whether or not this is a bot."
type: bool
- name: discriminator
- custom: parse_discriminator
+ custom: decode_discriminator
description: "The discriminator assigned to the user's username. While
discriminators are not unique, the username#discriminator combination is."
type: u16
diff --git a/definitions/structs/current_user.yml b/definitions/structs/current_user.yml
index 1d9c3f2..948a828 100644
--- a/definitions/structs/current_user.yml
+++ b/definitions/structs/current_user.yml
@@ -11,7 +11,7 @@ fields:
default: 'false'
type: bool
- name: discriminator
- custom: parse_discriminator
+ custom: decode_discriminator
type: u16
- name: email
optional: true
diff --git a/examples/01_basic_ping_bot/Cargo.toml b/examples/01_basic_ping_bot/Cargo.toml
new file mode 100644
index 0000000..603ee6b
--- /dev/null
+++ b/examples/01_basic_ping_bot/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "01_basic_ping_bot"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/01_basic_ping_bot.rs b/examples/01_basic_ping_bot/src/main.rs
index 8db4614..8db4614 100644
--- a/examples/01_basic_ping_bot.rs
+++ b/examples/01_basic_ping_bot/src/main.rs
diff --git a/examples/02_transparent_guild_sharding/Cargo.toml b/examples/02_transparent_guild_sharding/Cargo.toml
new file mode 100644
index 0000000..3899f6d
--- /dev/null
+++ b/examples/02_transparent_guild_sharding/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "02_transparent_guild_sharding"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/02_transparent_guild_sharding.rs b/examples/02_transparent_guild_sharding/src/main.rs
index 19b61d0..19b61d0 100644
--- a/examples/02_transparent_guild_sharding.rs
+++ b/examples/02_transparent_guild_sharding/src/main.rs
diff --git a/examples/03_struct_utilities/Cargo.toml b/examples/03_struct_utilities/Cargo.toml
new file mode 100644
index 0000000..8dc013c
--- /dev/null
+++ b/examples/03_struct_utilities/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "03_struct_utilities"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/03_struct_utilities.rs b/examples/03_struct_utilities/src/main.rs
index ea91500..6bf436d 100644
--- a/examples/03_struct_utilities.rs
+++ b/examples/03_struct_utilities/src/main.rs
@@ -1,13 +1,18 @@
-//! Requires the 'methods' feature flag be enabled.
+//! Requires the 'methods' feature flag be enabled in your project's Cargo.toml.
+//!
+//! This can be activated by specifying the feature in the dependency section:
+//!
+//! ```toml
+//! [dependencies.serenity]
+//! git = "https://github.com/zeyla/serenity.rs.git"
+//! features = ["methods"]
+//! ```
extern crate serenity;
-#[cfg(feature = "methods")]
use serenity::Client;
-#[cfg(feature = "methods")]
use std::env;
-#[cfg(feature = "methods")]
fn main() {
// Configure the client with your Discord bot token in the environment.
let token = env::var("DISCORD_TOKEN")
@@ -26,8 +31,3 @@ fn main() {
let _ = client.start();
}
-
-#[cfg(not(feature = "methods"))]
-fn main() {
- println!("The 'methods' feature flag is required for this example.");
-}
diff --git a/examples/04_message_builder/Cargo.toml b/examples/04_message_builder/Cargo.toml
new file mode 100644
index 0000000..cf0108f
--- /dev/null
+++ b/examples/04_message_builder/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "04_message_builder"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/04_message_builder.rs b/examples/04_message_builder/src/main.rs
index 41f390b..41f390b 100644
--- a/examples/04_message_builder.rs
+++ b/examples/04_message_builder/src/main.rs
diff --git a/examples/05_user_login/Cargo.toml b/examples/05_user_login/Cargo.toml
new file mode 100644
index 0000000..0f0a19e
--- /dev/null
+++ b/examples/05_user_login/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "05_user_login"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/05_user_login.rs b/examples/05_user_login/src/main.rs
index bbc9303..bbc9303 100644
--- a/examples/05_user_login.rs
+++ b/examples/05_user_login/src/main.rs
diff --git a/examples/06_command_framework/Cargo.toml b/examples/06_command_framework/Cargo.toml
new file mode 100644
index 0000000..fa93475
--- /dev/null
+++ b/examples/06_command_framework/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "06_command_framework"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/06_command_framework.rs b/examples/06_command_framework/src/main.rs
index 78e4e9e..95d832c 100644
--- a/examples/06_command_framework.rs
+++ b/examples/06_command_framework/src/main.rs
@@ -1,3 +1,13 @@
+//! Requires the 'methods' feature flag be enabled in your project's Cargo.toml.
+//!
+//! This can be activated by specifying the feature in the dependency section:
+//!
+//! ```toml
+//! [dependencies.serenity]
+//! git = "https://github.com/zeyla/serenity.rs.git"
+//! features = ["framework", methods"]
+//! ```
+
#[macro_use]
extern crate serenity;
@@ -56,18 +66,10 @@ fn dog_command(context: &Context, _msg: &Message, _args: Vec<String>) {
}
// `Message::reply` is only compiled if the `methods` feature flag is enabled.
-#[cfg(feature = "methods")]
fn ping_command(_context: &Context, message: &Message, _args: Vec<String>) {
let _ = message.reply("Pong!");
}
-#[cfg(not(feature = "methods"))]
-fn ping_command(context: &Context, message: &Message, _args: Vec<String>) {
- if let Err(why) = context.say(&format!("{}: Pong!", message.author)) {
- println!("Error sending message: {:?}", why);
- }
-}
-
fn owner_check(_context: &Context, message: &Message) -> bool {
// Replace 7 with your ID
message.author.id == 7
diff --git a/examples/07_voice/Cargo.toml b/examples/07_voice/Cargo.toml
new file mode 100644
index 0000000..d17a835
--- /dev/null
+++ b/examples/07_voice/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "07_voice"
+version = "0.1.0"
+authors = ["my name <[email protected]>"]
+
+[dependencies]
+serenity = { git = "https://github.com/zeyla/serenity.rs.git" }
diff --git a/examples/07_voice.rs b/examples/07_voice/src/main.rs
index e685f37..fe02245 100644
--- a/examples/07_voice.rs
+++ b/examples/07_voice/src/main.rs
@@ -1,24 +1,20 @@
-// Requires the feature "voice" be enabled.
+//! Requires the "cache", "methods", and "voice" features be enabled in your
+//! Cargo.toml, like so:
+//!
+//! ```toml
+//! [dependencies.serenity]
+//! version = "*"
+//! features = ["cache", "methods", "voice"]
+//! ```
extern crate serenity;
-#[cfg(feature = "voice")]
use serenity::client::{CACHE, Client, Context};
-#[cfg(feature = "voice")]
use serenity::ext::voice;
-#[cfg(feature = "voice")]
use serenity::model::{ChannelId, Message};
-#[cfg(feature = "voice")]
use serenity::Result as SerenityResult;
-#[cfg(feature = "voice")]
use std::env;
-#[cfg(not(feature = "voice"))]
-fn main() {
- panic!("'extras' and 'voice' must be enabled");
-}
-
-#[cfg(feature = "voice")]
fn main() {
// Configure the client with your Discord bot token in the environment.
let token = env::var("DISCORD_TOKEN")
@@ -45,7 +41,6 @@ fn main() {
let _ = client.start().map_err(|why| println!("Client ended: {:?}", why));
}
-#[cfg(feature = "voice")]
fn deafen(context: &Context, message: &Message, _args: Vec<String>) {
let guild_id = match CACHE.read().unwrap().get_guild_channel(message.channel_id) {
Some(channel) => channel.guild_id,
@@ -76,7 +71,6 @@ fn deafen(context: &Context, message: &Message, _args: Vec<String>) {
}
}
-#[cfg(feature = "voice")]
fn join(context: &Context, message: &Message, args: Vec<String>) {
let connect_to = match args.get(0) {
Some(arg) => match arg.parse::<u64>() {
@@ -109,7 +103,6 @@ fn join(context: &Context, message: &Message, args: Vec<String>) {
check_msg(context.say(&format!("Joined {}", connect_to.mention())));
}
-#[cfg(feature = "voice")]
fn leave(context: &Context, message: &Message, _args: Vec<String>) {
let guild_id = match CACHE.read().unwrap().get_guild_channel(message.channel_id) {
Some(channel) => channel.guild_id,
@@ -132,7 +125,6 @@ fn leave(context: &Context, message: &Message, _args: Vec<String>) {
}
}
-#[cfg(feature = "voice")]
fn mute(context: &Context, message: &Message, _args: Vec<String>) {
let guild_id = match CACHE.read().unwrap().get_guild_channel(message.channel_id) {
Some(channel) => channel.guild_id,
@@ -163,12 +155,10 @@ fn mute(context: &Context, message: &Message, _args: Vec<String>) {
}
}
-#[cfg(feature = "voice")]
fn ping(context: &Context, _message: &Message, _args: Vec<String>) {
check_msg(context.say("Pong!"));
}
-#[cfg(feature = "voice")]
fn play(context: &Context, message: &Message, args: Vec<String>) {
let url = match args.get(0) {
Some(url) => url,
@@ -214,7 +204,6 @@ fn play(context: &Context, message: &Message, args: Vec<String>) {
}
}
-#[cfg(feature = "voice")]
fn undeafen(context: &Context, message: &Message, _args: Vec<String>) {
let guild_id = match CACHE.read().unwrap().get_guild_channel(message.channel_id) {
Some(channel) => channel.guild_id,
@@ -234,7 +223,6 @@ fn undeafen(context: &Context, message: &Message, _args: Vec<String>) {
}
}
-#[cfg(feature = "voice")]
fn unmute(context: &Context, message: &Message, _args: Vec<String>) {
let guild_id = match CACHE.read().unwrap().get_guild_channel(message.channel_id) {
Some(channel) => channel.guild_id,
@@ -255,6 +243,7 @@ fn unmute(context: &Context, message: &Message, _args: Vec<String>) {
}
/// Checks that a message successfully sent; if not, then logs why to stdout.
+#[cfg(feature = "voice")]
fn check_msg(result: SerenityResult<Message>) {
if let Err(why) = result {
println!("Error sending message: {:?}", why);
diff --git a/src/client/context.rs b/src/client/context.rs
index 678d362..d648888 100644
--- a/src/client/context.rs
+++ b/src/client/context.rs
@@ -1,5 +1,6 @@
use serde_json::builder::ObjectBuilder;
use std::collections::HashMap;
+use std::fmt::Write as FmtWrite;
use std::io::Read;
use std::sync::{Arc, Mutex};
use super::gateway::Shard;
@@ -127,9 +128,7 @@ impl Context {
return Err(Error::Client(ClientError::InvalidOperationAsBot));
}
- let code = utils::parse_invite(invite);
-
- rest::accept_invite(code)
+ rest::accept_invite(utils::parse_invite(invite))
}
/// Mark a [`Channel`] as being read up to a certain [`Message`].
@@ -481,7 +480,13 @@ impl Context {
where F: FnOnce(EditRole) -> EditRole, G: Into<GuildId> {
let id = guild_id.into().0;
- // The API only allows creating an empty role.
+ // The API only allows creating an empty role, which must then be
+ // edited.
+ //
+ // Note to self: [this] issue/proposal may make this not require an
+ // edit.
+ //
+ // [this]: http://github.com/hammerandchisel/discord-api-docs/issues/156
let role = try!(rest::create_role(id));
let map = f(EditRole::default()).0.build();
@@ -544,9 +549,7 @@ impl Context {
/// [`Invite::delete`]: ../model/struct.Invite.html#method.delete
/// [Manage Guild]: permissions/constant.MANAGE_GUILD.html
pub fn delete_invite(&self, invite: &str) -> Result<Invite> {
- let code = utils::parse_invite(invite);
-
- rest::delete_invite(code)
+ rest::delete_invite(utils::parse_invite(invite))
}
/// Deletes a [`Message`] given its Id.
@@ -859,7 +862,7 @@ impl Context {
let guild_id = guild_id.into();
let role_id = role_id.into();
- feature_cache! {{
+ let map = feature_cache! {{
let cache = CACHE.read().unwrap();
let role = if let Some(role) = {
@@ -870,14 +873,12 @@ impl Context {
return Err(Error::Client(ClientError::RecordNotFound));
};
- let map = f(EditRole::new(role)).0.build();
-
- rest::edit_role(guild_id.0, role_id.0, map)
+ f(EditRole::new(role)).0.build()
} else {
- let map = f(EditRole::default()).0.build();
+ f(EditRole::default()).0.build()
+ }};
- rest::edit_role(guild_id.0, role_id.0, map)
- }}
+ rest::edit_role(guild_id.0, role_id.0, map)
}
/// Edit a message given its Id and the Id of the channel it belongs to.
@@ -1061,22 +1062,19 @@ impl Context {
where C: Into<ChannelId>, F: FnOnce(GetMessages) -> GetMessages {
let query = {
let mut map = f(GetMessages::default()).0;
- let mut query = format!("?limit={}",
- map.remove("limit").unwrap_or(50));
+ let mut query = String::new();
+ try!(write!(query, "?limit={}", map.remove("limit").unwrap_or(50)));
if let Some(after) = map.remove("after") {
- query.push_str("&after=");
- query.push_str(&after.to_string());
+ try!(write!(query, "&after={}", after));
}
if let Some(around) = map.remove("around") {
- query.push_str("&around=");
- query.push_str(&around.to_string());
+ try!(write!(query, "&around={}", around));
}
if let Some(before) = map.remove("before") {
- query.push_str("&before=");
- query.push_str(&before.to_string());
+ try!(write!(query, "&before={}", before));
}
query
@@ -1118,7 +1116,11 @@ impl Context {
M: Into<MessageId>,
R: Into<ReactionType>,
U: Into<UserId> {
- let limit = limit.map(|x| if x > 100 { 100 } else { x }).unwrap_or(50);
+ let limit = limit.map(|x| if x > 100 {
+ 100
+ } else {
+ x
+ }).unwrap_or(50);
rest::get_reaction_users(channel_id.into().0,
message_id.into().0,
diff --git a/src/client/gateway/prep.rs b/src/client/gateway/prep.rs
index 2ca435b..6aa40f3 100644
--- a/src/client/gateway/prep.rs
+++ b/src/client/gateway/prep.rs
@@ -21,10 +21,10 @@ use ::model::event::{Event, GatewayEvent, ReadyEvent};
#[inline]
pub fn parse_ready(event: GatewayEvent,
- tx: &MpscSender<GatewayStatus>,
- receiver: &mut Receiver<WebSocketStream>,
- identification: Value)
- -> Result<(ReadyEvent, u64)> {
+ tx: &MpscSender<GatewayStatus>,
+ receiver: &mut Receiver<WebSocketStream>,
+ identification: Value)
+ -> Result<(ReadyEvent, u64)> {
match event {
GatewayEvent::Dispatch(seq, Event::Ready(event)) => {
Ok((event, seq))
@@ -60,7 +60,7 @@ pub fn identify(token: &str, shard_info: Option<[u8; 2]>) -> Value {
object = identify_compression(object)
.insert("large_threshold", 250) // max value
.insert_object("properties", |object| object
- .insert("$browser", "Feature-full and ergonomic discord rust library")
+ .insert("$browser", "Ergonomic and high-level Rust library")
.insert("$device", "serenity")
.insert("$os", env::consts::OS)
.insert("$referrer", "")
@@ -70,10 +70,9 @@ pub fn identify(token: &str, shard_info: Option<[u8; 2]>) -> Value {
.insert("v", constants::GATEWAY_VERSION);
if let Some(shard_info) = shard_info {
- object = object
- .insert_array("shard", |a| a
- .push(shard_info[0])
- .push(shard_info[1]));
+ object = object.insert_array("shard", |a| a
+ .push(shard_info[0])
+ .push(shard_info[1]));
}
object
@@ -97,8 +96,8 @@ pub fn build_gateway_url(base: &str) -> Result<RequestUrl> {
}
pub fn keepalive(interval: u64,
- mut sender: Sender<WebSocketStream>,
- channel: MpscReceiver<GatewayStatus>) {
+ mut sender: Sender<WebSocketStream>,
+ channel: MpscReceiver<GatewayStatus>) {
let mut base_interval = Duration::milliseconds(interval as i64);
let mut next_tick = time::get_time() + base_interval;
diff --git a/src/client/gateway/shard.rs b/src/client/gateway/shard.rs
index 13a8c06..1464bd3 100644
--- a/src/client/gateway/shard.rs
+++ b/src/client/gateway/shard.rs
@@ -135,9 +135,9 @@ impl Shard {
// Parse READY
let event = try!(receiver.recv_json(GatewayEvent::decode));
let (ready, sequence) = try!(prep::parse_ready(event,
- &tx,
- &mut receiver,
- identification));
+ &tx,
+ &mut receiver,
+ identification));
Ok((feature_voice! {{
Shard {
@@ -512,8 +512,8 @@ impl Shard {
let msg = ObjectBuilder::new()
.insert("op", OpCode::StatusUpdate.num())
.insert_object("d", move |mut object| {
- object = object.insert("since", 0)
- .insert("afk", afk)
+ object = object.insert("afk", afk)
+ .insert("since", 0)
.insert("status", status.name());
match game.as_ref() {
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 41e982a..92b071e 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -812,8 +812,6 @@ impl Client {
}
}
- // How to avoid the problem while still working on other parts of the
- // library 101
loop {
thread::sleep(Duration::from_secs(1));
}
diff --git a/src/client/rest/mod.rs b/src/client/rest/mod.rs
index 84c7c00..fcd29e3 100644
--- a/src/client/rest/mod.rs
+++ b/src/client/rest/mod.rs
@@ -41,6 +41,7 @@ use serde_json::builder::ObjectBuilder;
use serde_json;
use std::collections::BTreeMap;
use std::default::Default;
+use std::fmt::Write as FmtWrite;
use std::io::{ErrorKind as IoErrorKind, Read};
use std::sync::{Arc, Mutex};
use ::constants;
@@ -1138,7 +1139,7 @@ pub fn get_message(channel_id: u64, message_id: u64)
/// Gets X messages from a channel.
pub fn get_messages(channel_id: u64, query: &str)
-> Result<Vec<Message>> {
- let url = format!(api_concat!("/channels/{}/messages{}"),
+ let url = format!(api!("/channels/{}/messages{}"),
channel_id,
query);
let client = HyperClient::new();
@@ -1172,8 +1173,7 @@ pub fn get_reaction_users(channel_id: u64,
limit);
if let Some(user_id) = after {
- uri.push_str("&after=");
- uri.push_str(&user_id.to_string());
+ try!(write!(uri, "&after={}", user_id));
}
let response = request!(Route::ChannelsIdMessagesIdReactionsUserIdType(channel_id),
@@ -1317,7 +1317,7 @@ pub fn send_file<R: Read>(channel_id: u64,
filename: &str,
map: BTreeMap<String, Value>)
-> Result<Message> {
- let uri = format!(api_concat!("/channels/{}/messages"), channel_id);
+ let uri = format!(api!("/channels/{}/messages"), channel_id);
let url = match Url::parse(&uri) {
Ok(url) => url,
Err(_why) => return Err(Error::Url(uri)),
diff --git a/src/constants.rs b/src/constants.rs
index 68f6524..50dd722 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -1,5 +1,3 @@
-use ::internal::prelude::*;
-
/// The gateway version used by the library. The gateway URI is retrieved via
/// the REST API.
pub const GATEWAY_VERSION: u8 = 6;
@@ -10,94 +8,6 @@ pub const MESSAGE_CODE_LIMIT: u16 = 2000;
/// [UserAgent]: ../hyper/header/struct.UserAgent.html
pub const USER_AGENT: &'static str = concat!("DiscordBot (https://github.com/zeyla/serenity.rs, ", env!("CARGO_PKG_VERSION"), ")");
-#[allow(dead_code)]
-#[derive(Clone, Copy, Debug, Eq, PartialEq)]
-pub enum ErrorCode {
- BotsCannotUse,
- CannotSendEmptyMessage,
- CannotSendMessagesInVoice,
- CannotSendMessagesToUser,
- ChannelVerificationTooHigh,
- EditByOtherAuthor,
- EmbedDisabled,
- InvalidAccountType,
- InvalidAuthToken,
- InvalidBulkDeleteCount,
- InvalidDMChannelAction,
- InvalidOauthState,
- InvalidPinChannel,
- MaxFriendsReached,
- MaxGuildsReached,
- MaxPinsReached,
- MaxRolesReached,
- MissingAccess,
- MissingPermissions,
- NoteTooLong,
- Oauth2ApplicationLacksBot,
- Oauth2ApplicationLimitReached,
- OnlyBotsCanUse,
- ReactionBlocked,
- TooManyReactions,
- Unauthorized,
- UnknownAccount,
- UnknownApplication,
- UnknownChannel,
- UnknownGuild,
- UnknownEmoji,
- UnknownIntegration,
- UnknownInvite,
- UnknownMember,
- UnknownMessage,
- UnknownOverwrite,
- UnknownProvider,
- UnknownRole,
- UnknownToken,
- UnknownUser,
-}
-
-map_nums! { ErrorCode;
- BotsCannotUse 20001,
- CannotSendEmptyMessage 50006,
- CannotSendMessagesInVoice 50008,
- CannotSendMessagesToUser 50007,
- ChannelVerificationTooHigh 50009,
- EditByOtherAuthor 50005,
- EmbedDisabled 50004,
- InvalidAccountType 50002,
- InvalidAuthToken 50014,
- InvalidBulkDeleteCount 50016,
- InvalidDMChannelAction 50003,
- InvalidOauthState 50012,
- InvalidPinChannel 50019,
- MaxFriendsReached 30002,
- MaxGuildsReached 30001,
- MaxPinsReached 30003,
- MaxRolesReached 30005,
- MissingAccess 50001,
- MissingPermissions 500013,
- NoteTooLong 50015,
- Oauth2ApplicationLacksBot 50010,
- Oauth2ApplicationLimitReached 50011,
- OnlyBotsCanUse 20002,
- ReactionBlocked 90001,
- TooManyReactions 30010,
- Unauthorized 40001,
- UnknownAccount 10001,
- UnknownApplication 10002,
- UnknownChannel 10003,
- UnknownEmoji 10014,
- UnknownGuild 10004,
- UnknownIntegration 10005,
- UnknownInvite 10006,
- UnknownMember 10007,
- UnknownMessage 10008,
- UnknownOverwrite 10009,
- UnknownProvider 10010,
- UnknownRole 10011,
- UnknownToken 10012,
- UnknownUser 10013,
-}
-
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum OpCode {
Event,
@@ -116,21 +26,45 @@ pub enum OpCode {
SyncCall,
}
-map_nums! { OpCode;
- Event 0,
- Heartbeat 1,
- Identify 2,
- StatusUpdate 3,
- VoiceStateUpdate 4,
- VoiceServerPing 5,
- Resume 6,
- Reconnect 7,
- GetGuildMembers 8,
- InvalidSession 9,
- Hello 10,
- HeartbeatAck 11,
- SyncGuild 12,
- SyncCall 13,
+impl OpCode {
+ pub fn from_num(num: u64) -> Option<Self> {
+ match num {
+ 0 => Some(OpCode::Event),
+ 1 => Some(OpCode::Heartbeat),
+ 2 => Some(OpCode::Identify),
+ 3 => Some(OpCode::StatusUpdate),
+ 4 => Some(OpCode::VoiceStateUpdate),
+ 5 => Some(OpCode::VoiceServerPing),
+ 6 => Some(OpCode::Resume),
+ 7 => Some(OpCode::Reconnect),
+ 8 => Some(OpCode::GetGuildMembers),
+ 9 => Some(OpCode::InvalidSession),
+ 10 => Some(OpCode::Hello),
+ 11 => Some(OpCode::HeartbeatAck),
+ 12 => Some(OpCode::SyncGuild),
+ 13 => Some(OpCode::SyncCall),
+ _ => None,
+ }
+ }
+
+ pub fn num(&self) -> u64 {
+ match *self {
+ OpCode::Event => 0,
+ OpCode::Heartbeat => 1,
+ OpCode::Identify => 2,
+ OpCode::StatusUpdate => 3,
+ OpCode::VoiceStateUpdate => 4,
+ OpCode::VoiceServerPing => 5,
+ OpCode::Resume => 6,
+ OpCode::Reconnect => 7,
+ OpCode::GetGuildMembers => 8,
+ OpCode::InvalidSession => 9,
+ OpCode::Hello => 10,
+ OpCode::HeartbeatAck => 11,
+ OpCode::SyncGuild => 12,
+ OpCode::SyncCall => 13,
+ }
+ }
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -144,12 +78,29 @@ pub enum VoiceOpCode {
Speaking,
}
-map_nums! { VoiceOpCode;
- Identify 0,
- SelectProtocol 1,
- Hello 2,
- KeepAlive 3,
- SessionDescription 4,
- Speaking 5,
- Heartbeat 8,
+impl VoiceOpCode {
+ pub fn from_num(num: u64) -> Option<Self> {
+ match num {
+ 0 => Some(VoiceOpCode::Identify),
+ 1 => Some(VoiceOpCode::SelectProtocol),
+ 2 => Some(VoiceOpCode::Hello),
+ 3 => Some(VoiceOpCode::KeepAlive),
+ 4 => Some(VoiceOpCode::SessionDescription),
+ 5 => Some(VoiceOpCode::Speaking),
+ 8 => Some(VoiceOpCode::Heartbeat),
+ _ => None,
+ }
+ }
+
+ pub fn num(&self) -> u64 {
+ match *self {
+ VoiceOpCode::Identify => 0,
+ VoiceOpCode::SelectProtocol => 1,
+ VoiceOpCode::Hello => 2,
+ VoiceOpCode::KeepAlive => 3,
+ VoiceOpCode::SessionDescription => 4,
+ VoiceOpCode::Speaking => 5,
+ VoiceOpCode::Heartbeat => 8,
+ }
+ }
}
diff --git a/src/error.rs b/src/error.rs
index 94958fd..eaa2e13 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,9 +1,9 @@
-use std::io::Error as IoError;
-use std::error::Error as StdError;
-use std::fmt::{self, Display};
use hyper::Error as HyperError;
use serde_json::Error as JsonError;
use serde_json::Value;
+use std::io::Error as IoError;
+use std::error::Error as StdError;
+use std::fmt::{self, Display, Error as FormatError};
use websocket::result::WebSocketError;
use ::client::gateway::GatewayError;
use ::client::ClientError;
@@ -47,6 +47,8 @@ pub enum Error {
Gateway(GatewayError),
/// An error while decoding a payload.
Decode(&'static str, Value),
+ /// There was an error with a format.
+ Format(FormatError),
/// An error from the `hyper` crate.
Hyper(HyperError),
/// An `std::io` error.
@@ -73,6 +75,12 @@ pub enum Error {
Voice(VoiceError),
}
+impl From<FormatError> for Error {
+ fn from(e: FormatError) -> Error {
+ Error::Format(e)
+ }
+}
+
impl From<IoError> for Error {
fn from(e: IoError) -> Error {
Error::Io(e)
@@ -122,8 +130,9 @@ impl StdError for Error {
fn description(&self) -> &str {
match *self {
Error::Client(_) => "Client refused a request",
- Error::Gateway(ref _inner) => "Gateway error",
Error::Decode(msg, _) | Error::Other(msg) => msg,
+ Error::Format(ref inner) => inner.description(),
+ Error::Gateway(ref _inner) => "Gateway error",
Error::Hyper(ref inner) => inner.description(),
Error::Io(ref inner) => inner.description(),
Error::Json(ref inner) => inner.description(),
diff --git a/src/ext/cache/mod.rs b/src/ext/cache/mod.rs
index 0981cf3..2272178 100644
--- a/src/ext/cache/mod.rs
+++ b/src/ext/cache/mod.rs
@@ -244,7 +244,7 @@ impl Cache {
pub fn all_guilds(&self) -> Vec<GuildId> {
self.guilds
.values()
- .map(|s| s.id)
+ .map(|g| g.id)
.chain(self.unavailable_guilds.iter().cloned())
.collect()
}
@@ -259,7 +259,7 @@ impl Cache {
guild.id
})
- .collect::<Vec<_>>()
+ .collect::<Vec<GuildId>>()
}
/// Retrieves a reference to a [`Call`] from the cache based on the
@@ -324,8 +324,9 @@ impl Cache {
/// let channel = match cache.get_guild_channel(message.channel_id) {
/// Some(channel) => channel,
/// None => {
- /// context.say("Could not find guild's channel data")
- /// .map_err(|why| println!("Error sending message: {:?}", why));
+ /// if let Err(why) = context.say("Could not find guild's channel data") {
+ /// println!("Error sending message: {:?}", why);
+ /// }
///
/// return;
/// },
@@ -406,7 +407,7 @@ impl Cache {
guild.members.get(&user_id.into())
}).and_then(|x| match x {
Some(x) => Some(x),
- _ => None,
+ None => None,
})
}
@@ -422,130 +423,6 @@ impl Cache {
}
}
- /// Update the cache according to the changes described in the given event.
- #[allow(cyclomatic_complexity)]
- #[allow(unneeded_field_pattern)]
- #[doc(hidden)]
- pub fn update(&mut self, event: &Event) {
- match *event {
- Event::CallCreate(ref event) => {
- self.update_with_call_create(event);
- },
- Event::CallDelete(ref event) => {
- self.update_with_call_delete(event);
- },
- Event::CallUpdate(ref event) => {
- self.update_with_call_update(event, false);
- },
- Event::ChannelCreate(ref event) => {
- self.update_with_channel_create(event);
- },
- Event::ChannelDelete(ref event) => {
- self.update_with_channel_delete(event);
- },
- Event::ChannelPinsUpdate(ref event) => {
- self.update_with_channel_pins_update(event);
- },
- Event::ChannelRecipientAdd(ref event) => {
- self.update_with_channel_recipient_add(event);
- },
- Event::ChannelRecipientRemove(ref event) => {
- self.update_with_channel_recipient_remove(event);
- },
- Event::ChannelUpdate(ref event) => {
- self.update_with_channel_update(event);
- },
- Event::GuildCreate(ref event) => {
- self.update_with_guild_create(event);
- },
- Event::GuildDelete(ref event) => {
- self.update_with_guild_delete(event);
- },
- Event::GuildEmojisUpdate(ref event) => {
- self.update_with_guild_emojis_update(event);
- },
- Event::GuildMemberAdd(ref event) => {
- self.update_with_guild_member_add(event);
- },
- Event::GuildMemberRemove(ref event) => {
- self.update_with_guild_member_remove(event);
- },
- Event::GuildMemberUpdate(ref event) => {
- self.update_with_guild_member_update(event);
- },
- Event::GuildMembersChunk(ref event) => {
- self.update_with_guild_members_chunk(event);
- },
- Event::GuildRoleCreate(ref event) => {
- self.update_with_guild_role_create(event);
- },
- Event::GuildRoleDelete(ref event) => {
- self.update_with_guild_role_delete(event);
- },
- Event::GuildRoleUpdate(ref event) => {
- self.update_with_guild_role_update(event);
- },
- Event::GuildSync(ref event) => {
- self.update_with_guild_sync(event);
- },
- Event::GuildUnavailable(ref event) => {
- self.update_with_guild_unavailable(event);
- },
- Event::GuildUpdate(ref event) => {
- self.update_with_guild_update(event);
- },
- Event::PresencesReplace(ref event) => {
- self.update_with_presences_replace(event);
- },
- Event::PresenceUpdate(ref event) => {
- self.update_with_presence_update(event);
- },
- Event::Ready(ref event) => {
- self.update_with_ready(event);
- },
- Event::RelationshipAdd(ref event) => {
- self.update_with_relationship_add(event);
- },
- Event::RelationshipRemove(ref event) => {
- self.update_with_relationship_remove(event);
- },
- Event::UserGuildSettingsUpdate(ref event) => {
- self.update_with_user_guild_settings_update(event);
- },
- Event::UserNoteUpdate(ref event) => {
- self.update_with_user_note_update(event);
- },
- Event::UserSettingsUpdate(ref event) => {
- self.update_with_user_settings_update(event, false);
- },
- Event::UserUpdate(ref event) => {
- self.update_with_user_update(event);
- },
- Event::VoiceStateUpdate(ref event) => {
- self.update_with_voice_state_update(event);
- },
- Event::ChannelPinsAck(_) |
- Event::FriendSuggestionCreate(_) |
- Event::FriendSuggestionDelete(_) |
- Event::GuildBanAdd(_) |
- Event::GuildBanRemove(_) |
- Event::GuildIntegrationsUpdate(_) |
- Event::MessageAck(_) |
- Event::MessageCreate(_) |
- Event::MessageDelete(_) |
- Event::MessageDeleteBulk(_) |
- Event::MessageUpdate(_) |
- Event::ReactionAdd(_) |
- Event::ReactionRemove(_) |
- Event::ReactionRemoveAll(_) |
- Event::Resumed(_) |
- Event::TypingStart(_) |
- Event::VoiceServerUpdate(_) |
- Event::WebhookUpdate(_) |
- Event::Unknown(_) => {},
- }
- }
-
#[doc(hidden)]
pub fn update_with_call_create(&mut self, event: &CallCreateEvent) {
match self.calls.entry(event.call.channel_id) {
@@ -604,12 +481,10 @@ impl Cache {
guild.channels.insert(channel.id, channel.clone())
});
- let ch = match ch {
- Some(Some(ch)) => Some(ch),
+ match ch {
+ Some(Some(ch)) => Some(Channel::Guild(ch)),
_ => None,
- };
-
- ch.map(Channel::Guild)
+ }
},
}
}
@@ -695,7 +570,8 @@ impl Cache {
let dest = e.get_mut();
if group.recipients.is_empty() {
- let recipients = mem::replace(&mut dest.recipients, HashMap::new());
+ let recipients = mem::replace(&mut dest.recipients,
+ HashMap::new());
dest.clone_from(group);
@@ -1075,8 +951,8 @@ impl Cache {
let finding = call.voice_states
.get_mut(&event.voice_state.user_id);
- if let Some(grp_state) = finding {
- grp_state.clone_from(&event.voice_state);
+ if let Some(group_state) = finding {
+ group_state.clone_from(&event.voice_state);
return;
}
diff --git a/src/ext/framework/command.rs b/src/ext/framework/command.rs
index e0a4616..46338a1 100644
--- a/src/ext/framework/command.rs
+++ b/src/ext/framework/command.rs
@@ -1,5 +1,5 @@
use std::sync::Arc;
-use super::{CommandType, Configuration};
+use super::Configuration;
use ::client::Context;
use ::model::Message;
@@ -8,15 +8,14 @@ pub type Command = Fn(&Context, &Message, Vec<String>) + Send + Sync;
#[doc(hidden)]
pub type InternalCommand = Arc<Command>;
-pub fn positions(content: &str, conf: &Configuration)
- -> Option<(Vec<usize>, CommandType)> {
+pub fn positions(content: &str, conf: &Configuration) -> Option<Vec<usize>> {
if let Some(ref prefix) = conf.prefix {
// Find out if they were mentioned. If not, determine if the prefix
// was used. If not, return None.
- let (mut positions, kind) = if let Some(mention_end) = find_mention_end(content, conf) {
- (vec![mention_end], CommandType::Mention)
+ let mut positions = if let Some(mention_end) = find_mention_end(content, conf) {
+ vec![mention_end]
} else if content.starts_with(prefix) {
- (vec![prefix.len()], CommandType::Prefix)
+ vec![prefix.len()]
} else {
return None;
};
@@ -29,7 +28,7 @@ pub fn positions(content: &str, conf: &Configuration)
positions.insert(0, pos + 1);
}
- Some((positions, kind))
+ Some(positions)
} else if conf.on_mention.is_some() {
match find_mention_end(content, conf) {
Some(mention_end) => {
@@ -39,7 +38,7 @@ pub fn positions(content: &str, conf: &Configuration)
positions.insert(0, mention_end + 1);
}
- Some((positions, CommandType::Mention))
+ Some(positions)
},
None => None,
}
diff --git a/src/ext/framework/mod.rs b/src/ext/framework/mod.rs
index e79bd18..a470550 100644
--- a/src/ext/framework/mod.rs
+++ b/src/ext/framework/mod.rs
@@ -125,34 +125,6 @@ macro_rules! command {
};
}
-/// The type of command being received.
-///
-/// The [`Mention`] variant is emitted if the bot is being commanded via a
-/// mention (`<@USER_ID>` or `<@!USER_ID>`). This can only be emitted if
-/// [`Configuration::on_mention`] is set to `true`.
-///
-/// The [`Prefix`] variant is emitted if a message starts with the prefix set
-/// via [`Configuration::prefix`].
-///
-/// [`Mention`]: #variant.Mention
-/// [`Prefix`]: #variant.Prefix
-// This is public due to being leaked by [`command::positions`], which is used
-// in [`Framework::dispatch`]. It therefore is hidden from the docs, due to
-// having no use to users.
-//
-// [`Framework::dispatch`]: struct.Framework.html#method.dispatch
-// [`command::positions`]: command/fn.positions.html
-#[derive(Clone, Copy, Debug)]
-#[doc(hidden)]
-pub enum CommandType {
- /// This is emitted if the bot is being commanded via a mention
- /// (`<@USER_ID>` or `<@!USER_ID>`). This can only be emitted if
- /// [`Configuration::on_mention`] is set to `true`.
- Mention,
- None,
- Prefix,
-}
-
/// A utility for easily managing dispatches to commands.
///
/// Refer to the [module-level documentation] for more information.
@@ -214,7 +186,6 @@ impl Framework {
pub fn configure<F>(mut self, f: F) -> Self
where F: FnOnce(Configuration) -> Configuration {
self.configuration = f(self.configuration);
- self.initialized = true;
self
}
@@ -224,7 +195,7 @@ impl Framework {
let res = command::positions(&message.content, &self.configuration);
let positions = match res {
- Some((positions, _kind)) => positions,
+ Some(positions) => positions,
None => return,
};
@@ -358,7 +329,6 @@ impl Framework {
where F: Fn(&Context, &Message) -> bool + Send + Sync + 'static,
S: Into<String> {
self.checks.insert(command.into(), Arc::new(check));
- self.initialized = true;
self
}
diff --git a/src/ext/voice/audio.rs b/src/ext/voice/audio.rs
index 814cd69..ea8c87a 100644
--- a/src/ext/voice/audio.rs
+++ b/src/ext/voice/audio.rs
@@ -1,5 +1,3 @@
-use ::model::UserId;
-
pub const HEADER_LEN: usize = 12;
pub const SAMPLE_RATE: u32 = 48000;
diff --git a/src/ext/voice/connection.rs b/src/ext/voice/connection.rs
index 8f1821d..f88a3ff 100644
--- a/src/ext/voice/connection.rs
+++ b/src/ext/voice/connection.rs
@@ -26,7 +26,7 @@ use websocket::stream::WebSocketStream;
use ::internal::prelude::*;
use ::internal::ws_impl::{ReceiverExt, SenderExt};
use ::internal::Timer;
-use ::model::VoiceEvent;
+use ::model::event::VoiceEvent;
enum ReceiverStatus {
Udp(Vec<u8>),
@@ -165,11 +165,11 @@ impl Connection {
}
#[allow(unused_variables)]
- pub fn update(&mut self,
- source: &mut Option<Box<AudioSource>>,
- receiver: &mut Option<Box<AudioReceiver>>,
- audio_timer: &mut Timer)
- -> Result<()> {
+ pub fn cycle(&mut self,
+ source: &mut Option<Box<AudioSource>>,
+ receiver: &mut Option<Box<AudioReceiver>>,
+ audio_timer: &mut Timer)
+ -> Result<()> {
let mut buffer = [0i16; 960 * 2];
let mut packet = [0u8; 512];
let mut nonce = secretbox::Nonce([0; 24]);
@@ -230,7 +230,7 @@ impl Connection {
try!(self.sender.send_json(&payload::build_keepalive()));
}
- // Send the UDP keepalive if it's time
+ // Send UDP keepalive if it's time
if self.audio_timer.check() {
let mut bytes = [0; 4];
try!((&mut bytes[..]).write_u32::<BigEndian>(self.ssrc));
@@ -286,7 +286,7 @@ impl Connection {
nonce.0[..HEADER_LEN].clone_from_slice(&packet[..HEADER_LEN]);
- let extent = packet.len() - 16;
+ let sl_index = packet.len() - 16;
let buffer_len = if self.encoder_stereo {
960 * 2
} else {
@@ -294,7 +294,7 @@ impl Connection {
};
let len = try!(self.encoder.encode(&buffer[..buffer_len],
- &mut packet[HEADER_LEN..extent]));
+ &mut packet[HEADER_LEN..sl_index]));
let crypted = {
let slice = &packet[HEADER_LEN..HEADER_LEN + len];
secretbox::seal(slice, &nonce, &self.key)
diff --git a/src/ext/voice/threading.rs b/src/ext/voice/threading.rs
index bbbffd1..8d3599b 100644
--- a/src/ext/voice/threading.rs
+++ b/src/ext/voice/threading.rs
@@ -66,11 +66,11 @@ fn runner(rx: MpscReceiver<Status>) {
// another event.
let error = match connection.as_mut() {
Some(connection) => {
- let update = connection.update(&mut sender,
- &mut receiver,
- &mut timer);
+ let cycle = connection.cycle(&mut sender,
+ &mut receiver,
+ &mut timer);
- match update {
+ match cycle {
Ok(()) => false,
Err(why) => {
error!("[Voice] Error updating connection: {:?}", why);
diff --git a/src/internal/ws_impl.rs b/src/internal/ws_impl.rs
index ea327fd..72af52c 100644
--- a/src/internal/ws_impl.rs
+++ b/src/internal/ws_impl.rs
@@ -22,11 +22,9 @@ impl ReceiverExt for Receiver<WebSocketStream> {
let message: WsMessage = try!(self.recv_message());
if message.opcode == WsType::Close {
- let representation = String::from_utf8_lossy(&message.payload)
- .into_owned();
+ let r = String::from_utf8_lossy(&message.payload).into_owned();
- Err(Error::Gateway(GatewayError::Closed(message.cd_status_code,
- representation)))
+ Err(Error::Gateway(GatewayError::Closed(message.cd_status_code, r)))
} else if message.opcode == WsType::Binary || message.opcode == WsType::Text {
let json: Value = if message.opcode == WsType::Binary {
try!(serde_json::from_reader(ZlibDecoder::new(&message.payload[..])))
@@ -34,17 +32,20 @@ impl ReceiverExt for Receiver<WebSocketStream> {
try!(serde_json::from_reader(&message.payload[..]))
};
- decode(json).map_err(|err| {
- warn!("Error decoding: {}",
- String::from_utf8_lossy(&message.payload));
+ match decode(json) {
+ Ok(v) => Ok(v),
+ Err(why) => {
+ let s = String::from_utf8_lossy(&message.payload);
- err
- })
+ warn!("Error decoding: {}", s);
+
+ Err(why)
+ }
+ }
} else {
- let representation = String::from_utf8_lossy(&message.payload)
- .into_owned();
+ let r = String::from_utf8_lossy(&message.payload).into_owned();
- Err(Error::Gateway(GatewayError::Closed(None, representation)))
+ Err(Error::Gateway(GatewayError::Closed(None, r)))
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 68402ad..761ef86 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -76,7 +76,7 @@
//! [`validate_token`]: client/fn.validate_token.html
#![allow(doc_markdown, inline_always, unknown_lints)]
#![doc(html_logo_url = "https://docs.austinhellyer.me/serenity.rs/docs_header.png")]
-#![warn(dead_code, enum_glob_use, if_not_else)]
+#![warn(enum_glob_use, if_not_else)]
#[macro_use]
extern crate bitflags;
diff --git a/src/model/channel.rs b/src/model/channel.rs
index 33e6044..13cf506 100644
--- a/src/model/channel.rs
+++ b/src/model/channel.rs
@@ -6,7 +6,6 @@ use super::utils::{
into_string,
opt,
remove,
- warn_field,
};
use super::*;
use ::constants;
@@ -343,7 +342,7 @@ impl Group {
/// Returns the formatted URI of the group's icon if one exists.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
- format!(cdn_concat!("/channel-icons/{}/{}.jpg"), self.channel_id, icon))
+ format!(cdn!("/channel-icons/{}/{}.jpg"), self.channel_id, icon))
}
/// Leaves the group.
@@ -639,8 +638,7 @@ impl Message {
}}
let mut gen = format!("{}", self.author.mention());
- gen.push(':');
- gen.push(' ');
+ gen.push_str(": ");
gen.push_str(content);
let map = ObjectBuilder::new()
@@ -690,7 +688,7 @@ impl PermissionOverwrite {
_ => return Err(Error::Decode("Expected valid PermissionOverwrite type", Value::String(kind))),
};
- missing!(map, PermissionOverwrite {
+ Ok(PermissionOverwrite {
kind: kind,
allow: try!(remove(&mut map, "allow").and_then(Permissions::decode)),
deny: try!(remove(&mut map, "deny").and_then(Permissions::decode)),
@@ -711,7 +709,7 @@ impl PrivateChannel {
let mut recipients = try!(decode_array(try!(remove(&mut map, "recipients")),
User::decode));
- missing!(map, PrivateChannel {
+ Ok(PrivateChannel {
id: try!(remove(&mut map, "id").and_then(ChannelId::decode)),
kind: try!(remove(&mut map, "type").and_then(ChannelType::decode)),
last_message_id: try!(opt(&mut map, "last_message_id", MessageId::decode)),
@@ -858,7 +856,8 @@ impl GuildChannel {
#[doc(hidden)]
pub fn decode_guild(value: Value, guild_id: GuildId) -> Result<GuildChannel> {
let mut map = try!(into_map(value));
- missing!(map, GuildChannel {
+
+ Ok(GuildChannel {
id: try!(remove(&mut map, "id").and_then(ChannelId::decode)),
name: try!(remove(&mut map, "name").and_then(into_string)),
guild_id: guild_id,
diff --git a/src/model/event.rs b/src/model/event.rs
index 694ebf1..d459503 100644
--- a/src/model/event.rs
+++ b/src/model/event.rs
@@ -3,7 +3,7 @@
use std::collections::{BTreeMap, HashMap};
use super::utils::*;
use super::*;
-use ::constants::OpCode;
+use ::constants::{OpCode, VoiceOpCode};
use ::internal::prelude::*;
use ::utils::decode_array;
@@ -489,11 +489,11 @@ impl Event {
call: try!(Call::decode(Value::Object(value))),
}))
} else if kind == "CALL_DELETE" {
- missing!(value, Event::CallDelete(CallDeleteEvent {
+ Ok(Event::CallDelete(CallDeleteEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
}))
} else if kind == "CALL_UPDATE" {
- missing!(value, Event::CallUpdate(CallUpdateEvent {
+ Ok(Event::CallUpdate(CallUpdateEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
message_id: try!(remove(&mut value, "message_id").and_then(MessageId::decode)),
region: try!(remove(&mut value, "region").and_then(into_string)),
@@ -508,22 +508,22 @@ impl Event {
channel: try!(Channel::decode(Value::Object(value))),
}))
} else if kind == "CHANNEL_PINS_ACK" {
- missing!(value, Event::ChannelPinsAck(ChannelPinsAckEvent {
+ Ok(Event::ChannelPinsAck(ChannelPinsAckEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
timestamp: try!(remove(&mut value, "timestamp").and_then(into_string)),
}))
} else if kind == "CHANNEL_PINS_UPDATE" {
- missing!(value, Event::ChannelPinsUpdate(ChannelPinsUpdateEvent {
+ Ok(Event::ChannelPinsUpdate(ChannelPinsUpdateEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
last_pin_timestamp: try!(opt(&mut value, "last_pin_timestamp", into_string)),
}))
} else if kind == "CHANNEL_RECIPIENT_ADD" {
- missing!(value, Event::ChannelRecipientAdd(ChannelRecipientAddEvent {
+ Ok(Event::ChannelRecipientAdd(ChannelRecipientAddEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
} else if kind == "CHANNEL_RECIPIENT_REMOVE" {
- missing!(value, Event::ChannelRecipientRemove(ChannelRecipientRemoveEvent {
+ Ok(Event::ChannelRecipientRemove(ChannelRecipientRemoveEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
@@ -532,21 +532,21 @@ impl Event {
channel: try!(Channel::decode(Value::Object(value))),
}))
} else if kind == "FRIEND_SUGGESTION_CREATE" {
- missing!(value, Event::FriendSuggestionCreate(FriendSuggestionCreateEvent {
+ Ok(Event::FriendSuggestionCreate(FriendSuggestionCreateEvent {
reasons: try!(decode_array(try!(remove(&mut value, "reasons")), SuggestionReason::decode)),
suggested_user: try!(remove(&mut value, "suggested_user").and_then(User::decode)),
}))
} else if kind == "FRIEND_SUGGESTION_DELETE" {
- missing!(value, Event::FriendSuggestionDelete(FriendSuggestionDeleteEvent {
+ Ok(Event::FriendSuggestionDelete(FriendSuggestionDeleteEvent {
suggested_user_id: try!(remove(&mut value, "suggested_user_id").and_then(UserId::decode)),
}))
} else if kind == "GUILD_BAN_ADD" {
- missing!(value, Event::GuildBanAdd(GuildBanAddEvent {
+ Ok(Event::GuildBanAdd(GuildBanAddEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
} else if kind == "GUILD_BAN_REMOVE" {
- missing!(value, Event::GuildBanRemove(GuildBanRemoveEvent {
+ Ok(Event::GuildBanRemove(GuildBanRemoveEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
@@ -571,12 +571,12 @@ impl Event {
}))
}
} else if kind == "GUILD_EMOJIS_UPDATE" {
- missing!(value, Event::GuildEmojisUpdate(GuildEmojisUpdateEvent {
+ Ok(Event::GuildEmojisUpdate(GuildEmojisUpdateEvent {
emojis: try!(remove(&mut value, "emojis").and_then(decode_emojis)),
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
}))
} else if kind == "GUILD_INTEGRATIONS_UPDATE" {
- missing!(value, Event::GuildIntegrationsUpdate(GuildIntegrationsUpdateEvent {
+ Ok(Event::GuildIntegrationsUpdate(GuildIntegrationsUpdateEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
}))
} else if kind == "GUILD_MEMBER_ADD" {
@@ -585,39 +585,39 @@ impl Event {
member: try!(Member::decode(Value::Object(value))),
}))
} else if kind == "GUILD_MEMBER_REMOVE" {
- missing!(value, Event::GuildMemberRemove(GuildMemberRemoveEvent {
+ Ok(Event::GuildMemberRemove(GuildMemberRemoveEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
} else if kind == "GUILD_MEMBER_UPDATE" {
- missing!(value, Event::GuildMemberUpdate(GuildMemberUpdateEvent {
+ Ok(Event::GuildMemberUpdate(GuildMemberUpdateEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
nick: try!(opt(&mut value, "nick", into_string)),
roles: try!(decode_array(try!(remove(&mut value, "roles")), RoleId::decode)),
user: try!(remove(&mut value, "user").and_then(User::decode)),
}))
} else if kind == "GUILD_MEMBERS_CHUNK" {
- missing!(value, Event::GuildMembersChunk(GuildMembersChunkEvent {
+ Ok(Event::GuildMembersChunk(GuildMembersChunkEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
members: try!(remove(&mut value, "members").and_then(decode_members)),
}))
} else if kind == "GUILD_ROLE_CREATE" {
- missing!(value, Event::GuildRoleCreate(GuildRoleCreateEvent {
+ Ok(Event::GuildRoleCreate(GuildRoleCreateEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
role: try!(remove(&mut value, "role").and_then(Role::decode)),
}))
} else if kind == "GUILD_ROLE_DELETE" {
- missing!(value, Event::GuildRoleDelete(GuildRoleDeleteEvent {
+ Ok(Event::GuildRoleDelete(GuildRoleDeleteEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
role_id: try!(remove(&mut value, "role_id").and_then(RoleId::decode)),
}))
} else if kind == "GUILD_ROLE_UPDATE" {
- missing!(value, Event::GuildRoleUpdate(GuildRoleUpdateEvent {
+ Ok(Event::GuildRoleUpdate(GuildRoleUpdateEvent {
guild_id: try!(remove(&mut value, "guild_id").and_then(GuildId::decode)),
role: try!(remove(&mut value, "role").and_then(Role::decode)),
}))
} else if kind == "GUILD_SYNC" {
- missing!(value, Event::GuildSync(GuildSyncEvent {
+ Ok(Event::GuildSync(GuildSyncEvent {
guild_id: try!(remove(&mut value, "id").and_then(GuildId::decode)),
large: req!(try!(remove(&mut value, "large")).as_bool()),
members: try!(remove(&mut value, "members").and_then(decode_members)),
@@ -628,7 +628,7 @@ impl Event {
guild: try!(PartialGuild::decode(Value::Object(value))),
}))
} else if kind == "MESSAGE_ACK" {
- missing!(value, Event::MessageAck(MessageAckEvent {
+ Ok(Event::MessageAck(MessageAckEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
message_id: try!(opt(&mut value, "message_id", MessageId::decode)),
}))
@@ -637,12 +637,12 @@ impl Event {
message: try!(Message::decode(Value::Object(value))),
}))
} else if kind == "MESSAGE_DELETE" {
- missing!(value, Event::MessageDelete(MessageDeleteEvent {
+ Ok(Event::MessageDelete(MessageDeleteEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
message_id: try!(remove(&mut value, "id").and_then(MessageId::decode)),
}))
} else if kind == "MESSAGE_DELETE_BULK" {
- missing!(value, Event::MessageDeleteBulk(MessageDeleteBulkEvent {
+ Ok(Event::MessageDeleteBulk(MessageDeleteBulkEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
ids: try!(decode_array(try!(remove(&mut value, "ids")), MessageId::decode)),
}))
@@ -650,7 +650,7 @@ impl Event {
Ok(Event::ReactionAdd(ReactionAddEvent {
reaction: try!(Reaction::decode(Value::Object(value)))
}))
- } else if kind == "MESSAG_REACTION_REMOVE" {
+ } else if kind == "MESSAGE_REACTION_REMOVE" {
Ok(Event::ReactionRemove(ReactionRemoveEvent {
reaction: try!(Reaction::decode(Value::Object(value)))
}))
@@ -660,7 +660,7 @@ impl Event {
message_id: try!(remove(&mut value, "message_id").and_then(MessageId::decode)),
}))
} else if kind == "MESSAGE_UPDATE" {
- missing!(value, Event::MessageUpdate(MessageUpdateEvent {
+ Ok(Event::MessageUpdate(MessageUpdateEvent {
id: try!(remove(&mut value, "id").and_then(MessageId::decode)),
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
kind: try!(opt(&mut value, "type", MessageType::decode)),
@@ -691,7 +691,7 @@ impl Event {
relationship: try!(Relationship::decode(Value::Object(value))),
}))
} else if kind == "RELATIONSHIP_REMOVE" {
- missing!(value, Event::RelationshipRemove(RelationshipRemoveEvent {
+ Ok(Event::RelationshipRemove(RelationshipRemoveEvent {
kind: try!(remove(&mut value, "type").and_then(RelationshipType::decode)),
user_id: try!(remove(&mut value, "id").and_then(UserId::decode)),
}))
@@ -700,12 +700,12 @@ impl Event {
ready: try!(Ready::decode(Value::Object(value))),
}))
} else if kind == "RESUMED" {
- missing!(value, Event::Resumed(ResumedEvent {
+ Ok(Event::Resumed(ResumedEvent {
heartbeat_interval: req!(try!(remove(&mut value, "heartbeat_interval")).as_u64()),
trace: try!(remove(&mut value, "_trace").and_then(|v| decode_array(v, |v| Ok(into_string(v).ok())))),
}))
} else if kind == "TYPING_START" {
- missing!(value, Event::TypingStart(TypingStartEvent {
+ Ok(Event::TypingStart(TypingStartEvent {
channel_id: try!(remove(&mut value, "channel_id").and_then(ChannelId::decode)),
timestamp: req!(try!(remove(&mut value, "timestamp")).as_u64()),
user_id: try!(remove(&mut value, "user_id").and_then(UserId::decode)),
@@ -715,12 +715,12 @@ impl Event {
settings: try!(UserGuildSettings::decode(Value::Object(value))),
}))
} else if kind == "USER_NOTE_UPDATE" {
- missing!(value, Event::UserNoteUpdate(UserNoteUpdateEvent {
+ Ok(Event::UserNoteUpdate(UserNoteUpdateEvent {
note: try!(remove(&mut value, "note").and_then(into_string)),
user_id: try!(remove(&mut value, "id").and_then(UserId::decode)),
}))
} else if kind == "USER_SETTINGS_UPDATE" {
- missing!(value, Event::UserSettingsUpdate(UserSettingsUpdateEvent {
+ Ok(Event::UserSettingsUpdate(UserSettingsUpdateEvent {
enable_tts_command: remove(&mut value, "enable_tts_command").ok().and_then(|v| v.as_bool()),
inline_attachment_media: remove(&mut value, "inline_attachment_media").ok().and_then(|v| v.as_bool()),
inline_embed_media: remove(&mut value, "inline_embed_media").ok().and_then(|v| v.as_bool()),
@@ -737,7 +737,7 @@ impl Event {
current_user: try!(CurrentUser::decode(Value::Object(value))),
}))
} else if kind == "VOICE_SERVER_UPDATE" {
- missing!(value, Event::VoiceServerUpdate(VoiceServerUpdateEvent {
+ Ok(Event::VoiceServerUpdate(VoiceServerUpdateEvent {
guild_id: try!(opt(&mut value, "guild_id", GuildId::decode)),
channel_id: try!(opt(&mut value, "channel_id", ChannelId::decode)),
endpoint: try!(opt(&mut value, "endpoint", into_string)),
@@ -761,3 +761,90 @@ impl Event {
}
}
}
+
+#[derive(Clone, Copy, Debug)]
+pub struct VoiceHeartbeat {
+ pub heartbeat_interval: u64,
+}
+
+#[derive(Clone, Debug)]
+pub struct VoiceHello {
+ pub heartbeat_interval: u64,
+ pub ip: String,
+ pub modes: Vec<String>,
+ pub port: u16,
+ pub ssrc: u32,
+}
+
+#[derive(Clone, Debug)]
+pub struct VoiceReady {
+ pub mode: String,
+ pub secret_key: Vec<u8>,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub struct VoiceSpeaking {
+ pub speaking: bool,
+ pub ssrc: u32,
+ pub user_id: UserId,
+}
+
+#[derive(Clone, Debug)]
+pub enum VoiceEvent {
+ Heartbeat(VoiceHeartbeat),
+ Hello(VoiceHello),
+ Ready(VoiceReady),
+ Speaking(VoiceSpeaking),
+ KeepAlive,
+ Unknown(VoiceOpCode, Value)
+}
+
+impl VoiceEvent {
+ pub fn decode(value: Value) -> Result<VoiceEvent> {
+ let mut value = try!(into_map(value));
+ let op = req!(try!(remove(&mut value, "op")).as_u64());
+ let mut map = try!(remove(&mut value, "d").and_then(into_map));
+
+ let opcode = try!(VoiceOpCode::from_num(op)
+ .ok_or(Error::Client(ClientError::InvalidOpCode)));
+
+ match opcode {
+ VoiceOpCode::Heartbeat => {
+ Ok(VoiceEvent::Heartbeat(VoiceHeartbeat {
+ heartbeat_interval: req!(try!(remove(&mut map, "heartbeat_interval")).as_u64()),
+ }))
+ },
+ VoiceOpCode::Hello => {
+ Ok(VoiceEvent::Hello(VoiceHello {
+ heartbeat_interval: req!(try!(remove(&mut map, "heartbeat_interval"))
+ .as_u64()),
+ ip: try!(remove(&mut map, "ip").and_then(into_string)),
+ modes: try!(decode_array(try!(remove(&mut map, "modes")),
+ into_string)),
+ port: req!(try!(remove(&mut map, "port"))
+ .as_u64()) as u16,
+ ssrc: req!(try!(remove(&mut map, "ssrc"))
+ .as_u64()) as u32,
+ }))
+ },
+ VoiceOpCode::KeepAlive => Ok(VoiceEvent::KeepAlive),
+ VoiceOpCode::SessionDescription => {
+ Ok(VoiceEvent::Ready(VoiceReady {
+ mode: try!(remove(&mut map, "mode")
+ .and_then(into_string)),
+ secret_key: try!(decode_array(try!(remove(&mut map, "secret_key")),
+ |v| Ok(req!(v.as_u64()) as u8)
+ )),
+ }))
+ },
+ VoiceOpCode::Speaking => {
+ Ok(VoiceEvent::Speaking(VoiceSpeaking {
+ speaking: req!(try!(remove(&mut map, "speaking")).as_bool()),
+ ssrc: req!(try!(remove(&mut map, "ssrc")).as_u64()) as u32,
+ user_id: try!(remove(&mut map, "user_id").and_then(UserId::decode)),
+ }))
+ }
+ other => Ok(VoiceEvent::Unknown(other, Value::Object(map))),
+ }
+ }
+}
diff --git a/src/model/gateway.rs b/src/model/gateway.rs
index 30ed695..93c779b 100644
--- a/src/model/gateway.rs
+++ b/src/model/gateway.rs
@@ -36,7 +36,7 @@ impl Game {
return Ok(None);
}
- missing!(map, Some(Game {
+ Ok(Some(Game {
name: name,
kind: try!(opt(&mut map, "type", GameType::decode)).unwrap_or(GameType::Playing),
url: try!(opt(&mut map, "url", into_string)),
@@ -62,7 +62,7 @@ impl Presence {
Some(v) => try!(Game::decode(v)),
};
- missing!(value, Presence {
+ Ok(Presence {
user_id: user_id,
status: try!(remove(&mut value, "status").and_then(OnlineStatus::decode_str)),
last_modified: try!(opt(&mut value, "last_modified", |v| Ok(req!(v.as_u64())))),
diff --git a/src/model/guild.rs b/src/model/guild.rs
index 4869e86..9408fae 100644
--- a/src/model/guild.rs
+++ b/src/model/guild.rs
@@ -10,7 +10,6 @@ use super::utils::{
into_string,
opt,
remove,
- warn_field
};
use super::*;
use ::internal::prelude::*;
@@ -122,7 +121,7 @@ impl GuildInfo {
/// Returns the formatted URL of the guild's icon, if the guild has an icon.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
- format!(cdn_concat!("/icons/{}/{}.jpg"), self.id, icon))
+ format!(cdn!("/icons/{}/{}.jpg"), self.id, icon))
}
}
@@ -149,7 +148,7 @@ impl PartialGuild {
/// Returns a formatted URL of the guild's icon, if the guild has an icon.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
- format!(cdn_concat!("/icons/{}/{}.jpg"), self.id, icon))
+ format!(cdn!("/icons/{}/{}.jpg"), self.id, icon))
}
/// Retrieves the guild's webhooks.
@@ -173,7 +172,6 @@ impl Guild {
};
let perms = self.permissions_for(ChannelId(self.id.0), member.user.id);
-
permissions.remove(perms);
Ok(permissions.is_empty())
@@ -321,10 +319,8 @@ impl Guild {
}
}}
- let role = {
- try!(rest::create_role(self.id.0))
- };
- let map = f(EditRole::default()).0.build();
+ let role = try!(rest::create_role(self.id.0));
+ let map = f(EditRole::new(&role)).0.build();
rest::edit_role(self.id.0, role.id.0, map)
}
@@ -348,7 +344,7 @@ impl Guild {
public_channels
};
- missing!(map, Guild {
+ Ok(Guild {
afk_channel_id: try!(opt(&mut map, "afk_channel_id", ChannelId::decode)),
afk_timeout: req!(try!(remove(&mut map, "afk_timeout")).as_u64()),
channels: public_channels,
@@ -557,7 +553,7 @@ impl Guild {
/// Returns the formatted URL of the guild's icon, if one exists.
pub fn icon_url(&self) -> Option<String> {
self.icon.as_ref().map(|icon|
- format!(cdn_concat!("/icons/{}/{}.jpg"), self.id, icon))
+ format!(cdn!("/icons/{}/{}.jpg"), self.id, icon))
}
/// Checks if the guild is 'large'. A guild is considered large if it has
diff --git a/src/model/user.rs b/src/model/user.rs
index 4201bd2..d7ea416 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -1,5 +1,5 @@
use std::fmt;
-use super::utils::{into_map, into_string, remove, warn_field};
+use super::utils::{into_map, into_string, remove};
use super::{
CurrentUser,
FriendSourceFlags,
@@ -29,7 +29,7 @@ impl CurrentUser {
/// Returns the formatted URL of the user's icon, if one exists.
pub fn avatar_url(&self) -> Option<String> {
self.avatar.as_ref().map(|av|
- format!(cdn_concat!("/avatars/{}/{}.jpg"), self.id, av))
+ format!(cdn!("/avatars/{}/{}.jpg"), self.id, av))
}
}
@@ -37,7 +37,7 @@ impl User {
/// Returns the formatted URL of the user's icon, if one exists.
pub fn avatar_url(&self) -> Option<String> {
self.avatar.as_ref().map(|av|
- format!(cdn_concat!("/avatars/{}/{}.jpg"), self.id, av))
+ format!(cdn!("/avatars/{}/{}.jpg"), self.id, av))
}
/// Retrieves the time that this user was created at.
@@ -166,7 +166,7 @@ impl UserSettings {
return Ok(None);
}
- missing!(map, UserSettings {
+ Ok(UserSettings {
convert_emoticons: req!(try!(remove(&mut map, "convert_emoticons")).as_bool()),
enable_tts_command: req!(try!(remove(&mut map, "enable_tts_command")).as_bool()),
friend_source_flags: try!(remove(&mut map, "friend_source_flags").and_then(FriendSourceFlags::decode)),
diff --git a/src/model/utils.rs b/src/model/utils.rs
index 0611a9f..9b4f6e4 100644
--- a/src/model/utils.rs
+++ b/src/model/utils.rs
@@ -25,19 +25,6 @@ use ::client::CACHE;
use ::ext::cache::ChannelRef;
#[macro_escape]
-macro_rules! missing {
- (@ $name:expr, $json:ident, $value:expr) => {
- (Ok($value), warn_field($name, $json)).0
- };
- ($json:ident, $ty:ident $(::$ext:ident)* ( $($value:expr),*$(,)* ) ) => {
- (Ok($ty$(::$ext)* ( $($value),* )), warn_field(stringify!($ty$(::$ext)*), $json)).0
- };
- ($json:ident, $ty:ident $(::$ext:ident)* { $($name:ident: $value:expr),*$(,)* } ) => {
- (Ok($ty$(::$ext)* { $($name: $value),* }), warn_field(stringify!($ty$(::$ext)*), $json)).0
- };
-}
-
-#[macro_escape]
macro_rules! req {
($opt:expr) => {
try!($opt.ok_or(Error::Decode(concat!("Type mismatch in model:",
@@ -253,7 +240,7 @@ pub fn opt<T, F: FnOnce(Value) -> Result<T>>(map: &mut BTreeMap<String, Value>,
}
}
-pub fn parse_discriminator(value: Value) -> Result<u16> {
+pub fn decode_discriminator(value: Value) -> Result<u16> {
match value {
Value::I64(v) => Ok(v as u16),
Value::U64(v) => Ok(v as u16),
@@ -303,9 +290,3 @@ pub fn user_has_perms(channel_id: ChannelId,
Ok(permissions.is_empty())
}
-
-pub fn warn_field(name: &str, map: BTreeMap<String, Value>) {
- if !map.is_empty() {
- debug!("Unhandled keys: {} has {:?}", name, Value::Object(map))
- }
-}
diff --git a/src/model/voice.rs b/src/model/voice.rs
index 61035c6..8b13789 100644
--- a/src/model/voice.rs
+++ b/src/model/voice.rs
@@ -1,92 +1 @@
-use super::utils::{into_map, into_string, remove, warn_field};
-use super::UserId;
-use ::constants::VoiceOpCode;
-use ::internal::prelude::*;
-use ::utils::decode_array;
-#[derive(Clone, Copy, Debug)]
-pub struct VoiceHeartbeat {
- pub heartbeat_interval: u64,
-}
-
-#[derive(Clone, Debug)]
-pub struct VoiceHello {
- pub heartbeat_interval: u64,
- pub ip: String,
- pub modes: Vec<String>,
- pub port: u16,
- pub ssrc: u32,
-}
-
-#[derive(Clone, Debug)]
-pub struct VoiceReady {
- pub mode: String,
- pub secret_key: Vec<u8>,
-}
-
-#[derive(Clone, Copy, Debug)]
-pub struct VoiceSpeaking {
- pub speaking: bool,
- pub ssrc: u32,
- pub user_id: UserId,
-}
-
-#[derive(Clone, Debug)]
-pub enum VoiceEvent {
- Heartbeat(VoiceHeartbeat),
- Hello(VoiceHello),
- Ready(VoiceReady),
- Speaking(VoiceSpeaking),
- KeepAlive,
- Unknown(VoiceOpCode, Value)
-}
-
-impl VoiceEvent {
- pub fn decode(value: Value) -> Result<VoiceEvent> {
- let mut value = try!(into_map(value));
- let op = req!(try!(remove(&mut value, "op")).as_u64());
- let mut map = try!(remove(&mut value, "d").and_then(into_map));
-
- let opcode = try!(VoiceOpCode::from_num(op)
- .ok_or(Error::Client(ClientError::InvalidOpCode)));
-
- match opcode {
- VoiceOpCode::Heartbeat => {
- missing!(map, VoiceEvent::Heartbeat(VoiceHeartbeat {
- heartbeat_interval: req!(try!(remove(&mut map, "heartbeat_interval")).as_u64()),
- }))
- },
- VoiceOpCode::Hello => {
- missing!(map, VoiceEvent::Hello(VoiceHello {
- heartbeat_interval: req!(try!(remove(&mut map, "heartbeat_interval"))
- .as_u64()),
- ip: try!(remove(&mut map, "ip").and_then(into_string)),
- modes: try!(decode_array(try!(remove(&mut map, "modes")),
- into_string)),
- port: req!(try!(remove(&mut map, "port"))
- .as_u64()) as u16,
- ssrc: req!(try!(remove(&mut map, "ssrc"))
- .as_u64()) as u32,
- }))
- },
- VoiceOpCode::KeepAlive => Ok(VoiceEvent::KeepAlive),
- VoiceOpCode::SessionDescription => {
- missing!(map, VoiceEvent::Ready(VoiceReady {
- mode: try!(remove(&mut map, "mode")
- .and_then(into_string)),
- secret_key: try!(decode_array(try!(remove(&mut map, "secret_key")),
- |v| Ok(req!(v.as_u64()) as u8)
- )),
- }))
- },
- VoiceOpCode::Speaking => {
- missing!(map, VoiceEvent::Speaking(VoiceSpeaking {
- speaking: req!(try!(remove(&mut map, "speaking")).as_bool()),
- ssrc: req!(try!(remove(&mut map, "ssrc")).as_u64()) as u32,
- user_id: try!(remove(&mut map, "user_id").and_then(UserId::decode)),
- }))
- }
- other => Ok(VoiceEvent::Unknown(other, Value::Object(map))),
- }
- }
-}
diff --git a/src/utils/builder/create_embed.rs b/src/utils/builder/create_embed.rs
index 0b0322c..369784f 100644
--- a/src/utils/builder/create_embed.rs
+++ b/src/utils/builder/create_embed.rs
@@ -349,39 +349,3 @@ impl Default for CreateEmbedThumbnail {
CreateEmbedThumbnail(ObjectBuilder::new())
}
}
-
-/// A builder to create a fake [`Embed`] object's video, for use with the
-/// [`CreateEmbed::video`] method.
-///
-/// Requires that you specify a [`url`].
-///
-/// [`Embed`]: ../../model/struct.Embed.html
-/// [`CreateEmbed::video`]: struct.CreateEmbed.html#method.video
-/// [`url`]: #method.url
-pub struct CreateEmbedVideo(pub ObjectBuilder);
-
-impl CreateEmbedVideo {
- /// Set the height of the video, in pixels.
- pub fn height(self, height: u64) -> Self {
- CreateEmbedVideo(self.0.insert("height", height))
- }
-
- /// Set the source URL of the video.
- ///
- /// _Must_ be specified.
- pub fn url(self, url: &str) -> Self {
- CreateEmbedVideo(self.0.insert("url", url))
- }
-
- /// Set the width of the video, in pixels.
- pub fn width(self, width: &str) -> Self {
- CreateEmbedVideo(self.0.insert("width", width))
- }
-}
-
-impl Default for CreateEmbedVideo {
- /// Creates a builder with no default values.
- fn default() -> CreateEmbedVideo {
- CreateEmbedVideo(ObjectBuilder::new())
- }
-}
diff --git a/src/utils/builder/mod.rs b/src/utils/builder/mod.rs
index bc8a20d..497d309 100644
--- a/src/utils/builder/mod.rs
+++ b/src/utils/builder/mod.rs
@@ -23,7 +23,6 @@ pub use self::create_embed::{
CreateEmbedField,
CreateEmbedImage,
CreateEmbedThumbnail,
- CreateEmbedVideo,
};
pub use self::create_invite::CreateInvite;
pub use self::create_message::CreateMessage;
diff --git a/src/utils/macros.rs b/src/utils/macros.rs
index d9026af..e8f74dd 100644
--- a/src/utils/macros.rs
+++ b/src/utils/macros.rs
@@ -19,11 +19,11 @@ macro_rules! request {
($route:expr, $method:ident, $url:expr) => {{
let client = HyperClient::new();
try!(request($route, || client
- .$method(api_concat!($url))))
+ .$method(api!($url))))
}};
}
-macro_rules! cdn_concat {
+macro_rules! cdn {
($e:expr) => {
concat!("https://cdn.discordapp.com", $e)
}
@@ -37,12 +37,7 @@ macro_rules! api {
};
}
-macro_rules! api_concat {
- ($e:expr) => {
- concat!("https://discordapp.com/api/v6", $e)
- }
-}
-macro_rules! status_concat {
+macro_rules! status {
($e:expr) => {
concat!("https://status.discordapp.com/api/v2", $e)
}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 0c154dd..aa97f4a 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -21,60 +21,6 @@ use ::internal::prelude::*;
pub use self::message_builder::MessageBuilder;
-macro_rules! cdn_concat {
- ($e:expr) => {
- concat!("https://cdn.discordapp.com", $e)
- }
-}
-macro_rules! api {
- ($e:expr) => {
- concat!("https://discordapp.com/api/v6", $e)
- };
- ($e:expr, $($rest:tt)*) => {
- format!(api!($e), $($rest)*)
- };
-}
-
-macro_rules! api_concat {
- ($e:expr) => {
- concat!("https://discordapp.com/api/v6", $e)
- }
-}
-macro_rules! status_concat {
- ($e:expr) => {
- concat!("https://status.discordapp.com/api/v2", $e)
- }
-}
-
-macro_rules! map_nums {
- ($item:ident; $($entry:ident $value:expr,)*) => {
- impl $item {
- #[allow(dead_code)]
- pub fn num(&self) -> u64 {
- match *self {
- $($item::$entry => $value,)*
- }
- }
-
- #[allow(dead_code)]
- pub fn from_num(num: u64) -> Option<Self> {
- match num {
- $($value => Some($item::$entry),)*
- _ => None,
- }
- }
-
- #[allow(dead_code)]
- fn decode(value: Value) -> Result<Self> {
- value.as_u64().and_then(Self::from_num).ok_or(Error::Decode(
- concat!("Expected valid ", stringify!($item)),
- value
- ))
- }
- }
- }
-}
-
#[doc(hidden)]
pub fn decode_array<T, F: Fn(Value) -> Result<T>>(value: Value, f: F) -> Result<Vec<T>> {
into_array(value).and_then(|x| x.into_iter().map(f).collect())