use serenity::model::id::{GuildId, RoleId}; use serenity::model::prelude::*; use serenity::prelude::*; use serenity::Client; use std::collections::HashMap; use std::fs::File; use std::io::{self, BufRead, BufReader}; #[macro_use] extern crate lazy_static; struct Handler; impl EventHandler for Handler { fn voice_state_update( &self, ctx: Context, guild_id: Option, old: Option, new: VoiceState, ) { if let Some(gid) = guild_id { if let Some(rid) = ROLES_BY_SERVER.get(&gid) { if let Ok(guild) = PartialGuild::get(&ctx.http, gid) { let mut roles = guild .member(&ctx.http, new.user_id) .expect("could not retrieve member") .roles; // user just joined the VC -> add the role if old.is_none() { roles.push(*rid); // user is no longer in VC -> remove the role } else if new.channel_id.is_none() { roles.retain(|r| r != rid); } if let Err(e) = guild.edit_member(&ctx.http, new.user_id, |m| m.roles(roles)) { println!( "Could not edit member {} of guild {}, {}", new.user_id, gid, e ); } } } } } } lazy_static! { static ref ROLES_BY_SERVER: HashMap = { std::env::args() .nth(1) .expect( " Please specify at least one guild-role tuple like `./bot 'guild_id:role_id;guild_id2:role_id2'`", ) .split(';') .map(|s| s.splitn(2, ':')) .map(|mut s| { ( GuildId { 0: s.next().unwrap().parse().unwrap(), }, RoleId { 0: s.next().unwrap().parse().unwrap(), }, ) }) .collect() }; } fn main() { println!("Running with config for {} servers", ROLES_BY_SERVER.len()); let mut client = Client::new(read_token().expect("Could not read secret"), Handler) .expect("Could not create new client."); client.start().expect("Could not start client."); } fn read_token() -> io::Result { let reader = BufReader::new(File::open("secret")?); reader.lines().next().unwrap() }