diff options
| -rw-r--r-- | src/client/dispatch.rs | 57 | ||||
| -rw-r--r-- | src/client/event_store.rs | 1 | ||||
| -rw-r--r-- | src/client/mod.rs | 26 |
3 files changed, 76 insertions, 8 deletions
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs index bbac54a..f617b14 100644 --- a/src/client/dispatch.rs +++ b/src/client/dispatch.rs @@ -1,11 +1,13 @@ use std::sync::{Arc, Mutex, RwLock}; use std::thread; +use std::time; use super::event_store::EventStore; use super::Context; use typemap::ShareMap; use ::gateway::Shard; use ::model::event::Event; -use ::model::Message; +use ::model::{Message, GuildId}; +use chrono::{UTC, Timelike}; #[cfg(feature="framework")] use ::ext::framework::Framework; @@ -58,6 +60,10 @@ macro_rules! update { }; } +macro_rules! now { + () => (UTC::now().time().second() * 1000) +} + fn context(conn: &Arc<Mutex<Shard>>, data: &Arc<Mutex<ShareMap>>) -> Context { Context::new(conn.clone(), data.clone()) @@ -125,6 +131,18 @@ fn handle_event(event: Event, conn: &Arc<Mutex<Shard>>, data: &Arc<Mutex<ShareMap>>, event_store: &Arc<RwLock<EventStore>>) { + let mut last_guild_create_time = now!(); + + let wait_for_guilds = move || -> ::Result<()> { + let unavailable_guilds = CACHE.read().unwrap().unavailable_guilds.len(); + + while unavailable_guilds != 0 && (now!() - last_guild_create_time < 2000) { + thread::sleep(time::Duration::from_millis(500)); + } + + Ok(()) + }; + match event { Event::ChannelCreate(event) => { if let Some(handler) = handler!(on_channel_create, event_store) { @@ -205,6 +223,25 @@ fn handle_event(event: Event, Event::GuildCreate(event) => { update!(update_with_guild_create, event); + last_guild_create_time = now!(); + + #[cfg(feature="cache")] + { + let cache = CACHE.read().unwrap(); + + if cache.unavailable_guilds.len() == 0 { + if let Some(handler) = handler!(on_cached, event_store) { + let context = context(conn, data); + + let guild_amount = cache.guilds.iter() + .map(|(&id, _)| id) + .collect::<Vec<GuildId>>(); + + thread::spawn(move || (handler)(context, guild_amount)); + } + } + } + if let Some(handler) = handler!(on_guild_create, event_store) { let context = context(conn, data); @@ -442,15 +479,19 @@ fn handle_event(event: Event, } }, Event::Ready(event) => { - if let Some(handler) = handler!(on_ready, event_store) { - update!(update_with_ready, event); + update!(update_with_ready, event); - let context = context(conn, data); + last_guild_create_time = now!(); - thread::spawn(move || (handler)(context, event.ready)); - } else { - update!(update_with_ready, event); - } + let _ = wait_for_guilds() + .map(|_| { + if let Some(handler) = handler!(on_ready, event_store) { + + let context = context(conn, data); + + thread::spawn(move || (handler)(context, event.ready)); + } + }); }, Event::Resumed(event) => { if let Some(handler) = handler!(on_resume, event_store) { diff --git a/src/client/event_store.rs b/src/client/event_store.rs index 6c3af57..6732225 100644 --- a/src/client/event_store.rs +++ b/src/client/event_store.rs @@ -29,6 +29,7 @@ use std::sync::RwLock; #[allow(type_complexity)] #[derive(Default)] pub struct EventStore { + pub on_cached: Option<Arc<Fn(Context, Vec<GuildId>) + Send + Sync + 'static>>, pub on_channel_create: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>, pub on_channel_delete: Option<Arc<Fn(Context, Channel) + Send + Sync + 'static>>, pub on_channel_pins_update: Option<Arc<Fn(Context, ChannelPinsUpdateEvent) + Send + Sync + 'static>>, diff --git a/src/client/mod.rs b/src/client/mod.rs index 96160a8..87ebfff 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -575,6 +575,32 @@ impl Client { .on_channel_create = Some(Arc::new(handler)); } + /// Attaches a handle for when all the [`GuildCreate`]s are received; + /// providing all the guilds' id. + /// + /// notes: This requires the cache feature. And that this'll fire when + /// all the guilds from all the shards have been cached. + /// + /// # Examples + /// + /// ```rust,no_run + /// # use serenity::client::Client; + /// # + /// # let mut client = Client::new(""); + /// + /// client.on_cached(|_, guilds| { + /// println!("All the guilds have been cached; and those are: {:?}", guilds); + /// }); + /// ``` + /// + /// [`GuildCreate`]: ../model/event/enum.Event.html#variant.GuildCreate + #[cfg(feature="cache")] + pub fn on_cached<F>(&mut self, handle: F) + where F: Fn(Context, Vec<GuildId>) + Send + Sync + 'static { + self.event_store.write() + .unwrap() + .on_cached = Some(Arc::new(handle)); + } /// Attaches a handler for when a [`ChannelDelete`] is received. /// /// # Examples |