Add option to export plain text room logs
This commit is contained in:
parent
02d3b067b8
commit
0ccf788d7b
5 changed files with 258 additions and 14 deletions
72
src/export.rs
Normal file
72
src/export.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
//! Export logs from the vault to plain text files.
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::path::Path;
|
||||
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
use crate::euph::api::Snowflake;
|
||||
use crate::store::{MsgStore, Tree};
|
||||
use crate::vault::{EuphMsg, Vault};
|
||||
|
||||
const TIME_FORMAT: &str = "%F %T";
|
||||
const TIME_EMPTY: &str = " ";
|
||||
|
||||
pub async fn export(vault: &Vault, room: String, file: &Path) -> anyhow::Result<()> {
|
||||
let mut file = BufWriter::new(File::create(file)?);
|
||||
let vault = vault.euph(room);
|
||||
|
||||
let mut tree_id = vault.first_tree().await;
|
||||
while let Some(some_tree_id) = tree_id {
|
||||
let tree = vault.tree(&some_tree_id).await;
|
||||
write_tree(&mut file, &tree, some_tree_id, 0)?;
|
||||
tree_id = vault.next_tree(&some_tree_id).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_tree(
|
||||
file: &mut BufWriter<File>,
|
||||
tree: &Tree<EuphMsg>,
|
||||
id: Snowflake,
|
||||
indent: usize,
|
||||
) -> anyhow::Result<()> {
|
||||
let indent_string = "| ".repeat(indent);
|
||||
|
||||
if let Some(msg) = tree.msg(&id) {
|
||||
write_msg(file, &indent_string, msg)?;
|
||||
} else {
|
||||
write_placeholder(file, &indent_string)?;
|
||||
}
|
||||
|
||||
if let Some(children) = tree.children(&id) {
|
||||
for child in children {
|
||||
write_tree(file, tree, *child, indent + 1)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_msg(file: &mut BufWriter<File>, indent_string: &str, msg: &EuphMsg) -> anyhow::Result<()> {
|
||||
let nick = &msg.nick;
|
||||
let nick_empty = " ".repeat(nick.width());
|
||||
|
||||
for (i, line) in msg.content.lines().enumerate() {
|
||||
if i == 0 {
|
||||
let time = msg.time.0.format(TIME_FORMAT);
|
||||
writeln!(file, "{time} {indent_string}[{nick}] {line}")?;
|
||||
} else {
|
||||
writeln!(file, "{TIME_EMPTY} {indent_string} {nick_empty} {line}")?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_placeholder(file: &mut BufWriter<File>, indent_string: &str) -> anyhow::Result<()> {
|
||||
writeln!(file, "{TIME_EMPTY} {indent_string}...")?;
|
||||
Ok(())
|
||||
}
|
||||
52
src/main.rs
52
src/main.rs
|
|
@ -3,21 +3,65 @@
|
|||
// TODO Clean up use and manipulation of toss Pos and Size
|
||||
|
||||
mod euph;
|
||||
mod export;
|
||||
mod logger;
|
||||
mod replies;
|
||||
mod store;
|
||||
mod ui;
|
||||
mod vault;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use clap::Parser;
|
||||
use directories::ProjectDirs;
|
||||
use log::info;
|
||||
use toss::terminal::Terminal;
|
||||
use ui::Ui;
|
||||
use vault::Vault;
|
||||
|
||||
use crate::logger::Logger;
|
||||
|
||||
#[derive(Debug, clap::Subcommand)]
|
||||
enum Command {
|
||||
/// Run the client interactively (default).
|
||||
Run,
|
||||
/// Export logs for a single room as a plain text file.
|
||||
Export { room: String, file: PathBuf },
|
||||
}
|
||||
|
||||
impl Default for Command {
|
||||
fn default() -> Self {
|
||||
Self::Run
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, clap::Parser)]
|
||||
struct Args {
|
||||
#[clap(subcommand)]
|
||||
command: Option<Command>,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
let dirs = ProjectDirs::from("de", "plugh", "cove").expect("unable to determine directories");
|
||||
println!("Data dir: {}", dirs.data_dir().to_string_lossy());
|
||||
|
||||
let vault = vault::launch(&dirs.data_dir().join("vault.db"))?;
|
||||
|
||||
match args.command.unwrap_or_default() {
|
||||
Command::Run => run(&vault).await?,
|
||||
Command::Export { room, file } => export::export(&vault, room, &file).await?,
|
||||
}
|
||||
|
||||
vault.close().await;
|
||||
|
||||
println!("Goodbye!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn run(vault: &Vault) -> anyhow::Result<()> {
|
||||
let (logger, logger_rx) = Logger::init(log::Level::Debug);
|
||||
info!(
|
||||
"Welcome to {} {}",
|
||||
|
|
@ -25,18 +69,10 @@ async fn main() -> anyhow::Result<()> {
|
|||
env!("CARGO_PKG_VERSION")
|
||||
);
|
||||
|
||||
let dirs = ProjectDirs::from("de", "plugh", "cove").expect("unable to determine directories");
|
||||
println!("Data dir: {}", dirs.data_dir().to_string_lossy());
|
||||
|
||||
let vault = vault::launch(&dirs.data_dir().join("vault.db"))?;
|
||||
|
||||
let mut terminal = Terminal::new()?;
|
||||
// terminal.set_measuring(true);
|
||||
Ui::run(&mut terminal, vault.clone(), logger, logger_rx).await?;
|
||||
drop(terminal); // So the vault can print again
|
||||
|
||||
vault.close().await;
|
||||
|
||||
println!("Goodbye!");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,11 @@ impl FromSql for Time {
|
|||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EuphMsg {
|
||||
id: Snowflake,
|
||||
parent: Option<Snowflake>,
|
||||
time: Time,
|
||||
nick: String,
|
||||
content: String,
|
||||
pub id: Snowflake,
|
||||
pub parent: Option<Snowflake>,
|
||||
pub time: Time,
|
||||
pub nick: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
impl Msg for EuphMsg {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue