Compare commits

..

2 commits

Author SHA1 Message Date
d413cad8bb
fix: number parsing for as,bs,it, update testdata
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-01-24 12:48:13 +01:00
fd3e128f50
fix: remove shorts duration parsing 2024-01-18 16:03:15 +01:00
7 changed files with 85 additions and 163 deletions

View file

@ -1,5 +1,3 @@
use once_cell::sync::Lazy;
use regex::Regex;
use serde::Deserialize;
use serde_with::{
rust::deserialize_ignore_any, serde_as, DefaultOnError, DisplayFromStr, VecSkipError,
@ -14,7 +12,7 @@ use crate::{
},
param::Language,
serializer::{
text::{AccessibilityText, Text, TextComponent},
text::{Text, TextComponent},
MapResult,
},
util::{self, timeago, TryRemove},
@ -139,13 +137,6 @@ pub(crate) struct ReelItemRenderer {
/// Contains `No views` if the view count is zero
#[serde_as(as = "Option<Text>")]
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_as(as = "DefaultOnError")]
pub navigation_endpoint: Option<ReelNavigationEndpoint>,
@ -395,10 +386,6 @@ 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
/// (videos, channels, playlists)
#[derive(Debug)]
@ -510,36 +497,10 @@ impl<T> YouTubeListMapper<T> {
.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 {
id: video.video_id,
name: video.headline,
length,
length: None,
thumbnail: video.thumbnail.into(),
channel: self.channel.clone(),
publish_date: pub_date_txt.as_ref().and_then(|txt| {
@ -789,50 +750,3 @@ impl YouTubeListMapper<PlaylistItem> {
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 #shorts8 секунд прайграць відэа",
"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 минута.");
}
}

View file

@ -122,7 +122,7 @@ Channel(
VideoItem(
id: "bGXP83AU3Mc",
name: "do u wanna get swole?",
length: Some(53),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/bGXP83AU3Mc/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC9bzCBeHDbZFLE84Up3IiBIsxmmA",
@ -148,7 +148,7 @@ Channel(
VideoItem(
id: "E52sSgZlgYs",
name: "the holy trinity of korean street food",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/E52sSgZlgYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDBahtFRcfBInHuA8CjXFPWkF2jHg",
@ -174,7 +174,7 @@ Channel(
VideoItem(
id: "ovaHmfy3O6U",
name: "hangover food",
length: Some(58),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/ovaHmfy3O6U/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCHmvWlG06h-DT6oxfmh69JGQ69KA",
@ -200,7 +200,7 @@ Channel(
VideoItem(
id: "FHTQmKTZnlI",
name: "pig trotter raguuuuuuuuu 💅",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/FHTQmKTZnlI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD0xhka1osA4nI3VCwhQusn3ND3Hg",
@ -226,7 +226,7 @@ Channel(
VideoItem(
id: "1AXB0l_wKMs",
name: "what i ate in google japan",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/1AXB0l_wKMs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBsfYJ0KffUNn-9jBzNRTqetyFr8g",
@ -252,7 +252,7 @@ Channel(
VideoItem(
id: "1ARLtk3HiB0",
name: "succumb to your cravings",
length: Some(53),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/1ARLtk3HiB0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBY9E40Ehvq862CVItJy0Uj_pS5bg",
@ -278,7 +278,7 @@ Channel(
VideoItem(
id: "0FfDoDHpaN8",
name: "you can\'t let the what ifs rule your life",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/0FfDoDHpaN8/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBiV2TVPO-VbIjoNtwCKmFuxmj6LA",
@ -304,7 +304,7 @@ Channel(
VideoItem(
id: "kuT90_RIdF0",
name: "duck confit lollipop 🦆🍭",
length: Some(59),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/kuT90_RIdF0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCUN-DW72m7sAXJMgVkWNxPYpJBcQ",
@ -330,7 +330,7 @@ Channel(
VideoItem(
id: "aPJLhrcM4Yg",
name: "HOUSE TOUR",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/aPJLhrcM4Yg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD1TbWAIbzyWq8AXLoW0xqaji3ukQ",
@ -356,7 +356,7 @@ Channel(
VideoItem(
id: "DKQrG_hJJX4",
name: "how to meal prep like a korean",
length: Some(59),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/DKQrG_hJJX4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBE2DnpLFvtXsZOu1Ta4JQeOToVAw",
@ -382,7 +382,7 @@ Channel(
VideoItem(
id: "lNizW_P_oVw",
name: "Rating Everything I ate at McDonald\'s Japan 🇯🇵",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/lNizW_P_oVw/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBI5XrkQ9Hesbf4lWELy7Uk3yMGMg",
@ -408,7 +408,7 @@ Channel(
VideoItem(
id: "kbWyJjrCjwA",
name: "enemies as fertilizer √(veg)",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/kbWyJjrCjwA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDlk30Km1M0jze1M3O90fB2LdvoAQ",
@ -434,7 +434,7 @@ Channel(
VideoItem(
id: "xAp910JTDig",
name: "let\'s make some cabbage rolls for lunch",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/xAp910JTDig/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAJtpPGRgffBu9WDXACbtiGa_oRgA",
@ -460,7 +460,7 @@ Channel(
VideoItem(
id: "vSL7dhKatEk",
name: "Rating Everything I ate at IKEA Korea",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/vSL7dhKatEk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBYpIDYbwwWiCqRNVi6PlfEfjrt4A",
@ -486,7 +486,7 @@ Channel(
VideoItem(
id: "LZzhUpACXSk",
name: "I\'m done being the bigger person",
length: Some(59),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/LZzhUpACXSk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAFTvhtVUP7QZ4P7U70-0XH7PzDDg",
@ -512,7 +512,7 @@ Channel(
VideoItem(
id: "5C7nqNDfhis",
name: "we\'re cooking a whole bird today",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/5C7nqNDfhis/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLA9I9irDsRjikwd0aqp1FWNFtjAqA",
@ -538,7 +538,7 @@ Channel(
VideoItem(
id: "6mj4Af0kUOQ",
name: "men will disappoint but never potatoes",
length: Some(50),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/6mj4Af0kUOQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAVxl-FPt878AQXPBhbV1VSGeR8sw",
@ -564,7 +564,7 @@ Channel(
VideoItem(
id: "1c3axhSJiaQ",
name: "I used to hate korean food",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/1c3axhSJiaQ/hq720_2.jpg?sqp=-oaymwEdCJUDENAFSFXyq4qpAw8IARUAAIhCcAHAAQbQAQE=&rs=AOn4CLBucOEbTsWTDjOOCjNa-fAvz1yxyA",
@ -590,7 +590,7 @@ Channel(
VideoItem(
id: "F9Vz0m7DPeU",
name: "Rating everything I got at 7/11 Hawaii ( ft. Mauna Kea )",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/F9Vz0m7DPeU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDOoCVL6la3ztUeQ6vP4iL1cEBRjQ",
@ -616,7 +616,7 @@ Channel(
VideoItem(
id: "Uey7kl56wks",
name: "Grabbing Snacks from 7/11 Hawaii",
length: Some(49),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/Uey7kl56wks/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCWmgajinNtIEbiPbqEtDvkC7Ydrg",
@ -642,7 +642,7 @@ Channel(
VideoItem(
id: "3un2eUAr6Dg",
name: "cheesy korean corn balls hit different",
length: Some(46),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/3un2eUAr6Dg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD4LziL6GHd1jg8btMJDIM_RhgE_A",
@ -668,7 +668,7 @@ Channel(
VideoItem(
id: "rI5tWrGpDJA",
name: "hawaiian tajin?!?",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/rI5tWrGpDJA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAjNiKHdFSKGavBrZRDxi9WdR-gJw",
@ -694,7 +694,7 @@ Channel(
VideoItem(
id: "WQiGksTxr5g",
name: "Rating everything I ate at Hawaiian Supermarket 🌺🏰 pt.2",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/WQiGksTxr5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvzC5xVdTEJX8xtiOqzmeKvmouIg",
@ -720,7 +720,7 @@ Channel(
VideoItem(
id: "G7aw-QOsagk",
name: "Grocery Shopping at Hawaiian Supermarket 🌺🏰 pt.1",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/G7aw-QOsagk/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAoKEkj2lqYU07yW_DU35TNHEOq4w",
@ -746,7 +746,7 @@ Channel(
VideoItem(
id: "Y_F1_Yf-DKQ",
name: "Breakfast at Hawaiian McDonald\'s 🌺",
length: Some(61),
length: None,
thumbnail: [
Thumbnail(
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(
id: "Q_ZMcP8faw4",
name: "crab rangoon toast 🦀 🍞",
length: Some(55),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/Q_ZMcP8faw4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLATLiHTNqLoBKsEKbOckkGjXMvoHA",
@ -798,7 +798,7 @@ Channel(
VideoItem(
id: "1aedyP3r3D0",
name: "my secret hot pot sauce 🧙\u{200d}♀\u{fe0f}🍃",
length: Some(59),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/1aedyP3r3D0/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCh2MpR5k3jCS_wfX-wjtVuIcu7YQ",
@ -824,7 +824,7 @@ Channel(
VideoItem(
id: "fkPkHZ1yyBU",
name: "the good vs the bad",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/fkPkHZ1yyBU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCMngiRtLrBPppmfPnJwJ-cYMwttA",
@ -850,7 +850,7 @@ Channel(
VideoItem(
id: "NbQcySLMLmA",
name: "cooking with waste?!🗑\u{fe0f}",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/NbQcySLMLmA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCvxPQo9eqYwjk4cxyBnrHed-tcZg",
@ -876,7 +876,7 @@ Channel(
VideoItem(
id: "3w_5vzM1Pc4",
name: "Shrek burger 🍔🍀👹",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/3w_5vzM1Pc4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLB64zOKgmhOt7bvQseeIbjKBICDAg",
@ -902,7 +902,7 @@ Channel(
VideoItem(
id: "girJP2r_zLg",
name: "$$$ on food",
length: Some(55),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/girJP2r_zLg/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBg2hmruZvx30aiP4Jb4dhz03qOZA",
@ -928,7 +928,7 @@ Channel(
VideoItem(
id: "zHp7sZ5OONM",
name: "pumpkin spice churro?! 🎃",
length: Some(58),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/zHp7sZ5OONM/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLD8ZrcI6mq91ARKnRb_vg-0Qv2raw",
@ -954,7 +954,7 @@ Channel(
VideoItem(
id: "iqMl3gQEZ0E",
name: "3,000,000",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/iqMl3gQEZ0E/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBUC1sw84NlLiyTJTcfnDWFjVC75w",
@ -980,7 +980,7 @@ Channel(
VideoItem(
id: "glyJWxp7a5g",
name: "being smart was my personality trait",
length: Some(56),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/glyJWxp7a5g/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBbrWwLndPt5ZV5x4dnqmTC_aAhig",
@ -1006,7 +1006,7 @@ Channel(
VideoItem(
id: "dd1EZIkANYs",
name: "the horror maze",
length: Some(44),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/dd1EZIkANYs/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBlqz2BM3K2VeLlXMPBVwXNXih6vg",
@ -1032,7 +1032,7 @@ Channel(
VideoItem(
id: "enioc_stRww",
name: "furikake bagels with wasabi cream cheese",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/enioc_stRww/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBz9Qo96FWssNsMhQ54DMxdYYwLfQ",
@ -1058,7 +1058,7 @@ Channel(
VideoItem(
id: "NUM8kCPas5w",
name: "simple is best",
length: Some(49),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/NUM8kCPas5w/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC8N3YRr9A6-u6L0AtMynct4C_GzQ",
@ -1084,7 +1084,7 @@ Channel(
VideoItem(
id: "1djkcsFnlYE",
name: "edible history lesson!",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/1djkcsFnlYE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBHn_6yOrnRXH_zbxVaAuKzSulcew",
@ -1110,7 +1110,7 @@ Channel(
VideoItem(
id: "cIYrJtAoftI",
name: "and I\'m feeling good",
length: Some(53),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/cIYrJtAoftI/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLC4q0VcbBZroejhAztDkdlk7Ww5Og",
@ -1136,7 +1136,7 @@ Channel(
VideoItem(
id: "cCrH8Er5tf4",
name: "Rating Korean Convenience Store Milk Flavors 🥛🍼",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/cCrH8Er5tf4/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBwc2ikrGH_gZfcyqTnZDfHjt5LuA",
@ -1162,7 +1162,7 @@ Channel(
VideoItem(
id: "tav5wsH7pzU",
name: "online dating?",
length: Some(58),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/tav5wsH7pzU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCheup7XAM_O1UAMEO5Iqup4-lGRQ",
@ -1188,7 +1188,7 @@ Channel(
VideoItem(
id: "5Vd4_GXjF7o",
name: "Creating thumbnails has never been easier with Adobe Express",
length: Some(26),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/5Vd4_GXjF7o/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCbYkH7INYGHW0IcO3DKip5iD2PCA",
@ -1214,7 +1214,7 @@ Channel(
VideoItem(
id: "-FN1sEI8HkU",
name: "my favorite color is green",
length: Some(45),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/-FN1sEI8HkU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLCLWKPrR-VCdsXagJ1MIyah7dDdDQ",
@ -1240,7 +1240,7 @@ Channel(
VideoItem(
id: "viT-dcl2DGE",
name: "frodo baggins?",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/viT-dcl2DGE/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDb0oYC_3V79CSR0j-4sR4CuNQekQ",
@ -1266,7 +1266,7 @@ Channel(
VideoItem(
id: "N5AKQflK1TU",
name: "When you impulse buy...",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/N5AKQflK1TU/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLDwfPTcuQHyziYsmTrSkg9xi1jnag",
@ -1292,7 +1292,7 @@ Channel(
VideoItem(
id: "OzIFALQ_YtA",
name: "taste testing gam!",
length: Some(60),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/OzIFALQ_YtA/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBMcyG6Fu4rrXk-JQL5tx0hzSAxlw",
@ -1318,7 +1318,7 @@ Channel(
VideoItem(
id: "dAcJILbc_0Q",
name: "How to: Korean rice wine 🍶 (makgeolli)",
length: Some(59),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/dAcJILbc_0Q/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLAXbHym4PFTTO25GCI4n1tjSaQVCw",
@ -1344,7 +1344,7 @@ Channel(
VideoItem(
id: "GvutfmW26JQ",
name: "👹stay sour 🍋",
length: Some(52),
length: None,
thumbnail: [
Thumbnail(
url: "https://i.ytimg.com/vi/GvutfmW26JQ/oar2.jpg?sqp=-oaymwEaCJUDENAFSFXyq4qpAwwIARUAAIhCcAHAAQY=&rs=AOn4CLBgCJ06W3wOend0UgkuBKoHOg0eig",

View file

@ -391,24 +391,25 @@ pub(crate) fn entry(lang: Language) -> Entry {
},
comma_decimal: false,
number_tokens: ::phf::Map {
key: 12913932095322966823,
key: 10121458955350035957,
disps: &[
(0, 7),
(9, 8),
(0, 0),
(1, 0),
(3, 6),
(1, 4),
],
entries: &[
("\u{9be}", 3),
("\u{9be}\u{9be}ৰট\u{9be}", 3),
("নিয\u{9c1}তট\u{9be}", 6),
("\u{9be}\u{9be}", 3),
("\u{9be}", 5),
("কোঃ", 5),
("\u{9be}খট\u{9be}", 5),
("কোঃট\u{9be}", 9),
("নিঃট\u{9be}", 6),
("নিয\u{9c1}", 6),
("নিঃ", 6),
("\u{9be}", 5),
("নিঃট\u{9be}", 6),
("\u{9be}\u{9be}ৰট\u{9be}", 3),
("কোঃট\u{9be}", 9),
("নিঃ", 6),
("নিয\u{9c1}তট\u{9be}", 6),
("\u{9be}", 5),
("নিয\u{9c1}", 6),
("\u{9be}\u{9be}", 3),
],
},
number_nd_tokens: ::phf::Map {
@ -890,14 +891,15 @@ pub(crate) fn entry(lang: Language) -> Entry {
},
comma_decimal: true,
number_tokens: ::phf::Map {
key: 12913932095322966823,
key: 10121458955350035957,
disps: &[
(2, 0),
],
entries: &[
("hilj", 3),
("mlr", 9),
("mil", 6),
("mlr", 9),
("hilj", 3),
("mlrd", 9),
],
},
number_nd_tokens: ::phf::Map {
@ -3094,8 +3096,9 @@ pub(crate) fn entry(lang: Language) -> Entry {
(0, 0),
],
entries: &[
("mrd", 9),
("mio", 6),
("mln", 6),
("mrd", 9),
],
},
number_nd_tokens: ::phf::Map {

View file

@ -643,6 +643,9 @@ pub(crate) mod tests {
#[case(Language::As, "১ জন গ্ৰাহক", 1)]
#[case(Language::Ru, "Зрителей, ожидающих начала трансляции: 6", 6)]
#[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) {
let res = parse_large_numstr::<u64>(string, lang).unwrap();
assert_eq!(res, expect);

View file

@ -322,6 +322,10 @@ 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 mut secs = 0;
if parts.is_empty() {
return None;
}
for part in parts {
let mut n = if part.digits.is_empty() {
1

View file

@ -203,6 +203,7 @@
"হা": 3,
"হাজাৰ": 3,
"হাজাৰটা": 3,
"কোঃ": 5,
"লা": 5,
"লাখ": 5,
"লাখটা": 5,
@ -504,7 +505,8 @@
"number_tokens": {
"hilj": 3,
"mil": 6,
"mlr": 9
"mlr": 9,
"mlrd": 9
},
"number_nd_tokens": {
"nema": 0
@ -1818,6 +1820,7 @@
},
"comma_decimal": true,
"number_tokens": {
"mio": 6,
"mln": 6,
"mrd": 9
},

View file

@ -831,7 +831,6 @@ fn channel_videos(rp: RustyPipe) {
fn channel_shorts(rp: RustyPipe) {
let channel = tokio_test::block_on(
rp.query()
.lang(Language::Sq)
.channel_videos_tab("UCh8gHdtzO2tXd593_bjErWg", ChannelVideoTab::Shorts),
)
.unwrap();
@ -1538,7 +1537,7 @@ fn music_album_not_found(rp: RustyPipe) {
// #[case::basic("basic", "UC7cl4MmM6ZZ2TcFyMk_b4pg", false, 15, 2)]
#[case::no_more_albums("no_more_albums", "UCOR4_bSVIXPsGa4BbCSt60Q", true, 15, 0)]
#[case::only_singles("only_singles", "UCfwCE5VhPMGxNPFxtVv7lRw", false, 13, 0)]
#[case::no_artist("no_artist", "UCh8gHdtzO2tXd593_bjErWg", false, 0, 2)]
#[case::no_artist("no_artist", "UCh8gHdtzO2tXd593_bjErWg", false, 0, 0)]
// querying Trailerpark's secondary YouTube channel should result in the YTM channel being fetched
#[case::secondary_channel("no_more_albums", "UCC9192yGQD25eBZgFZ84MPw", true, 15, 0)]
fn music_artist(
@ -1961,12 +1960,12 @@ fn music_search_albums(
assert_eq!(album.artists.len(), 1);
let album_artist = &album.artists[0];
assert_eq!(album_artist.id.as_ref().unwrap(), artist_id);
assert_eq!(album_artist.id.as_ref().expect("artist.id"), artist_id);
if unlocalized {
assert_eq!(album_artist.name, artist);
}
assert_eq!(album.artist_id.as_ref().unwrap(), artist_id);
assert_eq!(album.artist_id.as_ref().expect("artist_id"), artist_id);
assert!(!album.cover.is_empty(), "got no cover");
assert_eq!(album.year.as_ref().unwrap(), &year);
assert_eq!(album.album_type, album_type);
@ -2012,11 +2011,7 @@ fn music_search_artists_cont(rp: RustyPipe) {
#[rstest]
fn music_search_playlists(rp: RustyPipe, unlocalized: bool) {
let res = tokio_test::block_on(
rp.query()
.music_search_playlists("today's rock hits", false),
)
.unwrap();
let res = tokio_test::block_on(rp.query().music_search_playlists("rock hits", false)).unwrap();
assert_eq!(res.corrected_query, None);
let playlist = res
@ -2029,7 +2024,7 @@ fn music_search_playlists(rp: RustyPipe, unlocalized: bool) {
});
if unlocalized {
assert_eq!(playlist.name, "Today's Rock Hits");
assert_eq!(playlist.name, "Rock Hits");
}
assert!(!playlist.thumbnail.is_empty(), "got no thumbnail");
assert_gte(playlist.track_count.unwrap(), 100, "tracks");