Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 80 additions & 3 deletions src/app/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,34 @@ struct FetchedMessage {
media_path: Option<String>,
reply_to_id: Option<i64>,
topic_id: Option<i32>,
/// Sender identity captured with the message, so `contacts` can be
/// populated at store time without any extra API call. `None` when the
/// sender is not a user (e.g. a channel) or is unknown.
sender_contact: Option<SenderContact>,
}

/// A message sender's identity, lifted from the `Peer` that already rides
/// along with every fetched message. Used to upsert `contacts` for free.
struct SenderContact {
user_id: i64,
username: Option<String>,
first_name: String,
last_name: String,
phone: String,
}

/// Extract a [`SenderContact`] from a message's sender peer, if it is a user.
fn sender_contact_from_peer(sender: Option<&Peer>) -> Option<SenderContact> {
match sender {
Some(Peer::User(u)) => Some(SenderContact {
user_id: u.bare_id(),
username: u.username().map(|s| s.to_string()),
first_name: u.first_name().unwrap_or("").to_string(),
last_name: u.last_name().unwrap_or("").to_string(),
phone: u.phone().unwrap_or("").to_string(),
}),
_ => None,
}
}

/// Output representation of a synced message (used for Text/Json/Stream modes)
Expand Down Expand Up @@ -867,7 +895,10 @@ impl App {
latest_ts = Some(msg_ts);
}

let sender_id = msg.sender().map(|s| s.id().bare_id()).unwrap_or(0);
let sender = msg.sender();
let sender_id =
sender.as_ref().map(|s| s.id().bare_id()).unwrap_or(0);
let sender_contact = sender_contact_from_peer(sender);
let from_me = msg.outgoing();
let text = msg.text().to_string();
let reply_to_id = msg.reply_to_message_id().map(|id| id as i64);
Expand Down Expand Up @@ -904,6 +935,7 @@ impl App {
media_path,
reply_to_id,
topic_id,
sender_contact,
};

// Stream output immediately (before collecting all results)
Expand Down Expand Up @@ -1024,6 +1056,21 @@ impl App {
topic_id: msg.topic_id,
})
.await?;
// Populate contacts from the sender captured with the message
// (no extra API call — it rode along with the message history).
if let Some(c) = &msg.sender_contact {
let _ = self
.get_store()
.await?
.upsert_contact(
c.user_id,
c.username.as_deref(),
&c.first_name,
&c.last_name,
&c.phone,
)
.await;
}
messages_stored += 1;
}

Expand Down Expand Up @@ -1322,7 +1369,8 @@ impl App {
latest_ts = Some(msg_ts);
}

let sender_id = msg.sender().map(|s| s.id().bare_id()).unwrap_or(0);
let sender = msg.sender();
let sender_id = sender.as_ref().map(|s| s.id().bare_id()).unwrap_or(0);
let from_me = msg.outgoing();

let text = msg.text().to_string();
Expand Down Expand Up @@ -1364,6 +1412,20 @@ impl App {
topic_id,
})
.await?;
// Populate contacts from the message sender (free — no API call).
if let Some(c) = sender_contact_from_peer(sender) {
let _ = self
.get_store()
.await?
.upsert_contact(
c.user_id,
c.username.as_deref(),
&c.first_name,
&c.last_name,
&c.phone,
)
.await;
}
messages_stored += 1;

// Show progress periodically
Expand Down Expand Up @@ -1648,7 +1710,8 @@ impl App {
latest_ts = Some(msg_ts);
}

let sender_id = msg.sender().map(|s| s.id().bare_id()).unwrap_or(0);
let sender = msg.sender();
let sender_id = sender.as_ref().map(|s| s.id().bare_id()).unwrap_or(0);
let from_me = msg.outgoing();

let text = msg.text().to_string();
Expand Down Expand Up @@ -1687,6 +1750,20 @@ impl App {
topic_id,
})
.await?;
// Populate contacts from the message sender (free — no API call).
if let Some(c) = sender_contact_from_peer(sender) {
let _ = self
.get_store()
.await?
.upsert_contact(
c.user_id,
c.username.as_deref(),
&c.first_name,
&c.last_name,
&c.phone,
)
.await;
}
messages_stored += 1;

// Show progress periodically
Expand Down
13 changes: 13 additions & 0 deletions src/cmd/chats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,19 @@ pub async fn run(cli: &Cli, cmd: &ChatsCommand) -> Result<()> {
role: format_role(&participant.role),
};
members.push(member);
// Persist each participant into contacts so message senders in
// this chat resolve to names (covers silent members too).
let _ = app
.get_store()
.await?
.upsert_contact(
user.bare_id(),
user.username(),
user.first_name().unwrap_or(""),
user.last_name().unwrap_or(""),
user.phone().unwrap_or(""),
)
.await;
count += 1;

// Check limit (0 = unlimited)
Expand Down
20 changes: 20 additions & 0 deletions src/cmd/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,26 @@ pub async fn run(cli: &Cli, args: &DaemonArgs) -> Result<()> {
messages_stored.fetch_add(1, Ordering::Relaxed);
}

// Populate contacts from the sender in real time so
// names resolve. Costs nothing — the sender object
// already arrived with the update.
if let Some(Peer::User(user)) = msg.sender() {
if let Err(e) = app
.get_store()
.await?
.upsert_contact(
user.bare_id(),
user.username(),
user.first_name().unwrap_or(""),
user.last_name().unwrap_or(""),
user.phone().unwrap_or(""),
)
.await
{
log::warn!("Failed to upsert sender contact: {}", e);
}
}

// Update chat metadata
let chat_name = chat_name_from_peer(&peer);
let username = username_from_peer(&peer);
Expand Down