aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client/dispatch.rs57
-rw-r--r--src/client/event_store.rs1
-rw-r--r--src/client/mod.rs26
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