iota/iota-storage/src/util/chats_util.rs
2026-08-29 12:49:10 +02:00

128 lines
3.7 KiB
Rust

use crate::storage_error::StorageError;
use crate::users::contact::Contact;
use crate::util::db;
use crate::util::sync::{self, EntityType, Operation};
use rusqlite::params;
pub fn has_user(storage_owner: i64, user_id: i64) -> Result<bool, StorageError> {
db::with_db(|conn| {
Ok(conn.query_row(
"SELECT EXISTS(SELECT 1 FROM contacts WHERE storage_owner = ?1 AND user_id = ?2)",
params![storage_owner, user_id],
|row| row.get(0),
)?)
})
}
pub fn mod_user(storage_owner: i64, contact: &Contact) {
if let Err(e) = db::with_db(|conn| {
let tx = conn.unchecked_transaction()?;
tx.execute(
r#"
INSERT INTO contacts (storage_owner, user_id, user_name, last_message_at)
VALUES (?1, ?2, ?3, ?4)
ON CONFLICT(storage_owner, user_id) DO UPDATE SET
user_name = excluded.user_name,
last_message_at = excluded.last_message_at
"#,
params![
storage_owner,
contact.user_id,
contact.user_name.clone(),
contact.last_message_at,
],
)?;
sync::record_event(
&tx,
storage_owner,
EntityType::Contact,
contact.user_id,
Operation::Upsert,
)?;
tx.commit()?;
Ok(())
}) {
eprintln!("Failed to mod_user: {}", e);
}
}
pub fn get_users_by_ids(storage_owner: i64, ids: &[i64]) -> Vec<Contact> {
if ids.is_empty() {
return Vec::new();
}
let wanted: std::collections::HashSet<i64> = ids.iter().copied().collect();
get_users(storage_owner)
.into_iter()
.filter(|contact| wanted.contains(&contact.user_id))
.collect()
}
pub fn get_user(storage_owner: i64, user_id: i64) -> Option<Contact> {
match db::with_db(|conn| {
match conn.query_row(
r#"
SELECT user_id, user_name, last_message_at
FROM contacts
WHERE storage_owner = ?1 AND user_id = ?2
LIMIT 1
"#,
params![storage_owner, user_id],
|r| {
Ok(Contact {
user_id: r.get(0)?,
user_name: r.get(1)?,
last_message_at: r.get(2)?,
})
},
) {
Ok(c) => Ok(Some(c)),
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
Err(e) => Err(e.into()),
}
}) {
Ok(opt) => opt,
Err(e) => {
eprintln!("Error querying user in get_user: {}", e);
None
}
}
}
pub fn get_users(storage_owner: i64) -> Vec<Contact> {
match db::with_db(|conn| {
let mut stmt = conn.prepare(
r#"
SELECT user_id, user_name, last_message_at
FROM contacts
WHERE storage_owner = ?1
ORDER BY
CASE WHEN last_message_at IS NULL THEN 1 ELSE 0 END,
last_message_at DESC,
user_id ASC
"#,
)?;
let rows = stmt.query_map(params![storage_owner], |r| {
Ok(Contact {
user_id: r.get(0)?,
user_name: r.get(1)?,
last_message_at: r.get(2)?,
})
})?;
let mut out = Vec::new();
for row in rows {
match row {
Ok(contact) => out.push(contact),
Err(e) => eprintln!("Failed to read contact row: {}", e),
}
}
Ok(out)
}) {
Ok(v) => v,
Err(e) => {
eprintln!("Failed to query contacts in get_users: {}", e);
Vec::new()
}
}
}