This commit is contained in:
Oupson 2021-03-17 23:26:43 +01:00
parent f0a95356d4
commit afab95f45d
7 changed files with 279 additions and 224 deletions

View File

@ -7,20 +7,21 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features] [features]
music = ["serenity/voice"] music = ["serenity/voice", "songbird"]
[dependencies] [dependencies]
serenity = "0.9" serenity = "0.10"
toml = "0.5" toml = "0.5"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
reqwest = "0.10" reqwest = "0.10"
rand = "0.7" rand = "0.7"
lazy_static = "1.4" lazy_static = "1.4"
async-trait = "0.1" async-trait = "0.1"
tokio = { version = "0.2", features = ["full"] } tokio = { version = "1.0", features = ["full"] }
futures = "0.3" futures = "0.3"
chrono = "0.4" chrono = "0.4"
serde_json = "1.0" serde_json = "1.0"
log = "0.4" log = "0.4"
log4rs = "0.13" log4rs = "0.13"
ctrlc = "3.1" ctrlc = "3.1"
songbird = { version = "0.1.0", features = ["driver"], optional = true }

View File

@ -1,3 +1,4 @@
use log::debug;
use serenity::{ use serenity::{
framework::standard::{ framework::standard::{
macros::{command, group}, macros::{command, group},
@ -5,11 +6,13 @@ use serenity::{
}, },
model::prelude::*, model::prelude::*,
prelude::*, prelude::*,
http::CacheHttp,
}; };
use log::debug;
use crate::data::GuildOptionsKey;
#[group] #[group]
#[commands(ban, kick)] #[commands(ban, kick, ghost_pings)]
pub struct Admin; pub struct Admin;
#[command] #[command]
@ -93,5 +96,38 @@ async fn ban(ctx: &Context, msg: &Message) -> CommandResult {
} }
} }
} }
Ok(())
}
#[command]
#[description = ""]
#[only_in(guilds)]
#[required_permissions("KICK_MEMBERS")]
async fn ghost_pings(ctx: &Context, msg: &Message) -> CommandResult {
let data = ctx.data.read().await;
let guilds_options = data
.get::<GuildOptionsKey>()
.expect("Expected NonKickGuildsContainer in TypeMap.");
if let Some(guild) = guilds_options.get(&msg.guild_id.unwrap()) {
let mut message = String::from("\x60\x60\x60");
for ping in &guild.last_ghost_pings {
let sender = ctx
.http()
.get_user(ping.sender)
.await
.map(|u| u.name)
.unwrap_or_else(|_| String::from("Unkown"));
message += &format!("{} : {:?}\n", sender, ping.roles.iter().map(|r| format!("<!@{}>", r)))
}
message += "\x60\x60\x60";
crate::api::send_reply(ctx, msg, message).await?;
}
Ok(()) Ok(())
} }

View File

@ -1,18 +1,30 @@
use crate::{api, data::ShardManagerContainer}; use crate::{api, data::ShardManagerContainer};
use futures::StreamExt; use futures::StreamExt;
use log::error; use log::error;
use rand::prelude::IteratorRandom;
use serenity::{ use serenity::{
client::bridge::gateway::ShardId, client::bridge::gateway::ShardId,
framework::standard::{ framework::standard::{
macros::{command, group}, macros::{command, group},
ArgError, Args, CommandResult, ArgError, Args, CommandResult,
}, },
http::CacheHttp,
model::prelude::*, model::prelude::*,
prelude::*, prelude::*,
}; };
#[group] #[group]
#[commands(error, image, infos, invite, latency, longcode, older, ping)] #[commands(
error,
image,
infos,
invite,
latency,
longcode,
older,
ping,
random_mute
)]
pub struct General; pub struct General;
#[command] #[command]
@ -271,6 +283,34 @@ async fn _image(ctx: &Context, msg: &Message, mut args: Args) -> crate::commands
Ok(()) Ok(())
} }
#[command]
#[required_permissions(ADMINISTRATOR)]
async fn random_mute(ctx: &Context, msg: &Message) -> CommandResult {
if let Some(guild) = msg.guild_id {
let mut members = guild.members(&ctx, Some(1000), None).await?;
let mut m: usize = rand::random::<usize>() % members.len();
while members[m].permissions(&ctx).await.unwrap().administrator() || members[m].user.bot {
m = rand::random::<usize>() % members.len();
}
let guild = ctx.http().get_guild(msg.guild_id.unwrap().0).await?;
let role = match guild.role_by_name("mute") {
Some(role) => Ok(role.id),
None => Err(tokio::io::Error::new(
tokio::io::ErrorKind::Other,
"Unkown role",
)),
}?;
members[m].add_role(&ctx.http, role).await?;
api::send_reply(ctx, msg, format!("{} was choosen by the roulette of the mute !", members[m].mention())).await?;
}
Ok(())
}
// TODO JSON FILE // TODO JSON FILE
enum Image { enum Image {
HackerMan(), HackerMan(),

View File

@ -1,22 +1,17 @@
use crate::data::{GuildOptions, GuildOptionsKey}; use crate::data::{GuildOptions, GuildOptionsKey};
use log::{error, info}; use log::{error, info};
use serenity::{ use serenity::{
client::{bridge::voice::ClientVoiceManager, Context}, client::{Context},
framework::standard::{ framework::standard::{
macros::{command, group}, macros::{command, group},
Args, CommandResult, Args, CommandResult,
}, },
model::{channel::Message, guild::PartialMember, id::GuildId, misc::Mentionable}, model::{channel::Message, guild::PartialMember, id::GuildId, misc::Mentionable},
prelude::*, prelude::*,
voice, Result as SerenityResult, Result as SerenityResult,
}; };
use std::sync::Arc; use std::sync::Arc;
pub(crate) struct VoiceManager;
impl TypeMapKey for VoiceManager {
type Value = Arc<Mutex<ClientVoiceManager>>;
}
#[group] #[group]
#[commands(join, leave, play, stop)] #[commands(join, leave, play, stop)]
@ -28,7 +23,7 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
let guild = match msg.guild(&ctx.cache).await { let guild = match msg.guild(&ctx.cache).await {
Some(guild) => guild, Some(guild) => guild,
None => { None => {
check_msg(msg.channel_id.say(&ctx.http, "DMs not supported").await); msg.channel_id.say(&ctx.http, "DMs not supported").await;
return Ok(()); return Ok(());
} }
@ -39,11 +34,9 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
} else { } else {
false false
} { } {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error, you cant play music") .say(&ctx.http, "Error, you cant play music")
.await, .await;
);
return Ok(()); return Ok(());
} }
@ -57,33 +50,25 @@ async fn join(ctx: &Context, msg: &Message) -> CommandResult {
let connect_to = match channel_id { let connect_to = match channel_id {
Some(channel) => channel, Some(channel) => channel,
None => { None => {
check_msg(msg.reply(ctx, "Not in a voice channel").await); msg.reply(ctx, "Not in a voice channel").await;
return Ok(()); return Ok(());
} }
}; };
let manager_lock = ctx let manager = songbird::get(ctx).await
.data .expect("Songbird Voice client placed in at initialisation.").clone();
.read()
.await
.get::<VoiceManager>()
.cloned()
.expect("Expected VoiceManager in TypeMap.");
let mut manager = manager_lock.lock().await;
if manager.join(guild_id, connect_to).is_some() { if manager.join(guild_id, connect_to).await.1.is_ok() {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, &format!("Joined {}", connect_to.mention())) .say(&ctx.http, &format!("Joined {}", connect_to.mention()))
.await, .await;
);
} else { } else {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error joining the channel") .say(&ctx.http, "Error joining the channel")
.await, .await;
);
} }
Ok(()) Ok(())
@ -99,7 +84,7 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
{ {
Some(id) => id, Some(id) => id,
None => { None => {
check_msg(msg.channel_id.say(&ctx.http, "DMs not supported").await); msg.channel_id.say(&ctx.http, "DMs not supported").await;
return Ok(()); return Ok(());
} }
@ -110,32 +95,26 @@ async fn leave(ctx: &Context, msg: &Message) -> CommandResult {
} else { } else {
false false
} { } {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error, you cant play music") .say(&ctx.http, "Error, you cant play music")
.await, .await;
);
return Ok(()); return Ok(());
} }
let manager_lock = ctx let manager = songbird::get(ctx).await
.data .expect("Songbird Voice client placed in at initialisation.").clone();
.read()
.await
.get::<VoiceManager>()
.cloned()
.expect("Expected VoiceManager in TypeMap.");
let mut manager = manager_lock.lock().await;
if let Some(handler) = manager.get_mut(guild_id) { let has_handler = manager.get(guild_id).is_some();
handler.stop();
manager.remove(guild_id);
check_msg(msg.channel_id.say(&ctx.http, "Left voice channel").await);
} else {
check_msg(msg.reply(ctx, "Not in a voice channel").await);
}
if has_handler {
if let Err(e) = manager.remove(guild_id).await {
msg.channel_id.say(&ctx.http, format!("Failed: {:?}", e)).await;
}
msg.channel_id.say(&ctx.http, "Left voice channel").await;
} else {
msg.reply(ctx, "Not in a voice channel").await;
}
Ok(()) Ok(())
} }
@ -145,22 +124,20 @@ async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let url = match args.single::<String>() { let url = match args.single::<String>() {
Ok(url) => url, Ok(url) => url,
Err(_) => { Err(_) => {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Must provide a URL to a video or audio") .say(&ctx.http, "Must provide a URL to a video or audio")
.await, .await;
);
return Ok(()); return Ok(());
} }
}; };
if !url.starts_with("http") { if !url.starts_with("http") {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Must provide a valid URL") .say(&ctx.http, "Must provide a valid URL")
.await, .await;
);
return Ok(()); return Ok(());
} }
@ -168,11 +145,10 @@ async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
let guild_id = match ctx.cache.guild_channel(msg.channel_id).await { let guild_id = match ctx.cache.guild_channel(msg.channel_id).await {
Some(channel) => channel.guild_id, Some(channel) => channel.guild_id,
None => { None => {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error finding channel info") .say(&ctx.http, "Error finding channel info")
.await, .await;
);
return Ok(()); return Ok(());
} }
@ -183,45 +159,36 @@ async fn play(ctx: &Context, msg: &Message, mut args: Args) -> CommandResult {
} else { } else {
false false
} { } {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error, you cant play music") .say(&ctx.http, "Error, you cant play music")
.await, .await;
);
return Ok(()); return Ok(());
} }
let manager_lock = ctx let manager = songbird::get(ctx).await
.data .expect("Songbird Voice client placed in at initialisation.").clone();
.read()
.await
.get::<VoiceManager>()
.cloned()
.expect("Expected VoiceManager in TypeMap.");
let mut manager = manager_lock.lock().await;
if let Some(handler) = manager.get_mut(guild_id) { if let Some(handler_lock) = manager.get(guild_id) {
let source = match voice::ytdl(&url).await { let mut handler = handler_lock.lock().await;
Ok(source) => source,
Err(why) => { let source = match songbird::ytdl(&url).await {
error!("Err starting source: {:?}", why); Ok(source) => source,
Err(why) => {
check_msg(msg.channel_id.say(&ctx.http, "Error sourcing ffmpeg").await); error!("Err starting source: {:?}", why);
return Ok(()); msg.channel_id.say(&ctx.http, "Error sourcing ffmpeg").await;
}
}; return Ok(());
handler.stop(); },
handler.play(source); };
check_msg(msg.channel_id.say(&ctx.http, "Playing song").await); handler.play_source(source);
} else {
check_msg( msg.channel_id.say(&ctx.http, "Playing song").await;
msg.channel_id } else {
.say(&ctx.http, "Not in a voice channel to play in") msg.channel_id.say(&ctx.http, "Not in a voice channel to play in").await;
.await, }
);
}
Ok(()) Ok(())
} }
@ -232,11 +199,10 @@ async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
let guild_id = match ctx.cache.guild_channel(msg.channel_id).await { let guild_id = match ctx.cache.guild_channel(msg.channel_id).await {
Some(channel) => channel.guild_id, Some(channel) => channel.guild_id,
None => { None => {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error finding channel info") .say(&ctx.http, "Error finding channel info")
.await, .await;
);
return Ok(()); return Ok(());
} }
@ -247,51 +213,35 @@ async fn stop(ctx: &Context, msg: &Message) -> CommandResult {
} else { } else {
false false
} { } {
check_msg(
msg.channel_id msg.channel_id
.say(&ctx.http, "Error, you cant play music") .say(&ctx.http, "Error, you cant play music")
.await, .await;
);
return Ok(()); return Ok(());
} }
let manager_lock = ctx
.data
.read()
.await
.get::<VoiceManager>()
.cloned()
.expect("Expected VoiceManager in TypeMap.");
let mut manager = manager_lock.lock().await;
if let Some(handler) = manager.get_mut(guild_id) { let manager = songbird::get(ctx).await
handler.stop(); .expect("Songbird Voice client placed in at initialisation.").clone();
if let Some(handler) = manager.get(guild_id) {
check_msg(msg.channel_id.say(&ctx.http, "Stopping song").await); let mut handler = handler.lock().await;
} else { handler.stop();
check_msg(
msg.channel_id msg.channel_id.say(&ctx.http, "Stopping").await;
.say(&ctx.http, "Not in a voice channel to play in") } else {
.await, msg.reply(ctx, "Not in a voice channel").await;
); }
}
Ok(()) Ok(())
} }
/// Checks that a message successfully sent; if not, then logs why to stderr.
fn check_msg(result: SerenityResult<Message>) {
if let Err(why) = result {
error!("Error sending message: {:?}", why);
}
}
async fn is_mute( async fn is_mute(
ctx: &Context, ctx: &Context,
member: &PartialMember, member: &PartialMember,
guild_id: GuildId, guild_id: GuildId,
) -> tokio::io::Result<bool> { ) -> tokio::io::Result<bool> {
let mut data = ctx.data.write().await; let mut data = ctx.data.write().await;
let data = data let data = data
.get_mut::<GuildOptionsKey>() .get_mut::<GuildOptionsKey>()

View File

@ -1,8 +1,8 @@
use crate::{ use crate::{
api, commands, api,
data::{BulletsContainer, GuildOptions, GuildOptionsKey}, data::{GuildOptions, GuildOptionsKey},
}; };
use log::{debug, error, trace}; use log::{debug, error};
use rand::Rng; use rand::Rng;
use serenity::{ use serenity::{
framework::standard::{ framework::standard::{
@ -16,7 +16,7 @@ use serenity::{
#[group] #[group]
#[default_command(shot)] #[default_command(shot)]
#[prefix("roulette")] #[prefix("roulette")]
#[commands(reload, shot, check, kick, disable_kick)] #[commands(shot, kick, disable_kick)]
struct Roulette; struct Roulette;
#[command] #[command]
@ -30,83 +30,21 @@ async fn shot(ctx: &Context, msg: &Message, args: Args) -> CommandResult {
} else { } else {
api::send_reply(&ctx, &msg, format!("Click ! Reloading")).await?; api::send_reply(&ctx, &msg, format!("Click ! Reloading")).await?;
} }
} else if let Err(e) = api::send_reply( } else {
ctx, api::send_reply(
msg, ctx,
format!("Error : {} is not a valid argument", args.message()), msg,
) format!("Error : {} is not a valid argument", args.message()),
.await )
{
error!("Error : {:?}", e);
}
Ok(())
}
#[command]
#[description = "Reload"]
#[bucket = "roulette"]
async fn reload(ctx: &Context, msg: &Message) -> CommandResult {
if let Err(e) = _reload(ctx, msg).await {
error!("{}", e);
}
Ok(())
}
async fn _reload(ctx: &Context, msg: &Message) -> commands::Result<()> {
let mut data = ctx.data.write().await;
let bullets_map = data
.get_mut::<BulletsContainer>()
.expect("Expected CommandCounter in TypeMap.");
bullets_map.insert(msg.author.id.0, (5, rand::thread_rng().gen_range(0, 6)));
msg.react(ctx, ReactionType::Unicode(String::from("")))
.await?; .await?;
Ok(())
}
#[command]
#[description = "If you use that, you are a coward"]
async fn check(ctx: &Context, msg: &Message) -> CommandResult {
let mut data = ctx.data.write().await;
let bullets_map = data
.get_mut::<BulletsContainer>()
.expect("Expected CommandCounter in TypeMap.");
let bullets = bullets_map
.entry(msg.author.id.0)
.or_insert((5, rand::thread_rng().gen_range(0, 6)));
msg.channel_id.say(ctx, format!("Because you are a little shit, you open your barrel and you see that the bullet was at the {} position", bullet_to_str(bullets.1 + 1))).await?;
debug!("Bullets Map : {:?}", bullets_map);
Ok(())
}
fn bullet_to_str<'m>(nbr: u8) -> &'m str {
match nbr {
1 => "first",
2 => "second",
3 => "third",
4 => "fourth",
5 => "fifth",
6 => "sixth",
_ => unimplemented!(),
} }
Ok(())
} }
#[command] #[command]
#[description = "DO IT"] #[description = "DO IT"]
#[only_in(guilds)] #[only_in(guilds)]
async fn kick(ctx: &Context, msg: &Message) -> CommandResult { async fn kick(ctx: &Context, msg: &Message) -> CommandResult {
if msg.author.bot {
if let Err(e) =
api::send_reply(ctx, msg, "Error, this command cannot be used by a bot").await
{
error!("Error in kick : {:?}", e);
}
} else if let Err(e) = _kick(ctx, msg).await {
error!("Error in kick : {:?}", e);
}
Ok(())
}
async fn _kick(ctx: &Context, msg: &Message) -> CommandResult {
if let Some(guild_id) = &msg.guild_id { if let Some(guild_id) = &msg.guild_id {
let mut data = ctx.data.write().await; let mut data = ctx.data.write().await;
let guilds_options = data let guilds_options = data
@ -122,15 +60,14 @@ async fn _kick(ctx: &Context, msg: &Message) -> CommandResult {
) )
.await?; .await?;
} else { } else {
let bullets_map = data if rand::thread_rng().gen_range(0, 6) == 0 {
.get_mut::<BulletsContainer>()
.expect("Expected CommandCounter in TypeMap.");
let bullets = bullets_map
.entry(msg.author.id.0)
.or_insert((5, rand::thread_rng().gen_range(0, 6)));
if bullets.0 == bullets.1 {
api::send_reply(ctx, &msg, "💥").await?; api::send_reply(ctx, &msg, "💥").await?;
*bullets = (5, rand::thread_rng().gen_range(0, 6));
msg.author
.create_dm_channel(&ctx)
.await?
.send_message(&ctx.http, |m| m.content("<:cheh:780736245675982909>"))
.await?;
guild_id guild_id
.member(&ctx.http, &msg.author) .member(&ctx.http, &msg.author)
@ -138,15 +75,8 @@ async fn _kick(ctx: &Context, msg: &Message) -> CommandResult {
.kick_with_reason(&ctx.http, "You loose at the roulette") .kick_with_reason(&ctx.http, "You loose at the roulette")
.await?; .await?;
} else { } else {
*bullets = (bullets.0 - 1, bullets.1); api::send_reply(&ctx, &msg, format!("Click ! Reloading")).await?;
api::send_reply(
&ctx,
&msg,
format!("Click ! bullets remaining : {}", bullets.0 + 1),
)
.await?;
} }
debug!("Bullets Map : {:?}", bullets_map);
} }
} }
Ok(()) Ok(())

View File

@ -1,7 +1,10 @@
use log::error; use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serenity::{ use serenity::{
model::prelude::{GuildId, RoleId}, model::{
channel::Message,
prelude::{GuildId, RoleId, UserId},
},
prelude::TypeMapKey, prelude::TypeMapKey,
}; };
use std::{ use std::{
@ -22,6 +25,8 @@ pub(crate) struct GuildOptions {
#[serde(skip_serializing)] #[serde(skip_serializing)]
pub(crate) mute_id: Option<RoleId>, pub(crate) mute_id: Option<RoleId>,
pub(crate) roulette_options: RouletteOptions, pub(crate) roulette_options: RouletteOptions,
pub(crate) last_ghost_pings: Vec<GhostPing>,
pub(crate) mutes : Vec<(UserId, u64)>,
} }
impl GuildOptions { impl GuildOptions {
@ -118,6 +123,29 @@ impl GuildOptions {
} }
} }
} }
pub(crate) fn insert_or_ignore(&mut self, message: Message) {
let time = message.timestamp.timestamp_millis();
let mut i = 0;
while i < self.last_ghost_pings.len() {
if time > self.last_ghost_pings[i].time {
break;
}
i += 1;
}
log::debug!("u {}", i);
if i != 15 {
log::debug!("u {}", i);
self.last_ghost_pings.insert(i, message.into());
}
if self.last_ghost_pings.len() == 16 {
self.last_ghost_pings.remove(15);
}
}
} }
impl Default for GuildOptions { impl Default for GuildOptions {
@ -126,6 +154,8 @@ impl Default for GuildOptions {
roulette_options: RouletteOptions::default(), roulette_options: RouletteOptions::default(),
guild_id: None, guild_id: None,
mute_id: None, mute_id: None,
last_ghost_pings: Vec::new(),
mutes: Vec::new()
} }
} }
} }
@ -157,3 +187,22 @@ pub(crate) struct GuildOptionsKey;
impl TypeMapKey for GuildOptionsKey { impl TypeMapKey for GuildOptionsKey {
type Value = HashMap<GuildId, GuildOptions>; type Value = HashMap<GuildId, GuildOptions>;
} }
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct GhostPing {
pub(crate) sender: u64,
pub(crate) channel: u64,
pub(crate) roles: Vec<RoleId>,
pub(crate) time: i64,
}
impl From<Message> for GhostPing {
fn from(message: Message) -> Self {
Self {
sender: *message.author.id.as_u64(),
channel: *message.channel_id.as_u64(),
roles: message.mention_roles,
time: message.timestamp.timestamp_millis(),
}
}
}

View File

@ -14,7 +14,7 @@ use serenity::{
Args, CommandError, CommandGroup, CommandResult, DispatchError, HelpOptions, Args, CommandError, CommandGroup, CommandResult, DispatchError, HelpOptions,
StandardFramework, StandardFramework,
}, },
http::Http, http::{CacheHttp, Http},
model::prelude::*, model::prelude::*,
prelude::*, prelude::*,
}; };
@ -27,9 +27,10 @@ use std::{
time::Duration, time::Duration,
}; };
use tokio::{fs::File, io::AsyncWriteExt}; use tokio::{fs::File, io::AsyncWriteExt};
use songbird::SerenityInit;
#[cfg(feature = "music")] #[cfg(feature = "music")]
use crate::commands::music::{VoiceManager, MUSIC_GROUP}; use crate::commands::music::{MUSIC_GROUP};
mod api; mod api;
mod commands; mod commands;
@ -131,6 +132,7 @@ async fn main() -> IoResult<()> {
let mut client = Client::builder(&token) let mut client = Client::builder(&token)
.event_handler(Messages {}) .event_handler(Messages {})
.framework(framework) .framework(framework)
.register_songbird()
.await .await
.unwrap(); .unwrap();
@ -138,10 +140,10 @@ async fn main() -> IoResult<()> {
let mut data = client.data.write().await; let mut data = client.data.write().await;
data.insert::<BulletsContainer>(HashMap::default()); data.insert::<BulletsContainer>(HashMap::default());
data.insert::<ShardManagerContainer>(Arc::clone(&client.shard_manager)); data.insert::<ShardManagerContainer>(Arc::clone(&client.shard_manager));
#[cfg(feature = "music")] /*#[cfg(feature = "music")]
{ {
data.insert::<VoiceManager>(std::sync::Arc::clone(&client.voice_manager)); data.insert::<VoiceManager>(std::sync::Arc::clone(&client.voice_manager.unwrap()));
} }*/
data.insert::<GuildOptionsKey>({ data.insert::<GuildOptionsKey>({
let options = GuildOptions::load_from_dir("./data/guilds_options").unwrap_or_default(); let options = GuildOptions::load_from_dir("./data/guilds_options").unwrap_or_default();
@ -215,6 +217,10 @@ impl EventHandler for Messages {
async fn ready(&self, ctx: Context, ready: Ready) { async fn ready(&self, ctx: Context, ready: Ready) {
info!("{} connected to discord", ready.user.name); info!("{} connected to discord", ready.user.name);
if let Some(cache) = ctx.cache() {
cache.set_max_messages(10).await; // TODO CONFIG
}
ctx.set_presence(Some(Activity::listening("?")), OnlineStatus::Online) ctx.set_presence(Some(Activity::listening("?")), OnlineStatus::Online)
.await; .await;
@ -225,7 +231,7 @@ impl EventHandler for Messages {
ctx_clone ctx_clone
.set_presence(Some(act), OnlineStatus::Online) .set_presence(Some(act), OnlineStatus::Online)
.await; .await;
tokio::time::delay_for(delay).await; tokio::time::sleep(delay).await;
} }
} }
@ -242,6 +248,49 @@ impl EventHandler for Messages {
async fn unknown(&self, _ctx: Context, name: String, raw: Value) { async fn unknown(&self, _ctx: Context, name: String, raw: Value) {
debug!("Unknown event : {}, {:?}", name, raw); debug!("Unknown event : {}, {:?}", name, raw);
} }
async fn message_delete(
&self,
ctx: Context,
channel_id: ChannelId,
deleted_message_id: MessageId,
_guild_id: Option<GuildId>
) {
let message = ctx
.cache()
.unwrap()
.message(channel_id, deleted_message_id)
.await;
log::debug!("Deletted message : {:?}", message.as_ref().map(|m| &m.content));
if let Some(message) = message {
if let Some(guild_id) = message.guild_id {
if !message.mention_roles.is_empty() {
let mut data = ctx.data.write().await;
let guilds_options = data.get_mut::<GuildOptionsKey>().unwrap();
let entry = guilds_options
.entry(guild_id)
.or_insert_with(|| GuildOptions::default().set_guild_id(guild_id));
entry.insert_or_ignore(message);
log::debug!("{:?}", entry.last_ghost_pings);
}
}
}
}
async fn message_update(
&self,
_ctx: Context,
old_if_available: Option<Message>,
new: Option<Message>,
_event: MessageUpdateEvent,
) {
log::debug!("update : {:?} vs {:?}", old_if_available, new);
}
} }
async fn download_to_log(attachment: Attachment) -> commands::Result<()> { async fn download_to_log(attachment: Attachment) -> commands::Result<()> {