Compare commits
No commits in common. "43ed52daf9e79d53471580841aba6fd7e0e89b2c" and "e5c51fe99592519bca5500ce4082aad4a0cb8b7d" have entirely different histories.
43ed52daf9
...
e5c51fe995
16 changed files with 32 additions and 56 deletions
10
Justfile
10
Justfile
|
@ -7,6 +7,14 @@ unittest:
|
||||||
testyt:
|
testyt:
|
||||||
cargo test --features=rss --test youtube
|
cargo test --features=rss --test youtube
|
||||||
|
|
||||||
|
testyt10:
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
for i in {1..10}; do \
|
||||||
|
echo "---TEST RUN $i---"; \
|
||||||
|
cargo test --features=rss --test youtube; \
|
||||||
|
done
|
||||||
|
|
||||||
testintl:
|
testintl:
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
LANGUAGES=(
|
LANGUAGES=(
|
||||||
|
@ -39,4 +47,4 @@ testfiles:
|
||||||
|
|
||||||
report2yaml:
|
report2yaml:
|
||||||
mkdir -p rustypipe_reports/conv
|
mkdir -p rustypipe_reports/conv
|
||||||
for f in rustypipe_reports/*.json; do yq '.http_request.resp_body' $f | yq -o json -P > rustypipe_reports/conv/`basename $f .json`_body.json; yq e -Pi "del(.http_request.resp_body)" $f; mv $f rustypipe_reports/conv/`basename $f .json`.yaml; done;
|
for f in rustypipe_reports/*.json; do yq '.http_request.resp_body' $f | yq -o json -P > rustypipe_reports/conv/`basename $f .json`_body.json; yq e -Pi $f; mv $f rustypipe_reports/conv/`basename $f .json`.yaml; done;
|
||||||
|
|
26
README.md
26
README.md
|
@ -154,29 +154,3 @@ Subscribers: 1780000
|
||||||
[6Fv8bd9ICb4] Who owns this? (199s)
|
[6Fv8bd9ICb4] Who owns this? (199s)
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
**Requirements:**
|
|
||||||
|
|
||||||
- Current version of stable Rust
|
|
||||||
- [`just`](https://github.com/casey/just) task runner
|
|
||||||
- [`pre-commit`](https://pre-commit.com/)
|
|
||||||
- yq (YAML processor)
|
|
||||||
|
|
||||||
### Tasks
|
|
||||||
|
|
||||||
**Testing**
|
|
||||||
|
|
||||||
- `just test` Run unit+integration tests
|
|
||||||
- `just unittest` Run unit tests
|
|
||||||
- `just testyt` Run YouTube integration tests
|
|
||||||
- `just testintl` Run YouTube integration tests for all supported languages (this takes
|
|
||||||
a long time and is therefore not run in CI)
|
|
||||||
- `YT_LANG=de just testyt` Run YouTube integration tests for a specific language
|
|
||||||
|
|
||||||
**Tools**
|
|
||||||
|
|
||||||
- `just testfiles` Download missing testfiles for unit tests
|
|
||||||
- `just report2yaml` Convert RustyPipe reports into a more readable yaml format
|
|
||||||
(requires `yq`)
|
|
||||||
|
|
|
@ -19,9 +19,6 @@ use serde::Serialize;
|
||||||
struct Cli {
|
struct Cli {
|
||||||
#[clap(subcommand)]
|
#[clap(subcommand)]
|
||||||
command: Commands,
|
command: Commands,
|
||||||
/// Always generate a report (used for debugging)
|
|
||||||
#[clap(long)]
|
|
||||||
report: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[derive(Subcommand)]
|
||||||
|
@ -395,11 +392,10 @@ async fn main() {
|
||||||
storage_dir.push("rustypipe");
|
storage_dir.push("rustypipe");
|
||||||
_ = std::fs::create_dir(&storage_dir);
|
_ = std::fs::create_dir(&storage_dir);
|
||||||
|
|
||||||
let mut rp = RustyPipe::builder().storage_dir(storage_dir);
|
let rp = RustyPipe::builder()
|
||||||
if cli.report {
|
.storage_dir(storage_dir)
|
||||||
rp = rp.report();
|
.build()
|
||||||
}
|
.unwrap();
|
||||||
let rp = rp.build().unwrap();
|
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::Download {
|
Commands::Download {
|
||||||
|
|
|
@ -77,8 +77,8 @@ pub(crate) enum VideoResultsItem {
|
||||||
/// Like/Dislike button
|
/// Like/Dislike button
|
||||||
video_actions: VideoActions,
|
video_actions: VideoActions,
|
||||||
/// Absolute textual date (e.g. `Dec 29, 2019`)
|
/// Absolute textual date (e.g. `Dec 29, 2019`)
|
||||||
#[serde_as(as = "Option<Text>")]
|
#[serde_as(as = "Text")]
|
||||||
date_text: Option<String>,
|
date_text: String,
|
||||||
},
|
},
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
VideoSecondaryInfoRenderer {
|
VideoSecondaryInfoRenderer {
|
||||||
|
|
|
@ -139,7 +139,7 @@ VideoDetails(
|
||||||
view_count: 233243423,
|
view_count: 233243423,
|
||||||
like_count: Some(4015532),
|
like_count: Some(4015532),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Nov 17, 2020"),
|
publish_date_txt: "Nov 17, 2020",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -139,7 +139,7 @@ VideoDetails(
|
||||||
view_count: 234258725,
|
view_count: 234258725,
|
||||||
like_count: Some(4027586),
|
like_count: Some(4027586),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Nov 17, 2020"),
|
publish_date_txt: "Nov 17, 2020",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -389,7 +389,7 @@ VideoDetails(
|
||||||
view_count: 1251797,
|
view_count: 1251797,
|
||||||
like_count: Some(58077),
|
like_count: Some(58077),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Sep 15, 2022"),
|
publish_date_txt: "Sep 15, 2022",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [
|
chapters: [
|
||||||
|
|
|
@ -32,7 +32,7 @@ VideoDetails(
|
||||||
view_count: 205,
|
view_count: 205,
|
||||||
like_count: None,
|
like_count: None,
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Jan 2, 2019"),
|
publish_date_txt: "Jan 2, 2019",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -50,7 +50,7 @@ VideoDetails(
|
||||||
view_count: 2493983,
|
view_count: 2493983,
|
||||||
like_count: Some(52274),
|
like_count: Some(52274),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Dec 29, 2019"),
|
publish_date_txt: "Dec 29, 2019",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: true,
|
is_ccommons: true,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -371,7 +371,7 @@ VideoDetails(
|
||||||
view_count: 971966,
|
view_count: 971966,
|
||||||
like_count: Some(48244),
|
like_count: Some(48244),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Sep 15, 2022"),
|
publish_date_txt: "Sep 15, 2022",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [
|
chapters: [
|
||||||
|
|
|
@ -94,7 +94,7 @@ VideoDetails(
|
||||||
view_count: 681,
|
view_count: 681,
|
||||||
like_count: Some(872230),
|
like_count: Some(872230),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Started streaming on Sep 23, 2021"),
|
publish_date_txt: "Started streaming on Sep 23, 2021",
|
||||||
is_live: true,
|
is_live: true,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -36,7 +36,7 @@ VideoDetails(
|
||||||
view_count: 20304,
|
view_count: 20304,
|
||||||
like_count: Some(146),
|
like_count: Some(146),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Aug 6, 2020"),
|
publish_date_txt: "Aug 6, 2020",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -139,7 +139,7 @@ VideoDetails(
|
||||||
view_count: 232792465,
|
view_count: 232792465,
|
||||||
like_count: Some(4010156),
|
like_count: Some(4010156),
|
||||||
publish_date: "[date]",
|
publish_date: "[date]",
|
||||||
publish_date_txt: Some("Nov 17, 2020"),
|
publish_date_txt: "Nov 17, 2020",
|
||||||
is_live: false,
|
is_live: false,
|
||||||
is_ccommons: false,
|
is_ccommons: false,
|
||||||
chapters: [],
|
chapters: [],
|
||||||
|
|
|
@ -175,9 +175,7 @@ impl MapResponse<VideoDetails> for response::VideoDetails {
|
||||||
// accessibility_data contains no digits if the like count is hidden,
|
// accessibility_data contains no digits if the like count is hidden,
|
||||||
// so we ignore parse errors here for now
|
// so we ignore parse errors here for now
|
||||||
like_btn.and_then(|btn| util::parse_numeric(&btn.accessibility_data).ok()),
|
like_btn.and_then(|btn| util::parse_numeric(&btn.accessibility_data).ok()),
|
||||||
date_text.as_deref().and_then(|txt| {
|
timeago::parse_textual_date_or_warn(lang, &date_text, &mut warnings),
|
||||||
timeago::parse_textual_date_or_warn(lang, txt, &mut warnings)
|
|
||||||
}),
|
|
||||||
date_text,
|
date_text,
|
||||||
view_count
|
view_count
|
||||||
.map(|vc| vc.video_view_count_renderer.is_live)
|
.map(|vc| vc.video_view_count_renderer.is_live)
|
||||||
|
|
|
@ -567,7 +567,7 @@ pub struct VideoDetails {
|
||||||
#[serde(with = "time::serde::rfc3339::option")]
|
#[serde(with = "time::serde::rfc3339::option")]
|
||||||
pub publish_date: Option<OffsetDateTime>,
|
pub publish_date: Option<OffsetDateTime>,
|
||||||
/// Textual video publishing date (e.g. `Aug 2, 2013`, depends on language)
|
/// Textual video publishing date (e.g. `Aug 2, 2013`, depends on language)
|
||||||
pub publish_date_txt: Option<String>,
|
pub publish_date_txt: String,
|
||||||
/// Is the video a livestream?
|
/// Is the video a livestream?
|
||||||
pub is_live: bool,
|
pub is_live: bool,
|
||||||
/// Is the video published under the Creative Commons BY 3.0 license?
|
/// Is the video published under the Creative Commons BY 3.0 license?
|
||||||
|
|
|
@ -1278,10 +1278,10 @@ fn trending(rp: RustyPipe) {
|
||||||
false,
|
false,
|
||||||
)]
|
)]
|
||||||
#[case::short(
|
#[case::short(
|
||||||
"RDCLAK5uy_nLNY4ReQKH2kx5U23cyGMHql9ciHD9RSM",
|
"RDCLAK5uy_kFQXdnqMaQCVx2wpUM4ZfbsGCDibZtkJk",
|
||||||
"Presenting BLACKPINK (블랙핑크)",
|
"Easy Pop",
|
||||||
false,
|
false,
|
||||||
Some("The most played hits and essential tracks. #blackpink #best #kpop".to_owned()),
|
Some("Stress-free tunes from classic rockers and newer artists.\nThis playlist is no longer being updated.".to_owned()),
|
||||||
None,
|
None,
|
||||||
true
|
true
|
||||||
)]
|
)]
|
||||||
|
@ -2181,7 +2181,7 @@ fn music_genres(rp: RustyPipe, unlocalized: bool) {
|
||||||
let chill = genres
|
let chill = genres
|
||||||
.iter()
|
.iter()
|
||||||
.find(|g| g.id == "ggMPOg1uX1JOQWZFeDByc2Jm")
|
.find(|g| g.id == "ggMPOg1uX1JOQWZFeDByc2Jm")
|
||||||
.expect("genre: Chill");
|
.unwrap();
|
||||||
if unlocalized {
|
if unlocalized {
|
||||||
assert_eq!(chill.name, "Chill");
|
assert_eq!(chill.name, "Chill");
|
||||||
}
|
}
|
||||||
|
@ -2189,8 +2189,8 @@ fn music_genres(rp: RustyPipe, unlocalized: bool) {
|
||||||
|
|
||||||
let pop = genres
|
let pop = genres
|
||||||
.iter()
|
.iter()
|
||||||
.find(|g| g.id == "ggMPOg1uX1lMbVZmbzl6NlJ3" || g.id == "ggMPOg1uX1BmNzc2V2p0YXJ5")
|
.find(|g| g.id == "ggMPOg1uX1lMbVZmbzl6NlJ3")
|
||||||
.expect("genre: Pop");
|
.unwrap();
|
||||||
assert_eq!(pop.name, "Pop");
|
assert_eq!(pop.name, "Pop");
|
||||||
assert!(!pop.is_mood);
|
assert!(!pop.is_mood);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue