Private
Public Access
1
0

client: Started working on ability to sync messages after last known message

This commit is contained in:
2025-04-28 15:17:58 -07:00
parent 6375284d9e
commit 9c245a5b52
8 changed files with 55 additions and 11 deletions

View File

@@ -10,7 +10,7 @@ use async_trait::async_trait;
use serde::{de::DeserializeOwned, Deserialize, Serialize}; use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::{ use crate::{
model::{Conversation, ConversationID, JwtToken, Message}, model::{Conversation, ConversationID, JwtToken, Message, MessageID},
APIInterface APIInterface
}; };
@@ -118,8 +118,27 @@ impl<K: TokenStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
Ok(token) Ok(token)
} }
async fn get_messages(&mut self, conversation_id: &ConversationID) -> Result<Vec<Message>, Self::Error> { async fn get_messages(
let endpoint = format!("messages?guid={}", conversation_id); &mut self,
conversation_id: &ConversationID,
limit: Option<u32>,
before: Option<MessageID>,
after: Option<MessageID>,
) -> Result<Vec<Message>, Self::Error> {
let mut endpoint = format!("messages?guid={}", conversation_id);
if let Some(limit_val) = limit {
endpoint.push_str(&format!("&limit={}", limit_val));
}
if let Some(before_id) = before {
endpoint.push_str(&format!("&beforeMessageGUID={}", before_id));
}
if let Some(after_id) = after {
endpoint.push_str(&format!("&afterMessageGUID={}", after_id));
}
let messages: Vec<Message> = self.request(&endpoint, Method::GET).await?; let messages: Vec<Message> = self.request(&endpoint, Method::GET).await?;
Ok(messages) Ok(messages)
} }
@@ -288,7 +307,7 @@ mod test {
let mut client = local_mock_client(); let mut client = local_mock_client();
let conversations = client.get_conversations().await.unwrap(); let conversations = client.get_conversations().await.unwrap();
let conversation = conversations.first().unwrap(); let conversation = conversations.first().unwrap();
let messages = client.get_messages(&conversation.guid).await.unwrap(); let messages = client.get_messages(&conversation.guid, None, None, None).await.unwrap();
assert!(!messages.is_empty()); assert!(!messages.is_empty());
} }
} }

View File

@@ -1,6 +1,6 @@
use async_trait::async_trait; use async_trait::async_trait;
pub use crate::model::{ pub use crate::model::{
Conversation, Message, ConversationID Conversation, Message, ConversationID, MessageID,
}; };
use crate::model::JwtToken; use crate::model::JwtToken;
@@ -20,7 +20,13 @@ pub trait APIInterface {
async fn get_conversations(&mut self) -> Result<Vec<Conversation>, Self::Error>; async fn get_conversations(&mut self) -> Result<Vec<Conversation>, Self::Error>;
// (GET) /messages // (GET) /messages
async fn get_messages(&mut self, conversation_id: &ConversationID) -> Result<Vec<Message>, Self::Error>; async fn get_messages(
&mut self,
conversation_id: &ConversationID,
limit: Option<u32>,
before: Option<MessageID>,
after: Option<MessageID>,
) -> Result<Vec<Message>, Self::Error>;
// (POST) /authenticate // (POST) /authenticate
async fn authenticate(&mut self, credentials: Credentials) -> Result<JwtToken, Self::Error>; async fn authenticate(&mut self, credentials: Credentials) -> Result<JwtToken, Self::Error>;

View File

@@ -2,6 +2,10 @@ use serde::Deserialize;
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;
use super::Identifiable;
pub type MessageID = <Message as Identifiable>::ID;
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct Message { pub struct Message {
pub guid: String, pub guid: String,
@@ -22,6 +26,14 @@ impl Message {
} }
} }
impl Identifiable for Message {
type ID = String;
fn id(&self) -> &Self::ID {
&self.guid
}
}
#[derive(Default)] #[derive(Default)]
pub struct MessageBuilder { pub struct MessageBuilder {
guid: Option<String>, guid: Option<String>,

View File

@@ -5,6 +5,7 @@ pub use conversation::Conversation;
pub use conversation::ConversationID; pub use conversation::ConversationID;
pub use message::Message; pub use message::Message;
pub use message::MessageID;
pub mod jwt; pub mod jwt;
pub use jwt::JwtToken; pub use jwt::JwtToken;

View File

@@ -4,7 +4,7 @@ use std::collections::HashMap;
pub use crate::APIInterface; pub use crate::APIInterface;
use crate::{ use crate::{
api::http_client::Credentials, api::http_client::Credentials,
model::{Conversation, ConversationID, JwtToken, Message} model::{Conversation, ConversationID, JwtToken, Message, MessageID}
}; };
pub struct TestClient { pub struct TestClient {
@@ -44,7 +44,13 @@ impl APIInterface for TestClient {
Ok(self.conversations.clone()) Ok(self.conversations.clone())
} }
async fn get_messages(&mut self, conversation_id: &ConversationID) -> Result<Vec<Message>, Self::Error> { async fn get_messages(
&mut self,
conversation_id: &ConversationID,
limit: Option<u32>,
before: Option<MessageID>,
after: Option<MessageID>
) -> Result<Vec<Message>, Self::Error> {
if let Some(messages) = self.messages.get(conversation_id) { if let Some(messages) = self.messages.get(conversation_id) {
return Ok(messages.clone()) return Ok(messages.clone())
} }

View File

@@ -181,7 +181,7 @@ impl Daemon {
// Fetch and sync messages for this conversation // Fetch and sync messages for this conversation
log::debug!(target: target::SYNC, "Fetching messages for conversation {}", conversation_id); log::debug!(target: target::SYNC, "Fetching messages for conversation {}", conversation_id);
let messages = client.get_messages(&conversation_id).await?; let messages = client.get_messages(&conversation_id, None, None, None).await?;
let db_messages: Vec<kordophone_db::models::Message> = messages.into_iter() let db_messages: Vec<kordophone_db::models::Message> = messages.into_iter()
.map(|m| kordophone_db::models::Message::from(m)) .map(|m| kordophone_db::models::Message::from(m))
.collect(); .collect();

View File

@@ -77,7 +77,7 @@ impl ClientCli {
} }
pub async fn print_messages(&mut self, conversation_id: String) -> Result<()> { pub async fn print_messages(&mut self, conversation_id: String) -> Result<()> {
let messages = self.api.get_messages(&conversation_id).await?; let messages = self.api.get_messages(&conversation_id, None, None, None).await?;
for message in messages { for message in messages {
println!("{}", MessagePrinter::new(&message.into())); println!("{}", MessagePrinter::new(&message.into()));
} }

View File

@@ -151,7 +151,7 @@ impl DbClient {
}).await?; }).await?;
// Fetch and sync messages for this conversation // Fetch and sync messages for this conversation
let messages = client.get_messages(&conversation_id).await?; let messages = client.get_messages(&conversation_id, None, None, None).await?;
let db_messages: Vec<kordophone_db::models::Message> = messages.into_iter() let db_messages: Vec<kordophone_db::models::Message> = messages.into_iter()
.map(|m| kordophone_db::models::Message::from(m)) .map(|m| kordophone_db::models::Message::from(m))
.collect(); .collect();