diff --git a/src/main.rs b/src/main.rs index b81a7ae..f508164 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,7 +34,7 @@ struct Cli { } fn main() { - env_logger::init(); + env_logger::init(); // TODO add more logging let cli = Cli::parse(); @@ -42,6 +42,9 @@ fn main() { error!("No lists or configuration provided."); } - // TODO argument parsing - IN PROGRESS - // TODO logging + // TODO parse config file if one is provided + + // TODO read modsources from files + // TODO combine modsources into modmap + // TODO write modmap to files } diff --git a/src/manip.rs b/src/manip.rs index 9a38e76..a7ce984 100644 --- a/src/manip.rs +++ b/src/manip.rs @@ -4,35 +4,35 @@ use log::error; // ENUMS -/// Specifies a moderation action, whether block or silence +/// Specifies a limit type, whether block or silence #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ModAction { +pub enum Limit { Block, Silence, } // STRUCTS -/// Indicates weight of moderation action on a host +/// Wraps a host's weighted limits #[derive(Debug, Default, Eq, PartialEq)] -pub struct ModActionTrust { +pub struct LimitIndices { pub block: u16, pub silence: u16, } -impl ModActionTrust { - pub fn add_action(&mut self, action: ModAction, trust: u16) -> &mut Self { - match action { - ModAction::Block => self.block += trust, - ModAction::Silence => self.silence += trust, +impl LimitIndices { + pub fn add_limit(&mut self, limit: Limit, weight: u16) -> &mut Self { + match limit { + Limit::Block => self.block += weight, + Limit::Silence => self.silence += weight, } self } } -impl From<(u16, u16)> for ModActionTrust { - /// Creates mod action weights from a tuple of two `u16` weights. Useful - /// mostly for testing. +impl From<(u16, u16)> for LimitIndices { + /// Creates indices from a tuple of two `u16` weights. Useful mostly for + /// testing. fn from(value: (u16, u16)) -> Self { Self { block: value.0, @@ -41,67 +41,69 @@ impl From<(u16, u16)> for ModActionTrust { } } -/// Contains a mapping of hosts to moderation actions as well as a trust value, -/// which is used to weight moderation actions when building a mod map +/// Contains a mapping of hosts to limits as well as a trust value which is +/// used to weight limits when building a merged list #[derive(Debug, PartialEq, Eq)] -pub struct ModSource { - pub actions: HashMap, +pub struct LimitList { + pub limits: HashMap, pub trust: u16, } -impl Default for ModSource { +impl Default for LimitList { fn default() -> Self { Self { - actions: HashMap::new(), + limits: HashMap::new(), trust: 100, } } } -impl From> for ModSource { - fn from(map: HashMap) -> Self { +impl From> for LimitList { + fn from(map: HashMap) -> Self { Self { - actions: map, + limits: map, trust: 100, } } } -impl ModSource { - fn add_action(&mut self, host: &str, action: ModAction) -> &mut Self { - self.actions.insert(host.to_string(), action); +impl LimitList { + fn add_host(&mut self, host: &str, limit: Limit) -> &mut Self { + self.limits.insert(host.to_string(), limit); self } - pub fn build(map: HashMap, trust: u16) -> Self { + pub fn build(map: HashMap, trust: u16) -> Self { let mut src = Self::from(map); src.trust = trust; src } - pub fn import_file(&mut self, path: &str, action: ModAction) -> &mut Self { + pub fn import_file(&mut self, path: &str, limit: Limit) -> &mut Self { let contents = fs::read_to_string(path).unwrap(); for host in contents.lines().filter(|line| !line.is_empty()) { - self.add_action(host, action); + self.add_host(host, limit); } self } } -/// A map of hosts (as strings) to weighted mod actions +/// A map of hosts (as strings) to their limit weights #[derive(Debug, Default, Eq, PartialEq)] -pub struct ModMap(pub HashMap); +pub struct MergedLimitList { + pub map: HashMap, + pub max: u16, +} -impl ModMap { - pub fn add_source(&mut self, src: ModSource) -> &mut Self { - let items = src.actions.into_iter(); - - for (host, action) in items { - let entry = self.0.entry(host).or_default(); - entry.add_action(action, src.trust); +impl MergedLimitList { + pub fn add_limit_list(&mut self, src: LimitList) -> &mut Self { + for (host, limit) in src.limits.into_iter() { + let entry = self.map.entry(host).or_default(); + entry.add_limit(limit, src.trust); } + self.max += src.trust; self } @@ -109,18 +111,18 @@ impl ModMap { self, block_path: &str, mute_path: &str, - heat: (u16, u16), + indices: (u16, u16), ) -> std::io::Result<()> { - if self.0.is_empty() { + if self.map.is_empty() { error!("Nothing to export!"); return Ok(()); } - let (block_thresh, mute_thresh) = heat; + let (block_thresh, mute_thresh) = indices; let mut block_output: String = String::default(); let mut mute_output: String = String::default(); - for item in self.0.into_iter() { + for item in self.map.into_iter() { let (block_trust, mute_trust) = (item.1.block, item.1.silence); if block_trust >= block_thresh { diff --git a/src/tests/manip.rs b/src/tests/manip.rs index 7d9f5b5..a405693 100644 --- a/src/tests/manip.rs +++ b/src/tests/manip.rs @@ -5,13 +5,13 @@ use std::{collections::HashMap, fs}; use crate::manip::*; #[test] -fn modaction_add() { - let mut at = ModActionTrust::default(); +fn limit_add() { + let mut at = LimitIndices::default(); - at.add_action(ModAction::Block, 123) - .add_action(ModAction::Silence, 456); + at.add_limit(Limit::Block, 123) + .add_limit(Limit::Silence, 456); - let test_at = ModActionTrust { + let test_at = LimitIndices { block: 123, silence: 456, }; @@ -20,14 +20,14 @@ fn modaction_add() { } #[test] -fn modaction_combine() { - let mut at = ModActionTrust::default(); +fn limit_combine() { + let mut at = LimitIndices::default(); - at.add_action(ModAction::Block, 123) - .add_action(ModAction::Block, 333) - .add_action(ModAction::Silence, 123); + at.add_limit(Limit::Block, 123) + .add_limit(Limit::Block, 333) + .add_limit(Limit::Silence, 123); - let test_at = ModActionTrust { + let test_at = LimitIndices { block: 456, silence: 123, }; @@ -36,19 +36,19 @@ fn modaction_combine() { } #[test] -fn modsource_from_map() { - let src1 = ModSource::from(HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), +fn limitlist_from_map() { + let src1 = LimitList::from(HashMap::from([ + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ])); assert_eq!( - src1.actions, + src1.limits, HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ]) ); @@ -56,139 +56,145 @@ fn modsource_from_map() { } #[test] -fn modsource_from_map_and_trust() { - let src2 = ModSource::build( +fn limitlist_from_map_and_trust() { + let src2 = LimitList::build( HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ]), 123, ); assert_eq!( - src2.actions, + src2.limits, HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ]) ); assert_eq!(src2.trust, 123); } #[test] -fn modsource_from_file() { - let mut src = ModSource::default(); - src.import_file("test/example_blocklist.txt", ModAction::Block) - .import_file("test/example_mutelist.txt", ModAction::Silence); +fn limitlist_from_file() { + let mut src = LimitList::default(); + src.import_file("test/example_blocklist.txt", Limit::Block) + .import_file("test/example_mutelist.txt", Limit::Silence); - let test_src = ModSource::from(HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Block), - (String::from("example.net"), ModAction::Silence), + let test_src = LimitList::from(HashMap::from([ + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Block), + (String::from("example.net"), Limit::Silence), ])); assert_eq!(test_src, src); } #[test] -fn modmap_from_modsource() { - let mut ml = ModMap::default(); +fn mergedlist_from_limitlist() { + let mut ml = MergedLimitList::default(); - let src1 = ModSource::from(HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), + let src1 = LimitList::from(HashMap::from([ + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ])); - let mut src2 = ModSource::default(); - src2.import_file("test/example_blocklist.txt", ModAction::Block) - .import_file("test/example_mutelist.txt", ModAction::Silence); + let mut src2 = LimitList::default(); + src2.import_file("test/example_blocklist.txt", Limit::Block) + .import_file("test/example_mutelist.txt", Limit::Silence); - ml.add_source(src1).add_source(src2); + ml.add_limit_list(src1).add_limit_list(src2); - let test_ml = ModMap(HashMap::from([ - (String::from("example.com"), ModActionTrust::from((200, 0))), - ( - String::from("example.org"), - ModActionTrust::from((100, 100)), - ), - ( - String::from("example.net"), - ModActionTrust::from((100, 100)), - ), - ])); + let test_ml = MergedLimitList { + map: HashMap::from([ + (String::from("example.com"), LimitIndices::from((200, 0))), + ( + String::from("example.org"), + LimitIndices::from((100, 100)), + ), + ( + String::from("example.net"), + LimitIndices::from((100, 100)), + ), + ]), + max: 200, + }; assert_eq!(ml, test_ml); - let src3 = ModSource::build( + let src3 = LimitList::build( HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), ]), 200, ); - let src4 = ModSource::build( + let src4 = LimitList::build( HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.net"), ModAction::Silence), + (String::from("example.com"), Limit::Block), + (String::from("example.net"), Limit::Silence), ]), 50, ); - ml.add_source(src3).add_source(src4); + ml.add_limit_list(src3).add_limit_list(src4); - let test_ml = ModMap(HashMap::from([ - (String::from("example.com"), ModActionTrust::from((450, 0))), - ( - String::from("example.org"), - ModActionTrust::from((100, 300)), - ), - ( - String::from("example.net"), - ModActionTrust::from((100, 150)), - ), - ])); + let test_ml = MergedLimitList { + map: HashMap::from([ + (String::from("example.com"), LimitIndices::from((450, 0))), + ( + String::from("example.org"), + LimitIndices::from((100, 300)), + ), + ( + String::from("example.net"), + LimitIndices::from((100, 150)), + ), + ]), + max: 450, + }; assert_eq!(ml, test_ml); } #[test] -fn modmap_export_txt() { - let mut ml = ModMap::default(); +fn mergedlist_export_txt() { + let mut ml = MergedLimitList::default(); - let src1 = ModSource::from(HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), - (String::from("example.net"), ModAction::Block), + let src1 = LimitList::from(HashMap::from([ + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), + (String::from("example.net"), Limit::Block), ])); - let mut src2 = ModSource::default(); - src2.import_file("test/example_blocklist.txt", ModAction::Block) - .import_file("test/example_mutelist.txt", ModAction::Silence); + let mut src2 = LimitList::default(); + src2.import_file("test/example_blocklist.txt", Limit::Block) + .import_file("test/example_mutelist.txt", Limit::Silence); - let src3 = ModSource::build( + let src3 = LimitList::build( HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.org"), ModAction::Silence), + (String::from("example.com"), Limit::Block), + (String::from("example.org"), Limit::Silence), ]), 200, ); - let src4 = ModSource::build( + let src4 = LimitList::build( HashMap::from([ - (String::from("example.com"), ModAction::Block), - (String::from("example.net"), ModAction::Silence), + (String::from("example.com"), Limit::Block), + (String::from("example.net"), Limit::Silence), ]), 50, ); - ml.add_source(src1) - .add_source(src2) - .add_source(src3) - .add_source(src4); + ml.add_limit_list(src1) + .add_limit_list(src2) + .add_limit_list(src3) + .add_limit_list(src4); let _ = ml.export_file("test/test_blocks.txt", "test/test_mutes.txt", (200, 150));