aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAustin Hellyer <[email protected]>2016-12-05 07:46:22 -0800
committerAustin Hellyer <[email protected]>2016-12-05 07:46:22 -0800
commitccb9d16e5dbe965e5a604e1cb402cd3bc7de0df5 (patch)
treeb7eed1952ae14f215074452c3e3d1bc081a89b0a
parentAdd more Context docs+permission requirements (diff)
downloadserenity-ccb9d16e5dbe965e5a604e1cb402cd3bc7de0df5.tar.xz
serenity-ccb9d16e5dbe965e5a604e1cb402cd3bc7de0df5.zip
Add a ShareMap across contexts
The context now exposes, through the Client, a `data` field, which can be accessed safely across contexts. This allows for a custom "shared state" without the need for (ab)using lazy-static.rs. Refer to example 06 for an example on how to use shared data.
-rw-r--r--Cargo.toml1
-rw-r--r--examples/06_command_framework/Cargo.toml3
-rw-r--r--examples/06_command_framework/src/main.rs44
-rw-r--r--src/client/context.rs8
-rw-r--r--src/client/dispatch.rs99
-rw-r--r--src/client/mod.rs35
-rw-r--r--src/lib.rs1
7 files changed, 147 insertions, 44 deletions
diff --git a/Cargo.toml b/Cargo.toml
index be64dfd..78caa80 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -21,6 +21,7 @@ lazy_static = "0.2"
log = "0.3"
serde_json = "0.8"
time = "0.1"
+typemap = "0.3"
websocket = "0.17"
[dependencies.cookie]
diff --git a/examples/06_command_framework/Cargo.toml b/examples/06_command_framework/Cargo.toml
index 481dd6f..a73f940 100644
--- a/examples/06_command_framework/Cargo.toml
+++ b/examples/06_command_framework/Cargo.toml
@@ -3,6 +3,9 @@ name = "06_command_framework"
version = "0.1.0"
authors = ["my name <[email protected]>"]
+[dependencies]
+typemap = "0.3"
+
[dependencies.serenity]
features = ["framework", "methods"]
version = "0.1"
diff --git a/examples/06_command_framework/src/main.rs b/examples/06_command_framework/src/main.rs
index b399dff..0943d81 100644
--- a/examples/06_command_framework/src/main.rs
+++ b/examples/06_command_framework/src/main.rs
@@ -10,11 +10,21 @@
#[macro_use]
extern crate serenity;
+extern crate typemap;
use serenity::client::Context;
use serenity::Client;
use serenity::model::Message;
+use std::collections::HashMap;
use std::env;
+use std::fmt::Write;
+use typemap::Key;
+
+struct CommandCounter;
+
+impl Key for CommandCounter {
+ type Value = HashMap<String, u64>;
+}
fn main() {
// Configure the client with your Discord bot token in the environment.
@@ -22,6 +32,11 @@ fn main() {
.expect("Expected a token in the environment");
let mut client = Client::login_bot(&token);
+ {
+ let mut data = client.data.lock().unwrap();
+ data.insert::<CommandCounter>(HashMap::default());
+ }
+
client.on_ready(|_context, ready| {
println!("{} is connected!", ready.user.name);
});
@@ -51,16 +66,26 @@ fn main() {
// You can not use this to determine whether a command should be
// executed. Instead, `set_check` is provided to give you this
// functionality.
- .before(|_context, message, command_name| {
+ .before(|context, message, command_name| {
println!("Got command '{}' by user '{}'",
command_name,
message.author.name);
+
+ // Increment the number of times this command has been run once. If
+ // the command's name does not exist in the counter, add a default
+ // value of 0.
+ let mut data = context.data.lock().unwrap();
+ let counter = data.get_mut::<CommandCounter>().unwrap();
+ let entry = counter.entry(command_name.clone()).or_insert(0);
+ *entry += 1;
})
// Very similar to `before`, except this will be called directly _after_
// command execution.
.after(|_context, _message, command_name| {
println!("Processed command '{}'", command_name)
})
+ .on("commands", commands)
+ .set_check("commands", owner_check)
.on("ping", ping_command)
.set_check("ping", owner_check) // Ensure only the owner can run this
.on("emoji cat", cat_command)
@@ -84,12 +109,27 @@ fn main() {
// This may bring more features available for commands in the future. See the
// "multiply" command below for some of the power that the `command!` macro can
// bring.
-command!(cat_command(context, _msg, _arg) {
+command!(cat_command(context, _msg, _args) {
if let Err(why) = context.say(":cat:") {
println!("Eror sending message: {:?}", why);
}
});
+command!(commands(context, _msg, _args) {
+ let mut contents = "Commands used:\n".to_owned();
+
+ let data = context.data.lock().unwrap();
+ let counter = data.get::<CommandCounter>().unwrap();
+
+ for (k, v) in counter {
+ let _ = write!(contents, "- {name}: {amount}\n", name=k, amount=v);
+ }
+
+ if let Err(why) = context.say(&contents) {
+ println!("Error sending message: {:?}", why);
+ }
+});
+
fn dog_command(context: &Context, _msg: &Message, _args: Vec<String>) {
if let Err(why) = context.say(":dog:") {
println!("Error sending message: {:?}", why);
diff --git a/src/client/context.rs b/src/client/context.rs
index 4fca519..af90447 100644
--- a/src/client/context.rs
+++ b/src/client/context.rs
@@ -6,6 +6,7 @@ use std::sync::{Arc, Mutex};
use super::gateway::Shard;
use super::rest::{self, GuildPagination};
use super::login_type::LoginType;
+use typemap::ShareMap;
use ::utils::builder::{
CreateEmbed,
CreateInvite,
@@ -82,6 +83,11 @@ pub struct Context {
///
/// [`on_message`]: struct.Client.html#method.on_message
pub channel_id: Option<ChannelId>,
+ /// A clone of [`Client::data`]. Refer to its documentation for more
+ /// information.
+ ///
+ /// [`Client::data`]: struct.Client.html#method.data
+ pub data: Arc<Mutex<ShareMap>>,
/// The associated shard which dispatched the event handler.
///
/// Note that if you are sharding, in relevant terms, this is the shard
@@ -101,9 +107,11 @@ impl Context {
#[doc(hidden)]
pub fn new(channel_id: Option<ChannelId>,
shard: Arc<Mutex<Shard>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType) -> Context {
Context {
channel_id: channel_id,
+ data: data,
shard: shard,
login_type: login_type,
}
diff --git a/src/client/dispatch.rs b/src/client/dispatch.rs
index 44832cc..3207a0a 100644
--- a/src/client/dispatch.rs
+++ b/src/client/dispatch.rs
@@ -4,6 +4,7 @@ use super::event_store::EventStore;
use super::login_type::LoginType;
use super::Context;
use super::gateway::Shard;
+use typemap::ShareMap;
use ::model::event::Event;
use ::model::{ChannelId, Message};
@@ -38,20 +39,23 @@ macro_rules! update {
fn context(channel_id: Option<ChannelId>,
conn: Arc<Mutex<Shard>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType) -> Context {
- Context::new(channel_id, conn, login_type)
+ Context::new(channel_id, conn, data, login_type)
}
#[cfg(feature="framework")]
pub fn dispatch(event: Event,
conn: Arc<Mutex<Shard>>,
framework: Arc<Mutex<Framework>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType,
event_store: Arc<RwLock<EventStore>>) {
match event {
Event::MessageCreate(event) => {
let context = context(Some(event.message.channel_id),
conn,
+ data,
login_type);
let mut framework = framework.lock().expect("framework poisoned");
@@ -65,7 +69,7 @@ pub fn dispatch(event: Event,
dispatch_message(context, event.message, event_store);
}
},
- other => handle_event(other, conn, login_type, event_store),
+ other => handle_event(other, conn, data, login_type, event_store),
}
}
@@ -73,17 +77,19 @@ pub fn dispatch(event: Event,
pub fn dispatch(event: Event,
conn: Arc<Mutex<Shard>>,
login_type: LoginType,
+ data: Arc<Mutex<ShareMap>>,
event_store: Arc<RwLock<EventStore>>) {
match event {
Event::MessageCreate(event) => {
let context = context(Some(event.message.channel_id),
conn,
+ data,
login_type);
dispatch_message(context.clone(),
event.message.clone(),
event_store);
},
- other => handle_event(other, conn, login_type, event_store),
+ other => handle_event(other, conn, data, login_type, event_store),
}
}
@@ -102,6 +108,7 @@ fn dispatch_message(context: Context,
#[allow(cyclomatic_complexity)]
fn handle_event(event: Event,
conn: Arc<Mutex<Shard>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType,
event_store: Arc<RwLock<EventStore>>) {
match event {
@@ -109,7 +116,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_call_create, event_store) {
update!(update_with_call_create, event);
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -121,7 +128,7 @@ fn handle_event(event: Event,
},
Event::CallDelete(event) => {
if let Some(ref handler) = handler!(on_call_delete, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -141,7 +148,7 @@ fn handle_event(event: Event,
},
Event::CallUpdate(event) => {
if let Some(ref handler) = handler!(on_call_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -172,6 +179,7 @@ fn handle_event(event: Event,
update!(update_with_channel_create, event);
let context = context(Some(event.channel.id()),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -185,7 +193,7 @@ fn handle_event(event: Event,
Event::ChannelDelete(event) => {
if let Some(ref handler) = handler!(on_channel_delete, event_store) {
update!(update_with_channel_delete, event);
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -199,6 +207,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_channel_pins_ack, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -211,6 +220,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_channel_pins_update, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -225,6 +235,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_channel_recipient_addition, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -239,6 +250,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_channel_recipient_removal, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -251,6 +263,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_channel_update, event_store) {
let context = context(Some(event.channel.id()),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -275,7 +288,7 @@ fn handle_event(event: Event,
},
Event::FriendSuggestionCreate(event) => {
if let Some(ref handler) = handler!(on_friend_suggestion_create, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -285,7 +298,7 @@ fn handle_event(event: Event,
},
Event::FriendSuggestionDelete(event) => {
if let Some(ref handler) = handler!(on_friend_suggestion_delete, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -295,7 +308,7 @@ fn handle_event(event: Event,
},
Event::GuildBanAdd(event) => {
if let Some(ref handler) = handler!(on_guild_ban_addition, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -305,7 +318,7 @@ fn handle_event(event: Event,
},
Event::GuildBanRemove(event) => {
if let Some(ref handler) = handler!(on_guild_ban_removal, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -317,7 +330,7 @@ fn handle_event(event: Event,
update!(update_with_guild_create, event);
if let Some(ref handler) = handler!(on_guild_create, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -327,7 +340,7 @@ fn handle_event(event: Event,
},
Event::GuildDelete(event) => {
if let Some(ref handler) = handler!(on_guild_delete, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -351,7 +364,7 @@ fn handle_event(event: Event,
update!(update_with_guild_emojis_update, event);
if let Some(ref handler) = handler!(on_guild_emojis_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -361,7 +374,7 @@ fn handle_event(event: Event,
},
Event::GuildIntegrationsUpdate(event) => {
if let Some(ref handler) = handler!(on_guild_integrations_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -373,7 +386,7 @@ fn handle_event(event: Event,
update!(update_with_guild_member_add, event);
if let Some(ref handler) = handler!(on_guild_member_addition, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -383,7 +396,7 @@ fn handle_event(event: Event,
},
Event::GuildMemberRemove(event) => {
if let Some(ref handler) = handler!(on_guild_member_removal, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -405,7 +418,7 @@ fn handle_event(event: Event,
},
Event::GuildMemberUpdate(event) => {
if let Some(ref handler) = handler!(on_guild_member_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -436,7 +449,7 @@ fn handle_event(event: Event,
update!(update_with_guild_members_chunk, event);
if let Some(ref handler) = handler!(on_guild_members_chunk, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -448,7 +461,7 @@ fn handle_event(event: Event,
update!(update_with_guild_role_create, event);
if let Some(ref handler) = handler!(on_guild_role_create, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -458,7 +471,7 @@ fn handle_event(event: Event,
},
Event::GuildRoleDelete(event) => {
if let Some(ref handler) = handler!(on_guild_role_delete, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -480,7 +493,7 @@ fn handle_event(event: Event,
},
Event::GuildRoleUpdate(event) => {
if let Some(ref handler) = handler!(on_guild_role_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -502,7 +515,7 @@ fn handle_event(event: Event,
},
Event::GuildSync(event) => {
if let Some(ref handler) = handler!(on_guild_sync, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -514,7 +527,7 @@ fn handle_event(event: Event,
update!(update_with_guild_unavailable, event);
if let Some(ref handler) = handler!(on_guild_unavailable, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -524,7 +537,7 @@ fn handle_event(event: Event,
},
Event::GuildUpdate(event) => {
if let Some(ref handler) = handler!(on_guild_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -551,6 +564,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_message_ack, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -565,6 +579,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_message_delete_bulk, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -577,6 +592,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_message_delete, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -589,6 +605,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_message_update, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -601,7 +618,7 @@ fn handle_event(event: Event,
update!(update_with_presences_replace, event);
if let Some(handler) = handler!(on_presence_replace, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -613,7 +630,7 @@ fn handle_event(event: Event,
update!(update_with_presence_update, event);
if let Some(handler) = handler!(on_presence_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -625,6 +642,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_reaction_add, event_store) {
let context = context(Some(event.reaction.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -637,6 +655,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_reaction_remove, event_store) {
let context = context(Some(event.reaction.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -649,6 +668,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_reaction_remove_all, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -661,7 +681,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_ready, event_store) {
update!(update_with_ready, event);
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -675,7 +695,7 @@ fn handle_event(event: Event,
update!(update_with_relationship_add, event);
if let Some(ref handler) = handler!(on_relationship_addition, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -687,7 +707,7 @@ fn handle_event(event: Event,
update!(update_with_relationship_remove, event);
if let Some(ref handler) = handler!(on_relationship_removal, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -697,7 +717,7 @@ fn handle_event(event: Event,
},
Event::Resumed(event) => {
if let Some(ref handler) = handler!(on_resume, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -709,6 +729,7 @@ fn handle_event(event: Event,
if let Some(ref handler) = handler!(on_typing_start, event_store) {
let context = context(Some(event.channel_id),
conn,
+ data,
login_type);
let handler = handler.clone();
@@ -719,7 +740,7 @@ fn handle_event(event: Event,
},
Event::Unknown(event) => {
if let Some(ref handler) = handler!(on_unknown, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -729,7 +750,7 @@ fn handle_event(event: Event,
},
Event::UserGuildSettingsUpdate(event) => {
if let Some(ref handler) = handler!(on_user_guild_settings_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -751,7 +772,7 @@ fn handle_event(event: Event,
},
Event::UserNoteUpdate(event) => {
if let Some(ref handler) = handler!(on_note_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -773,7 +794,7 @@ fn handle_event(event: Event,
},
Event::UserSettingsUpdate(event) => {
if let Some(ref handler) = handler!(on_user_settings_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -796,7 +817,7 @@ fn handle_event(event: Event,
},
Event::UserUpdate(event) => {
if let Some(ref handler) = handler!(on_user_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
feature_cache! {{
@@ -818,7 +839,7 @@ fn handle_event(event: Event,
},
Event::VoiceServerUpdate(event) => {
if let Some(ref handler) = handler!(on_voice_server_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -830,7 +851,7 @@ fn handle_event(event: Event,
update!(update_with_voice_state_update, event);
if let Some(ref handler) = handler!(on_voice_state_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
@@ -840,7 +861,7 @@ fn handle_event(event: Event,
},
Event::WebhookUpdate(event) => {
if let Some(ref handler) = handler!(on_webhook_update, event_store) {
- let context = context(None, conn, login_type);
+ let context = context(None, conn, data, login_type);
let handler = handler.clone();
thread::spawn(move || {
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 0369677..cf67b5b 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -42,6 +42,7 @@ use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex, RwLock};
use std::thread;
use std::time::Duration;
+use typemap::ShareMap;
use websocket::client::Receiver;
use websocket::stream::WebSocketStream;
use ::internal::prelude::{Error, Result, Value};
@@ -150,6 +151,23 @@ lazy_static! {
/// [`Event::MessageCreate`]: ../model/event/enum.Event.html#variant.MessageCreate
/// [sharding docs]: gateway/index.html#sharding
pub struct Client {
+ /// A ShareMap which requires types to be Send + Sync. This is a map that
+ /// can be safely shared across contexts.
+ ///
+ /// The purpose of the data field is to be accessible and persistent across
+ /// contexts; that is, data can be modified by one context, and will persist
+ /// through the future and be accessible through other contexts. This is
+ /// useful for anything that should "live" through the program: counters,
+ /// database connections, custom user caches, etc.
+ ///
+ /// In the meaning of a context, this data can be accessed through
+ /// [`Context::data`].
+ ///
+ /// Refer to [example 06] for an example on using the `data` field.
+ ///
+ /// [`Context::data`]: struct.Context.html#method.data
+ /// [example 06]: https://github.com/zeyla/serenity.rs/tree/master/examples/06_command_framework
+ pub data: Arc<Mutex<ShareMap>>,
/// A vector of all active shards that have received their [`Event::Ready`]
/// payload, and have dispatched to [`on_ready`] if an event handler was
/// configured.
@@ -773,18 +791,21 @@ impl Client {
dispatch(Event::Ready(ready),
shard.clone(),
self.framework.clone(),
+ self.data.clone(),
self.login_type,
self.event_store.clone());
} else {
dispatch(Event::Ready(ready),
shard.clone(),
+ self.data.clone(),
self.login_type,
self.event_store.clone());
}}
- let shard_clone = shard.clone();
+ let data_clone = self.data.clone();
let event_store = self.event_store.clone();
let login_type = self.login_type;
+ let shard_clone = shard.clone();
feature_framework! {{
let framework = self.framework.clone();
@@ -792,6 +813,7 @@ impl Client {
thread::spawn(move || {
handle_shard(shard_clone,
framework,
+ data_clone,
login_type,
event_store,
receiver)
@@ -799,6 +821,7 @@ impl Client {
} else {
thread::spawn(move || {
handle_shard(shard_clone,
+ data_clone,
login_type,
event_store,
receiver)
@@ -1125,6 +1148,7 @@ impl Client {
#[cfg(feature="framework")]
fn handle_shard(shard: Arc<Mutex<Shard>>,
framework: Arc<Mutex<Framework>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType,
event_store: Arc<RwLock<EventStore>>,
mut receiver: Receiver<WebSocketStream>) {
@@ -1146,6 +1170,7 @@ fn handle_shard(shard: Arc<Mutex<Shard>>,
dispatch(event,
shard.clone(),
framework.clone(),
+ data.clone(),
login_type,
event_store.clone());
}
@@ -1153,6 +1178,7 @@ fn handle_shard(shard: Arc<Mutex<Shard>>,
#[cfg(not(feature="framework"))]
fn handle_shard(shard: Arc<Mutex<Shard>>,
+ data: Arc<Mutex<ShareMap>>,
login_type: LoginType,
event_store: Arc<RwLock<EventStore>>,
mut receiver: Receiver<WebSocketStream>) {
@@ -1173,6 +1199,7 @@ fn handle_shard(shard: Arc<Mutex<Shard>>,
dispatch(event,
shard.clone(),
+ data.clone(),
login_type,
event_store.clone());
}
@@ -1185,17 +1212,19 @@ fn login(token: &str, login_type: LoginType) -> Client {
feature_framework! {{
Client {
- shards: Vec::default(),
+ data: Arc::new(Mutex::new(ShareMap::custom())),
event_store: Arc::new(RwLock::new(EventStore::default())),
framework: Arc::new(Mutex::new(Framework::default())),
login_type: login_type,
+ shards: Vec::default(),
token: token.to_owned(),
}
} else {
Client {
- shards: Vec::default(),
+ data: Arc::new(Mutex::new(ShareMap::custom())),
event_store: Arc::new(RwLock::new(EventStore::default())),
login_type: login_type,
+ shards: Vec::default(),
token: token.to_owned(),
}
}}
diff --git a/src/lib.rs b/src/lib.rs
index ca4a2fe..29237da 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -145,6 +145,7 @@ extern crate hyper;
extern crate multipart;
extern crate serde_json;
extern crate time;
+extern crate typemap;
extern crate websocket;
#[cfg(feature="voice")]