Skip to content

Commit

Permalink
A more rigorous handling of MSGREFTYPES.
Browse files Browse the repository at this point in the history
  • Loading branch information
andymandias committed May 21, 2024
1 parent 005c4e4 commit a6c1427
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 136 deletions.
21 changes: 10 additions & 11 deletions data/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub enum Event {
ChatHistoryCommand(
ChatHistorySubcommand,
String,
isupport::MessageReferenceType,
Vec<isupport::MessageReferenceType>,
),
ChatHistoryBatchFilter,
ChatHistorySingle(
Expand Down Expand Up @@ -329,8 +329,7 @@ impl Client {
finished.events.push(Event::ChatHistoryCommand(
subcommand.clone(),
chathistory_target.to_string(),
self.chathistory_message_reference_type()
.clone(),
self.chathistory_message_reference_types(),
));
}
}
Expand Down Expand Up @@ -909,7 +908,7 @@ impl Client {
return Some(vec![Event::ChatHistoryCommand(
ChatHistorySubcommand::Latest(server_time(&message)),
channel.clone(),
self.chathistory_message_reference_type(),
self.chathistory_message_reference_types(),
)]);
}
}
Expand Down Expand Up @@ -1204,14 +1203,14 @@ impl Client {
CLIENT_CHATHISTORY_LIMIT
}

pub fn chathistory_message_reference_type(&self) -> isupport::MessageReferenceType {
pub fn chathistory_message_reference_types(&self) -> Vec<isupport::MessageReferenceType> {
if let Some(isupport::Parameter::MSGREFTYPES(message_reference_types)) =
self.isupport.get(&isupport::Kind::MSGREFTYPES)
{
return message_reference_types.first().cloned().unwrap_or_default();
message_reference_types.clone()
} else {
vec![]
}

isupport::MessageReferenceType::default()
}

pub fn chathistory_request(&self, target: &str) -> Option<ChatHistoryRequest> {
Expand Down Expand Up @@ -1542,12 +1541,12 @@ impl Map {
.unwrap_or_default()
}

pub fn get_server_chathistory_message_reference_type(
pub fn get_server_chathistory_message_reference_types(
&self,
server: &Server,
) -> isupport::MessageReferenceType {
) -> Vec<isupport::MessageReferenceType> {
self.client(server)
.map(|client| client.chathistory_message_reference_type())
.map(|client| client.chathistory_message_reference_types())
.unwrap_or_default()
}

Expand Down
90 changes: 41 additions & 49 deletions data/src/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ impl History {
.iter()
.skip(insert_position)
.position(|existing_message| {
is_referenceable_message(existing_message)
is_referenceable_message(existing_message, None)
|| existing_message
.server_time
.signed_duration_since(message.server_time)
Expand Down Expand Up @@ -285,7 +285,7 @@ impl History {
.iter()
.skip(insert_position)
.position(|existing_message| {
is_referenceable_message(existing_message)
is_referenceable_message(existing_message, None)
|| existing_message
.server_time
.signed_duration_since(message.server_time)
Expand All @@ -304,7 +304,7 @@ impl History {
.rev()
.skip(messages.len() - insert_position)
.position(|existing_message| {
is_referenceable_message(existing_message)
is_referenceable_message(existing_message, None)
&& existing_message
.server_time
.signed_duration_since(message.server_time)
Expand Down Expand Up @@ -445,70 +445,62 @@ impl History {

fn get_latest_message(
&self,
message_reference_type: isupport::MessageReferenceType,
message_reference_type: &isupport::MessageReferenceType,
join_server_time: DateTime<Utc>,
) -> Option<&Message> {
match self {
History::Partial { messages, .. } | History::Full { messages, .. } => {
match message_reference_type {
isupport::MessageReferenceType::MessageId => {
messages.iter().rev().find(|message| {
message
.server_time
.signed_duration_since(join_server_time)
.num_seconds()
< 0
&& message.id.is_some()
&& is_referenceable_message(message)
})
}
isupport::MessageReferenceType::Timestamp => {
messages.iter().rev().find(|message| {
message
.server_time
.signed_duration_since(join_server_time)
.num_seconds()
< 0
&& is_referenceable_message(message)
})
}
}
messages.iter().rev().find(|message| {
log::debug!(
"join_server_time {:?} message {:?}",
join_server_time,
message
);
message
.server_time
.signed_duration_since(join_server_time)
.num_seconds()
< 0
&& is_referenceable_message(message, Some(message_reference_type))
})
}
}
}

fn get_oldest_message(
&self,
message_reference_type: isupport::MessageReferenceType,
message_reference_type: &isupport::MessageReferenceType,
) -> Option<&Message> {
match self {
History::Partial { messages, .. } | History::Full { messages, .. } => {
match message_reference_type {
isupport::MessageReferenceType::MessageId => messages
.iter()
.find(|message| message.id.is_some() && is_referenceable_message(message)),
isupport::MessageReferenceType::Timestamp => messages
.iter()
.find(|message| is_referenceable_message(message)),
}
}
History::Partial { messages, .. } | History::Full { messages, .. } => messages
.iter()
.find(|message| is_referenceable_message(message, Some(message_reference_type))),
}
}
}

fn is_referenceable_message(message: &Message) -> bool {
if let message::Source::Server(Some(source)) = message.target.source() {
if matches!(source.kind(), message::source::server::Kind::ReplyTopic) {
return false;
fn is_referenceable_message(
message: &Message,
message_reference_type: Option<&isupport::MessageReferenceType>,
) -> bool {
if matches!(message.target.source(), message::Source::Internal(_)) {
false
} else {
match message_reference_type {
Some(isupport::MessageReferenceType::MessageId) => message
.id
.as_ref()
.is_some_and(|message_id| !message_id.starts_with(':')),
Some(isupport::MessageReferenceType::Timestamp) => message
.id
.as_ref()
.is_some_and(|message_id| message_id.starts_with(':') && message_id != ":"),
None => message
.id
.as_ref()
.is_some_and(|message_id| message_id != ":"),
}
} else if matches!(message.target.source(), message::Source::Internal(_)) {
return false;
}

message
.id
.as_ref()
.is_some_and(|message_id| message_id != ":")
}

#[derive(Debug)]
Expand Down
4 changes: 2 additions & 2 deletions data/src/history/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl Manager {
&self,
server: &Server,
target: &str,
message_reference_type: isupport::MessageReferenceType,
message_reference_type: &isupport::MessageReferenceType,
join_server_time: DateTime<Utc>,
) -> Option<&crate::Message> {
let kind = if proto::is_channel(target) {
Expand All @@ -267,7 +267,7 @@ impl Manager {
&self,
server: &Server,
target: &str,
message_reference_type: isupport::MessageReferenceType,
message_reference_type: &isupport::MessageReferenceType,
) -> Option<&crate::Message> {
let kind = if proto::is_channel(target) {
history::Kind::Channel(target.to_string())
Expand Down
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,15 @@ impl Application for Halloy {
commands.push(command.map(Message::Dashboard));
}
}
data::client::Event::ChatHistoryCommand(subcommand, target, message_reference_type) => {
data::client::Event::ChatHistoryCommand(subcommand, target, message_reference_types) => {
match subcommand {
ChatHistorySubcommand::Latest(join_server_time) => {
dashboard.load_history_now(server.clone(), &target);

let latest_message_reference = dashboard.get_latest_message_reference(
&server,
&target,
message_reference_type,
&message_reference_types,
join_server_time,
);

Expand All @@ -600,7 +600,7 @@ impl Application for Halloy {
let oldest_message_reference = dashboard.get_oldest_message_reference(
&server,
&target,
message_reference_type,
&message_reference_types,
);

self.clients.send_chathistory_request(
Expand Down
Loading

0 comments on commit a6c1427

Please sign in to comment.