Announcer Trait (#9)

This commit is contained in:
natsukagami 2020-01-18 23:08:38 +00:00 committed by Gitea
parent a17e9c6d1d
commit 7d49edb1fe
3 changed files with 92 additions and 1 deletions

View file

@ -0,0 +1,84 @@
use crate::db::{AnnouncerChannels, DBWriteGuard};
use serenity::{
framework::standard::{CommandError as Error, CommandResult},
http::{CacheHttp, Http},
model::id::{ChannelId, GuildId, UserId},
prelude::ShareMap,
};
use std::{
collections::HashSet,
thread::{spawn, JoinHandle},
};
pub trait Announcer {
fn announcer_key() -> &'static str;
fn send_messages(
c: &Http,
d: &mut ShareMap,
channels: impl Fn(UserId) -> Vec<ChannelId> + Sync,
) -> CommandResult;
fn set_channel(d: &mut ShareMap, guild: GuildId, channel: ChannelId) -> CommandResult {
let mut data: DBWriteGuard<_> = d
.get_mut::<AnnouncerChannels>()
.expect("DB initialized")
.into();
let mut data = data.borrow_mut()?;
data.entry(Self::announcer_key().to_owned())
.or_default()
.insert(guild, channel);
Ok(())
}
fn get_guilds(d: &mut ShareMap) -> Result<Vec<(GuildId, ChannelId)>, Error> {
let data = d
.get::<AnnouncerChannels>()
.expect("DB initialized")
.read(|v| {
v.get(Self::announcer_key())
.map(|m| m.iter().map(|(a, b)| (*a, *b)).collect())
.unwrap_or_else(|| vec![])
})?;
Ok(data)
}
fn announce(c: &Http, d: &mut ShareMap) -> CommandResult {
let guilds: Vec<_> = Self::get_guilds(d)?;
let member_sets = {
let mut v = Vec::with_capacity(guilds.len());
for (guild, channel) in guilds.into_iter() {
let mut s = HashSet::new();
for user in guild
.members_iter(c.as_ref())
.take_while(|u| u.is_ok())
.filter_map(|u| u.ok())
{
s.insert(user.user_id());
}
v.push((s, channel))
}
v
};
Self::send_messages(c.as_ref(), d, |user_id| {
let mut v = Vec::new();
for (members, channel) in member_sets.iter() {
if members.contains(&user_id) {
v.push(*channel);
}
}
v
})?;
Ok(())
}
fn scan(client: &serenity::Client, cooldown: std::time::Duration) -> JoinHandle<()> {
let c = client.cache_and_http.clone();
let data = client.data.clone();
spawn(move || loop {
if let Err(e) = Self::announce(c.http(), &mut *data.write()) {
dbg!(e);
}
std::thread::sleep(cooldown);
})
}
}

View file

@ -7,6 +7,7 @@ use serenity::{
}; };
use std::collections::HashSet; use std::collections::HashSet;
mod announcer;
mod args; mod args;
pub mod admin; pub mod admin;
@ -17,6 +18,8 @@ pub use admin::ADMIN_GROUP;
pub use community::COMMUNITY_GROUP; pub use community::COMMUNITY_GROUP;
pub use fun::FUN_GROUP; pub use fun::FUN_GROUP;
pub use announcer::Announcer;
// A help command // A help command
#[help] #[help]
pub fn help( pub fn help(

View file

@ -5,7 +5,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serenity::{ use serenity::{
client::Client, client::Client,
framework::standard::CommandError as Error, framework::standard::CommandError as Error,
model::id::{GuildId, RoleId, UserId}, model::id::{ChannelId, GuildId, RoleId, UserId},
prelude::*, prelude::*,
}; };
use std::collections::HashMap; use std::collections::HashMap;
@ -32,6 +32,9 @@ where
} }
} }
/// A map from announcer keys to guild IDs and to channels.
pub type AnnouncerChannels = DB<HashMap<String, GuildMap<ChannelId>>>;
/// A list of SoftBans for all servers. /// A list of SoftBans for all servers.
pub type SoftBans = DB<GuildMap<ServerSoftBans>>; pub type SoftBans = DB<GuildMap<ServerSoftBans>>;
@ -43,6 +46,7 @@ pub fn setup_db(client: &mut Client) -> Result<(), Error> {
}); });
let mut data = client.data.write(); let mut data = client.data.write();
SoftBans::insert_into(&mut *data, &path.join("soft_bans.ron"))?; SoftBans::insert_into(&mut *data, &path.join("soft_bans.ron"))?;
AnnouncerChannels::insert_into(&mut *data, &path.join("announcers.yaml"))?;
Ok(()) Ok(())
} }