Skip to content

Commit

Permalink
Merge pull request #221 from andymandias/smart-message-filter
Browse files Browse the repository at this point in the history
Add Smart Message Filter
  • Loading branch information
casperstorm authored Feb 28, 2024
2 parents 6c39210 + 5afac0c commit 8b48fdb
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 25 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Changed:
- `hidden_server_messages` has been changed to `server_messages` and additional customization has been added:
- Exclude messages [join, part, quit].
- Adjust username format.
- Exclude server messages for users who have not messaged in the last X seconds

Fixed:

Expand Down
10 changes: 6 additions & 4 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,18 @@ buffer:
input_visibility: Always

# Control different server messages.
# - exclude [boolean]: exclude the message from showing
# - exclude [All, None, !Smart seconds]:
# - Smart will show a server message if the user has sent a message
# in the given time interval (seconds) prior to the server message
# - user_format [Short, Full]: controls the username formatting
server_messages:
join:
exclude: true
exclude: All
username_format: Short
part:
exclude: false
exclude: None
quit:
exclude: false
exclude: !Smart 1200

# Channel buffer settings
channel:
Expand Down
18 changes: 13 additions & 5 deletions data/src/config/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ pub struct Buffer {
pub server_messages: ServerMessages,
}

#[derive(Debug, Copy, Clone, Default, Deserialize)]
pub enum Exclude {
#[default]
All,
None,
Smart(i64),
}

#[derive(Debug, Clone, Default, Deserialize)]
pub struct ServerMessages {
#[serde(default)]
Expand All @@ -33,18 +41,18 @@ pub struct ServerMessages {

impl ServerMessages {
pub fn get(&self, server: &source::Server) -> ServerMessage {
match server {
source::Server::Join => self.join,
source::Server::Part => self.part,
source::Server::Quit => self.quit,
match server.kind() {
source::server::Kind::Join => self.join,
source::server::Kind::Part => self.part,
source::server::Kind::Quit => self.quit,
}
}
}

#[derive(Debug, Copy, Clone, Default, Deserialize)]
pub struct ServerMessage {
#[serde(default)]
pub exclude: bool,
pub exclude: Exclude,
#[serde(default)]
pub username_format: UsernameFormat,
}
Expand Down
61 changes: 56 additions & 5 deletions data/src/history/manager.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use std::collections::{HashMap, HashSet};

use chrono::{DateTime, Utc};
use futures::future::BoxFuture;
use futures::{future, Future, FutureExt};
use itertools::Itertools;
use tokio::time::Instant;

use crate::config::buffer::ServerMessages;
use crate::config::buffer::{Exclude, ServerMessages};
use crate::history::{self, History};
use crate::message::{self, Limit};
use crate::time::Posix;
Expand Down Expand Up @@ -437,14 +438,47 @@ impl Data {
return None;
};

let mut most_recent_messages = HashMap::<Nick, DateTime<Utc>>::new();

let filtered = messages
.iter()
.filter(|message| {
if let message::Source::Server(Some(source)) = message.target.source() {
!server_messages.get(source).exclude
} else {
.filter(|message| match message.target.source() {
message::Source::Server(Some(source)) => {
let source_config = server_messages.get(source);

match source_config.exclude {
Exclude::All => false,
Exclude::None => true,
Exclude::Smart(seconds) => {
if let Some(nick) = source.nick() {
!smart_filter_message(
message,
&seconds,
most_recent_messages.get(nick),
)
} else if let Some(nickname) =
message.text.split(' ').collect::<Vec<_>>().get(1)
{
let nick = Nick::from(*nickname);

!smart_filter_message(
message,
&seconds,
most_recent_messages.get(&nick),
)
} else {
true
}
}
}
}
crate::message::Source::User(message_user) => {
most_recent_messages
.insert(message_user.nickname().to_owned(), message.server_time);

true
}
_ => true,
})
.collect::<Vec<_>>();

Expand Down Expand Up @@ -507,6 +541,23 @@ impl Data {
}
}

fn smart_filter_message(
message: &crate::Message,
seconds: &i64,
most_recent_message_server_time: Option<&DateTime<Utc>>,
) -> bool {
let Some(server_time) = most_recent_message_server_time else {
return true;
};

let duration_seconds = message
.server_time
.signed_duration_since(*server_time)
.num_seconds();

duration_seconds > *seconds
}

#[derive(Debug, Clone)]
pub enum Broadcast {
Connecting,
Expand Down
10 changes: 8 additions & 2 deletions data/src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,17 @@ fn target(message: Encoded, our_nick: &Nick) -> Option<Target> {
}),
Command::PART(channel, _) => Some(Target::Channel {
channel,
source: source::Source::Server(Some(source::Server::Part)),
source: source::Source::Server(Some(source::Server::new(
source::server::Kind::Part,
Some(user?.nickname().to_owned()),
))),
}),
Command::JOIN(channel, _) => Some(Target::Channel {
channel,
source: source::Source::Server(Some(source::Server::Join)),
source: source::Source::Server(Some(source::Server::new(
source::server::Kind::Join,
Some(user?.nickname().to_owned()),
))),
}),
Command::Numeric(RPL_TOPIC | RPL_TOPICWHOTIME | RPL_CHANNELMODEIS, params) => {
let channel = params.get(1)?.clone();
Expand Down
5 changes: 4 additions & 1 deletion data/src/message/broadcast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,10 @@ pub fn quit(
channels,
queries,
false,
Cause::Server(Some(source::Server::Quit)),
Cause::Server(Some(source::Server::new(
source::server::Kind::Quit,
Some(user.nickname().to_owned()),
))),
text,
)
}
Expand Down
59 changes: 51 additions & 8 deletions data/src/message/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use serde::{Deserialize, Serialize};

use crate::User;

pub use self::server::Server;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Source {
User(User),
Expand All @@ -10,14 +12,6 @@ pub enum Source {
Internal(Internal),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Server {
Join,
Part,
Quit,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Internal {
Status(Status),
Expand All @@ -28,3 +22,52 @@ pub enum Status {
Success,
Error,
}

pub mod server {
#![allow(deprecated)]
use serde::{Deserialize, Serialize};

use crate::user::Nick;

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(untagged)]
pub enum Server {
#[deprecated(note = "use Server::Details")]
Kind(Kind),
Details(Details),
}

impl Server {
pub fn new(kind: Kind, nick: Option<Nick>) -> Self {
Self::Details(Details { kind, nick })
}

pub fn kind(&self) -> Kind {
match self {
Server::Kind(kind) => *kind,
Server::Details(details) => details.kind,
}
}

pub fn nick(&self) -> Option<&Nick> {
match self {
Server::Kind(_) => None,
Server::Details(details) => details.nick.as_ref(),
}
}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Kind {
Join,
Part,
Quit,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Details {
pub kind: Kind,
pub nick: Option<Nick>,
}
}

0 comments on commit 8b48fdb

Please sign in to comment.