diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/builder/create_embed.rs | 88 | ||||
| -rw-r--r-- | src/cache/mod.rs | 2 | ||||
| -rw-r--r-- | src/framework/buckets.rs | 4 | ||||
| -rw-r--r-- | src/framework/mod.rs | 6 | ||||
| -rw-r--r-- | src/gateway/prep.rs | 6 | ||||
| -rw-r--r-- | src/gateway/shard.rs | 4 | ||||
| -rw-r--r-- | src/http/ratelimiting.rs | 4 | ||||
| -rw-r--r-- | src/internal/timer.rs | 25 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/model/channel/group.rs | 3 | ||||
| -rw-r--r-- | src/model/channel/guild_channel.rs | 3 | ||||
| -rw-r--r-- | src/model/channel/message.rs | 25 | ||||
| -rw-r--r-- | src/model/channel/private_channel.rs | 3 | ||||
| -rw-r--r-- | src/model/event.rs | 7 | ||||
| -rw-r--r-- | src/model/guild/member.rs | 5 | ||||
| -rw-r--r-- | src/model/guild/mod.rs | 5 | ||||
| -rw-r--r-- | src/model/invite.rs | 5 | ||||
| -rw-r--r-- | src/model/mod.rs | 6 | ||||
| -rw-r--r-- | src/model/user.rs | 6 |
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; } } @@ -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() } |