// yt - A fully featured command line YouTube client
//
// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de>
// 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 <https://www.gnu.org/licenses/gpl-3.0.txt>.
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::<Vec<YtccListData>>(
&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::<Vec<String>>()
.join("\n");
println!("{}", &watching);
Ok(())
}