Code cleanup/reformat, added comments, other stuff i forgor
This commit is contained in:
parent
ff2d897549
commit
14246c7b60
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -2067,7 +2067,7 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scam-police"
|
name = "scam-police"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "scam-police"
|
name = "scam-police"
|
||||||
version = "0.4.0"
|
version = "0.5.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = [ "@0xf8:projectsegfau.lt", "@jjj333:pain.agency" ]
|
authors = [ "@0xf8:projectsegfau.lt", "@jjj333:pain.agency" ]
|
||||||
|
|
||||||
|
@ -7,15 +7,19 @@ pub struct Config {
|
|||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn load() -> Config {
|
pub fn load() -> Config {
|
||||||
let keywords_reader = std::fs::File::open("config/keywords.json").expect("Couldn't find keywords.json");
|
let keywords_reader =
|
||||||
let keywords: Value = serde_json::from_reader(keywords_reader).expect("Couldn't read keywords");
|
std::fs::File::open("config/keywords.json").expect("Couldn't find keywords.json");
|
||||||
|
let keywords: Value =
|
||||||
|
serde_json::from_reader(keywords_reader).expect("Couldn't read keywords");
|
||||||
|
|
||||||
let responses_reader = std::fs::File::open("config/responses.json").expect("Couldn't find responses.json");
|
let responses_reader =
|
||||||
let responses: Value = serde_json::from_reader(responses_reader).expect("Couldn't read responses");
|
std::fs::File::open("config/responses.json").expect("Couldn't find responses.json");
|
||||||
|
let responses: Value =
|
||||||
|
serde_json::from_reader(responses_reader).expect("Couldn't read responses");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
keywords,
|
keywords,
|
||||||
responses
|
responses,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
61
src/judge.rs
61
src/judge.rs
@ -1,5 +1,11 @@
|
|||||||
use crate::{CONFIG, keywords::{Keywords, KeywordCategory}};
|
use crate::{
|
||||||
use matrix_sdk::{room::Joined, ruma::events::room::message::{RoomMessageEventContent, OriginalRoomMessageEvent}};
|
keywords::{KeywordCategory, Keywords},
|
||||||
|
CONFIG,
|
||||||
|
};
|
||||||
|
use matrix_sdk::{
|
||||||
|
room::Joined,
|
||||||
|
ruma::events::room::message::{OriginalRoomMessageEvent, RoomMessageEventContent},
|
||||||
|
};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -14,20 +20,24 @@ impl JudgementResult {
|
|||||||
match self {
|
match self {
|
||||||
Self::Ok => "Ok",
|
Self::Ok => "Ok",
|
||||||
Self::MaybeScam => "MaybeScam",
|
Self::MaybeScam => "MaybeScam",
|
||||||
Self::LikelyScam => "LikelyScam"
|
Self::LikelyScam => "LikelyScam",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Judgement {
|
pub struct Judgement {
|
||||||
pub text: String
|
pub text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Judgement {
|
impl Judgement {
|
||||||
pub fn judge(&self) -> anyhow::Result<JudgementResult> {
|
pub fn judge(&self) -> anyhow::Result<JudgementResult> {
|
||||||
// Load keywords
|
// Load keywords
|
||||||
let mut keywords = CONFIG.keywords.clone();
|
let mut keywords = CONFIG.keywords.clone();
|
||||||
let keywords = keywords.as_object_mut().unwrap().get_mut("keywords").unwrap();
|
let keywords = keywords
|
||||||
|
.as_object_mut()
|
||||||
|
.unwrap()
|
||||||
|
.get_mut("keywords")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Turn json into Keywords
|
// Turn json into Keywords
|
||||||
let verbs = Keywords::create("verbs", &keywords["verbs"]);
|
let verbs = Keywords::create("verbs", &keywords["verbs"]);
|
||||||
@ -48,15 +58,23 @@ impl Judgement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if count_all == 0 { return Ok(JudgementResult::Ok) };
|
if count_all == 0 {
|
||||||
if count_all < total { return Ok(JudgementResult::MaybeScam) };
|
return Ok(JudgementResult::Ok);
|
||||||
|
};
|
||||||
|
if count_all < total {
|
||||||
|
return Ok(JudgementResult::MaybeScam);
|
||||||
|
};
|
||||||
Ok(JudgementResult::LikelyScam)
|
Ok(JudgementResult::LikelyScam)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send_debug(&self, room: &Joined) -> anyhow::Result<()> {
|
pub async fn send_debug(&self, room: &Joined) -> anyhow::Result<()> {
|
||||||
// Load keywords
|
// Load keywords
|
||||||
let mut keywords = CONFIG.keywords.clone();
|
let mut keywords = CONFIG.keywords.clone();
|
||||||
let keywords = keywords.as_object_mut().unwrap().get_mut("keywords").unwrap();
|
let keywords = keywords
|
||||||
|
.as_object_mut()
|
||||||
|
.unwrap()
|
||||||
|
.get_mut("keywords")
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Turn json into Keywords
|
// Turn json into Keywords
|
||||||
let verbs = Keywords::create("verbs", &keywords["verbs"]);
|
let verbs = Keywords::create("verbs", &keywords["verbs"]);
|
||||||
@ -78,8 +96,12 @@ impl Judgement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut result = JudgementResult::LikelyScam;
|
let mut result = JudgementResult::LikelyScam;
|
||||||
if count_all == 0 { result = JudgementResult::Ok }
|
if count_all == 0 {
|
||||||
if count_all < total { result = JudgementResult::MaybeScam }
|
result = JudgementResult::Ok
|
||||||
|
}
|
||||||
|
if count_all < total {
|
||||||
|
result = JudgementResult::MaybeScam
|
||||||
|
}
|
||||||
|
|
||||||
// Send message
|
// Send message
|
||||||
let msg = RoomMessageEventContent::text_html(
|
let msg = RoomMessageEventContent::text_html(
|
||||||
@ -90,11 +112,16 @@ impl Judgement {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn alert(room: &Joined, event: &OriginalRoomMessageEvent, result: JudgementResult, is_reply: bool) -> anyhow::Result<()> {
|
pub async fn alert(
|
||||||
|
room: &Joined,
|
||||||
|
event: &OriginalRoomMessageEvent,
|
||||||
|
result: JudgementResult,
|
||||||
|
is_reply: bool,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
let mut responses = CONFIG.responses.clone();
|
let mut responses = CONFIG.responses.clone();
|
||||||
let responses = responses.as_object_mut().unwrap();
|
let responses = responses.as_object_mut().unwrap();
|
||||||
|
|
||||||
// Add stats to end of response
|
// Determine which message to send
|
||||||
let section = if is_reply {
|
let section = if is_reply {
|
||||||
responses["reply"].as_object().unwrap()
|
responses["reply"].as_object().unwrap()
|
||||||
} else {
|
} else {
|
||||||
@ -117,12 +144,18 @@ impl Judgement {
|
|||||||
|
|
||||||
// Send reaction
|
// Send reaction
|
||||||
if !is_reply {
|
if !is_reply {
|
||||||
room.send_raw(json!({
|
room.send_raw(
|
||||||
|
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", None).await.expect("Couldn't send reaction");
|
}}),
|
||||||
|
"m.reaction",
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.expect("Couldn't send reaction");
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -19,7 +19,6 @@ impl std::fmt::Display for KeywordCategory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl KeywordCategory {
|
impl KeywordCategory {
|
||||||
pub fn to_json_var(&self) -> &str {
|
pub fn to_json_var(&self) -> &str {
|
||||||
use KeywordCategory::*;
|
use KeywordCategory::*;
|
||||||
@ -38,7 +37,7 @@ impl KeywordCategory {
|
|||||||
"verbs" => Ok(Verb),
|
"verbs" => Ok(Verb),
|
||||||
"currencies" => Ok(Currency),
|
"currencies" => Ok(Currency),
|
||||||
"socials" => Ok(Social),
|
"socials" => Ok(Social),
|
||||||
_ => Err(())
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,10 +53,9 @@ impl KeywordCategory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct Keywords {
|
pub struct Keywords {
|
||||||
pub category: KeywordCategory,
|
pub category: KeywordCategory,
|
||||||
pub words: Vec<Value>
|
pub words: Vec<Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Keywords {
|
impl Keywords {
|
||||||
@ -69,7 +67,7 @@ impl Keywords {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
category,
|
category,
|
||||||
words: v.to_vec()
|
words: v.to_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
80
src/main.rs
80
src/main.rs
@ -1,22 +1,27 @@
|
|||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
room::Room,
|
room::Room,
|
||||||
ruma::{events::room::message::{
|
ruma::{
|
||||||
MessageType, OriginalSyncRoomMessageEvent, Relation, RoomMessageEvent
|
events::room::message::{
|
||||||
}, OwnedRoomId},
|
MessageType, OriginalSyncRoomMessageEvent, Relation, RoomMessageEvent,
|
||||||
|
},
|
||||||
|
OwnedRoomId,
|
||||||
|
},
|
||||||
Error, LoopCtrl,
|
Error, LoopCtrl,
|
||||||
};
|
};
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub mod matrix;
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod keywords;
|
|
||||||
pub mod judge;
|
pub mod judge;
|
||||||
|
pub mod keywords;
|
||||||
|
pub mod matrix;
|
||||||
|
|
||||||
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 orig_event = event.to_owned().into_full_event(OwnedRoomId::from(room.room_id()));
|
let orig_event = event
|
||||||
|
.to_owned()
|
||||||
|
.into_full_event(OwnedRoomId::from(room.room_id()));
|
||||||
|
|
||||||
// Ignore non-text
|
// Ignore non-text
|
||||||
let MessageType::Text(text_content) = event.to_owned().content.msgtype else {
|
let MessageType::Text(text_content) = event.to_owned().content.msgtype else {
|
||||||
@ -24,14 +29,24 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Too short to be a scam lol
|
// Too short to be a scam lol
|
||||||
if text_content.body.chars().count() < 12 { return Ok(()) }
|
if text_content.body.chars().count() < 12 {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let text_content = text_content.body.to_lowercase();
|
let text_content = text_content.body.to_lowercase();
|
||||||
|
|
||||||
let debug = text_content.contains(";spdebug");
|
let debug = text_content.contains(";spdebug");
|
||||||
|
|
||||||
// Ignore own messages
|
// Ignore own messages
|
||||||
if !debug && event.sender == room.client().user_id().expect("Couldn't get user_id").to_string() { return Ok(()) }
|
if !debug
|
||||||
|
&& event.sender
|
||||||
|
== room
|
||||||
|
.client()
|
||||||
|
.user_id()
|
||||||
|
.expect("Couldn't get user_id")
|
||||||
|
.to_string()
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let judgement = judge::Judgement { text: text_content };
|
let judgement = judge::Judgement { text: text_content };
|
||||||
|
|
||||||
@ -48,13 +63,22 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => None
|
_ => None,
|
||||||
} {
|
} {
|
||||||
let event = event.as_original().unwrap();
|
let event = event.as_original().unwrap();
|
||||||
let content = event.content.to_owned().body().to_lowercase();
|
let content = event.content.to_owned().body().to_lowercase();
|
||||||
|
|
||||||
if !debug && event.sender == room.client().user_id().expect("Couldn't get user_id").to_string() { return Ok(()) }
|
if !debug
|
||||||
|
&& event.sender
|
||||||
|
== room
|
||||||
|
.client()
|
||||||
|
.user_id()
|
||||||
|
.expect("Couldn't get user_id")
|
||||||
|
.to_string()
|
||||||
|
{
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let reply_judgement = judge::Judgement { text: content };
|
let reply_judgement = judge::Judgement { text: content };
|
||||||
|
|
||||||
@ -67,7 +91,13 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
|
|||||||
judge::JudgementResult::Ok => (),
|
judge::JudgementResult::Ok => (),
|
||||||
judge::JudgementResult::MaybeScam => (),
|
judge::JudgementResult::MaybeScam => (),
|
||||||
judge::JudgementResult::LikelyScam => {
|
judge::JudgementResult::LikelyScam => {
|
||||||
judge::Judgement::alert(&room, &orig_event, judge::JudgementResult::LikelyScam, true).await?;
|
judge::Judgement::alert(
|
||||||
|
&room,
|
||||||
|
&orig_event,
|
||||||
|
judge::JudgementResult::LikelyScam,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,7 +108,13 @@ async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) -> any
|
|||||||
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 => {
|
||||||
judge::Judgement::alert(&room, &orig_event, judge::JudgementResult::LikelyScam, false).await?;
|
judge::Judgement::alert(
|
||||||
|
&room,
|
||||||
|
&orig_event,
|
||||||
|
judge::JudgementResult::LikelyScam,
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,9 +135,15 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
let (client, sync_token) = if session_file.exists() {
|
let (client, sync_token) = if session_file.exists() {
|
||||||
matrix::restore_session(&session_file).await?
|
matrix::restore_session(&session_file).await?
|
||||||
} else if args.len() > 1 {
|
} else if args.len() > 1 {
|
||||||
(matrix::login(&data_dir, &session_file, args.get(1).unwrap().to_owned()).await?, None)
|
(
|
||||||
|
matrix::login(&data_dir, &session_file, args.get(1).unwrap().to_owned()).await?,
|
||||||
|
None,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
anyhow::bail!("No previous session found, please run \"{} <MXID>\"", args.get(0).unwrap());
|
anyhow::bail!(
|
||||||
|
"No previous session found, please run \"{} <MXID>\"",
|
||||||
|
args.get(0).unwrap()
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
let (client, sync_settings) = match matrix::sync(client, sync_token).await {
|
let (client, sync_settings) = match matrix::sync(client, sync_token).await {
|
||||||
@ -114,7 +156,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
|
|
||||||
client.add_event_handler(on_room_message);
|
client.add_event_handler(on_room_message);
|
||||||
|
|
||||||
client.sync_with_result_callback(sync_settings, |sync_result| async move {
|
client
|
||||||
|
.sync_with_result_callback(sync_settings, |sync_result| async move {
|
||||||
let response = sync_result?;
|
let response = sync_result?;
|
||||||
|
|
||||||
matrix::persist_sync_token(response.next_batch)
|
matrix::persist_sync_token(response.next_batch)
|
||||||
@ -122,7 +165,8 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.map_err(|err| Error::UnknownError(err.into()))?;
|
.map_err(|err| Error::UnknownError(err.into()))?;
|
||||||
|
|
||||||
Ok(LoopCtrl::Continue)
|
Ok(LoopCtrl::Continue)
|
||||||
}).await?;
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
config::SyncSettings, ruma::api::client::filter::FilterDefinition, Client, Session
|
config::SyncSettings, ruma::api::client::filter::FilterDefinition, Client, Session,
|
||||||
};
|
};
|
||||||
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
use rand::{distributions::Alphanumeric, thread_rng, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::{Value, from_str};
|
|
||||||
use std::path::{Path, PathBuf};
|
|
||||||
use reqwest::Client as http;
|
use reqwest::Client as http;
|
||||||
use rpassword::prompt_password;
|
use rpassword::prompt_password;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{from_str, Value};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@ -24,7 +24,6 @@ pub struct FullSession {
|
|||||||
sync_token: Option<String>,
|
sync_token: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Matrix Login & Init
|
// Matrix Login & Init
|
||||||
//
|
//
|
||||||
@ -98,7 +97,7 @@ pub async fn build_client(data_dir: &Path, hs: String) -> anyhow::Result<(Client
|
|||||||
db_path,
|
db_path,
|
||||||
passphrase,
|
passphrase,
|
||||||
},
|
},
|
||||||
))
|
));
|
||||||
}
|
}
|
||||||
Err(error) => match &error {
|
Err(error) => match &error {
|
||||||
matrix_sdk::ClientBuildError::AutoDiscovery(_)
|
matrix_sdk::ClientBuildError::AutoDiscovery(_)
|
||||||
@ -141,7 +140,10 @@ pub async fn resolve_homeserver(homeserver: String) -> anyhow::Result<String> {
|
|||||||
hs.pop();
|
hs.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
let ident = http::new().get(format!("{hs}/.well-known/matrix/client")).send().await;
|
let ident = http::new()
|
||||||
|
.get(format!("{hs}/.well-known/matrix/client"))
|
||||||
|
.send()
|
||||||
|
.await;
|
||||||
match ident {
|
match ident {
|
||||||
Ok(r) => {
|
Ok(r) => {
|
||||||
let body = r.text().await?;
|
let body = r.text().await?;
|
||||||
@ -150,13 +152,10 @@ pub async fn resolve_homeserver(homeserver: String) -> anyhow::Result<String> {
|
|||||||
let discovered = json["m.homeserver"]["base_url"].as_str().unwrap();
|
let discovered = json["m.homeserver"]["base_url"].as_str().unwrap();
|
||||||
|
|
||||||
Ok(discovered.to_string())
|
Ok(discovered.to_string())
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => Err(e.into()),
|
||||||
Err(e.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Persistence
|
// Persistence
|
||||||
|
Loading…
Reference in New Issue
Block a user