From 607638b99fef007e97dc9421d96d16d27292f73a Mon Sep 17 00:00:00 2001 From: Oskar Date: Sat, 9 Jul 2022 23:53:23 +0200 Subject: [PATCH] chore(fmt): change to default rustfmt config (#12) --- rustfmt.toml | 16 -- src/logger.rs | 4 +- src/main.rs | 397 ++++++++++++++++++++------------------- src/model/application.rs | 151 ++++++++------- 4 files changed, 288 insertions(+), 280 deletions(-) delete mode 100644 rustfmt.toml diff --git a/rustfmt.toml b/rustfmt.toml deleted file mode 100644 index bce4bbc..0000000 --- a/rustfmt.toml +++ /dev/null @@ -1,16 +0,0 @@ -edition = "2018" -match_block_trailing_comma = true -newline_style = "Unix" -use_field_init_shorthand = true -use_small_heuristics = "Max" -use_try_shorthand = true - -hard_tabs = true -format_code_in_doc_comments = true -group_imports = "StdExternalCrate" -imports_granularity = "Module" -imports_layout = "HorizontalVertical" -match_arm_blocks = true -normalize_comments = true -overflow_delimited_expr = true -struct_lit_single_line = false \ No newline at end of file diff --git a/src/logger.rs b/src/logger.rs index ab3b834..93984d9 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -1,4 +1,4 @@ pub fn init() { - // TODO: log to file - tracing_subscriber::fmt::init(); + // TODO: log to file + tracing_subscriber::fmt::init(); } diff --git a/src/main.rs b/src/main.rs index 2672ad6..967e946 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,240 +19,259 @@ mod model; struct BotConfiguration; impl TypeMapKey for BotConfiguration { - type Value = Arc>; + type Value = Arc>; } pub struct Handler; async fn get_configuration_lock(ctx: &Context) -> Arc> { - ctx.data - .read() - .await - .get::() - .expect("Expected Configuration in TypeMap.") - .clone() + ctx.data + .read() + .await + .get::() + .expect("Expected Configuration in TypeMap.") + .clone() } fn contains_match(regex: &[Regex], text: &str) -> bool { - regex.iter().any(|r| r.is_match(text)) + regex.iter().any(|r| r.is_match(text)) } fn load_configuration() -> Configuration { - Configuration::load().expect("Failed to load configuration") + Configuration::load().expect("Failed to load configuration") } #[async_trait] impl EventHandler for Handler { - async fn interaction_create(&self, ctx: Context, interaction: Interaction) { - debug!("Created an interaction: {:?}", interaction); + async fn interaction_create(&self, ctx: Context, interaction: Interaction) { + debug!("Created an interaction: {:?}", interaction); - if let Interaction::ApplicationCommand(command) = interaction { - let configuration_lock = get_configuration_lock(&ctx).await; - let mut configuration = configuration_lock.write().await; + if let Interaction::ApplicationCommand(command) = interaction { + let configuration_lock = get_configuration_lock(&ctx).await; + let mut configuration = configuration_lock.write().await; - let administrators = &configuration.administrators; - let member = command.member.as_ref().unwrap(); - let user_id = member.user.id.0; - let mut stop_command = false; - let mut permission_granted = false; + let administrators = &configuration.administrators; + let member = command.member.as_ref().unwrap(); + let user_id = member.user.id.0; + let mut stop_command = false; + let mut permission_granted = false; - // check if the user is an administrator - if administrators.users.iter().any(|&id| user_id == id) { - permission_granted = true - } - // check if the user has an administrating role - if !permission_granted - && administrators - .roles - .iter() - .any(|role_id| member.roles.iter().any(|member_role| member_role == role_id)) - { - permission_granted = true - } + // check if the user is an administrator + if administrators.users.iter().any(|&id| user_id == id) { + permission_granted = true + } + // check if the user has an administrating role + if !permission_granted + && administrators.roles.iter().any(|role_id| { + member + .roles + .iter() + .any(|member_role| member_role == role_id) + }) + { + permission_granted = true + } - let content = if permission_granted { - match command.data.name.as_str() { - "reload" => { - debug!("{:?} reloaded the configuration.", command.user); + let content = if permission_granted { + match command.data.name.as_str() { + "reload" => { + debug!("{:?} reloaded the configuration.", command.user); - let new_config = load_configuration(); + let new_config = load_configuration(); - configuration.administrators = new_config.administrators; - configuration.message_responses = new_config.message_responses; - configuration.thread_introductions = new_config.thread_introductions; + configuration.administrators = new_config.administrators; + configuration.message_responses = new_config.message_responses; + configuration.thread_introductions = new_config.thread_introductions; - "Successfully reloaded configuration.".to_string() - }, - "stop" => { - debug!("{:?} stopped the bot.", command.user); - stop_command = true; - "Stopped the bot.".to_string() - }, - _ => "Unknown command.".to_string(), - } - } else { - "You do not have permission to use this command.".to_string() - }; + "Successfully reloaded configuration.".to_string() + } + "stop" => { + debug!("{:?} stopped the bot.", command.user); + stop_command = true; + "Stopped the bot.".to_string() + } + _ => "Unknown command.".to_string(), + } + } else { + "You do not have permission to use this command.".to_string() + }; - // send the response - if let Err(why) = command - .create_interaction_response(&ctx.http, |response| { - response - .kind(InteractionResponseType::ChannelMessageWithSource) - .interaction_response_data(|message| { - message.content(content).flags(MessageFlags::EPHEMERAL) - }) - }) - .await - { - error!("Cannot respond to slash command: {}", why); - } + // send the response + if let Err(why) = command + .create_interaction_response(&ctx.http, |response| { + response + .kind(InteractionResponseType::ChannelMessageWithSource) + .interaction_response_data(|message| { + message.content(content).flags(MessageFlags::EPHEMERAL) + }) + }) + .await + { + error!("Cannot respond to slash command: {}", why); + } - if stop_command { - process::exit(0); - } - } - } + if stop_command { + process::exit(0); + } + } + } - async fn message(&self, ctx: Context, msg: Message) { - debug!("Received message: {}", msg.content); - if msg.guild_id.is_none() || msg.author.bot { - return; - } + async fn message(&self, ctx: Context, msg: Message) { + debug!("Received message: {}", msg.content); + if msg.guild_id.is_none() || msg.author.bot { + return; + } - if let Some(message_response) = - get_configuration_lock(&ctx).await.read().await.message_responses.iter().find( - |&response| { - // check if the message was sent in a channel that is included in the responder - response.includes.channels.iter().any(|&channel_id| channel_id == msg.channel_id.0) - // check if the message was sent by a user that is not excluded from the responder - && !response.excludes.roles.iter().any(|&role_id| role_id == msg.author.id.0) - // check if the message does not match any of the excludes - && !contains_match(&response.excludes.match_field, &msg.content) - // check if the message matches any of the includes - && contains_match(&response.includes.match_field, &msg.content) - }, - ) { - let min_age = message_response.condition.user.server_age; + if let Some(message_response) = get_configuration_lock(&ctx) + .await + .read() + .await + .message_responses + .iter() + .find(|&response| { + // check if the message was sent in a channel that is included in the responder + response.includes.channels.iter().any(|&channel_id| channel_id == msg.channel_id.0) + // check if the message was sent by a user that is not excluded from the responder + && !response.excludes.roles.iter().any(|&role_id| role_id == msg.author.id.0) + // check if the message does not match any of the excludes + && !contains_match(&response.excludes.match_field, &msg.content) + // check if the message matches any of the includes + && contains_match(&response.includes.match_field, &msg.content) + }) + { + let min_age = message_response.condition.user.server_age; - if min_age != 0 { - let joined_at = ctx - .http - .get_member(msg.guild_id.unwrap().0, msg.author.id.0) - .await - .unwrap() - .joined_at - .unwrap() - .unix_timestamp(); + if min_age != 0 { + let joined_at = ctx + .http + .get_member(msg.guild_id.unwrap().0, msg.author.id.0) + .await + .unwrap() + .joined_at + .unwrap() + .unix_timestamp(); - let must_joined_at = - DateTime::::from_utc(NaiveDateTime::from_timestamp(joined_at, 0), Utc); - let but_joined_at = Utc::now() - Duration::days(min_age); + let must_joined_at = + DateTime::::from_utc(NaiveDateTime::from_timestamp(joined_at, 0), Utc); + let but_joined_at = Utc::now() - Duration::days(min_age); - if must_joined_at <= but_joined_at { - return; - } + if must_joined_at <= but_joined_at { + return; + } - msg.channel_id - .send_message(&ctx.http, |m| { - m.reference_message(&msg); - match &message_response.response.embed { - Some(embed) => m.embed(|e| { - e.title(&embed.title) - .description(&embed.description) - .color(embed.color) - .fields(embed.fields.iter().map(|field| { - (field.name.clone(), field.value.clone(), field.inline) - })) - .footer(|f| { - f.text(&embed.footer.text); - f.icon_url(&embed.footer.icon_url) - }) - .thumbnail(&embed.thumbnail.url) - .image(&embed.image.url) - .author(|a| { - a.name(&embed.author.name).icon_url(&embed.author.icon_url) - }) - }), - None => m.content(message_response.response.message.as_ref().unwrap()), - } - }) - .await - .expect("Could not reply to message author."); - } - } - } + msg.channel_id + .send_message(&ctx.http, |m| { + m.reference_message(&msg); + match &message_response.response.embed { + Some(embed) => m.embed(|e| { + e.title(&embed.title) + .description(&embed.description) + .color(embed.color) + .fields(embed.fields.iter().map(|field| { + (field.name.clone(), field.value.clone(), field.inline) + })) + .footer(|f| { + f.text(&embed.footer.text); + f.icon_url(&embed.footer.icon_url) + }) + .thumbnail(&embed.thumbnail.url) + .image(&embed.image.url) + .author(|a| { + a.name(&embed.author.name).icon_url(&embed.author.icon_url) + }) + }), + None => m.content(message_response.response.message.as_ref().unwrap()), + } + }) + .await + .expect("Could not reply to message author."); + } + } + } - async fn thread_create(&self, ctx: Context, thread: GuildChannel) { - if thread.member.is_some() { - debug!("Thread was joined. Block dispatch."); - return; - } + async fn thread_create(&self, ctx: Context, thread: GuildChannel) { + if thread.member.is_some() { + debug!("Thread was joined. Block dispatch."); + return; + } - debug!("Thread created: {:?}", thread); + debug!("Thread created: {:?}", thread); - let configuration_lock = get_configuration_lock(&ctx).await; - let configuration = configuration_lock.read().await; + let configuration_lock = get_configuration_lock(&ctx).await; + let configuration = configuration_lock.read().await; - if let Some(introducer) = &configuration.thread_introductions.iter().find(|introducer| { - introducer.channels.iter().any(|channel_id| *channel_id == thread.parent_id.unwrap().0) - }) { - if let Err(why) = - thread.say(&ctx.http, &introducer.response.message.as_ref().unwrap()).await - { - error!("Error sending message: {:?}", why); - } - } - } + if let Some(introducer) = &configuration + .thread_introductions + .iter() + .find(|introducer| { + introducer + .channels + .iter() + .any(|channel_id| *channel_id == thread.parent_id.unwrap().0) + }) + { + if let Err(why) = thread + .say(&ctx.http, &introducer.response.message.as_ref().unwrap()) + .await + { + error!("Error sending message: {:?}", why); + } + } + } - async fn ready(&self, ctx: Context, ready: Ready) { - info!("Connected as {}", ready.user.name); + async fn ready(&self, ctx: Context, ready: Ready) { + info!("Connected as {}", ready.user.name); - for (cmd, description) in - [("repload", "Reloads the configuration."), ("stop", "Stop the Discord bot.")] - { - Command::create_global_application_command(&ctx.http, |command| { - command.name(cmd).description(description) - }) - .await - .expect("Could not create command."); - } - } + for (cmd, description) in [ + ("repload", "Reloads the configuration."), + ("stop", "Stop the Discord bot."), + ] { + Command::create_global_application_command(&ctx.http, |command| { + command.name(cmd).description(description) + }) + .await + .expect("Could not create command."); + } + } } #[tokio::main] async fn main() { - // Initialize the logging framework. - logger::init(); + // Initialize the logging framework. + logger::init(); - // Set up the configuration. - let configuration = load_configuration(); + // Set up the configuration. + let configuration = load_configuration(); - // Load environment variables from .env file - dotenv::dotenv().ok(); + // Load environment variables from .env file + dotenv::dotenv().ok(); - // Get the Discord authorization token. - let token = env::var("DISCORD_AUTHORIZATION_TOKEN") - .expect("Could not load Discord authorization token"); - if token.len() != 70 { - error!("Invalid Discord authorization token."); - process::exit(1); - } + // Get the Discord authorization token. + let token = env::var("DISCORD_AUTHORIZATION_TOKEN") + .expect("Could not load Discord authorization token"); + if token.len() != 70 { + error!("Invalid Discord authorization token."); + process::exit(1); + } - // Create the Discord bot client. - let mut client = Client::builder( - &token, - GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT, - ) - .event_handler(Handler) - .await - .expect("Failed to create client"); + // Create the Discord bot client. + let mut client = Client::builder( + &token, + GatewayIntents::GUILDS | GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT, + ) + .event_handler(Handler) + .await + .expect("Failed to create client"); - // Save the configuration. - client.data.write().await.insert::(Arc::new(RwLock::new(configuration))); + // Save the configuration. + client + .data + .write() + .await + .insert::(Arc::new(RwLock::new(configuration))); - // Start the Discord bot. - client.start().await.expect("failed to start discord bot"); + // Start the Discord bot. + client.start().await.expect("failed to start discord bot"); - info!("Client started."); + info!("Client started."); } diff --git a/src/model/application.rs b/src/model/application.rs index 98cc43e..b100c4f 100644 --- a/src/model/application.rs +++ b/src/model/application.rs @@ -1,7 +1,7 @@ use std::{ - fs::{self, File}, - io::{Read, Result, Write}, - path::Path, + fs::{self, File}, + io::{Read, Result, Write}, + path::Path, }; use dirs::config_dir; @@ -10,142 +10,147 @@ use serde::{Deserialize, Serialize}; #[derive(Default, Serialize, Deserialize)] pub struct Configuration { - pub administrators: Administrators, - pub thread_introductions: Vec, - pub message_responses: Vec, + pub administrators: Administrators, + pub thread_introductions: Vec, + pub message_responses: Vec, } const CONFIG_PATH: &str = "configuration.json"; impl Configuration { - fn save(&self) -> Result<()> { - let sys_config_dir = config_dir().expect("find config dir"); + fn save(&self) -> Result<()> { + let sys_config_dir = config_dir().expect("find config dir"); - fs::create_dir_all(format!("{}/revanced-discord-bot", sys_config_dir.to_string_lossy())) - .expect("create config dir"); + fs::create_dir_all(format!( + "{}/revanced-discord-bot", + sys_config_dir.to_string_lossy() + )) + .expect("create config dir"); - let mut file = File::create(CONFIG_PATH)?; - let json = serde_json::to_string_pretty(&self)?; - file.write_all(json.as_bytes())?; - Ok(()) - } + let mut file = File::create(CONFIG_PATH)?; + let json = serde_json::to_string_pretty(&self)?; + file.write_all(json.as_bytes())?; + Ok(()) + } - pub fn load() -> Result { - let sys_config_dir = config_dir().expect("Can not find the configuration directory."); - let sys_config = - format!("{}/revanced-discord-bot/{CONFIG_PATH}", sys_config_dir.to_string_lossy()); + pub fn load() -> Result { + let sys_config_dir = config_dir().expect("Can not find the configuration directory."); + let sys_config = format!( + "{}/revanced-discord-bot/{CONFIG_PATH}", + sys_config_dir.to_string_lossy() + ); - // config file in current dir - let mut file = if Path::new(CONFIG_PATH).exists() { - File::open(CONFIG_PATH)? - } - // config file in system dir (on *nix: `~/.config/revanced-discord-bot/`) - else if Path::new(&sys_config).exists() { - File::open(sys_config)? - } - // create defalt config - else { - let default_config = Configuration::default(); - default_config.save()?; + // config file in current dir + let mut file = if Path::new(CONFIG_PATH).exists() { + File::open(CONFIG_PATH)? + } + // config file in system dir (on *nix: `~/.config/revanced-discord-bot/`) + else if Path::new(&sys_config).exists() { + File::open(sys_config)? + } + // create defalt config + else { + let default_config = Configuration::default(); + default_config.save()?; - File::open(sys_config)? - }; + File::open(sys_config)? + }; - let mut buf = String::new(); - file.read_to_string(&mut buf)?; + let mut buf = String::new(); + file.read_to_string(&mut buf)?; - Ok(serde_json::from_str(&buf)?) - } + Ok(serde_json::from_str(&buf)?) + } } #[derive(Default, Serialize, Deserialize)] pub struct Administrators { - pub roles: Vec, - pub users: Vec, + pub roles: Vec, + pub users: Vec, } #[derive(Serialize, Deserialize)] pub struct Introduction { - pub channels: Vec, - pub response: Response, + pub channels: Vec, + pub response: Response, } #[derive(Serialize, Deserialize)] pub struct MessageResponse { - pub includes: Includes, - pub excludes: Excludes, - pub condition: Condition, - pub response: Response, + pub includes: Includes, + pub excludes: Excludes, + pub condition: Condition, + pub response: Response, } #[derive(Serialize, Deserialize)] pub struct Response { - pub message: Option, - pub embed: Option, + pub message: Option, + pub embed: Option, } #[derive(Serialize, Deserialize)] pub struct Embed { - pub title: String, - pub description: String, - pub color: i32, - pub fields: Vec, - pub footer: Footer, - pub image: Image, - pub thumbnail: Thumbnail, - pub author: Author, + pub title: String, + pub description: String, + pub color: i32, + pub fields: Vec, + pub footer: Footer, + pub image: Image, + pub thumbnail: Thumbnail, + pub author: Author, } #[derive(Serialize, Deserialize)] pub struct Field { - pub name: String, - pub value: String, - pub inline: bool, + pub name: String, + pub value: String, + pub inline: bool, } #[derive(Serialize, Deserialize)] pub struct Footer { - pub text: String, - pub icon_url: String, + pub text: String, + pub icon_url: String, } #[derive(Serialize, Deserialize)] pub struct Image { - pub url: String, + pub url: String, } #[derive(Serialize, Deserialize)] pub struct Thumbnail { - pub url: String, + pub url: String, } #[derive(Serialize, Deserialize)] pub struct Author { - pub name: String, - pub icon_url: String, - pub url: String, + pub name: String, + pub icon_url: String, + pub url: String, } #[derive(Serialize, Deserialize)] pub struct Includes { - pub channels: Vec, - #[serde(rename = "match", with = "serde_regex")] - pub match_field: Vec, + pub channels: Vec, + #[serde(rename = "match", with = "serde_regex")] + pub match_field: Vec, } #[derive(Serialize, Deserialize)] pub struct Excludes { - pub roles: Vec, - #[serde(rename = "match", with = "serde_regex")] - pub match_field: Vec, + pub roles: Vec, + #[serde(rename = "match", with = "serde_regex")] + pub match_field: Vec, } #[derive(Serialize, Deserialize)] pub struct Condition { - pub user: User, + pub user: User, } #[derive(Serialize, Deserialize)] pub struct User { - pub server_age: i64, + pub server_age: i64, }