Skip to content

Commit 7f77dd9

Browse files
committed
WIP support for the soju.im/search extension.
1 parent d8975df commit 7f77dd9

File tree

29 files changed

+1785
-236
lines changed

29 files changed

+1785
-236
lines changed

book/src/commands.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ The argument(s) for a command are shown in [tooltips](configuration/tooltips.md)
4444
| `plain` | `p` | Send text with markdown and colors disabled |
4545
| `quit` | | Disconnect from the server with an optional reason |
4646
| `raw` | | Send data to the server without modifying it |
47+
| `search` | | Search message history by content, sender, and/or time[^5] |
4748
| `setname` | | Change your realname[^5] |
4849
| `sysinfo` | | Send system information (OS, CPU, memory, GPU, uptime) |
4950
| `topic` | `t` | Retrieve the topic of a channel or set a new topic[^1] |

data/src/buffer.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ pub enum Internal {
3232
Highlights,
3333
#[strum(serialize = "Channel Discovery")]
3434
ChannelDiscovery(Option<Server>),
35+
#[strum(serialize = "Search Results")]
36+
SearchResults(Server),
3537
}
3638

3739
impl Buffer {
@@ -98,19 +100,19 @@ impl Upstream {
98100
pub fn server_message_target(
99101
self,
100102
source: Option<message::source::Server>,
101-
) -> message::Target {
103+
) -> Option<message::Target> {
102104
match self {
103-
Self::Server(_) => message::Target::Server {
105+
Self::Server(_) => Some(message::Target::Server {
104106
source: message::Source::Server(source),
105-
},
106-
Self::Channel(_, channel) => message::Target::Channel {
107+
}),
108+
Self::Channel(_, channel) => Some(message::Target::Channel {
107109
channel,
108110
source: message::Source::Server(source),
109-
},
110-
Self::Query(_, query) => message::Target::Query {
111+
}),
112+
Self::Query(_, query) => Some(message::Target::Query {
111113
query,
112114
source: message::Source::Server(source),
113-
},
115+
}),
114116
}
115117
}
116118
}
@@ -125,12 +127,14 @@ impl Internal {
125127

126128
pub fn key(&self) -> String {
127129
match self {
128-
Internal::FileTransfers => "file-transfers",
129-
Internal::Logs => "logs",
130-
Internal::Highlights => "highlights",
131-
Internal::ChannelDiscovery(_) => "channel-discovery",
130+
Internal::FileTransfers => "file-transfers".to_string(),
131+
Internal::Logs => "logs".to_string(),
132+
Internal::Highlights => "highlights".to_string(),
133+
Internal::ChannelDiscovery(_) => "channel-discovery".to_string(),
134+
Internal::SearchResults(server) => {
135+
format!("server:{server}:search-results")
136+
}
132137
}
133-
.to_string()
134138
}
135139
}
136140

data/src/client.rs

Lines changed: 184 additions & 124 deletions
Large diffs are not rendered by default.

data/src/client/on_connect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub fn on_connect(
9696
| command::Internal::ChannelDiscovery
9797
| command::Internal::Connect(_)
9898
| command::Internal::Hop(_, _)
99+
| command::Internal::SearchResults(_)
99100
| command::Internal::SysInfo => None,
100101
},
101102
}

data/src/command.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub enum Internal {
2929
/// - Part message
3030
Hop(Option<String>, Option<String>),
3131
ChannelDiscovery,
32+
SearchResults(Option<String>),
3233
Delay(u64),
3334
SysInfo,
3435
Detach(Vec<target::Channel>),
@@ -54,6 +55,7 @@ pub enum Irc {
5455
SetName(String),
5556
Notice(String, String),
5657
Raw(String),
58+
Search(String),
5759
Unknown(String, Vec<String>),
5860
Ctcp(ctcp::Command, String, Option<String>),
5961
}
@@ -172,6 +174,18 @@ impl Irc {
172174
supports_echoes.then_some(self.clone()),
173175
)])
174176
}
177+
Irc::Search(search_query) => {
178+
let message_target = message::Target::SearchResults {
179+
target: None,
180+
source: message::Source::Server(None),
181+
};
182+
183+
Some(vec![Message::sent(
184+
message_target,
185+
message::search_query_text(search_query)?,
186+
None,
187+
)])
188+
}
175189
_ => None,
176190
}
177191
}
@@ -204,6 +218,7 @@ enum Kind {
204218
SysInfo,
205219
Detach,
206220
Connect,
221+
Search,
207222
Raw,
208223
}
209224

@@ -238,6 +253,7 @@ impl FromStr for Kind {
238253
"sysinfo" => Ok(Kind::SysInfo),
239254
"detach" => Ok(Kind::Detach),
240255
"connect" => Ok(Kind::Connect),
256+
"search" => Ok(Kind::Search),
241257
_ => Err(()),
242258
}
243259
}
@@ -1079,6 +1095,9 @@ pub fn parse(
10791095
Err(Error::InvalidServerUrl)
10801096
}
10811097
}),
1098+
Kind::Search => validated::<0, 1, true>(args, |_, [text]| {
1099+
Ok(Command::Internal(Internal::SearchResults(text)))
1100+
}),
10821101
},
10831102
Err(()) => Ok(unknown()),
10841103
}
@@ -1188,6 +1207,7 @@ impl TryFrom<Irc> for proto::Command {
11881207
Irc::List(channels, elistcond) => {
11891208
proto::Command::LIST(channels, elistcond)
11901209
}
1210+
Irc::Search(params) => proto::Command::SEARCH(params),
11911211
})
11921212
}
11931213
}

data/src/config/actions.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ pub struct Buffer {
1616
pub click_highlight: BufferAction,
1717
pub click_username: BufferAction,
1818
pub join_channel: Option<BufferAction>,
19+
pub list: BufferAction,
1920
pub local: BufferAction,
2021
pub message_channel: BufferAction,
2122
pub message_user: BufferAction,
23+
pub search: BufferAction,
2224
}
2325

2426
#[derive(Debug, Default, Clone, Deserialize)]

data/src/history.rs

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ pub enum Kind {
3838
Query(Server, target::Query),
3939
Logs,
4040
Highlights,
41+
SearchResults(Server),
4142
}
4243

4344
impl Kind {
@@ -75,7 +76,14 @@ impl Kind {
7576
server: Server,
7677
message: &Message,
7778
) -> Option<Self> {
78-
match &message.target {
79+
Self::from_message_target(server, &message.target)
80+
}
81+
82+
pub fn from_message_target(
83+
server: Server,
84+
message_target: &message::Target,
85+
) -> Option<Self> {
86+
match &message_target {
7987
message::Target::Server { .. } => Some(Self::Server(server)),
8088
message::Target::Channel { channel, .. } => {
8189
Some(Self::Channel(server, channel.clone()))
@@ -85,6 +93,9 @@ impl Kind {
8593
}
8694
message::Target::Logs { .. } => None,
8795
message::Target::Highlights { .. } => None,
96+
message::Target::SearchResults { .. } => {
97+
Some(Self::SearchResults(server))
98+
}
8899
}
89100
}
90101

@@ -105,6 +116,16 @@ impl Kind {
105116
}
106117
Buffer::Internal(buffer::Internal::FileTransfers) => None,
107118
Buffer::Internal(buffer::Internal::ChannelDiscovery(_)) => None,
119+
Buffer::Internal(buffer::Internal::SearchResults(server)) => {
120+
Some(Kind::SearchResults(server))
121+
}
122+
}
123+
}
124+
125+
pub fn ordered_by(&self) -> OrderedBy {
126+
match self {
127+
Kind::SearchResults(_) => OrderedBy::ReceivedAt,
128+
_ => OrderedBy::default(),
108129
}
109130
}
110131
}
@@ -117,6 +138,7 @@ impl Kind {
117138
Kind::Query(server, _) => Some(server),
118139
Kind::Logs => None,
119140
Kind::Highlights => None,
141+
Kind::SearchResults(server) => Some(server),
120142
}
121143
}
122144

@@ -127,6 +149,7 @@ impl Kind {
127149
Kind::Query(_, nick) => Some(Target::Query(nick.clone())),
128150
Kind::Logs => None,
129151
Kind::Highlights => None,
152+
Kind::SearchResults(_) => None,
130153
}
131154
}
132155
}
@@ -141,6 +164,9 @@ impl fmt::Display for Kind {
141164
Kind::Query(server, nick) => write!(f, "user {nick} on {server}"),
142165
Kind::Logs => write!(f, "logs"),
143166
Kind::Highlights => write!(f, "highlights"),
167+
Kind::SearchResults(server) => {
168+
write!(f, "search results from {server}")
169+
}
144170
}
145171
}
146172
}
@@ -159,6 +185,9 @@ impl From<Kind> for Buffer {
159185
}
160186
Kind::Logs => Buffer::Internal(buffer::Internal::Logs),
161187
Kind::Highlights => Buffer::Internal(buffer::Internal::Highlights),
188+
Kind::SearchResults(server) => {
189+
Buffer::Internal(buffer::Internal::SearchResults(server))
190+
}
162191
}
163192
}
164193
}
@@ -241,7 +270,7 @@ pub async fn append(
241270

242271
let mut all_messages = loaded.messages;
243272
messages.into_iter().for_each(|message| {
244-
insert_message(&mut all_messages, message);
273+
insert_message(&mut all_messages, kind.ordered_by(), message);
245274
});
246275

247276
overwrite(kind, &all_messages, read_marker).await
@@ -285,6 +314,9 @@ async fn path(kind: &Kind) -> Result<PathBuf, Error> {
285314
}
286315
Kind::Logs => "logs".to_string(),
287316
Kind::Highlights => "highlights".to_string(),
317+
Kind::SearchResults(server) => {
318+
format!("{server:b}search results")
319+
}
288320
};
289321

290322
let hashed_name = seahash::hash(name.as_bytes());
@@ -416,12 +448,14 @@ impl History {
416448
match self {
417449
History::Partial {
418450
messages,
451+
kind,
419452
last_updated_at,
420453
last_seen,
421454
..
422455
}
423456
| History::Full {
424457
messages,
458+
kind,
425459
last_updated_at,
426460
last_seen,
427461
..
@@ -430,7 +464,7 @@ impl History {
430464

431465
update_last_seen(last_seen, &message);
432466

433-
insert_message(messages, message)
467+
insert_message(messages, kind.ordered_by(), message)
434468
}
435469
}
436470
}
@@ -817,8 +851,15 @@ impl History {
817851
/// this client was replaced by an echo
818852
pub fn insert_message(
819853
messages: &mut Vec<Message>,
854+
ordered_by: OrderedBy,
820855
message: Message,
821856
) -> Option<ReadMarker> {
857+
if messages.is_empty() || matches!(ordered_by, OrderedBy::ReceivedAt) {
858+
messages.push(message);
859+
860+
return None;
861+
}
862+
822863
let fuzz_seconds =
823864
if matches!(message.direction, message::Direction::Received)
824865
&& message.is_echo
@@ -828,12 +869,6 @@ pub fn insert_message(
828869
chrono::Duration::seconds(1)
829870
};
830871

831-
if messages.is_empty() {
832-
messages.push(message);
833-
834-
return None;
835-
}
836-
837872
let start = message.server_time - fuzz_seconds;
838873
let end = message.server_time + fuzz_seconds;
839874

@@ -1001,6 +1036,14 @@ pub struct View<'a> {
10011036
pub max_prefix_chars: Option<usize>,
10021037
pub range_timestamp_extra_chars: Option<usize>,
10031038
pub cleared: bool,
1039+
pub ordered_by: OrderedBy,
1040+
}
1041+
1042+
#[derive(Debug, Clone, Copy, Default, PartialEq)]
1043+
pub enum OrderedBy {
1044+
ReceivedAt,
1045+
#[default]
1046+
ServerTime,
10041047
}
10051048

10061049
#[derive(Debug, thiserror::Error)]

data/src/history/filter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ impl Filter {
269269
Kind::Server(server)
270270
| Kind::Channel(server, _)
271271
| Kind::Query(server, _) => target_server == server,
272-
Kind::Highlights | Kind::Logs => false,
272+
Kind::Highlights | Kind::Logs | Kind::SearchResults(_) => false,
273273
},
274274
}
275275
}

0 commit comments

Comments
 (0)