Skip to content

Commit cd444d2

Browse files
committed
feat: Case-insensitive search for non-ASCII chat and contact names (#7477)
This makes `Contact::get_all()` and `Chatlist::try_load()` case-insensitive for non-ASCII chat and contact names as well. The same approach as in f6f4ccc "feat: Case-insensitive search for non-ASCII messages (#5052)" is used: `chats.name_normalized` and `contacts.name_normalized` colums are added which store lowercased/normalized names (for a contact, if the name is unset, it's a normalized authname). If a normalized name is the same as the chat/contact name, it's not stored to reduce the db size. A db migration is added for 10000 random chats and the same number of the most recently seen contacts, for users it will probably migrate all chats/contacts and for bots which may have more data it's not important.
1 parent aa5ee19 commit cd444d2

File tree

10 files changed

+212
-88
lines changed

10 files changed

+212
-88
lines changed

src/calls.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@ use crate::context::{Context, WeakContext};
1010
use crate::events::EventType;
1111
use crate::headerdef::HeaderDef;
1212
use crate::log::warn;
13-
use crate::message::{self, Message, MsgId, Viewtype};
13+
use crate::message::{Message, MsgId, Viewtype};
1414
use crate::mimeparser::{MimeMessage, SystemMessage};
1515
use crate::net::dns::lookup_host_with_cache;
1616
use crate::param::Param;
17-
use crate::tools::time;
17+
use crate::tools::{normalize_text, time};
1818
use anyhow::{Context as _, Result, ensure};
1919
use sdp::SessionDescription;
2020
use serde::Serialize;
@@ -86,7 +86,7 @@ impl CallInfo {
8686
.sql
8787
.execute(
8888
"UPDATE msgs SET txt=?, txt_normalized=? WHERE id=?",
89-
(text, message::normalize_text(text), self.msg.id),
89+
(text, normalize_text(text), self.msg.id),
9090
)
9191
.await?;
9292
Ok(())

src/chat.rs

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::sync::{self, Sync::*, SyncData};
4545
use crate::tools::{
4646
IsNoneOrEmpty, SystemTime, buf_compress, create_broadcast_secret, create_id,
4747
create_outgoing_rfc724_mid, create_smeared_timestamp, create_smeared_timestamps, get_abs_path,
48-
gm2local_offset, smeared_time, time, truncate_msg_text,
48+
gm2local_offset, normalize_text, smeared_time, time, truncate_msg_text,
4949
};
5050
use crate::webxdc::StatusUpdateSerial;
5151
use crate::{chatlist_events, imap};
@@ -286,10 +286,11 @@ impl ChatId {
286286
let timestamp = cmp::min(timestamp, smeared_time(context));
287287
let row_id =
288288
context.sql.insert(
289-
"INSERT INTO chats (type, name, grpid, blocked, created_timestamp, protected, param) VALUES(?, ?, ?, ?, ?, 0, ?);",
289+
"INSERT INTO chats (type, name, name_normalized, grpid, blocked, created_timestamp, protected, param) VALUES(?, ?, ?, ?, ?, ?, 0, ?)",
290290
(
291291
chattype,
292292
&grpname,
293+
normalize_text(&grpname),
293294
grpid,
294295
create_blocked,
295296
timestamp,
@@ -782,7 +783,7 @@ impl ChatId {
782783
time(),
783784
msg.viewtype,
784785
&msg.text,
785-
message::normalize_text(&msg.text),
786+
normalize_text(&msg.text),
786787
msg.param.to_string(),
787788
msg.in_reply_to.as_deref().unwrap_or_default(),
788789
msg.id,
@@ -823,7 +824,7 @@ impl ChatId {
823824
msg.viewtype,
824825
MessageState::OutDraft,
825826
&msg.text,
826-
message::normalize_text(&msg.text),
827+
normalize_text(&msg.text),
827828
msg.param.to_string(),
828829
1,
829830
msg.in_reply_to.as_deref().unwrap_or_default(),
@@ -1919,7 +1920,7 @@ impl Chat {
19191920
msg.viewtype,
19201921
msg.state,
19211922
msg_text,
1922-
message::normalize_text(&msg_text),
1923+
normalize_text(&msg_text),
19231924
&msg.subject,
19241925
msg.param.to_string(),
19251926
msg.hidden,
@@ -1970,7 +1971,7 @@ impl Chat {
19701971
msg.viewtype,
19711972
msg.state,
19721973
msg_text,
1973-
message::normalize_text(&msg_text),
1974+
normalize_text(&msg_text),
19741975
&msg.subject,
19751976
msg.param.to_string(),
19761977
msg.hidden,
@@ -2274,8 +2275,8 @@ async fn update_special_chat_name(
22742275
context
22752276
.sql
22762277
.execute(
2277-
"UPDATE chats SET name=? WHERE id=? AND name!=?",
2278-
(&name, chat_id, &name),
2278+
"UPDATE chats SET name=?, name_normalized=? WHERE id=? AND name!=?",
2279+
(&name, normalize_text(&name), chat_id, &name),
22792280
)
22802281
.await?;
22812282
}
@@ -2388,11 +2389,12 @@ impl ChatIdBlocked {
23882389
.transaction(move |transaction| {
23892390
transaction.execute(
23902391
"INSERT INTO chats
2391-
(type, name, param, blocked, created_timestamp)
2392-
VALUES(?, ?, ?, ?, ?)",
2392+
(type, name, name_normalized, param, blocked, created_timestamp)
2393+
VALUES(?, ?, ?, ?, ?, ?)",
23932394
(
23942395
Chattype::Single,
2395-
chat_name,
2396+
&chat_name,
2397+
normalize_text(&chat_name),
23962398
params.to_string(),
23972399
create_blocked as u8,
23982400
smeared_time,
@@ -2944,7 +2946,7 @@ pub(crate) async fn save_text_edit_to_db(
29442946
"UPDATE msgs SET txt=?, txt_normalized=?, param=? WHERE id=?",
29452947
(
29462948
new_text,
2947-
message::normalize_text(new_text),
2949+
normalize_text(new_text),
29482950
original_msg.param.to_string(),
29492951
original_msg.id,
29502952
),
@@ -3433,9 +3435,15 @@ pub(crate) async fn create_group_ex(
34333435
.sql
34343436
.insert(
34353437
"INSERT INTO chats
3436-
(type, name, grpid, param, created_timestamp)
3437-
VALUES(?, ?, ?, \'U=1\', ?);",
3438-
(Chattype::Group, &chat_name, &grpid, timestamp),
3438+
(type, name, name_normalized, grpid, param, created_timestamp)
3439+
VALUES(?, ?, ?, ?, \'U=1\', ?)",
3440+
(
3441+
Chattype::Group,
3442+
&chat_name,
3443+
normalize_text(&chat_name),
3444+
&grpid,
3445+
timestamp,
3446+
),
34393447
)
34403448
.await?;
34413449

@@ -3519,9 +3527,15 @@ pub(crate) async fn create_out_broadcast_ex(
35193527

35203528
t.execute(
35213529
"INSERT INTO chats
3522-
(type, name, grpid, created_timestamp)
3523-
VALUES(?, ?, ?, ?);",
3524-
(Chattype::OutBroadcast, &chat_name, &grpid, timestamp),
3530+
(type, name, name_normalized, grpid, created_timestamp)
3531+
VALUES(?, ?, ?, ?, ?)",
3532+
(
3533+
Chattype::OutBroadcast,
3534+
&chat_name,
3535+
normalize_text(&chat_name),
3536+
&grpid,
3537+
timestamp,
3538+
),
35253539
)?;
35263540
let chat_id = ChatId::new(t.last_insert_rowid().try_into()?);
35273541

@@ -4094,8 +4108,8 @@ async fn rename_ex(
40944108
context
40954109
.sql
40964110
.execute(
4097-
"UPDATE chats SET name=? WHERE id=?;",
4098-
(new_name.to_string(), chat_id),
4111+
"UPDATE chats SET name=?, name_normalized=? WHERE id=?",
4112+
(&new_name, normalize_text(&new_name), chat_id),
40994113
)
41004114
.await?;
41014115
if chat.is_promoted()
@@ -4529,7 +4543,7 @@ pub async fn add_device_msg_with_importance(
45294543
msg.viewtype,
45304544
state,
45314545
&msg.text,
4532-
message::normalize_text(&msg.text),
4546+
normalize_text(&msg.text),
45334547
msg.param.to_string(),
45344548
rfc724_mid,
45354549
),
@@ -4668,7 +4682,7 @@ pub(crate) async fn add_info_msg_with_cmd(
46684682
Viewtype::Text,
46694683
MessageState::InNoticed,
46704684
text,
4671-
message::normalize_text(text),
4685+
normalize_text(text),
46724686
rfc724_mid,
46734687
ephemeral_timer,
46744688
param.to_string(),
@@ -4710,7 +4724,7 @@ pub(crate) async fn update_msg_text_and_timestamp(
47104724
.sql
47114725
.execute(
47124726
"UPDATE msgs SET txt=?, txt_normalized=?, timestamp=? WHERE id=?;",
4713-
(text, message::normalize_text(text), timestamp, msg_id),
4727+
(text, normalize_text(text), timestamp, msg_id),
47144728
)
47154729
.await?;
47164730
context.emit_msgs_changed(chat_id, msg_id);

src/chatlist.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl Chatlist {
185185
warn!(context, "Cannot update special chat names: {err:#}.")
186186
}
187187

188-
let str_like_cmd = format!("%{query}%");
188+
let str_like_cmd = format!("%{}%", query.to_lowercase());
189189
context
190190
.sql
191191
.query_map_vec(
@@ -201,7 +201,7 @@ impl Chatlist {
201201
ORDER BY timestamp DESC, id DESC LIMIT 1)
202202
WHERE c.id>9 AND c.id!=?2
203203
AND c.blocked!=1
204-
AND c.name LIKE ?3
204+
AND IFNULL(c.name_normalized,c.name) LIKE ?3
205205
AND (NOT ?4 OR EXISTS (SELECT 1 FROM msgs m WHERE m.chat_id = c.id AND m.state == ?5 AND hidden=0))
206206
GROUP BY c.id
207207
ORDER BY IFNULL(m.timestamp,c.created_timestamp) DESC, m.id DESC;",
@@ -472,7 +472,7 @@ mod tests {
472472
use crate::chat::save_msgs;
473473
use crate::chat::{
474474
add_contact_to_chat, create_group, get_chat_contacts, remove_contact_from_chat,
475-
send_text_msg,
475+
send_text_msg, set_chat_name,
476476
};
477477
use crate::receive_imf::receive_imf;
478478
use crate::stock_str::StockMessage;
@@ -482,7 +482,7 @@ mod tests {
482482
use std::time::Duration;
483483

484484
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
485-
async fn test_try_load() {
485+
async fn test_try_load() -> Result<()> {
486486
let mut tcm = TestContextManager::new();
487487
let bob = &tcm.bob().await;
488488
let chat_id1 = create_group(bob, "a chat").await.unwrap();
@@ -552,6 +552,15 @@ mod tests {
552552
.await
553553
.unwrap();
554554
assert_eq!(chats.len(), 1);
555+
556+
let chat_id = create_group(bob, "Δ-chat").await.unwrap();
557+
let chats = Chatlist::try_load(bob, 0, Some("δ"), None).await?;
558+
assert_eq!(chats.len(), 1);
559+
assert_eq!(chats.ids[0].0, chat_id);
560+
set_chat_name(bob, chat_id, "abcδe").await?;
561+
let chats = Chatlist::try_load(bob, 0, Some("Δ"), None).await?;
562+
assert_eq!(chats.len(), 1);
563+
Ok(())
555564
}
556565

557566
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]

0 commit comments

Comments
 (0)