about summary refs log tree commit diff stats
path: root/pkgs/by-name/yt/yt/src/select/selection_file/mod.rs
blob: 957fcd0876e88fad0311a697e03ed6886dc3420e (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
//! The data structures needed to express the file, which the user edits

use anyhow::{bail, Context};
use url::Url;

use crate::{app::App, storage::video_database::extractor_hash::ExtractorHash};

pub mod display;
pub mod duration;

pub enum LineCommand {
    Pick,
    Drop,
    Watch,
    Url,
}

impl std::str::FromStr for LineCommand {
    type Err = anyhow::Error;
    fn from_str(v: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
        match v {
            "pick" | "p" => Ok(Self::Pick),
            "drop" | "d" => Ok(Self::Drop),
            "watch" | "w" => Ok(Self::Watch),
            "url" | "u" => Ok(Self::Url),
            other => bail!("'{}' is not a recognized command!", other),
        }
    }
}

pub struct Line {
    pub cmd: LineCommand,
    pub hash: ExtractorHash,
    pub url: Url,
}

impl Line {
    pub async fn from_str(app: &App, s: &str) -> anyhow::Result<Self> {
        let buf: Vec<_> = s.split_whitespace().collect();

        let url_as_str = buf
            .last()
            .with_context(|| format!("The line '{}' misses it's url field!'", s))?
            .trim_matches('"');

        let url: Url = Url::parse(url_as_str)
            .with_context(|| format!("The url '{}' could not be parsed!", url_as_str))?;

        Ok(Line {
            cmd: buf
                .get(0)
                .with_context(|| format!("The line '{}' is missing it's command!", s))?
                .parse()?,
            hash: ExtractorHash::parse_from_short_version(
                app,
                buf.get(1)
                    .with_context(|| format!("The line '{}' is missing it's blake3 hash!", s))?,
            )
            .await
            .with_context(|| {
                format!(
                    "Can't parse '{}' as blake3 hash!",
                    buf.get(1).expect("Already checked"),
                )
            })?,
            url,
        })
    }
}

pub async fn filter_line(app: &App, line: &str) -> anyhow::Result<Option<Line>> {
    // Filter out comments and empty lines
    if line.starts_with('#') || line.trim().is_empty() {
        return Ok(None);
    }

    let line: Line = Line::from_str(app, line).await?;
    Ok(Some(line))
}