about summary refs log tree commit diff stats
path: root/old/ytc/main.rs
blob: e1359f99513b5eb34d49c68cdcf37b577d383f68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
// 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 std::{env, process::Command as StdCmd};

use anyhow::{bail, Context, Result};
use clap::Parser;
use log::debug;
use url::Url;
use yt::{
    downloader::{Downloadable, Downloader},
    YtccListData,
};

use crate::args::{Args, Command};

fn main() -> Result<()> {
    let args = Args::parse();
    cli_log::init_cli_log!();

    let playspec: Vec<Downloadable> = match args.subcommand {
        Command::Id { ids } => {
            let mut output = Vec::with_capacity(ids.len());
            for id in ids {
                debug!("Adding {}", id);
                let mut ytcc = StdCmd::new("ytcc");
                ytcc.args([
                    "--output",
                    "json",
                    "list",
                    "--watched",
                    "--unwatched",
                    "--attributes",
                    "url",
                    "--ids",
                    id.to_string().as_str(),
                ]);
                let json = serde_json::from_slice::<Vec<YtccListData>>(
                    &ytcc.output().context("Failed to get url from id")?.stdout,
                )
                .context("Failed to deserialize json output")?;

                if json.is_empty() {
                    bail!("Could not find a video with id: {}", id);
                }
                assert_eq!(json.len(), 1);
                let json = json.first().expect("Has only one element");

                debug!("Id resolved to: '{}'", &json.url);

                output.push(Downloadable {
                    url: Url::parse(&json.url)?,
                    id: Some(json.id),
                })
            }
            output
        }
        Command::Url { urls } => {
            let mut output = Vec::with_capacity(urls.len());
            for url in urls {
                output.push(Downloadable {
                    url: Url::parse(&url).context("Failed to parse url")?,
                    id: None,
                })
            }
            output
        }
    };

    debug!("Initializing downloader");
    let downloader = Downloader::new(playspec)?;

    downloader
        .consume()
        .context("Failed to consume downloader")?;

    Ok(())
}