aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/builder/create_embed.rs88
-rw-r--r--src/cache/mod.rs2
-rw-r--r--src/framework/buckets.rs4
-rw-r--r--src/framework/mod.rs6
-rw-r--r--src/gateway/prep.rs6
-rw-r--r--src/gateway/shard.rs4
-rw-r--r--src/http/ratelimiting.rs4
-rw-r--r--src/internal/timer.rs25
-rw-r--r--src/lib.rs2
-rw-r--r--src/model/channel/group.rs3
-rw-r--r--src/model/channel/guild_channel.rs3
-rw-r--r--src/model/channel/message.rs25
-rw-r--r--src/model/channel/private_channel.rs3
-rw-r--r--src/model/event.rs7
-rw-r--r--src/model/guild/member.rs5
-rw-r--r--src/model/guild/mod.rs5
-rw-r--r--src/model/invite.rs5
-rw-r--r--src/model/mod.rs6
-rw-r--r--src/model/user.rs6
19 files changed, 139 insertions, 70 deletions
diff --git a/src/builder/create_embed.rs b/src/builder/create_embed.rs
index 0099936..7b676be 100644
--- a/src/builder/create_embed.rs
+++ b/src/builder/create_embed.rs
@@ -15,9 +15,10 @@
//! [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
//! [here]: https://discordapp.com/developers/docs/resources/channel#embed-object
+use chrono::{DateTime, TimeZone};
use serde_json::Value;
use std::default::Default;
-use time::Tm;
+use std::fmt::Display;
use ::internal::prelude::*;
use ::model::Embed;
@@ -177,26 +178,75 @@ impl CreateEmbed {
/// Set the timestamp.
///
- /// **Note**: This timestamp must be in ISO-8601 format. It must also be
- /// in UTC format.
- ///
- /// # Examples
- ///
/// You may pass a direct string:
///
/// - `2017-01-03T23:00:00`
/// - `2004-06-08T16:04:23`
/// - `2004-06-08T16:04:23`
///
- /// Or a `time::Tm`:
+ /// This timestamp must be in ISO-8601 format. It must also be in UTC format.
///
- /// ```rust,ignore
- /// extern crate time;
+ /// You can also pass anything that implements `chrono::TimeZone`.
///
- /// let now = time::now();
+ /// # Examples
+ ///
+ /// Passing a string timestamp:
///
- /// embed = embed.timestamp(now);
- /// // ...
+ /// ```rust,no_run
+ /// # use serenity::Client;
+ /// #
+ /// # let mut client = Client::login("");
+ /// #
+ /// client.on_message(|_, msg| {
+ /// if msg.content == "~embed" {
+ /// let _ = msg.channel_id.send_message(|m| m
+ /// .embed(|e| e
+ /// .title("hello")
+ /// .timestamp("2004-06-08T16:04:23")));
+ /// }
+ /// });
+ /// ```
+ ///
+ /// Creating a join-log:
+ ///
+ /// Note: this example isn't efficient and is for demonstrative purposes.
+ ///
+ /// ```rust,no_run
+ /// # use serenity::Client;
+ /// #
+ /// # let mut client = Client::login("");
+ /// #
+ /// use serenity::CACHE;
+ ///
+ /// client.on_guild_member_add(|_, guild_id, member| {
+ /// let cache = CACHE.read().unwrap();
+ ///
+ /// if let Some(guild) = cache.guild(guild_id) {
+ /// let guild = guild.read().unwrap();
+ ///
+ /// let channel_search = guild
+ /// .channels
+ /// .values()
+ /// .find(|c| c.read().unwrap().name == "join-log");
+ ///
+ /// if let Some(channel) = channel_search {
+ /// let user = member.user.read().unwrap();
+ ///
+ /// let _ = channel.read().unwrap().send_message(|m| m
+ /// .embed(|e| {
+ /// let mut e = e
+ /// .author(|a| a.icon_url(&user.face()).name(&user.name))
+ /// .title("Member Join");
+ ///
+ /// if let Some(ref joined_at) = member.joined_at {
+ /// e = e.timestamp(joined_at);
+ /// }
+ ///
+ /// e
+ /// }));
+ /// }
+ /// }
+ /// });
/// ```
pub fn timestamp<T: Into<Timestamp>>(mut self, timestamp: T) -> Self {
self.0.insert("timestamp".to_owned(), Value::String(timestamp.into().ts));
@@ -406,10 +456,18 @@ impl From<String> for Timestamp {
}
}
-impl From<Tm> for Timestamp {
- fn from(tm: Tm) -> Self {
+impl<'a> From<&'a str> for Timestamp {
+ fn from(ts: &'a str) -> Self {
+ Timestamp {
+ ts: ts.to_owned(),
+ }
+ }
+}
+
+impl<'a, Tz: TimeZone> From<&'a DateTime<Tz>> for Timestamp where Tz::Offset: Display {
+ fn from(dt: &'a DateTime<Tz>) -> Self {
Timestamp {
- ts: tm.to_utc().rfc3339().to_string(),
+ ts: dt.to_rfc3339(),
}
}
}
diff --git a/src/cache/mod.rs b/src/cache/mod.rs
index 246ca02..98c6648 100644
--- a/src/cache/mod.rs
+++ b/src/cache/mod.rs
@@ -960,7 +960,7 @@ impl Cache {
guild.members.insert(event.user.id, Member {
deaf: false,
guild_id: Some(event.guild_id),
- joined_at: String::default(),
+ joined_at: None,
mute: false,
nick: event.nick.clone(),
roles: event.roles.clone(),
diff --git a/src/framework/buckets.rs b/src/framework/buckets.rs
index eea1253..4f24893 100644
--- a/src/framework/buckets.rs
+++ b/src/framework/buckets.rs
@@ -1,6 +1,6 @@
+use chrono::UTC;
use std::collections::HashMap;
use std::default::Default;
-use time;
#[doc(hidden)]
pub struct Ratelimit {
@@ -33,7 +33,7 @@ pub struct Bucket {
impl Bucket {
pub fn take(&mut self, user_id: u64) -> i64 {
- let time = time::get_time().sec;
+ let time = UTC::now().timestamp();
let user = self.users.entry(user_id)
.or_insert_with(MemberRatelimit::default);
diff --git a/src/framework/mod.rs b/src/framework/mod.rs
index ba0aa36..38615c8 100644
--- a/src/framework/mod.rs
+++ b/src/framework/mod.rs
@@ -591,7 +591,7 @@ impl Framework {
/// ```rust
/// # #[macro_use] extern crate serenity;
/// command!(ping(_ctx, msg) {
- /// msg.channel_id.say("pong!");
+ /// msg.channel_id.say("pong!");
/// });
/// #
/// # fn main() {
@@ -700,7 +700,7 @@ impl Framework {
/// # use serenity::Client;
/// # let mut client = Client::login("token");
/// use serenity::framework::DispatchError::{NotEnoughArguments, TooManyArguments};
- ///
+ ///
/// client.with_framework(|f| f
/// .on_dispatch_error(|ctx, msg, error| {
/// match error {
@@ -711,7 +711,7 @@ impl Framework {
/// msg.channel_id.say(&format!("Max arguments allowed is {}, but got {}.", max, given));
/// }
/// _ => println!("Unhandled dispatch error.")
- /// }
+ /// }
/// }));
/// ```
pub fn on_dispatch_error<F>(mut self, f: F) -> Self
diff --git a/src/gateway/prep.rs b/src/gateway/prep.rs
index 6a415f8..8e04df4 100644
--- a/src/gateway/prep.rs
+++ b/src/gateway/prep.rs
@@ -1,3 +1,4 @@
+use chrono::{Duration, UTC};
use serde_json::Value;
use std::sync::mpsc::{
Receiver as MpscReceiver,
@@ -8,7 +9,6 @@ use std::sync::{Arc, Mutex};
use std::time::{Duration as StdDuration, Instant};
use std::{env, thread};
use super::{GatewayError, GatewayStatus};
-use time::{self, Duration};
use websocket::client::request::Url as RequestUrl;
use websocket::client::{Receiver, Sender};
use websocket::result::WebSocketError as WsError;
@@ -81,7 +81,7 @@ pub fn keepalive(interval: u64,
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;
+ let mut next_tick = UTC::now() + base_interval;
let mut last_sequence = 0;
let mut last_successful = false;
@@ -110,7 +110,7 @@ pub fn keepalive(interval: u64,
}
}
- if time::get_time() >= next_tick {
+ if UTC::now() >= next_tick {
// If the last heartbeat didn't receive an acknowledgement, then
// shutdown and auto-reconnect.
if !*last_ack.lock().unwrap() {
diff --git a/src/gateway/shard.rs b/src/gateway/shard.rs
index 7790cc6..343aa06 100644
--- a/src/gateway/shard.rs
+++ b/src/gateway/shard.rs
@@ -1,3 +1,4 @@
+use chrono::UTC;
use std::io::Write;
use std::net::Shutdown;
use std::sync::mpsc::{self, Sender as MpscSender};
@@ -6,7 +7,6 @@ use std::thread::{self, Builder as ThreadBuilder};
use std::time::{Duration as StdDuration, Instant};
use std::mem;
use super::{GatewayError, GatewayStatus, prep};
-use time;
use websocket::client::{Client as WsClient, Sender, Receiver};
use websocket::message::Message as WsMessage;
use websocket::result::WebSocketError;
@@ -788,7 +788,7 @@ impl Shard {
fn update_presence(&self) {
let (ref game, status, afk) = self.current_presence;
- let now = time::get_time().sec as u64;
+ let now = UTC::now().timestamp() as u64;
let msg = json!({
"op": OpCode::StatusUpdate.num(),
diff --git a/src/http/ratelimiting.rs b/src/http/ratelimiting.rs
index 95318ae..d290dd0 100644
--- a/src/http/ratelimiting.rs
+++ b/src/http/ratelimiting.rs
@@ -40,6 +40,7 @@
//! [Taken from]: https://discordapp.com/developers/docs/topics/rate-limits#rate-limits
#![allow(zero_ptr)]
+use chrono::UTC;
use hyper::client::{RequestBuilder, Response};
use hyper::header::Headers;
use hyper::status::StatusCode;
@@ -48,7 +49,6 @@ use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{i64, str, thread};
use super::{HttpError, LightMethod};
-use time;
use ::internal::prelude::*;
lazy_static! {
@@ -441,7 +441,7 @@ impl RateLimit {
return;
}
- let current_time = time::get_time().sec;
+ let current_time = UTC::now().timestamp();
// The reset was in the past, so we're probably good.
if current_time > self.reset {
diff --git a/src/internal/timer.rs b/src/internal/timer.rs
index cc846b3..677ece1 100644
--- a/src/internal/timer.rs
+++ b/src/internal/timer.rs
@@ -1,9 +1,9 @@
+use chrono::{DateTime, Duration, UTC};
use std::thread;
use std::time::Duration as StdDuration;
-use time::{self, Duration, Timespec};
pub struct Timer {
- due: Timespec,
+ due: DateTime<UTC>,
duration: Duration,
}
@@ -12,25 +12,32 @@ impl Timer {
let duration = Duration::milliseconds(duration_in_ms as i64);
Timer {
- due: time::get_time() + duration,
+ due: UTC::now() + duration,
duration: duration,
}
}
pub fn await(&mut self) {
- let diff = self.due - time::get_time();
+ let due_time = (self.due.timestamp() * 1000) + self.due.timestamp_subsec_millis() as i64;
+ let now_time = {
+ let now = UTC::now();
- if diff > time::Duration::zero() {
- let amount = diff.num_milliseconds() as u64;
+ (now.timestamp() * 1000) + now.timestamp_subsec_millis() as i64
+ };
- thread::sleep(StdDuration::from_millis(amount));
+ if due_time > now_time {
+ let sleep_time = due_time - now_time;
+
+ if sleep_time > 0 {
+ thread::sleep(StdDuration::from_millis(sleep_time as u64));
+ }
}
self.due = self.due + self.duration;
}
pub fn check(&mut self) -> bool {
- if time::get_time() >= self.due {
+ if UTC::now() >= self.due {
self.due = self.due + self.duration;
true
@@ -40,6 +47,6 @@ impl Timer {
}
pub fn reset(&mut self) {
- self.due = time::get_time() + self.duration;
+ self.due = UTC::now() + self.duration;
}
}
diff --git a/src/lib.rs b/src/lib.rs
index f5f695c..8a2e680 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -103,9 +103,9 @@ extern crate serde_json;
extern crate lazy_static;
extern crate base64;
+extern crate chrono;
extern crate flate2;
extern crate serde;
-extern crate time;
#[cfg(feature="voice")]
extern crate byteorder;
diff --git a/src/model/channel/group.rs b/src/model/channel/group.rs
index 25c4690..63efb90 100644
--- a/src/model/channel/group.rs
+++ b/src/model/channel/group.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use ::model::*;
#[cfg(feature="model")]
@@ -26,7 +27,7 @@ pub struct Group {
/// The Id of the last message sent.
pub last_message_id: Option<MessageId>,
/// Timestamp of the latest pinned message.
- pub last_pin_timestamp: Option<String>,
+ pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
/// The name of the group channel.
pub name: Option<String>,
/// The Id of the group owner.
diff --git a/src/model/channel/guild_channel.rs b/src/model/channel/guild_channel.rs
index 8b55d04..5ce7031 100644
--- a/src/model/channel/guild_channel.rs
+++ b/src/model/channel/guild_channel.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use ::model::*;
#[cfg(feature="model")]
@@ -46,7 +47,7 @@ pub struct GuildChannel {
/// The timestamp of the time a pin was most recently made.
///
/// **Note**: This is only available for text channels.
- pub last_pin_timestamp: Option<String>,
+ pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
/// The name of the channel.
pub name: String,
/// Permission overwrites for [`Member`]s and for [`Role`]s.
diff --git a/src/model/channel/message.rs b/src/model/channel/message.rs
index 8b9f0af..612113d 100644
--- a/src/model/channel/message.rs
+++ b/src/model/channel/message.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use ::model::*;
#[cfg(feature="cache")]
@@ -5,8 +6,6 @@ use std::fmt::Write;
#[cfg(feature="model")]
use std::mem;
#[cfg(feature="model")]
-use time;
-#[cfg(feature="model")]
use ::builder::{CreateEmbed, CreateMessage};
#[cfg(feature="model")]
use ::constants;
@@ -33,7 +32,7 @@ pub struct Message {
/// The content of the message.
pub content: String,
/// The timestamp of the last time the message was updated, if it was.
- pub edited_timestamp: Option<String>,
+ pub edited_timestamp: Option<DateTime<FixedOffset>>,
/// Array of embeds sent with the message.
pub embeds: Vec<Embed>,
/// Indicator of the type of message this is, i.e. whether it is a regular
@@ -56,7 +55,7 @@ pub struct Message {
#[serde(default)]
pub reactions: Vec<MessageReaction>,
/// Initial message creation timestamp, calculated from its Id.
- pub timestamp: String,
+ pub timestamp: DateTime<FixedOffset>,
/// Indicator of whether the command is to be played back via
/// text-to-speech.
///
@@ -240,16 +239,14 @@ impl Message {
self.content = format!("{} pinned a message to this channel. See all the pins.", self.author);
},
MessageType::MemberJoin => {
- if let Ok(tm) = time::strptime(&self.timestamp, "%Y-%m-%dT%H:%M:%S") {
- let sec = tm.to_timespec().sec as usize;
- let chosen = constants::JOIN_MESSAGES[sec % constants::JOIN_MESSAGES.len()];
-
- self.content = if chosen.contains("$user") {
- chosen.replace("$user", &self.author.mention())
- } else {
- chosen.to_owned()
- };
- }
+ let sec = self.timestamp.timestamp() as usize;
+ let chosen = constants::JOIN_MESSAGES[sec % constants::JOIN_MESSAGES.len()];
+
+ self.content = if chosen.contains("$user") {
+ chosen.replace("$user", &self.author.mention())
+ } else {
+ chosen.to_owned()
+ };
},
_ => {},
}
diff --git a/src/model/channel/private_channel.rs b/src/model/channel/private_channel.rs
index 7a0ed54..797ba94 100644
--- a/src/model/channel/private_channel.rs
+++ b/src/model/channel/private_channel.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::deserialize_single_recipient;
use ::model::*;
@@ -21,7 +22,7 @@ pub struct PrivateChannel {
/// Timestamp of the last time a [`Message`] was pinned.
///
/// [`Message`]: struct.Message.html
- pub last_pin_timestamp: Option<String>,
+ pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
/// Indicator of the type of channel this is.
///
/// This should always be [`ChannelType::Private`].
diff --git a/src/model/event.rs b/src/model/event.rs
index 6458b77..bbb60c7 100644
--- a/src/model/event.rs
+++ b/src/model/event.rs
@@ -1,5 +1,6 @@
//! All the events this library handles.
+use chrono::{DateTime, FixedOffset};
use serde::de::Error as DeError;
use serde_json::{self, Error as JsonError};
use std::collections::HashMap;
@@ -55,7 +56,7 @@ impl<'de> Deserialize<'de> for ChannelDeleteEvent {
#[derive(Clone, Debug, Deserialize)]
pub struct ChannelPinsUpdateEvent {
pub channel_id: ChannelId,
- pub last_pin_timestamp: Option<String>,
+ pub last_pin_timestamp: Option<DateTime<FixedOffset>>,
}
#[derive(Clone, Debug, Deserialize)]
@@ -278,8 +279,8 @@ pub struct MessageUpdateEvent {
pub nonce: Option<String>,
pub tts: Option<bool>,
pub pinned: Option<bool>,
- pub timestamp: Option<String>,
- pub edited_timestamp: Option<String>,
+ pub timestamp: Option<DateTime<FixedOffset>>,
+ pub edited_timestamp: Option<DateTime<FixedOffset>>,
pub author: Option<User>,
pub mention_everyone: Option<bool>,
pub mentions: Option<Vec<User>>,
diff --git a/src/model/guild/member.rs b/src/model/guild/member.rs
index 99bf67b..0082643 100644
--- a/src/model/guild/member.rs
+++ b/src/model/guild/member.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use std::fmt::{Display, Formatter, Result as FmtResult};
use super::deserialize_sync_user;
use ::model::*;
@@ -23,7 +24,7 @@ pub struct Member {
/// The unique Id of the guild that the member is a part of.
pub guild_id: Option<GuildId>,
/// Timestamp representing the date when the member joined.
- pub joined_at: String,
+ pub joined_at: Option<DateTime<FixedOffset>>,
/// Indicator of whether the member can speak in voice channels.
pub mute: bool,
/// The member's nickname, if present.
@@ -326,7 +327,7 @@ impl Member {
.unwrap()
.members
.values()
- .any(|m| m.user.read().unwrap().id == self.user.read().unwrap().id && m.joined_at == *self.joined_at))
+ .any(|m| m.user.read().unwrap().id == self.user.read().unwrap().id && m.joined_at == self.joined_at))
.map(|guild| guild
.read()
.unwrap()
diff --git a/src/model/guild/mod.rs b/src/model/guild/mod.rs
index 24e1881..a744b2c 100644
--- a/src/model/guild/mod.rs
+++ b/src/model/guild/mod.rs
@@ -14,6 +14,7 @@ pub use self::member::*;
pub use self::partial_guild::*;
pub use self::role::*;
+use chrono::{DateTime, FixedOffset};
use serde::de::Error as DeError;
use serde_json;
use super::utils::*;
@@ -73,7 +74,7 @@ pub struct Guild {
/// that of the default channel (typically `#general`).
pub id: GuildId,
/// The date that the current user joined the guild.
- pub joined_at: String,
+ pub joined_at: DateTime<FixedOffset>,
/// Indicator of whether the guild is considered "large" by Discord.
pub large: bool,
/// The number of members in the guild.
@@ -1149,7 +1150,7 @@ impl<'de> Deserialize<'de> for Guild {
.map_err(DeError::custom)?;
let joined_at = map.remove("joined_at")
.ok_or_else(|| DeError::custom("expected guild joined_at"))
- .and_then(String::deserialize)
+ .and_then(DateTime::deserialize)
.map_err(DeError::custom)?;
let large = map.remove("large")
.ok_or_else(|| DeError::custom("expected guild large"))
diff --git a/src/model/invite.rs b/src/model/invite.rs
index 7b67296..7ff3fd1 100644
--- a/src/model/invite.rs
+++ b/src/model/invite.rs
@@ -1,3 +1,4 @@
+use chrono::{DateTime, FixedOffset};
use super::*;
#[cfg(feature="cache")]
@@ -228,7 +229,7 @@ pub struct RichInvite {
/// The unique code for the invite.
pub code: String,
/// When the invite was created.
- pub created_at: String,
+ pub created_at: DateTime<FixedOffset>,
/// A representation of the minimal amount of information needed about the
/// guild being invited to.
pub guild: InviteGuild,
@@ -302,7 +303,7 @@ impl RichInvite {
/// # name: "foo".to_owned(),
/// # kind: ChannelType::Text,
/// # },
- /// # created_at: "bar".to_owned(),
+ /// # created_at: "2017-01-29T15:35:17.136000+00:00".parse().unwrap(),
/// # guild: InviteGuild {
/// # id: GuildId(2),
/// # icon: None,
diff --git a/src/model/mod.rs b/src/model/mod.rs
index 26c6f42..bc414c7 100644
--- a/src/model/mod.rs
+++ b/src/model/mod.rs
@@ -40,12 +40,12 @@ pub use self::user::*;
pub use self::voice::*;
pub use self::webhook::*;
+use chrono::NaiveDateTime;
use self::utils::*;
use serde::de::Visitor;
use std::collections::HashMap;
use std::fmt::{Formatter, Result as FmtResult};
use std::sync::{Arc, RwLock};
-use time::Timespec;
use ::internal::prelude::*;
#[cfg(feature="utils")]
@@ -63,10 +63,10 @@ macro_rules! id {
impl $name {
/// Retrieves the time that the Id was created at.
- pub fn created_at(&self) -> Timespec {
+ pub fn created_at(&self) -> NaiveDateTime {
let offset = (self.0 >> 22) / 1000;
- Timespec::new(1420070400 + offset as i64, 0)
+ NaiveDateTime::from_timestamp(1420070400 + offset as i64, 0)
}
}
diff --git a/src/model/user.rs b/src/model/user.rs
index e1483d2..ef26ca1 100644
--- a/src/model/user.rs
+++ b/src/model/user.rs
@@ -6,13 +6,13 @@ use ::internal::prelude::*;
use ::model::misc::Mentionable;
#[cfg(feature="model")]
+use chrono::NaiveDateTime;
+#[cfg(feature="model")]
use std::fmt::Write;
#[cfg(feature="model")]
use std::mem;
#[cfg(feature="cache")]
use std::sync::{Arc, RwLock};
-#[cfg(feature="model")]
-use time::Timespec;
#[cfg(feature="cache")]
use ::CACHE;
#[cfg(feature="model")]
@@ -377,7 +377,7 @@ impl User {
/// Retrieves the time that this user was created at.
#[inline]
- pub fn created_at(&self) -> Timespec {
+ pub fn created_at(&self) -> NaiveDateTime {
self.id.created_at()
}