Yet Another Youtube Down Loader

⌈⌋ ⎇ branch:  yaydl


Check-in [512577aefc]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:yaydl 0.7.1: Updated one dependency and fixed YouTube's URL regex - thank you, @yeurch!
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk | release-0.7.1
Files: files | file ages | folders
SHA3-256: 512577aefce95769683357942ca14b70b3f7fd8a83c7d1c1d953c33dbec55a7e
User & Date: Cthulhux 2022-05-17 11:44:43
Context
2022-05-23
11:16
yaydl 0.8.0: * Introducing WebDriver support with fantoccini. In theory, yaydl can now use Firefox or Chrome for scraping a website, even if its contents require JavaScript. The only obvious downside is that this adds complexity to the SiteDefinition trait. (Requires a compatible WebDriver client as described in the README.) * Fixed the WatchMDH handler which is the first handler to use a WebDriver. * Upgraded the argument parser to clap_derive (easier annotation, even easier usage). * Updated the Rust edition to 2021, could be useful later. check-in: 684630ccbe user: Cthulhux tags: trunk, release-0.8.0
2022-05-17
11:44
yaydl 0.7.1: Updated one dependency and fixed YouTube's URL regex - thank you, @yeurch! check-in: 512577aefc user: Cthulhux tags: trunk, release-0.7.1
2022-04-10
16:03
yaydl 0.7.0: updated dependencies, added new -k flag. Fixes #5. check-in: 5e3cd2b65f user: Cthulhux tags: trunk, release-0.7.0
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to Cargo.toml.

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
[package]
name = "yaydl"
description = "yet another youtube (and more) down loader"
version = "0.7.0"
authors = ["Cthulhux <git@tuxproject.de>"]
edition = "2018"
license = "CDDL-1.0"
repository = "https://code.rosaelefanten.org/yaydl"
categories = ["command-line-utilities"]
keywords = ["youtube", "downloading", "video"]

[dependencies]
anyhow = "1.0"
cienli = "0.3"
clap = "3.1"
indicatif = "0.16"
inventory = "0.1"
regex = "1.5"
scraper = "0.12"
serde_json = "1.0"
ureq = { version = "2.4", features = ["json"] }
url = "2.2"
urlencoding = "2.1"

[profile.release]
lto = true



|














|







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
[package]
name = "yaydl"
description = "yet another youtube (and more) down loader"
version = "0.7.1"
authors = ["Cthulhux <git@tuxproject.de>"]
edition = "2018"
license = "CDDL-1.0"
repository = "https://code.rosaelefanten.org/yaydl"
categories = ["command-line-utilities"]
keywords = ["youtube", "downloading", "video"]

[dependencies]
anyhow = "1.0"
cienli = "0.3"
clap = "3.1"
indicatif = "0.16"
inventory = "0.1"
regex = "1.5"
scraper = "0.13"
serde_json = "1.0"
ureq = { version = "2.4", features = ["json"] }
url = "2.2"
urlencoding = "2.1"

[profile.release]
lto = true

Changes to src/handlers/youtube.rs.

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
    Ok(v)
}

// Implement the site definition:
struct YouTubeHandler;
impl SiteDefinition for YouTubeHandler {
    fn can_handle_url<'a>(&'a self, url: &'a str) -> bool {
        Regex::new(r"(?:www\.)?youtu(?:be.com|be)/")
            .unwrap()
            .is_match(url)
    }

    fn find_video_title<'a>(&'a self, url: &'a str) -> Result<String> {
        let id_regex = Regex::new(r"(?:v=|.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_title = video_info["videoDetails"]["title"].as_str().unwrap_or("");

            Ok(String::from(video_info_title))
        }
    }

    fn find_video_direct_url<'a>(&'a self, url: &'a str, onlyaudio: bool) -> Result<String> {
        let id_regex = Regex::new(r"(?:v=|.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_itags = match video_info["streamingData"]["formats"].as_array() {
                None => return Ok("".to_string()),
                Some(itags) => itags,
            };







|





|










|







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
    Ok(v)
}

// Implement the site definition:
struct YouTubeHandler;
impl SiteDefinition for YouTubeHandler {
    fn can_handle_url<'a>(&'a self, url: &'a str) -> bool {
        Regex::new(r"(?:www\.)?youtu(?:be\.com|\.be)/")
            .unwrap()
            .is_match(url)
    }

    fn find_video_title<'a>(&'a self, url: &'a str) -> Result<String> {
        let id_regex = Regex::new(r"(?:v=|\.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_title = video_info["videoDetails"]["title"].as_str().unwrap_or("");

            Ok(String::from(video_info_title))
        }
    }

    fn find_video_direct_url<'a>(&'a self, url: &'a str, onlyaudio: bool) -> Result<String> {
        let id_regex = Regex::new(r"(?:v=|\.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_itags = match video_info["streamingData"]["formats"].as_array() {
                None => return Ok("".to_string()),
                Some(itags) => itags,
            };
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
            } else {
                Ok(url_to_choose.to_string())
            }
        }
    }

    fn does_video_exist<'a>(&'a self, url: &'a str) -> Result<bool> {
        let id_regex = Regex::new(r"(?:v=|.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_is_playable = video_info["playabilityStatus"]["status"] == json!("OK");
            let video_info_has_details = video_info["videoDetails"] != json!(null);
            Ok(video_info_has_details && video_info_is_playable)
        }







|







151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
            } else {
                Ok(url_to_choose.to_string())
            }
        }
    }

    fn does_video_exist<'a>(&'a self, url: &'a str) -> Result<bool> {
        let id_regex = Regex::new(r"(?:v=|\.be/)(.*$)").unwrap();
        let id = id_regex.captures(url).unwrap().get(1).unwrap().as_str();
        unsafe {
            let video_info = get_video_info(id)?;
            let video_info_is_playable = video_info["playabilityStatus"]["status"] == json!("OK");
            let video_info_has_details = video_info["videoDetails"] != json!(null);
            Ok(video_info_has_details && video_info_is_playable)
        }