mirror of
https://github.com/natsukagami/youmubot.git
synced 2025-04-18 16:28:55 +00:00
Announcer Trait (#9)
This commit is contained in:
parent
a17e9c6d1d
commit
7d49edb1fe
3 changed files with 92 additions and 1 deletions
84
youmubot/src/commands/announcer.rs
Normal file
84
youmubot/src/commands/announcer.rs
Normal 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);
|
||||
})
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use serenity::{
|
|||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
mod announcer;
|
||||
mod args;
|
||||
|
||||
pub mod admin;
|
||||
|
@ -17,6 +18,8 @@ pub use admin::ADMIN_GROUP;
|
|||
pub use community::COMMUNITY_GROUP;
|
||||
pub use fun::FUN_GROUP;
|
||||
|
||||
pub use announcer::Announcer;
|
||||
|
||||
// A help command
|
||||
#[help]
|
||||
pub fn help(
|
||||
|
|
|
@ -5,7 +5,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|||
use serenity::{
|
||||
client::Client,
|
||||
framework::standard::CommandError as Error,
|
||||
model::id::{GuildId, RoleId, UserId},
|
||||
model::id::{ChannelId, GuildId, RoleId, UserId},
|
||||
prelude::*,
|
||||
};
|
||||
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.
|
||||
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();
|
||||
SoftBans::insert_into(&mut *data, &path.join("soft_bans.ron"))?;
|
||||
AnnouncerChannels::insert_into(&mut *data, &path.join("announcers.yaml"))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue