Private
Public Access
1
0

kpcli: client: adds printing of conversations

This commit is contained in:
2024-11-10 19:40:39 -08:00
parent 6b9f528cbf
commit 0e8b8f339a
9 changed files with 492 additions and 59 deletions

4
kpcli/.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.env
.env.*

View File

@@ -6,5 +6,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.93"
clap = { version = "4.5.20", features = ["derive"] }
dotenv = "0.15.0"
kordophone = { path = "../kordophone" }
log = "0.4.22"
pretty = { version = "0.12.3", features = ["termcolor"] }
tokio = "1.41.1"

48
kpcli/src/client_cli.rs Normal file
View File

@@ -0,0 +1,48 @@
use kordophone::APIInterface;
use kordophone::api::http_client::HTTPAPIClient;
use kordophone::api::http_client::Credentials;
use dotenv;
use crate::printers::ConversationPrinter;
pub struct ClientCli {
api: HTTPAPIClient,
}
impl ClientCli {
pub fn new() -> Self {
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"),
};
let api = HTTPAPIClient::new(base_url.parse().unwrap(), credentials.into());
Self { api: api }
}
pub async fn print_version(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let version = self.api.get_version().await?;
println!("Version: {}", version);
Ok(())
}
pub async fn print_conversations(&mut self) -> Result<(), Box<dyn std::error::Error>> {
let conversations = self.api.get_conversations().await?;
for conversation in conversations {
println!("{}", ConversationPrinter::new(&conversation));
}
Ok(())
}
}

View File

@@ -1,9 +1,12 @@
use clap::{Parser, Subcommand};
use kordophone::APIInterface;
mod client_cli;
mod printers;
use clap::{Parser, Subcommand};
use client_cli::ClientCli;
/// A command line interface for the Kordophone library and daemon
#[derive(Parser)]
#[command(name = "kpcli")]
#[command(about = "CLI tool for the Kordophone daemon")]
struct Cli {
#[command(subcommand)]
command: Commands,
@@ -20,24 +23,28 @@ enum Commands {
#[derive(Subcommand)]
enum ClientCommands {
ListConversations,
/// Prints all known conversations on the server.
Conversations,
/// Prints the server Kordophone version.
Version,
}
fn main() {
let cli = Cli::parse();
match cli.command {
async fn run_command(command: Commands) -> Result<(), Box<dyn std::error::Error>> {
let mut client = ClientCli::new();
match command {
Commands::Client { command } => match command {
ClientCommands::ListConversations => {
println!("Listing conversations...");
// TODO: Implement conversation listing
},
ClientCommands::Version => {
println!("Getting version...");
// TODO: Implement version getting
},
ClientCommands::Version => client.print_version().await,
ClientCommands::Conversations => client.print_conversations().await,
},
}
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
run_command(cli.command).await
.map_err(|e| log::error!("Error: {}", e))
.err();
}

58
kpcli/src/printers.rs Normal file
View File

@@ -0,0 +1,58 @@
use std::fmt::Display;
use pretty::RcDoc;
use kordophone::model::Conversation;
pub struct ConversationPrinter<'a> {
doc: RcDoc<'a, Conversation>
}
impl<'a> ConversationPrinter<'a> {
pub fn new(conversation: &'a Conversation) -> Self {
let preview = conversation.last_message_preview
.as_deref()
.unwrap_or("<null>")
.replace('\n', " ");
let doc = RcDoc::text(format!("<Conversation: \"{}\"", &conversation.guid))
.append(
RcDoc::line()
.append("Display Name: ")
.append(conversation.display_name.as_deref().unwrap_or("<null>"))
.append(RcDoc::line())
.append("Date: ")
.append(conversation.date.to_string())
.append(RcDoc::line())
.append("Participants: ")
.append("[")
.append(RcDoc::line()
.append(
conversation.participant_display_names
.iter()
.map(|name|
RcDoc::text(name)
.append(",")
.append(RcDoc::line())
)
.fold(RcDoc::nil(), |acc, x| acc.append(x))
)
.nest(4)
)
.append("]")
.append(RcDoc::line())
.append("Last Message Preview: ")
.append(preview)
.nest(4)
)
.append(RcDoc::line())
.append(">");
ConversationPrinter { doc }
}
}
impl<'a> Display for ConversationPrinter<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.doc.render_fmt(180, f)
}
}