Skip to content

Commit

Permalink
Merge branch 'master' into clippy
Browse files Browse the repository at this point in the history
  • Loading branch information
progval committed May 4, 2024
2 parents 94062fd + ee0a9cc commit 21883fe
Show file tree
Hide file tree
Showing 16 changed files with 321 additions and 215 deletions.
160 changes: 82 additions & 78 deletions sable_ircd/src/command/handlers/chathistory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ fn handle_chathistory(
}
"LATEST" => {
let target = arg_1;
let from_ts = match arg_2 {
let to_ts = match arg_2 {
"*" => None,
_ => Some(parse_msgref(subcommand, Some(target), arg_2)?),
};
Expand All @@ -92,13 +92,21 @@ fn handle_chathistory(
return Ok(());
}

send_history_for_target_reverse(
server, response, source, subcommand, target, from_ts, None, limit,
send_history_for_target(
server,
&response,
source,
subcommand,
&target,
None,
to_ts,
limit,
Some(0), // forward limit
)?;
}
"BEFORE" => {
let target = arg_1;
let end_ts = parse_msgref(subcommand, Some(target), arg_2)?;
let from_ts = parse_msgref(subcommand, Some(target), arg_2)?;

let limit = arg_3.parse().ok();
if limit.is_none() {
Expand All @@ -111,15 +119,16 @@ fn handle_chathistory(
return Ok(());
}

send_history_for_target_reverse(
send_history_for_target(
server,
response,
source,
subcommand,
target,
Some(from_ts),
None,
Some(end_ts),
limit,
Some(0), // forward limit
)?;
}
"AFTER" => {
Expand All @@ -137,14 +146,15 @@ fn handle_chathistory(
return Ok(());
}

send_history_for_target_forward(
send_history_for_target(
server,
response,
source,
subcommand,
target,
Some(start_ts),
None,
Some(0), // backward limit
limit,
)?;
}
Expand All @@ -165,25 +175,16 @@ fn handle_chathistory(
}
};

send_history_for_target_reverse(
server,
response,
source,
subcommand,
target,
Some(around_ts),
None,
Some(limit / 2),
)?;
send_history_for_target_forward(
send_history_for_target(
server,
response,
source,
subcommand,
target,
Some(around_ts),
None,
Some(limit / 2),
Some(limit / 2), // backward limit
Some(limit / 2), // forward limit
)?;
}
"BETWEEN" => {
Expand All @@ -202,14 +203,15 @@ fn handle_chathistory(
return Ok(());
}

send_history_for_target_forward(
send_history_for_target(
server,
response,
source,
subcommand,
target,
Some(start_ts),
Some(end_ts),
Some(0), // backward limit
limit,
)?;
}
Expand Down Expand Up @@ -291,91 +293,86 @@ fn list_targets(
}
}

fn send_history_for_target_forward(
fn send_history_for_target(
server: &ClientServer,
into: impl MessageSink,
source: &wrapper::User,
subcommand: &str,
target: &str,
from_ts: Option<i64>,
to_ts: Option<i64>,
limit: Option<usize>,
backward_limit: Option<usize>,
forward_limit: Option<usize>,
) -> CommandResult {
let log = server.node().history();
let mut entries = Vec::new();

for entry in log.entries_for_user(source.id()) {
if matches!(from_ts, Some(ts) if entry.timestamp <= ts) {
// Skip over until we hit the timestamp window we're interested in
continue;
}
if matches!(to_ts, Some(ts) if entry.timestamp >= ts) {
// If we hit this then we've passed the requested window and should stop
break;
}
let mut backward_entries = Vec::new();
let mut forward_entries = Vec::new();

if backward_limit != Some(0) {
let from_ts = if forward_limit == Some(0) {
from_ts
} else {
// HACK: This is AROUND so we want to capture messages whose timestamp matches exactly
// (it's a message in the middle of the range)
from_ts.map(|from_ts| from_ts + 1)
};

for entry in log.entries_for_user_reverse(source.id()) {
if matches!(from_ts, Some(ts) if entry.timestamp >= ts) {
// Skip over until we hit the timestamp window we're interested in
continue;
}
if matches!(to_ts, Some(ts) if entry.timestamp <= ts) {
// If we hit this then we've passed the requested window and should stop
break;
}

if let Some(event_target) = target_name_for_entry(source.id(), entry) {
if event_target == target {
entries.push(entry);
if let Some(event_target) = target_name_for_entry(source.id(), entry) {
if event_target == target {
backward_entries.push(entry);
}
}
}

if matches!(limit, Some(limit) if limit <= entries.len()) {
break;
if matches!(backward_limit, Some(limit) if limit <= backward_entries.len()) {
break;
}
}
}

send_history_entries(into, subcommand, target, entries.into_iter())
}

// As above, but work backwards
fn send_history_for_target_reverse(
server: &ClientServer,
into: impl MessageSink,
source: &wrapper::User,
subcommand: &str,
target: &str,
from_ts: Option<i64>,
to_ts: Option<i64>,
limit: Option<usize>,
) -> CommandResult {
let log = server.node().history();
let mut entries = Vec::new();

for entry in log.entries_for_user_reverse(source.id()) {
if matches!(from_ts, Some(ts) if entry.timestamp <= ts) {
// Skip over until we hit the timestamp window we're interested in
continue;
}
if matches!(to_ts, Some(ts) if entry.timestamp >= ts) {
// If we hit this then we've passed the requested window and should stop
break;
}
if forward_limit != Some(0) {
for entry in log.entries_for_user(source.id()) {
if matches!(from_ts, Some(ts) if entry.timestamp <= ts) {
// Skip over until we hit the timestamp window we're interested in
continue;
}
if matches!(to_ts, Some(ts) if entry.timestamp >= ts) {
// If we hit this then we've passed the requested window and should stop
break;
}

if let Some(event_target) = target_name_for_entry(source.id(), entry) {
if event_target == target {
entries.push(entry);
if let Some(event_target) = target_name_for_entry(source.id(), entry) {
if event_target == target {
forward_entries.push(entry);
}
}
}

if matches!(limit, Some(limit) if limit <= entries.len()) {
break;
if matches!(forward_limit, Some(limit) if limit <= forward_entries.len()) {
break;
}
}
}

// "The order of returned messages within the batch is implementation-defined, but SHOULD be
// ascending time order or some approximation thereof, regardless of the subcommand used."
// -- https://ircv3.net/specs/extensions/chathistory#returned-message-notes
send_history_entries(into, subcommand, target, entries.into_iter().rev())
send_history_entries(into, subcommand, target, backward_entries, forward_entries)
}

fn send_history_entries<'a>(
into: impl MessageSink,
subcommand: &str,
target: &str,
entries: impl ExactSizeIterator<Item = &'a HistoryLogEntry>,
backward_entries: Vec<&'a HistoryLogEntry>,
forward_entries: Vec<&'a HistoryLogEntry>,
) -> CommandResult {
if entries.len() == 0 {
if backward_entries.len() == 0 && forward_entries.len() == 0 {
into.send(message::Fail::new(
"CHATHISTORY",
"INVALID_TARGET",
Expand All @@ -388,7 +385,14 @@ fn send_history_entries<'a>(
.with_arguments(&[target])
.start();

for entry in entries {
// "The order of returned messages within the batch is implementation-defined, but SHOULD be
// ascending time order or some approximation thereof, regardless of the subcommand used."
// -- https://ircv3.net/specs/extensions/chathistory#returned-message-notes
for entry in backward_entries
.into_iter()
.rev()
.chain(forward_entries.into_iter())
{
entry.send_to(&batch, entry)?;
}
}
Expand Down
10 changes: 5 additions & 5 deletions sable_ircd/src/command/handlers/mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ async fn handle_user_mode(
for c in mode_str.chars() {
if let Ok(d) = Direction::try_from(c) {
dir = d;
} else if let Some(flag) = UserModeSet::flag_for(c) {
} else if let Some(flag) = UserModeFlag::from_mode_char(c) {
if server.policy().can_set_umode(source, flag).is_err() {
continue;
}
Expand Down Expand Up @@ -125,7 +125,7 @@ async fn handle_channel_mode(
for c in mode_str.chars() {
if let Ok(d) = Direction::try_from(c) {
dir = d;
} else if let Some(flag) = ChannelModeSet::flag_for(c) {
} else if let Some(flag) = ChannelModeFlag::from_mode_char(c) {
server.policy().can_change_mode(source, &chan, flag)?;
match dir {
Direction::Add => {
Expand All @@ -136,7 +136,7 @@ async fn handle_channel_mode(
}
_ => {}
}
} else if let Some(flag) = MembershipFlagSet::flag_for(c) {
} else if let Some(flag) = MembershipFlagFlag::from_mode_char(c) {
let target = args.next::<wrapper::User>()?;
let membership = target
.is_in_channel(chan.id())
Expand Down Expand Up @@ -166,7 +166,7 @@ async fn handle_channel_mode(
removed: perm_removed,
};
cmd.new_event_with_response(membership.id(), detail).await;
} else if let Some(list_type) = ListModeType::from_char(c) {
} else if let Some(list_type) = ListModeType::from_mode_char(c) {
let list = chan.list(list_type);

if dir == Direction::Query || args.is_empty() {
Expand Down Expand Up @@ -202,7 +202,7 @@ async fn handle_channel_mode(
}
}
}
} else if let Some(_key_type) = KeyModeType::from_char(c) {
} else if let Some(_key_type) = KeyModeType::from_mode_char(c) {
match dir {
// Can't query keys
Direction::Query => (),
Expand Down
14 changes: 14 additions & 0 deletions sable_ircd/src/command/handlers/who.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ use super::*;
use crate::capability::ClientCapability;
use crate::utils::make_numeric;

const MAX_RESULTS: usize = 10;

#[command_handler("WHO")]
fn handle_who(
server: &ClientServer,
Expand Down Expand Up @@ -31,6 +33,18 @@ fn handle_who(
None, // membership
);
}
} else {
let nick_pattern = NicknameMatcher::new(Pattern::new(target.to_owned()));
network
.users_by_nick_pattern(&nick_pattern)
.filter(|user| server.policy().can_list_user(&source, user).is_ok())
.take(MAX_RESULTS)
.for_each(|user| {
send_who_reply(
response, &user, None, // channel
None, // membership
);
});
}

// If nick/channel is not found, EndOfWho should be the only numeric we send
Expand Down
14 changes: 14 additions & 0 deletions sable_ircd/src/command/plumbing/handler.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
use super::*;

// TODO: once rustc implements support for it, use `if(not(Self::Output=CommandResult))`
// to pick the right note to display.
#[diagnostic::on_unimplemented(
message = "Invalid command handler",
label = "`{Self}` is not a valid command handler",
note = "All parameter types must implement `AmbientArgument` or `PositionalArgument`",
note = "Return type must be `CommandResult`"
)]
pub trait HandlerFn<'ctx, Ambient, Positional> {
fn call(&self, ctx: &'ctx dyn Command, args: ArgListIter<'ctx>) -> CommandResult;
}

#[diagnostic::on_unimplemented(
message = "Invalid command handler",
label = "`{Self}` is not a valid command handler",
note = "All parameter types must implement `AmbientArgument` or `PositionalArgument`",
note = "Return type must be `CommandResult`"
)]
pub trait AsyncHandlerFn<'ctx, Ambient, Positional>: Send + Sync {
fn call(
&'ctx self,
Expand Down
4 changes: 2 additions & 2 deletions sable_ircd/src/messages/send_history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl SendHistoryItem for update::ChannelTopicChange {

impl SendHistoryItem for update::ListModeAdded {
fn send_to(&self, conn: impl MessageSink, from_entry: &HistoryLogEntry) -> HandleResult {
let text = format!("+{} {}", self.list_type.mode_letter(), self.pattern);
let text = format!("+{} {}", self.list_type.mode_char(), self.pattern);
let message =
message::Mode::new(&self.set_by, &self.channel, &text).with_tags_from(from_entry);
conn.send(message);
Expand All @@ -168,7 +168,7 @@ impl SendHistoryItem for update::ListModeAdded {

impl SendHistoryItem for update::ListModeRemoved {
fn send_to(&self, conn: impl MessageSink, from_entry: &HistoryLogEntry) -> HandleResult {
let text = format!("-{} {}", self.list_type.mode_letter(), self.pattern);
let text = format!("-{} {}", self.list_type.mode_char(), self.pattern);
let message =
message::Mode::new(&self.removed_by, &self.channel, &text).with_tags_from(from_entry);
conn.send(message);
Expand Down
Loading

0 comments on commit 21883fe

Please sign in to comment.