// yt - A fully featured command line YouTube client // // Copyright (C) 2024 Benedikt Peetz // SPDX-License-Identifier: GPL-3.0-or-later // // This file is part of Yt. // // You should have received a copy of the License along with this program. // If not, see . use anyhow::{bail, Context, Result}; use clap::Parser; use std::{ env, io::{BufRead, BufReader, Write}, process::Command as StdCmd, }; use tempfile::NamedTempFile; use yt::{constants::HELP_STR, filter_line, YtccListData}; use crate::args::{Args, Command, OrderCommand}; fn main() -> Result<()> { let args = Args::parse(); cli_log::init_cli_log!(); let ordering = match args.subcommand.unwrap_or(Command::Order { command: OrderCommand::Date { desc: true, asc: false, }, }) { Command::Order { command } => match command { OrderCommand::Date { desc, asc } => { if desc { vec!["--order-by".into(), "publish_date".into(), "desc".into()] } else if asc { vec!["--order-by".into(), "publish_date".into(), "asc".into()] } else { vec!["--order-by".into(), "publish_date".into(), "desc".into()] } } OrderCommand::Raw { value } => [vec!["--order-by".into()], value].concat(), }, }; let json_map = { let mut ytcc = StdCmd::new("ytcc"); ytcc.args(["--output", "json", "list"]); ytcc.args(ordering); serde_json::from_slice::>( &ytcc.output().context("Failed to json from ytcc")?.stdout, ) .context("Failed to deserialize json output")? }; let mut edit_file = NamedTempFile::new().context("Failed to get tempfile")?; json_map.iter().for_each(|line| { let line = line.to_string(); edit_file .write_all(line.as_bytes()) .expect("This write should not fail"); }); write!(&edit_file, "{}", HELP_STR)?; edit_file.flush().context("Failed to flush edit file")?; let read_file = edit_file.reopen()?; let mut nvim = StdCmd::new("nvim"); nvim.arg(edit_file.path()); let status = nvim.status().context("Falied to run nvim")?; if !status.success() { bail!("Nvim exited with error status: {}", status) } let mut watching = Vec::new(); let reader = BufReader::new(&read_file); for line in reader.lines() { let line = line.context("Failed to read line")?; if let Some(downloadable) = filter_line(&line).with_context(|| format!("Failed to process line: '{}'", line))? { watching.push(downloadable); } } let watching: String = watching .iter() .map(|d| d.to_string()) .collect::>() .join("\n"); println!("{}", &watching); Ok(()) }