Added better timezone support and added confirm_event

+ Times are now read in and displayed as a configured timezone
+ Added `confirm_event` to preview the event message before posting
master
Joey Hines 2020-04-23 19:45:02 -05:00
parent b654d0b167
commit 3eda40dcc0
7 changed files with 214 additions and 62 deletions

72
Cargo.lock generated
View File

@ -5,6 +5,14 @@ name = "adler32"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aho-corasick"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "aho-corasick"
version = "0.7.10"
@ -123,6 +131,15 @@ dependencies = [
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "chrono-tz"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"parse-zoneinfo 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "clap"
version = "2.33.0"
@ -426,6 +443,7 @@ name = "hype_bot"
version = "0.1.0"
dependencies = [
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono-tz 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
"config 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
"diesel 1.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
@ -757,6 +775,14 @@ dependencies = [
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "parse-zoneinfo"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
@ -868,6 +894,18 @@ name = "redox_syscall"
version = "0.1.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "regex"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "1.3.7"
@ -879,6 +917,14 @@ dependencies = [
"thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ucd-util 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.6.17"
@ -1196,6 +1242,14 @@ dependencies = [
"unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "1.0.1"
@ -1316,6 +1370,11 @@ name = "typenum"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ucd-util"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "unicase"
version = "2.6.0"
@ -1378,6 +1437,11 @@ name = "utf-8"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utf8-ranges"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "uwl"
version = "0.6.0"
@ -1561,6 +1625,7 @@ dependencies = [
[metadata]
"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2"
"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
"checksum aho-corasick 0.7.10 (registry+https://github.com/rust-lang/crates.io-index)" = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
@ -1578,6 +1643,7 @@ dependencies = [
"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
"checksum chrono-tz 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa1878c18b5b01b9978d5f130fe366d434022004d12fb87c182e8459b427c4a3"
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum command_attr 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c27d6155f93d880b6379d93ddc9b2417b3b69b715360c5f25525e4576338a381"
@ -1649,6 +1715,7 @@ dependencies = [
"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de"
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
"checksum parse-zoneinfo 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ee19a3656dadae35a33467f9714f1228dd34766dbe49e10e656b5296867aea"
"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
"checksum pin-project 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6f6a7f5eee6292c559c793430c55c00aea9d3b3d1905e855806ca4d7253426a2"
"checksum pin-project-internal 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "8988430ce790d8682672117bc06dda364c0be32d3abd738234f19f3240bad99a"
@ -1665,7 +1732,9 @@ dependencies = [
"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84"
"checksum regex 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384"
"checksum regex 1.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a6020f034922e3194c711b82a627453881bc4682166cabb07134a10c26ba7692"
"checksum regex-syntax 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7d707a4fa2637f2dca2ef9fd02225ec7661fe01a53623c1e6515b6916511f7a7"
"checksum regex-syntax 0.6.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae"
"checksum reqwest 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b81e49ddec5109a9dcfc5f2a317ff53377c915e9ae9d4f2fb50914b85614e2"
"checksum ring 0.16.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1ba5a8ec64ee89a76c98c549af81ff14813df09c3e6dc4766c3856da48597a0c"
@ -1699,6 +1768,7 @@ dependencies = [
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum syn 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865"
"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
@ -1712,6 +1782,7 @@ dependencies = [
"checksum tungstenite 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8a0c2bd5aeb7dcd2bb32e472c8872759308495e5eccc942e929a513cd8d36110"
"checksum typemap 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
"checksum typenum 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33"
"checksum ucd-util 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236"
"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4"
@ -1721,6 +1792,7 @@ dependencies = [
"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb"
"checksum utf-8 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
"checksum utf8-ranges 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba"
"checksum uwl 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f4bf03e0ca70d626ecc4ba6b0763b934b6f2976e8c744088bb3c1d646fbb1ad0"
"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168"
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"

View File

@ -12,6 +12,7 @@ serde = "1.0.106"
serde_derive = "1.0.104"
config = "0.9"
chrono = "0.4.11"
chrono-tz = "0.4"
diesel = { version = "1.4.0", features = ["mysql", "chrono"] }
diesel_migrations = "1.4.0"

View File

@ -19,4 +19,6 @@ prefix = "~"
event_channel = 0
# Permissions to use the bot
event_roles = 0
# Timezone to display events
event_timezone = "America/New_York"
```

View File

@ -2,7 +2,6 @@ pub mod schema;
pub mod models;
use diesel::prelude::*;
use chrono::NaiveDateTime;
use models::{Event, NewEvent};
pub fn establish_connection(database_url: String) -> MysqlConnection {
@ -10,22 +9,13 @@ pub fn establish_connection(database_url: String) -> MysqlConnection {
.expect(&format!("Error connecting to {}", database_url))
}
pub fn insert_event(databse_url: String, event_name: &str, event_desc: &str,
event_time: &NaiveDateTime, message_id: &str, thumbnail_link: &str) -> Event {
pub fn insert_event(databse_url: String, new_event: &NewEvent) -> Event {
use schema::events::dsl::{id, events};
let new_event = NewEvent {
event_name,
event_desc,
event_time,
message_id,
thumbnail_link,
};
let connection = establish_connection(databse_url);
diesel::insert_into(events)
.values(&new_event)
.values(new_event)
.execute(&connection)
.expect("Error saving event");

View File

@ -13,10 +13,10 @@ pub struct Event {
#[derive(Insertable)]
#[table_name="events"]
pub struct NewEvent<'a> {
pub event_name: &'a str,
pub event_desc: &'a str,
pub event_time: &'a NaiveDateTime,
pub message_id: &'a str,
pub thumbnail_link: &'a str,
pub struct NewEvent {
pub event_name: String,
pub event_desc: String,
pub event_time: NaiveDateTime,
pub message_id: String,
pub thumbnail_link: String,
}

View File

@ -8,7 +8,8 @@ pub struct HypeBotConfig {
pub discord_key: String,
pub prefix: String,
pub event_channel: u64,
pub event_roles: Vec<String>,
pub event_roles: Vec<u64>,
pub event_timezone: String,
}
impl HypeBotConfig {

View File

@ -7,7 +7,7 @@ extern crate diesel_migrations;
extern crate serde;
use serenity::client::Client;
use serenity::model::channel::Message;
use serenity::model::channel::{Message};
use serenity::prelude::{EventHandler, Context};
use serenity::utils::{content_safe, ContentSafeOptions, Colour};
use serenity::model::gateway::Ready;
@ -15,8 +15,11 @@ use serenity::framework::standard::StandardFramework;
use serenity::framework::standard::CommandResult;
use serenity::framework::standard::macros::{command, group,};
use serenity::framework::standard::Args;
use serenity::prelude::TypeMapKey;
use serenity::model::error::Error;
use clap::{Arg, App};
use chrono::{DateTime, Utc};
use chrono::{DateTime, Utc, NaiveDateTime, Datelike, Timelike, TimeZone};
use chrono_tz::Tz;
use std::process::exit;
mod hypebot_config;
@ -24,10 +27,11 @@ mod database;
use database::*;
use hypebot_config::HypeBotConfig;
use crate::database::models::NewEvent;
/// Event commands group
#[group]
#[commands(create_event)]
#[commands(create_event, confirm_event)]
struct EventCommands;
/// Handler for Discord events
@ -40,8 +44,17 @@ impl EventHandler for Handler {
}
}
embed_migrations!("migrations/");
/// Struct for storing drafted events
struct DraftEvent {
pub event: NewEvent,
pub creator_id: u64
}
impl TypeMapKey for DraftEvent {
type Value = DraftEvent;
}
embed_migrations!("migrations/");
fn main() {
// Initialize arg parser
let mut app = App::new("Hype Bot")
@ -83,6 +96,16 @@ fn main() {
{
let mut data = client.data.write();
data.insert::<HypeBotConfig>(cfg);
data.insert::<DraftEvent>(DraftEvent {
event: NewEvent {
message_id: String::new(),
event_time: Utc::now().naive_utc(),
event_name: String::new(),
event_desc: String::new(),
thumbnail_link: String::new(),
},
creator_id: 0
});
}
// Start bot
@ -97,60 +120,123 @@ fn main() {
}
}
#[command]
/// Creates an event and announce it
fn create_event (ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
// Open config
fn send_event_msg(ctx: &Context, channel_id: u64, event: &NewEvent) -> CommandResult {
let data = ctx.data.read();
let config = data.get::<HypeBotConfig>().unwrap();
let channel = ctx.http.get_channel(channel_id)?;
// Parse args
let event_name = args.single::<String>()?.replace("\"", "");
let date_string = args.single::<String>()?.replace("\"", "");
let description = args.single::<String>()?.replace("\"", "");
let thumbnail_link = match args.single::<String>() {
Ok(link) => link,
Err(_) => config.default_thumbnail_link.clone(),
};
// Parse date
let date = DateTime::parse_from_str(date_string.as_str(),
"%H:%M %z %Y-%m-%d").unwrap();
let date = DateTime::<Utc>::from(date);
// Clean channel, role, and everyone pings
let settings = ContentSafeOptions::default()
.clean_channel(true)
.clean_role(true)
.clean_everyone(true)
.display_as_member_from(msg.guild_id.unwrap());
let description = content_safe(&ctx.cache, description, &settings);
let channel = ctx.http.get_channel(config.event_channel)?;
let tz: Tz = config.event_timezone.parse()?;
let utc_time = DateTime::<Utc>::from_utc(event.event_time.clone(), Utc);
let native_time = utc_time.with_timezone(&tz);
// Send message
let msg = channel.id().send_message(&ctx, |m| {
m.embed(|e| {
e.title(event_name.as_str())
e.title(event.event_name.clone())
.color(Colour::PURPLE)
.description(format!("**{}**\n{}", date.format("%A, %B %d @ %I:%M %P %t %Z"), description))
.thumbnail(&thumbnail_link)
.description(format!("**{}**\n{}", native_time.format("%A, %B %d @ %I:%M %P %t %Z"), event.event_desc))
.thumbnail(event.thumbnail_link.clone())
.footer(|f| { f.text("Local Event Time") })
.timestamp(date.to_rfc3339())
.timestamp(utc_time.to_rfc3339())
})
})?;
// Add reacts
msg.react(&ctx, "\u{2705}")?;
msg.react(&ctx, "\u{274C}")?;
msg.react(ctx, "\u{2705}")?;
msg.react(ctx, "\u{274C}")?;
// Insert event into the database
insert_event(config.db_url.clone(), event_name.as_str(),
description.as_str(), &date.naive_utc(),
format!("{}", msg.id.0).as_str(),
thumbnail_link.as_str());
Ok(())
}
#[command]
fn confirm_event(ctx: &mut Context, msg: &Message, _args: Args) -> CommandResult {
let data = ctx.data.read();
let config = data.get::<HypeBotConfig>().unwrap();
let draft_event = match data.get::<DraftEvent>() {
Some(draft_event) => Ok(draft_event),
None => Err(Error::ItemMissing)
}?;
let new_event = &draft_event.event;
if draft_event.creator_id == msg.author.id.0 {
send_event_msg(ctx, config.event_channel, new_event)?;
// Insert event into the database
insert_event(config.db_url.clone(), new_event);
msg.reply(&ctx, "Event posted!")?;
}
else {
msg.reply(&ctx, format!("You do not have a pending event!"))?;
}
Ok(())
}
#[command]
/// Creates an event and announce it
fn create_event (ctx: &mut Context, msg: &Message, mut args: Args) -> CommandResult {
let mut event_name;
let mut description;
let thumbnail_link;
let date;
{
// Open config
let data = ctx.data.read();
let config = data.get::<HypeBotConfig>().unwrap();
// Parse args
event_name = args.single::<String>()?.replace("\"", "");
let date_string = args.single::<String>()?.replace("\"", "");
description = args.single::<String>()?.replace("\"", "");
thumbnail_link = match args.single::<String>() {
Ok(link) => link.replace("<", "").replace(">", ""),
Err(_) => config.default_thumbnail_link.clone(),
};
// Parse date
let tz: Tz = config.event_timezone.parse()?;
let input_date = NaiveDateTime::parse_from_str(date_string.as_str(), "%I:%M%p %Y-%m-%d")?;
let input_date = tz.ymd(input_date.date().year(), input_date.date().month(), input_date.date().day())
.and_hms(input_date.time().hour(), input_date.time().minute(), input_date.time().second());
date = input_date.with_timezone(&Utc);
// Clean channel, role, and everyone pings
let settings = ContentSafeOptions::default()
.clean_role(true)
.clean_here(true)
.clean_user(true)
.clean_everyone(true)
.display_as_member_from(msg.guild_id.unwrap());
description = content_safe(&ctx.cache, description, &settings);
event_name = content_safe(&ctx.cache, event_name, &settings);
}
{
let mut data = ctx.data.write();
let mut draft_event = match data.get_mut::<DraftEvent>() {
Some(event) => event,
None => {
println!("Error");
panic!("Can't get write lock")
}
};
draft_event.event.event_name = event_name;
draft_event.event.event_desc = description;
draft_event.event.thumbnail_link = thumbnail_link;
draft_event.event.message_id = String::new();
draft_event.event.event_time = date.naive_utc();
draft_event.creator_id = msg.author.id.0;
}
{
let data = ctx.data.read();
msg.reply(&ctx, format!("Draft message, use the `confirm_event` command to confirm it."))?;
send_event_msg(ctx, msg.channel_id.0, &data.get::<DraftEvent>().unwrap().event)?;
}
Ok(())
}