189 lines
5.9 KiB
Rust
189 lines
5.9 KiB
Rust
use kordophone::api::event_socket::{EventSocket, SocketEvent, SocketUpdate};
|
|
use kordophone::api::http_client::Credentials;
|
|
use kordophone::api::http_client::HTTPAPIClient;
|
|
use kordophone::api::InMemoryAuthenticationStore;
|
|
use kordophone::APIInterface;
|
|
|
|
use crate::printers::{ConversationPrinter, MessagePrinter};
|
|
use anyhow::Result;
|
|
use clap::Subcommand;
|
|
use kordophone::model::event::EventData;
|
|
use kordophone::model::outgoing_message::OutgoingMessage;
|
|
|
|
use futures_util::StreamExt;
|
|
|
|
pub fn make_api_client_from_env() -> HTTPAPIClient<InMemoryAuthenticationStore> {
|
|
dotenv::dotenv().ok();
|
|
|
|
// read from env
|
|
let base_url = std::env::var("KORDOPHONE_API_URL").expect("KORDOPHONE_API_URL must be set");
|
|
|
|
let credentials = Credentials {
|
|
username: std::env::var("KORDOPHONE_USERNAME").expect("KORDOPHONE_USERNAME must be set"),
|
|
|
|
password: std::env::var("KORDOPHONE_PASSWORD").expect("KORDOPHONE_PASSWORD must be set"),
|
|
};
|
|
|
|
HTTPAPIClient::new(
|
|
base_url.parse().unwrap(),
|
|
InMemoryAuthenticationStore::new(Some(credentials)),
|
|
)
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum Commands {
|
|
/// Prints all known conversations on the server.
|
|
Conversations,
|
|
|
|
/// Prints all messages in a conversation.
|
|
Messages { conversation_id: String },
|
|
|
|
/// Prints the server Kordophone version.
|
|
Version,
|
|
|
|
/// Prints all events from the server.
|
|
Events,
|
|
|
|
/// Prints all raw updates from the server.
|
|
RawUpdates,
|
|
|
|
/// Sends a message to the server.
|
|
SendMessage {
|
|
conversation_id: String,
|
|
message: String,
|
|
},
|
|
|
|
/// Marks a conversation as read.
|
|
Mark { conversation_id: String },
|
|
}
|
|
|
|
impl Commands {
|
|
pub async fn run(cmd: Commands) -> Result<()> {
|
|
let mut client = ClientCli::new();
|
|
match cmd {
|
|
Commands::Version => client.print_version().await,
|
|
Commands::Conversations => client.print_conversations().await,
|
|
Commands::Messages { conversation_id } => client.print_messages(conversation_id).await,
|
|
Commands::RawUpdates => client.print_raw_updates().await,
|
|
Commands::Events => client.print_events().await,
|
|
Commands::SendMessage {
|
|
conversation_id,
|
|
message,
|
|
} => client.send_message(conversation_id, message).await,
|
|
Commands::Mark { conversation_id } => {
|
|
client.mark_conversation_as_read(conversation_id).await
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct ClientCli {
|
|
api: HTTPAPIClient<InMemoryAuthenticationStore>,
|
|
}
|
|
|
|
impl ClientCli {
|
|
pub fn new() -> Self {
|
|
let api = make_api_client_from_env();
|
|
Self { api }
|
|
}
|
|
|
|
pub async fn print_version(&mut self) -> Result<()> {
|
|
let version = self.api.get_version().await?;
|
|
println!("Version: {}", version);
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn print_conversations(&mut self) -> Result<()> {
|
|
let conversations = self.api.get_conversations().await?;
|
|
for conversation in conversations {
|
|
println!("{}", ConversationPrinter::new(&conversation.into()));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn print_messages(&mut self, conversation_id: String) -> Result<()> {
|
|
let messages = self
|
|
.api
|
|
.get_messages(&conversation_id, None, None, None)
|
|
.await?;
|
|
for message in messages {
|
|
println!("{}", MessagePrinter::new(&message.into()));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn print_events(&mut self) -> Result<()> {
|
|
let socket = self.api.open_event_socket(None).await?;
|
|
|
|
let (mut stream, _) = socket.events().await;
|
|
while let Some(Ok(socket_event)) = stream.next().await {
|
|
match socket_event {
|
|
SocketEvent::Update(event) => match event.data {
|
|
EventData::ConversationChanged(conversation) => {
|
|
println!("Conversation changed: {}", conversation.guid);
|
|
}
|
|
EventData::MessageReceived(conversation, message) => {
|
|
println!(
|
|
"Message received: msg: {} conversation: {}",
|
|
message.guid, conversation.guid
|
|
);
|
|
}
|
|
},
|
|
SocketEvent::Pong => {
|
|
println!("Pong");
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub async fn print_raw_updates(&mut self) -> Result<()> {
|
|
let socket = self.api.open_event_socket(None).await?;
|
|
|
|
println!("Listening for raw updates...");
|
|
let mut stream = socket.raw_updates().await;
|
|
|
|
loop {
|
|
match stream.next().await.unwrap() {
|
|
Ok(update) => {
|
|
match update {
|
|
SocketUpdate::Update(updates) => {
|
|
for update in updates {
|
|
println!("Got update: {:?}", update);
|
|
}
|
|
}
|
|
SocketUpdate::Pong => {
|
|
println!("Pong");
|
|
}
|
|
}
|
|
},
|
|
|
|
Err(e) => {
|
|
println!("Update error: {:?}", e);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
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(())
|
|
}
|
|
|
|
pub async fn mark_conversation_as_read(&mut self, conversation_id: String) -> Result<()> {
|
|
self.api.mark_conversation_as_read(&conversation_id).await?;
|
|
println!("Conversation marked as read: {}", conversation_id);
|
|
Ok(())
|
|
}
|
|
}
|