Compare commits
No commits in common. "d413cad8bbe0957aae150e21c9f1121fda6a629c" and "f618add384d6812b5ac1576fe58bd7603101b42f" have entirely different histories.
d413cad8bb
...
f618add384
7 changed files with 162 additions and 84 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use regex::Regex;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_with::{
|
use serde_with::{
|
||||||
rust::deserialize_ignore_any, serde_as, DefaultOnError, DisplayFromStr, VecSkipError,
|
rust::deserialize_ignore_any, serde_as, DefaultOnError, DisplayFromStr, VecSkipError,
|
||||||
|
@ -12,7 +14,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
param::Language,
|
param::Language,
|
||||||
serializer::{
|
serializer::{
|
||||||
text::{Text, TextComponent},
|
text::{AccessibilityText, Text, TextComponent},
|
||||||
MapResult,
|
MapResult,
|
||||||
},
|
},
|
||||||
util::{self, timeago, TryRemove},
|
util::{self, timeago, TryRemove},
|
||||||
|
@ -137,6 +139,13 @@ pub(crate) struct ReelItemRenderer {
|
||||||
/// Contains `No views` if the view count is zero
|
/// Contains `No views` if the view count is zero
|
||||||
#[serde_as(as = "Option<Text>")]
|
#[serde_as(as = "Option<Text>")]
|
||||||
pub view_count_text: Option<String>,
|
pub view_count_text: Option<String>,
|
||||||
|
/// video duration
|
||||||
|
///
|
||||||
|
/// Example: `the horror maze - 44 seconds - play video`
|
||||||
|
///
|
||||||
|
/// Dashes may be `\u2013` (emdash)
|
||||||
|
#[serde_as(as = "Option<AccessibilityText>")]
|
||||||
|
pub accessibility: Option<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[serde_as(as = "DefaultOnError")]
|
#[serde_as(as = "DefaultOnError")]
|
||||||
pub navigation_endpoint: Option<ReelNavigationEndpoint>,
|
pub navigation_endpoint: Option<ReelNavigationEndpoint>,
|
||||||
|
@ -386,6 +395,10 @@ impl IsShort for Vec<TimeOverlay> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ACCESSIBILITY_SEP_REGEX: Lazy<Regex> = Lazy::new(|| {
|
||||||
|
Regex::new("(?:[ \u{00a0}][-\u{2013}\u{2014}] )|\u{2013}|(?:\u{055d} )|(?:\", )").unwrap()
|
||||||
|
});
|
||||||
|
|
||||||
/// Result of mapping a list of different YouTube enities
|
/// Result of mapping a list of different YouTube enities
|
||||||
/// (videos, channels, playlists)
|
/// (videos, channels, playlists)
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -497,10 +510,36 @@ impl<T> YouTubeListMapper<T> {
|
||||||
.timestamp_text
|
.timestamp_text
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let length = video.accessibility.and_then(|acc| {
|
||||||
|
// The video title has to be stripped from the beginning because in Swahili
|
||||||
|
// the duration follows the title with no separator (probably a bug).
|
||||||
|
// Example: `what I do with leftoversdakika 1 - cheza video`
|
||||||
|
let parts = ACCESSIBILITY_SEP_REGEX
|
||||||
|
.split(acc.trim_start_matches(&video.headline))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
if parts.len() > 1 {
|
||||||
|
// In Russian, the duration is the last part
|
||||||
|
// Example: `Воспроизвести видео – \"hangover food\". Его продолжительность – 58 секунд.`
|
||||||
|
let i = match self.lang {
|
||||||
|
Language::Ru => 1,
|
||||||
|
_ => 2,
|
||||||
|
};
|
||||||
|
timeago::parse_video_duration_or_warn(
|
||||||
|
self.lang,
|
||||||
|
parts[parts.len() - i],
|
||||||
|
&mut self.warnings,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
self.warnings
|
||||||
|
.push(format!("could not split video duration `{acc}`"));
|
||||||
|
None
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
VideoItem {
|
VideoItem {
|
||||||
id: video.video_id,
|
id: video.video_id,
|
||||||
name: video.headline,
|
name: video.headline,
|
||||||
length: None,
|
length,
|
||||||
thumbnail: video.thumbnail.into(),
|
thumbnail: video.thumbnail.into(),
|
||||||
channel: self.channel.clone(),
|
channel: self.channel.clone(),
|
||||||
publish_date: pub_date_txt.as_ref().and_then(|txt| {
|
publish_date: pub_date_txt.as_ref().and_then(|txt| {
|
||||||
|
@ -750,3 +789,50 @@ impl YouTubeListMapper<PlaylistItem> {
|
||||||
res.c.into_iter().for_each(|item| self.map_item(item));
|
res.c.into_iter().for_each(|item| self.map_item(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::ACCESSIBILITY_SEP_REGEX;
|
||||||
|
|
||||||
|
use rstest::rstest;
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::af(
|
||||||
|
"BTS - Permission to Dance Cover #shorts #pinkfong – 50 sekondes – speel video",
|
||||||
|
"50 sekondes"
|
||||||
|
)]
|
||||||
|
#[case::de(
|
||||||
|
"Point of view: Me VS My mom #shorts – 8 Sekunden – Video wiedergeben",
|
||||||
|
"8 Sekunden"
|
||||||
|
)]
|
||||||
|
#[case::be(
|
||||||
|
"Point of view: Me VS My mom #shorts–8 секунд – прайграць відэа",
|
||||||
|
"8 секунд"
|
||||||
|
)]
|
||||||
|
#[case::fil("do u wanna get swole? - 53 segundo - i-play ang video", "53 segundo")]
|
||||||
|
#[case::ar(
|
||||||
|
"«the holy trinity of korean street food»՝ 1 րոպե՝ նվագարկել տեսանյութը",
|
||||||
|
"1 րոպե"
|
||||||
|
)]
|
||||||
|
#[case::lv(
|
||||||
|
"what i ate in google japan — 1 minūte — atskaņot videoklipu",
|
||||||
|
"1 minūte"
|
||||||
|
)]
|
||||||
|
#[case::sq("When you impulse buy... - 1 minutë - luaj videon", "1 minutë")]
|
||||||
|
#[case::uk(
|
||||||
|
"\"Point of view: Me VS My mom #shorts\", 8 секунд – відтворити відео",
|
||||||
|
"8 секунд"
|
||||||
|
)]
|
||||||
|
// INFO: sw is unparseable "coming soonsekunde 58 - cheza video"
|
||||||
|
fn split_duration_txt(#[case] s: &str, #[case] expect: &str) {
|
||||||
|
let parts = ACCESSIBILITY_SEP_REGEX.split(s).collect::<Vec<_>>();
|
||||||
|
assert_eq!(parts[parts.len() - 2], expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_duration_txt_ru() {
|
||||||
|
let s = "Воспроизвести видео – \"the holy trinity of korean street food\". Его продолжительность – 1 минута.";
|
||||||
|
let parts = ACCESSIBILITY_SEP_REGEX.split(s).collect::<Vec<_>>();
|
||||||
|
assert_eq!(parts[parts.len() - 1], "1 минута.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -122,7 +122,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "bGXP83AU3Mc",
|
id: "bGXP83AU3Mc",
|
||||||
name: "do u wanna get swole?",
|
name: "do u wanna get swole?",
|
||||||
length: None,
|
length: Some(53),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/bGXP83AU3Mc/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC9bzCBeHDbZFLE84Up3IiBIsxmmA",
|
url: "https://i.ytimg.com/vi/bGXP83AU3Mc/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC9bzCBeHDbZFLE84Up3IiBIsxmmA",
|
||||||
|
@ -148,7 +148,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "E52sSgZlgYs",
|
id: "E52sSgZlgYs",
|
||||||
name: "the holy trinity of korean street food",
|
name: "the holy trinity of korean street food",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/E52sSgZlgYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDBahtFRcfBInHuA8CjXFPWkF2jHg",
|
url: "https://i.ytimg.com/vi/E52sSgZlgYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDBahtFRcfBInHuA8CjXFPWkF2jHg",
|
||||||
|
@ -174,7 +174,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "ovaHmfy3O6U",
|
id: "ovaHmfy3O6U",
|
||||||
name: "hangover food",
|
name: "hangover food",
|
||||||
length: None,
|
length: Some(58),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/ovaHmfy3O6U/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCHmvWlG06h-DT6oxfmh69JGQ69KA",
|
url: "https://i.ytimg.com/vi/ovaHmfy3O6U/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCHmvWlG06h-DT6oxfmh69JGQ69KA",
|
||||||
|
@ -200,7 +200,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "FHTQmKTZnlI",
|
id: "FHTQmKTZnlI",
|
||||||
name: "pig trotter raguuuuuuuuu 💅",
|
name: "pig trotter raguuuuuuuuu 💅",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/FHTQmKTZnlI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD0xhka1osA4nI3VCwhQusn3ND3Hg",
|
url: "https://i.ytimg.com/vi/FHTQmKTZnlI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD0xhka1osA4nI3VCwhQusn3ND3Hg",
|
||||||
|
@ -226,7 +226,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "1AXB0l_wKMs",
|
id: "1AXB0l_wKMs",
|
||||||
name: "what i ate in google japan",
|
name: "what i ate in google japan",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/1AXB0l_wKMs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBsfYJ0KffUNn-9jBzNRTqetyFr8g",
|
url: "https://i.ytimg.com/vi/1AXB0l_wKMs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBsfYJ0KffUNn-9jBzNRTqetyFr8g",
|
||||||
|
@ -252,7 +252,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "1ARLtk3HiB0",
|
id: "1ARLtk3HiB0",
|
||||||
name: "succumb to your cravings",
|
name: "succumb to your cravings",
|
||||||
length: None,
|
length: Some(53),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/1ARLtk3HiB0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBY9E40Ehvq862CVItJy0Uj_pS5bg",
|
url: "https://i.ytimg.com/vi/1ARLtk3HiB0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBY9E40Ehvq862CVItJy0Uj_pS5bg",
|
||||||
|
@ -278,7 +278,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "0FfDoDHpaN8",
|
id: "0FfDoDHpaN8",
|
||||||
name: "you can\'t let the what ifs rule your life",
|
name: "you can\'t let the what ifs rule your life",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/0FfDoDHpaN8/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBiV2TVPO-VbIjoNtwCKmFuxmj6LA",
|
url: "https://i.ytimg.com/vi/0FfDoDHpaN8/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBiV2TVPO-VbIjoNtwCKmFuxmj6LA",
|
||||||
|
@ -304,7 +304,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "kuT90_RIdF0",
|
id: "kuT90_RIdF0",
|
||||||
name: "duck confit lollipop 🦆🍭",
|
name: "duck confit lollipop 🦆🍭",
|
||||||
length: None,
|
length: Some(59),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/kuT90_RIdF0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCUN-DW72m7sAXJMgVkWNxPYpJBcQ",
|
url: "https://i.ytimg.com/vi/kuT90_RIdF0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCUN-DW72m7sAXJMgVkWNxPYpJBcQ",
|
||||||
|
@ -330,7 +330,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "aPJLhrcM4Yg",
|
id: "aPJLhrcM4Yg",
|
||||||
name: "HOUSE TOUR",
|
name: "HOUSE TOUR",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/aPJLhrcM4Yg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD1TbWAIbzyWq8AXLoW0xqaji3ukQ",
|
url: "https://i.ytimg.com/vi/aPJLhrcM4Yg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD1TbWAIbzyWq8AXLoW0xqaji3ukQ",
|
||||||
|
@ -356,7 +356,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "DKQrG_hJJX4",
|
id: "DKQrG_hJJX4",
|
||||||
name: "how to meal prep like a korean",
|
name: "how to meal prep like a korean",
|
||||||
length: None,
|
length: Some(59),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/DKQrG_hJJX4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBE2DnpLFvtXsZOu1Ta4JQeOToVAw",
|
url: "https://i.ytimg.com/vi/DKQrG_hJJX4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBE2DnpLFvtXsZOu1Ta4JQeOToVAw",
|
||||||
|
@ -382,7 +382,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "lNizW_P_oVw",
|
id: "lNizW_P_oVw",
|
||||||
name: "Rating Everything I ate at McDonald\'s Japan 🇯🇵",
|
name: "Rating Everything I ate at McDonald\'s Japan 🇯🇵",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/lNizW_P_oVw/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBI5XrkQ9Hesbf4lWELy7Uk3yMGMg",
|
url: "https://i.ytimg.com/vi/lNizW_P_oVw/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBI5XrkQ9Hesbf4lWELy7Uk3yMGMg",
|
||||||
|
@ -408,7 +408,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "kbWyJjrCjwA",
|
id: "kbWyJjrCjwA",
|
||||||
name: "enemies as fertilizer √(veg)",
|
name: "enemies as fertilizer √(veg)",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/kbWyJjrCjwA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDlk30Km1M0jze1M3O90fB2LdvoAQ",
|
url: "https://i.ytimg.com/vi/kbWyJjrCjwA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDlk30Km1M0jze1M3O90fB2LdvoAQ",
|
||||||
|
@ -434,7 +434,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "xAp910JTDig",
|
id: "xAp910JTDig",
|
||||||
name: "let\'s make some cabbage rolls for lunch",
|
name: "let\'s make some cabbage rolls for lunch",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/xAp910JTDig/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAJtpPGRgffBu9WDXACbtiGa_oRgA",
|
url: "https://i.ytimg.com/vi/xAp910JTDig/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAJtpPGRgffBu9WDXACbtiGa_oRgA",
|
||||||
|
@ -460,7 +460,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "vSL7dhKatEk",
|
id: "vSL7dhKatEk",
|
||||||
name: "Rating Everything I ate at IKEA Korea",
|
name: "Rating Everything I ate at IKEA Korea",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/vSL7dhKatEk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBYpIDYbwwWiCqRNVi6PlfEfjrt4A",
|
url: "https://i.ytimg.com/vi/vSL7dhKatEk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBYpIDYbwwWiCqRNVi6PlfEfjrt4A",
|
||||||
|
@ -486,7 +486,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "LZzhUpACXSk",
|
id: "LZzhUpACXSk",
|
||||||
name: "I\'m done being the bigger person",
|
name: "I\'m done being the bigger person",
|
||||||
length: None,
|
length: Some(59),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/LZzhUpACXSk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAFTvhtVUP7QZ4P7U70-0XH7PzDDg",
|
url: "https://i.ytimg.com/vi/LZzhUpACXSk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAFTvhtVUP7QZ4P7U70-0XH7PzDDg",
|
||||||
|
@ -512,7 +512,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "5C7nqNDfhis",
|
id: "5C7nqNDfhis",
|
||||||
name: "we\'re cooking a whole bird today",
|
name: "we\'re cooking a whole bird today",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/5C7nqNDfhis/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLA9I9irDsRjikwd0aqp1FWNFtjAqA",
|
url: "https://i.ytimg.com/vi/5C7nqNDfhis/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLA9I9irDsRjikwd0aqp1FWNFtjAqA",
|
||||||
|
@ -538,7 +538,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "6mj4Af0kUOQ",
|
id: "6mj4Af0kUOQ",
|
||||||
name: "men will disappoint but never potatoes",
|
name: "men will disappoint but never potatoes",
|
||||||
length: None,
|
length: Some(50),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/6mj4Af0kUOQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAVxl-FPt878AQXPBhbV1VSGeR8sw",
|
url: "https://i.ytimg.com/vi/6mj4Af0kUOQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAVxl-FPt878AQXPBhbV1VSGeR8sw",
|
||||||
|
@ -564,7 +564,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "1c3axhSJiaQ",
|
id: "1c3axhSJiaQ",
|
||||||
name: "I used to hate korean food",
|
name: "I used to hate korean food",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/1c3axhSJiaQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBucOEbTsWTDjOOCjNa-fAvz1yxyA",
|
url: "https://i.ytimg.com/vi/1c3axhSJiaQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBucOEbTsWTDjOOCjNa-fAvz1yxyA",
|
||||||
|
@ -590,7 +590,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "F9Vz0m7DPeU",
|
id: "F9Vz0m7DPeU",
|
||||||
name: "Rating everything I got at 7/11 Hawaii ( ft. Mauna Kea )",
|
name: "Rating everything I got at 7/11 Hawaii ( ft. Mauna Kea )",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/F9Vz0m7DPeU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDOoCVL6la3ztUeQ6vP4iL1cEBRjQ",
|
url: "https://i.ytimg.com/vi/F9Vz0m7DPeU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDOoCVL6la3ztUeQ6vP4iL1cEBRjQ",
|
||||||
|
@ -616,7 +616,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "Uey7kl56wks",
|
id: "Uey7kl56wks",
|
||||||
name: "Grabbing Snacks from 7/11 Hawaii",
|
name: "Grabbing Snacks from 7/11 Hawaii",
|
||||||
length: None,
|
length: Some(49),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/Uey7kl56wks/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCWmgajinNtIEbiPbqEtDvkC7Ydrg",
|
url: "https://i.ytimg.com/vi/Uey7kl56wks/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCWmgajinNtIEbiPbqEtDvkC7Ydrg",
|
||||||
|
@ -642,7 +642,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "3un2eUAr6Dg",
|
id: "3un2eUAr6Dg",
|
||||||
name: "cheesy korean corn balls hit different",
|
name: "cheesy korean corn balls hit different",
|
||||||
length: None,
|
length: Some(46),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/3un2eUAr6Dg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD4LziL6GHd1jg8btMJDIM_RhgE_A",
|
url: "https://i.ytimg.com/vi/3un2eUAr6Dg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD4LziL6GHd1jg8btMJDIM_RhgE_A",
|
||||||
|
@ -668,7 +668,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "rI5tWrGpDJA",
|
id: "rI5tWrGpDJA",
|
||||||
name: "hawaiian tajin?!?",
|
name: "hawaiian tajin?!?",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/rI5tWrGpDJA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAjNiKHdFSKGavBrZRDxi9WdR-gJw",
|
url: "https://i.ytimg.com/vi/rI5tWrGpDJA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAjNiKHdFSKGavBrZRDxi9WdR-gJw",
|
||||||
|
@ -694,7 +694,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "WQiGksTxr5g",
|
id: "WQiGksTxr5g",
|
||||||
name: "Rating everything I ate at Hawaiian Supermarket 🌺🏰 pt.2",
|
name: "Rating everything I ate at Hawaiian Supermarket 🌺🏰 pt.2",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/WQiGksTxr5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvzC5xVdTEJX8xtiOqzmeKvmouIg",
|
url: "https://i.ytimg.com/vi/WQiGksTxr5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvzC5xVdTEJX8xtiOqzmeKvmouIg",
|
||||||
|
@ -720,7 +720,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "G7aw-QOsagk",
|
id: "G7aw-QOsagk",
|
||||||
name: "Grocery Shopping at Hawaiian Supermarket 🌺🏰 pt.1",
|
name: "Grocery Shopping at Hawaiian Supermarket 🌺🏰 pt.1",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/G7aw-QOsagk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAoKEkj2lqYU07yW_DU35TNHEOq4w",
|
url: "https://i.ytimg.com/vi/G7aw-QOsagk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAoKEkj2lqYU07yW_DU35TNHEOq4w",
|
||||||
|
@ -746,7 +746,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "Y_F1_Yf-DKQ",
|
id: "Y_F1_Yf-DKQ",
|
||||||
name: "Breakfast at Hawaiian McDonald\'s 🌺",
|
name: "Breakfast at Hawaiian McDonald\'s 🌺",
|
||||||
length: None,
|
length: Some(61),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/Y_F1_Yf-DKQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDTLFBwRThZUk0eugFSNxc-CKI_HQ",
|
url: "https://i.ytimg.com/vi/Y_F1_Yf-DKQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLDTLFBwRThZUk0eugFSNxc-CKI_HQ",
|
||||||
|
@ -772,7 +772,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "Q_ZMcP8faw4",
|
id: "Q_ZMcP8faw4",
|
||||||
name: "crab rangoon toast 🦀 🍞",
|
name: "crab rangoon toast 🦀 🍞",
|
||||||
length: None,
|
length: Some(55),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/Q_ZMcP8faw4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLATLiHTNqLoBKsEKbOckkGjXMvoHA",
|
url: "https://i.ytimg.com/vi/Q_ZMcP8faw4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLATLiHTNqLoBKsEKbOckkGjXMvoHA",
|
||||||
|
@ -798,7 +798,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "1aedyP3r3D0",
|
id: "1aedyP3r3D0",
|
||||||
name: "my secret hot pot sauce 🧙\u{200d}♀\u{fe0f}🍃",
|
name: "my secret hot pot sauce 🧙\u{200d}♀\u{fe0f}🍃",
|
||||||
length: None,
|
length: Some(59),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/1aedyP3r3D0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCh2MpR5k3jCS_wfX-wjtVuIcu7YQ",
|
url: "https://i.ytimg.com/vi/1aedyP3r3D0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCh2MpR5k3jCS_wfX-wjtVuIcu7YQ",
|
||||||
|
@ -824,7 +824,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "fkPkHZ1yyBU",
|
id: "fkPkHZ1yyBU",
|
||||||
name: "the good vs the bad",
|
name: "the good vs the bad",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/fkPkHZ1yyBU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCMngiRtLrBPppmfPnJwJ-cYMwttA",
|
url: "https://i.ytimg.com/vi/fkPkHZ1yyBU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCMngiRtLrBPppmfPnJwJ-cYMwttA",
|
||||||
|
@ -850,7 +850,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "NbQcySLMLmA",
|
id: "NbQcySLMLmA",
|
||||||
name: "cooking with waste?!🗑\u{fe0f}",
|
name: "cooking with waste?!🗑\u{fe0f}",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/NbQcySLMLmA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvxPQo9eqYwjk4cxyBnrHed-tcZg",
|
url: "https://i.ytimg.com/vi/NbQcySLMLmA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvxPQo9eqYwjk4cxyBnrHed-tcZg",
|
||||||
|
@ -876,7 +876,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "3w_5vzM1Pc4",
|
id: "3w_5vzM1Pc4",
|
||||||
name: "Shrek burger 🍔🍀👹",
|
name: "Shrek burger 🍔🍀👹",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/3w_5vzM1Pc4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLB64zOKgmhOt7bvQseeIbjKBICDAg",
|
url: "https://i.ytimg.com/vi/3w_5vzM1Pc4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLB64zOKgmhOt7bvQseeIbjKBICDAg",
|
||||||
|
@ -902,7 +902,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "girJP2r_zLg",
|
id: "girJP2r_zLg",
|
||||||
name: "$$$ on food",
|
name: "$$$ on food",
|
||||||
length: None,
|
length: Some(55),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/girJP2r_zLg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBg2hmruZvx30aiP4Jb4dhz03qOZA",
|
url: "https://i.ytimg.com/vi/girJP2r_zLg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBg2hmruZvx30aiP4Jb4dhz03qOZA",
|
||||||
|
@ -928,7 +928,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "zHp7sZ5OONM",
|
id: "zHp7sZ5OONM",
|
||||||
name: "pumpkin spice churro?! 🎃",
|
name: "pumpkin spice churro?! 🎃",
|
||||||
length: None,
|
length: Some(58),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/zHp7sZ5OONM/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD8ZrcI6mq91ARKnRb_vg-0Qv2raw",
|
url: "https://i.ytimg.com/vi/zHp7sZ5OONM/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD8ZrcI6mq91ARKnRb_vg-0Qv2raw",
|
||||||
|
@ -954,7 +954,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "iqMl3gQEZ0E",
|
id: "iqMl3gQEZ0E",
|
||||||
name: "3,000,000",
|
name: "3,000,000",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/iqMl3gQEZ0E/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBUC1sw84NlLiyTJTcfnDWFjVC75w",
|
url: "https://i.ytimg.com/vi/iqMl3gQEZ0E/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBUC1sw84NlLiyTJTcfnDWFjVC75w",
|
||||||
|
@ -980,7 +980,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "glyJWxp7a5g",
|
id: "glyJWxp7a5g",
|
||||||
name: "being smart was my personality trait",
|
name: "being smart was my personality trait",
|
||||||
length: None,
|
length: Some(56),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/glyJWxp7a5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBbrWwLndPt5ZV5x4dnqmTC_aAhig",
|
url: "https://i.ytimg.com/vi/glyJWxp7a5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBbrWwLndPt5ZV5x4dnqmTC_aAhig",
|
||||||
|
@ -1006,7 +1006,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "dd1EZIkANYs",
|
id: "dd1EZIkANYs",
|
||||||
name: "the horror maze",
|
name: "the horror maze",
|
||||||
length: None,
|
length: Some(44),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/dd1EZIkANYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBlqz2BM3K2VeLlXMPBVwXNXih6vg",
|
url: "https://i.ytimg.com/vi/dd1EZIkANYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBlqz2BM3K2VeLlXMPBVwXNXih6vg",
|
||||||
|
@ -1032,7 +1032,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "enioc_stRww",
|
id: "enioc_stRww",
|
||||||
name: "furikake bagels with wasabi cream cheese",
|
name: "furikake bagels with wasabi cream cheese",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/enioc_stRww/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBz9Qo96FWssNsMhQ54DMxdYYwLfQ",
|
url: "https://i.ytimg.com/vi/enioc_stRww/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBz9Qo96FWssNsMhQ54DMxdYYwLfQ",
|
||||||
|
@ -1058,7 +1058,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "NUM8kCPas5w",
|
id: "NUM8kCPas5w",
|
||||||
name: "simple is best",
|
name: "simple is best",
|
||||||
length: None,
|
length: Some(49),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/NUM8kCPas5w/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC8N3YRr9A6-u6L0AtMynct4C_GzQ",
|
url: "https://i.ytimg.com/vi/NUM8kCPas5w/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC8N3YRr9A6-u6L0AtMynct4C_GzQ",
|
||||||
|
@ -1084,7 +1084,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "1djkcsFnlYE",
|
id: "1djkcsFnlYE",
|
||||||
name: "edible history lesson!",
|
name: "edible history lesson!",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/1djkcsFnlYE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBHn_6yOrnRXH_zbxVaAuKzSulcew",
|
url: "https://i.ytimg.com/vi/1djkcsFnlYE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBHn_6yOrnRXH_zbxVaAuKzSulcew",
|
||||||
|
@ -1110,7 +1110,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "cIYrJtAoftI",
|
id: "cIYrJtAoftI",
|
||||||
name: "and I\'m feeling good",
|
name: "and I\'m feeling good",
|
||||||
length: None,
|
length: Some(53),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/cIYrJtAoftI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC4q0VcbBZroejhAztDkdlk7Ww5Og",
|
url: "https://i.ytimg.com/vi/cIYrJtAoftI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC4q0VcbBZroejhAztDkdlk7Ww5Og",
|
||||||
|
@ -1136,7 +1136,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "cCrH8Er5tf4",
|
id: "cCrH8Er5tf4",
|
||||||
name: "Rating Korean Convenience Store Milk Flavors 🥛🍼",
|
name: "Rating Korean Convenience Store Milk Flavors 🥛🍼",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/cCrH8Er5tf4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBwc2ikrGH_gZfcyqTnZDfHjt5LuA",
|
url: "https://i.ytimg.com/vi/cCrH8Er5tf4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBwc2ikrGH_gZfcyqTnZDfHjt5LuA",
|
||||||
|
@ -1162,7 +1162,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "tav5wsH7pzU",
|
id: "tav5wsH7pzU",
|
||||||
name: "online dating?",
|
name: "online dating?",
|
||||||
length: None,
|
length: Some(58),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/tav5wsH7pzU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCheup7XAM_O1UAMEO5Iqup4-lGRQ",
|
url: "https://i.ytimg.com/vi/tav5wsH7pzU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCheup7XAM_O1UAMEO5Iqup4-lGRQ",
|
||||||
|
@ -1188,7 +1188,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "5Vd4_GXjF7o",
|
id: "5Vd4_GXjF7o",
|
||||||
name: "Creating thumbnails has never been easier with Adobe Express",
|
name: "Creating thumbnails has never been easier with Adobe Express",
|
||||||
length: None,
|
length: Some(26),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/5Vd4_GXjF7o/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCbYkH7INYGHW0IcO3DKip5iD2PCA",
|
url: "https://i.ytimg.com/vi/5Vd4_GXjF7o/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCbYkH7INYGHW0IcO3DKip5iD2PCA",
|
||||||
|
@ -1214,7 +1214,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "-FN1sEI8HkU",
|
id: "-FN1sEI8HkU",
|
||||||
name: "my favorite color is green",
|
name: "my favorite color is green",
|
||||||
length: None,
|
length: Some(45),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/-FN1sEI8HkU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCLWKPrR-VCdsXagJ1MIyah7dDdDQ",
|
url: "https://i.ytimg.com/vi/-FN1sEI8HkU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCLWKPrR-VCdsXagJ1MIyah7dDdDQ",
|
||||||
|
@ -1240,7 +1240,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "viT-dcl2DGE",
|
id: "viT-dcl2DGE",
|
||||||
name: "frodo baggins?",
|
name: "frodo baggins?",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/viT-dcl2DGE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDb0oYC_3V79CSR0j-4sR4CuNQekQ",
|
url: "https://i.ytimg.com/vi/viT-dcl2DGE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDb0oYC_3V79CSR0j-4sR4CuNQekQ",
|
||||||
|
@ -1266,7 +1266,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "N5AKQflK1TU",
|
id: "N5AKQflK1TU",
|
||||||
name: "When you impulse buy...",
|
name: "When you impulse buy...",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/N5AKQflK1TU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDwfPTcuQHyziYsmTrSkg9xi1jnag",
|
url: "https://i.ytimg.com/vi/N5AKQflK1TU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDwfPTcuQHyziYsmTrSkg9xi1jnag",
|
||||||
|
@ -1292,7 +1292,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "OzIFALQ_YtA",
|
id: "OzIFALQ_YtA",
|
||||||
name: "taste testing gam!",
|
name: "taste testing gam!",
|
||||||
length: None,
|
length: Some(60),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/OzIFALQ_YtA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBMcyG6Fu4rrXk-JQL5tx0hzSAxlw",
|
url: "https://i.ytimg.com/vi/OzIFALQ_YtA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBMcyG6Fu4rrXk-JQL5tx0hzSAxlw",
|
||||||
|
@ -1318,7 +1318,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "dAcJILbc_0Q",
|
id: "dAcJILbc_0Q",
|
||||||
name: "How to: Korean rice wine 🍶 (makgeolli)",
|
name: "How to: Korean rice wine 🍶 (makgeolli)",
|
||||||
length: None,
|
length: Some(59),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/dAcJILbc_0Q/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAXbHym4PFTTO25GCI4n1tjSaQVCw",
|
url: "https://i.ytimg.com/vi/dAcJILbc_0Q/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAXbHym4PFTTO25GCI4n1tjSaQVCw",
|
||||||
|
@ -1344,7 +1344,7 @@ Channel(
|
||||||
VideoItem(
|
VideoItem(
|
||||||
id: "GvutfmW26JQ",
|
id: "GvutfmW26JQ",
|
||||||
name: "👹stay sour 🍋",
|
name: "👹stay sour 🍋",
|
||||||
length: None,
|
length: Some(52),
|
||||||
thumbnail: [
|
thumbnail: [
|
||||||
Thumbnail(
|
Thumbnail(
|
||||||
url: "https://i.ytimg.com/vi/GvutfmW26JQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBgCJ06W3wOend0UgkuBKoHOg0eig",
|
url: "https://i.ytimg.com/vi/GvutfmW26JQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBgCJ06W3wOend0UgkuBKoHOg0eig",
|
||||||
|
|
|
@ -391,25 +391,24 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
},
|
},
|
||||||
comma_decimal: false,
|
comma_decimal: false,
|
||||||
number_tokens: ::phf::Map {
|
number_tokens: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
(1, 0),
|
(0, 7),
|
||||||
(3, 6),
|
(9, 8),
|
||||||
(1, 4),
|
(0, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("হ\u{9be}", 3),
|
("হ\u{9be}", 3),
|
||||||
("কোঃ", 5),
|
|
||||||
("ল\u{9be}খট\u{9be}", 5),
|
|
||||||
("ল\u{9be}খ", 5),
|
|
||||||
("নিঃট\u{9be}", 6),
|
|
||||||
("হ\u{9be}জ\u{9be}ৰট\u{9be}", 3),
|
("হ\u{9be}জ\u{9be}ৰট\u{9be}", 3),
|
||||||
("কোঃট\u{9be}", 9),
|
|
||||||
("নিঃ", 6),
|
|
||||||
("নিয\u{9c1}তট\u{9be}", 6),
|
("নিয\u{9c1}তট\u{9be}", 6),
|
||||||
("ল\u{9be}", 5),
|
|
||||||
("নিয\u{9c1}ত", 6),
|
|
||||||
("হ\u{9be}জ\u{9be}ৰ", 3),
|
("হ\u{9be}জ\u{9be}ৰ", 3),
|
||||||
|
("ল\u{9be}", 5),
|
||||||
|
("ল\u{9be}খট\u{9be}", 5),
|
||||||
|
("কোঃট\u{9be}", 9),
|
||||||
|
("নিঃট\u{9be}", 6),
|
||||||
|
("নিয\u{9c1}ত", 6),
|
||||||
|
("নিঃ", 6),
|
||||||
|
("ল\u{9be}খ", 5),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
number_nd_tokens: ::phf::Map {
|
number_nd_tokens: ::phf::Map {
|
||||||
|
@ -891,15 +890,14 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
},
|
},
|
||||||
comma_decimal: true,
|
comma_decimal: true,
|
||||||
number_tokens: ::phf::Map {
|
number_tokens: ::phf::Map {
|
||||||
key: 10121458955350035957,
|
key: 12913932095322966823,
|
||||||
disps: &[
|
disps: &[
|
||||||
(2, 0),
|
(2, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("mil", 6),
|
|
||||||
("mlr", 9),
|
|
||||||
("hilj", 3),
|
("hilj", 3),
|
||||||
("mlrd", 9),
|
("mlr", 9),
|
||||||
|
("mil", 6),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
number_nd_tokens: ::phf::Map {
|
number_nd_tokens: ::phf::Map {
|
||||||
|
@ -3096,9 +3094,8 @@ pub(crate) fn entry(lang: Language) -> Entry {
|
||||||
(0, 0),
|
(0, 0),
|
||||||
],
|
],
|
||||||
entries: &[
|
entries: &[
|
||||||
("mio", 6),
|
|
||||||
("mln", 6),
|
|
||||||
("mrd", 9),
|
("mrd", 9),
|
||||||
|
("mln", 6),
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
number_nd_tokens: ::phf::Map {
|
number_nd_tokens: ::phf::Map {
|
||||||
|
|
|
@ -643,9 +643,6 @@ pub(crate) mod tests {
|
||||||
#[case(Language::As, "১ জন গ্ৰাহক", 1)]
|
#[case(Language::As, "১ জন গ্ৰাহক", 1)]
|
||||||
#[case(Language::Ru, "Зрителей, ожидающих начала трансляции: 6", 6)]
|
#[case(Language::Ru, "Зрителей, ожидающих начала трансляции: 6", 6)]
|
||||||
#[case(Language::Si, "වාදන මි4.6ක්", 4_600_000)]
|
#[case(Language::Si, "වාදන මි4.6ක්", 4_600_000)]
|
||||||
#[case(Language::As, "3.7 শঃ কোঃ বাৰ প্লে’ কৰা হৈছে", 370_000)]
|
|
||||||
#[case(Language::Bs, "3,3 mlrd. pregleda", 3_300_000_000)]
|
|
||||||
#[case(Language::It, "3,73 Mio di iscritti", 3_730_000)]
|
|
||||||
fn t_parse_large_numstr(#[case] lang: Language, #[case] string: &str, #[case] expect: u64) {
|
fn t_parse_large_numstr(#[case] lang: Language, #[case] string: &str, #[case] expect: u64) {
|
||||||
let res = parse_large_numstr::<u64>(string, lang).unwrap();
|
let res = parse_large_numstr::<u64>(string, lang).unwrap();
|
||||||
assert_eq!(res, expect);
|
assert_eq!(res, expect);
|
||||||
|
|
|
@ -322,10 +322,6 @@ pub fn parse_video_duration(lang: Language, video_duration: &str) -> Option<u32>
|
||||||
let parts = split_duration_txt(video_duration, matches!(lang, Language::Si | Language::Sw));
|
let parts = split_duration_txt(video_duration, matches!(lang, Language::Si | Language::Sw));
|
||||||
let mut secs = 0;
|
let mut secs = 0;
|
||||||
|
|
||||||
if parts.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
for part in parts {
|
for part in parts {
|
||||||
let mut n = if part.digits.is_empty() {
|
let mut n = if part.digits.is_empty() {
|
||||||
1
|
1
|
||||||
|
|
|
@ -203,7 +203,6 @@
|
||||||
"হা": 3,
|
"হা": 3,
|
||||||
"হাজাৰ": 3,
|
"হাজাৰ": 3,
|
||||||
"হাজাৰটা": 3,
|
"হাজাৰটা": 3,
|
||||||
"কোঃ": 5,
|
|
||||||
"লা": 5,
|
"লা": 5,
|
||||||
"লাখ": 5,
|
"লাখ": 5,
|
||||||
"লাখটা": 5,
|
"লাখটা": 5,
|
||||||
|
@ -505,8 +504,7 @@
|
||||||
"number_tokens": {
|
"number_tokens": {
|
||||||
"hilj": 3,
|
"hilj": 3,
|
||||||
"mil": 6,
|
"mil": 6,
|
||||||
"mlr": 9,
|
"mlr": 9
|
||||||
"mlrd": 9
|
|
||||||
},
|
},
|
||||||
"number_nd_tokens": {
|
"number_nd_tokens": {
|
||||||
"nema": 0
|
"nema": 0
|
||||||
|
@ -1820,7 +1818,6 @@
|
||||||
},
|
},
|
||||||
"comma_decimal": true,
|
"comma_decimal": true,
|
||||||
"number_tokens": {
|
"number_tokens": {
|
||||||
"mio": 6,
|
|
||||||
"mln": 6,
|
"mln": 6,
|
||||||
"mrd": 9
|
"mrd": 9
|
||||||
},
|
},
|
||||||
|
|
|
@ -831,6 +831,7 @@ fn channel_videos(rp: RustyPipe) {
|
||||||
fn channel_shorts(rp: RustyPipe) {
|
fn channel_shorts(rp: RustyPipe) {
|
||||||
let channel = tokio_test::block_on(
|
let channel = tokio_test::block_on(
|
||||||
rp.query()
|
rp.query()
|
||||||
|
.lang(Language::Sq)
|
||||||
.channel_videos_tab("UCh8gHdtzO2tXd593_bjErWg", ChannelVideoTab::Shorts),
|
.channel_videos_tab("UCh8gHdtzO2tXd593_bjErWg", ChannelVideoTab::Shorts),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -1537,7 +1538,7 @@ fn music_album_not_found(rp: RustyPipe) {
|
||||||
// #[case::basic("basic", "UC7cl4MmM6ZZ2TcFyMk_b4pg", false, 15, 2)]
|
// #[case::basic("basic", "UC7cl4MmM6ZZ2TcFyMk_b4pg", false, 15, 2)]
|
||||||
#[case::no_more_albums("no_more_albums", "UCOR4_bSVIXPsGa4BbCSt60Q", true, 15, 0)]
|
#[case::no_more_albums("no_more_albums", "UCOR4_bSVIXPsGa4BbCSt60Q", true, 15, 0)]
|
||||||
#[case::only_singles("only_singles", "UCfwCE5VhPMGxNPFxtVv7lRw", false, 13, 0)]
|
#[case::only_singles("only_singles", "UCfwCE5VhPMGxNPFxtVv7lRw", false, 13, 0)]
|
||||||
#[case::no_artist("no_artist", "UCh8gHdtzO2tXd593_bjErWg", false, 0, 0)]
|
#[case::no_artist("no_artist", "UCh8gHdtzO2tXd593_bjErWg", false, 0, 2)]
|
||||||
// querying Trailerpark's secondary YouTube channel should result in the YTM channel being fetched
|
// querying Trailerpark's secondary YouTube channel should result in the YTM channel being fetched
|
||||||
#[case::secondary_channel("no_more_albums", "UCC9192yGQD25eBZgFZ84MPw", true, 15, 0)]
|
#[case::secondary_channel("no_more_albums", "UCC9192yGQD25eBZgFZ84MPw", true, 15, 0)]
|
||||||
fn music_artist(
|
fn music_artist(
|
||||||
|
@ -1960,12 +1961,12 @@ fn music_search_albums(
|
||||||
|
|
||||||
assert_eq!(album.artists.len(), 1);
|
assert_eq!(album.artists.len(), 1);
|
||||||
let album_artist = &album.artists[0];
|
let album_artist = &album.artists[0];
|
||||||
assert_eq!(album_artist.id.as_ref().expect("artist.id"), artist_id);
|
assert_eq!(album_artist.id.as_ref().unwrap(), artist_id);
|
||||||
if unlocalized {
|
if unlocalized {
|
||||||
assert_eq!(album_artist.name, artist);
|
assert_eq!(album_artist.name, artist);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(album.artist_id.as_ref().expect("artist_id"), artist_id);
|
assert_eq!(album.artist_id.as_ref().unwrap(), artist_id);
|
||||||
assert!(!album.cover.is_empty(), "got no cover");
|
assert!(!album.cover.is_empty(), "got no cover");
|
||||||
assert_eq!(album.year.as_ref().unwrap(), &year);
|
assert_eq!(album.year.as_ref().unwrap(), &year);
|
||||||
assert_eq!(album.album_type, album_type);
|
assert_eq!(album.album_type, album_type);
|
||||||
|
@ -2011,7 +2012,11 @@ fn music_search_artists_cont(rp: RustyPipe) {
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn music_search_playlists(rp: RustyPipe, unlocalized: bool) {
|
fn music_search_playlists(rp: RustyPipe, unlocalized: bool) {
|
||||||
let res = tokio_test::block_on(rp.query().music_search_playlists("rock hits", false)).unwrap();
|
let res = tokio_test::block_on(
|
||||||
|
rp.query()
|
||||||
|
.music_search_playlists("today's rock hits", false),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(res.corrected_query, None);
|
assert_eq!(res.corrected_query, None);
|
||||||
let playlist = res
|
let playlist = res
|
||||||
|
@ -2024,7 +2029,7 @@ fn music_search_playlists(rp: RustyPipe, unlocalized: bool) {
|
||||||
});
|
});
|
||||||
|
|
||||||
if unlocalized {
|
if unlocalized {
|
||||||
assert_eq!(playlist.name, "Rock Hits");
|
assert_eq!(playlist.name, "Today's Rock Hits");
|
||||||
}
|
}
|
||||||
assert!(!playlist.thumbnail.is_empty(), "got no thumbnail");
|
assert!(!playlist.thumbnail.is_empty(), "got no thumbnail");
|
||||||
assert_gte(playlist.track_count.unwrap(), 100, "tracks");
|
assert_gte(playlist.track_count.unwrap(), 100, "tracks");
|
||||||
|
|
Loading…
Reference in a new issue