about summary refs log blame commit diff stats
path: root/old/yts/main.rs
blob: cd4ef356e4aac8fc634f51fd83fed4e412c37797 (plain) (tree)

































































































                                                                                              
// 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(())
}