client: implements send_message
This commit is contained in:
@@ -20,7 +20,17 @@ use tokio_tungstenite::connect_async;
|
|||||||
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
use tokio_tungstenite::{MaybeTlsStream, WebSocketStream};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
model::{Conversation, ConversationID, JwtToken, Message, MessageID, UpdateItem, Event},
|
model::{
|
||||||
|
Conversation,
|
||||||
|
ConversationID,
|
||||||
|
JwtToken,
|
||||||
|
Message,
|
||||||
|
MessageID,
|
||||||
|
UpdateItem,
|
||||||
|
Event,
|
||||||
|
OutgoingMessage,
|
||||||
|
},
|
||||||
|
|
||||||
APIInterface
|
APIInterface
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -215,6 +225,19 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
|
|||||||
Ok(messages)
|
Ok(messages)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_message(
|
||||||
|
&mut self,
|
||||||
|
outgoing_message: OutgoingMessage,
|
||||||
|
) -> Result<Message, Self::Error> {
|
||||||
|
let message: Message = self.request_with_body(
|
||||||
|
"sendMessage",
|
||||||
|
Method::POST,
|
||||||
|
|| serde_json::to_string(&outgoing_message).unwrap().into()
|
||||||
|
).await?;
|
||||||
|
|
||||||
|
Ok(message)
|
||||||
|
}
|
||||||
|
|
||||||
async fn open_event_socket(&mut self) -> Result<WebsocketEventSocket, Self::Error> {
|
async fn open_event_socket(&mut self) -> Result<WebsocketEventSocket, Self::Error> {
|
||||||
use tungstenite::http::StatusCode;
|
use tungstenite::http::StatusCode;
|
||||||
use tungstenite::handshake::client::Request as TungsteniteRequest;
|
use tungstenite::handshake::client::Request as TungsteniteRequest;
|
||||||
@@ -285,24 +308,23 @@ impl<K: AuthenticationStore + Send + Sync> HTTPAPIClient<K> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn request<T: DeserializeOwned>(&mut self, endpoint: &str, method: Method) -> Result<T, Error> {
|
async fn request<T: DeserializeOwned>(&mut self, endpoint: &str, method: Method) -> Result<T, Error> {
|
||||||
self.request_with_body(endpoint, method, || { Body::empty() }).await
|
self.request_with_body(endpoint, method, Body::empty).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request_with_body<T, B>(&mut self, endpoint: &str, method: Method, body_fn: B) -> Result<T, Error>
|
async fn request_with_body<T>(&mut self, endpoint: &str, method: Method, body_fn: impl Fn() -> Body) -> Result<T, Error>
|
||||||
where T: DeserializeOwned, B: Fn() -> Body
|
where T: DeserializeOwned
|
||||||
{
|
{
|
||||||
self.request_with_body_retry(endpoint, method, body_fn, true).await
|
self.request_with_body_retry(endpoint, method, body_fn, true).await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn request_with_body_retry<T, B>(
|
async fn request_with_body_retry<T>(
|
||||||
&mut self,
|
&mut self,
|
||||||
endpoint: &str,
|
endpoint: &str,
|
||||||
method: Method,
|
method: Method,
|
||||||
body_fn: B,
|
body_fn: impl Fn() -> Body,
|
||||||
retry_auth: bool) -> Result<T, Error>
|
retry_auth: bool) -> Result<T, Error>
|
||||||
where
|
where
|
||||||
T: DeserializeOwned,
|
T: DeserializeOwned,
|
||||||
B: Fn() -> Body
|
|
||||||
{
|
{
|
||||||
use hyper::StatusCode;
|
use hyper::StatusCode;
|
||||||
|
|
||||||
|
|||||||
@@ -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, MessageID,
|
Conversation, Message, ConversationID, MessageID, OutgoingMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
@@ -35,6 +35,12 @@ pub trait APIInterface {
|
|||||||
after: Option<MessageID>,
|
after: Option<MessageID>,
|
||||||
) -> Result<Vec<Message>, Self::Error>;
|
) -> Result<Vec<Message>, Self::Error>;
|
||||||
|
|
||||||
|
// (POST) /sendMessage
|
||||||
|
async fn send_message(
|
||||||
|
&mut self,
|
||||||
|
outgoing_message: OutgoingMessage,
|
||||||
|
) -> Result<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>;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
pub mod conversation;
|
pub mod conversation;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
pub mod outgoing_message;
|
||||||
pub mod update;
|
pub mod update;
|
||||||
|
|
||||||
pub use conversation::Conversation;
|
pub use conversation::Conversation;
|
||||||
@@ -9,6 +10,9 @@ pub use conversation::ConversationID;
|
|||||||
pub use message::Message;
|
pub use message::Message;
|
||||||
pub use message::MessageID;
|
pub use message::MessageID;
|
||||||
|
|
||||||
|
pub use outgoing_message::OutgoingMessage;
|
||||||
|
pub use outgoing_message::OutgoingMessageBuilder;
|
||||||
|
|
||||||
pub use update::UpdateItem;
|
pub use update::UpdateItem;
|
||||||
|
|
||||||
pub use event::Event;
|
pub use event::Event;
|
||||||
|
|||||||
56
kordophone/src/model/outgoing_message.rs
Normal file
56
kordophone/src/model/outgoing_message.rs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use super::conversation::ConversationID;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub struct OutgoingMessage {
|
||||||
|
#[serde(rename = "body")]
|
||||||
|
pub text: String,
|
||||||
|
|
||||||
|
#[serde(rename = "guid")]
|
||||||
|
pub conversation_id: ConversationID,
|
||||||
|
|
||||||
|
#[serde(rename = "fileTransferGUIDs")]
|
||||||
|
pub file_transfer_guids: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutgoingMessage {
|
||||||
|
pub fn builder() -> OutgoingMessageBuilder {
|
||||||
|
OutgoingMessageBuilder::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct OutgoingMessageBuilder {
|
||||||
|
text: Option<String>,
|
||||||
|
conversation_id: Option<ConversationID>,
|
||||||
|
file_transfer_guids: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OutgoingMessageBuilder {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self::default()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn text(mut self, text: String) -> Self {
|
||||||
|
self.text = Some(text);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn conversation_id(mut self, conversation_id: ConversationID) -> Self {
|
||||||
|
self.conversation_id = Some(conversation_id);
|
||||||
|
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 build(self) -> OutgoingMessage {
|
||||||
|
OutgoingMessage {
|
||||||
|
text: self.text.unwrap(),
|
||||||
|
conversation_id: self.conversation_id.unwrap(),
|
||||||
|
file_transfer_guids: self.file_transfer_guids.unwrap_or_default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
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, MessageID, UpdateItem, Event},
|
model::{Conversation, ConversationID, JwtToken, Message, MessageID, UpdateItem, Event, OutgoingMessage},
|
||||||
api::event_socket::EventSocket,
|
api::event_socket::EventSocket,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -88,6 +91,20 @@ impl APIInterface for TestClient {
|
|||||||
Err(TestError::ConversationNotFound)
|
Err(TestError::ConversationNotFound)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn send_message(
|
||||||
|
&mut self,
|
||||||
|
outgoing_message: OutgoingMessage,
|
||||||
|
) -> Result<Message, Self::Error> {
|
||||||
|
let message = Message::builder()
|
||||||
|
.guid(Uuid::new_v4().to_string())
|
||||||
|
.text(outgoing_message.text)
|
||||||
|
.date(OffsetDateTime::now_utc())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
self.messages.entry(outgoing_message.conversation_id).or_insert(vec![]).push(message.clone());
|
||||||
|
Ok(message)
|
||||||
|
}
|
||||||
|
|
||||||
async fn open_event_socket(&mut self) -> Result<impl EventSocket, Self::Error> {
|
async fn open_event_socket(&mut self) -> Result<impl EventSocket, Self::Error> {
|
||||||
Ok(TestEventSocket::new())
|
Ok(TestEventSocket::new())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use anyhow::Result;
|
|||||||
use clap::Subcommand;
|
use clap::Subcommand;
|
||||||
use crate::printers::{ConversationPrinter, MessagePrinter};
|
use crate::printers::{ConversationPrinter, MessagePrinter};
|
||||||
use kordophone::model::event::Event;
|
use kordophone::model::event::Event;
|
||||||
|
use kordophone::model::outgoing_message::OutgoingMessage;
|
||||||
|
|
||||||
use futures_util::StreamExt;
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
@@ -47,6 +48,12 @@ pub enum Commands {
|
|||||||
|
|
||||||
/// Prints all raw updates from the server.
|
/// Prints all raw updates from the server.
|
||||||
RawUpdates,
|
RawUpdates,
|
||||||
|
|
||||||
|
/// Sends a message to the server.
|
||||||
|
SendMessage {
|
||||||
|
conversation_id: String,
|
||||||
|
message: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Commands {
|
impl Commands {
|
||||||
@@ -58,6 +65,7 @@ impl Commands {
|
|||||||
Commands::Messages { conversation_id } => client.print_messages(conversation_id).await,
|
Commands::Messages { conversation_id } => client.print_messages(conversation_id).await,
|
||||||
Commands::RawUpdates => client.print_raw_updates().await,
|
Commands::RawUpdates => client.print_raw_updates().await,
|
||||||
Commands::Events => client.print_events().await,
|
Commands::Events => client.print_events().await,
|
||||||
|
Commands::SendMessage { conversation_id, message } => client.send_message(conversation_id, message).await,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -123,6 +131,17 @@ impl ClientCli {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_message(&mut self, conversation_id: String, message: String) -> Result<()> {
|
||||||
|
let outgoing_message = OutgoingMessage::builder()
|
||||||
|
.conversation_id(conversation_id)
|
||||||
|
.text(message)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let message = self.api.send_message(outgoing_message).await?;
|
||||||
|
println!("Message sent: {}", message.guid);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user