plub through attachment guids via messages
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@@ -1036,6 +1036,7 @@ dependencies = [
|
|||||||
"kordophone",
|
"kordophone",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
"uuid",
|
"uuid",
|
||||||
@@ -1059,6 +1060,7 @@ dependencies = [
|
|||||||
"kordophone",
|
"kordophone",
|
||||||
"kordophone-db",
|
"kordophone-db",
|
||||||
"log",
|
"log",
|
||||||
|
"serde_json",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.12",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-condvar",
|
"tokio-condvar",
|
||||||
@@ -1082,6 +1084,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"pretty",
|
"pretty",
|
||||||
"prettytable",
|
"prettytable",
|
||||||
|
"serde_json",
|
||||||
"time",
|
"time",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ diesel_migrations = { version = "2.2.0", features = ["sqlite"] }
|
|||||||
kordophone = { path = "../kordophone" }
|
kordophone = { path = "../kordophone" }
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
serde = { version = "1.0.215", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
||||||
time = "0.3.37"
|
time = "0.3.37"
|
||||||
tokio = "1.44.2"
|
tokio = "1.44.2"
|
||||||
uuid = { version = "1.11.0", features = ["v4"] }
|
uuid = { version = "1.11.0", features = ["v4"] }
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- Remove attachment_metadata column from messages table
|
||||||
|
ALTER TABLE messages DROP COLUMN attachment_metadata;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- Add attachment_metadata column to messages table
|
||||||
|
ALTER TABLE messages ADD COLUMN attachment_metadata TEXT;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- Remove file_transfer_guids column from messages table
|
||||||
|
ALTER TABLE messages DROP COLUMN file_transfer_guids;
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
-- Add file_transfer_guids column to messages table
|
||||||
|
ALTER TABLE messages ADD COLUMN file_transfer_guids TEXT;
|
||||||
@@ -10,10 +10,21 @@ pub struct Record {
|
|||||||
pub sender_participant_id: Option<i32>,
|
pub sender_participant_id: Option<i32>,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub date: NaiveDateTime,
|
pub date: NaiveDateTime,
|
||||||
|
pub file_transfer_guids: Option<String>, // JSON array
|
||||||
|
pub attachment_metadata: Option<String>, // JSON string
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Message> for Record {
|
impl From<Message> for Record {
|
||||||
fn from(message: Message) -> Self {
|
fn from(message: Message) -> Self {
|
||||||
|
let file_transfer_guids = if message.file_transfer_guids.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(serde_json::to_string(&message.file_transfer_guids).unwrap_or_default())
|
||||||
|
};
|
||||||
|
|
||||||
|
let attachment_metadata = message.attachment_metadata
|
||||||
|
.map(|metadata| serde_json::to_string(&metadata).unwrap_or_default());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: message.id,
|
id: message.id,
|
||||||
sender_participant_id: match message.sender {
|
sender_participant_id: match message.sender {
|
||||||
@@ -22,18 +33,29 @@ impl From<Message> for Record {
|
|||||||
},
|
},
|
||||||
text: message.text,
|
text: message.text,
|
||||||
date: message.date,
|
date: message.date,
|
||||||
|
file_transfer_guids,
|
||||||
|
attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Record> for Message {
|
impl From<Record> for Message {
|
||||||
fn from(record: Record) -> Self {
|
fn from(record: Record) -> Self {
|
||||||
|
let file_transfer_guids = record.file_transfer_guids
|
||||||
|
.and_then(|json| serde_json::from_str(&json).ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let attachment_metadata = record.attachment_metadata
|
||||||
|
.and_then(|json| serde_json::from_str(&json).ok());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
id: record.id,
|
id: record.id,
|
||||||
// We'll set the proper sender later when loading participant info
|
// We'll set the proper sender later when loading participant info
|
||||||
sender: Participant::Me,
|
sender: Participant::Me,
|
||||||
text: record.text,
|
text: record.text,
|
||||||
date: record.date,
|
date: record.date,
|
||||||
|
file_transfer_guids,
|
||||||
|
attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use chrono::{DateTime, NaiveDateTime};
|
use chrono::{DateTime, NaiveDateTime};
|
||||||
|
use std::collections::HashMap;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
use crate::models::participant::Participant;
|
use crate::models::participant::Participant;
|
||||||
use kordophone::model::outgoing_message::OutgoingMessage;
|
use kordophone::model::outgoing_message::OutgoingMessage;
|
||||||
|
use kordophone::model::message::AttachmentMetadata;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
@@ -9,6 +11,8 @@ pub struct Message {
|
|||||||
pub sender: Participant,
|
pub sender: Participant,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
pub date: NaiveDateTime,
|
pub date: NaiveDateTime,
|
||||||
|
pub file_transfer_guids: Vec<String>,
|
||||||
|
pub attachment_metadata: Option<HashMap<String, AttachmentMetadata>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
@@ -36,7 +40,9 @@ impl From<kordophone::model::Message> for Message {
|
|||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
)
|
)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.naive_local()
|
.naive_local(),
|
||||||
|
file_transfer_guids: value.file_transfer_guids,
|
||||||
|
attachment_metadata: value.attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,6 +54,8 @@ impl From<&OutgoingMessage> for Message {
|
|||||||
sender: Participant::Me,
|
sender: Participant::Me,
|
||||||
text: value.text.clone(),
|
text: value.text.clone(),
|
||||||
date: value.date,
|
date: value.date,
|
||||||
|
file_transfer_guids: Vec::new(), // Outgoing messages don't have file transfer GUIDs initially
|
||||||
|
attachment_metadata: None, // Outgoing messages don't have attachment metadata initially
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +65,8 @@ pub struct MessageBuilder {
|
|||||||
sender: Option<Participant>,
|
sender: Option<Participant>,
|
||||||
text: Option<String>,
|
text: Option<String>,
|
||||||
date: Option<NaiveDateTime>,
|
date: Option<NaiveDateTime>,
|
||||||
|
file_transfer_guids: Option<Vec<String>>,
|
||||||
|
attachment_metadata: Option<HashMap<String, AttachmentMetadata>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for MessageBuilder {
|
impl Default for MessageBuilder {
|
||||||
@@ -72,6 +82,8 @@ impl MessageBuilder {
|
|||||||
sender: None,
|
sender: None,
|
||||||
text: None,
|
text: None,
|
||||||
date: None,
|
date: None,
|
||||||
|
file_transfer_guids: None,
|
||||||
|
attachment_metadata: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,12 +102,24 @@ impl MessageBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file_transfer_guids(mut self, file_transfer_guids: Vec<String>) -> Self {
|
||||||
|
self.file_transfer_guids = Some(file_transfer_guids);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attachment_metadata(mut self, attachment_metadata: HashMap<String, AttachmentMetadata>) -> Self {
|
||||||
|
self.attachment_metadata = Some(attachment_metadata);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Message {
|
pub fn build(self) -> Message {
|
||||||
Message {
|
Message {
|
||||||
id: self.id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
id: self.id.unwrap_or_else(|| Uuid::new_v4().to_string()),
|
||||||
sender: self.sender.unwrap_or(Participant::Me),
|
sender: self.sender.unwrap_or(Participant::Me),
|
||||||
text: self.text.unwrap_or_default(),
|
text: self.text.unwrap_or_default(),
|
||||||
date: self.date.unwrap_or_else(|| chrono::Utc::now().naive_utc()),
|
date: self.date.unwrap_or_else(|| chrono::Utc::now().naive_utc()),
|
||||||
|
file_transfer_guids: self.file_transfer_guids.unwrap_or_default(),
|
||||||
|
attachment_metadata: self.attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ diesel::table! {
|
|||||||
text -> Text,
|
text -> Text,
|
||||||
sender_participant_id -> Nullable<Integer>,
|
sender_participant_id -> Nullable<Integer>,
|
||||||
date -> Timestamp,
|
date -> Timestamp,
|
||||||
|
file_transfer_guids -> Nullable<Text>, // JSON array of file transfer GUIDs
|
||||||
|
attachment_metadata -> Nullable<Text>, // JSON string of attachment metadata
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::HashMap;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -6,6 +7,23 @@ use super::Identifiable;
|
|||||||
|
|
||||||
pub type MessageID = <Message as Identifiable>::ID;
|
pub type MessageID = <Message as Identifiable>::ID;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct AttributionInfo {
|
||||||
|
/// Picture width
|
||||||
|
#[serde(rename = "pgensh")]
|
||||||
|
pub width: Option<u32>,
|
||||||
|
|
||||||
|
/// Picture height
|
||||||
|
#[serde(rename = "pgensw")]
|
||||||
|
pub height: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct AttachmentMetadata {
|
||||||
|
#[serde(rename = "attributionInfo")]
|
||||||
|
pub attribution_info: Option<AttributionInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
pub guid: String,
|
pub guid: String,
|
||||||
@@ -18,6 +36,14 @@ pub struct Message {
|
|||||||
|
|
||||||
#[serde(with = "time::serde::iso8601")]
|
#[serde(with = "time::serde::iso8601")]
|
||||||
pub date: OffsetDateTime,
|
pub date: OffsetDateTime,
|
||||||
|
|
||||||
|
/// Array of file transfer GUIDs for attachments
|
||||||
|
#[serde(rename = "fileTransferGUIDs", default)]
|
||||||
|
pub file_transfer_guids: Vec<String>,
|
||||||
|
|
||||||
|
/// Optional attachment metadata, keyed by attachment GUID
|
||||||
|
#[serde(rename = "attachmentMetadata")]
|
||||||
|
pub attachment_metadata: Option<HashMap<String, AttachmentMetadata>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Message {
|
impl Message {
|
||||||
@@ -40,6 +66,8 @@ pub struct MessageBuilder {
|
|||||||
text: Option<String>,
|
text: Option<String>,
|
||||||
sender: Option<String>,
|
sender: Option<String>,
|
||||||
date: Option<OffsetDateTime>,
|
date: Option<OffsetDateTime>,
|
||||||
|
file_transfer_guids: Option<Vec<String>>,
|
||||||
|
attachment_metadata: Option<HashMap<String, AttachmentMetadata>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MessageBuilder {
|
impl MessageBuilder {
|
||||||
@@ -67,12 +95,24 @@ impl MessageBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn file_transfer_guids(mut self, file_transfer_guids: Vec<String>) -> Self {
|
||||||
|
self.file_transfer_guids = Some(file_transfer_guids);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn attachment_metadata(mut self, attachment_metadata: HashMap<String, AttachmentMetadata>) -> Self {
|
||||||
|
self.attachment_metadata = Some(attachment_metadata);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> Message {
|
pub fn build(self) -> Message {
|
||||||
Message {
|
Message {
|
||||||
guid: self.guid.unwrap_or(Uuid::new_v4().to_string()),
|
guid: self.guid.unwrap_or(Uuid::new_v4().to_string()),
|
||||||
text: self.text.unwrap_or("".to_string()),
|
text: self.text.unwrap_or("".to_string()),
|
||||||
sender: self.sender,
|
sender: self.sender,
|
||||||
date: self.date.unwrap_or(OffsetDateTime::now_utc()),
|
date: self.date.unwrap_or(OffsetDateTime::now_utc()),
|
||||||
|
file_transfer_guids: self.file_transfer_guids.unwrap_or_default(),
|
||||||
|
attachment_metadata: self.attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ keyring = { version = "3.6.2", features = ["sync-secret-service"] }
|
|||||||
kordophone = { path = "../kordophone" }
|
kordophone = { path = "../kordophone" }
|
||||||
kordophone-db = { path = "../kordophone-db" }
|
kordophone-db = { path = "../kordophone-db" }
|
||||||
log = "0.4.25"
|
log = "0.4.25"
|
||||||
|
serde_json = "1.0"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tokio-condvar = "0.3.0"
|
tokio-condvar = "0.3.0"
|
||||||
|
|||||||
@@ -58,7 +58,16 @@
|
|||||||
<method name="GetMessages">
|
<method name="GetMessages">
|
||||||
<arg type="s" name="conversation_id" direction="in"/>
|
<arg type="s" name="conversation_id" direction="in"/>
|
||||||
<arg type="s" name="last_message_id" direction="in"/>
|
<arg type="s" name="last_message_id" direction="in"/>
|
||||||
<arg type="aa{sv}" direction="out" name="messages"/>
|
<arg type="aa{sv}" direction="out" name="messages">
|
||||||
|
<annotation name="org.freedesktop.DBus.DocString"
|
||||||
|
value="Array of dictionaries. Each dictionary has keys:
|
||||||
|
'id' (string): Unique message identifier
|
||||||
|
'text' (string): Message body text
|
||||||
|
'date' (int64): Message timestamp
|
||||||
|
'sender' (string): Sender display name
|
||||||
|
'file_transfer_guids' (string, optional): JSON array of file transfer GUIDs
|
||||||
|
'attachment_metadata' (string, optional): JSON string of attachment metadata"/>
|
||||||
|
</arg>
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
<method name="SendMessage">
|
<method name="SendMessage">
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ impl DbusRepository for ServerImpl {
|
|||||||
messages
|
messages
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|msg| {
|
.map(|msg| {
|
||||||
|
let msg_id = msg.id.clone(); // Store ID for potential error logging
|
||||||
let mut map = arg::PropMap::new();
|
let mut map = arg::PropMap::new();
|
||||||
map.insert("id".into(), arg::Variant(Box::new(msg.id)));
|
map.insert("id".into(), arg::Variant(Box::new(msg.id)));
|
||||||
map.insert("text".into(), arg::Variant(Box::new(msg.text)));
|
map.insert("text".into(), arg::Variant(Box::new(msg.text)));
|
||||||
@@ -139,6 +140,31 @@ impl DbusRepository for ServerImpl {
|
|||||||
"sender".into(),
|
"sender".into(),
|
||||||
arg::Variant(Box::new(msg.sender.display_name())),
|
arg::Variant(Box::new(msg.sender.display_name())),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add file transfer GUIDs if present
|
||||||
|
if !msg.file_transfer_guids.is_empty() {
|
||||||
|
match serde_json::to_string(&msg.file_transfer_guids) {
|
||||||
|
Ok(json_str) => {
|
||||||
|
map.insert("file_transfer_guids".into(), arg::Variant(Box::new(json_str)));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to serialize file transfer GUIDs for message {}: {}", msg_id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add attachment metadata if present
|
||||||
|
if let Some(ref attachment_metadata) = msg.attachment_metadata {
|
||||||
|
match serde_json::to_string(attachment_metadata) {
|
||||||
|
Ok(json_str) => {
|
||||||
|
map.insert("attachment_metadata".into(), arg::Variant(Box::new(json_str)));
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to serialize attachment metadata for message {}: {}", msg_id, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
map
|
map
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ kordophone-db = { path = "../kordophone-db" }
|
|||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
pretty = { version = "0.12.3", features = ["termcolor"] }
|
pretty = { version = "0.12.3", features = ["termcolor"] }
|
||||||
prettytable = "0.10.0"
|
prettytable = "0.10.0"
|
||||||
|
serde_json = "1.0"
|
||||||
time = "0.3.37"
|
time = "0.3.37"
|
||||||
tokio = "1.41.1"
|
tokio = "1.41.1"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
use std::collections::HashMap;
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use pretty::RcDoc;
|
use pretty::RcDoc;
|
||||||
use dbus::arg::{self, RefArg};
|
use dbus::arg::{self, RefArg};
|
||||||
|
use kordophone::model::message::AttachmentMetadata;
|
||||||
|
|
||||||
pub struct PrintableConversation {
|
pub struct PrintableConversation {
|
||||||
pub guid: String,
|
pub guid: String,
|
||||||
@@ -62,6 +64,8 @@ pub struct PrintableMessage {
|
|||||||
pub date: OffsetDateTime,
|
pub date: OffsetDateTime,
|
||||||
pub sender: String,
|
pub sender: String,
|
||||||
pub text: String,
|
pub text: String,
|
||||||
|
pub file_transfer_guids: Vec<String>,
|
||||||
|
pub attachment_metadata: Option<HashMap<String, AttachmentMetadata>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<kordophone::model::Message> for PrintableMessage {
|
impl From<kordophone::model::Message> for PrintableMessage {
|
||||||
@@ -71,6 +75,8 @@ impl From<kordophone::model::Message> for PrintableMessage {
|
|||||||
date: value.date,
|
date: value.date,
|
||||||
sender: value.sender.unwrap_or("<me>".to_string()),
|
sender: value.sender.unwrap_or("<me>".to_string()),
|
||||||
text: value.text,
|
text: value.text,
|
||||||
|
file_transfer_guids: value.file_transfer_guids,
|
||||||
|
attachment_metadata: value.attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,17 +88,32 @@ impl From<kordophone_db::models::Message> for PrintableMessage {
|
|||||||
date: OffsetDateTime::from_unix_timestamp(value.date.and_utc().timestamp()).unwrap(),
|
date: OffsetDateTime::from_unix_timestamp(value.date.and_utc().timestamp()).unwrap(),
|
||||||
sender: value.sender.display_name(),
|
sender: value.sender.display_name(),
|
||||||
text: value.text,
|
text: value.text,
|
||||||
|
file_transfer_guids: value.file_transfer_guids,
|
||||||
|
attachment_metadata: value.attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<arg::PropMap> for PrintableMessage {
|
impl From<arg::PropMap> for PrintableMessage {
|
||||||
fn from(value: arg::PropMap) -> Self {
|
fn from(value: arg::PropMap) -> Self {
|
||||||
|
// Parse file transfer GUIDs from JSON if present
|
||||||
|
let file_transfer_guids = value.get("file_transfer_guids")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.and_then(|json_str| serde_json::from_str(json_str).ok())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
// Parse attachment metadata from JSON if present
|
||||||
|
let attachment_metadata = value.get("attachment_metadata")
|
||||||
|
.and_then(|v| v.as_str())
|
||||||
|
.and_then(|json_str| serde_json::from_str(json_str).ok());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
guid: value.get("id").unwrap().as_str().unwrap().to_string(),
|
guid: value.get("id").unwrap().as_str().unwrap().to_string(),
|
||||||
date: OffsetDateTime::from_unix_timestamp(value.get("date").unwrap().as_i64().unwrap()).unwrap(),
|
date: OffsetDateTime::from_unix_timestamp(value.get("date").unwrap().as_i64().unwrap()).unwrap(),
|
||||||
sender: value.get("sender").unwrap().as_str().unwrap().to_string(),
|
sender: value.get("sender").unwrap().as_str().unwrap().to_string(),
|
||||||
text: value.get("text").unwrap().as_str().unwrap().to_string(),
|
text: value.get("text").unwrap().as_str().unwrap().to_string(),
|
||||||
|
file_transfer_guids,
|
||||||
|
attachment_metadata,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,21 +187,57 @@ impl Display for MessagePrinter<'_> {
|
|||||||
|
|
||||||
impl<'a> MessagePrinter<'a> {
|
impl<'a> MessagePrinter<'a> {
|
||||||
pub fn new(message: &'a PrintableMessage) -> Self {
|
pub fn new(message: &'a PrintableMessage) -> Self {
|
||||||
let doc = RcDoc::text(format!("<Message: \"{}\"", &message.guid))
|
let mut doc = RcDoc::text(format!("<Message: \"{}\"", &message.guid))
|
||||||
.append(
|
.append(
|
||||||
RcDoc::line()
|
RcDoc::line()
|
||||||
.append("Date: ")
|
.append("Date: ")
|
||||||
.append(message.date.to_string())
|
.append(message.date.to_string())
|
||||||
.append(RcDoc::line())
|
.append(RcDoc::line())
|
||||||
.append("Sender: ")
|
.append("Sender: ")
|
||||||
.append(&message.sender)
|
.append(&message.sender)
|
||||||
.append(RcDoc::line())
|
.append(RcDoc::line())
|
||||||
.append("Body: ")
|
.append("Body: ")
|
||||||
.append(&message.text)
|
.append(&message.text)
|
||||||
.nest(4)
|
.nest(4)
|
||||||
)
|
);
|
||||||
.append(RcDoc::line())
|
|
||||||
.append(">");
|
// Add file transfer GUIDs and attachment metadata if present
|
||||||
|
if !message.file_transfer_guids.is_empty() {
|
||||||
|
doc = doc.append(RcDoc::line())
|
||||||
|
.append(
|
||||||
|
RcDoc::line()
|
||||||
|
.append("Attachments:")
|
||||||
|
.append(
|
||||||
|
message.file_transfer_guids.iter().map(|guid| {
|
||||||
|
let mut attachment_doc = RcDoc::line()
|
||||||
|
.append("- ")
|
||||||
|
.append(guid);
|
||||||
|
|
||||||
|
// Add metadata if available for this GUID
|
||||||
|
if let Some(ref metadata) = message.attachment_metadata {
|
||||||
|
if let Some(attachment_meta) = metadata.get(guid) {
|
||||||
|
if let Some(ref attribution) = attachment_meta.attribution_info {
|
||||||
|
if let (Some(width), Some(height)) = (attribution.width, attribution.height) {
|
||||||
|
attachment_doc = attachment_doc
|
||||||
|
.append(RcDoc::line())
|
||||||
|
.append(" Dimensions: ")
|
||||||
|
.append(width.to_string())
|
||||||
|
.append(" × ")
|
||||||
|
.append(height.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attachment_doc
|
||||||
|
})
|
||||||
|
.fold(RcDoc::nil(), |acc, x| acc.append(x))
|
||||||
|
)
|
||||||
|
.nest(4)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc = doc.append(RcDoc::line()).append(">");
|
||||||
|
|
||||||
MessagePrinter { doc }
|
MessagePrinter { doc }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user