1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
/*!
This module represents common (but not all) columns in the `chat` table.
*/
use std::collections::HashMap;
use rusqlite::{Connection, Error, Result, Row, Statement};
use crate::{
error::table::TableError,
tables::table::{Cacheable, Table, CHAT},
};
/// Represents a single row in the `chat` table.
#[derive(Debug)]
pub struct Chat {
pub rowid: i32,
pub chat_identifier: String,
/// The service the chat used, i.e. iMessage, SMS, IRC, etc.
pub service_name: Option<String>,
/// Optional custom name created created for the chat
pub display_name: Option<String>,
}
impl Table for Chat {
fn from_row(row: &Row) -> Result<Chat> {
Ok(Chat {
rowid: row.get("rowid")?,
chat_identifier: row.get("chat_identifier")?,
service_name: row.get("service_name")?,
display_name: row.get("display_name").unwrap_or(None),
})
}
fn get(db: &Connection) -> Result<Statement, TableError> {
db.prepare(&format!("SELECT * from {CHAT}"))
.map_err(TableError::Chat)
}
fn extract(chat: Result<Result<Self, Error>, Error>) -> Result<Self, TableError> {
match chat {
Ok(Ok(chat)) => Ok(chat),
Err(why) | Ok(Err(why)) => Err(TableError::Chat(why)),
}
}
}
impl Cacheable for Chat {
type K = i32;
type V = Chat;
/// Generate a hashmap containing each chatroom's ID pointing to the chatroom's metadata.
///
/// These chatroom ID's contain duplicates and must be deduped later once we have all of
/// the participants parsed out. On its own this data is not useful.
///
/// # Example:
///
/// ```
/// use imessage_database::util::dirs::default_db_path;
/// use imessage_database::tables::table::{Cacheable, get_connection};
/// use imessage_database::tables::chat::Chat;
///
/// let db_path = default_db_path();
/// let conn = get_connection(&db_path).unwrap();
/// let chatrooms = Chat::cache(&conn);
/// ```
fn cache(db: &Connection) -> Result<HashMap<Self::K, Self::V>, TableError> {
let mut map = HashMap::new();
let mut statement = Chat::get(db)?;
let chats = statement
.query_map([], |row| Ok(Chat::from_row(row)))
.map_err(TableError::Chat)?;
for chat in chats {
let result = Chat::extract(chat)?;
map.insert(result.rowid, result);
}
Ok(map)
}
}
impl Chat {
/// Generate a name for a chat, falling back to the default if a custom one is not set
pub fn name(&self) -> &str {
match self.display_name() {
Some(name) => name,
None => &self.chat_identifier,
}
}
/// Get the current display name for the chat, if it exists.
pub fn display_name(&self) -> Option<&str> {
match &self.display_name {
Some(name) => {
if !name.is_empty() {
return Some(name.as_str());
}
None
}
None => None,
}
}
}