Better detection system; Detection types

This commit is contained in:
0xf8 2023-04-16 20:43:36 -04:00
parent f7c7526081
commit d94095e8d9
Signed by: 0xf8
GPG Key ID: 446580D758689584
9 changed files with 245 additions and 264 deletions

9
Cargo.lock generated
View File

@ -2067,7 +2067,7 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]] [[package]]
name = "scam-police" name = "scam-police"
version = "0.5.0" version = "0.6.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"dirs", "dirs",
@ -2078,6 +2078,7 @@ dependencies = [
"rpassword", "rpassword",
"serde", "serde",
"serde_json", "serde_json",
"strfmt",
"tokio", "tokio",
"url", "url",
] ]
@ -2252,6 +2253,12 @@ dependencies = [
"der", "der",
] ]
[[package]]
name = "strfmt"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.10.0" version = "0.10.0"

View File

@ -1,6 +1,6 @@
[package] [package]
name = "scam-police" name = "scam-police"
version = "0.5.0" version = "0.6.0"
edition = "2021" edition = "2021"
authors = [ "@0xf8:projectsegfau.lt", "@jjj333:pain.agency" ] authors = [ "@0xf8:projectsegfau.lt", "@jjj333:pain.agency" ]
@ -16,5 +16,6 @@ reqwest = "0.11.16"
rpassword = "7.2.0" rpassword = "7.2.0"
serde = "1.0.160" serde = "1.0.160"
serde_json = "1.0.95" serde_json = "1.0.95"
strfmt = "0.2.4"
tokio = { version = "1.27.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.27.0", features = ["macros", "rt-multi-thread"] }
url = "2.3.1" url = "2.3.1"

View File

@ -1,66 +1,52 @@
{ {
"keywords":{ "sections": {
"verbs":[ "18+": {
"earn", "threshold": 3,
"make", "making", "made", "requiredKeywords": [
"generate", "sex",
"win", "nude",
"invest", "18+",
"cashout", "private",
"sell", "pictures",
"get", "cheap"
"pay", ],
"sex", "keywords": [
"meet", "pay", "pal",
"upload", "buy",
"login", "sell",
"send", "message",
"join", "meet",
"buy", "check",
"check", "card"
"private" ]
], },
"currencies":[ "Investment": {
"$", "£", "€", "threshold": 4,
"money", "requiredKeywords": [
"million", "tg", "t.me/",
"dollar", "pound", "euro", "invest",
"crypto", "crypto", "market",
"paypal", "profit",
"bitcoin", "btc", "my commission",
"etherium", " eth", "cashout", "cash out",
"usd", "million",
"nft", "cash.app",
"token", "l.wl.co/", ".app.link/"
"free", ],
"gift", "keywords": [
"card", "earn", "earning",
"nude", "make", "making", "made",
"18+", "buy",
"pay" "send",
], "interested",
"socials":[ "btc", "bitcoin",
"l.wl.co/", "eth", "ethereum", "etherium",
".app.link/", "$", "usd",
"bit.ly/", "asking me how",
"paypal.me/", "cash", "whats", "app",
"matrix.to/", "tele", "gram",
"wa.me/", "👇", "👆️"
"t.me/", ]
"cash.app", }
"cash app",
"cashapp",
"discord.gg/",
"discord",
"is.gd/",
"telegram",
"whatsapp", "whatapp", "whats app", "what app",
"wickr",
"kik",
"instagram",
"dm me",
"👇", "👆️",
"+1", "+2"
]
} }
} }

View File

@ -3,16 +3,16 @@
"Ok": null, "Ok": null,
"MaybeScam": null, "MaybeScam": null,
"LikelyScam": { "LikelyScam": {
"plain": "Watch out, the message you replied to has been detected as a scam! Please don't do anything they ask you to do! Stay safe", "plain": "Watch out, the message you replied to has been detected as an {scam} scam! Please don't do anything they ask you to do! Stay safe",
"html": "Watch out, the message you replied to has been detected as a <b>scam</b>! <u>Please don't do anything they ask you to do</u>! Stay safe" "html": "Watch out, the message you replied to has been detected as an <b>{scam} scam</b>! <u>Please don't do anything they ask you to do</u>! Stay safe"
} }
}, },
"message": { "message": {
"Ok": null, "Ok": null,
"MaybeScam": null, "MaybeScam": null,
"LikelyScam": { "LikelyScam": {
"plain": "Warning! This message is likely to be a scam, seeking to lure you in and steal your money! Please visit these resources for more information:\n- https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert\n- https://www.youtube.com/watch?v=gFWaA7mt9oM \n [!mods !modhelp]", "plain": "Warning! This message was detected as an {scam} scam, seeking to lure you in and steal your money! Please visit these resources for more information:\n- https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert\n- https://www.youtube.com/watch?v=gFWaA7mt9oM \n [!mods !modhelp]",
"html": "Warning! This message is likely to be a <b>scam</b>, seeking to lure you in and steal your money! Please visit these resources for more information: <ul><li><a href=\"https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert\">https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert</a></li><li><a href=\"https://www.youtube.com/watch?v=gFWaA7mt9oM\">https://www.youtube.com/watch?v=gFWaA7mt9oM</a></li></ul> [!mods !modhelp]" "html": "Warning! This message was detected as an <b>{scam} scam</b>, seeking to lure you in and steal your money! Please visit these resources for more information: <ul><li><a href=\"https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert\">https://www.sec.gov/oiea/investor-alerts-and-bulletins/digital-asset-and-crypto-investment-scams-investor-alert</a></li><li><a href=\"https://www.youtube.com/watch?v=gFWaA7mt9oM\">https://www.youtube.com/watch?v=gFWaA7mt9oM</a></li></ul> [!mods !modhelp]"
} }
} }
} }

View File

@ -1,9 +1,11 @@
use serde_json::Value; use crate::keywords::KeywordSection;
use matrix_sdk::{room::Joined, ruma::OwnedRoomId};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::BTreeSet; use serde_json::Value;
use matrix_sdk::{ruma::OwnedRoomId, room::Joined}; use std::collections::{BTreeMap, BTreeSet};
use tokio::fs; use tokio::fs;
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)] #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord)]
pub struct RoomConfig { pub struct RoomConfig {
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
@ -16,7 +18,11 @@ pub struct RoomConfig {
impl Default for RoomConfig { impl Default for RoomConfig {
fn default() -> Self { fn default() -> Self {
Self { id: None, no_reply: false, reply_to_scam: false } Self {
id: None,
no_reply: false,
reply_to_scam: false,
}
} }
} }
@ -30,7 +36,9 @@ impl RoomConfigController {
pub async fn find(&self, id: OwnedRoomId) -> Option<&RoomConfig> { pub async fn find(&self, id: OwnedRoomId) -> Option<&RoomConfig> {
let id = Some(id); let id = Some(id);
for room in self.rooms.to_owned() { for room in self.rooms.to_owned() {
if room.id == id { return Some(self.rooms.get(&room).unwrap()) } if room.id == id {
return Some(self.rooms.get(&room).unwrap());
}
} }
None None
@ -45,7 +53,11 @@ impl RoomConfigController {
Ok(self.rooms.insert(config)) Ok(self.rooms.insert(config))
} }
pub async fn find_or_create(&mut self, room: &Joined, id: OwnedRoomId) -> anyhow::Result<&RoomConfig> { pub async fn find_or_create(
&mut self,
room: &Joined,
id: OwnedRoomId,
) -> anyhow::Result<&RoomConfig> {
if self.find(id.to_owned()).await.is_none() { if self.find(id.to_owned()).await.is_none() {
self.create_config(room).await?; self.create_config(room).await?;
} }
@ -54,7 +66,12 @@ impl RoomConfigController {
} }
pub async fn save(&mut self, config: &RoomConfig) -> anyhow::Result<()> { pub async fn save(&mut self, config: &RoomConfig) -> anyhow::Result<()> {
self.rooms.take(self.to_owned().find(config.id.to_owned().unwrap()).await.unwrap()); self.rooms.take(
self.to_owned()
.find(config.id.to_owned().unwrap())
.await
.unwrap(),
);
self.rooms.insert(config.to_owned()); self.rooms.insert(config.to_owned());
let serialized = serde_json::to_string_pretty(self)?; let serialized = serde_json::to_string_pretty(self)?;
@ -65,13 +82,18 @@ impl RoomConfigController {
pub fn restore() -> anyhow::Result<Self> { pub fn restore() -> anyhow::Result<Self> {
if !std::path::Path::new(crate::ROOMS_CONFIG_FILE.to_owned().to_str().unwrap()).exists() { if !std::path::Path::new(crate::ROOMS_CONFIG_FILE.to_owned().to_str().unwrap()).exists() {
return Ok(Self { rooms: BTreeSet::<RoomConfig>::new() }); return Ok(Self {
rooms: BTreeSet::<RoomConfig>::new(),
});
} }
let serialized = std::fs::read_to_string(crate::ROOMS_CONFIG_FILE.to_owned())?; let serialized = std::fs::read_to_string(crate::ROOMS_CONFIG_FILE.to_owned())?;
let ctrl: Result<RoomConfigController, serde_json::Error> = serde_json::from_str(&serialized); let ctrl: Result<RoomConfigController, serde_json::Error> =
serde_json::from_str(&serialized);
if ctrl.is_err() { if ctrl.is_err() {
return Ok(Self { rooms: BTreeSet::<RoomConfig>::new() }); return Ok(Self {
rooms: BTreeSet::<RoomConfig>::new(),
});
} }
Ok(ctrl.unwrap()) Ok(ctrl.unwrap())
} }
@ -80,24 +102,31 @@ impl RoomConfigController {
#[derive(Debug)] #[derive(Debug)]
pub struct Config { pub struct Config {
pub keywords: Value, pub keywords: BTreeMap<String, KeywordSection>,
pub responses: Value, pub responses: Value,
} }
impl Config { impl Config {
pub fn load() -> Config { pub fn load() -> Config {
let keywords_reader = let responses: Value = serde_json::from_reader(
std::fs::File::open("config/keywords.json").expect("Couldn't find keywords.json"); std::fs::File::open("config/responses.json").expect("Couldn't find responses.json"),
let keywords: Value = )
serde_json::from_reader(keywords_reader).expect("Couldn't read keywords"); .expect("Couldn't read responses");
let responses_reader = let keywords: Value = serde_json::from_reader(
std::fs::File::open("config/responses.json").expect("Couldn't find responses.json"); std::fs::File::open("config/keywords.json").expect("Couldn't find keywords.json"),
let responses: Value = )
serde_json::from_reader(responses_reader).expect("Couldn't read responses"); .expect("Couldn't read keywords");
let sections: BTreeMap<String, KeywordSection> = keywords["sections"]
.as_object()
.unwrap()
.into_iter()
.map(|a| (a.0.to_owned(), KeywordSection::load(a.1)))
.collect();
Self { Self {
keywords, keywords: sections,
responses, responses,
} }
} }

50
src/debug.rs Normal file
View File

@ -0,0 +1,50 @@
use matrix_sdk::{
room::Joined,
ruma::events::room::message::RoomMessageEventContent,
};
use crate::{
judge::{Judgement, JudgementResult},
keywords::KeywordSection,
CONFIG,
};
pub struct Debug {}
impl Debug {
pub async fn send_debug(judge: &Judgement, room: &Joined) -> anyhow::Result<()> {
let sections = CONFIG.keywords.to_owned();
let mut result_report: Vec<(String, String)> = vec![];
let res: (JudgementResult, Option<KeywordSection>) = (|| {
for section in sections {
let (hits, hit_required) = section.1.find(judge.text.to_owned());
result_report.push((
format!("\"{}\": \"{hits}\", {hit_required} ", section.0),
format!("<code>{}</code>: <code>{hits}</code>, <code>{hit_required}</code>", section.0)
));
if hit_required && hits >= section.1.threshold {
return (JudgementResult::LikelyScam, Some(section.1))
} else if hits >= section.1.threshold {
return (JudgementResult::MaybeScam, Some(section.1))
}
}
(JudgementResult::Ok, None)
})();
let mut full_report: (String, String) = ("".to_string(), "".to_string());
for (plain, html) in result_report {
full_report.0.push_str(format!("{plain}\n").as_str());
full_report.1.push_str(format!("{html}<br>").as_str());
}
let msg = RoomMessageEventContent::text_html(full_report.0, full_report.1);
room.send(msg, None).await.expect("Couldn't send message");
Ok(())
}
}

View File

@ -1,5 +1,5 @@
use crate::{ use crate::{
keywords::{KeywordCategory, Keywords}, keywords::KeywordSection,
config::RoomConfig, config::RoomConfig,
CONFIG, CONFIG,
}; };
@ -7,9 +7,11 @@ use matrix_sdk::{
room::Joined, room::Joined,
ruma::events::room::message::{OriginalRoomMessageEvent, RoomMessageEventContent}, ruma::events::room::message::{OriginalRoomMessageEvent, RoomMessageEventContent},
}; };
use std::collections::HashMap;
use strfmt::strfmt;
use serde_json::json; use serde_json::json;
#[derive(Debug)] #[derive(Debug, PartialEq, Eq)]
pub enum JudgementResult { pub enum JudgementResult {
Ok, Ok,
MaybeScam, // hit atleast one category MaybeScam, // hit atleast one category
@ -31,93 +33,27 @@ pub struct Judgement {
} }
impl Judgement { impl Judgement {
pub fn judge(&self, config: &RoomConfig) -> anyhow::Result<JudgementResult> { pub fn judge(&self, _config: &RoomConfig) -> anyhow::Result<(JudgementResult, Option<(String, KeywordSection)>)> {
// Load keywords let sections = CONFIG.keywords.to_owned();
let mut keywords = CONFIG.keywords.clone();
let keywords = keywords
.as_object_mut()
.unwrap()
.get_mut("keywords")
.unwrap();
// Turn json into Keywords for section in sections {
let verbs = Keywords::create("verbs", &keywords["verbs"]); let (hits, hit_required) = section.1.find(self.text.to_owned());
let currencies = Keywords::create("currencies", &keywords["currencies"]);
let socials = Keywords::create("socials", &keywords["socials"]);
// Count occurences if hit_required && hits >= section.1.threshold {
let mut counter = KeywordCategory::create_counter_map(); return Ok((JudgementResult::LikelyScam, Some(section)))
counter.insert(KeywordCategory::Verb, verbs.find(&self.text)); } else if hits >= section.1.threshold {
counter.insert(KeywordCategory::Currency, currencies.find(&self.text)); return Ok((JudgementResult::MaybeScam, Some(section)))
counter.insert(KeywordCategory::Social, socials.find(&self.text));
let mut count_all = 0;
let total = counter.len();
for (_category, count) in counter.to_owned() {
if count > 0 {
count_all = count_all + 1;
} }
} }
if count_all == 0 {
return Ok(JudgementResult::Ok);
};
if count_all < total {
return Ok(JudgementResult::MaybeScam);
};
Ok(JudgementResult::LikelyScam)
}
pub async fn send_debug(&self, config: &RoomConfig, room: &Joined) -> anyhow::Result<()> {
// Load keywords
let mut keywords = CONFIG.keywords.clone();
let keywords = keywords
.as_object_mut()
.unwrap()
.get_mut("keywords")
.unwrap();
// Turn json into Keywords
let verbs = Keywords::create("verbs", &keywords["verbs"]);
let currencies = Keywords::create("currencies", &keywords["currencies"]);
let socials = Keywords::create("socials", &keywords["socials"]);
// Count occurences
let mut counter = KeywordCategory::create_counter_map();
counter.insert(KeywordCategory::Verb, verbs.find(&self.text));
counter.insert(KeywordCategory::Currency, currencies.find(&self.text));
counter.insert(KeywordCategory::Social, socials.find(&self.text));
let mut count_all = 0;
let total = counter.len();
for (_category, count) in counter.to_owned() {
if count > 0 {
count_all = count_all + 1;
}
}
let mut result = JudgementResult::LikelyScam;
if count_all < total {
result = JudgementResult::MaybeScam
}
if count_all == 0 {
result = JudgementResult::Ok
}
// Send message Ok((JudgementResult::Ok, None))
let msg = RoomMessageEventContent::text_html(
format!("{counter:?}\nCategories covered: {count_all}/{total}\nVerdict: {result:?}\n{config:?}"),
format!("<code>{counter:?}</code><br>Categories covered: <code>{count_all}/{total}</code><br>Verdict: <code>{result:?}</code><br><code>{config:?}</code>"));
room.send(msg, None).await.expect("Couldn't send message");
Ok(())
} }
pub async fn alert( pub async fn alert(
config: &RoomConfig, config: &RoomConfig,
room: &Joined, room: &Joined,
event: &OriginalRoomMessageEvent, event: &OriginalRoomMessageEvent,
result: JudgementResult, result: (JudgementResult, Option<(String, KeywordSection)>),
is_reply: bool, is_reply: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
if config.no_reply { if config.no_reply {
@ -129,44 +65,45 @@ impl Judgement {
// Determine which message to send // Determine which message to send
let section = if is_reply { let section = if is_reply {
responses["reply"].as_object().unwrap() responses["reply"].to_owned()
} else { } else {
responses["message"].as_object().unwrap() responses["message"].to_owned()
}; };
let response_type = section.get(result.to_json_var()).unwrap(); let response_type = section.get(result.0.to_json_var()).unwrap();
if response_type.is_null() { if response_type.is_null() {
anyhow::bail!("Called alert with result that has no detection message"); anyhow::bail!("Called alert with result that has no detection message");
} }
let response_type = response_type.as_object().unwrap(); let scam_type = result.1.unwrap().0;
let plain = response_type["plain"].as_str().unwrap(); let mut args: HashMap<String, &str> = HashMap::new();
let html = response_type["html"].as_str().unwrap(); args.insert("scam".to_string(), &scam_type);
let plain = strfmt(response_type["plain"].as_str().unwrap(), &args).unwrap();
let html = strfmt(response_type["html"].as_str().unwrap(), &args).unwrap();
// Send message // Send message
let msg = RoomMessageEventContent::text_html(plain, html); let msg = RoomMessageEventContent::text_html(plain, html);
if config.reply_to_scam { let msg = if config.reply_to_scam {
let reply = msg.make_reply_to(event); msg.make_reply_to(event)
room.send(reply, None).await.expect("Couldn't send message");
} else { } else {
room.send(msg, None).await.expect("Couldn't send message"); msg
} };
room.send(msg, None).await.expect("Couldn't send message");
// Send reaction // Send reaction
if !is_reply { if !is_reply {
room.send_raw( room.send_raw(
json!({ json!({
"m.relates_to": { "m.relates_to": {
"rel_type": "m.annotation", "rel_type": "m.annotation",
"event_id": event.event_id.to_string(), "event_id": event.event_id.to_string(),
"key": "🚨🚨 SCAM 🚨🚨" "key": "🚨🚨 SCAM 🚨🚨"
}}), }}),
"m.reaction", "m.reaction",
None, None)
) .await
.await .expect("Couldn't send reaction");
.expect("Couldn't send reaction");
} }
Ok(()) Ok(())

View File

@ -1,87 +1,53 @@
use serde_json::Value; use serde_json::Value;
use std::collections::HashMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum KeywordCategory {
Verb,
Currency,
Social,
}
impl std::fmt::Display for KeywordCategory {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use KeywordCategory::*;
match self { #[derive(Debug, Clone)]
Verb => write!(f, "Verb"), pub struct KeywordSection {
Currency => write!(f, "Currency"), pub threshold: u64,
Social => write!(f, "Social"), pub required: Vec<String>,
} pub keywords: Vec<String>,
}
} }
impl KeywordCategory { impl KeywordSection {
pub fn to_json_var(&self) -> &str { pub fn load(json: &Value) -> Self {
use KeywordCategory::*; let threshold: u64 = json["threshold"].as_u64().unwrap();
let required: Vec<String> = json["requiredKeywords"]
match self { .as_array()
Verb => "verbs", .unwrap()
Currency => "currencies", .into_iter()
Social => "socials", .map(|a| a.as_str().unwrap().to_string())
} .collect();
} let keywords: Vec<String> = json["keywords"]
.as_array()
pub fn from_json_var(var: &str) -> Result<Self, ()> { .unwrap()
use KeywordCategory::*; .into_iter()
.map(|a| a.as_str().unwrap().to_string())
match var { .collect();
"verbs" => Ok(Verb),
"currencies" => Ok(Currency),
"socials" => Ok(Social),
_ => Err(()),
}
}
pub fn create_counter_map() -> HashMap<KeywordCategory, u64> {
use KeywordCategory::*;
let mut map: HashMap<KeywordCategory, u64> = HashMap::new();
map.insert(Verb, 0);
map.insert(Currency, 0);
map.insert(Social, 0);
map
}
}
pub struct Keywords {
pub category: KeywordCategory,
pub words: Vec<Value>,
}
impl Keywords {
pub fn create(name: &str, v: &Value) -> Self {
let v = v.as_array().unwrap();
let Ok(category) = KeywordCategory::from_json_var(name) else {
panic!("Couldn't translate \"{name}\" to KeywordCategory");
};
Self { Self {
category, threshold,
words: v.to_vec(), required,
keywords,
} }
} }
pub fn find(&self, hay: &str) -> u64 { pub fn find(&self, s: String) -> (u64, bool) {
let mut hits: u64 = 0; let mut hits: u64 = 0;
let mut hit_required: bool = false;
for kw in self.words.to_owned().into_iter() { for kw in self.keywords.to_owned() {
let kw = kw.as_str().unwrap(); if s.contains(&kw) {
hits += 1;
if hay.contains(kw) {
hits += 1
} }
} }
hits for rkw in self.required.to_owned() {
if s.contains(&rkw) {
hits += 1;
hit_required = true;
}
}
(hits, hit_required)
} }
} }

View File

@ -15,6 +15,8 @@ pub mod config;
pub mod judge; pub mod judge;
pub mod keywords; pub mod keywords;
pub mod matrix; pub mod matrix;
pub mod debug;
static DATA_DIR: Lazy<PathBuf> = Lazy::new(|| dirs::data_dir().expect("No data_dir found").join("scam_police")); static DATA_DIR: Lazy<PathBuf> = Lazy::new(|| dirs::data_dir().expect("No data_dir found").join("scam_police"));
static SESSION_FILE: Lazy<PathBuf> = Lazy::new(|| DATA_DIR.join("session")); static SESSION_FILE: Lazy<PathBuf> = Lazy::new(|| DATA_DIR.join("session"));
@ -22,6 +24,7 @@ static ROOMS_CONFIG_FILE: Lazy<PathBuf> = Lazy::new(|| DATA_DIR.join("rooms_conf
static CONFIG: Lazy<config::Config> = Lazy::new(|| config::Config::load()); static CONFIG: Lazy<config::Config> = Lazy::new(|| config::Config::load());
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> anyhow::Result<()> { async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> anyhow::Result<()> {
if let Room::Joined(room) = room { if let Room::Joined(room) = room {
let mut room_ctrl = config::RoomConfigController::restore().expect("Couldn't restore room configs"); let mut room_ctrl = config::RoomConfigController::restore().expect("Couldn't restore room configs");
@ -108,11 +111,12 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
let reply_judgement = judge::Judgement { text: content }; let reply_judgement = judge::Judgement { text: content };
if debug { if debug {
reply_judgement.send_debug(&config, &room).await?; debug::Debug::send_debug(&reply_judgement, &room).await?;
return Ok(()); return Ok(());
} }
match reply_judgement.judge(&config)? { let judgement = reply_judgement.judge(&config)?;
match judgement.0 {
judge::JudgementResult::Ok => (), judge::JudgementResult::Ok => (),
judge::JudgementResult::MaybeScam => (), judge::JudgementResult::MaybeScam => (),
judge::JudgementResult::LikelyScam => { judge::JudgementResult::LikelyScam => {
@ -120,7 +124,7 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
&config, &config,
&room, &room,
&orig_event, &orig_event,
judge::JudgementResult::LikelyScam, judgement,
true, true,
) )
.await?; .await?;
@ -130,7 +134,8 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
} }
} }
match judgement.judge(&config)? { let judgement = judgement.judge(&config)?;
match judgement.0 {
judge::JudgementResult::Ok => return Ok(()), judge::JudgementResult::Ok => return Ok(()),
judge::JudgementResult::MaybeScam => return Ok(()), judge::JudgementResult::MaybeScam => return Ok(()),
judge::JudgementResult::LikelyScam => { judge::JudgementResult::LikelyScam => {
@ -138,7 +143,7 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
&config, &config,
&room, &room,
&orig_event, &orig_event,
judge::JudgementResult::LikelyScam, judgement,
false, false,
) )
.await?; .await?;